Merge commit e7408fe366bb
* upstream svn@328903
Test: git diff e7408fe366bb == git diff 860fc25e85a 0c1c1aa856d9
Change-Id: Ia44205dc5c17eb34f4b62e0209987f3458a29a29
diff --git a/.clang-tidy b/.clang-tidy
index d10f688..2cfcc2a 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -5,8 +5,13 @@
- key: readability-identifier-naming.EnumCase
value: CamelCase
- key: readability-identifier-naming.FunctionCase
- value: lowerCase
+ value: camelBack
+ - key: readability-identifier-naming.MemberCase
+ value: CamelCase
+ - key: readability-identifier-naming.ParameterCase
+ value: CamelCase
- key: readability-identifier-naming.UnionCase
value: CamelCase
- key: readability-identifier-naming.VariableCase
value: CamelCase
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a2fcaec..0aec299 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -212,6 +212,12 @@
set(ENABLE_X86_RELAX_RELOCATIONS OFF CACHE BOOL
"enable x86 relax relocations by default")
+# TODO: verify the values against LangStandards.def?
+set(CLANG_DEFAULT_STD_C "" CACHE STRING
+ "Default standard to use for C/ObjC code (IDENT from LangStandards.def, empty for platform default)")
+set(CLANG_DEFAULT_STD_CXX "" CACHE STRING
+ "Default standard to use for C++/ObjC++ code (IDENT from LangStandards.def, empty for platform default)")
+
set(CLANG_DEFAULT_LINKER "" CACHE STRING
"Default linker to use (linker name or absolute path, empty for platform default)")
@@ -418,11 +424,11 @@
# Clang version information
set(CLANG_EXECUTABLE_VERSION
- "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}" CACHE STRING
- "Version number that will be placed into the clang executable, in the form XX.YY")
+ "${CLANG_VERSION_MAJOR}" CACHE STRING
+ "Major version number that will be appended to the clang executable name")
set(LIBCLANG_LIBRARY_VERSION
- "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}" CACHE STRING
- "Version number that will be placed into the libclang library , in the form XX.YY")
+ "${CLANG_VERSION_MAJOR}" CACHE STRING
+ "Major version number that will be appended to the libclang library")
mark_as_advanced(CLANG_EXECUTABLE_VERSION LIBCLANG_LIBRARY_VERSION)
option(CLANG_INCLUDE_TESTS
diff --git a/cmake/caches/Apple-stage2.cmake b/cmake/caches/Apple-stage2.cmake
index d58e4b6..fd46c1e 100644
--- a/cmake/caches/Apple-stage2.cmake
+++ b/cmake/caches/Apple-stage2.cmake
@@ -47,7 +47,7 @@
# setup toolchain
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
set(LLVM_TOOLCHAIN_TOOLS
- llvm-dsymutil
+ dsymutil
llvm-cov
llvm-dwarfdump
llvm-profdata
diff --git a/cmake/caches/BaremetalARM.cmake b/cmake/caches/BaremetalARM.cmake
index 73f797d..d9d2efc 100644
--- a/cmake/caches/BaremetalARM.cmake
+++ b/cmake/caches/BaremetalARM.cmake
@@ -24,11 +24,11 @@
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
set(LLVM_TOOLCHAIN_TOOLS
+ dsymutil
llc
llvm-ar
llvm-cxxfilt
llvm-dwarfdump
- llvm-dsymutil
llvm-nm
llvm-objdump
llvm-ranlib
diff --git a/cmake/caches/DistributionExample-stage2.cmake b/cmake/caches/DistributionExample-stage2.cmake
index 894ea6a..600ba56 100644
--- a/cmake/caches/DistributionExample-stage2.cmake
+++ b/cmake/caches/DistributionExample-stage2.cmake
@@ -10,7 +10,7 @@
# setup toolchain
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
set(LLVM_TOOLCHAIN_TOOLS
- llvm-dsymutil
+ dsymutil
llvm-cov
llvm-dwarfdump
llvm-profdata
diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake
index 2d36f09..3105f05 100644
--- a/cmake/caches/Fuchsia-stage2.cmake
+++ b/cmake/caches/Fuchsia-stage2.cmake
@@ -19,6 +19,8 @@
set(CLANG_DEFAULT_LINKER lld CACHE STRING "")
set(CLANG_DEFAULT_OBJCOPY llvm-objcopy CACHE STRING "")
endif()
+set(CLANG_DEFAULT_CXX_STDLIB libc++ CACHE STRING "")
+set(CLANG_DEFAULT_RTLIB compiler-rt CACHE STRING "")
set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
@@ -26,18 +28,45 @@
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "")
set(LLVM_BUILTIN_TARGETS "default;x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "")
+
+# Set the per-target builtins options.
foreach(target x86_64;aarch64)
set(BUILTINS_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "")
set(BUILTINS_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "")
endforeach()
set(LLVM_RUNTIME_TARGETS "default;x86_64-fuchsia;aarch64-fuchsia;x86_64-fuchsia-asan:x86_64-fuchsia;aarch64-fuchsia-asan:aarch64-fuchsia" CACHE STRING "")
+
+# Set the default target runtimes options.
+if(APPLE)
+ # Disable installing libc++, libc++abi or libunwind on Darwin, since Clang
+ # driver doesn't know how to use libraries that are part of the toolchain.
+ set(LIBUNWIND_INSTALL_HEADERS OFF CACHE BOOL "")
+ set(LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "")
+ set(LIBCXXABI_INSTALL_HEADERS OFF CACHE BOOL "")
+ set(LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "")
+ set(LIBCXX_INSTALL_HEADERS OFF CACHE BOOL "")
+ set(LIBCXX_INSTALL_LIBRARY OFF CACHE BOOL "")
+else()
+ set(LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "")
+ set(LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "")
+ set(LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "")
+ set(LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "")
+ set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "")
+ set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
+ set(LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "")
+ set(LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "")
+ set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
+ set(LIBCXX_ENABLE_SHARED OFF CACHE BOOL "")
+ set(LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")
+endif()
+
+# Set the per-target runtimes options.
foreach(target x86_64;aarch64)
set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "")
set(RUNTIMES_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "")
set(RUNTIMES_${target}-fuchsia_UNIX 1 CACHE BOOL "")
- set(RUNTIMES_${target}-fuchsia_LLVM_ENABLE_LIBCXX ON CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_LIBUNWIND_ENABLE_STATIC OFF CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "")
@@ -57,12 +86,12 @@
# Setup toolchain.
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
set(LLVM_TOOLCHAIN_TOOLS
+ dsymutil
llc
llvm-ar
llvm-cov
llvm-cxxfilt
llvm-dwarfdump
- llvm-dsymutil
llvm-lib
llvm-nm
llvm-objcopy
diff --git a/docs/HardwareAssistedAddressSanitizerDesign.rst b/docs/HardwareAssistedAddressSanitizerDesign.rst
index 71a9df1..06e5a43 100644
--- a/docs/HardwareAssistedAddressSanitizerDesign.rst
+++ b/docs/HardwareAssistedAddressSanitizerDesign.rst
@@ -7,8 +7,6 @@
a tool similar to :doc:`AddressSanitizer`,
but based on partial hardware assistance.
-The document is a draft, suggestions are welcome.
-
Introduction
============
@@ -30,15 +28,16 @@
Algorithm
=========
-* Every heap/stack/global memory object is forcibly aligned by `N` bytes
- (`N` is e.g. 16 or 64). We call `N` the **granularity** of tagging.
-* For every such object a random `K`-bit tag `T` is chosen (`K` is e.g. 4 or 8)
+* Every heap/stack/global memory object is forcibly aligned by `TG` bytes
+ (`TG` is e.g. 16 or 64). We call `TG` the **tagging granularity**.
+* For every such object a random `TS`-bit tag `T` is chosen (`TS`, or tag size, is e.g. 4 or 8)
* The pointer to the object is tagged with `T`.
-* The memory for the object is also tagged with `T`
- (using a `N=>1` shadow memory)
+* The memory for the object is also tagged with `T` (using a `TG=>1` shadow memory)
* Every load and store is instrumented to read the memory tag and compare it
with the pointer tag, exception is raised on tag mismatch.
+For a more detailed discussion of this approach see https://arxiv.org/pdf/1802.09517.pdf
+
Instrumentation
===============
@@ -59,8 +58,8 @@
c: 3f 01 08 6b cmp w9, w8 // compare tags
10: 61 00 00 54 b.ne #12 // jump on mismatch
14: 00 00 40 b9 ldr w0, [x0] // original load
- 18: c0 03 5f d6 ret
- 1c: 40 20 40 d4 hlt #0x102 // halt
+ 18: c0 03 5f d6 ret
+ 1c: 40 20 21 d4 brk #0x902 // trap
Alternatively, memory accesses are prefixed with a function call.
@@ -69,14 +68,14 @@
----
Tagging the heap memory/pointers is done by `malloc`.
-This can be based on any malloc that forces all objects to be N-aligned.
+This can be based on any malloc that forces all objects to be TG-aligned.
`free` tags the memory with a different tag.
Stack
-----
Stack frames are instrumented by aligning all non-promotable allocas
-by `N` and tagging stack memory in function prologue and epilogue.
+by `TG` and tagging stack memory in function prologue and epilogue.
Tags for different allocas in one function are **not** generated
independently; doing that in a function with `M` allocas would require
@@ -131,15 +130,25 @@
https://www.kernel.org/doc/Documentation/arm64/tagged-pointers.txt).
* **Does not require redzones to detect buffer overflows**,
but the buffer overflow detection is probabilistic, with roughly
- `(2**K-1)/(2**K)` probability of catching a bug.
+ `(2**TS-1)/(2**TS)` probability of catching a bug.
* **Does not require quarantine to detect heap-use-after-free,
or stack-use-after-return**.
The detection is similarly probabilistic.
The memory overhead of HWASAN is expected to be much smaller
than that of AddressSanitizer:
-`1/N` extra memory for the shadow
-and some overhead due to `N`-aligning all objects.
+`1/TG` extra memory for the shadow
+and some overhead due to `TG`-aligning all objects.
+
+Supported architectures
+=======================
+HWASAN relies on `Address Tagging`_ which is only available on AArch64.
+For other 64-bit architectures it is possible to remove the address tags
+before every load and store by compiler instrumentation, but this variant
+will have limited deployability since not all of the code is
+typically instrumented.
+
+The HWASAN's approach is not applicable to 32-bit architectures.
Related Work
diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html
index 0a9fcceb0..28f8d90 100644
--- a/docs/LibASTMatchersReference.html
+++ b/docs/LibASTMatchersReference.html
@@ -1926,6 +1926,19 @@
</pre></td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('isAssignmentOperator0')"><a name="isAssignmentOperator0Anchor">isAssignmentOperator</a></td></tr>
+<tr><td colspan="4" class="doc" id="isAssignmentOperator0"><pre>Matches all kinds of assignment operators.
+
+Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
+ if (a == b)
+ a += b;
+
+Example 2: matches s1 = s2 (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
+ struct S { S& operator=(const S&); };
+ void x() { S s1, s2; s1 = s2; })
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>></td><td class="name" onclick="toggle('equals5')"><a name="equals5Anchor">equals</a></td><td>bool Value</td></tr>
<tr><td colspan="4" class="doc" id="equals5"><pre></pre></td></tr>
@@ -2306,6 +2319,19 @@
</pre></td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('isAssignmentOperator1')"><a name="isAssignmentOperator1Anchor">isAssignmentOperator</a></td></tr>
+<tr><td colspan="4" class="doc" id="isAssignmentOperator1"><pre>Matches all kinds of assignment operators.
+
+Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
+ if (a == b)
+ a += b;
+
+Example 2: matches s1 = s2 (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
+ struct S { S& operator=(const S&); };
+ void x() { S s1, s2; s1 = s2; })
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('hasDefinition0')"><a name="hasDefinition0Anchor">hasDefinition</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDefinition0"><pre>Matches a class declaration that is defined.
@@ -3932,6 +3958,17 @@
</pre></td></tr>
+<tr><td>Matcher<internal::Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>>></td><td class="name" onclick="toggle('hasAnySelector0')"><a name="hasAnySelector0Anchor">hasAnySelector</a></td><td>StringRef, ..., StringRef</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnySelector0"><pre>Matches when at least one of the supplied string equals to the
+Selector.getAsString()
+
+ matcher = objCMessageExpr(hasSelector("methodA:", "methodB:"));
+ matches both of the expressions below:
+ [myObj methodA:argA];
+ [myObj methodB:argB];
+</pre></td></tr>
+
+
<tr><td>Matcher<internal::Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>></td><td class="name" onclick="toggle('isInTemplateInstantiation0')"><a name="isInTemplateInstantiation0Anchor">isInTemplateInstantiation</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInTemplateInstantiation0"><pre>Matches statements inside of a template instantiation.
@@ -4342,7 +4379,7 @@
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>></td><td class="name" onclick="toggle('hasAnyArgument1')"><a name="hasAnyArgument1Anchor">hasAnyArgument</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyArgument1"><pre>Matches any argument of a call expression or a constructor call
-expression.
+expression, or an ObjC-message-send expression.
Given
void x(int, int, int) { int y; x(1, y, 42); }
@@ -4350,6 +4387,12 @@
matches x(1, y, 42)
with hasAnyArgument(...)
matching y
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+ void foo(I *i) { [i f:12]; }
+objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
+ matches [i f:12]
</pre></td></tr>
@@ -4689,7 +4732,7 @@
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>></td><td class="name" onclick="toggle('hasAnyArgument0')"><a name="hasAnyArgument0Anchor">hasAnyArgument</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyArgument0"><pre>Matches any argument of a call expression or a constructor call
-expression.
+expression, or an ObjC-message-send expression.
Given
void x(int, int, int) { int y; x(1, y, 42); }
@@ -4697,6 +4740,12 @@
matches x(1, y, 42)
with hasAnyArgument(...)
matching y
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+ void foo(I *i) { [i f:12]; }
+objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
+ matches [i f:12]
</pre></td></tr>
@@ -5140,7 +5189,7 @@
</pre></td></tr>
-<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>></td><td class="name" onclick="toggle('ignoringImplicit0')"><a name="ignoringImplicit0Anchor">ignoringImplicit</a></td><td>ast_matchers::Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>></td><td class="name" onclick="toggle('ignoringImplicit0')"><a name="ignoringImplicit0Anchor">ignoringImplicit</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="ignoringImplicit0"><pre>Matches expressions that match InnerMatcher after any implicit AST
nodes are stripped off.
@@ -5260,7 +5309,7 @@
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('hasAnyParameter0')"><a name="hasAnyParameter0Anchor">hasAnyParameter</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>> InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasAnyParameter0"><pre>Matches any parameter of a function declaration.
+<tr><td colspan="4" class="doc" id="hasAnyParameter0"><pre>Matches any parameter of a function or ObjC method declaration.
Does not match the 'this' parameter of a method.
@@ -5270,6 +5319,13 @@
matches f(int x, int y, int z) {}
with hasAnyParameter(...)
matching int y
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
</pre></td></tr>
@@ -5309,7 +5365,8 @@
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('hasParameter0')"><a name="hasParameter0Anchor">hasParameter</a></td><td>unsigned N, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>> InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasParameter0"><pre>Matches the n'th parameter of a function declaration.
+<tr><td colspan="4" class="doc" id="hasParameter0"><pre>Matches the n'th parameter of a function or an ObjC method
+declaration.
Given
class X { void f(int x) {} };
@@ -5317,6 +5374,13 @@
matches f(int x) {}
with hasParameter(...)
matching int x
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasParameter(0, hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
</pre></td></tr>
@@ -5634,6 +5698,25 @@
</pre></td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('hasAnyArgument2')"><a name="hasAnyArgument2Anchor">hasAnyArgument</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnyArgument2"><pre>Matches any argument of a call expression or a constructor call
+expression, or an ObjC-message-send expression.
+
+Given
+ void x(int, int, int) { int y; x(1, y, 42); }
+callExpr(hasAnyArgument(declRefExpr()))
+ matches x(1, y, 42)
+with hasAnyArgument(...)
+ matching y
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+ void foo(I *i) { [i f:12]; }
+objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
+ matches [i f:12]
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('hasArgument2')"><a name="hasArgument2Anchor">hasArgument</a></td><td>unsigned N, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasArgument2"><pre>Matches the n'th argument of a call expression or a constructor
call expression.
@@ -5656,6 +5739,47 @@
</pre></td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>></td><td class="name" onclick="toggle('hasAnyParameter1')"><a name="hasAnyParameter1Anchor">hasAnyParameter</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnyParameter1"><pre>Matches any parameter of a function or ObjC method declaration.
+
+Does not match the 'this' parameter of a method.
+
+Given
+ class X { void f(int x, int y, int z) {} };
+cxxMethodDecl(hasAnyParameter(hasName("y")))
+ matches f(int x, int y, int z) {}
+with hasAnyParameter(...)
+ matching int y
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
+</pre></td></tr>
+
+
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>></td><td class="name" onclick="toggle('hasParameter1')"><a name="hasParameter1Anchor">hasParameter</a></td><td>unsigned N, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasParameter1"><pre>Matches the n'th parameter of a function or an ObjC method
+declaration.
+
+Given
+ class X { void f(int x) {} };
+cxxMethodDecl(hasParameter(0, hasType(varDecl())))
+ matches f(int x) {}
+with hasParameter(...)
+ matching int x
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasParameter(0, hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1OpaqueValueExpr.html">OpaqueValueExpr</a>></td><td class="name" onclick="toggle('hasSourceExpression1')"><a name="hasSourceExpression1Anchor">hasSourceExpression</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasSourceExpression1"><pre>Matches if the cast's source expression
or opaque value's source expression matches the given matcher.
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index b29cd06..58c8113 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -51,11 +51,20 @@
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- ...
+- ``-Wc++98-compat-extra-semi`` is a new flag, which was previously inseparable
+ from ``-Wc++98-compat-pedantic``. The latter still controls the new flag.
+
+- ``-Wextra-semi`` now also controls ``-Wc++98-compat-extra-semi``.
+ Please do note that if you pass ``-Wno-c++98-compat-pedantic``, it implies
+ ``-Wno-c++98-compat-extra-semi``, so if you want that diagnostic, you need
+ to explicitly re-enable it (e.g. by appending ``-Wextra-semi``).
Non-comprehensive list of changes in this release
-------------------------------------------------
+- clang binary and libraries have been renamed from 7.0 to 7.
+ For example, the clang binary will be called clang-7 instead of clang-7.0.
+
- ...
New Compiler Flags
@@ -71,6 +80,16 @@
- ...
+Modified Compiler Flags
+-----------------------
+
+- Before Clang 7.0, we prepended the `#` character to the `--autocomplete`
+ argument to enable cc1 flags. For example, when the `-cc1` or `-Xclang` flag
+ is in the :program:`clang` invocation, the shell executed
+ `clang --autocomplete=#-<flag to be completed>`. Clang 7.0 now requires the
+ whole invocation including all flags to be passed to the `--autocomplete` like
+ this: `clang --autocomplete=-cc1,-xc++,-fsyn`.
+
New Pragmas in Clang
-----------------------
@@ -86,6 +105,7 @@
sanity, however it is otherwise compatible with existing code using this
feature for GCC. Consult the documentation for the target attribute for more
information.
+
- ...
Windows Support
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index f19aacc..25f99cf 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -1931,8 +1931,8 @@
------------------------------------------
clang supports the -std option, which changes what language mode clang
-uses. The supported modes for C are c89, gnu89, c94, c99, gnu99, c11,
-gnu11, and various aliases for those modes. If no -std option is
+uses. The supported modes for C are c89, gnu89, c99, gnu99, c11, gnu11,
+c17, gnu17, and various aliases for those modes. If no -std option is
specified, clang defaults to gnu11 mode. Many C99 and C11 features are
supported in earlier modes as a conforming extension, with a warning. Use
``-pedantic-errors`` to request an error if a feature from a later standard
@@ -1979,8 +1979,9 @@
- Warnings for use of C11 features are disabled.
- ``__STDC_VERSION__`` is defined to ``201112L`` rather than ``199901L``.
-c94 mode is identical to c89 mode except that digraphs are enabled in
-c94 mode (FIXME: And ``__STDC_VERSION__`` should be defined!).
+Differences between ``*11`` and ``*17`` modes:
+
+- ``__STDC_VERSION__`` is defined to ``201710L`` rather than ``201112L``.
GCC extensions not implemented yet
----------------------------------
@@ -2179,7 +2180,7 @@
.. code-block:: console
$ clang -target nvptx64-unknown-unknown test.cl
- $ clang -target amdgcn-amd-amdhsa-opencl test.cl
+ $ clang -target amdgcn-amd-amdhsa -mcpu=gfx900 test.cl
Compiling to bitcode can be done as follows:
@@ -2287,7 +2288,7 @@
.. code-block:: console
- $ clang -target amdgcn-amd-amdhsa-opencl test.cl
+ $ clang -target amdgcn-amd-amdhsa -mcpu=gfx900 test.cl
- For Nvidia architectures:
diff --git a/examples/clang-interpreter/CMakeLists.txt b/examples/clang-interpreter/CMakeLists.txt
index 3084238..0d13280 100644
--- a/examples/clang-interpreter/CMakeLists.txt
+++ b/examples/clang-interpreter/CMakeLists.txt
@@ -3,13 +3,17 @@
ExecutionEngine
MC
MCJIT
+ OrcJit
Option
+ RuntimeDyld
Support
native
)
add_clang_executable(clang-interpreter
main.cpp
+ Invoke.cpp
+ Manager.cpp
)
add_dependencies(clang-interpreter
@@ -23,3 +27,67 @@
clangDriver
clangFrontend
)
+
+export_executable_symbols(clang-interpreter)
+
+if (MSVC)
+ # Is this a CMake bug that even with export_executable_symbols, Windows
+ # needs to explictly export the type_info vtable
+ set_property(TARGET clang-interpreter
+ APPEND_STRING PROPERTY LINK_FLAGS " /EXPORT:??_7type_info@@6B@")
+endif()
+
+function(clang_enable_exceptions TARGET)
+ # Really have to jump through hoops to enable exception handling independent
+ # of how LLVM is being built.
+ if (NOT LLVM_REQUIRES_EH AND NOT LLVM_REQUIRES_RTTI)
+ if (MSVC)
+ # /EHs to allow throwing from extern "C"
+ set(excptnExceptions_ON "/D _HAS_EXCEPTIONS=1 /EHs /wd4714")
+ set(excptnExceptions_OFF "/D _HAS_EXCEPTIONS=0 /EHs-c-")
+ set(excptnRTTI_ON "/GR")
+ set(excptnRTTI_OFF "/GR-")
+ set(excptnEHRTTIRegEx "(/EHs(-c-?)|_HAS_EXCEPTIONS=(0|1))")
+ else()
+ set(excptnExceptions_ON "-fexceptions")
+ set(excptnExceptions_OFF "-fno-exceptions")
+ set(excptnRTTI_ON "-frtti")
+ set(excptnRTTI_OFF "-fno-rtti")
+ set(excptnEHRTTIRegEx "-f(exceptions|no-exceptions)")
+ endif()
+ if (LLVM_REQUIRES_EH)
+ set(excptnExceptions_DFLT ${excptnExceptions_ON})
+ else()
+ set(excptnExceptions_DFLT ${excptnExceptions_OFF})
+ endif()
+ if (LLVM_REQUIRES_RTTI)
+ set(excptnRTTI_DFLT ${excptnRTTI_ON})
+ else()
+ set(excptnRTTI_DFLT ${excptnRTTI_OFF})
+ endif()
+
+ # Strip the exception & rtti flags from the target
+ get_property(addedFlags TARGET ${TARGET} PROPERTY COMPILE_FLAGS)
+ string(REGEX REPLACE ${excptnEHRTTIRegEx} "" editedFlags "${addedFlags}")
+ string(REPLACE ${excptnRTTI_OFF} "" editedFlags "${editedFlags}")
+ set_property(TARGET ${TARGET} PROPERTY COMPILE_FLAGS "${editedFlags}")
+
+ get_property(addedFlags TARGET ${TARGET} PROPERTY COMPILE_DEFINITIONS)
+ string(REGEX REPLACE ${excptnEHRTTIRegEx} "" editedFlags "${addedFlags}")
+ string(REPLACE ${excptnRTTI_OFF} "" editedFlags "${editedFlags}")
+ set_property(TARGET ${TARGET} PROPERTY COMPILE_DEFINITIONS "${editedFlags}")
+
+ # Re-add the exception & rtti flags from LLVM
+ set_property(SOURCE main.cpp APPEND_STRING PROPERTY COMPILE_FLAGS
+ " ${excptnExceptions_DFLT} ${excptnRTTI_DFLT} ")
+ set_property(SOURCE Manager.cpp APPEND_STRING PROPERTY COMPILE_FLAGS
+ " ${excptnExceptions_DFLT} ${excptnRTTI_DFLT} ")
+
+ # Invoke with exceptions & rtti
+ set_property(SOURCE Invoke.cpp APPEND_STRING PROPERTY COMPILE_FLAGS
+ " ${excptnExceptions_ON} ${excptnRTTI_ON} ")
+
+ endif()
+endfunction(clang_enable_exceptions)
+
+clang_enable_exceptions(clang-interpreter)
diff --git a/examples/clang-interpreter/Invoke.cpp b/examples/clang-interpreter/Invoke.cpp
new file mode 100644
index 0000000..90afa01
--- /dev/null
+++ b/examples/clang-interpreter/Invoke.cpp
@@ -0,0 +1,31 @@
+//==-- examples/clang-interpreter/Invoke.cpp - Clang C Interpreter Example -==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Invoke.h"
+
+#include <iostream>
+#include <stdexcept>
+
+namespace interpreter {
+
+int TryIt(llvm::ExecutionEngine *EE, llvm::Function *EntryFn,
+ const std::vector<std::string> &Args, char *const *EnvP,
+ Invoker Invoke) {
+ int Res = -1;
+ try {
+ Res = Invoke(EE, EntryFn, Args, EnvP);
+ } catch (const std::exception &E) {
+ std::cout << "Caught '" << E.what() << "'\n";
+ } catch (...) {
+ std::cout << "Unknown exception\n";
+ }
+ return Res;
+}
+
+}
diff --git a/examples/clang-interpreter/Invoke.h b/examples/clang-interpreter/Invoke.h
new file mode 100644
index 0000000..3394253
--- /dev/null
+++ b/examples/clang-interpreter/Invoke.h
@@ -0,0 +1,34 @@
+//===-- examples/clang-interpreter/Invoke.h - Clang C Interpreter Example -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_EXAMPLE_INTERPRETER_INVOKE_H
+#define CLANG_EXAMPLE_INTERPRETER_INVOKE_H
+
+namespace llvm {
+ class ExecutionEngine;
+ class Function;
+}
+
+#include <string>
+#include <vector>
+
+namespace interpreter {
+
+typedef std::vector<std::string> InvokeArgs;
+
+typedef int (*Invoker)(llvm::ExecutionEngine *EE, llvm::Function *EntryFn,
+ const InvokeArgs &Args, char *const *EnvP);
+
+int TryIt(llvm::ExecutionEngine *EE, llvm::Function *EntryFn,
+ const InvokeArgs &Args, char *const *EnvP,
+ Invoker Invoke);
+
+} // interpreter
+
+#endif // CLANG_EXAMPLE_INTERPRETER_INVOKE_H
diff --git a/examples/clang-interpreter/Manager.cpp b/examples/clang-interpreter/Manager.cpp
new file mode 100644
index 0000000..6c83b9d
--- /dev/null
+++ b/examples/clang-interpreter/Manager.cpp
@@ -0,0 +1,328 @@
+//==-- examples/clang-interpreter/Manager.cpp - Clang C Interpreter Example -=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Manager.h"
+
+#ifdef CLANG_INTERPRETER_WIN_EXCEPTIONS
+#include "llvm/Support/DynamicLibrary.h"
+
+#define WIN32_LEAN_AND_MEAN
+#define NOGDI
+#define NOMINMAX
+#include <windows.h>
+#endif
+
+namespace interpreter {
+
+using namespace llvm;
+
+void SingleSectionMemoryManager::Block::Reset(uint8_t *Ptr, uintptr_t Size) {
+ assert(Ptr != nullptr && "Bad allocation");
+ Addr = Ptr;
+ End = Ptr ? Ptr + Size : nullptr;
+}
+
+uint8_t *SingleSectionMemoryManager::Block::Next(uintptr_t Size,
+ unsigned Alignment) {
+ uintptr_t Out = (uintptr_t)Addr;
+
+ // Align the out pointer properly
+ if (!Alignment)
+ Alignment = 16;
+ Out = (Out + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
+
+ // RuntimeDyld should have called reserveAllocationSpace with an amount that
+ // will fit all required alignemnts...but assert on this to make sure.
+ assert((Out + Size) <= (uintptr_t)End && "Out of bounds");
+
+ // Set the next Addr to deliver at the end of this one.
+ Addr = (uint8_t *)(Out + Size);
+ return (uint8_t *)Out;
+}
+
+uint8_t *SingleSectionMemoryManager::allocateCodeSection(uintptr_t Size,
+ unsigned Align,
+ unsigned ID,
+ StringRef Name) {
+ return Code.Next(Size, Align);
+}
+
+uint8_t *SingleSectionMemoryManager::allocateDataSection(
+ uintptr_t Size, unsigned Align, unsigned ID, StringRef Name, bool RO) {
+ return RO ? ROData.Next(Size, Align) : RWData.Next(Size, Align);
+}
+
+void SingleSectionMemoryManager::reserveAllocationSpace(
+ uintptr_t CodeSize, uint32_t CodeAlign, uintptr_t ROSize, uint32_t ROAlign,
+ uintptr_t RWSize, uint32_t RWAlign) {
+ // FIXME: Ideally this should be one contiguous block, with Code, ROData,
+ // and RWData pointing to sub-blocks within, but setting the correct
+ // permissions for that wouldn't work unless we over-allocated to have each
+ // Block.Base aligned on a page boundary.
+ const unsigned SecID = 0;
+ Code.Reset(SectionMemoryManager::allocateCodeSection(CodeSize, CodeAlign,
+ SecID, "code"),
+ CodeSize);
+
+ ROData.Reset(SectionMemoryManager::allocateDataSection(ROSize, ROAlign, SecID,
+ "rodata", true/*RO*/),
+ ROSize);
+
+ RWData.Reset(SectionMemoryManager::allocateDataSection(RWSize, RWAlign, SecID,
+ "rwdata", false/*RO*/),
+ RWSize);
+
+#ifdef CLANG_INTERPRETER_WIN_EXCEPTIONS
+ ImageBase =
+ (uintptr_t)std::min(std::min(Code.Addr, ROData.Addr), RWData.Addr);
+#endif
+}
+
+#ifdef CLANG_INTERPRETER_WIN_EXCEPTIONS
+
+// Map an "ImageBase" to a range of adresses that can throw.
+//
+class SEHFrameHandler {
+ typedef SingleSectionMemoryManager::EHFrameInfos EHFrameInfos;
+ typedef std::vector<std::pair<DWORD, DWORD>> ImageRanges;
+ typedef std::map<uintptr_t, ImageRanges> ImageBaseMap;
+ ImageBaseMap m_Map;
+
+ static void MergeRanges(ImageRanges &Ranges);
+ uintptr_t FindEHFrame(uintptr_t Caller);
+
+public:
+ static __declspec(noreturn) void __stdcall RaiseSEHException(void *, void *);
+ void RegisterEHFrames(uintptr_t ImageBase, const EHFrameInfos &Frames,
+ bool Block = true);
+ void DeRegisterEHFrames(uintptr_t ImageBase, const EHFrameInfos &Frames);
+};
+
+// Merge overlaping ranges for faster searching with throwing PC
+void SEHFrameHandler::MergeRanges(ImageRanges &Ranges) {
+ std::sort(Ranges.begin(), Ranges.end());
+
+ ImageRanges Merged;
+ ImageRanges::iterator It = Ranges.begin();
+ auto Current = *(It)++;
+ while (It != Ranges.end()) {
+ if (Current.second + 1 < It->first) {
+ Merged.push_back(Current);
+ Current = *(It);
+ } else
+ Current.second = std::max(Current.second, It->second);
+ ++It;
+ }
+ Merged.emplace_back(Current);
+ Ranges.swap(Merged);
+}
+
+// Find the "ImageBase" for Caller/PC who is throwing an exception
+uintptr_t SEHFrameHandler::FindEHFrame(uintptr_t Caller) {
+ for (auto &&Itr : m_Map) {
+ const uintptr_t ImgBase = Itr.first;
+ for (auto &&Rng : Itr.second) {
+ if (Caller >= (ImgBase + Rng.first) && Caller <= (ImgBase + Rng.second))
+ return ImgBase;
+ }
+ }
+ return 0;
+}
+
+// Register a range of adresses for a single section that
+void SEHFrameHandler::RegisterEHFrames(uintptr_t ImageBase,
+ const EHFrameInfos &Frames, bool Block) {
+ if (Frames.empty())
+ return;
+ assert(m_Map.find(ImageBase) == m_Map.end());
+
+ ImageBaseMap::mapped_type &Ranges = m_Map[ImageBase];
+ ImageRanges::value_type *BlockRange = nullptr;
+ if (Block) {
+ // Merge all unwind adresses into a single contiguous block for faster
+ // searching later.
+ Ranges.emplace_back(std::numeric_limits<DWORD>::max(),
+ std::numeric_limits<DWORD>::min());
+ BlockRange = &Ranges.back();
+ }
+
+ for (auto &&Frame : Frames) {
+ assert(m_Map.find(DWORD64(Frame.Addr)) == m_Map.end() &&
+ "Runtime function should not be a key!");
+
+ PRUNTIME_FUNCTION RFunc = reinterpret_cast<PRUNTIME_FUNCTION>(Frame.Addr);
+ const size_t N = Frame.Size / sizeof(RUNTIME_FUNCTION);
+ if (BlockRange) {
+ for (PRUNTIME_FUNCTION It = RFunc, End = RFunc + N; It < End; ++It) {
+ BlockRange->first = std::min(BlockRange->first, It->BeginAddress);
+ BlockRange->second = std::max(BlockRange->second, It->EndAddress);
+ }
+ } else {
+ for (PRUNTIME_FUNCTION It = RFunc, End = RFunc + N; It < End; ++It)
+ Ranges.emplace_back(It->BeginAddress, It->EndAddress);
+ }
+
+ ::RtlAddFunctionTable(RFunc, N, ImageBase);
+ }
+
+ if (!Block)
+ MergeRanges(Ranges); // Initial sort and merge
+}
+
+void SEHFrameHandler::DeRegisterEHFrames(uintptr_t ImageBase,
+ const EHFrameInfos &Frames) {
+ if (Frames.empty())
+ return;
+
+ auto Itr = m_Map.find(ImageBase);
+ if (Itr != m_Map.end()) {
+ // Remove the ImageBase from lookup
+ m_Map.erase(Itr);
+
+ // Unregister all the PRUNTIME_FUNCTIONs
+ for (auto &&Frame : Frames)
+ ::RtlDeleteFunctionTable(reinterpret_cast<PRUNTIME_FUNCTION>(Frame.Addr));
+ }
+}
+
+// FIXME: Rather than this static and overriding _CxxThrowException via
+// DynamicLibrary::AddSymbol, a better route would be to transform the call
+// to _CxxThrowException(Arg0, Arg1) -> RaiseSEHException(Arg0, Arg1, this)
+// where 'this' is the SingleSectionMemoryManager instance. This could probably
+// be done with clang, and definitely possible by injecting an llvm-IR function
+// into the module with the name '_CxxThrowException'
+//
+static SEHFrameHandler sFrameHandler;
+
+void SingleSectionMemoryManager::deregisterEHFrames() {
+ sFrameHandler.DeRegisterEHFrames(ImageBase, EHFrames);
+ EHFrameInfos().swap(EHFrames);
+}
+
+bool SingleSectionMemoryManager::finalizeMemory(std::string *ErrMsg) {
+ sFrameHandler.RegisterEHFrames(ImageBase, EHFrames);
+ ImageBase = 0;
+ return SectionMemoryManager::finalizeMemory(ErrMsg);
+}
+
+SingleSectionMemoryManager::SingleSectionMemoryManager() {
+ // Override Windows _CxxThrowException to call into our local version that
+ // can throw to and from the JIT.
+ sys::DynamicLibrary::AddSymbol(
+ "_CxxThrowException",
+ (void *)(uintptr_t)&SEHFrameHandler::RaiseSEHException);
+}
+
+// Adapted from VisualStudio/VC/crt/src/vcruntime/throw.cpp
+#ifdef _WIN64
+#define _EH_RELATIVE_OFFSETS 1
+#endif
+// The NT Exception # that we use
+#define EH_EXCEPTION_NUMBER ('msc' | 0xE0000000)
+// The magic # identifying this version
+#define EH_MAGIC_NUMBER1 0x19930520
+#define EH_PURE_MAGIC_NUMBER1 0x01994000
+// Number of parameters in exception record
+#define EH_EXCEPTION_PARAMETERS 4
+
+// A generic exception record
+struct EHExceptionRecord {
+ DWORD ExceptionCode;
+ DWORD ExceptionFlags; // Flags determined by NT
+ _EXCEPTION_RECORD *ExceptionRecord; // Extra exception record (unused)
+ void *ExceptionAddress; // Address at which exception occurred
+ DWORD NumberParameters; // No. of parameters = EH_EXCEPTION_PARAMETERS
+ struct EHParameters {
+ DWORD magicNumber; // = EH_MAGIC_NUMBER1
+ void *pExceptionObject; // Pointer to the actual object thrown
+ struct ThrowInfo *pThrowInfo; // Description of thrown object
+#if _EH_RELATIVE_OFFSETS
+ DWORD64 pThrowImageBase; // Image base of thrown object
+#endif
+ } params;
+};
+
+__declspec(noreturn) void __stdcall
+SEHFrameHandler::RaiseSEHException(void *CxxExcept, void *Info) {
+ uintptr_t Caller;
+ static_assert(sizeof(Caller) == sizeof(PVOID), "Size mismatch");
+
+ USHORT Frames = CaptureStackBackTrace(1, 1, (PVOID *)&Caller, NULL);
+ assert(Frames && "No frames captured");
+ (void)Frames;
+
+ const DWORD64 BaseAddr = sFrameHandler.FindEHFrame(Caller);
+ if (BaseAddr == 0)
+ _CxxThrowException(CxxExcept, (_ThrowInfo *)Info);
+
+ // A generic exception record
+ EHExceptionRecord Exception = {
+ EH_EXCEPTION_NUMBER, // Exception number
+ EXCEPTION_NONCONTINUABLE, // Exception flags (we don't do resume)
+ nullptr, // Additional record (none)
+ nullptr, // Address of exception (OS fills in)
+ EH_EXCEPTION_PARAMETERS, // Number of parameters
+ {EH_MAGIC_NUMBER1, CxxExcept, (struct ThrowInfo *)Info,
+#if _EH_RELATIVE_OFFSETS
+ BaseAddr
+#endif
+ }};
+
+// const ThrowInfo* pTI = (const ThrowInfo*)Info;
+
+#ifdef THROW_ISWINRT
+ if (pTI && (THROW_ISWINRT((*pTI)))) {
+ // The pointer to the ExceptionInfo structure is stored sizeof(void*)
+ // infront of each WinRT Exception Info.
+ ULONG_PTR *EPtr = *reinterpret_cast<ULONG_PTR **>(CxxExcept);
+ EPtr--;
+
+ WINRTEXCEPTIONINFO **ppWei = reinterpret_cast<WINRTEXCEPTIONINFO **>(EPtr);
+ pTI = (*ppWei)->throwInfo;
+ (*ppWei)->PrepareThrow(ppWei);
+ }
+#endif
+
+ // If the throw info indicates this throw is from a pure region,
+ // set the magic number to the Pure one, so only a pure-region
+ // catch will see it.
+ //
+ // Also use the Pure magic number on Win64 if we were unable to
+ // determine an image base, since that was the old way to determine
+ // a pure throw, before the TI_IsPure bit was added to the FuncInfo
+ // attributes field.
+ if (Info != nullptr) {
+#ifdef THROW_ISPURE
+ if (THROW_ISPURE(*pTI))
+ Exception.params.magicNumber = EH_PURE_MAGIC_NUMBER1;
+#if _EH_RELATIVE_OFFSETS
+ else
+#endif // _EH_RELATIVE_OFFSETS
+#endif // THROW_ISPURE
+
+ // Not quite sure what this is about, but pThrowImageBase can never be 0
+ // here, as that is used to mark when an "ImageBase" was not found.
+#if 0 && _EH_RELATIVE_OFFSETS
+ if (Exception.params.pThrowImageBase == 0)
+ Exception.params.magicNumber = EH_PURE_MAGIC_NUMBER1;
+#endif // _EH_RELATIVE_OFFSETS
+ }
+
+// Hand it off to the OS:
+#if defined(_M_X64) && defined(_NTSUBSET_)
+ RtlRaiseException((PEXCEPTION_RECORD)&Exception);
+#else
+ RaiseException(Exception.ExceptionCode, Exception.ExceptionFlags,
+ Exception.NumberParameters, (PULONG_PTR)&Exception.params);
+#endif
+}
+
+#endif // CLANG_INTERPRETER_WIN_EXCEPTIONS
+
+} // namespace interpreter
diff --git a/examples/clang-interpreter/Manager.h b/examples/clang-interpreter/Manager.h
new file mode 100644
index 0000000..d1b1461
--- /dev/null
+++ b/examples/clang-interpreter/Manager.h
@@ -0,0 +1,59 @@
+//===-- examples/clang-interpreter/Manager.h - Clang C Interpreter Example -==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_EXAMPLE_INTERPRETER_MANAGER_H
+#define CLANG_EXAMPLE_INTERPRETER_MANAGER_H
+
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+
+#if defined(LLVM_ON_WIN32) && defined(_WIN64)
+#define CLANG_INTERPRETER_COFF_FORMAT
+#define CLANG_INTERPRETER_WIN_EXCEPTIONS
+#endif
+
+namespace interpreter {
+
+class SingleSectionMemoryManager : public llvm::SectionMemoryManager {
+ struct Block {
+ uint8_t *Addr = nullptr, *End = nullptr;
+ void Reset(uint8_t *Ptr, uintptr_t Size);
+ uint8_t *Next(uintptr_t Size, unsigned Alignment);
+ };
+ Block Code, ROData, RWData;
+
+public:
+ uint8_t *allocateCodeSection(uintptr_t Size, unsigned Align, unsigned ID,
+ llvm::StringRef Name) final;
+
+ uint8_t *allocateDataSection(uintptr_t Size, unsigned Align, unsigned ID,
+ llvm::StringRef Name, bool RO) final;
+
+ void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
+ uintptr_t ROSize, uint32_t ROAlign,
+ uintptr_t RWSize, uint32_t RWAlign) final;
+
+ bool needsToReserveAllocationSpace() override { return true; }
+
+#ifdef CLANG_INTERPRETER_WIN_EXCEPTIONS
+ using llvm::SectionMemoryManager::EHFrameInfos;
+
+ SingleSectionMemoryManager();
+
+ void deregisterEHFrames() override;
+
+ bool finalizeMemory(std::string *ErrMsg) override;
+
+private:
+ uintptr_t ImageBase = 0;
+#endif
+};
+
+}
+
+#endif // CLANG_EXAMPLE_INTERPRETER_MANAGER_H
diff --git a/examples/clang-interpreter/README.txt b/examples/clang-interpreter/README.txt
index 7dd45fa..b4f8a93 100644
--- a/examples/clang-interpreter/README.txt
+++ b/examples/clang-interpreter/README.txt
@@ -1,4 +1,4 @@
-This is an example of Clang based interpreter, for executing standalone C
+This is an example of Clang based interpreter, for executing standalone C/C++
programs.
It demonstrates the following features:
@@ -12,6 +12,9 @@
4. Use the LLVM JIT functionality to execute the final module.
+ 5. Intercepting a Win64 library call to allow throwing and catching exceptions
+ in and from the JIT.
+
The implementation has many limitations and is not designed to be a full fledged
-C interpreter. It is designed to demonstrate a simple but functional use of the
+interpreter. It is designed to demonstrate a simple but functional use of the
Clang compiler libraries.
diff --git a/examples/clang-interpreter/Test.cxx b/examples/clang-interpreter/Test.cxx
new file mode 100644
index 0000000..d2cbb0b
--- /dev/null
+++ b/examples/clang-interpreter/Test.cxx
@@ -0,0 +1,34 @@
+//===-- examples/clang-interpreter/Test.cxx - Clang C Interpreter Example -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Example throwing in and from the JIT (particularly on Win64).
+//
+// ./bin/clang-interpreter <src>/tools/clang/examples/clang-interpreter/Test.cxx
+
+#include <stdexcept>
+#include <stdio.h>
+
+static void ThrowerAnError(const char* Name) {
+ throw std::runtime_error(Name);
+}
+
+int main(int argc, const char** argv) {
+ for (int I = 0; I < argc; ++I)
+ printf("arg[%d]='%s'\n", I, argv[I]);
+
+ try {
+ ThrowerAnError("In JIT");
+ } catch (const std::exception& E) {
+ printf("Caught: '%s'\n", E.what());
+ } catch (...) {
+ printf("Unknown exception\n");
+ }
+ ThrowerAnError("From JIT");
+ return 0;
+}
diff --git a/examples/clang-interpreter/main.cpp b/examples/clang-interpreter/main.cpp
index f783229..5c5e335 100644
--- a/examples/clang-interpreter/main.cpp
+++ b/examples/clang-interpreter/main.cpp
@@ -7,6 +7,9 @@
//
//===----------------------------------------------------------------------===//
+#include "Invoke.h"
+#include "Manager.h"
+
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/Compilation.h"
@@ -26,60 +29,45 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
-#include <memory>
+
using namespace clang;
using namespace clang::driver;
+namespace interpreter {
+
+static llvm::ExecutionEngine *
+createExecutionEngine(std::unique_ptr<llvm::Module> M, std::string *ErrorStr) {
+ llvm::EngineBuilder EB(std::move(M));
+ EB.setErrorStr(ErrorStr);
+ EB.setMemoryManager(llvm::make_unique<SingleSectionMemoryManager>());
+ llvm::ExecutionEngine *EE = EB.create();
+ EE->finalizeObject();
+ return EE;
+}
+
+// Invoked from a try/catch block in invoke.cpp.
+//
+static int Invoke(llvm::ExecutionEngine *EE, llvm::Function *EntryFn,
+ const std::vector<std::string> &Args, char *const *EnvP) {
+ return EE->runFunctionAsMain(EntryFn, Args, EnvP);
+}
+
// This function isn't referenced outside its translation unit, but it
// can't use the "static" keyword because its address is used for
// GetMainExecutable (since some platforms don't support taking the
// address of main, and some platforms can't implement GetMainExecutable
// without being given the address of a function in the main executable).
-std::string GetExecutablePath(const char *Argv0) {
- // This just needs to be some symbol in the binary; C++ doesn't
- // allow taking the address of ::main however.
- void *MainAddr = (void*) (intptr_t) GetExecutablePath;
+std::string GetExecutablePath(const char *Argv0, void *MainAddr) {
return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
}
-static llvm::ExecutionEngine *
-createExecutionEngine(std::unique_ptr<llvm::Module> M, std::string *ErrorStr) {
- return llvm::EngineBuilder(std::move(M))
- .setEngineKind(llvm::EngineKind::Either)
- .setErrorStr(ErrorStr)
- .create();
-}
-
-static int Execute(std::unique_ptr<llvm::Module> Mod, char *const *envp) {
- llvm::InitializeNativeTarget();
- llvm::InitializeNativeTargetAsmPrinter();
-
- llvm::Module &M = *Mod;
- std::string Error;
- std::unique_ptr<llvm::ExecutionEngine> EE(
- createExecutionEngine(std::move(Mod), &Error));
- if (!EE) {
- llvm::errs() << "unable to make execution engine: " << Error << "\n";
- return 255;
- }
-
- llvm::Function *EntryFn = M.getFunction("main");
- if (!EntryFn) {
- llvm::errs() << "'main' function not found in module.\n";
- return 255;
- }
-
- // FIXME: Support passing arguments.
- std::vector<std::string> Args;
- Args.push_back(M.getModuleIdentifier());
-
- EE->finalizeObject();
- return EE->runFunctionAsMain(EntryFn, Args, envp);
-}
+} // namespace interpreter
int main(int argc, const char **argv, char * const *envp) {
- void *MainAddr = (void*) (intptr_t) GetExecutablePath;
- std::string Path = GetExecutablePath(argv[0]);
+ // This just needs to be some symbol in the binary; C++ doesn't
+ // allow taking the address of ::main however.
+ void *MainAddr = (void*) (intptr_t) interpreter::GetExecutablePath;
+ std::string Path = interpreter::GetExecutablePath(argv[0], MainAddr);
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
TextDiagnosticPrinter *DiagClient =
new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
@@ -87,12 +75,15 @@
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
- // Use ELF on windows for now.
- std::string TripleStr = llvm::sys::getProcessTriple();
+ const std::string TripleStr = llvm::sys::getProcessTriple();
llvm::Triple T(TripleStr);
+
+ // Use ELF on Windows-32 and MingW for now.
+#ifndef CLANG_INTERPRETER_COFF_FORMAT
if (T.isOSBinFormatCOFF())
T.setObjectFormat(llvm::Triple::ELF);
-
+#endif
+
Driver TheDriver(Path, T.str(), Diags);
TheDriver.setTitle("clang interpreter");
TheDriver.setCheckInputsExist(false);
@@ -163,12 +154,36 @@
if (!Clang.ExecuteAction(*Act))
return 1;
+ llvm::InitializeNativeTarget();
+ llvm::InitializeNativeTargetAsmPrinter();
+
int Res = 255;
- if (std::unique_ptr<llvm::Module> Module = Act->takeModule())
- Res = Execute(std::move(Module), envp);
+ if (std::unique_ptr<llvm::Module> Module = Act->takeModule()) {
+ llvm::Function *EntryFn = Module->getFunction("main");
+ if (!EntryFn) {
+ llvm::errs() << "'main' function not found in module.\n";
+ return Res;
+ }
+
+ std::string Error;
+ std::unique_ptr<llvm::ExecutionEngine> EE(
+ interpreter::createExecutionEngine(std::move(Module), &Error));
+ if (!EE) {
+ llvm::errs() << "unable to make execution engine: " << Error << "\n";
+ return Res;
+ }
+
+ interpreter::InvokeArgs Args;
+ for (int I = 1; I < argc; ++I)
+ Args.push_back(argv[I]);
+
+ if (Clang.getLangOpts().CPlusPlus)
+ Res = interpreter::TryIt(EE.get(), EntryFn, Args, envp, interpreter::Invoke);
+ else
+ Res = interpreter::Invoke(EE.get(), EntryFn, Args, envp);
+ }
// Shutdown.
-
llvm::llvm_shutdown();
return Res;
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 38dce44..10b78bc 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -227,28 +227,33 @@
/// determine if there is a C++ implicit this parameter.
ParamIdx(unsigned Idx, const Decl *D)
: Idx(Idx), HasThis(false), IsValid(true) {
+ assert(Idx >= 1 && "Idx must be one-origin");
if (const auto *FD = dyn_cast<FunctionDecl>(D))
HasThis = FD->isCXXInstanceMember();
}
- /// \param Idx is the parameter index as it is normally specified in
- /// attributes in the source: one-origin including any C++ implicit this
- /// parameter.
+ /// A type into which \c ParamIdx can be serialized.
///
- /// \param HasThis specifies whether the function has a C++ implicit this
- /// parameter.
- ParamIdx(unsigned Idx, bool HasThis)
- : Idx(Idx), HasThis(HasThis), IsValid(true) {}
+ /// A static assertion that it's of the correct size follows the \c ParamIdx
+ /// class definition.
+ typedef uint32_t SerialType;
+
+ /// Produce a representation that can later be passed to \c deserialize to
+ /// construct an equivalent \c ParamIdx.
+ SerialType serialize() const {
+ return *reinterpret_cast<const SerialType *>(this);
+ }
+
+ /// Construct from a result from \c serialize.
+ static ParamIdx deserialize(SerialType S) {
+ ParamIdx P(*reinterpret_cast<ParamIdx *>(&S));
+ assert((!P.IsValid || P.Idx >= 1) && "valid Idx must be one-origin");
+ return P;
+ }
/// Is this parameter index valid?
bool isValid() const { return IsValid; }
- /// Is there a C++ implicit this parameter?
- bool hasThis() const {
- assert(isValid() && "ParamIdx must be valid");
- return HasThis;
- }
-
/// Get the parameter index as it would normally be encoded for attributes at
/// the source level of representation: one-origin including any C++ implicit
/// this parameter.
@@ -309,6 +314,9 @@
}
};
+static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType),
+ "ParamIdx does not fit its serialization type");
+
#include "clang/AST/Attrs.inc"
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 57c6f45..da164c6 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -937,6 +937,9 @@
/// for-range statement.
unsigned CXXForRangeDecl : 1;
+ /// Whether this variable is the for-in loop declaration in Objective-C.
+ unsigned ObjCForDecl : 1;
+
/// Whether this variable is an ARC pseudo-__strong
/// variable; see isARCPseudoStrong() for details.
unsigned ARCPseudoStrong : 1;
@@ -1334,6 +1337,16 @@
NonParmVarDeclBits.CXXForRangeDecl = FRD;
}
+ /// \brief Determine whether this variable is a for-loop declaration for a
+ /// for-in statement in Objective-C.
+ bool isObjCForDecl() const {
+ return NonParmVarDeclBits.ObjCForDecl;
+ }
+
+ void setObjCForDecl(bool FRD) {
+ NonParmVarDeclBits.ObjCForDecl = FRD;
+ }
+
/// \brief Determine whether this variable is an ARC pseudo-__strong
/// variable. A pseudo-__strong variable has a __strong-qualified
/// type but does not actually retain the object written into it.
@@ -3553,6 +3566,17 @@
bool NonTrivialToPrimitiveCopy : 1;
bool NonTrivialToPrimitiveDestroy : 1;
+ /// True if this class can be passed in a non-address-preserving fashion
+ /// (such as in registers).
+ /// This does not imply anything about how the ABI in use will actually
+ /// pass an object of this class.
+ bool CanPassInRegisters : 1;
+
+ /// Indicates whether this struct is destroyed in the callee. This flag is
+ /// meaningless when Microsoft ABI is used since parameters are always
+ /// destroyed in the callee.
+ bool ParamDestroyedInCallee : 1;
+
protected:
RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -3616,24 +3640,44 @@
return NonTrivialToPrimitiveDefaultInitialize;
}
- void setNonTrivialToPrimitiveDefaultInitialize() {
- NonTrivialToPrimitiveDefaultInitialize = true;
+ void setNonTrivialToPrimitiveDefaultInitialize(bool V) {
+ NonTrivialToPrimitiveDefaultInitialize = V;
}
bool isNonTrivialToPrimitiveCopy() const {
return NonTrivialToPrimitiveCopy;
}
- void setNonTrivialToPrimitiveCopy() {
- NonTrivialToPrimitiveCopy = true;
+ void setNonTrivialToPrimitiveCopy(bool V) {
+ NonTrivialToPrimitiveCopy = V;
}
bool isNonTrivialToPrimitiveDestroy() const {
return NonTrivialToPrimitiveDestroy;
}
- void setNonTrivialToPrimitiveDestroy() {
- NonTrivialToPrimitiveDestroy = true;
+ void setNonTrivialToPrimitiveDestroy(bool V) {
+ NonTrivialToPrimitiveDestroy = V;
+ }
+
+ /// Determine whether this class can be passed in registers. In C++ mode,
+ /// it must have at least one trivial, non-deleted copy or move constructor.
+ /// FIXME: This should be set as part of completeDefinition.
+ bool canPassInRegisters() const {
+ return CanPassInRegisters;
+ }
+
+ /// Set that we can pass this RecordDecl in registers.
+ void setCanPassInRegisters(bool CanPass) {
+ CanPassInRegisters = CanPass;
+ }
+
+ bool isParamDestroyedInCallee() const {
+ return ParamDestroyedInCallee;
+ }
+
+ void setParamDestroyedInCallee(bool V) {
+ ParamDestroyedInCallee = V;
}
/// \brief Determines whether this declaration represents the
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index faa86e3..a5e1677 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -467,12 +467,6 @@
/// constructor.
unsigned HasDefaultedDefaultConstructor : 1;
- /// \brief True if this class can be passed in a non-address-preserving
- /// fashion (such as in registers) according to the C++ language rules.
- /// This does not imply anything about how the ABI in use will actually
- /// pass an object of this class.
- unsigned CanPassInRegisters : 1;
-
/// \brief True if a defaulted default constructor for this class would
/// be constexpr.
unsigned DefaultedDefaultConstructorIsConstexpr : 1;
@@ -1474,25 +1468,6 @@
return data().HasIrrelevantDestructor;
}
- /// \brief Determine whether this class has at least one trivial, non-deleted
- /// copy or move constructor.
- bool canPassInRegisters() const {
- return data().CanPassInRegisters;
- }
-
- /// \brief Set that we can pass this RecordDecl in registers.
- // FIXME: This should be set as part of completeDefinition.
- void setCanPassInRegisters(bool CanPass) {
- data().CanPassInRegisters = CanPass;
- }
-
- /// Determine whether the triviality for the purpose of calls for this class
- /// is overridden to be trivial because this class or the type of one of its
- /// subobjects has attribute "trivial_abi".
- bool hasTrivialABIOverride() const {
- return canPassInRegisters() && hasNonTrivialDestructor();
- }
-
/// \brief Determine whether this class has a non-literal or/ volatile type
/// non-static data member or base class.
bool hasNonLiteralTypeFieldsOrBases() const {
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 7842d70..9c68352 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -299,7 +299,7 @@
static ParmDecl *getParmOwningDefaultArg(ParmDecl *Parm) {
const DefaultArgStorage &Storage = Parm->getDefaultArgStorage();
- if (auto *Prev = Storage.ValueOrInherited.template dyn_cast<ParmDecl*>())
+ if (auto *Prev = Storage.ValueOrInherited.template dyn_cast<ParmDecl *>())
Parm = Prev;
assert(!Parm->getDefaultArgStorage()
.ValueOrInherited.template is<ParmDecl *>() &&
@@ -321,9 +321,9 @@
/// default argument is visible.
ArgType get() const {
const DefaultArgStorage *Storage = this;
- if (auto *Prev = ValueOrInherited.template dyn_cast<ParmDecl*>())
+ if (const auto *Prev = ValueOrInherited.template dyn_cast<ParmDecl *>())
Storage = &Prev->getDefaultArgStorage();
- if (auto *C = Storage->ValueOrInherited.template dyn_cast<Chain*>())
+ if (const auto *C = Storage->ValueOrInherited.template dyn_cast<Chain *>())
return C->Value;
return Storage->ValueOrInherited.template get<ArgType>();
}
@@ -331,9 +331,9 @@
/// Get the parameter from which we inherit the default argument, if any.
/// This is the parameter on which the default argument was actually written.
const ParmDecl *getInheritedFrom() const {
- if (auto *D = ValueOrInherited.template dyn_cast<ParmDecl*>())
+ if (const auto *D = ValueOrInherited.template dyn_cast<ParmDecl *>())
return D;
- if (auto *C = ValueOrInherited.template dyn_cast<Chain*>())
+ if (const auto *C = ValueOrInherited.template dyn_cast<Chain *>())
return C->PrevDeclWithDefaultArg;
return nullptr;
}
@@ -443,7 +443,7 @@
}
Expr *getAssociatedConstraints() const {
- const TemplateDecl *const C = cast<TemplateDecl>(getCanonicalDecl());
+ const auto *const C = cast<TemplateDecl>(getCanonicalDecl());
const auto *const CTDI =
C->TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
return CTDI ? CTDI->getAssociatedConstraints() : nullptr;
@@ -466,6 +466,7 @@
protected:
NamedDecl *TemplatedDecl;
+
/// \brief The template parameter list and optional requires-clause
/// associated with this declaration; alternatively, a
/// \c ConstrainedTemplateDeclInfo if the associated constraints of the
@@ -1621,7 +1622,7 @@
}
SourceRange getSourceRange() const override LLVM_READONLY {
- return SourceRange();
+ return {};
}
BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; }
@@ -1789,8 +1790,8 @@
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
getSpecializedTemplateOrPartial() const {
- if (SpecializedPartialSpecialization *PartialSpec
- = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ if (const auto *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return PartialSpec->PartialSpecialization;
return SpecializedTemplate.get<ClassTemplateDecl*>();
@@ -1808,8 +1809,8 @@
/// deduced template arguments for the class template partial specialization
/// itself.
const TemplateArgumentList &getTemplateInstantiationArgs() const {
- if (SpecializedPartialSpecialization *PartialSpec
- = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ if (const auto *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return *PartialSpec->TemplateArgs;
return getTemplateArgs();
@@ -1822,8 +1823,7 @@
const TemplateArgumentList *TemplateArgs) {
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
"Already set to a class template partial specialization!");
- SpecializedPartialSpecialization *PS
- = new (getASTContext()) SpecializedPartialSpecialization();
+ auto *PS = new (getASTContext()) SpecializedPartialSpecialization();
PS->PartialSpecialization = PartialSpec;
PS->TemplateArgs = TemplateArgs;
SpecializedTemplate = PS;
@@ -1984,7 +1984,7 @@
/// \c Outer<float>::Inner<U*>, this function would return
/// \c Outer<T>::Inner<U*>.
ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
- const ClassTemplatePartialSpecializationDecl *First =
+ const auto *First =
cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getPointer();
}
@@ -1995,8 +1995,7 @@
void setInstantiatedFromMember(
ClassTemplatePartialSpecializationDecl *PartialSpec) {
- ClassTemplatePartialSpecializationDecl *First =
- cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
+ auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
First->InstantiatedFromMember.setPointer(PartialSpec);
}
@@ -2017,15 +2016,14 @@
/// struct X<int>::Inner<T*> { /* ... */ };
/// \endcode
bool isMemberSpecialization() {
- ClassTemplatePartialSpecializationDecl *First =
+ const auto *First =
cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getInt();
}
/// \brief Note that this member template is a specialization.
void setMemberSpecialization() {
- ClassTemplatePartialSpecializationDecl *First =
- cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
+ auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
assert(First->InstantiatedFromMember.getPointer() &&
"Only member templates can be member template specializations");
return First->InstantiatedFromMember.setInt(true);
@@ -2627,7 +2625,7 @@
/// specialization which was specialized by this.
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
getSpecializedTemplateOrPartial() const {
- if (SpecializedPartialSpecialization *PartialSpec =
+ if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return PartialSpec->PartialSpecialization;
@@ -2646,7 +2644,7 @@
/// return deduced template arguments for the variable template partial
/// specialization itself.
const TemplateArgumentList &getTemplateInstantiationArgs() const {
- if (SpecializedPartialSpecialization *PartialSpec =
+ if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return *PartialSpec->TemplateArgs;
@@ -2660,8 +2658,7 @@
const TemplateArgumentList *TemplateArgs) {
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
"Already set to a variable template partial specialization!");
- SpecializedPartialSpecialization *PS =
- new (getASTContext()) SpecializedPartialSpecialization();
+ auto *PS = new (getASTContext()) SpecializedPartialSpecialization();
PS->PartialSpecialization = PartialSpec;
PS->TemplateArgs = TemplateArgs;
SpecializedTemplate = PS;
@@ -2815,15 +2812,14 @@
/// \c Outer<float>::Inner<U*>, this function would return
/// \c Outer<T>::Inner<U*>.
VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
- const VarTemplatePartialSpecializationDecl *First =
+ const auto *First =
cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getPointer();
}
void
setInstantiatedFromMember(VarTemplatePartialSpecializationDecl *PartialSpec) {
- VarTemplatePartialSpecializationDecl *First =
- cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
First->InstantiatedFromMember.setPointer(PartialSpec);
}
@@ -2844,15 +2840,14 @@
/// U* X<int>::Inner<T*> = (T*)(0) + 1;
/// \endcode
bool isMemberSpecialization() {
- VarTemplatePartialSpecializationDecl *First =
+ const auto *First =
cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getInt();
}
/// \brief Note that this member template is a specialization.
void setMemberSpecialization() {
- VarTemplatePartialSpecializationDecl *First =
- cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
assert(First->InstantiatedFromMember.getPointer() &&
"Only member templates can be member template specializations");
return First->InstantiatedFromMember.setInt(true);
@@ -3021,11 +3016,11 @@
};
inline NamedDecl *getAsNamedDecl(TemplateParameter P) {
- if (auto *PD = P.dyn_cast<TemplateTypeParmDecl*>())
+ if (auto *PD = P.dyn_cast<TemplateTypeParmDecl *>())
return PD;
- if (auto *PD = P.dyn_cast<NonTypeTemplateParmDecl*>())
+ if (auto *PD = P.dyn_cast<NonTypeTemplateParmDecl *>())
return PD;
- return P.get<TemplateTemplateParmDecl*>();
+ return P.get<TemplateTemplateParmDecl *>();
}
inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) {
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 9707a7e..8c339a8 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -883,6 +883,7 @@
(SourceExpr && SourceExpr->isInstantiationDependent()),
false),
SourceExpr(SourceExpr), Loc(Loc) {
+ setIsUnique(false);
}
/// Given an expression which invokes a copy constructor --- i.e. a
@@ -925,6 +926,14 @@
/// place.
Expr *getSourceExpr() const { return SourceExpr; }
+ void setIsUnique(bool V) {
+ assert((!V || SourceExpr) &&
+ "unique OVEs are expected to have source expressions");
+ OpaqueValueExprBits.IsUnique = V;
+ }
+
+ bool isUnique() const { return OpaqueValueExprBits.IsUnique; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OpaqueValueExprClass;
}
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
index 7a45d88..71c78dc 100644
--- a/include/clang/AST/Mangle.h
+++ b/include/clang/AST/Mangle.h
@@ -30,6 +30,7 @@
class CXXDestructorDecl;
class CXXMethodDecl;
class FunctionDecl;
+ struct MethodVFTableLocation;
class NamedDecl;
class ObjCMethodDecl;
class StringLiteral;
@@ -201,7 +202,8 @@
raw_ostream &Out) = 0;
virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
- raw_ostream &) = 0;
+ const MethodVFTableLocation &ML,
+ raw_ostream &Out) = 0;
virtual void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD,
const CXXRecordDecl *DstRD,
diff --git a/include/clang/Sema/PrettyDeclStackTrace.h b/include/clang/AST/PrettyDeclStackTrace.h
similarity index 80%
rename from include/clang/Sema/PrettyDeclStackTrace.h
rename to include/clang/AST/PrettyDeclStackTrace.h
index ca22e64..8eb519e 100644
--- a/include/clang/Sema/PrettyDeclStackTrace.h
+++ b/include/clang/AST/PrettyDeclStackTrace.h
@@ -13,31 +13,31 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SEMA_PRETTYDECLSTACKTRACE_H
-#define LLVM_CLANG_SEMA_PRETTYDECLSTACKTRACE_H
+#ifndef LLVM_CLANG_AST_PRETTYDECLSTACKTRACE_H
+#define LLVM_CLANG_AST_PRETTYDECLSTACKTRACE_H
#include "clang/Basic/SourceLocation.h"
#include "llvm/Support/PrettyStackTrace.h"
namespace clang {
+class ASTContext;
class Decl;
-class Sema;
class SourceManager;
/// PrettyDeclStackTraceEntry - If a crash occurs in the parser while
/// parsing something related to a declaration, include that
/// declaration in the stack trace.
class PrettyDeclStackTraceEntry : public llvm::PrettyStackTraceEntry {
- Sema &S;
+ ASTContext &Context;
Decl *TheDecl;
SourceLocation Loc;
const char *Message;
public:
- PrettyDeclStackTraceEntry(Sema &S, Decl *D, SourceLocation Loc,
+ PrettyDeclStackTraceEntry(ASTContext &Ctx, Decl *D, SourceLocation Loc,
const char *Msg)
- : S(S), TheDecl(D), Loc(Loc), Message(Msg) {}
+ : Context(Ctx), TheDecl(D), Loc(Loc), Message(Msg) {}
void print(raw_ostream &OS) const override;
};
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index b27dbfa..aa8f3d9 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -237,6 +237,16 @@
unsigned ResultIndex : 32 - 8 - NumExprBits;
};
+ class OpaqueValueExprBitfields {
+ friend class OpaqueValueExpr;
+
+ unsigned : NumExprBits;
+
+ /// The OVE is a unique semantic reference to its source expressio if this
+ /// bit is set to true.
+ unsigned IsUnique : 1;
+ };
+
class ObjCIndirectCopyRestoreExprBitfields {
friend class ObjCIndirectCopyRestoreExpr;
@@ -294,6 +304,7 @@
CallExprBitfields CallExprBits;
ExprWithCleanupsBitfields ExprWithCleanupsBits;
PseudoObjectExprBitfields PseudoObjectExprBits;
+ OpaqueValueExprBitfields OpaqueValueExprBits;
ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
InitListExprBitfields InitListExprBits;
TypeTraitExprBitfields TypeTraitExprBits;
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 4dd67f7..b5bb133 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -667,8 +667,7 @@
const ExtQualsTypeCommonBase *getCommonPtr() const {
assert(!isNull() && "Cannot retrieve a NULL type pointer");
- uintptr_t CommonPtrVal
- = reinterpret_cast<uintptr_t>(Value.getOpaqueValue());
+ auto CommonPtrVal = reinterpret_cast<uintptr_t>(Value.getOpaqueValue());
CommonPtrVal &= ~(uintptr_t)((1 << TypeAlignmentInBits) - 1);
return reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal);
}
@@ -808,11 +807,6 @@
/// Return true if this is a trivially copyable type (C++0x [basic.types]p9)
bool isTriviallyCopyableType(const ASTContext &Context) const;
- /// Determine whether this is a class whose triviality for the purpose of
- /// calls is overridden to be trivial because the class or the type of one of
- /// its subobjects has attribute "trivial_abi".
- bool hasTrivialABIOverride() const;
-
// Don't promise in the API that anything besides 'const' can be
// easily added.
@@ -1097,6 +1091,10 @@
/// with the ARC __strong qualifier.
PDIK_ARCStrong,
+ /// The type is an Objective-C retainable pointer type that is qualified
+ /// with the ARC __weak qualifier.
+ PDIK_ARCWeak,
+
/// The type is a struct containing a field whose type is not PCK_Trivial.
PDIK_Struct
};
@@ -1124,6 +1122,10 @@
/// with the ARC __strong qualifier.
PCK_ARCStrong,
+ /// The type is an Objective-C retainable pointer type that is qualified
+ /// with the ARC __weak qualifier.
+ PCK_ARCWeak,
+
/// The type is a struct containing a field whose type is neither
/// PCK_Trivial nor PCK_VolatileTrivial.
/// Note that a C++ struct type does not necessarily match this; C++ copying
@@ -1146,6 +1148,8 @@
/// source object is placed in an uninitialized state.
PrimitiveCopyKind isNonTrivialToPrimitiveDestructiveMove() const;
+ bool canPassInRegisters() const;
+
enum DestructionKind {
DK_none,
DK_cxx_destructor,
@@ -1511,7 +1515,7 @@
/// Extra information which affects how the function is called, like
/// regparm and the calling convention.
- unsigned ExtInfo : 11;
+ unsigned ExtInfo : 12;
/// Used only by FunctionProtoType, put here to pack with the
/// other bitfields.
@@ -3147,24 +3151,24 @@
class ExtInfo {
friend class FunctionType;
- // Feel free to rearrange or add bits, but if you go over 11,
+ // Feel free to rearrange or add bits, but if you go over 12,
// you'll need to adjust both the Bits field below and
// Type::FunctionTypeBitfields.
- // | CC |noreturn|produces|nocallersavedregs|regparm|
- // |0 .. 4| 5 | 6 | 7 |8 .. 10|
+ // | CC |noreturn|produces|nocallersavedregs|regparm|nocfcheck|
+ // |0 .. 4| 5 | 6 | 7 |8 .. 10| 11 |
//
// regparm is either 0 (no regparm attribute) or the regparm value+1.
enum { CallConvMask = 0x1F };
enum { NoReturnMask = 0x20 };
enum { ProducesResultMask = 0x40 };
enum { NoCallerSavedRegsMask = 0x80 };
+ enum { NoCfCheckMask = 0x800 };
enum {
RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask |
- NoCallerSavedRegsMask),
+ NoCallerSavedRegsMask | NoCfCheckMask),
RegParmOffset = 8
}; // Assumed to be the last field
-
uint16_t Bits = CC_C;
ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
@@ -3173,12 +3177,13 @@
// Constructor with no defaults. Use this when you know that you
// have all the elements (when reading an AST file for example).
ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc,
- bool producesResult, bool noCallerSavedRegs) {
+ bool producesResult, bool noCallerSavedRegs, bool NoCfCheck) {
assert((!hasRegParm || regParm < 7) && "Invalid regparm value");
Bits = ((unsigned)cc) | (noReturn ? NoReturnMask : 0) |
(producesResult ? ProducesResultMask : 0) |
(noCallerSavedRegs ? NoCallerSavedRegsMask : 0) |
- (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0);
+ (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0) |
+ (NoCfCheck ? NoCfCheckMask : 0);
}
// Constructor with all defaults. Use when for example creating a
@@ -3192,10 +3197,11 @@
bool getNoReturn() const { return Bits & NoReturnMask; }
bool getProducesResult() const { return Bits & ProducesResultMask; }
bool getNoCallerSavedRegs() const { return Bits & NoCallerSavedRegsMask; }
+ bool getNoCfCheck() const { return Bits & NoCfCheckMask; }
bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; }
unsigned getRegParm() const {
- unsigned RegParm = Bits >> RegParmOffset;
+ unsigned RegParm = (Bits & RegParmMask) >> RegParmOffset;
if (RegParm > 0)
--RegParm;
return RegParm;
@@ -3234,6 +3240,13 @@
return ExtInfo(Bits & ~NoCallerSavedRegsMask);
}
+ ExtInfo withNoCfCheck(bool noCfCheck) const {
+ if (noCfCheck)
+ return ExtInfo(Bits | NoCfCheckMask);
+ else
+ return ExtInfo(Bits & ~NoCfCheckMask);
+ }
+
ExtInfo withRegParm(unsigned RegParm) const {
assert(RegParm < 7 && "Invalid regparm value");
return ExtInfo((Bits & ~RegParmMask) |
@@ -3530,7 +3543,7 @@
assert(hasExtParameterInfos());
// Find the end of the exception specification.
- const char *ptr = reinterpret_cast<const char *>(exception_begin());
+ const auto *ptr = reinterpret_cast<const char *>(exception_begin());
ptr += getExceptionSpecSize();
return reinterpret_cast<const ExtParameterInfo *>(ptr);
@@ -4120,6 +4133,7 @@
// No operand.
attr_noreturn,
+ attr_nocf_check,
attr_cdecl,
attr_fastcall,
attr_stdcall,
@@ -5484,8 +5498,8 @@
inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const {
QualType baseType = getBaseType();
- while (const ObjCObjectType *ObjT = baseType->getAs<ObjCObjectType>()) {
- if (const ObjCInterfaceType *T = dyn_cast<ObjCInterfaceType>(ObjT))
+ while (const auto *ObjT = baseType->getAs<ObjCObjectType>()) {
+ if (const auto *T = dyn_cast<ObjCInterfaceType>(ObjT))
return T->getDecl();
baseType = ObjT->getBaseType();
@@ -5907,10 +5921,10 @@
}
inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) {
- if (const PointerType *PT = t.getAs<PointerType>()) {
- if (const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>())
+ if (const auto *PT = t.getAs<PointerType>()) {
+ if (const auto *FT = PT->getPointeeType()->getAs<FunctionType>())
return FT->getExtInfo();
- } else if (const FunctionType *FT = t.getAs<FunctionType>())
+ } else if (const auto *FT = t.getAs<FunctionType>())
return FT->getExtInfo();
return FunctionType::ExtInfo();
@@ -5955,7 +5969,7 @@
/// analysis, the expression designates the object or function
/// denoted by the reference, and the expression is an lvalue.
inline QualType QualType::getNonReferenceType() const {
- if (const ReferenceType *RefType = (*this)->getAs<ReferenceType>())
+ if (const auto *RefType = (*this)->getAs<ReferenceType>())
return RefType->getPointeeType();
else
return *this;
@@ -6030,7 +6044,7 @@
}
inline bool Type::isFunctionPointerType() const {
- if (const PointerType *T = getAs<PointerType>())
+ if (const auto *T = getAs<PointerType>())
return T->getPointeeType()->isFunctionType();
else
return false;
@@ -6041,14 +6055,14 @@
}
inline bool Type::isMemberFunctionPointerType() const {
- if (const MemberPointerType* T = getAs<MemberPointerType>())
+ if (const auto *T = getAs<MemberPointerType>())
return T->isMemberFunctionPointer();
else
return false;
}
inline bool Type::isMemberDataPointerType() const {
- if (const MemberPointerType* T = getAs<MemberPointerType>())
+ if (const auto *T = getAs<MemberPointerType>())
return T->isMemberDataPointer();
else
return false;
@@ -6120,31 +6134,31 @@
}
inline bool Type::isObjCQualifiedIdType() const {
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ if (const auto *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCQualifiedIdType();
return false;
}
inline bool Type::isObjCQualifiedClassType() const {
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ if (const auto *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCQualifiedClassType();
return false;
}
inline bool Type::isObjCIdType() const {
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ if (const auto *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCIdType();
return false;
}
inline bool Type::isObjCClassType() const {
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ if (const auto *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCClassType();
return false;
}
inline bool Type::isObjCSelType() const {
- if (const PointerType *OPT = getAs<PointerType>())
+ if (const auto *OPT = getAs<PointerType>())
return OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCSel);
return false;
}
@@ -6207,13 +6221,13 @@
}
inline bool Type::isPlaceholderType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+ if (const auto *BT = dyn_cast<BuiltinType>(this))
return BT->isPlaceholderType();
return false;
}
inline const BuiltinType *Type::getAsPlaceholderType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+ if (const auto *BT = dyn_cast<BuiltinType>(this))
if (BT->isPlaceholderType())
return BT;
return nullptr;
@@ -6221,38 +6235,38 @@
inline bool Type::isSpecificPlaceholderType(unsigned K) const {
assert(BuiltinType::isPlaceholderTypeKind((BuiltinType::Kind) K));
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+ if (const auto *BT = dyn_cast<BuiltinType>(this))
return (BT->getKind() == (BuiltinType::Kind) K);
return false;
}
inline bool Type::isNonOverloadPlaceholderType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+ if (const auto *BT = dyn_cast<BuiltinType>(this))
return BT->isNonOverloadPlaceholderType();
return false;
}
inline bool Type::isVoidType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Void;
return false;
}
inline bool Type::isHalfType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Half;
// FIXME: Should we allow complex __fp16? Probably not.
return false;
}
inline bool Type::isFloat16Type() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Float16;
return false;
}
inline bool Type::isNullPtrType() const {
- if (const BuiltinType *BT = getAs<BuiltinType>())
+ if (const auto *BT = getAs<BuiltinType>())
return BT->getKind() == BuiltinType::NullPtr;
return false;
}
@@ -6261,7 +6275,7 @@
bool IsEnumDeclScoped(EnumDecl *);
inline bool Type::isIntegerType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Int128;
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
@@ -6274,7 +6288,7 @@
}
inline bool Type::isScalarType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() > BuiltinType::Void &&
BT->getKind() <= BuiltinType::NullPtr;
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
@@ -6289,20 +6303,20 @@
}
inline bool Type::isIntegralOrEnumerationType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Int128;
// Check for a complete enum type; incomplete enum types are not properly an
// enumeration type in the sense required here.
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
return IsEnumDeclComplete(ET->getDecl());
return false;
}
inline bool Type::isBooleanType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Bool;
return false;
}
@@ -6379,7 +6393,7 @@
"ArrayType cannot be used with getAs!");
// If this is directly a T type, return it.
- if (const T *Ty = dyn_cast<T>(this))
+ if (const auto *Ty = dyn_cast<T>(this))
return Ty;
// If the canonical form of this type isn't the right kind, reject it.
@@ -6395,7 +6409,7 @@
static_assert(!TypeIsArrayType<T>::value, "ArrayType cannot be used with getAsAdjusted!");
// If this is directly a T type, return it.
- if (const T *Ty = dyn_cast<T>(this))
+ if (const auto *Ty = dyn_cast<T>(this))
return Ty;
// If the canonical form of this type isn't the right kind, reject it.
@@ -6425,7 +6439,7 @@
inline const ArrayType *Type::getAsArrayTypeUnsafe() const {
// If this is directly an array type, return it.
- if (const ArrayType *arr = dyn_cast<ArrayType>(this))
+ if (const auto *arr = dyn_cast<ArrayType>(this))
return arr;
// If the canonical form of this type isn't the right kind, reject it.
@@ -6441,14 +6455,14 @@
static_assert(!TypeIsArrayType<T>::value,
"ArrayType cannot be used with castAs!");
- if (const T *ty = dyn_cast<T>(this)) return ty;
+ if (const auto *ty = dyn_cast<T>(this)) return ty;
assert(isa<T>(CanonicalType));
return cast<T>(getUnqualifiedDesugaredType());
}
inline const ArrayType *Type::castAsArrayTypeUnsafe() const {
assert(isa<ArrayType>(CanonicalType));
- if (const ArrayType *arr = dyn_cast<ArrayType>(this)) return arr;
+ if (const auto *arr = dyn_cast<ArrayType>(this)) return arr;
return cast<ArrayType>(getUnqualifiedDesugaredType());
}
diff --git a/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h
index b0b71e4..96565fa 100644
--- a/include/clang/AST/VTableBuilder.h
+++ b/include/clang/AST/VTableBuilder.h
@@ -479,41 +479,42 @@
VPtrInfoVector VBPtrPaths;
};
+struct MethodVFTableLocation {
+ /// If nonzero, holds the vbtable index of the virtual base with the vfptr.
+ uint64_t VBTableIndex;
+
+ /// If nonnull, holds the last vbase which contains the vfptr that the
+ /// method definition is adjusted to.
+ const CXXRecordDecl *VBase;
+
+ /// This is the offset of the vfptr from the start of the last vbase, or the
+ /// complete type if there are no virtual bases.
+ CharUnits VFPtrOffset;
+
+ /// Method's index in the vftable.
+ uint64_t Index;
+
+ MethodVFTableLocation()
+ : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()),
+ Index(0) {}
+
+ MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase,
+ CharUnits VFPtrOffset, uint64_t Index)
+ : VBTableIndex(VBTableIndex), VBase(VBase), VFPtrOffset(VFPtrOffset),
+ Index(Index) {}
+
+ bool operator<(const MethodVFTableLocation &other) const {
+ if (VBTableIndex != other.VBTableIndex) {
+ assert(VBase != other.VBase);
+ return VBTableIndex < other.VBTableIndex;
+ }
+ return std::tie(VFPtrOffset, Index) <
+ std::tie(other.VFPtrOffset, other.Index);
+ }
+};
+
class MicrosoftVTableContext : public VTableContextBase {
public:
- struct MethodVFTableLocation {
- /// If nonzero, holds the vbtable index of the virtual base with the vfptr.
- uint64_t VBTableIndex;
-
- /// If nonnull, holds the last vbase which contains the vfptr that the
- /// method definition is adjusted to.
- const CXXRecordDecl *VBase;
-
- /// This is the offset of the vfptr from the start of the last vbase, or the
- /// complete type if there are no virtual bases.
- CharUnits VFPtrOffset;
-
- /// Method's index in the vftable.
- uint64_t Index;
-
- MethodVFTableLocation()
- : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()),
- Index(0) {}
-
- MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase,
- CharUnits VFPtrOffset, uint64_t Index)
- : VBTableIndex(VBTableIndex), VBase(VBase),
- VFPtrOffset(VFPtrOffset), Index(Index) {}
-
- bool operator<(const MethodVFTableLocation &other) const {
- if (VBTableIndex != other.VBTableIndex) {
- assert(VBase != other.VBase);
- return VBTableIndex < other.VBTableIndex;
- }
- return std::tie(VFPtrOffset, Index) <
- std::tie(other.VFPtrOffset, other.Index);
- }
- };
private:
ASTContext &Context;
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 6279172..5008d53 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -693,7 +693,7 @@
/// varDecl(hasInitializer(cxxConstructExpr()))
/// \endcode
/// only match the declarations for b and c.
-AST_MATCHER_P(Expr, ignoringImplicit, ast_matchers::internal::Matcher<Expr>,
+AST_MATCHER_P(Expr, ignoringImplicit, internal::Matcher<Expr>,
InnerMatcher) {
return InnerMatcher.matches(*Node.IgnoreImplicit(), Finder, Builder);
}
@@ -2313,9 +2313,7 @@
/// namespace a { namespace b { class X; } }
/// \endcode
inline internal::Matcher<NamedDecl> hasName(const std::string &Name) {
- std::vector<std::string> Names;
- Names.push_back(Name);
- return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Names));
+ return internal::Matcher<NamedDecl>(new internal::HasNameMatcher({Name}));
}
/// \brief Matches NamedDecl nodes that have any of the specified names.
@@ -2711,7 +2709,7 @@
const QualType TypeDecl = Node.getReceiverType();
return InnerMatcher.matches(TypeDecl, Finder, Builder);
}
-
+
/// \brief Matches when BaseName == Selector.getAsString()
///
/// matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:"));
@@ -2725,7 +2723,21 @@
return BaseName.compare(Sel.getAsString()) == 0;
}
-
+
+/// \brief Matches when at least one of the supplied string equals to the
+/// Selector.getAsString()
+///
+/// matcher = objCMessageExpr(hasSelector("methodA:", "methodB:"));
+/// matches both of the expressions below:
+/// \code
+/// [myObj methodA:argA];
+/// [myObj methodB:argB];
+/// \endcode
+extern const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>,
+ StringRef,
+ internal::hasAnySelectorFunc>
+ hasAnySelector;
+
/// \brief Matches ObjC selectors whose name contains
/// a substring matched by the given RegExp.
/// matcher = objCMessageExpr(matchesSelector("loadHTMLString\:baseURL?"));
@@ -3412,7 +3424,7 @@
}
/// \brief Matches any argument of a call expression or a constructor call
-/// expression.
+/// expression, or an ObjC-message-send expression.
///
/// Given
/// \code
@@ -3422,9 +3434,18 @@
/// matches x(1, y, 42)
/// with hasAnyArgument(...)
/// matching y
+///
+/// For ObjectiveC, given
+/// \code
+/// @interface I - (void) f:(int) y; @end
+/// void foo(I *i) { [i f:12]; }
+/// \endcode
+/// objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
+/// matches [i f:12]
AST_POLYMORPHIC_MATCHER_P(hasAnyArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
- CXXConstructExpr),
+ CXXConstructExpr,
+ ObjCMessageExpr),
internal::Matcher<Expr>, InnerMatcher) {
for (const Expr *Arg : Node.arguments()) {
BoundNodesTreeBuilder Result(*Builder);
@@ -3457,7 +3478,8 @@
return Node.requiresZeroInitialization();
}
-/// \brief Matches the n'th parameter of a function declaration.
+/// \brief Matches the n'th parameter of a function or an ObjC method
+/// declaration.
///
/// Given
/// \code
@@ -3467,12 +3489,22 @@
/// matches f(int x) {}
/// with hasParameter(...)
/// matching int x
-AST_MATCHER_P2(FunctionDecl, hasParameter,
- unsigned, N, internal::Matcher<ParmVarDecl>,
- InnerMatcher) {
- return (N < Node.getNumParams() &&
- InnerMatcher.matches(
- *Node.getParamDecl(N), Finder, Builder));
+///
+/// For ObjectiveC, given
+/// \code
+/// @interface I - (void) f:(int) y; @end
+/// \endcode
+//
+/// the matcher objcMethodDecl(hasParameter(0, hasName("y")))
+/// matches the declaration of method f with hasParameter
+/// matching y.
+AST_POLYMORPHIC_MATCHER_P2(hasParameter,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
+ ObjCMethodDecl),
+ unsigned, N, internal::Matcher<ParmVarDecl>,
+ InnerMatcher) {
+ return (N < Node.parameters().size()
+ && InnerMatcher.matches(*Node.parameters()[N], Finder, Builder));
}
/// \brief Matches all arguments and their respective ParmVarDecl.
@@ -3529,7 +3561,7 @@
return Matched;
}
-/// \brief Matches any parameter of a function declaration.
+/// \brief Matches any parameter of a function or ObjC method declaration.
///
/// Does not match the 'this' parameter of a method.
///
@@ -3541,8 +3573,20 @@
/// matches f(int x, int y, int z) {}
/// with hasAnyParameter(...)
/// matching int y
-AST_MATCHER_P(FunctionDecl, hasAnyParameter,
- internal::Matcher<ParmVarDecl>, InnerMatcher) {
+///
+/// For ObjectiveC, given
+/// \code
+/// @interface I - (void) f:(int) y; @end
+/// \endcode
+//
+/// the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
+/// matches the declaration of method f with hasParameter
+/// matching y.
+AST_POLYMORPHIC_MATCHER_P(hasAnyParameter,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
+ ObjCMethodDecl),
+ internal::Matcher<ParmVarDecl>,
+ InnerMatcher) {
return matchesFirstInPointerRange(InnerMatcher, Node.param_begin(),
Node.param_end(), Finder, Builder);
}
@@ -3994,6 +4038,26 @@
return Name == Node.getOpcodeStr(Node.getOpcode());
}
+/// \brief Matches on all kinds of assignment operators.
+///
+/// Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
+/// \code
+/// if (a == b)
+/// a += b;
+/// \endcode
+///
+/// Example 2: matches s1 = s2
+/// (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
+/// \code
+/// struct S { S& operator=(const S&); };
+/// void x() { S s1, s2; s1 = s2; })
+/// \endcode
+AST_POLYMORPHIC_MATCHER(isAssignmentOperator,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
+ CXXOperatorCallExpr)) {
+ return Node.isAssignmentOp();
+}
+
/// \brief Matches the left hand side of binary operator expressions.
///
/// Example matches a (matcher = binaryOperator(hasLHS()))
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index 8bd61a7..8c1267b 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -731,6 +731,11 @@
/// HasNameMatcher.
Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs);
+/// \brief Trampoline function to use VariadicFunction<> to construct a
+/// hasAnySelector matcher.
+Matcher<ObjCMessageExpr> hasAnySelectorFunc(
+ ArrayRef<const StringRef *> NameRefs);
+
/// \brief Matches declarations for QualType and CallExpr.
///
/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
diff --git a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
index cc14c7b..da59514 100644
--- a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
+++ b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
@@ -1,4 +1,4 @@
-//==- CFGReachabilityAnalysis.h - Basic reachability analysis ----*- C++ -*-==//
+//===- CFGReachabilityAnalysis.h - Basic reachability analysis --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -30,10 +30,12 @@
// from the destination node and cache the results to prevent work
// duplication.
class CFGReverseBlockReachabilityAnalysis {
- typedef llvm::BitVector ReachableSet;
- typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap;
+ using ReachableSet = llvm::BitVector;
+ using ReachableMap = llvm::DenseMap<unsigned, ReachableSet>;
+
ReachableSet analyzed;
ReachableMap reachable;
+
public:
CFGReverseBlockReachabilityAnalysis(const CFG &cfg);
@@ -44,6 +46,6 @@
void mapReachability(const CFGBlock *Dst);
};
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H
diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h
index 5ba42b4..295d122 100644
--- a/include/clang/Analysis/Analyses/Consumed.h
+++ b/include/clang/Analysis/Analyses/Consumed.h
@@ -1,4 +1,4 @@
-//===- Consumed.h ----------------------------------------------*- C++ --*-===//
+//===- Consumed.h -----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,16 +15,32 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtCXX.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
-#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <list>
+#include <memory>
+#include <utility>
+#include <vector>
namespace clang {
+
+class AnalysisDeclContext;
+class CXXBindTemporaryExpr;
+class FunctionDecl;
+class PostOrderCFGView;
+class Stmt;
+class VarDecl;
+
namespace consumed {
+ class ConsumedStmtVisitor;
+
enum ConsumedState {
// No state information for the given variable.
CS_None,
@@ -34,16 +50,12 @@
CS_Consumed
};
- class ConsumedStmtVisitor;
-
- typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
- typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
- typedef std::list<DelayedDiag> DiagList;
+ using OptionalNotes = SmallVector<PartialDiagnosticAt, 1>;
+ using DelayedDiag = std::pair<PartialDiagnosticAt, OptionalNotes>;
+ using DiagList = std::list<DelayedDiag>;
class ConsumedWarningsHandlerBase {
-
public:
-
virtual ~ConsumedWarningsHandlerBase();
/// \brief Emit the warnings and notes left by the analysis.
@@ -129,23 +141,21 @@
};
class ConsumedStateMap {
-
- typedef llvm::DenseMap<const VarDecl *, ConsumedState> VarMapType;
- typedef llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState>
- TmpMapType;
+ using VarMapType = llvm::DenseMap<const VarDecl *, ConsumedState>;
+ using TmpMapType =
+ llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState>;
protected:
-
- bool Reachable;
- const Stmt *From;
+ bool Reachable = true;
+ const Stmt *From = nullptr;
VarMapType VarMap;
TmpMapType TmpMap;
public:
- ConsumedStateMap() : Reachable(true), From(nullptr) {}
+ ConsumedStateMap() = default;
ConsumedStateMap(const ConsumedStateMap &Other)
- : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap),
- TmpMap() {}
+ : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap),
+ TmpMap() {}
/// \brief Warn if any of the parameters being tracked are not in the state
/// they were declared to be in upon return from a function.
@@ -205,10 +215,8 @@
ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph)
: StateMapsArray(NumBlocks), VisitOrder(NumBlocks, 0) {
unsigned int VisitOrderCounter = 0;
- for (PostOrderCFGView::iterator BI = SortedGraph->begin(),
- BE = SortedGraph->end(); BI != BE; ++BI) {
- VisitOrder[(*BI)->getBlockID()] = VisitOrderCounter++;
- }
+ for (const auto BI : *SortedGraph)
+ VisitOrder[BI->getBlockID()] = VisitOrderCounter++;
}
bool allBackEdgesVisited(const CFGBlock *CurrBlock,
@@ -231,7 +239,6 @@
/// A class that handles the analysis of uniqueness violations.
class ConsumedAnalyzer {
-
ConsumedBlockInfo BlockInfo;
std::unique_ptr<ConsumedStateMap> CurrStates;
@@ -243,7 +250,6 @@
const ConsumedStmtVisitor &Visitor);
public:
-
ConsumedWarningsHandlerBase &WarningsHandler;
ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler)
@@ -259,6 +265,9 @@
/// exactly once.
void run(AnalysisDeclContext &AC);
};
-}} // end namespace clang::consumed
-#endif
+} // namespace consumed
+
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h
index 6cb161a..963bbd3 100644
--- a/include/clang/Analysis/Analyses/Dominators.h
+++ b/include/clang/Analysis/Analyses/Dominators.h
@@ -1,4 +1,4 @@
-//==- Dominators.h - Implementation of dominators tree for Clang CFG C++ -*-==//
+//- Dominators.h - Implementation of dominators tree for Clang CFG -*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
@@ -16,29 +16,35 @@
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/Support/GenericDomTree.h"
-#include "llvm/Support/GenericDomTreeConstruction.h"
+#include "llvm/Support/GenericDomTreeConstruction.h"
+#include "llvm/Support/raw_ostream.h"
// FIXME: There is no good reason for the domtree to require a print method
// which accepts an LLVM Module, so remove this (and the method's argument that
// needs it) when that is fixed.
+
namespace llvm {
+
class Module;
-}
+
+} // namespace llvm
namespace clang {
-class CFGBlock;
-typedef llvm::DomTreeNodeBase<CFGBlock> DomTreeNode;
+using DomTreeNode = llvm::DomTreeNodeBase<CFGBlock>;
/// \brief Concrete subclass of DominatorTreeBase for Clang
/// This class implements the dominators tree functionality given a Clang CFG.
///
class DominatorTree : public ManagedAnalysis {
virtual void anchor();
+
public:
- llvm::DomTreeBase<CFGBlock>* DT;
+ llvm::DomTreeBase<CFGBlock> *DT;
DominatorTree() {
DT = new llvm::DomTreeBase<CFGBlock>();
@@ -49,22 +55,20 @@
llvm::DomTreeBase<CFGBlock>& getBase() { return *DT; }
/// \brief This method returns the root CFGBlock of the dominators tree.
- ///
- inline CFGBlock *getRoot() const {
+ CFGBlock *getRoot() const {
return DT->getRoot();
}
/// \brief This method returns the root DomTreeNode, which is the wrapper
/// for CFGBlock.
- inline DomTreeNode *getRootNode() const {
+ DomTreeNode *getRootNode() const {
return DT->getRootNode();
}
/// \brief This method compares two dominator trees.
/// The method returns false if the other dominator tree matches this
/// dominator tree, otherwise returns true.
- ///
- inline bool compare(DominatorTree &Other) const {
+ bool compare(DominatorTree &Other) const {
DomTreeNode *R = getRootNode();
DomTreeNode *OtherR = Other.getRootNode();
@@ -79,7 +83,6 @@
/// \brief This method builds the dominator tree for a given CFG
/// The CFG information is passed via AnalysisDeclContext
- ///
void buildDominatorTree(AnalysisDeclContext &AC) {
cfg = AC.getCFG();
DT->recalculate(*cfg);
@@ -87,7 +90,6 @@
/// \brief This method dumps immediate dominators for each block,
/// mainly used for debug purposes.
- ///
void dump() {
llvm::errs() << "Immediate dominance tree (Node#,IDom#):\n";
for (CFG::const_iterator I = cfg->begin(),
@@ -105,52 +107,45 @@
/// \brief This method tests if one CFGBlock dominates the other.
/// The method return true if A dominates B, false otherwise.
/// Note a block always dominates itself.
- ///
- inline bool dominates(const CFGBlock* A, const CFGBlock* B) const {
+ bool dominates(const CFGBlock *A, const CFGBlock *B) const {
return DT->dominates(A, B);
}
/// \brief This method tests if one CFGBlock properly dominates the other.
/// The method return true if A properly dominates B, false otherwise.
- ///
- bool properlyDominates(const CFGBlock*A, const CFGBlock*B) const {
+ bool properlyDominates(const CFGBlock *A, const CFGBlock *B) const {
return DT->properlyDominates(A, B);
}
/// \brief This method finds the nearest common dominator CFG block
/// for CFG block A and B. If there is no such block then return NULL.
- ///
- inline CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) {
+ CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) {
return DT->findNearestCommonDominator(A, B);
}
- inline const CFGBlock *findNearestCommonDominator(const CFGBlock *A,
- const CFGBlock *B) {
+ const CFGBlock *findNearestCommonDominator(const CFGBlock *A,
+ const CFGBlock *B) {
return DT->findNearestCommonDominator(A, B);
}
/// \brief This method is used to update the dominator
/// tree information when a node's immediate dominator changes.
- ///
- inline void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) {
+ void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) {
DT->changeImmediateDominator(N, NewIDom);
}
/// \brief This method tests if the given CFGBlock can be reachable from root.
/// Returns true if reachable, false otherwise.
- ///
bool isReachableFromEntry(const CFGBlock *A) {
return DT->isReachableFromEntry(A);
}
/// \brief This method releases the memory held by the dominator tree.
- ///
virtual void releaseMemory() {
DT->releaseMemory();
}
/// \brief This method converts the dominator tree to human readable form.
- ///
virtual void print(raw_ostream &OS, const llvm::Module* M= nullptr) const {
DT->print(OS);
}
@@ -159,23 +154,24 @@
CFG *cfg;
};
-} // end namespace clang
+} // namespace clang
//===-------------------------------------
/// DominatorTree GraphTraits specialization so the DominatorTree can be
/// iterable by generic graph iterators.
///
namespace llvm {
+
template <> struct GraphTraits< ::clang::DomTreeNode* > {
- typedef ::clang::DomTreeNode *NodeRef;
- typedef ::clang::DomTreeNode::iterator ChildIteratorType;
+ using NodeRef = ::clang::DomTreeNode *;
+ using ChildIteratorType = ::clang::DomTreeNode::iterator;
static NodeRef getEntryNode(NodeRef N) { return N; }
static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
static ChildIteratorType child_end(NodeRef N) { return N->end(); }
- typedef llvm::pointer_iterator<df_iterator<::clang::DomTreeNode *>>
- nodes_iterator;
+ using nodes_iterator =
+ llvm::pointer_iterator<df_iterator<::clang::DomTreeNode *>>;
static nodes_iterator nodes_begin(::clang::DomTreeNode *N) {
return nodes_iterator(df_begin(getEntryNode(N)));
@@ -187,7 +183,7 @@
};
template <> struct GraphTraits< ::clang::DominatorTree* >
- : public GraphTraits< ::clang::DomTreeNode* > {
+ : public GraphTraits< ::clang::DomTreeNode* > {
static NodeRef getEntryNode(::clang::DominatorTree *DT) {
return DT->getRootNode();
}
@@ -200,6 +196,7 @@
return nodes_iterator(df_end(getEntryNode(N)));
}
};
-} // end namespace llvm
-#endif
+} // namespace llvm
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H
diff --git a/include/clang/Analysis/Analyses/PostOrderCFGView.h b/include/clang/Analysis/Analyses/PostOrderCFGView.h
index c0a9352..e76f3d4 100644
--- a/include/clang/Analysis/Analyses/PostOrderCFGView.h
+++ b/include/clang/Analysis/Analyses/PostOrderCFGView.h
@@ -1,4 +1,4 @@
-//===- PostOrderCFGView.h - Post order view of CFG blocks ---------*- C++ --*-//
+//===- PostOrderCFGView.h - Post order view of CFG blocks -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,20 +14,21 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
-#include <vector>
-//#include <algorithm>
-
-#include "llvm/ADT/PostOrderIterator.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/BitVector.h"
-
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/PostOrderIterator.h"
+#include <utility>
+#include <vector>
namespace clang {
class PostOrderCFGView : public ManagedAnalysis {
virtual void anchor();
+
public:
/// \brief Implements a set of CFGBlocks using a BitVector.
///
@@ -37,12 +38,13 @@
/// visit during the analysis.
class CFGBlockSet {
llvm::BitVector VisitedBlockIDs;
+
public:
// po_iterator requires this iterator, but the only interface needed is the
- // value_type typedef.
- struct iterator { typedef const CFGBlock *value_type; };
+ // value_type type.
+ struct iterator { using value_type = const CFGBlock *; };
- CFGBlockSet() {}
+ CFGBlockSet() = default;
CFGBlockSet(const CFG *G) : VisitedBlockIDs(G->getNumBlockIDs(), false) {}
/// \brief Set the bit associated with a particular CFGBlock.
@@ -69,33 +71,34 @@
};
private:
- typedef llvm::po_iterator<const CFG*, CFGBlockSet, true> po_iterator;
- std::vector<const CFGBlock*> Blocks;
+ using po_iterator = llvm::po_iterator<const CFG *, CFGBlockSet, true>;
+ std::vector<const CFGBlock *> Blocks;
- typedef llvm::DenseMap<const CFGBlock *, unsigned> BlockOrderTy;
+ using BlockOrderTy = llvm::DenseMap<const CFGBlock *, unsigned>;
BlockOrderTy BlockOrder;
public:
- typedef std::vector<const CFGBlock *>::reverse_iterator iterator;
- typedef std::vector<const CFGBlock *>::const_reverse_iterator const_iterator;
+ friend struct BlockOrderCompare;
+
+ using iterator = std::vector<const CFGBlock *>::reverse_iterator;
+ using const_iterator = std::vector<const CFGBlock *>::const_reverse_iterator;
PostOrderCFGView(const CFG *cfg);
iterator begin() { return Blocks.rbegin(); }
- iterator end() { return Blocks.rend(); }
+ iterator end() { return Blocks.rend(); }
const_iterator begin() const { return Blocks.rbegin(); }
const_iterator end() const { return Blocks.rend(); }
bool empty() const { return begin() == end(); }
- struct BlockOrderCompare;
- friend struct BlockOrderCompare;
-
struct BlockOrderCompare {
const PostOrderCFGView &POV;
+
public:
BlockOrderCompare(const PostOrderCFGView &pov) : POV(pov) {}
+
bool operator()(const CFGBlock *b1, const CFGBlock *b2) const;
};
@@ -109,7 +112,6 @@
static PostOrderCFGView *create(AnalysisDeclContext &analysisContext);
};
-} // end clang namespace
+} // namespace clang
-#endif
-
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h
index 7e403b1..940f3ac 100644
--- a/include/clang/Analysis/Analyses/ThreadSafety.h
+++ b/include/clang/Analysis/Analyses/ThreadSafety.h
@@ -1,4 +1,4 @@
-//===- ThreadSafety.h ------------------------------------------*- C++ --*-===//
+//===- ThreadSafety.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,11 +19,15 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
-#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/StringRef.h"
namespace clang {
+
+class AnalysisDeclContext;
+class FunctionDecl;
+class NamedDecl;
+
namespace threadSafety {
class BeforeSet;
@@ -31,27 +35,44 @@
/// This enum distinguishes between different kinds of operations that may
/// need to be protected by locks. We use this enum in error handling.
enum ProtectedOperationKind {
- POK_VarDereference, ///< Dereferencing a variable (e.g. p in *p = 5;)
- POK_VarAccess, ///< Reading or writing a variable (e.g. x in x = 5;)
- POK_FunctionCall, ///< Making a function call (e.g. fool())
- POK_PassByRef, ///< Passing a guarded variable by reference.
- POK_PtPassByRef, ///< Passing a pt-guarded variable by reference.
+ /// Dereferencing a variable (e.g. p in *p = 5;)
+ POK_VarDereference,
+
+ /// Reading or writing a variable (e.g. x in x = 5;)
+ POK_VarAccess,
+
+ /// Making a function call (e.g. fool())
+ POK_FunctionCall,
+
+ /// Passing a guarded variable by reference.
+ POK_PassByRef,
+
+ /// Passing a pt-guarded variable by reference.
+ POK_PtPassByRef
};
/// This enum distinguishes between different kinds of lock actions. For
/// example, it is an error to write a variable protected by shared version of a
/// mutex.
enum LockKind {
- LK_Shared, ///< Shared/reader lock of a mutex.
- LK_Exclusive, ///< Exclusive/writer lock of a mutex.
- LK_Generic ///< Can be either Shared or Exclusive
+ /// Shared/reader lock of a mutex.
+ LK_Shared,
+
+ /// Exclusive/writer lock of a mutex.
+ LK_Exclusive,
+
+ /// Can be either Shared or Exclusive.
+ LK_Generic
};
/// This enum distinguishes between different ways to access (read or write) a
/// variable.
enum AccessKind {
- AK_Read, ///< Reading a variable.
- AK_Written ///< Writing a variable.
+ /// Reading a variable.
+ AK_Read,
+
+ /// Writing a variable.
+ AK_Written
};
/// This enum distinguishes between different situations where we warn due to
@@ -72,8 +93,9 @@
/// Handler class for thread safety warnings.
class ThreadSafetyHandler {
public:
- typedef StringRef Name;
- ThreadSafetyHandler() : IssueBetaWarnings(false) { }
+ using Name = StringRef;
+
+ ThreadSafetyHandler() = default;
virtual ~ThreadSafetyHandler();
/// Warn about lock expressions which fail to resolve to lockable objects.
@@ -185,7 +207,6 @@
virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
Name LockName, SourceLocation Loc) {}
-
/// Warn that L1 cannot be acquired before L2.
virtual void handleLockAcquiredBefore(StringRef Kind, Name L1Name,
Name L2Name, SourceLocation Loc) {}
@@ -204,7 +225,7 @@
void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; }
private:
- bool IssueBetaWarnings;
+ bool IssueBetaWarnings = false;
};
/// \brief Check a function's CFG for thread-safety violations.
@@ -222,5 +243,7 @@
/// of access.
LockKind getLockKindFromAccessKind(AccessKind AK);
-}} // end namespace clang::threadSafety
-#endif
+} // namespace threadSafety
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
index 414645b..d8677ba 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -1,4 +1,4 @@
-//===- ThreadSafetyCommon.h ------------------------------------*- C++ --*-===//
+//===- ThreadSafetyCommon.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -22,20 +22,41 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
+#include "clang/AST/Decl.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
+#include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
#include "clang/Analysis/AnalysisDeclContext.h"
-#include "clang/Basic/OperatorKinds.h"
-#include <memory>
-#include <ostream>
+#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
#include <sstream>
+#include <string>
+#include <utility>
#include <vector>
-
namespace clang {
-namespace threadSafety {
+class AbstractConditionalOperator;
+class ArraySubscriptExpr;
+class BinaryOperator;
+class CallExpr;
+class CastExpr;
+class CXXDestructorDecl;
+class CXXMemberCallExpr;
+class CXXOperatorCallExpr;
+class CXXThisExpr;
+class DeclRefExpr;
+class DeclStmt;
+class Expr;
+class MemberExpr;
+class Stmt;
+class UnaryOperator;
+
+namespace threadSafety {
// Various helper functions on til::SExpr
namespace sx {
@@ -72,9 +93,7 @@
return ss.str();
}
-} // end namespace sx
-
-
+} // namespace sx
// This class defines the interface of a clang CFG Visitor.
// CFGWalker will invoke the following methods.
@@ -123,11 +142,10 @@
void exitCFG(const CFGBlock *Last) {}
};
-
// Walks the clang CFG, and invokes methods on a given CFGVisitor.
class CFGWalker {
public:
- CFGWalker() : CFGraph(nullptr), ACtx(nullptr), SortedGraph(nullptr) {}
+ CFGWalker() = default;
// Initialize the CFGWalker. This setup only needs to be done once, even
// if there are multiple passes over the CFG.
@@ -186,15 +204,15 @@
// Process statements
for (const auto &BI : *CurrBlock) {
switch (BI.getKind()) {
- case CFGElement::Statement: {
+ case CFGElement::Statement:
V.handleStatement(BI.castAs<CFGStmt>().getStmt());
break;
- }
+
case CFGElement::AutomaticObjectDtor: {
CFGAutomaticObjDtor AD = BI.castAs<CFGAutomaticObjDtor>();
- CXXDestructorDecl *DD = const_cast<CXXDestructorDecl*>(
+ auto *DD = const_cast<CXXDestructorDecl *>(
AD.getDestructorDecl(ACtx->getASTContext()));
- VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl());
+ auto *VD = const_cast<VarDecl *>(AD.getVarDecl());
V.handleDestructorCall(VD, DD);
break;
}
@@ -242,28 +260,27 @@
const PostOrderCFGView *getSortedGraph() const { return SortedGraph; }
private:
- CFG *CFGraph;
- AnalysisDeclContext *ACtx;
- PostOrderCFGView *SortedGraph;
+ CFG *CFGraph = nullptr;
+ AnalysisDeclContext *ACtx = nullptr;
+ PostOrderCFGView *SortedGraph = nullptr;
};
-
-
-
+// TODO: move this back into ThreadSafety.cpp
+// This is specific to thread safety. It is here because
+// translateAttrExpr needs it, but that should be moved too.
class CapabilityExpr {
- // TODO: move this back into ThreadSafety.cpp
- // This is specific to thread safety. It is here because
- // translateAttrExpr needs it, but that should be moved too.
-
private:
- const til::SExpr* CapExpr; ///< The capability expression.
- bool Negated; ///< True if this is a negative capability
+ /// The capability expression.
+ const til::SExpr* CapExpr;
+
+ /// True if this is a negative capability.
+ bool Negated;
public:
CapabilityExpr(const til::SExpr *E, bool Neg) : CapExpr(E), Negated(Neg) {}
- const til::SExpr* sexpr() const { return CapExpr; }
- bool negative() const { return Negated; }
+ const til::SExpr* sexpr() const { return CapExpr; }
+ bool negative() const { return Negated; }
CapabilityExpr operator!() const {
return CapabilityExpr(CapExpr, !Negated);
@@ -289,9 +306,9 @@
const ValueDecl* valueDecl() const {
if (Negated || CapExpr == nullptr)
return nullptr;
- if (auto *P = dyn_cast<til::Project>(CapExpr))
+ if (const auto *P = dyn_cast<til::Project>(CapExpr))
return P->clangDecl();
- if (auto *P = dyn_cast<til::LiteralPtr>(CapExpr))
+ if (const auto *P = dyn_cast<til::LiteralPtr>(CapExpr))
return P->clangDecl();
return nullptr;
}
@@ -309,8 +326,6 @@
bool isUniversal() const { return sexpr() && isa<til::Wildcard>(sexpr()); }
};
-
-
// Translate clang::Expr to til::SExpr.
class SExprBuilder {
public:
@@ -324,22 +339,29 @@
/// should be evaluated; multiple calling contexts can be chained together
/// by the lock_returned attribute.
struct CallingContext {
- CallingContext *Prev; // The previous context; or 0 if none.
- const NamedDecl *AttrDecl; // The decl to which the attr is attached.
- const Expr *SelfArg; // Implicit object argument -- e.g. 'this'
- unsigned NumArgs; // Number of funArgs
- const Expr *const *FunArgs; // Function arguments
- bool SelfArrow; // is Self referred to with -> or .?
+ // The previous context; or 0 if none.
+ CallingContext *Prev;
+
+ // The decl to which the attr is attached.
+ const NamedDecl *AttrDecl;
+
+ // Implicit object argument -- e.g. 'this'
+ const Expr *SelfArg = nullptr;
+
+ // Number of funArgs
+ unsigned NumArgs = 0;
+
+ // Function arguments
+ const Expr *const *FunArgs = nullptr;
+
+ // is Self referred to with -> or .?
+ bool SelfArrow = false;
CallingContext(CallingContext *P, const NamedDecl *D = nullptr)
- : Prev(P), AttrDecl(D), SelfArg(nullptr),
- NumArgs(0), FunArgs(nullptr), SelfArrow(false)
- {}
+ : Prev(P), AttrDecl(D) {}
};
- SExprBuilder(til::MemRegionRef A)
- : Arena(A), SelfVar(nullptr), Scfg(nullptr), CurrentBB(nullptr),
- CurrentBlockInfo(nullptr) {
+ SExprBuilder(til::MemRegionRef A) : Arena(A) {
// FIXME: we don't always have a self-variable.
SelfVar = new (Arena) til::Variable(nullptr);
SelfVar->setKind(til::Variable::VK_SFun);
@@ -368,6 +390,9 @@
til::SCFG *getCFG() { return Scfg; }
private:
+ // We implement the CFGVisitor API
+ friend class CFGWalker;
+
til::SExpr *translateDeclRefExpr(const DeclRefExpr *DRE,
CallingContext *Ctx) ;
til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx);
@@ -397,31 +422,30 @@
til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx);
// Map from statements in the clang CFG to SExprs in the til::SCFG.
- typedef llvm::DenseMap<const Stmt*, til::SExpr*> StatementMap;
+ using StatementMap = llvm::DenseMap<const Stmt *, til::SExpr *>;
// Map from clang local variables to indices in a LVarDefinitionMap.
- typedef llvm::DenseMap<const ValueDecl *, unsigned> LVarIndexMap;
+ using LVarIndexMap = llvm::DenseMap<const ValueDecl *, unsigned>;
// Map from local variable indices to SSA variables (or constants).
- typedef std::pair<const ValueDecl *, til::SExpr *> NameVarPair;
- typedef CopyOnWriteVector<NameVarPair> LVarDefinitionMap;
+ using NameVarPair = std::pair<const ValueDecl *, til::SExpr *>;
+ using LVarDefinitionMap = CopyOnWriteVector<NameVarPair>;
struct BlockInfo {
LVarDefinitionMap ExitMap;
- bool HasBackEdges;
- unsigned UnprocessedSuccessors; // Successors yet to be processed
- unsigned ProcessedPredecessors; // Predecessors already processed
+ bool HasBackEdges = false;
- BlockInfo()
- : HasBackEdges(false), UnprocessedSuccessors(0),
- ProcessedPredecessors(0) {}
+ // Successors yet to be processed
+ unsigned UnprocessedSuccessors = 0;
+
+ // Predecessors already processed
+ unsigned ProcessedPredecessors = 0;
+
+ BlockInfo() = default;
BlockInfo(BlockInfo &&) = default;
BlockInfo &operator=(BlockInfo &&) = default;
};
- // We implement the CFGVisitor API
- friend class CFGWalker;
-
void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First);
void enterCFGBlock(const CFGBlock *B);
bool visitPredecessors() { return true; }
@@ -440,6 +464,7 @@
void insertStmt(const Stmt *S, til::SExpr *E) {
SMap.insert(std::make_pair(S, E));
}
+
til::SExpr *getCurrentLVarDefinition(const ValueDecl *VD);
til::SExpr *addStatement(til::SExpr *E, const Stmt *S,
@@ -459,30 +484,36 @@
static const bool CapabilityExprMode = true;
til::MemRegionRef Arena;
- til::Variable *SelfVar; // Variable to use for 'this'. May be null.
- til::SCFG *Scfg;
- StatementMap SMap; // Map from Stmt to TIL Variables
- LVarIndexMap LVarIdxMap; // Indices of clang local vars.
- std::vector<til::BasicBlock *> BlockMap; // Map from clang to til BBs.
- std::vector<BlockInfo> BBInfo; // Extra information per BB.
- // Indexed by clang BlockID.
+ // Variable to use for 'this'. May be null.
+ til::Variable *SelfVar = nullptr;
+
+ til::SCFG *Scfg = nullptr;
+
+ // Map from Stmt to TIL Variables
+ StatementMap SMap;
+
+ // Indices of clang local vars.
+ LVarIndexMap LVarIdxMap;
+
+ // Map from clang to til BBs.
+ std::vector<til::BasicBlock *> BlockMap;
+
+ // Extra information per BB. Indexed by clang BlockID.
+ std::vector<BlockInfo> BBInfo;
LVarDefinitionMap CurrentLVarMap;
- std::vector<til::Phi*> CurrentArguments;
- std::vector<til::SExpr*> CurrentInstructions;
- std::vector<til::Phi*> IncompleteArgs;
- til::BasicBlock *CurrentBB;
- BlockInfo *CurrentBlockInfo;
+ std::vector<til::Phi *> CurrentArguments;
+ std::vector<til::SExpr *> CurrentInstructions;
+ std::vector<til::Phi *> IncompleteArgs;
+ til::BasicBlock *CurrentBB = nullptr;
+ BlockInfo *CurrentBlockInfo = nullptr;
};
-
// Dump an SCFG to llvm::errs().
void printSCFG(CFGWalker &Walker);
+} // namespace threadSafety
+} // namespace clang
-} // end namespace threadSafety
-
-} // end namespace clang
-
-#endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H
+#endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
index 0a58d2a..810f205 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
@@ -1,4 +1,4 @@
-//===- ThreadSafetyTIL.h ---------------------------------------*- C++ --*-===//
+//===- ThreadSafetyTIL.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -47,20 +47,33 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
-// All clang include dependencies for this file must be put in
-// ThreadSafetyUtil.h.
-#include "ThreadSafetyUtil.h"
+#include "clang/AST/Decl.h"
+#include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
-#include <stdint.h>
+#include <cstdint>
+#include <iterator>
+#include <string>
#include <utility>
-
namespace clang {
+
+class CallExpr;
+class Expr;
+class Stmt;
+
namespace threadSafety {
namespace til {
+class BasicBlock;
/// Enum for the different distinct classes of SExpr
enum TIL_Opcode {
@@ -100,11 +113,21 @@
/// Opcode for cast operations.
enum TIL_CastOpcode : unsigned char {
CAST_none = 0,
- CAST_extendNum, // extend precision of numeric type
- CAST_truncNum, // truncate precision of numeric type
- CAST_toFloat, // convert to floating point type
- CAST_toInt, // convert to integer type
- CAST_objToPtr // convert smart pointer to pointer (C++ only)
+
+ // Extend precision of numeric type
+ CAST_extendNum,
+
+ // Truncate precision of numeric type
+ CAST_truncNum,
+
+ // Convert to floating point type
+ CAST_toFloat,
+
+ // Convert to integer type
+ CAST_toInt,
+
+ // Convert smart pointer to pointer (C++ only)
+ CAST_objToPtr
};
const TIL_Opcode COP_Min = COP_Future;
@@ -122,7 +145,6 @@
/// Return the name of a binary opcode.
StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op);
-
/// ValueTypes are data types that can actually be held in registers.
/// All variables and expressions must have a value type.
/// Pointer types are further subdivided into the various heap-allocated
@@ -150,22 +172,22 @@
ST_128
};
+ ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS)
+ : Base(B), Size(Sz), Signed(S), VectSize(VS) {}
+
inline static SizeType getSizeType(unsigned nbytes);
template <class T>
inline static ValueType getValueType();
- ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS)
- : Base(B), Size(Sz), Signed(S), VectSize(VS)
- { }
+ BaseType Base;
+ SizeType Size;
+ bool Signed;
- BaseType Base;
- SizeType Size;
- bool Signed;
- unsigned char VectSize; // 0 for scalar, otherwise num elements in vector
+ // 0 for scalar, otherwise num elements in vector
+ unsigned char VectSize;
};
-
inline ValueType::SizeType ValueType::getSizeType(unsigned nbytes) {
switch (nbytes) {
case 1: return ST_8;
@@ -177,7 +199,6 @@
}
}
-
template<>
inline ValueType ValueType::getValueType<void>() {
return ValueType(BT_Void, ST_0, false, 0);
@@ -253,13 +274,11 @@
return ValueType(BT_Pointer, getSizeType(sizeof(void*)), false, 0);
}
-
-class BasicBlock;
-
-
/// Base class for AST nodes in the typed intermediate language.
class SExpr {
public:
+ SExpr() = delete;
+
TIL_Opcode opcode() const { return static_cast<TIL_Opcode>(Opcode); }
// Subclasses of SExpr must define the following:
@@ -280,6 +299,9 @@
return ::operator new(S, R);
}
+ /// SExpr objects must be created in an arena.
+ void *operator new(size_t) = delete;
+
/// SExpr objects cannot be deleted.
// This declaration is public to workaround a gcc bug that breaks building
// with REQUIRES_EH=1.
@@ -291,45 +313,33 @@
/// Returns the block, if this is an instruction in a basic block,
/// otherwise returns null.
- BasicBlock* block() const { return Block; }
+ BasicBlock *block() const { return Block; }
/// Set the basic block and instruction ID for this expression.
void setID(BasicBlock *B, unsigned id) { Block = B; SExprID = id; }
protected:
- SExpr(TIL_Opcode Op)
- : Opcode(Op), Reserved(0), Flags(0), SExprID(0), Block(nullptr) {}
- SExpr(const SExpr &E)
- : Opcode(E.Opcode), Reserved(0), Flags(E.Flags), SExprID(0),
- Block(nullptr) {}
+ SExpr(TIL_Opcode Op) : Opcode(Op) {}
+ SExpr(const SExpr &E) : Opcode(E.Opcode), Flags(E.Flags) {}
const unsigned char Opcode;
- unsigned char Reserved;
- unsigned short Flags;
- unsigned SExprID;
- BasicBlock* Block;
-
-private:
- SExpr() = delete;
-
- /// SExpr objects must be created in an arena.
- void *operator new(size_t) = delete;
+ unsigned char Reserved = 0;
+ unsigned short Flags = 0;
+ unsigned SExprID = 0;
+ BasicBlock *Block = nullptr;
};
-
// Contains various helper functions for SExprs.
namespace ThreadSafetyTIL {
- inline bool isTrivial(const SExpr *E) {
- unsigned Op = E->opcode();
- return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
- }
+
+inline bool isTrivial(const SExpr *E) {
+ unsigned Op = E->opcode();
+ return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
}
-// Nodes which declare variables
-class Function;
-class SFunction;
-class Let;
+} // namespace ThreadSafetyTIL
+// Nodes which declare variables
/// A named variable, e.g. "x".
///
@@ -345,28 +355,35 @@
/// pointer to the original declaration.
class Variable : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
-
enum VariableKind {
- VK_Let, ///< Let-variable
- VK_Fun, ///< Function parameter
- VK_SFun ///< SFunction (self) parameter
+ /// Let-variable
+ VK_Let,
+
+ /// Function parameter
+ VK_Fun,
+
+ /// SFunction (self) parameter
+ VK_SFun
};
Variable(StringRef s, SExpr *D = nullptr)
- : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr) {
+ : SExpr(COP_Variable), Name(s), Definition(D) {
Flags = VK_Let;
}
- Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr)
+
+ Variable(SExpr *D, const ValueDecl *Cvd = nullptr)
: SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"),
Definition(D), Cvdecl(Cvd) {
Flags = VK_Let;
}
+
Variable(const Variable &Vd, SExpr *D) // rewrite constructor
: SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
Flags = Vd.kind();
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
+
/// Return the kind of variable (let, function param, or self)
VariableKind kind() const { return static_cast<VariableKind>(Flags); }
@@ -374,7 +391,7 @@
StringRef name() const { return Name; }
/// Return the clang declaration for this variable, if any.
- const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+ const ValueDecl *clangDecl() const { return Cvdecl; }
/// Return the definition of the variable.
/// For let-vars, this is the setting expression.
@@ -385,7 +402,7 @@
void setName(StringRef S) { Name = S; }
void setKind(VariableKind K) { Flags = K; }
void setDefinition(SExpr *E) { Definition = E; }
- void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; }
+ void setClangDecl(const ValueDecl *VD) { Cvdecl = VD; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -399,42 +416,41 @@
}
private:
- friend class Function;
- friend class SFunction;
friend class BasicBlock;
+ friend class Function;
friend class Let;
+ friend class SFunction;
- StringRef Name; // The name of the variable.
- SExpr* Definition; // The TIL type or definition
- const clang::ValueDecl *Cvdecl; // The clang declaration for this variable.
+ // The name of the variable.
+ StringRef Name;
+
+ // The TIL type or definition.
+ SExpr *Definition;
+
+ // The clang declaration for this variable.
+ const ValueDecl *Cvdecl = nullptr;
};
-
/// Placeholder for an expression that has not yet been created.
/// Used to implement lazy copy and rewriting strategies.
class Future : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Future; }
-
enum FutureStatus {
FS_pending,
FS_evaluating,
FS_done
};
- Future() : SExpr(COP_Future), Status(FS_pending), Result(nullptr) {}
-
-private:
+ Future() : SExpr(COP_Future) {}
virtual ~Future() = delete;
-public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Future; }
+
// A lazy rewriting strategy should subclass Future and override this method.
virtual SExpr *compute() { return nullptr; }
// Return the result of this future if it exists, otherwise return null.
- SExpr *maybeGetResult() const {
- return Result;
- }
+ SExpr *maybeGetResult() const { return Result; }
// Return the result of this future; forcing it if necessary.
SExpr *result() {
@@ -464,19 +480,18 @@
private:
SExpr* force();
- FutureStatus Status;
- SExpr *Result;
+ FutureStatus Status = FS_pending;
+ SExpr *Result = nullptr;
};
-
/// Placeholder for expressions that cannot be represented in the TIL.
class Undefined : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
-
- Undefined(const clang::Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {}
+ Undefined(const Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {}
Undefined(const Undefined &U) : SExpr(U), Cstmt(U.Cstmt) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
+
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
return Vs.reduceUndefined(*this);
@@ -488,17 +503,16 @@
}
private:
- const clang::Stmt *Cstmt;
+ const Stmt *Cstmt;
};
-
/// Placeholder for a wildcard that matches any other expression.
class Wildcard : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; }
-
Wildcard() : SExpr(COP_Wildcard) {}
- Wildcard(const Wildcard &W) : SExpr(W) {}
+ Wildcard(const Wildcard &) = default;
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; }
template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
return Vs.reduceWildcard(*this);
@@ -510,22 +524,20 @@
}
};
-
template <class T> class LiteralT;
// Base class for literal values.
class Literal : public SExpr {
public:
+ Literal(const Expr *C)
+ : SExpr(COP_Literal), ValType(ValueType::getValueType<void>()), Cexpr(C) {}
+ Literal(ValueType VT) : SExpr(COP_Literal), ValType(VT) {}
+ Literal(const Literal &) = default;
+
static bool classof(const SExpr *E) { return E->opcode() == COP_Literal; }
- Literal(const clang::Expr *C)
- : SExpr(COP_Literal), ValType(ValueType::getValueType<void>()), Cexpr(C)
- { }
- Literal(ValueType VT) : SExpr(COP_Literal), ValType(VT), Cexpr(nullptr) {}
- Literal(const Literal &L) : SExpr(L), ValType(L.ValType), Cexpr(L.Cexpr) {}
-
// The clang expression for this literal.
- const clang::Expr *clangExpr() const { return Cexpr; }
+ const Expr *clangExpr() const { return Cexpr; }
ValueType valueType() const { return ValType; }
@@ -546,26 +558,23 @@
private:
const ValueType ValType;
- const clang::Expr *Cexpr;
+ const Expr *Cexpr = nullptr;
};
-
// Derived class for literal values, which stores the actual value.
template<class T>
class LiteralT : public Literal {
public:
- LiteralT(T Dat) : Literal(ValueType::getValueType<T>()), Val(Dat) { }
- LiteralT(const LiteralT<T> &L) : Literal(L), Val(L.Val) { }
+ LiteralT(T Dat) : Literal(ValueType::getValueType<T>()), Val(Dat) {}
+ LiteralT(const LiteralT<T> &L) : Literal(L), Val(L.Val) {}
- T value() const { return Val;}
+ T value() const { return Val;}
T& value() { return Val; }
private:
T Val;
};
-
-
template <class V>
typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) {
if (Cexpr)
@@ -622,18 +631,17 @@
return Vs.reduceLiteral(*this);
}
-
/// A Literal pointer to an object allocated in memory.
/// At compile time, pointer literals are represented by symbolic names.
class LiteralPtr : public SExpr {
public:
+ LiteralPtr(const ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {}
+ LiteralPtr(const LiteralPtr &) = default;
+
static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
- LiteralPtr(const clang::ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {}
- LiteralPtr(const LiteralPtr &R) : SExpr(R), Cvdecl(R.Cvdecl) {}
-
// The clang declaration for the value that this pointer points to.
- const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+ const ValueDecl *clangDecl() const { return Cvdecl; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -646,26 +654,26 @@
}
private:
- const clang::ValueDecl *Cvdecl;
+ const ValueDecl *Cvdecl;
};
-
/// A function -- a.k.a. lambda abstraction.
/// Functions with multiple arguments are created by currying,
/// e.g. (Function (x: Int) (Function (y: Int) (Code { return x + y })))
class Function : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Function; }
-
Function(Variable *Vd, SExpr *Bd)
: SExpr(COP_Function), VarDecl(Vd), Body(Bd) {
Vd->setKind(Variable::VK_Fun);
}
+
Function(const Function &F, Variable *Vd, SExpr *Bd) // rewrite constructor
: SExpr(F), VarDecl(Vd), Body(Bd) {
Vd->setKind(Variable::VK_Fun);
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Function; }
+
Variable *variableDecl() { return VarDecl; }
const Variable *variableDecl() const { return VarDecl; }
@@ -700,20 +708,18 @@
SExpr* Body;
};
-
/// A self-applicable function.
/// A self-applicable function can be applied to itself. It's useful for
/// implementing objects and late binding.
class SFunction : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; }
-
SFunction(Variable *Vd, SExpr *B)
: SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
assert(Vd->Definition == nullptr);
Vd->setKind(Variable::VK_SFun);
Vd->Definition = this;
}
+
SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor
: SExpr(F), VarDecl(Vd), Body(B) {
assert(Vd->Definition == nullptr);
@@ -721,6 +727,8 @@
Vd->Definition = this;
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; }
+
Variable *variableDecl() { return VarDecl; }
const Variable *variableDecl() const { return VarDecl; }
@@ -752,16 +760,15 @@
SExpr* Body;
};
-
/// A block of code -- e.g. the body of a function.
class Code : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Code; }
-
Code(SExpr *T, SExpr *B) : SExpr(COP_Code), ReturnType(T), Body(B) {}
Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor
: SExpr(C), ReturnType(T), Body(B) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Code; }
+
SExpr *returnType() { return ReturnType; }
const SExpr *returnType() const { return ReturnType; }
@@ -788,16 +795,15 @@
SExpr* Body;
};
-
/// A typed, writable location in memory
class Field : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Field; }
-
Field(SExpr *R, SExpr *B) : SExpr(COP_Field), Range(R), Body(B) {}
Field(const Field &C, SExpr *R, SExpr *B) // rewrite constructor
: SExpr(C), Range(R), Body(B) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Field; }
+
SExpr *range() { return Range; }
const SExpr *range() const { return Range; }
@@ -824,7 +830,6 @@
SExpr* Body;
};
-
/// Apply an argument to a function.
/// Note that this does not actually call the function. Functions are curried,
/// so this returns a closure in which the first parameter has been applied.
@@ -832,12 +837,11 @@
/// function.
class Apply : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; }
-
Apply(SExpr *F, SExpr *A) : SExpr(COP_Apply), Fun(F), Arg(A) {}
Apply(const Apply &A, SExpr *F, SExpr *Ar) // rewrite constructor
- : SExpr(A), Fun(F), Arg(Ar)
- {}
+ : SExpr(A), Fun(F), Arg(Ar) {}
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; }
SExpr *fun() { return Fun; }
const SExpr *fun() const { return Fun; }
@@ -865,16 +869,15 @@
SExpr* Arg;
};
-
/// Apply a self-argument to a self-applicable function.
class SApply : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; }
-
SApply(SExpr *Sf, SExpr *A = nullptr) : SExpr(COP_SApply), Sfun(Sf), Arg(A) {}
SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr) // rewrite constructor
: SExpr(A), Sfun(Sf), Arg(Ar) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; }
+
SExpr *sfun() { return Sfun; }
const SExpr *sfun() const { return Sfun; }
@@ -904,23 +907,23 @@
SExpr* Arg;
};
-
/// Project a named slot from a C++ struct or class.
class Project : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Project; }
-
- Project(SExpr *R, const clang::ValueDecl *Cvd)
+ Project(SExpr *R, const ValueDecl *Cvd)
: SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {
assert(Cvd && "ValueDecl must not be null");
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Project; }
+
SExpr *record() { return Rec; }
const SExpr *record() const { return Rec; }
- const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+ const ValueDecl *clangDecl() const { return Cvdecl; }
bool isArrow() const { return (Flags & 0x01) != 0; }
+
void setArrow(bool b) {
if (b) Flags |= 0x01;
else Flags &= 0xFFFE;
@@ -954,23 +957,22 @@
private:
SExpr* Rec;
mutable llvm::Optional<std::string> SlotName;
- const clang::ValueDecl *Cvdecl;
+ const ValueDecl *Cvdecl;
};
-
/// Call a function (after all arguments have been applied).
class Call : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
-
- Call(SExpr *T, const clang::CallExpr *Ce = nullptr)
+ Call(SExpr *T, const CallExpr *Ce = nullptr)
: SExpr(COP_Call), Target(T), Cexpr(Ce) {}
Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
+
SExpr *target() { return Target; }
const SExpr *target() const { return Target; }
- const clang::CallExpr *clangCallExpr() const { return Cexpr; }
+ const CallExpr *clangCallExpr() const { return Cexpr; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -985,15 +987,12 @@
private:
SExpr* Target;
- const clang::CallExpr *Cexpr;
+ const CallExpr *Cexpr;
};
-
/// Allocate memory for a new value on the heap or stack.
class Alloc : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
-
enum AllocKind {
AK_Stack,
AK_Heap
@@ -1002,6 +1001,8 @@
Alloc(SExpr *D, AllocKind K) : SExpr(COP_Alloc), Dtype(D) { Flags = K; }
Alloc(const Alloc &A, SExpr *Dt) : SExpr(A), Dtype(Dt) { Flags = A.kind(); }
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
+
AllocKind kind() const { return static_cast<AllocKind>(Flags); }
SExpr *dataType() { return Dtype; }
@@ -1025,15 +1026,14 @@
SExpr* Dtype;
};
-
/// Load a value from memory.
class Load : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Load; }
-
Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {}
Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Load; }
+
SExpr *pointer() { return Ptr; }
const SExpr *pointer() const { return Ptr; }
@@ -1052,16 +1052,15 @@
SExpr* Ptr;
};
-
/// Store a value to memory.
/// The destination is a pointer to a field, the source is the value to store.
class Store : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
-
Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Dest(P), Source(V) {}
Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Dest(P), Source(V) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
+
SExpr *destination() { return Dest; } // Address to store to
const SExpr *destination() const { return Dest; }
@@ -1088,16 +1087,15 @@
SExpr* Source;
};
-
/// If p is a reference to an array, then p[i] is a reference to the i'th
/// element of the array.
class ArrayIndex : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; }
-
ArrayIndex(SExpr *A, SExpr *N) : SExpr(COP_ArrayIndex), Array(A), Index(N) {}
ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N)
- : SExpr(E), Array(A), Index(N) {}
+ : SExpr(E), Array(A), Index(N) {}
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; }
SExpr *array() { return Array; }
const SExpr *array() const { return Array; }
@@ -1125,17 +1123,16 @@
SExpr* Index;
};
-
/// Pointer arithmetic, restricted to arrays only.
/// If p is a reference to an array, then p + n, where n is an integer, is
/// a reference to a subarray.
class ArrayAdd : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; }
-
ArrayAdd(SExpr *A, SExpr *N) : SExpr(COP_ArrayAdd), Array(A), Index(N) {}
ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N)
- : SExpr(E), Array(A), Index(N) {}
+ : SExpr(E), Array(A), Index(N) {}
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; }
SExpr *array() { return Array; }
const SExpr *array() const { return Array; }
@@ -1163,18 +1160,18 @@
SExpr* Index;
};
-
/// Simple arithmetic unary operations, e.g. negate and not.
/// These operations have no side-effects.
class UnaryOp : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; }
-
UnaryOp(TIL_UnaryOpcode Op, SExpr *E) : SExpr(COP_UnaryOp), Expr0(E) {
Flags = Op;
}
+
UnaryOp(const UnaryOp &U, SExpr *E) : SExpr(U), Expr0(E) { Flags = U.Flags; }
+ static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; }
+
TIL_UnaryOpcode unaryOpcode() const {
return static_cast<TIL_UnaryOpcode>(Flags);
}
@@ -1201,22 +1198,22 @@
SExpr* Expr0;
};
-
/// Simple arithmetic binary operations, e.g. +, -, etc.
/// These operations have no side effects.
class BinaryOp : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; }
-
BinaryOp(TIL_BinaryOpcode Op, SExpr *E0, SExpr *E1)
: SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
Flags = Op;
}
+
BinaryOp(const BinaryOp &B, SExpr *E0, SExpr *E1)
: SExpr(B), Expr0(E0), Expr1(E1) {
Flags = B.Flags;
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; }
+
TIL_BinaryOpcode binaryOpcode() const {
return static_cast<TIL_BinaryOpcode>(Flags);
}
@@ -1251,17 +1248,16 @@
SExpr* Expr1;
};
-
/// Cast expressions.
/// Cast expressions are essentially unary operations, but we treat them
/// as a distinct AST node because they only change the type of the result.
class Cast : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; }
-
Cast(TIL_CastOpcode Op, SExpr *E) : SExpr(COP_Cast), Expr0(E) { Flags = Op; }
Cast(const Cast &C, SExpr *E) : SExpr(C), Expr0(E) { Flags = C.Flags; }
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; }
+
TIL_CastOpcode castOpcode() const {
return static_cast<TIL_CastOpcode>(Flags);
}
@@ -1288,16 +1284,14 @@
SExpr* Expr0;
};
-
class SCFG;
-
/// Phi Node, for code in SSA form.
/// Each Phi node has an array of possible values that it can take,
/// depending on where control flow comes from.
class Phi : public SExpr {
public:
- typedef SimpleArray<SExpr *> ValArray;
+ using ValArray = SimpleArray<SExpr *>;
// In minimal SSA form, all Phi nodes are MultiVal.
// During conversion to SSA, incomplete Phi nodes may be introduced, which
@@ -1308,14 +1302,11 @@
PH_Incomplete // Phi node is incomplete
};
- static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; }
+ Phi() : SExpr(COP_Phi) {}
+ Phi(MemRegionRef A, unsigned Nvals) : SExpr(COP_Phi), Values(A, Nvals) {}
+ Phi(const Phi &P, ValArray &&Vs) : SExpr(P), Values(std::move(Vs)) {}
- Phi()
- : SExpr(COP_Phi), Cvdecl(nullptr) {}
- Phi(MemRegionRef A, unsigned Nvals)
- : SExpr(COP_Phi), Values(A, Nvals), Cvdecl(nullptr) {}
- Phi(const Phi &P, ValArray &&Vs)
- : SExpr(P), Values(std::move(Vs)), Cvdecl(nullptr) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; }
const ValArray &values() const { return Values; }
ValArray &values() { return Values; }
@@ -1324,19 +1315,18 @@
void setStatus(Status s) { Flags = s; }
/// Return the clang declaration of the variable for this Phi node, if any.
- const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+ const ValueDecl *clangDecl() const { return Cvdecl; }
/// Set the clang variable associated with this Phi node.
- void setClangDecl(const clang::ValueDecl *Cvd) { Cvdecl = Cvd; }
+ void setClangDecl(const ValueDecl *Cvd) { Cvdecl = Cvd; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
typename V::template Container<typename V::R_SExpr>
Nvs(Vs, Values.size());
- for (auto *Val : Values) {
+ for (const auto *Val : Values)
Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) );
- }
return Vs.reducePhi(*this, Nvs);
}
@@ -1348,31 +1338,28 @@
private:
ValArray Values;
- const clang::ValueDecl* Cvdecl;
+ const ValueDecl* Cvdecl = nullptr;
};
-
/// Base class for basic block terminators: Branch, Goto, and Return.
class Terminator : public SExpr {
+protected:
+ Terminator(TIL_Opcode Op) : SExpr(Op) {}
+ Terminator(const SExpr &E) : SExpr(E) {}
+
public:
static bool classof(const SExpr *E) {
return E->opcode() >= COP_Goto && E->opcode() <= COP_Return;
}
-protected:
- Terminator(TIL_Opcode Op) : SExpr(Op) {}
- Terminator(const SExpr &E) : SExpr(E) {}
-
-public:
/// Return the list of basic blocks that this terminator can branch to.
- ArrayRef<BasicBlock*> successors();
+ ArrayRef<BasicBlock *> successors();
- ArrayRef<BasicBlock*> successors() const {
+ ArrayRef<BasicBlock *> successors() const {
return const_cast<Terminator*>(this)->successors();
}
};
-
/// Jump to another basic block.
/// A goto instruction is essentially a tail-recursive call into another
/// block. In addition to the block pointer, it specifies an index into the
@@ -1380,13 +1367,13 @@
/// of the call.
class Goto : public Terminator {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
-
Goto(BasicBlock *B, unsigned I)
: Terminator(COP_Goto), TargetBlock(B), Index(I) {}
Goto(const Goto &G, BasicBlock *B, unsigned I)
: Terminator(COP_Goto), TargetBlock(B), Index(I) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
+
const BasicBlock *targetBlock() const { return TargetBlock; }
BasicBlock *targetBlock() { return TargetBlock; }
@@ -1394,9 +1381,7 @@
unsigned index() const { return Index; }
/// Return the list of basic blocks that this terminator can branch to.
- ArrayRef<BasicBlock*> successors() {
- return TargetBlock;
- }
+ ArrayRef<BasicBlock *> successors() { return TargetBlock; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1415,25 +1400,25 @@
unsigned Index;
};
-
/// A conditional branch to two other blocks.
/// Note that unlike Goto, Branch does not have an index. The target blocks
/// must be child-blocks, and cannot have Phi nodes.
class Branch : public Terminator {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
-
Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
: Terminator(COP_Branch), Condition(C) {
Branches[0] = T;
Branches[1] = E;
}
+
Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)
: Terminator(Br), Condition(C) {
Branches[0] = T;
Branches[1] = E;
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
+
const SExpr *condition() const { return Condition; }
SExpr *condition() { return Condition; }
@@ -1463,24 +1448,21 @@
}
private:
- SExpr* Condition;
+ SExpr *Condition;
BasicBlock *Branches[2];
};
-
/// Return from the enclosing function, passing the return value to the caller.
/// Only the exit block should end with a return statement.
class Return : public Terminator {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Return; }
-
Return(SExpr* Rval) : Terminator(COP_Return), Retval(Rval) {}
Return(const Return &R, SExpr* Rval) : Terminator(R), Retval(Rval) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Return; }
+
/// Return an empty list.
- ArrayRef<BasicBlock*> successors() {
- return None;
- }
+ ArrayRef<BasicBlock *> successors() { return None; }
SExpr *returnValue() { return Retval; }
const SExpr *returnValue() const { return Retval; }
@@ -1500,7 +1482,6 @@
SExpr* Retval;
};
-
inline ArrayRef<BasicBlock*> Terminator::successors() {
switch (opcode()) {
case COP_Goto: return cast<Goto>(this)->successors();
@@ -1511,7 +1492,6 @@
}
}
-
/// A basic block is part of an SCFG. It can be treated as a function in
/// continuation passing style. A block consists of a sequence of phi nodes,
/// which are "arguments" to the function, followed by a sequence of
@@ -1519,15 +1499,23 @@
/// another basic block in the same SCFG.
class BasicBlock : public SExpr {
public:
- typedef SimpleArray<SExpr*> InstrArray;
- typedef SimpleArray<BasicBlock*> BlockArray;
+ using InstrArray = SimpleArray<SExpr *>;
+ using BlockArray = SimpleArray<BasicBlock *>;
// TopologyNodes are used to overlay tree structures on top of the CFG,
// such as dominator and postdominator trees. Each block is assigned an
// ID in the tree according to a depth-first search. Tree traversals are
// always up, towards the parents.
struct TopologyNode {
- TopologyNode() : NodeID(0), SizeOfSubTree(0), Parent(nullptr) {}
+ int NodeID = 0;
+
+ // Includes this node, so must be > 1.
+ int SizeOfSubTree = 0;
+
+ // Pointer to parent.
+ BasicBlock *Parent = nullptr;
+
+ TopologyNode() = default;
bool isParentOf(const TopologyNode& OtherNode) {
return OtherNode.NodeID > NodeID &&
@@ -1538,22 +1526,17 @@
return OtherNode.NodeID >= NodeID &&
OtherNode.NodeID < NodeID + SizeOfSubTree;
}
-
- int NodeID;
- int SizeOfSubTree; // Includes this node, so must be > 1.
- BasicBlock *Parent; // Pointer to parent.
};
- static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; }
-
explicit BasicBlock(MemRegionRef A)
- : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),
- Visited(0), TermInstr(nullptr) {}
+ : SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(false) {}
BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is,
Terminator *T)
- : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),Visited(0),
+ : SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(false),
Args(std::move(As)), Instrs(std::move(Is)), TermInstr(T) {}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; }
+
/// Returns the block ID. Every block has a unique ID in the CFG.
int blockID() const { return BlockID; }
@@ -1600,11 +1583,13 @@
Args.reserveCheck(1, Arena);
Args.push_back(V);
}
+
/// Add a new instruction.
void addInstruction(SExpr *V) {
Instrs.reserveCheck(1, Arena);
Instrs.push_back(V);
}
+
// Add a new predecessor, and return the phi-node index for it.
// Will add an argument to all phi-nodes, initialized to nullptr.
unsigned addPredecessor(BasicBlock *Pred);
@@ -1632,11 +1617,11 @@
// Entering the basic block should do any scope initialization.
Vs.enterBasicBlock(*this);
- for (auto *E : Args) {
+ for (const auto *E : Args) {
auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
Nas.push_back(Ne);
}
- for (auto *E : Instrs) {
+ for (const auto *E : Instrs) {
auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
Nis.push_back(Ne);
}
@@ -1657,43 +1642,56 @@
private:
friend class SCFG;
- int renumberInstrs(int id); // assign unique ids to all instructions
- int topologicalSort(SimpleArray<BasicBlock*>& Blocks, int ID);
- int topologicalFinalSort(SimpleArray<BasicBlock*>& Blocks, int ID);
+ // assign unique ids to all instructions
+ int renumberInstrs(int id);
+
+ int topologicalSort(SimpleArray<BasicBlock *> &Blocks, int ID);
+ int topologicalFinalSort(SimpleArray<BasicBlock *> &Blocks, int ID);
void computeDominator();
void computePostDominator();
-private:
- MemRegionRef Arena; // The arena used to allocate this block.
- SCFG *CFGPtr; // The CFG that contains this block.
- int BlockID : 31; // unique id for this BB in the containing CFG.
- // IDs are in topological order.
- bool Visited : 1; // Bit to determine if a block has been visited
- // during a traversal.
- BlockArray Predecessors; // Predecessor blocks in the CFG.
- InstrArray Args; // Phi nodes. One argument per predecessor.
- InstrArray Instrs; // Instructions.
- Terminator* TermInstr; // Terminating instruction
+ // The arena used to allocate this block.
+ MemRegionRef Arena;
- TopologyNode DominatorNode; // The dominator tree
- TopologyNode PostDominatorNode; // The post-dominator tree
+ // The CFG that contains this block.
+ SCFG *CFGPtr = nullptr;
+
+ // Unique ID for this BB in the containing CFG. IDs are in topological order.
+ int BlockID : 31;
+
+ // Bit to determine if a block has been visited during a traversal.
+ bool Visited : 1;
+
+ // Predecessor blocks in the CFG.
+ BlockArray Predecessors;
+
+ // Phi nodes. One argument per predecessor.
+ InstrArray Args;
+
+ // Instructions.
+ InstrArray Instrs;
+
+ // Terminating instruction.
+ Terminator *TermInstr = nullptr;
+
+ // The dominator tree.
+ TopologyNode DominatorNode;
+
+ // The post-dominator tree.
+ TopologyNode PostDominatorNode;
};
-
/// An SCFG is a control-flow graph. It consists of a set of basic blocks,
/// each of which terminates in a branch to another basic block. There is one
/// entry point, and one exit point.
class SCFG : public SExpr {
public:
- typedef SimpleArray<BasicBlock *> BlockArray;
- typedef BlockArray::iterator iterator;
- typedef BlockArray::const_iterator const_iterator;
-
- static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; }
+ using BlockArray = SimpleArray<BasicBlock *>;
+ using iterator = BlockArray::iterator;
+ using const_iterator = BlockArray::const_iterator;
SCFG(MemRegionRef A, unsigned Nblocks)
- : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks),
- Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
+ : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks) {
Entry = new (A) BasicBlock(A);
Exit = new (A) BasicBlock(A);
auto *V = new (A) Phi();
@@ -1702,12 +1700,14 @@
add(Entry);
add(Exit);
}
+
SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba
- : SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)),
- Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
+ : SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)) {
// TODO: set entry and exit!
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; }
+
/// Return true if this CFG is valid.
bool valid() const { return Entry && Exit && Blocks.size() > 0; }
@@ -1756,7 +1756,7 @@
Vs.enterCFG(*this);
typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size());
- for (auto *B : Blocks) {
+ for (const auto *B : Blocks) {
Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
}
Vs.exitCFG(*this);
@@ -1770,27 +1770,25 @@
}
private:
- void renumberInstrs(); // assign unique ids to all instructions
+ // assign unique ids to all instructions
+ void renumberInstrs();
-private:
MemRegionRef Arena;
- BlockArray Blocks;
- BasicBlock *Entry;
- BasicBlock *Exit;
- unsigned NumInstructions;
- bool Normal;
+ BlockArray Blocks;
+ BasicBlock *Entry = nullptr;
+ BasicBlock *Exit = nullptr;
+ unsigned NumInstructions = 0;
+ bool Normal = false;
};
-
-
/// An identifier, e.g. 'foo' or 'x'.
/// This is a pseduo-term; it will be lowered to a variable or projection.
class Identifier : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Identifier; }
+ Identifier(StringRef Id): SExpr(COP_Identifier), Name(Id) {}
+ Identifier(const Identifier &) = default;
- Identifier(StringRef Id): SExpr(COP_Identifier), Name(Id) { }
- Identifier(const Identifier& I) : SExpr(I), Name(I.Name) { }
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Identifier; }
StringRef name() const { return Name; }
@@ -1808,19 +1806,16 @@
StringRef Name;
};
-
/// An if-then-else expression.
/// This is a pseduo-term; it will be lowered to a branch in a CFG.
class IfThenElse : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_IfThenElse; }
-
IfThenElse(SExpr *C, SExpr *T, SExpr *E)
- : SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E)
- { }
+ : SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E) {}
IfThenElse(const IfThenElse &I, SExpr *C, SExpr *T, SExpr *E)
- : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E)
- { }
+ : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E) {}
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_IfThenElse; }
SExpr *condition() { return Condition; } // Address to store to
const SExpr *condition() const { return Condition; }
@@ -1856,20 +1851,20 @@
SExpr* ElseExpr;
};
-
/// A let-expression, e.g. let x=t; u.
/// This is a pseduo-term; it will be lowered to instructions in a CFG.
class Let : public SExpr {
public:
- static bool classof(const SExpr *E) { return E->opcode() == COP_Let; }
-
Let(Variable *Vd, SExpr *Bd) : SExpr(COP_Let), VarDecl(Vd), Body(Bd) {
Vd->setKind(Variable::VK_Let);
}
+
Let(const Let &L, Variable *Vd, SExpr *Bd) : SExpr(L), VarDecl(Vd), Body(Bd) {
Vd->setKind(Variable::VK_Let);
}
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Let; }
+
Variable *variableDecl() { return VarDecl; }
const Variable *variableDecl() const { return VarDecl; }
@@ -1904,15 +1899,13 @@
SExpr* Body;
};
-
-
const SExpr *getCanonicalVal(const SExpr *E);
SExpr* simplifyToCanonicalVal(SExpr *E);
void simplifyIncompleteArg(til::Phi *Ph);
+} // namespace til
+} // namespace threadSafety
-} // end namespace til
-} // end namespace threadSafety
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
index 705fe91..38e6205 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
@@ -1,4 +1,4 @@
-//===- ThreadSafetyTraverse.h ----------------------------------*- C++ --*-===//
+//===- ThreadSafetyTraverse.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,7 +17,13 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
-#include "ThreadSafetyTIL.h"
+#include "clang/AST/Decl.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
+#include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <cstdint>
#include <ostream>
namespace clang {
@@ -92,21 +98,27 @@
#undef TIL_OPCODE_DEF
};
-
// Base class for simple reducers that don't much care about the context.
class SimpleReducerBase {
public:
enum TraversalKind {
- TRV_Normal, // ordinary subexpressions
- TRV_Decl, // declarations (e.g. function bodies)
- TRV_Lazy, // expressions that require lazy evaluation
- TRV_Type // type expressions
+ // Ordinary subexpressions.
+ TRV_Normal,
+
+ // Declarations (e.g. function bodies).
+ TRV_Decl,
+
+ // Expressions that require lazy evaluation.
+ TRV_Lazy,
+
+ // Type expressions.
+ TRV_Type
};
// R_Ctx defines a "context" for the traversal, which encodes information
// about where a term appears. This can be used to encoding the
// "current continuation" for CPS transforms, or other information.
- typedef TraversalKind R_Ctx;
+ using R_Ctx = TraversalKind;
// Create context for an ordinary subexpression.
R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; }
@@ -123,14 +135,13 @@
R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; }
};
-
// Base class for traversals that rewrite an SExpr to another SExpr.
class CopyReducerBase : public SimpleReducerBase {
public:
// R_SExpr is the result type for a traversal.
// A copy or non-destructive rewrite returns a newly allocated term.
- typedef SExpr *R_SExpr;
- typedef BasicBlock *R_BasicBlock;
+ using R_SExpr = SExpr *;
+ using R_BasicBlock = BasicBlock *;
// Container is a minimal interface used to store results when traversing
// SExprs of variable arity, such as Phi, Goto, and SCFG.
@@ -151,32 +162,31 @@
MemRegionRef Arena;
};
-
// Base class for visit traversals.
class VisitReducerBase : public SimpleReducerBase {
public:
// A visitor returns a bool, representing success or failure.
- typedef bool R_SExpr;
- typedef bool R_BasicBlock;
+ using R_SExpr = bool;
+ using R_BasicBlock = bool;
// A visitor "container" is a single bool, which accumulates success.
template <class T> class Container {
public:
- Container(VisitReducerBase &S, unsigned N) : Success(true) {}
- void push_back(bool E) { Success = Success && E; }
+ bool Success = true;
- bool Success;
+ Container(VisitReducerBase &S, unsigned N) {}
+
+ void push_back(bool E) { Success = Success && E; }
};
};
-
// Implements a traversal that visits each subexpression, and returns either
// true or false.
template <class Self>
class VisitReducer : public Traversal<Self, VisitReducerBase>,
public VisitReducerBase {
public:
- VisitReducer() {}
+ VisitReducer() = default;
public:
R_SExpr reduceNull() { return true; }
@@ -191,54 +201,70 @@
R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
return Nvd && E0;
}
+
R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
return Nvd && E0;
}
+
R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; }
R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; }
R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
+
R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
+
R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
return E0 && E1;
}
+
R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; }
R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) {
return Bbs.Success;
}
+
R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<R_SExpr> &As,
Container<R_SExpr> &Is, R_SExpr T) {
return (As.Success && Is.Success && T);
}
+
R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
return As.Success;
}
+
R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
return true;
}
+
R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
return C;
}
+
R_SExpr reduceReturn(Return &O, R_SExpr E) {
return E;
}
@@ -246,9 +272,11 @@
R_SExpr reduceIdentifier(Identifier &Orig) {
return true;
}
+
R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
return C && T && E;
}
+
R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
return Nvd && B;
}
@@ -260,7 +288,7 @@
void enterBasicBlock(BasicBlock &BB) {}
void exitBasicBlock(BasicBlock &BB) {}
- Variable *reduceVariableRef (Variable *Ovd) { return Ovd; }
+ Variable *reduceVariableRef(Variable *Ovd) { return Ovd; }
BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
public:
@@ -278,7 +306,6 @@
bool Success;
};
-
// Basic class for comparison operations over expressions.
template <typename Self>
class Comparator {
@@ -298,19 +325,18 @@
}
};
-
class EqualsComparator : public Comparator<EqualsComparator> {
public:
// Result type for the comparison, e.g. bool for simple equality,
// or int for lexigraphic comparison (-1, 0, 1). Must have one value which
// denotes "true".
- typedef bool CType;
+ using CType = bool;
CType trueResult() { return true; }
bool notTrue(CType ct) { return !ct; }
- bool compareIntegers(unsigned i, unsigned j) { return i == j; }
- bool compareStrings (StringRef s, StringRef r) { return s == r; }
+ bool compareIntegers(unsigned i, unsigned j) { return i == j; }
+ bool compareStrings (StringRef s, StringRef r) { return s == r; }
bool comparePointers(const void* P, const void* Q) { return P == Q; }
bool compare(const SExpr *E1, const SExpr* E2) {
@@ -320,10 +346,10 @@
}
// TODO -- handle alpha-renaming of variables
- void enterScope(const Variable* V1, const Variable* V2) { }
- void leaveScope() { }
+ void enterScope(const Variable *V1, const Variable *V2) {}
+ void leaveScope() {}
- bool compareVariableRefs(const Variable* V1, const Variable* V2) {
+ bool compareVariableRefs(const Variable *V1, const Variable *V2) {
return V1 == V2;
}
@@ -333,23 +359,21 @@
}
};
-
-
class MatchComparator : public Comparator<MatchComparator> {
public:
// Result type for the comparison, e.g. bool for simple equality,
// or int for lexigraphic comparison (-1, 0, 1). Must have one value which
// denotes "true".
- typedef bool CType;
+ using CType = bool;
CType trueResult() { return true; }
bool notTrue(CType ct) { return !ct; }
- bool compareIntegers(unsigned i, unsigned j) { return i == j; }
- bool compareStrings (StringRef s, StringRef r) { return s == r; }
- bool comparePointers(const void* P, const void* Q) { return P == Q; }
+ bool compareIntegers(unsigned i, unsigned j) { return i == j; }
+ bool compareStrings (StringRef s, StringRef r) { return s == r; }
+ bool comparePointers(const void *P, const void *Q) { return P == Q; }
- bool compare(const SExpr *E1, const SExpr* E2) {
+ bool compare(const SExpr *E1, const SExpr *E2) {
// Wildcards match anything.
if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard)
return true;
@@ -360,8 +384,8 @@
}
// TODO -- handle alpha-renaming of variables
- void enterScope(const Variable* V1, const Variable* V2) { }
- void leaveScope() { }
+ void enterScope(const Variable* V1, const Variable* V2) {}
+ void leaveScope() {}
bool compareVariableRefs(const Variable* V1, const Variable* V2) {
return V1 == V2;
@@ -373,8 +397,6 @@
}
};
-
-
// inline std::ostream& operator<<(std::ostream& SS, StringRef R) {
// return SS.write(R.data(), R.size());
// }
@@ -383,14 +405,18 @@
template <typename Self, typename StreamType>
class PrettyPrinter {
private:
- bool Verbose; // Print out additional information
- bool Cleanup; // Omit redundant decls.
- bool CStyle; // Print exprs in C-like syntax.
+ // Print out additional information.
+ bool Verbose;
+
+ // Omit redundant decls.
+ bool Cleanup;
+
+ // Print exprs in C-like syntax.
+ bool CStyle;
public:
PrettyPrinter(bool V = false, bool C = true, bool CS = true)
- : Verbose(V), Cleanup(C), CStyle(CS)
- {}
+ : Verbose(V), Cleanup(C), CStyle(CS) {}
static void print(const SExpr *E, StreamType &SS) {
Self printer;
@@ -470,7 +496,6 @@
}
}
-
void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true) {
if (!E) {
self()->printNull(SS);
@@ -531,18 +556,16 @@
else {
ValueType VT = E->valueType();
switch (VT.Base) {
- case ValueType::BT_Void: {
+ case ValueType::BT_Void:
SS << "void";
return;
- }
- case ValueType::BT_Bool: {
+ case ValueType::BT_Bool:
if (E->as<bool>().value())
SS << "true";
else
SS << "false";
return;
- }
- case ValueType::BT_Int: {
+ case ValueType::BT_Int:
switch (VT.Size) {
case ValueType::ST_8:
if (VT.Signed)
@@ -572,8 +595,7 @@
break;
}
break;
- }
- case ValueType::BT_Float: {
+ case ValueType::BT_Float:
switch (VT.Size) {
case ValueType::ST_32:
printLiteralT(&E->as<float>(), SS);
@@ -585,22 +607,18 @@
break;
}
break;
- }
- case ValueType::BT_String: {
+ case ValueType::BT_String:
SS << "\"";
printLiteralT(&E->as<StringRef>(), SS);
SS << "\"";
return;
- }
- case ValueType::BT_Pointer: {
+ case ValueType::BT_Pointer:
SS << "#ptr";
return;
- }
- case ValueType::BT_ValueRef: {
+ case ValueType::BT_ValueRef:
SS << "#vref";
return;
}
- }
}
SS << "#lit";
}
@@ -688,8 +706,8 @@
void printProject(const Project *E, StreamType &SS) {
if (CStyle) {
// Omit the this->
- if (const SApply *SAP = dyn_cast<SApply>(E->record())) {
- if (const Variable *V = dyn_cast<Variable>(SAP->sfun())) {
+ if (const auto *SAP = dyn_cast<SApply>(E->record())) {
+ if (const auto *V = dyn_cast<Variable>(SAP->sfun())) {
if (!SAP->isDelegation() && V->kind() == Variable::VK_SFun) {
SS << E->slotName();
return;
@@ -704,12 +722,10 @@
}
}
self()->printSExpr(E->record(), SS, Prec_Postfix);
- if (CStyle && E->isArrow()) {
+ if (CStyle && E->isArrow())
SS << "->";
- }
- else {
+ else
SS << ".";
- }
SS << E->slotName();
}
@@ -780,18 +796,16 @@
void printSCFG(const SCFG *E, StreamType &SS) {
SS << "CFG {\n";
- for (auto BBI : *E) {
+ for (const auto *BBI : *E)
printBasicBlock(BBI, SS);
- }
SS << "}";
newline(SS);
}
-
void printBBInstr(const SExpr *E, StreamType &SS) {
bool Sub = false;
if (E->opcode() == COP_Variable) {
- auto *V = cast<Variable>(E);
+ const auto *V = cast<Variable>(E);
SS << "let " << V->name() << V->id() << " = ";
E = V->definition();
Sub = true;
@@ -810,10 +824,10 @@
SS << " BB_" << E->parent()->blockID();
newline(SS);
- for (auto *A : E->arguments())
+ for (const auto *A : E->arguments())
printBBInstr(A, SS);
- for (auto *I : E->instructions())
+ for (const auto *I : E->instructions())
printBBInstr(I, SS);
const SExpr *T = E->terminator();
@@ -831,7 +845,7 @@
self()->printSExpr(E->values()[0], SS, Prec_MAX);
else {
unsigned i = 0;
- for (auto V : E->values()) {
+ for (const auto *V : E->values()) {
if (i++ > 0)
SS << ", ";
self()->printSExpr(V, SS, Prec_MAX);
@@ -890,13 +904,10 @@
}
};
+class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> {};
-class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> { };
+} // namespace til
+} // namespace threadSafety
+} // namespace clang
-
-
-} // end namespace til
-} // end namespace threadSafety
-} // end namespace clang
-
-#endif // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
index cb80ce5..1658393 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
@@ -1,4 +1,4 @@
-//===- ThreadSafetyUtil.h --------------------------------------*- C++ --*-===//
+//===- ThreadSafetyUtil.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,18 +14,23 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H
-#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/AlignOf.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstddef>
+#include <cstring>
+#include <iterator>
#include <ostream>
-#include <utility>
+#include <string>
#include <vector>
namespace clang {
+
+class Expr;
+
namespace threadSafety {
namespace til {
@@ -41,7 +46,7 @@
};
public:
- MemRegionRef() : Allocator(nullptr) {}
+ MemRegionRef() = default;
MemRegionRef(llvm::BumpPtrAllocator *A) : Allocator(A) {}
void *allocate(size_t Sz) {
@@ -55,12 +60,13 @@
}
private:
- llvm::BumpPtrAllocator *Allocator;
+ llvm::BumpPtrAllocator *Allocator = nullptr;
};
-} // end namespace til
-} // end namespace threadSafety
-} // end namespace clang
+} // namespace til
+} // namespace threadSafety
+
+} // namespace clang
inline void *operator new(size_t Sz,
clang::threadSafety::til::MemRegionRef &R) {
@@ -70,10 +76,7 @@
namespace clang {
namespace threadSafety {
-std::string getSourceLiteralString(const clang::Expr *CE);
-
-using llvm::StringRef;
-using clang::SourceLocation;
+std::string getSourceLiteralString(const Expr *CE);
namespace til {
@@ -81,11 +84,13 @@
// suitable for use with bump pointer allocation.
template <class T> class SimpleArray {
public:
- SimpleArray() : Data(nullptr), Size(0), Capacity(0) {}
+ SimpleArray() = default;
SimpleArray(T *Dat, size_t Cp, size_t Sz = 0)
: Data(Dat), Size(Sz), Capacity(Cp) {}
SimpleArray(MemRegionRef A, size_t Cp)
- : Data(Cp == 0 ? nullptr : A.allocateT<T>(Cp)), Size(0), Capacity(Cp) {}
+ : Data(Cp == 0 ? nullptr : A.allocateT<T>(Cp)), Capacity(Cp) {}
+ SimpleArray(const SimpleArray<T> &A) = delete;
+
SimpleArray(SimpleArray<T> &&A)
: Data(A.Data), Size(A.Size), Capacity(A.Capacity) {
A.Data = nullptr;
@@ -123,10 +128,10 @@
reserve(u_max(Size + N, Capacity * 2), A);
}
- typedef T *iterator;
- typedef const T *const_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ using iterator = T *;
+ using const_iterator = const T *;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
size_t size() const { return Size; }
size_t capacity() const { return Capacity; }
@@ -135,27 +140,30 @@
assert(i < Size && "Array index out of bounds.");
return Data[i];
}
+
const T &operator[](unsigned i) const {
assert(i < Size && "Array index out of bounds.");
return Data[i];
}
+
T &back() {
assert(Size && "No elements in the array.");
return Data[Size - 1];
}
+
const T &back() const {
assert(Size && "No elements in the array.");
return Data[Size - 1];
}
iterator begin() { return Data; }
- iterator end() { return Data + Size; }
+ iterator end() { return Data + Size; }
const_iterator begin() const { return Data; }
- const_iterator end() const { return Data + Size; }
+ const_iterator end() const { return Data + Size; }
const_iterator cbegin() const { return Data; }
- const_iterator cend() const { return Data + Size; }
+ const_iterator cend() const { return Data + Size; }
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
@@ -163,6 +171,7 @@
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
+
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
@@ -198,6 +207,7 @@
llvm::iterator_range<reverse_iterator> reverse() {
return llvm::make_range(rbegin(), rend());
}
+
llvm::iterator_range<const_reverse_iterator> reverse() const {
return llvm::make_range(rbegin(), rend());
}
@@ -209,14 +219,12 @@
static const size_t InitialCapacity = 4;
- SimpleArray(const SimpleArray<T> &A) = delete;
-
- T *Data;
- size_t Size;
- size_t Capacity;
+ T *Data = nullptr;
+ size_t Size = 0;
+ size_t Capacity = 0;
};
-} // end namespace til
+} // namespace til
// A copy on write vector.
// The vector can be in one of three states:
@@ -228,20 +236,28 @@
class CopyOnWriteVector {
class VectorData {
public:
- VectorData() : NumRefs(1) { }
- VectorData(const VectorData &VD) : NumRefs(1), Vect(VD.Vect) { }
-
- unsigned NumRefs;
+ unsigned NumRefs = 1;
std::vector<T> Vect;
+
+ VectorData() = default;
+ VectorData(const VectorData &VD) : Vect(VD.Vect) {}
};
- // No copy constructor or copy assignment. Use clone() with move assignment.
- CopyOnWriteVector(const CopyOnWriteVector &V) = delete;
- void operator=(const CopyOnWriteVector &V) = delete;
-
public:
- CopyOnWriteVector() : Data(nullptr) {}
+ CopyOnWriteVector() = default;
CopyOnWriteVector(CopyOnWriteVector &&V) : Data(V.Data) { V.Data = nullptr; }
+
+ CopyOnWriteVector &operator=(CopyOnWriteVector &&V) {
+ destroy();
+ Data = V.Data;
+ V.Data = nullptr;
+ return *this;
+ }
+
+ // No copy constructor or copy assignment. Use clone() with move assignment.
+ CopyOnWriteVector(const CopyOnWriteVector &) = delete;
+ CopyOnWriteVector &operator=(const CopyOnWriteVector &) = delete;
+
~CopyOnWriteVector() { destroy(); }
// Returns true if this holds a valid vector.
@@ -283,14 +299,7 @@
// Create a lazy copy of this vector.
CopyOnWriteVector clone() { return CopyOnWriteVector(Data); }
- CopyOnWriteVector &operator=(CopyOnWriteVector &&V) {
- destroy();
- Data = V.Data;
- V.Data = nullptr;
- return *this;
- }
-
- typedef typename std::vector<T>::const_iterator const_iterator;
+ using const_iterator = typename std::vector<T>::const_iterator;
const std::vector<T> &elements() const { return Data->Vect; }
@@ -336,14 +345,14 @@
++Data->NumRefs;
}
- VectorData *Data;
+ VectorData *Data = nullptr;
};
inline std::ostream& operator<<(std::ostream& ss, const StringRef str) {
return ss.write(str.data(), str.size());
}
-} // end namespace threadSafety
-} // end namespace clang
+} // namespace threadSafety
+} // namespace clang
#endif // LLVM_CLANG_THREAD_SAFETY_UTIL_H
diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h
index 53ff20c..79d89e0 100644
--- a/include/clang/Analysis/Analyses/UninitializedValues.h
+++ b/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -1,4 +1,4 @@
-//= UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-==//
+//=- UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
@@ -15,7 +15,7 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
-#include "clang/AST/Stmt.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {
@@ -24,6 +24,7 @@
class CFG;
class DeclContext;
class Expr;
+class Stmt;
class VarDecl;
/// A use of a variable, which might be uninitialized.
@@ -39,10 +40,10 @@
const Expr *User;
/// Is this use uninitialized whenever the function is called?
- bool UninitAfterCall;
+ bool UninitAfterCall = false;
/// Is this use uninitialized whenever the variable declaration is reached?
- bool UninitAfterDecl;
+ bool UninitAfterDecl = false;
/// Does this use always see an uninitialized value?
bool AlwaysUninit;
@@ -53,8 +54,7 @@
public:
UninitUse(const Expr *User, bool AlwaysUninit)
- : User(User), UninitAfterCall(false), UninitAfterDecl(false),
- AlwaysUninit(AlwaysUninit) {}
+ : User(User), AlwaysUninit(AlwaysUninit) {}
void addUninitBranch(Branch B) {
UninitBranches.push_back(B);
@@ -70,14 +70,18 @@
enum Kind {
/// The use might be uninitialized.
Maybe,
+
/// The use is uninitialized whenever a certain branch is taken.
Sometimes,
+
/// The use is uninitialized the first time it is reached after we reach
/// the variable's declaration.
AfterDecl,
+
/// The use is uninitialized the first time it is reached after the function
/// is called.
AfterCall,
+
/// The use is always uninitialized.
Always
};
@@ -90,7 +94,8 @@
!branch_empty() ? Sometimes : Maybe;
}
- typedef SmallVectorImpl<Branch>::const_iterator branch_iterator;
+ using branch_iterator = SmallVectorImpl<Branch>::const_iterator;
+
/// Branches which inevitably result in the variable being used uninitialized.
branch_iterator branch_begin() const { return UninitBranches.begin(); }
branch_iterator branch_end() const { return UninitBranches.end(); }
@@ -99,7 +104,7 @@
class UninitVariablesHandler {
public:
- UninitVariablesHandler() {}
+ UninitVariablesHandler() = default;
virtual ~UninitVariablesHandler();
/// Called when the uninitialized variable is used at the given expression.
@@ -122,5 +127,6 @@
UninitVariablesHandler &handler,
UninitVariablesAnalysisStats &stats);
-}
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
diff --git a/include/clang/Analysis/AnalysisDeclContext.h b/include/clang/Analysis/AnalysisDeclContext.h
index 63d4676..448d8f3 100644
--- a/include/clang/Analysis/AnalysisDeclContext.h
+++ b/include/clang/Analysis/AnalysisDeclContext.h
@@ -1,4 +1,4 @@
-//=== AnalysisDeclContext.h - Analysis context for Path Sens analysis --*- C++ -*-//
+// AnalysisDeclContext.h - Analysis context for Path Sens analysis -*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
@@ -15,37 +15,42 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
#define LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
-#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/Analysis/BodyFarm.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CodeInjector.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
+#include <functional>
#include <memory>
namespace clang {
-class Stmt;
+class AnalysisDeclContextManager;
+class ASTContext;
+class BlockDecl;
+class BlockInvocationContext;
class CFGReverseBlockReachabilityAnalysis;
class CFGStmtMap;
-class LiveVariables;
-class ManagedAnalysis;
+class ImplicitParamDecl;
+class LocationContext;
+class LocationContextManager;
class ParentMap;
class PseudoConstantAnalysis;
-class LocationContextManager;
class StackFrameContext;
-class BlockInvocationContext;
-class AnalysisDeclContextManager;
-class LocationContext;
-
-namespace idx { class TranslationUnit; }
+class Stmt;
+class VarDecl;
/// The base class of a hierarchy of objects representing analyses tied
/// to AnalysisDeclContext.
class ManagedAnalysis {
protected:
- ManagedAnalysis() {}
+ ManagedAnalysis() = default;
+
public:
virtual ~ManagedAnalysis();
@@ -61,7 +66,6 @@
// which creates the analysis object given an AnalysisDeclContext.
};
-
/// AnalysisDeclContext contains the context data for the function or method
/// under analysis.
class AnalysisDeclContext {
@@ -75,18 +79,19 @@
std::unique_ptr<CFGStmtMap> cfgStmtMap;
CFG::BuildOptions cfgBuildOptions;
- CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
+ CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs = nullptr;
- bool builtCFG, builtCompleteCFG;
+ bool builtCFG = false;
+ bool builtCompleteCFG = false;
std::unique_ptr<ParentMap> PM;
std::unique_ptr<PseudoConstantAnalysis> PCA;
std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
llvm::BumpPtrAllocator A;
- llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
+ llvm::DenseMap<const BlockDecl *,void *> *ReferencedBlockVars = nullptr;
- void *ManagedAnalyses;
+ void *ManagedAnalyses = nullptr;
public:
AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
@@ -172,7 +177,7 @@
ParentMap &getParentMap();
PseudoConstantAnalysis *getPseudoConstantAnalysis();
- typedef const VarDecl * const * referenced_decls_iterator;
+ using referenced_decls_iterator = const VarDecl * const *;
llvm::iterator_range<referenced_decls_iterator>
getReferencedBlockVars(const BlockDecl *BD);
@@ -200,12 +205,13 @@
if (!data) {
data = T::create(*this);
}
- return static_cast<T*>(data);
+ return static_cast<T *>(data);
}
/// Returns true if the root namespace of the given declaration is the 'std'
/// C++ namespace.
static bool isInStdNamespace(const Decl *D);
+
private:
ManagedAnalysis *&getAnalysisImpl(const void* tag);
@@ -228,7 +234,7 @@
protected:
LocationContext(ContextKind k, AnalysisDeclContext *ctx,
const LocationContext *parent)
- : Kind(k), Ctx(ctx), Parent(parent) {}
+ : Kind(k), Ctx(ctx), Parent(parent) {}
public:
virtual ~LocationContext();
@@ -266,7 +272,7 @@
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
void dumpStack(
- raw_ostream &OS, StringRef Indent = "", const char *NL = "\n",
+ raw_ostream &OS, StringRef Indent = {}, const char *NL = "\n",
const char *Sep = "",
std::function<void(const LocationContext *)> printMoreInfoPerContext =
[](const LocationContext *) {}) const;
@@ -281,6 +287,8 @@
};
class StackFrameContext : public LocationContext {
+ friend class LocationContextManager;
+
// The callsite where this stack frame is established.
const Stmt *CallSite;
@@ -290,15 +298,14 @@
// The index of the callsite in the CFGBlock.
unsigned Index;
- friend class LocationContextManager;
StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
const Stmt *s, const CFGBlock *blk,
unsigned idx)
- : LocationContext(StackFrame, ctx, parent), CallSite(s),
- Block(blk), Index(idx) {}
+ : LocationContext(StackFrame, ctx, parent), CallSite(s),
+ Block(blk), Index(idx) {}
public:
- ~StackFrameContext() override {}
+ ~StackFrameContext() override = default;
const Stmt *getCallSite() const { return CallSite; }
@@ -325,15 +332,16 @@
};
class ScopeContext : public LocationContext {
+ friend class LocationContextManager;
+
const Stmt *Enter;
- friend class LocationContextManager;
ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
const Stmt *s)
- : LocationContext(Scope, ctx, parent), Enter(s) {}
+ : LocationContext(Scope, ctx, parent), Enter(s) {}
public:
- ~ScopeContext() override {}
+ ~ScopeContext() override = default;
void Profile(llvm::FoldingSetNodeID &ID) override;
@@ -348,20 +356,20 @@
};
class BlockInvocationContext : public LocationContext {
+ friend class LocationContextManager;
+
const BlockDecl *BD;
// FIXME: Come up with a more type-safe way to model context-sensitivity.
const void *ContextData;
- friend class LocationContextManager;
-
BlockInvocationContext(AnalysisDeclContext *ctx,
const LocationContext *parent,
const BlockDecl *bd, const void *contextData)
- : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
+ : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
public:
- ~BlockInvocationContext() override {}
+ ~BlockInvocationContext() override = default;
const BlockDecl *getBlockDecl() const { return BD; }
@@ -383,6 +391,7 @@
class LocationContextManager {
llvm::FoldingSet<LocationContext> Contexts;
+
public:
~LocationContextManager();
@@ -411,8 +420,8 @@
};
class AnalysisDeclContextManager {
- typedef llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>
- ContextMap;
+ using ContextMap =
+ llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>;
ContextMap Contexts;
LocationContextManager LocContexts;
@@ -435,7 +444,9 @@
bool addImplicitDtors = false,
bool addInitializers = false,
bool addTemporaryDtors = false,
- bool addLifetime = false, bool addLoopExit = false,
+ bool addLifetime = false,
+ bool addLoopExit = false,
+ bool addScopes = false,
bool synthesizeBodies = false,
bool addStaticInitBranches = false,
bool addCXXNewAllocator = true,
@@ -493,5 +504,6 @@
}
};
-} // end clang namespace
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index 1465163..8120041 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -17,6 +17,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/Analysis/ConstructionContext.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
@@ -38,7 +39,6 @@
class ASTContext;
class BinaryOperator;
class CFG;
-class ConstructionContext;
class CXXBaseSpecifier;
class CXXBindTemporaryExpr;
class CXXCtorInitializer;
@@ -57,14 +57,17 @@
enum Kind {
// main kind
Initializer,
+ ScopeBegin,
+ ScopeEnd,
NewAllocator,
LifetimeEnds,
LoopExit,
// stmt kind
Statement,
Constructor,
+ CXXRecordTypedCall,
STMT_BEGIN = Statement,
- STMT_END = Constructor,
+ STMT_END = CXXRecordTypedCall,
// dtor kind
AutomaticObjectDtor,
DeleteDtor,
@@ -156,10 +159,6 @@
return static_cast<ConstructionContext *>(Data2.getPointer());
}
- QualType getType() const {
- return cast<CXXConstructExpr>(getStmt())->getType();
- }
-
private:
friend class CFGElement;
@@ -170,6 +169,47 @@
}
};
+/// CFGCXXRecordTypedCall - Represents a function call that returns a C++ object
+/// by value. This, like constructor, requires a construction context in order
+/// to understand the storage of the returned object . In C such tracking is not
+/// necessary because no additional effort is required for destroying the object
+/// or modeling copy elision. Like CFGConstructor, this element is for now only
+/// used by the analyzer's CFG.
+class CFGCXXRecordTypedCall : public CFGStmt {
+public:
+ /// Returns true when call expression \p CE needs to be represented
+ /// by CFGCXXRecordTypedCall, as opposed to a regular CFGStmt.
+ static bool isCXXRecordTypedCall(CallExpr *CE, const ASTContext &ACtx) {
+ return CE->getCallReturnType(ACtx).getCanonicalType()->getAsCXXRecordDecl();
+ }
+
+ explicit CFGCXXRecordTypedCall(CallExpr *CE, const ConstructionContext *C)
+ : CFGStmt(CE, CXXRecordTypedCall) {
+ // FIXME: This is not protected against squeezing a non-record-typed-call
+ // into the constructor. An assertion would require passing an ASTContext
+ // which would mean paying for something we don't use.
+ assert(C && (isa<TemporaryObjectConstructionContext>(C) ||
+ // These are possible in C++17 due to mandatory copy elision.
+ isa<ReturnedValueConstructionContext>(C) ||
+ isa<VariableConstructionContext>(C) ||
+ isa<ConstructorInitializerConstructionContext>(C)));
+ Data2.setPointer(const_cast<ConstructionContext *>(C));
+ }
+
+ const ConstructionContext *getConstructionContext() const {
+ return static_cast<ConstructionContext *>(Data2.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+
+ CFGCXXRecordTypedCall() = default;
+
+ static bool isKind(const CFGElement &E) {
+ return E.getKind() == CXXRecordTypedCall;
+ }
+};
+
/// CFGInitializer - Represents C++ base or member initializer from
/// constructor's initialization list.
class CFGInitializer : public CFGElement {
@@ -260,6 +300,55 @@
}
};
+/// Represents beginning of a scope implicitly generated
+/// by the compiler on encountering a CompoundStmt
+class CFGScopeBegin : public CFGElement {
+public:
+ CFGScopeBegin() {}
+ CFGScopeBegin(const VarDecl *VD, const Stmt *S)
+ : CFGElement(ScopeBegin, VD, S) {}
+
+ // Get statement that triggered a new scope.
+ const Stmt *getTriggerStmt() const {
+ return static_cast<Stmt*>(Data2.getPointer());
+ }
+
+ // Get VD that triggered a new scope.
+ const VarDecl *getVarDecl() const {
+ return static_cast<VarDecl *>(Data1.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ static bool isKind(const CFGElement &E) {
+ Kind kind = E.getKind();
+ return kind == ScopeBegin;
+ }
+};
+
+/// Represents end of a scope implicitly generated by
+/// the compiler after the last Stmt in a CompoundStmt's body
+class CFGScopeEnd : public CFGElement {
+public:
+ CFGScopeEnd() {}
+ CFGScopeEnd(const VarDecl *VD, const Stmt *S) : CFGElement(ScopeEnd, VD, S) {}
+
+ const VarDecl *getVarDecl() const {
+ return static_cast<VarDecl *>(Data1.getPointer());
+ }
+
+ const Stmt *getTriggerStmt() const {
+ return static_cast<Stmt *>(Data2.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ static bool isKind(const CFGElement &E) {
+ Kind kind = E.getKind();
+ return kind == ScopeEnd;
+ }
+};
+
/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
/// by compiler on various occasions.
class CFGImplicitDtor : public CFGElement {
@@ -789,6 +878,12 @@
Elements.push_back(CFGConstructor(CE, CC), C);
}
+ void appendCXXRecordTypedCall(CallExpr *CE,
+ const ConstructionContext *CC,
+ BumpVectorContext &C) {
+ Elements.push_back(CFGCXXRecordTypedCall(CE, CC), C);
+ }
+
void appendInitializer(CXXCtorInitializer *initializer,
BumpVectorContext &C) {
Elements.push_back(CFGInitializer(initializer), C);
@@ -799,6 +894,24 @@
Elements.push_back(CFGNewAllocator(NE), C);
}
+ void appendScopeBegin(const VarDecl *VD, const Stmt *S,
+ BumpVectorContext &C) {
+ Elements.push_back(CFGScopeBegin(VD, S), C);
+ }
+
+ void prependScopeBegin(const VarDecl *VD, const Stmt *S,
+ BumpVectorContext &C) {
+ Elements.insert(Elements.rbegin(), 1, CFGScopeBegin(VD, S), C);
+ }
+
+ void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C) {
+ Elements.push_back(CFGScopeEnd(VD, S), C);
+ }
+
+ void prependScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C) {
+ Elements.insert(Elements.rbegin(), 1, CFGScopeEnd(VD, S), C);
+ }
+
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) {
Elements.push_back(CFGBaseDtor(BS), C);
}
@@ -852,6 +965,19 @@
*I = CFGLifetimeEnds(VD, S);
return ++I;
}
+
+ // Scope leaving must be performed in reversed order. So insertion is in two
+ // steps. First we prepare space for some number of elements, then we insert
+ // the elements beginning at the last position in prepared space.
+ iterator beginScopeEndInsert(iterator I, size_t Cnt, BumpVectorContext &C) {
+ return iterator(
+ Elements.insert(I.base(), Cnt, CFGScopeEnd(nullptr, nullptr), C));
+ }
+ iterator insertScopeEnd(iterator I, VarDecl *VD, Stmt *S) {
+ *I = CFGScopeEnd(VD, S);
+ return ++I;
+ }
+
};
/// \brief CFGCallback defines methods that should be called when a logical
@@ -894,6 +1020,7 @@
bool AddLifetime = false;
bool AddLoopExit = false;
bool AddTemporaryDtors = false;
+ bool AddScopes = false;
bool AddStaticInitBranches = false;
bool AddCXXNewAllocator = false;
bool AddCXXDefaultInitExprInCtors = false;
diff --git a/include/clang/Analysis/ConstructionContext.h b/include/clang/Analysis/ConstructionContext.h
index 770f1c9..8df95a8 100644
--- a/include/clang/Analysis/ConstructionContext.h
+++ b/include/clang/Analysis/ConstructionContext.h
@@ -99,24 +99,40 @@
public:
enum Kind {
SimpleVariableKind,
- ConstructorInitializerKind,
+ CXX17ElidedCopyVariableKind,
+ VARIABLE_BEGIN = SimpleVariableKind,
+ VARIABLE_END = CXX17ElidedCopyVariableKind,
+ SimpleConstructorInitializerKind,
+ CXX17ElidedCopyConstructorInitializerKind,
+ INITIALIZER_BEGIN = SimpleConstructorInitializerKind,
+ INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind,
NewAllocatedObjectKind,
TemporaryObjectKind,
- ReturnedValueKind
+ SimpleReturnedValueKind,
+ CXX17ElidedCopyReturnedValueKind,
+ RETURNED_VALUE_BEGIN = SimpleReturnedValueKind,
+ RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind
};
protected:
Kind K;
-protected:
// Do not make public! These need to only be constructed
// via createFromLayers().
explicit ConstructionContext(Kind K) : K(K) {}
-public:
+private:
+ // A helper function for constructing an instance into a bump vector context.
+ template <typename T, typename... ArgTypes>
+ static T *create(BumpVectorContext &C, ArgTypes... Args) {
+ auto *CC = C.getAllocator().Allocate<T>();
+ return new (CC) T(Args...);
+ }
+public:
/// Consume the construction context layer, together with its parent layers,
- /// and wrap it up into a complete construction context.
+ /// and wrap it up into a complete construction context. May return null
+ /// if layers do not form any supported construction context.
static const ConstructionContext *
createFromLayers(BumpVectorContext &C,
const ConstructionContextLayer *TopLayer);
@@ -124,40 +140,139 @@
Kind getKind() const { return K; }
};
-/// Represents construction into a simple local variable, eg. T var(123);.
-class SimpleVariableConstructionContext : public ConstructionContext {
+/// An abstract base class for local variable constructors.
+class VariableConstructionContext : public ConstructionContext {
const DeclStmt *DS;
-public:
- explicit SimpleVariableConstructionContext(const DeclStmt *DS)
- : ConstructionContext(ConstructionContext::SimpleVariableKind), DS(DS) {
+protected:
+ VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
+ : ConstructionContext(K), DS(DS) {
+ assert(classof(this));
assert(DS);
}
+public:
const DeclStmt *getDeclStmt() const { return DS; }
static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() >= VARIABLE_BEGIN &&
+ CC->getKind() <= VARIABLE_END;
+ }
+};
+
+/// Represents construction into a simple local variable, eg. T var(123);.
+/// If a variable has an initializer, eg. T var = makeT();, then the final
+/// elidable copy-constructor from makeT() into var would also be a simple
+/// variable constructor handled by this class.
+class SimpleVariableConstructionContext : public VariableConstructionContext {
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit SimpleVariableConstructionContext(const DeclStmt *DS)
+ : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
+ DS) {}
+
+public:
+ static bool classof(const ConstructionContext *CC) {
return CC->getKind() == SimpleVariableKind;
}
};
-/// Represents construction into a field or a base class within a bigger object
-/// via a constructor initializer, eg. T(): field(123) { ... }.
+/// Represents construction into a simple variable with an initializer syntax,
+/// with a single constructor, eg. T var = makeT();. Such construction context
+/// may only appear in C++17 because previously it was split into a temporary
+/// object constructor and an elidable simple variable copy-constructor and
+/// we were producing separate construction contexts for these constructors.
+/// In C++17 we have a single construction context that combines both.
+/// Note that if the object has trivial destructor, then this code is
+/// indistinguishable from a simple variable constructor on the AST level;
+/// in this case we provide a simple variable construction context.
+class CXX17ElidedCopyVariableConstructionContext
+ : public VariableConstructionContext {
+ const CXXBindTemporaryExpr *BTE;
+
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit CXX17ElidedCopyVariableConstructionContext(
+ const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
+ : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
+ assert(BTE);
+ }
+
+public:
+ const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == CXX17ElidedCopyVariableKind;
+ }
+};
+
+// An abstract base class for constructor-initializer-based constructors.
class ConstructorInitializerConstructionContext : public ConstructionContext {
const CXXCtorInitializer *I;
-public:
+protected:
explicit ConstructorInitializerConstructionContext(
- const CXXCtorInitializer *I)
- : ConstructionContext(ConstructionContext::ConstructorInitializerKind),
- I(I) {
+ ConstructionContext::Kind K, const CXXCtorInitializer *I)
+ : ConstructionContext(K), I(I) {
+ assert(classof(this));
assert(I);
}
+public:
const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
static bool classof(const ConstructionContext *CC) {
- return CC->getKind() == ConstructorInitializerKind;
+ return CC->getKind() >= INITIALIZER_BEGIN &&
+ CC->getKind() <= INITIALIZER_END;
+ }
+};
+
+/// Represents construction into a field or a base class within a bigger object
+/// via a constructor initializer, eg. T(): field(123) { ... }.
+class SimpleConstructorInitializerConstructionContext
+ : public ConstructorInitializerConstructionContext {
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit SimpleConstructorInitializerConstructionContext(
+ const CXXCtorInitializer *I)
+ : ConstructorInitializerConstructionContext(
+ ConstructionContext::SimpleConstructorInitializerKind, I) {}
+
+public:
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == SimpleConstructorInitializerKind;
+ }
+};
+
+/// Represents construction into a field or a base class within a bigger object
+/// via a constructor initializer, with a single constructor, eg.
+/// T(): field(Field(123)) { ... }. Such construction context may only appear
+/// in C++17 because previously it was split into a temporary object constructor
+/// and an elidable simple constructor-initializer copy-constructor and we were
+/// producing separate construction contexts for these constructors. In C++17
+/// we have a single construction context that combines both. Note that if the
+/// object has trivial destructor, then this code is indistinguishable from
+/// a simple constructor-initializer constructor on the AST level; in this case
+/// we provide a simple constructor-initializer construction context.
+class CXX17ElidedCopyConstructorInitializerConstructionContext
+ : public ConstructorInitializerConstructionContext {
+ const CXXBindTemporaryExpr *BTE;
+
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
+ const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
+ : ConstructorInitializerConstructionContext(
+ CXX17ElidedCopyConstructorInitializerKind, I),
+ BTE(BTE) {
+ assert(BTE);
+ }
+
+public:
+ const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind;
}
};
@@ -166,13 +281,15 @@
class NewAllocatedObjectConstructionContext : public ConstructionContext {
const CXXNewExpr *NE;
-public:
+ friend class ConstructionContext; // Allows to create<>() itself.
+
explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
: ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
NE(NE) {
assert(NE);
}
+public:
const CXXNewExpr *getCXXNewExpr() const { return NE; }
static bool classof(const ConstructionContext *CC) {
@@ -188,7 +305,8 @@
const CXXBindTemporaryExpr *BTE;
const MaterializeTemporaryExpr *MTE;
-public:
+ friend class ConstructionContext; // Allows to create<>() itself.
+
explicit TemporaryObjectConstructionContext(
const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
: ConstructionContext(ConstructionContext::TemporaryObjectKind),
@@ -199,6 +317,7 @@
// nowhere that doesn't have a non-trivial destructor).
}
+public:
/// CXXBindTemporaryExpr here is non-null as long as the temporary has
/// a non-trivial destructor.
const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
@@ -219,24 +338,72 @@
}
};
+class ReturnedValueConstructionContext : public ConstructionContext {
+ const ReturnStmt *RS;
+
+protected:
+ explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
+ const ReturnStmt *RS)
+ : ConstructionContext(K), RS(RS) {
+ assert(classof(this));
+ assert(RS);
+ }
+
+public:
+ const ReturnStmt *getReturnStmt() const { return RS; }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() >= RETURNED_VALUE_BEGIN &&
+ CC->getKind() <= RETURNED_VALUE_END;
+ }
+};
+
/// Represents a temporary object that is being immediately returned from a
/// function by value, eg. return t; or return T(123);. In this case there is
/// always going to be a constructor at the return site. However, the usual
/// temporary-related bureaucracy (CXXBindTemporaryExpr,
/// MaterializeTemporaryExpr) is normally located in the caller function's AST.
-class ReturnedValueConstructionContext : public ConstructionContext {
- const ReturnStmt *RS;
+class SimpleReturnedValueConstructionContext
+ : public ReturnedValueConstructionContext {
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
+ : ReturnedValueConstructionContext(
+ ConstructionContext::SimpleReturnedValueKind, RS) {}
public:
- explicit ReturnedValueConstructionContext(const ReturnStmt *RS)
- : ConstructionContext(ConstructionContext::ReturnedValueKind), RS(RS) {
- assert(RS);
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == SimpleReturnedValueKind;
+ }
+};
+
+/// Represents a temporary object that is being immediately returned from a
+/// function by value, eg. return t; or return T(123); in C++17.
+/// In C++17 there is not going to be an elidable copy constructor at the
+/// return site. However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr,
+/// MaterializeTemporaryExpr) is normally located in the caller function's AST.
+/// Note that if the object has trivial destructor, then this code is
+/// indistinguishable from a simple returned value constructor on the AST level;
+/// in this case we provide a simple returned value construction context.
+class CXX17ElidedCopyReturnedValueConstructionContext
+ : public ReturnedValueConstructionContext {
+ const CXXBindTemporaryExpr *BTE;
+
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit CXX17ElidedCopyReturnedValueConstructionContext(
+ const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
+ : ReturnedValueConstructionContext(
+ ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
+ BTE(BTE) {
+ assert(BTE);
}
- const ReturnStmt *getReturnStmt() const { return RS; }
+public:
+ const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
static bool classof(const ConstructionContext *CC) {
- return CC->getKind() == ReturnedValueKind;
+ return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
}
};
diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h
index 67019f6..286b033 100644
--- a/include/clang/Basic/AddressSpaces.h
+++ b/include/clang/Basic/AddressSpaces.h
@@ -1,4 +1,4 @@
-//===--- AddressSpaces.h - Language-specific address spaces -----*- C++ -*-===//
+//===- AddressSpaces.h - Language-specific address spaces -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,17 +6,17 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Provides definitions for the various language-specific address
/// spaces.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_ADDRESSSPACES_H
#define LLVM_CLANG_BASIC_ADDRESSSPACES_H
-#include <assert.h>
+#include <cassert>
namespace clang {
@@ -51,7 +51,7 @@
/// The type of a lookup table which maps from language-specific address spaces
/// to target-specific ones.
-typedef unsigned LangASMap[(unsigned)LangAS::FirstTargetAddressSpace];
+using LangASMap = unsigned[(unsigned)LangAS::FirstTargetAddressSpace];
/// \return whether \p AS is a target-specific address space rather than a
/// clang AST address space
@@ -71,4 +71,4 @@
} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_ADDRESSSPACES_H
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 92d1dd6..afbfd04 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -1889,7 +1889,7 @@
template<class Compare>
ParsedTargetAttr parse(Compare cmp) const {
ParsedTargetAttr Attrs = parse();
- std::sort(std::begin(Attrs.Features), std::end(Attrs.Features), cmp);
+ llvm::sort(std::begin(Attrs.Features), std::end(Attrs.Features), cmp);
return Attrs;
}
@@ -2122,6 +2122,12 @@
let Documentation = [AnyX86NoCallerSavedRegistersDocs];
}
+def AnyX86NoCfCheck : InheritableAttr, TargetSpecificAttr<TargetAnyX86>{
+ let Spellings = [GCC<"nocf_check">];
+ let Subjects = SubjectList<[FunctionLike]>;
+ let Documentation = [AnyX86NoCfCheckDocs];
+}
+
def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetAnyX86> {
let Spellings = [GCC<"force_align_arg_pointer">];
// Technically, this appertains to a FunctionDecl, but the target-specific
@@ -2773,6 +2779,14 @@
let Documentation = [Undocumented];
}
+def OMPReferencedVar : Attr {
+ // This attribute has no spellings as it is only ever created implicitly.
+ let Spellings = [];
+ let SemaHandler = 0;
+ let Args = [ExprArgument<"Ref">];
+ let Documentation = [Undocumented];
+}
+
def OMPDeclareSimdDecl : Attr {
let Spellings = [Pragma<"omp", "declare simd">];
let Subjects = SubjectList<[Function]>;
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
index 35c0cb3..03300b8 100644
--- a/include/clang/Basic/AttrDocs.td
+++ b/include/clang/Basic/AttrDocs.td
@@ -273,7 +273,7 @@
let Content = [{
The ``alloc_size`` attribute can be placed on functions that return pointers in
order to hint to the compiler how many bytes of memory will be available at the
-returned poiner. ``alloc_size`` takes one or two arguments.
+returned pointer. ``alloc_size`` takes one or two arguments.
- ``alloc_size(N)`` implies that argument number N equals the number of
available bytes at the returned pointer.
@@ -311,7 +311,7 @@
let Content = [{
Use ``__attribute__((alloc_align(<alignment>))`` on a function
declaration to specify that the return value of the function (which must be a
-pointer type) is at least as aligned as the value of the indicated parameter. The
+pointer type) is at least as aligned as the value of the indicated parameter. The
parameter is given by its index in the list of formal parameters; the first
parameter has index 1 unless the function is a C++ non-static member function,
in which case the first parameter has index 2 to account for the implicit ``this``
@@ -330,7 +330,7 @@
void *Foo::b(void *v, size_t align) __attribute__((alloc_align(3)));
Note that this attribute merely informs the compiler that a function always
-returns a sufficiently aligned pointer. It does not cause the compiler to
+returns a sufficiently aligned pointer. It does not cause the compiler to
emit code to enforce that alignment. The behavior is undefined if the returned
poitner is not sufficiently aligned.
}];
@@ -913,10 +913,10 @@
attribute allows annotated interfaces or protocols to use the
specified string argument in the object's metadata name instead of the
default name.
-
+
**Usage**: ``__attribute__((objc_runtime_name("MyLocalName")))``. This attribute
can only be placed before an @protocol or @interface declaration:
-
+
.. code-block:: objc
__attribute__((objc_runtime_name("MyLocalName")))
@@ -2626,7 +2626,7 @@
int fetch_or_zero(int * _Nullable ptr);
-a caller of ``fetch_or_zero`` can provide null.
+a caller of ``fetch_or_zero`` can provide null.
}];
}
@@ -2861,7 +2861,7 @@
caller-saved registers. That is, all registers are callee-saved except for
registers used for passing parameters to the function or returning parameters
from the function.
-The compiler saves and restores any modified registers that were not used for
+The compiler saves and restores any modified registers that were not used for
passing or returning arguments to the function.
The user can call functions specified with the 'no_caller_saved_registers'
@@ -2913,6 +2913,24 @@
}];
}
+def AnyX86NoCfCheckDocs : Documentation{
+ let Category = DocCatFunction;
+ let Content = [{
+Jump Oriented Programming attacks rely on tampering with addresses used by
+indirect call / jmp, e.g. redirect control-flow to non-programmer
+intended bytes in the binary.
+X86 Supports Indirect Branch Tracking (IBT) as part of Control-Flow
+Enforcement Technology (CET). IBT instruments ENDBR instructions used to
+specify valid targets of indirect call / jmp.
+The ``nocf_check`` attribute has two roles:
+1. Appertains to a function - do not add ENDBR instruction at the
+ beginning of the function.
+2. Appertains to a function pointer - do not track the target
+ function of this pointer (by adding nocf_check prefix to the
+ indirect-call instruction).
+}];
+}
+
def SwiftCallDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
@@ -3280,7 +3298,7 @@
let Content = [{
The ``artificial`` attribute can be applied to an inline function. If such a
function is inlined, the attribute indicates that debuggers should associate
-the resulting instructions with the call site, rather than with the
+the resulting instructions with the call site, rather than with the
corresponding line within the inlined callee.
}];
}
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 9b7e09a..36b72ba 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -1371,8 +1371,8 @@
// Clang builtins (not available in GCC).
BUILTIN(__builtin_addressof, "v*v&", "nct")
-BUILTIN(__builtin_operator_new, "v*z", "c")
-BUILTIN(__builtin_operator_delete, "vv*", "n")
+BUILTIN(__builtin_operator_new, "v*z", "tc")
+BUILTIN(__builtin_operator_delete, "vv*", "tn")
BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
// Safestack builtins
diff --git a/include/clang/Basic/BuiltinsHexagon.def b/include/clang/Basic/BuiltinsHexagon.def
index fda50b5..f976720 100644
--- a/include/clang/Basic/BuiltinsHexagon.def
+++ b/include/clang/Basic/BuiltinsHexagon.def
@@ -17,28 +17,51 @@
// The builtins below are not autogenerated from iset.py.
// Make sure you do not overwrite these.
-BUILTIN(__builtin_brev_ldd, "LLi*LLi*LLi*i", "")
-BUILTIN(__builtin_brev_ldw, "i*i*i*i", "")
-BUILTIN(__builtin_brev_ldh, "s*s*s*i", "")
-BUILTIN(__builtin_brev_lduh, "Us*Us*Us*i", "")
-BUILTIN(__builtin_brev_ldb, "c*c*c*i", "")
-BUILTIN(__builtin_brev_ldub, "Uc*Uc*Uc*i", "")
+BUILTIN(__builtin_brev_ldd, "v*LLi*CLLi*iC", "")
+BUILTIN(__builtin_brev_ldw, "v*i*Ci*iC", "")
+BUILTIN(__builtin_brev_ldh, "v*s*Cs*iC", "")
+BUILTIN(__builtin_brev_lduh, "v*Us*CUs*iC", "")
+BUILTIN(__builtin_brev_ldb, "v*Sc*CSc*iC", "")
+BUILTIN(__builtin_brev_ldub, "v*Uc*CUc*iC", "")
BUILTIN(__builtin_circ_ldd, "LLi*LLi*LLi*iIi", "")
BUILTIN(__builtin_circ_ldw, "i*i*i*iIi", "")
BUILTIN(__builtin_circ_ldh, "s*s*s*iIi", "")
BUILTIN(__builtin_circ_lduh, "Us*Us*Us*iIi", "")
BUILTIN(__builtin_circ_ldb, "c*c*c*iIi", "")
BUILTIN(__builtin_circ_ldub, "Uc*Uc*Uc*iIi", "")
-BUILTIN(__builtin_brev_std, "LLi*LLi*LLii", "")
-BUILTIN(__builtin_brev_stw, "i*i*ii", "")
-BUILTIN(__builtin_brev_sth, "s*s*ii", "")
-BUILTIN(__builtin_brev_sthhi, "s*s*ii", "")
-BUILTIN(__builtin_brev_stb, "c*c*ii", "")
+BUILTIN(__builtin_brev_std, "LLi*CLLi*LLiiC", "")
+BUILTIN(__builtin_brev_stw, "i*Ci*iiC", "")
+BUILTIN(__builtin_brev_sth, "s*Cs*iiC", "")
+BUILTIN(__builtin_brev_sthhi, "s*Cs*iiC", "")
+BUILTIN(__builtin_brev_stb, "c*Cc*iiC", "")
BUILTIN(__builtin_circ_std, "LLi*LLi*LLiiIi", "")
BUILTIN(__builtin_circ_stw, "i*i*iiIi", "")
BUILTIN(__builtin_circ_sth, "s*s*iiIi", "")
BUILTIN(__builtin_circ_sthhi, "s*s*iiIi", "")
BUILTIN(__builtin_circ_stb, "c*c*iiIi", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrub_pci, "iv*IiivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrb_pci, "iv*IiivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadruh_pci, "iv*IiivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrh_pci, "iv*IiivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadri_pci, "iv*IiivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrd_pci, "LLiv*IiivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrub_pcr, "iv*ivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrb_pcr, "iv*ivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadruh_pcr, "iv*ivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrh_pcr, "iv*ivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadri_pcr, "iv*ivC*", "")
+BUILTIN(__builtin_HEXAGON_L2_loadrd_pcr, "LLiv*ivC*", "")
+
+BUILTIN(__builtin_HEXAGON_S2_storerb_pci, "vv*IiiivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerh_pci, "vv*IiiivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerf_pci, "vv*IiiivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storeri_pci, "vv*IiiivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerd_pci, "vv*IiiLLivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerb_pcr, "vv*iivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerh_pcr, "vv*iivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerf_pcr, "vv*iivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storeri_pcr, "vv*iivC*", "")
+BUILTIN(__builtin_HEXAGON_S2_storerd_pcr, "vv*iLLivC*", "")
// The builtins above are not autogenerated from iset.py.
// Make sure you do not overwrite these.
diff --git a/include/clang/Basic/CharInfo.h b/include/clang/Basic/CharInfo.h
index cc27bbb..be49f36 100644
--- a/include/clang/Basic/CharInfo.h
+++ b/include/clang/Basic/CharInfo.h
@@ -180,14 +180,15 @@
/// Return true if this is a valid ASCII identifier.
///
-/// Note that this is a very simple check; it does not accept '$' or UCNs as
-/// valid identifier characters.
-LLVM_READONLY inline bool isValidIdentifier(StringRef S) {
- if (S.empty() || !isIdentifierHead(S[0]))
+/// Note that this is a very simple check; it does not accept UCNs as valid
+/// identifier characters.
+LLVM_READONLY inline bool isValidIdentifier(StringRef S,
+ bool AllowDollar = false) {
+ if (S.empty() || !isIdentifierHead(S[0], AllowDollar))
return false;
for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I)
- if (!isIdentifierBody(*I))
+ if (!isIdentifierBody(*I, AllowDollar))
return false;
return true;
diff --git a/include/clang/Basic/CommentOptions.h b/include/clang/Basic/CommentOptions.h
index 92419f9..efd94e6 100644
--- a/include/clang/Basic/CommentOptions.h
+++ b/include/clang/Basic/CommentOptions.h
@@ -1,4 +1,4 @@
-//===--- CommentOptions.h - Options for parsing comments -----*- C++ -*-===//
+//===- CommentOptions.h - Options for parsing comments ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the clang::CommentOptions interface.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_COMMENTOPTIONS_H
@@ -22,18 +22,18 @@
/// \brief Options for controlling comment parsing.
struct CommentOptions {
- typedef std::vector<std::string> BlockCommandNamesTy;
+ using BlockCommandNamesTy = std::vector<std::string>;
/// \brief Command names to treat as block commands in comments.
/// Should not include the leading backslash.
BlockCommandNamesTy BlockCommandNames;
/// \brief Treat ordinary comments as documentation comments.
- bool ParseAllComments;
+ bool ParseAllComments = false;
- CommentOptions() : ParseAllComments(false) { }
+ CommentOptions() = default;
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_COMMENTOPTIONS_H
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 182136f..ccc4db8 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -203,6 +203,9 @@
def warn_drv_omp_offload_target_duplicate : Warning<
"The OpenMP offloading target '%0' is similar to target '%1' already specified - will be ignored.">,
InGroup<OpenMPTarget>;
+def warn_drv_omp_offload_target_missingbcruntime : Warning<
+ "No library '%0' found in the default clang lib directory or in LIBRARY_PATH. Expect degraded performance due to no inlining of runtime functions on target devices.">,
+ InGroup<OpenMPTarget>;
def err_drv_bitcode_unsupported_on_toolchain : Error<
"-fembed-bitcode is not supported on versions of iOS prior to 6.0">;
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 2d471f1..0a3e563 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -151,8 +151,10 @@
def GNUEmptyInitializer : DiagGroup<"gnu-empty-initializer">;
def GNUEmptyStruct : DiagGroup<"gnu-empty-struct">;
def ExtraTokens : DiagGroup<"extra-tokens">;
+def CXX98CompatExtraSemi : DiagGroup<"c++98-compat-extra-semi">;
def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">;
-def ExtraSemi : DiagGroup<"extra-semi", [CXX11ExtraSemi]>;
+def ExtraSemi : DiagGroup<"extra-semi", [CXX98CompatExtraSemi,
+ CXX11ExtraSemi]>;
def GNUFlexibleArrayInitializer : DiagGroup<"gnu-flexible-array-initializer">;
def GNUFlexibleArrayUnionMember : DiagGroup<"gnu-flexible-array-union-member">;
@@ -196,6 +198,7 @@
def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic",
[CXX98Compat,
CXX98CompatBindToTemporaryCopy,
+ CXX98CompatExtraSemi,
CXXPre14CompatPedantic,
CXXPre17CompatPedantic,
CXXPre2aCompatPedantic]>;
@@ -512,8 +515,13 @@
def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes,
UninitializedStaticSelfInit]>;
def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">;
+// #pragma optimize is often used to avoid to work around MSVC codegen bugs or
+// to disable inlining. It's not completely clear what alternative to suggest
+// (#pragma clang optimize, noinline) so suggest nothing for now.
+def IgnoredPragmaOptimize : DiagGroup<"ignored-pragma-optimize">;
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
-def IgnoredPragmas : DiagGroup<"ignored-pragmas", [IgnoredPragmaIntrinsic]>;
+def IgnoredPragmas : DiagGroup<"ignored-pragmas",
+ [IgnoredPragmaIntrinsic, IgnoredPragmaOptimize]>;
def PragmaClangAttribute : DiagGroup<"pragma-clang-attribute">;
def PragmaPackSuspiciousInclude : DiagGroup<"pragma-pack-suspicious-include">;
def PragmaPack : DiagGroup<"pragma-pack", [PragmaPackSuspiciousInclude]>;
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index e60f3ae..cc4232f 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -39,7 +39,7 @@
InGroup<DiagGroup<"empty-translation-unit">>;
def warn_cxx98_compat_top_level_semi : Warning<
"extra ';' outside of a function is incompatible with C++98">,
- InGroup<CXX98CompatPedantic>, DefaultIgnore;
+ InGroup<CXX98CompatExtraSemi>, DefaultIgnore;
def ext_extra_semi : Extension<
"extra ';' %select{"
"outside of a function|"
@@ -575,7 +575,7 @@
def err_attribute_requires_arguments : Error<
"parentheses must be omitted if %0 attribute's argument list is empty">;
def err_cxx11_attribute_forbids_ellipsis : Error<
- "attribute '%0' cannot be used as an attribute pack">;
+ "attribute %0 cannot be used as an attribute pack">;
def err_cxx11_attribute_repeated : Error<
"attribute %0 cannot appear multiple times in an attribute specifier">;
def warn_cxx14_compat_using_attribute_ns : Warning<
@@ -895,6 +895,12 @@
"missing ')' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
def warn_pragma_expected_identifier : Warning<
"expected identifier in '#pragma %0' - ignored">, InGroup<IgnoredPragmas>;
+def warn_pragma_expected_string : Warning<
+ "expected string literal in '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
+def warn_pragma_missing_argument : Warning<
+ "missing argument to '#pragma %0'%select{|; expected %2}1">, InGroup<IgnoredPragmas>;
+def warn_pragma_invalid_argument : Warning<
+ "unexpected argument '%0' to '#pragma %1'%select{|; expected %3}2">, InGroup<IgnoredPragmas>;
// '#pragma clang section' related errors
def err_pragma_expected_clang_section_name : Error<
@@ -923,6 +929,8 @@
def warn_pragma_extra_tokens_at_eol : Warning<
"extra tokens at end of '#pragma %0' - ignored">,
InGroup<IgnoredPragmas>;
+def warn_pragma_expected_comma : Warning<
+ "expected ',' in '#pragma %0'">, InGroup<IgnoredPragmas>;
def warn_pragma_expected_punc : Warning<
"expected ')' or ',' in '#pragma %0'">, InGroup<IgnoredPragmas>;
def warn_pragma_expected_non_wide_string : Warning<
@@ -960,6 +968,10 @@
def warn_pragma_intrinsic_builtin : Warning<
"%0 is not a recognized builtin%select{|; consider including <intrin.h> to access non-builtin intrinsics}1">,
InGroup<IgnoredPragmaIntrinsic>;
+// - #pragma optimize
+def warn_pragma_optimize : Warning<
+ "'#pragma optimize' is not supported">,
+ InGroup<IgnoredPragmaOptimize>;
// - #pragma unused
def warn_pragma_unused_expected_var : Warning<
"expected '#pragma unused' argument to be a variable name">,
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index fd0b408..06ae1b7 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1329,7 +1329,7 @@
"nested class }0%1 is not permitted within an interface type">;
def err_invalid_base_in_interface : Error<
"interface type cannot inherit from "
- "%select{'struct|non-public 'interface|'class}0 %1'">;
+ "%select{struct|non-public interface|class}0 %1">;
def err_abstract_type_in_decl : Error<
"%select{return|parameter|variable|field|instance variable|"
@@ -1586,6 +1586,8 @@
"bit-field %0 has non-integral type %1">;
def err_not_integral_type_anon_bitfield : Error<
"anonymous bit-field has non-integral type %0">;
+def err_anon_bitfield_qualifiers : Error<
+ "anonymous bit-field cannot have qualifiers">;
def err_member_function_initialization : Error<
"initializer on function does not look like a pure-specifier">;
def err_non_virtual_pure : Error<
@@ -1627,7 +1629,7 @@
"%select{base class|member}2 %3 %select{which|which|of %1}0 "
"does not have a default constructor">;
def note_due_to_dllexported_class : Note<
- "due to '%0' being dllexported%select{|; try compiling in C++11 mode}1">;
+ "due to %0 being dllexported%select{|; try compiling in C++11 mode}1">;
def err_illegal_union_or_anon_struct_member : Error<
"%select{anonymous struct|union}0 member %1 has a non-trivial "
@@ -2691,6 +2693,9 @@
def warn_attribute_ignored_on_inline :
Warning<"%0 attribute ignored on inline function">,
InGroup<IgnoredAttributes>;
+def warn_nocf_check_attribute_ignored :
+ Warning<"'nocf_check' attribute ignored; use -fcf-protection to enable the attribute">,
+ InGroup<IgnoredAttributes>;
def warn_attribute_after_definition_ignored : Warning<
"attribute %0 after definition is ignored">,
InGroup<IgnoredAttributes>;
@@ -2981,11 +2986,11 @@
def note_lock_exclusive_and_shared : Note<
"the other acquisition of %0 '%1' is here">;
def warn_variable_requires_any_lock : Warning<
- "%select{reading|writing}1 variable '%0' requires holding "
+ "%select{reading|writing}1 variable %0 requires holding "
"%select{any mutex|any mutex exclusively}1">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_var_deref_requires_any_lock : Warning<
- "%select{reading|writing}1 the value pointed to by '%0' requires holding "
+ "%select{reading|writing}1 the value pointed to by %0 requires holding "
"%select{any mutex|any mutex exclusively}1">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_fun_excludes_mutex : Warning<
@@ -3009,25 +3014,25 @@
// Thread safety warnings on pass by reference
def warn_guarded_pass_by_reference : Warning<
- "passing variable '%1' by reference requires holding %0 "
+ "passing variable %1 by reference requires holding %0 "
"%select{'%2'|'%2' exclusively}3">,
InGroup<ThreadSafetyReference>, DefaultIgnore;
def warn_pt_guarded_pass_by_reference : Warning<
- "passing the value that '%1' points to by reference requires holding %0 "
+ "passing the value that %1 points to by reference requires holding %0 "
"%select{'%2'|'%2' exclusively}3">,
InGroup<ThreadSafetyReference>, DefaultIgnore;
// Imprecise thread safety warnings
def warn_variable_requires_lock : Warning<
- "%select{reading|writing}3 variable '%1' requires holding %0 "
+ "%select{reading|writing}3 variable %1 requires holding %0 "
"%select{'%2'|'%2' exclusively}3">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_var_deref_requires_lock : Warning<
- "%select{reading|writing}3 the value pointed to by '%1' requires "
+ "%select{reading|writing}3 the value pointed to by %1 requires "
"holding %0 %select{'%2'|'%2' exclusively}3">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_fun_requires_lock : Warning<
- "calling function '%1' requires holding %0 %select{'%2'|'%2' exclusively}3">,
+ "calling function %1 requires holding %0 %select{'%2'|'%2' exclusively}3">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
// Precise thread safety warnings
@@ -3045,7 +3050,7 @@
// Verbose thread safety warnings
def warn_thread_safety_verbose : Warning<"Thread safety verbose warning.">,
InGroup<ThreadSafetyVerbose>, DefaultIgnore;
-def note_thread_warning_in_fun : Note<"Thread warning in function '%0'">;
+def note_thread_warning_in_fun : Note<"Thread warning in function %0">;
def note_guarded_by_declared_here : Note<"Guarded_by declared here.">;
// Dummy warning that will trigger "beta" warnings from the analysis if enabled.
@@ -3093,6 +3098,9 @@
def warn_impcast_float_precision : Warning<
"implicit conversion loses floating-point precision: %0 to %1">,
InGroup<Conversion>, DefaultIgnore;
+def warn_impcast_float_result_precision : Warning<
+ "implicit conversion when assigning computation result loses floating-point precision: %0 to %1">,
+ InGroup<Conversion>, DefaultIgnore;
def warn_impcast_double_promotion : Warning<
"implicit conversion increases floating-point precision: %0 to %1">,
InGroup<DoublePromotion>, DefaultIgnore;
@@ -4141,42 +4149,20 @@
"explicit specialization declared here">;
def err_template_spec_decl_function_scope : Error<
"explicit specialization of %0 in function scope">;
-def err_template_spec_decl_class_scope : Error<
- "explicit specialization of %0 in class scope">;
def err_template_spec_decl_friend : Error<
"cannot declare an explicit specialization in a friend">;
-def err_template_spec_decl_out_of_scope_global : Error<
- "%select{class template|class template partial|variable template|"
- "variable template partial|function template|member function|"
- "static data member|member class|member enumeration}0 "
- "specialization of %1 must originally be declared in the global scope">;
-def err_template_spec_decl_out_of_scope : Error<
- "%select{class template|class template partial|variable template|"
- "variable template partial|function template|member "
- "function|static data member|member class|member enumeration}0 "
- "specialization of %1 must originally be declared in namespace %2">;
-def ext_template_spec_decl_out_of_scope : ExtWarn<
- "first declaration of %select{class template|class template partial|"
- "variable template|variable template partial|"
- "function template|member function|static data member|member class|"
- "member enumeration}0 specialization of %1 outside namespace %2 is a "
- "C++11 extension">, InGroup<CXX11>;
-def warn_cxx98_compat_template_spec_decl_out_of_scope : Warning<
- "%select{class template|class template partial|variable template|"
- "variable template partial|function template|member "
- "function|static data member|member class|member enumeration}0 "
- "specialization of %1 outside namespace %2 is incompatible with C++98">,
- InGroup<CXX98Compat>, DefaultIgnore;
def err_template_spec_redecl_out_of_scope : Error<
"%select{class template|class template partial|variable template|"
"variable template partial|function template|member "
"function|static data member|member class|member enumeration}0 "
- "specialization of %1 not in a namespace enclosing %2">;
+ "specialization of %1 not in %select{a namespace enclosing %2|"
+ "class %2 or an enclosing namespace}3">;
def ext_ms_template_spec_redecl_out_of_scope: ExtWarn<
"%select{class template|class template partial|variable template|"
"variable template partial|function template|member "
"function|static data member|member class|member enumeration}0 "
- "specialization of %1 outside namespace enclosing %2 "
+ "specialization of %1 not in %select{a namespace enclosing %2|"
+ "class %2 or an enclosing namespace}3 "
"is a Microsoft extension">, InGroup<MicrosoftTemplate>;
def err_template_spec_redecl_global_scope : Error<
"%select{class template|class template partial|variable template|"
@@ -4198,11 +4184,6 @@
def err_not_class_template_specialization : Error<
"cannot specialize a %select{dependent template|template template "
"parameter}0">;
-def err_function_specialization_in_class : Error<
- "cannot specialize a function %0 within class scope">;
-def ext_function_specialization_in_class : ExtWarn<
- "explicit specialization of %0 within class scope is a Microsoft extension">,
- InGroup<MicrosoftTemplate>;
def ext_explicit_specialization_storage_class : ExtWarn<
"explicit specialization cannot have a storage class">;
def err_explicit_specialization_inconsistent_storage_class : Error<
@@ -6205,9 +6186,9 @@
def err_incomplete_type_objc_at_encode : Error<
"'@encode' of incomplete type %0">;
def warn_objc_circular_container : Warning<
- "adding '%0' to '%1' might cause circular dependency in container">,
+ "adding %0 to %1 might cause circular dependency in container">,
InGroup<DiagGroup<"objc-circular-container">>;
-def note_objc_circular_container_declared_here : Note<"'%0' declared here">;
+def note_objc_circular_container_declared_here : Note<"%0 declared here">;
def warn_objc_unsafe_perform_selector : Warning<
"%0 is incompatible with selectors that return a "
"%select{struct|union|vector}1 type">,
@@ -7156,7 +7137,7 @@
"CUDA device code does not support va_arg">;
def err_alias_not_supported_on_nvptx : Error<"CUDA does not support aliases">;
def err_cuda_unattributed_constexpr_cannot_overload_device : Error<
- "constexpr function '%0' without __host__ or __device__ attributes cannot "
+ "constexpr function %0 without __host__ or __device__ attributes cannot "
"overload __device__ function with same signature. Add a __host__ "
"attribute, or build with -fno-cuda-host-device-constexpr.">;
def note_cuda_conflicting_device_function_declared_here : Note<
@@ -7646,6 +7627,11 @@
"alignment parameter">;
def note_implicit_delete_this_in_destructor_here : Note<
"while checking implicit 'delete this' for virtual destructor">;
+def err_builtin_operator_new_delete_not_usual : Error<
+ "call to '%select{__builtin_operator_new|__builtin_operator_delete}0' "
+ "selects non-usual %select{allocation|deallocation}0 function">;
+def note_non_usual_function_declared_here : Note<
+ "non-usual %0 declared here">;
// C++ literal operators
def err_literal_operator_outside_namespace : Error<
@@ -9350,7 +9336,8 @@
InGroup<GccCompat>;
def warn_shadow_field :
- Warning<"non-static data member '%0' of '%1' shadows member inherited from type '%2'">,
+ Warning<"non-static data member %0 of %1 shadows member inherited from "
+ "type %2">,
InGroup<ShadowField>, DefaultIgnore;
def note_shadow_field : Note<"declared here">;
diff --git a/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h
index 75f986b..7bd2267 100644
--- a/include/clang/Basic/FileSystemStatCache.h
+++ b/include/clang/Basic/FileSystemStatCache.h
@@ -1,4 +1,4 @@
-//===--- FileSystemStatCache.h - Caching for 'stat' calls -------*- C++ -*-===//
+//===- FileSystemStatCache.h - Caching for 'stat' calls ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the FileSystemStatCache interface.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_FILESYSTEMSTATCACHE_H
@@ -17,29 +17,38 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/FileSystem.h"
+#include <cstdint>
+#include <ctime>
#include <memory>
+#include <string>
+#include <utility>
namespace clang {
namespace vfs {
+
class File;
class FileSystem;
-}
+
+} // namespace vfs
// FIXME: should probably replace this with vfs::Status
struct FileData {
std::string Name;
- uint64_t Size;
- time_t ModTime;
+ uint64_t Size = 0;
+ time_t ModTime = 0;
llvm::sys::fs::UniqueID UniqueID;
- bool IsDirectory;
- bool IsNamedPipe;
- bool InPCH;
- bool IsVFSMapped; // FIXME: remove this when files support multiple names
- FileData()
- : Size(0), ModTime(0), IsDirectory(false), IsNamedPipe(false),
- InPCH(false), IsVFSMapped(false) {}
+ bool IsDirectory = false;
+ bool IsNamedPipe = false;
+ bool InPCH = false;
+
+ // FIXME: remove this when files support multiple names
+ bool IsVFSMapped = false;
+
+ FileData() = default;
};
/// \brief Abstract interface for introducing a FileManager cache for 'stat'
@@ -47,15 +56,19 @@
/// improve performance.
class FileSystemStatCache {
virtual void anchor();
+
protected:
std::unique_ptr<FileSystemStatCache> NextStatCache;
public:
- virtual ~FileSystemStatCache() {}
+ virtual ~FileSystemStatCache() = default;
enum LookupResult {
- CacheExists, ///< We know the file exists and its cached stat data.
- CacheMissing ///< We know that the file doesn't exist.
+ /// We know the file exists and its cached stat data.
+ CacheExists,
+
+ /// We know that the file doesn't exist.
+ CacheMissing
};
/// \brief Get the 'stat' information for the specified path, using the cache
@@ -115,8 +128,8 @@
/// \brief The set of stat() calls that have been seen.
llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls;
- typedef llvm::StringMap<FileData, llvm::BumpPtrAllocator>::const_iterator
- iterator;
+ using iterator =
+ llvm::StringMap<FileData, llvm::BumpPtrAllocator>::const_iterator;
iterator begin() const { return StatCalls.begin(); }
iterator end() const { return StatCalls.end(); }
@@ -126,6 +139,6 @@
vfs::FileSystem &FS) override;
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_FILESYSTEMSTATCACHE_H
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index 68edee2..0802bbe 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -236,6 +236,7 @@
LANGOPT(ObjCWeakRuntime , 1, 0, "__weak support in the ARC runtime")
LANGOPT(ObjCWeak , 1, 0, "Objective-C __weak in ARC and MRC files")
LANGOPT(ObjCSubscriptingLegacyRuntime , 1, 0, "Subscripting support in legacy ObjectiveC runtime")
+LANGOPT(CFProtectionBranch , 1, 0, "Control-Flow Branch Protection enabled")
LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")
LANGOPT(IncludeDefaultHeader, 1, 0, "Include default header file for OpenCL")
@@ -283,6 +284,10 @@
BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0,
"allow editor placeholders in source")
+ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest,
+ "version of Clang that we should attempt to be ABI-compatible "
+ "with")
+
#undef LANGOPT
#undef COMPATIBLE_LANGOPT
#undef BENIGN_LANGOPT
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index b16392d..048ccc6 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -102,6 +102,23 @@
MSVC2015 = 19
};
+ /// Clang versions with different platform ABI conformance.
+ enum class ClangABI {
+ /// Attempt to be ABI-compatible with code generated by Clang 3.8.x
+ /// (SVN r257626). This causes <1 x long long> to be passed in an
+ /// integer register instead of an SSE register on x64_64.
+ Ver3_8,
+
+ /// Attempt to be ABI-compatible with code generated by Clang 4.0.x
+ /// (SVN r291814). This causes move operations to be ignored when
+ /// determining whether a class type can be passed or returned directly.
+ Ver4,
+
+ /// Conform to the underlying platform's C and C++ ABIs as closely
+ /// as we can.
+ Latest
+ };
+
enum FPContractModeKind {
// Form fused FP ops only where result will not be affected.
FPC_Off,
@@ -141,10 +158,14 @@
/// If none is specified, abort (GCC-compatible behaviour).
std::string OverflowHandler;
+ /// The module currently being compiled as speficied by -fmodule-name.
+ std::string ModuleName;
+
/// \brief The name of the current module, of which the main source file
/// is a part. If CompilingModule is set, we are compiling the interface
/// of this module, otherwise we are compiling an implementation file of
- /// it.
+ /// it. This starts as ModuleName in case -fmodule-name is provided and
+ /// changes during compilation to reflect the current module.
std::string CurrentModule;
/// \brief The names of any features to enable in module 'requires' decls
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
index 6ec8763..adf1d08 100644
--- a/include/clang/Basic/Linkage.h
+++ b/include/clang/Basic/Linkage.h
@@ -1,4 +1,4 @@
-//===--- Linkage.h - Linkage enumeration and utilities ----------*- C++ -*-===//
+//===- Linkage.h - Linkage enumeration and utilities ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,16 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the Linkage enumeration and various utility functions.
-///
+//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_BASIC_LINKAGE_H
#define LLVM_CLANG_BASIC_LINKAGE_H
-#include <assert.h>
-#include <stdint.h>
#include <utility>
namespace clang {
@@ -125,6 +124,6 @@
return L1 < L2 ? L1 : L2;
}
-} // end namespace clang
+} // namespace clang
#endif // LLVM_CLANG_BASIC_LINKAGE_H
diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h
index 3926c0c..c41803c 100644
--- a/include/clang/Basic/ObjCRuntime.h
+++ b/include/clang/Basic/ObjCRuntime.h
@@ -1,4 +1,4 @@
-//===--- ObjCRuntime.h - Objective-C Runtime Configuration ------*- C++ -*-===//
+//===- ObjCRuntime.h - Objective-C Runtime Configuration --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,18 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines types useful for describing an Objective-C runtime.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_OBJCRUNTIME_H
#define LLVM_CLANG_BASIC_OBJCRUNTIME_H
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/VersionTuple.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ErrorHandling.h"
+#include <string>
namespace clang {
@@ -57,15 +60,14 @@
};
private:
- Kind TheKind;
+ Kind TheKind = MacOSX;
VersionTuple Version;
public:
/// A bogus initialization of the runtime.
- ObjCRuntime() : TheKind(MacOSX) {}
-
+ ObjCRuntime() = default;
ObjCRuntime(Kind kind, const VersionTuple &version)
- : TheKind(kind), Version(version) {}
+ : TheKind(kind), Version(version) {}
void set(Kind kind, VersionTuple version) {
TheKind = kind;
@@ -182,9 +184,8 @@
return true;
case GNUstep:
return getVersion() >= VersionTuple(1, 7);
-
default:
- return false;
+ return false;
}
}
@@ -320,7 +321,6 @@
return getVersion() >= VersionTuple(2);
case GNUstep:
return false;
-
default:
return false;
}
@@ -360,6 +360,6 @@
raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value);
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_OBJCRUNTIME_H
diff --git a/include/clang/Basic/Sanitizers.h b/include/clang/Basic/Sanitizers.h
index 1b936c7..fad22b2 100644
--- a/include/clang/Basic/Sanitizers.h
+++ b/include/clang/Basic/Sanitizers.h
@@ -1,4 +1,4 @@
-//===--- Sanitizers.h - C Language Family Language Options ------*- C++ -*-===//
+//===- Sanitizers.h - C Language Family Language Options --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,10 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
+//
/// \file
/// \brief Defines the clang::SanitizerKind enum.
-///
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_SANITIZERS_H
@@ -18,10 +18,12 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <cstdint>
namespace clang {
-typedef uint64_t SanitizerMask;
+using SanitizerMask = uint64_t;
namespace SanitizerKind {
@@ -43,7 +45,7 @@
const SanitizerMask ID##Group = 1ULL << SO_##ID##Group;
#include "clang/Basic/Sanitizers.def"
-}
+} // namespace SanitizerKind
struct SanitizerSet {
/// \brief Check if a certain (single) sanitizer is enabled.
@@ -85,6 +87,6 @@
SanitizerKind::Nullability | SanitizerKind::Undefined;
}
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_SANITIZERS_H
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index 377534b..c5d2e26 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -231,23 +231,24 @@
/// \brief CallingConv - Specifies the calling convention that a function uses.
enum CallingConv {
- CC_C, // __attribute__((cdecl))
- CC_X86StdCall, // __attribute__((stdcall))
- CC_X86FastCall, // __attribute__((fastcall))
- CC_X86ThisCall, // __attribute__((thiscall))
+ CC_C, // __attribute__((cdecl))
+ CC_X86StdCall, // __attribute__((stdcall))
+ CC_X86FastCall, // __attribute__((fastcall))
+ CC_X86ThisCall, // __attribute__((thiscall))
CC_X86VectorCall, // __attribute__((vectorcall))
- CC_X86Pascal, // __attribute__((pascal))
- CC_Win64, // __attribute__((ms_abi))
- CC_X86_64SysV, // __attribute__((sysv_abi))
- CC_X86RegCall, // __attribute__((regcall))
- CC_AAPCS, // __attribute__((pcs("aapcs")))
- CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
- CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
- CC_SpirFunction, // default for OpenCL functions on SPIR target
- CC_OpenCLKernel, // inferred for OpenCL kernels
- CC_Swift, // __attribute__((swiftcall))
- CC_PreserveMost, // __attribute__((preserve_most))
- CC_PreserveAll, // __attribute__((preserve_all))
+ CC_X86Pascal, // __attribute__((pascal))
+ CC_Win64, // __attribute__((ms_abi))
+ CC_X86_64SysV, // __attribute__((sysv_abi))
+ CC_X86RegCall, // __attribute__((regcall))
+ CC_AAPCS, // __attribute__((pcs("aapcs")))
+ CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
+ CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
+ CC_SpirFunction, // default for OpenCL functions on SPIR target
+ CC_OpenCLKernel, // inferred for OpenCL kernels
+ CC_Swift, // __attribute__((swiftcall))
+ CC_PreserveMost, // __attribute__((preserve_most))
+ CC_PreserveAll, // __attribute__((preserve_all))
+ CC_CUDAKernel, // inferred for CUDA kernels
};
/// \brief Checks whether the given calling convention supports variadic
diff --git a/include/clang/Basic/TargetCXXABI.h b/include/clang/Basic/TargetCXXABI.h
index 7fb1f82..074f07c 100644
--- a/include/clang/Basic/TargetCXXABI.h
+++ b/include/clang/Basic/TargetCXXABI.h
@@ -199,13 +199,6 @@
llvm_unreachable("bad ABI kind");
}
- /// \brief Is the default C++ member function calling convention
- /// the same as the default calling convention?
- bool isMemberFunctionCCDefault() const {
- // Right now, this is always false for Microsoft.
- return !isMicrosoft();
- }
-
/// Are arguments to a call destroyed left to right in the callee?
/// This is a fundamental language change, since it implies that objects
/// passed by value do *not* live to the end of the full expression.
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 96e51c9..26f72a1 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -61,6 +61,8 @@
bool TLSSupported;
bool VLASupported;
bool NoAsmVariants; // True if {|} are normal characters.
+ bool HasLegalHalfType; // True if the backend supports operations on the half
+ // LLVM IR type.
bool HasFloat128;
unsigned char PointerWidth, PointerAlign;
unsigned char BoolWidth, BoolAlign;
@@ -361,6 +363,9 @@
return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128;
} // FIXME
+ /// \brief Determine whether _Float16 is supported on this target.
+ virtual bool hasLegalHalfType() const { return HasLegalHalfType; }
+
/// \brief Determine whether the __float128 type is supported on this target.
virtual bool hasFloat128Type() const { return HasFloat128; }
@@ -1048,6 +1053,14 @@
}
}
+ enum CallingConvKind {
+ CCK_Default,
+ CCK_ClangABI4OrPS4,
+ CCK_MicrosoftX86_64
+ };
+
+ virtual CallingConvKind getCallingConvKind(bool ClangABICompat4) const;
+
/// Controls if __builtin_longjmp / __builtin_setjmp can be lowered to
/// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp.
virtual bool hasSjLjLowering() const {
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index f18e06f..56f3a69 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -433,12 +433,12 @@
TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX)
TYPE_TRAIT_1(__has_nothrow_copy, HasNothrowCopy, KEYCXX)
TYPE_TRAIT_1(__has_nothrow_constructor, HasNothrowConstructor, KEYCXX)
-TYPE_TRAIT_1(__has_trivial_assign, HasTrivialAssign, KEYCXX)
-TYPE_TRAIT_1(__has_trivial_move_assign, HasTrivialMoveAssign, KEYCXX)
-TYPE_TRAIT_1(__has_trivial_copy, HasTrivialCopy, KEYCXX)
-TYPE_TRAIT_1(__has_trivial_constructor, HasTrivialDefaultConstructor, KEYCXX)
-TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX)
-TYPE_TRAIT_1(__has_trivial_destructor, HasTrivialDestructor, KEYCXX)
+TYPE_TRAIT_1(__has_trivial_assign, HasTrivialAssign, KEYALL)
+TYPE_TRAIT_1(__has_trivial_move_assign, HasTrivialMoveAssign, KEYALL)
+TYPE_TRAIT_1(__has_trivial_copy, HasTrivialCopy, KEYALL)
+TYPE_TRAIT_1(__has_trivial_constructor, HasTrivialDefaultConstructor, KEYALL)
+TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYALL)
+TYPE_TRAIT_1(__has_trivial_destructor, HasTrivialDestructor, KEYALL)
TYPE_TRAIT_1(__has_virtual_destructor, HasVirtualDestructor, KEYCXX)
TYPE_TRAIT_1(__is_abstract, IsAbstract, KEYCXX)
TYPE_TRAIT_1(__is_aggregate, IsAggregate, KEYCXX)
diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h
index 245452d..ec7cd6f 100644
--- a/include/clang/Basic/VirtualFileSystem.h
+++ b/include/clang/Basic/VirtualFileSystem.h
@@ -6,8 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
/// \file
/// \brief Defines the virtual file system interface vfs::FileSystem.
+//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
@@ -15,6 +17,7 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -23,8 +26,6 @@
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
#include <cassert>
#include <cstdint>
#include <ctime>
@@ -39,7 +40,7 @@
class MemoryBuffer;
-} // end namespace llvm
+} // namespace llvm
namespace clang {
namespace vfs {
@@ -52,14 +53,14 @@
uint32_t User;
uint32_t Group;
uint64_t Size;
- llvm::sys::fs::file_type Type;
+ llvm::sys::fs::file_type Type = llvm::sys::fs::file_type::status_error;
llvm::sys::fs::perms Perms;
public:
- bool IsVFSMapped; // FIXME: remove when files support multiple names
+ // FIXME: remove when files support multiple names
+ bool IsVFSMapped = false;
-public:
- Status() : Type(llvm::sys::fs::file_type::status_error) {}
+ Status() = default;
Status(const llvm::sys::fs::file_status &Status);
Status(StringRef Name, llvm::sys::fs::UniqueID UID,
llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group,
@@ -139,7 +140,7 @@
Status CurrentEntry;
};
-} // end namespace detail
+} // namespace detail
/// \brief An input iterator over the entries in a virtual path, similar to
/// llvm::sys::fs::directory_iterator.
@@ -184,8 +185,8 @@
/// \brief An input iterator over the recursive contents of a virtual path,
/// similar to llvm::sys::fs::recursive_directory_iterator.
class recursive_directory_iterator {
- typedef std::stack<directory_iterator, std::vector<directory_iterator>>
- IterState;
+ using IterState =
+ std::stack<directory_iterator, std::vector<directory_iterator>>;
FileSystem *FS;
std::shared_ptr<IterState> State; // Input iterator semantics on copy.
@@ -193,6 +194,7 @@
public:
recursive_directory_iterator(FileSystem &FS, const Twine &Path,
std::error_code &EC);
+
/// \brief Construct an 'end' iterator.
recursive_directory_iterator() = default;
@@ -211,7 +213,7 @@
/// \brief Gets the current level. Starting path is at level 0.
int level() const {
- assert(State->size() && "Cannot get level without any iteration state");
+ assert(!State->empty() && "Cannot get level without any iteration state");
return State->size()-1;
}
};
@@ -223,6 +225,7 @@
/// \brief Get the status of the entry at \p Path, if one exists.
virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0;
+
/// \brief Get a \p File object for the file at \p Path, if one exists.
virtual llvm::ErrorOr<std::unique_ptr<File>>
openFileForRead(const Twine &Path) = 0;
@@ -241,6 +244,7 @@
/// Set the working directory. This will affect all following operations on
/// this file system and may propagate down for nested file systems.
virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) = 0;
+
/// Get the working directory of this file system.
virtual llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const = 0;
@@ -276,13 +280,15 @@
/// that exists in more than one file system, the file in the top-most file
/// system overrides the other(s).
class OverlayFileSystem : public FileSystem {
- typedef SmallVector<IntrusiveRefCntPtr<FileSystem>, 1> FileSystemList;
+ using FileSystemList = SmallVector<IntrusiveRefCntPtr<FileSystem>, 1>;
+
/// \brief The stack of file systems, implemented as a list in order of
/// their addition.
FileSystemList FSList;
public:
OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> Base);
+
/// \brief Pushes a file system on top of the stack.
void pushOverlay(IntrusiveRefCntPtr<FileSystem> FS);
@@ -293,7 +299,7 @@
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
- typedef FileSystemList::reverse_iterator iterator;
+ using iterator = FileSystemList::reverse_iterator;
/// \brief Get an iterator pointing to the most recently added file system.
iterator overlays_begin() { return FSList.rbegin(); }
@@ -307,7 +313,7 @@
class InMemoryDirectory;
-} // end namespace detail
+} // namespace detail
/// An in-memory file system.
class InMemoryFileSystem : public FileSystem {
@@ -330,6 +336,7 @@
Optional<uint32_t> User = None, Optional<uint32_t> Group = None,
Optional<llvm::sys::fs::file_type> Type = None,
Optional<llvm::sys::fs::perms> Perms = None);
+
/// Add a buffer to the VFS with a path. The VFS does not own the buffer.
/// If present, User, Group, Type and Perms apply to the newly-created file
/// or directory.
@@ -344,6 +351,7 @@
Optional<llvm::sys::fs::perms> Perms = None);
std::string toString() const;
+
/// Return true if this file system normalizes . and .. in paths.
bool useNormalizedPaths() const { return UseNormalizedPaths; }
@@ -351,9 +359,11 @@
llvm::ErrorOr<std::unique_ptr<File>>
openFileForRead(const Twine &Path) override;
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
+
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
return WorkingDirectory;
}
+
std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
};
@@ -419,7 +429,7 @@
void write(llvm::raw_ostream &OS);
};
-} // end namespace vfs
-} // end namespace clang
+} // namespace vfs
+} // namespace clang
#endif // LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td
index 37aac58..28a763c 100644
--- a/include/clang/Basic/arm_neon.td
+++ b/include/clang/Basic/arm_neon.td
@@ -1363,8 +1363,8 @@
def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "sji", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
}
-// ARMv8.2-A FP16 intrinsics.
-let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarch64__)" in {
+// ARMv8.2-A FP16 vector intrinsics for A32/A64.
+let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in {
// ARMv8.2-A FP16 one-operand vector intrinsics.
@@ -1395,14 +1395,12 @@
def FRINTPH : SInst<"vrndp", "dd", "hQh">;
def FRINTMH : SInst<"vrndm", "dd", "hQh">;
def FRINTXH : SInst<"vrndx", "dd", "hQh">;
- def FRINTIH : SInst<"vrndi", "dd", "hQh">;
// Misc.
def VABSH : SInst<"vabs", "dd", "hQh">;
def VNEGH : SOpInst<"vneg", "dd", "hQh", OP_NEG>;
def VRECPEH : SInst<"vrecpe", "dd", "hQh">;
def FRSQRTEH : SInst<"vrsqrte", "dd", "hQh">;
- def FSQRTH : SInst<"vsqrt", "dd", "hQh">;
// ARMv8.2-A FP16 two-operands vector intrinsics.
@@ -1443,18 +1441,13 @@
// Multiplication/Division
def VMULH : SOpInst<"vmul", "ddd", "hQh", OP_MUL>;
- def MULXH : SInst<"vmulx", "ddd", "hQh">;
- def FDIVH : IOpInst<"vdiv", "ddd", "hQh", OP_DIV>;
// Pairwise addition
- def VPADDH : SInst<"vpadd", "ddd", "hQh">;
+ def VPADDH : SInst<"vpadd", "ddd", "h">;
// Pairwise Max/Min
- def VPMAXH : SInst<"vpmax", "ddd", "hQh">;
- def VPMINH : SInst<"vpmin", "ddd", "hQh">;
- // Pairwise MaxNum/MinNum
- def FMAXNMPH : SInst<"vpmaxnm", "ddd", "hQh">;
- def FMINNMPH : SInst<"vpminnm", "ddd", "hQh">;
+ def VPMAXH : SInst<"vpmax", "ddd", "h">;
+ def VPMINH : SInst<"vpmin", "ddd", "h">;
// Reciprocal/Sqrt
def VRECPSH : SInst<"vrecps", "ddd", "hQh">;
@@ -1468,6 +1461,63 @@
// ARMv8.2-A FP16 lane vector intrinsics.
+ // Mul lane
+ def VMUL_LANEH : IOpInst<"vmul_lane", "ddgi", "hQh", OP_MUL_LN>;
+ def VMUL_NH : IOpInst<"vmul_n", "dds", "hQh", OP_MUL_N>;
+
+ // Data processing intrinsics - section 5
+
+ // Logical operations
+ let isHiddenLInst = 1 in
+ def VBSLH : SInst<"vbsl", "dudd", "hQh">;
+
+ // Transposition operations
+ def VZIPH : WInst<"vzip", "2dd", "hQh">;
+ def VUZPH : WInst<"vuzp", "2dd", "hQh">;
+ def VTRNH : WInst<"vtrn", "2dd", "hQh">;
+
+
+ let ArchGuard = "!defined(__aarch64__)" in {
+ // Set all lanes to same value.
+ // Already implemented prior to ARMv8.2-A.
+ def VMOV_NH : WOpInst<"vmov_n", "ds", "hQh", OP_DUP>;
+ def VDUP_NH : WOpInst<"vdup_n", "ds", "hQh", OP_DUP>;
+ def VDUP_LANE1H : WOpInst<"vdup_lane", "dgi", "hQh", OP_DUP_LN>;
+ }
+
+ // Vector Extract
+ def VEXTH : WInst<"vext", "dddi", "hQh">;
+
+ // Reverse vector elements
+ def VREV64H : WOpInst<"vrev64", "dd", "hQh", OP_REV64>;
+}
+
+// ARMv8.2-A FP16 vector intrinsics for A64 only.
+let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarch64__)" in {
+
+ // Vector rounding
+ def FRINTIH : SInst<"vrndi", "dd", "hQh">;
+
+ // Misc.
+ def FSQRTH : SInst<"vsqrt", "dd", "hQh">;
+
+ // Multiplication/Division
+ def MULXH : SInst<"vmulx", "ddd", "hQh">;
+ def FDIVH : IOpInst<"vdiv", "ddd", "hQh", OP_DIV>;
+
+ // Pairwise addition
+ def VPADDH1 : SInst<"vpadd", "ddd", "Qh">;
+
+ // Pairwise Max/Min
+ def VPMAXH1 : SInst<"vpmax", "ddd", "Qh">;
+ def VPMINH1 : SInst<"vpmin", "ddd", "Qh">;
+
+ // Pairwise MaxNum/MinNum
+ def FMAXNMPH : SInst<"vpmaxnm", "ddd", "hQh">;
+ def FMINNMPH : SInst<"vpminnm", "ddd", "hQh">;
+
+ // ARMv8.2-A FP16 lane vector intrinsics.
+
// FMA lane
def VFMA_LANEH : IInst<"vfma_lane", "dddgi", "hQh">;
def VFMA_LANEQH : IInst<"vfma_laneq", "dddji", "hQh">;
@@ -1488,9 +1538,7 @@
def SCALAR_FMLS_LANEQH : IOpInst<"vfms_laneq", "sssji", "Sh", OP_FMS_LNQ>;
// Mul lane
- def VMUL_LANEH : IOpInst<"vmul_lane", "ddgi", "hQh", OP_MUL_LN>;
def VMUL_LANEQH : IOpInst<"vmul_laneq", "ddji", "hQh", OP_MUL_LN>;
- def VMUL_NH : IOpInst<"vmul_n", "dds", "hQh", OP_MUL_N>;
// Scalar floating point multiply (scalar, by element)
def SCALAR_FMUL_LANEH : IOpInst<"vmul_lane", "ssdi", "Sh", OP_SCALAR_MUL_LN>;
def SCALAR_FMUL_LANEQH : IOpInst<"vmul_laneq", "ssji", "Sh", OP_SCALAR_MUL_LN>;
@@ -1499,11 +1547,9 @@
def VMULX_LANEH : IOpInst<"vmulx_lane", "ddgi", "hQh", OP_MULX_LN>;
def VMULX_LANEQH : IOpInst<"vmulx_laneq", "ddji", "hQh", OP_MULX_LN>;
def VMULX_NH : IOpInst<"vmulx_n", "dds", "hQh", OP_MULX_N>;
- // TODO: Scalar floating point multiply extended (scalar, by element)
- // Below ones are commented out because they need vmulx_f16(float16_t, float16_t)
- // which will be implemented later with fp16 scalar intrinsic (arm_fp16.h)
- //def SCALAR_FMULX_LANEH : IOpInst<"vmulx_lane", "ssdi", "Sh", OP_SCALAR_MUL_LN>;
- //def SCALAR_FMULX_LANEQH : IOpInst<"vmulx_laneq", "ssji", "Sh", OP_SCALAR_MUL_LN>;
+ // Scalar floating point mulx (scalar, by element)
+ def SCALAR_FMULX_LANEH : IInst<"vmulx_lane", "ssdi", "Sh">;
+ def SCALAR_FMULX_LANEQH : IInst<"vmulx_laneq", "ssji", "Sh">;
// ARMv8.2-A FP16 reduction vector intrinsics.
def VMAXVH : SInst<"vmaxv", "sd", "hQh">;
@@ -1511,29 +1557,6 @@
def FMAXNMVH : SInst<"vmaxnmv", "sd", "hQh">;
def FMINNMVH : SInst<"vminnmv", "sd", "hQh">;
- // Data processing intrinsics - section 5
-
- // Logical operations
- let isHiddenLInst = 1 in
- def VBSLH : SInst<"vbsl", "dudd", "hQh">;
-
- // Transposition operations
- def VZIPH : WInst<"vzip", "2dd", "hQh">;
- def VUZPH : WInst<"vuzp", "2dd", "hQh">;
- def VTRNH : WInst<"vtrn", "2dd", "hQh">;
-
- // Set all lanes to same value.
- /* Already implemented prior to ARMv8.2-A.
- def VMOV_NH : WOpInst<"vmov_n", "ds", "hQh", OP_DUP>;
- def VDUP_NH : WOpInst<"vdup_n", "ds", "hQh", OP_DUP>;
- def VDUP_LANE1H : WOpInst<"vdup_lane", "dgi", "hQh", OP_DUP_LN>;*/
-
- // Vector Extract
- def VEXTH : WInst<"vext", "dddi", "hQh">;
-
- // Reverse vector elements
- def VREV64H : WOpInst<"vrev64", "dd", "hQh", OP_REV64>;
-
// Permutation
def VTRN1H : SOpInst<"vtrn1", "ddd", "hQh", OP_TRN1>;
def VZIP1H : SOpInst<"vzip1", "ddd", "hQh", OP_ZIP1>;
diff --git a/include/clang/CodeGen/CGFunctionInfo.h b/include/clang/CodeGen/CGFunctionInfo.h
index 42f963b..d6f9908 100644
--- a/include/clang/CodeGen/CGFunctionInfo.h
+++ b/include/clang/CodeGen/CGFunctionInfo.h
@@ -494,7 +494,7 @@
unsigned EffectiveCallingConvention : 8;
/// The clang::CallingConv that this was originally created with.
- unsigned ASTCallingConvention : 7;
+ unsigned ASTCallingConvention : 6;
/// Whether this is an instance method.
unsigned InstanceMethod : 1;
@@ -515,6 +515,9 @@
unsigned HasRegParm : 1;
unsigned RegParm : 3;
+ /// Whether this function has nocf_check attribute.
+ unsigned NoCfCheck : 1;
+
RequiredArgs Required;
/// The struct representing all arguments passed in memory. Only used when
@@ -599,6 +602,9 @@
/// Whether this function no longer saves caller registers.
bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; }
+ /// Whether this function has nocf_check attribute.
+ bool isNoCfCheck() const { return NoCfCheck; }
+
/// getASTCallingConvention() - Return the AST-specified calling
/// convention.
CallingConv getASTCallingConvention() const {
@@ -624,7 +630,7 @@
FunctionType::ExtInfo getExtInfo() const {
return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(),
getASTCallingConvention(), isReturnsRetained(),
- isNoCallerSavedRegs());
+ isNoCallerSavedRegs(), isNoCfCheck());
}
CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
@@ -664,6 +670,7 @@
ID.AddBoolean(NoCallerSavedRegs);
ID.AddBoolean(HasRegParm);
ID.AddInteger(RegParm);
+ ID.AddBoolean(NoCfCheck);
ID.AddInteger(Required.getOpaqueData());
ID.AddBoolean(HasExtParameterInfos);
if (HasExtParameterInfos) {
@@ -690,6 +697,7 @@
ID.AddBoolean(info.getNoCallerSavedRegs());
ID.AddBoolean(info.getHasRegParm());
ID.AddInteger(info.getRegParm());
+ ID.AddBoolean(info.getNoCfCheck());
ID.AddInteger(required.getOpaqueData());
ID.AddBoolean(!paramInfos.empty());
if (!paramInfos.empty()) {
diff --git a/include/clang/Config/config.h.cmake b/include/clang/Config/config.h.cmake
index 5f42019..5822619 100644
--- a/include/clang/Config/config.h.cmake
+++ b/include/clang/Config/config.h.cmake
@@ -11,6 +11,12 @@
/* Default linker to use. */
#define CLANG_DEFAULT_LINKER "${CLANG_DEFAULT_LINKER}"
+/* Default C/ObjC standard to use. */
+#cmakedefine CLANG_DEFAULT_STD_C LangStandard::lang_${CLANG_DEFAULT_STD_C}
+
+/* Default C++/ObjC++ standard to use. */
+#cmakedefine CLANG_DEFAULT_STD_CXX LangStandard::lang_${CLANG_DEFAULT_STD_CXX}
+
/* Default C++ stdlib to use. */
#define CLANG_DEFAULT_CXX_STDLIB "${CLANG_DEFAULT_CXX_STDLIB}"
diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h
index 72456d3..4922817 100644
--- a/include/clang/Driver/Action.h
+++ b/include/clang/Driver/Action.h
@@ -1,4 +1,4 @@
-//===--- Action.h - Abstract compilation steps ------------------*- C++ -*-===//
+//===- Action.h - Abstract compilation steps --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,20 +10,23 @@
#ifndef LLVM_CLANG_DRIVER_ACTION_H
#define LLVM_CLANG_DRIVER_ACTION_H
-#include "clang/Basic/Cuda.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include <string>
namespace llvm {
-
-class StringRef;
-
namespace opt {
- class Arg;
-}
-}
+
+class Arg;
+
+} // namespace opt
+} // namespace llvm
namespace clang {
namespace driver {
@@ -44,11 +47,11 @@
/// actions via MakeAction().
class Action {
public:
- typedef ActionList::size_type size_type;
- typedef ActionList::iterator input_iterator;
- typedef ActionList::const_iterator input_const_iterator;
- typedef llvm::iterator_range<input_iterator> input_range;
- typedef llvm::iterator_range<input_const_iterator> input_const_range;
+ using size_type = ActionList::size_type;
+ using input_iterator = ActionList::iterator;
+ using input_const_iterator = ActionList::const_iterator;
+ using input_range = llvm::iterator_range<input_iterator>;
+ using input_const_range = llvm::iterator_range<input_const_iterator>;
enum ActionClass {
InputClass = 0,
@@ -78,8 +81,10 @@
// to designate the host offloading tool chain.
enum OffloadKind {
OFK_None = 0x00,
+
// The host offloading tool chain.
OFK_Host = 0x01,
+
// The device offloading tool chains - one bit for each programming model.
OFK_Cuda = 0x02,
OFK_OpenMP = 0x04,
@@ -110,8 +115,10 @@
/// Multiple programming models may be supported simultaneously by the same
/// host.
unsigned ActiveOffloadKindMask = 0u;
+
/// Offloading kind of the device.
OffloadKind OffloadingDeviceKind = OFK_None;
+
/// The Offloading architecture associated with this action.
const char *OffloadingArch = nullptr;
@@ -149,6 +156,7 @@
void setCannotBeCollapsedWithNextDependentAction() {
CanBeCollapsedWithNextDependentAction = false;
}
+
/// Return true if this function can be collapsed with others.
bool isCollapsingWithNextDependentActionLegal() const {
return CanBeCollapsedWithNextDependentAction;
@@ -156,22 +164,26 @@
/// Return a string containing the offload kind of the action.
std::string getOffloadingKindPrefix() const;
+
/// Return a string that can be used as prefix in order to generate unique
/// files for each offloading kind. By default, no prefix is used for
/// non-device kinds, except if \a CreatePrefixForHost is set.
static std::string
GetOffloadingFileNamePrefix(OffloadKind Kind,
- llvm::StringRef NormalizedTriple,
+ StringRef NormalizedTriple,
bool CreatePrefixForHost = false);
+
/// Return a string containing a offload kind name.
static StringRef GetOffloadKindName(OffloadKind Kind);
/// Set the device offload info of this action and propagate it to its
/// dependences.
void propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch);
+
/// Append the host offload info of this action and propagate it to its
/// dependences.
void propagateHostOffloadInfo(unsigned OKinds, const char *OArch);
+
/// Set the offload info of this action to be the same as the provided action,
/// and propagate it to its dependences.
void propagateOffloadInfo(const Action *A);
@@ -179,6 +191,7 @@
unsigned getOffloadingHostActiveKinds() const {
return ActiveOffloadKindMask;
}
+
OffloadKind getOffloadingDeviceKind() const { return OffloadingDeviceKind; }
const char *getOffloadingArch() const { return OffloadingArch; }
@@ -196,9 +209,10 @@
};
class InputAction : public Action {
- virtual void anchor();
const llvm::opt::Arg &Input;
+ virtual void anchor();
+
public:
InputAction(const llvm::opt::Arg &Input, types::ID Type);
@@ -211,6 +225,7 @@
class BindArchAction : public Action {
virtual void anchor();
+
/// The architecture to bind, or 0 if the default architecture
/// should be bound.
StringRef ArchName;
@@ -236,9 +251,9 @@
/// toolchain, and offload kind to each action.
class DeviceDependences final {
public:
- typedef SmallVector<const ToolChain *, 3> ToolChainList;
- typedef SmallVector<const char *, 3> BoundArchList;
- typedef SmallVector<OffloadKind, 3> OffloadKindList;
+ using ToolChainList = SmallVector<const ToolChain *, 3>;
+ using BoundArchList = SmallVector<const char *, 3>;
+ using OffloadKindList = SmallVector<OffloadKind, 3>;
private:
// Lists that keep the information for each dependency. All the lists are
@@ -248,10 +263,13 @@
/// The dependence actions.
ActionList DeviceActions;
+
/// The offloading toolchains that should be used with the action.
ToolChainList DeviceToolChains;
+
/// The architectures that should be used with this action.
BoundArchList DeviceBoundArchs;
+
/// The offload kind of each dependence.
OffloadKindList DeviceOffloadKinds;
@@ -262,12 +280,12 @@
OffloadKind OKind);
/// Get each of the individual arrays.
- const ActionList &getActions() const { return DeviceActions; };
- const ToolChainList &getToolChains() const { return DeviceToolChains; };
- const BoundArchList &getBoundArchs() const { return DeviceBoundArchs; };
+ const ActionList &getActions() const { return DeviceActions; }
+ const ToolChainList &getToolChains() const { return DeviceToolChains; }
+ const BoundArchList &getBoundArchs() const { return DeviceBoundArchs; }
const OffloadKindList &getOffloadKinds() const {
return DeviceOffloadKinds;
- };
+ }
};
/// Type used to communicate host actions. It associates bound architecture,
@@ -275,10 +293,13 @@
class HostDependence final {
/// The dependence action.
Action &HostAction;
+
/// The offloading toolchain that should be used with the action.
const ToolChain &HostToolChain;
+
/// The architectures that should be used with this action.
const char *HostBoundArch = nullptr;
+
/// The offload kind of each dependence.
unsigned HostOffloadKinds = 0u;
@@ -286,19 +307,20 @@
HostDependence(Action &A, const ToolChain &TC, const char *BoundArch,
const unsigned OffloadKinds)
: HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch),
- HostOffloadKinds(OffloadKinds){};
+ HostOffloadKinds(OffloadKinds) {}
+
/// Constructor version that obtains the offload kinds from the device
/// dependencies.
HostDependence(Action &A, const ToolChain &TC, const char *BoundArch,
const DeviceDependences &DDeps);
- Action *getAction() const { return &HostAction; };
- const ToolChain *getToolChain() const { return &HostToolChain; };
- const char *getBoundArch() const { return HostBoundArch; };
- unsigned getOffloadKinds() const { return HostOffloadKinds; };
+ Action *getAction() const { return &HostAction; }
+ const ToolChain *getToolChain() const { return &HostToolChain; }
+ const char *getBoundArch() const { return HostBoundArch; }
+ unsigned getOffloadKinds() const { return HostOffloadKinds; }
};
- typedef llvm::function_ref<void(Action *, const ToolChain *, const char *)>
- OffloadActionWorkTy;
+ using OffloadActionWorkTy =
+ llvm::function_ref<void(Action *, const ToolChain *, const char *)>;
private:
/// The host offloading toolchain that should be used with the action.
@@ -349,6 +371,7 @@
class JobAction : public Action {
virtual void anchor();
+
protected:
JobAction(ActionClass Kind, Action *Input, types::ID Type);
JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type);
@@ -362,6 +385,7 @@
class PreprocessJobAction : public JobAction {
void anchor() override;
+
public:
PreprocessJobAction(Action *Input, types::ID OutputType);
@@ -372,6 +396,7 @@
class PrecompileJobAction : public JobAction {
void anchor() override;
+
public:
PrecompileJobAction(Action *Input, types::ID OutputType);
@@ -382,6 +407,7 @@
class AnalyzeJobAction : public JobAction {
void anchor() override;
+
public:
AnalyzeJobAction(Action *Input, types::ID OutputType);
@@ -392,6 +418,7 @@
class MigrateJobAction : public JobAction {
void anchor() override;
+
public:
MigrateJobAction(Action *Input, types::ID OutputType);
@@ -402,6 +429,7 @@
class CompileJobAction : public JobAction {
void anchor() override;
+
public:
CompileJobAction(Action *Input, types::ID OutputType);
@@ -412,6 +440,7 @@
class BackendJobAction : public JobAction {
void anchor() override;
+
public:
BackendJobAction(Action *Input, types::ID OutputType);
@@ -422,6 +451,7 @@
class AssembleJobAction : public JobAction {
void anchor() override;
+
public:
AssembleJobAction(Action *Input, types::ID OutputType);
@@ -432,6 +462,7 @@
class LinkJobAction : public JobAction {
void anchor() override;
+
public:
LinkJobAction(ActionList &Inputs, types::ID Type);
@@ -442,6 +473,7 @@
class LipoJobAction : public JobAction {
void anchor() override;
+
public:
LipoJobAction(ActionList &Inputs, types::ID Type);
@@ -452,6 +484,7 @@
class DsymutilJobAction : public JobAction {
void anchor() override;
+
public:
DsymutilJobAction(ActionList &Inputs, types::ID Type);
@@ -462,8 +495,10 @@
class VerifyJobAction : public JobAction {
void anchor() override;
+
public:
VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type);
+
static bool classof(const Action *A) {
return A->getKind() == VerifyDebugInfoJobClass ||
A->getKind() == VerifyPCHJobClass;
@@ -472,8 +507,10 @@
class VerifyDebugInfoJobAction : public VerifyJobAction {
void anchor() override;
+
public:
VerifyDebugInfoJobAction(Action *Input, types::ID Type);
+
static bool classof(const Action *A) {
return A->getKind() == VerifyDebugInfoJobClass;
}
@@ -481,8 +518,10 @@
class VerifyPCHJobAction : public VerifyJobAction {
void anchor() override;
+
public:
VerifyPCHJobAction(Action *Input, types::ID Type);
+
static bool classof(const Action *A) {
return A->getKind() == VerifyPCHJobClass;
}
@@ -509,16 +548,19 @@
struct DependentActionInfo final {
/// \brief The tool chain of the dependent action.
const ToolChain *DependentToolChain = nullptr;
+
/// \brief The bound architecture of the dependent action.
StringRef DependentBoundArch;
+
/// \brief The offload kind of the dependent action.
const OffloadKind DependentOffloadKind = OFK_None;
+
DependentActionInfo(const ToolChain *DependentToolChain,
StringRef DependentBoundArch,
const OffloadKind DependentOffloadKind)
: DependentToolChain(DependentToolChain),
DependentBoundArch(DependentBoundArch),
- DependentOffloadKind(DependentOffloadKind){};
+ DependentOffloadKind(DependentOffloadKind) {}
};
private:
@@ -546,7 +588,7 @@
}
};
-} // end namespace driver
-} // end namespace clang
+} // namespace driver
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_DRIVER_ACTION_H
diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td
index fb9eb59..345cf69 100644
--- a/include/clang/Driver/CLCompatOptions.td
+++ b/include/clang/Driver/CLCompatOptions.td
@@ -245,7 +245,7 @@
def _SLASH_GX : CLFlag<"GX">,
HelpText<"Enable exception handling">;
def _SLASH_GX_ : CLFlag<"GX-">,
- HelpText<"Enable exception handling">;
+ HelpText<"Disable exception handling">;
def _SLASH_imsvc : CLJoinedOrSeparate<"imsvc">,
HelpText<"Add directory to system include search path, as if part of %INCLUDE%">,
MetaVarName<"<dir>">;
diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h
index 89c0def..0b4bb50 100644
--- a/include/clang/Driver/Compilation.h
+++ b/include/clang/Driver/Compilation.h
@@ -1,4 +1,4 @@
-//===--- Compilation.h - Compilation Task Data Structure --------*- C++ -*-===//
+//===- Compilation.h - Compilation Task Data Structure ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,24 +10,36 @@
#ifndef LLVM_CLANG_DRIVER_COMPILATION_H
#define LLVM_CLANG_DRIVER_COMPILATION_H
+#include "clang/Basic/LLVM.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Util.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Option.h"
+#include <cassert>
+#include <iterator>
#include <map>
+#include <memory>
+#include <utility>
+#include <vector>
namespace llvm {
namespace opt {
- class DerivedArgList;
- class InputArgList;
-}
-}
+
+class DerivedArgList;
+class InputArgList;
+
+} // namespace opt
+} // namespace llvm
namespace clang {
namespace driver {
- class Driver;
- class JobList;
- class ToolChain;
+
+class Driver;
+class ToolChain;
/// Compilation - A set of tasks to perform for a single driver
/// invocation.
@@ -40,7 +52,7 @@
/// A mask of all the programming models the host has to support in the
/// current compilation.
- unsigned ActiveOffloadMask;
+ unsigned ActiveOffloadMask = 0;
/// Array with the toolchains of offloading host and devices in the order they
/// were requested by the user. We are preserving that order in case the code
@@ -73,6 +85,11 @@
const ToolChain *TC = nullptr;
StringRef BoundArch;
Action::OffloadKind DeviceOffloadKind = Action::OFK_None;
+
+ TCArgsKey(const ToolChain *TC, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind)
+ : TC(TC), BoundArch(BoundArch), DeviceOffloadKind(DeviceOffloadKind) {}
+
bool operator<(const TCArgsKey &K) const {
if (TC < K.TC)
return true;
@@ -83,9 +100,6 @@
return true;
return false;
}
- TCArgsKey(const ToolChain *TC, StringRef BoundArch,
- Action::OffloadKind DeviceOffloadKind)
- : TC(TC), BoundArch(BoundArch), DeviceOffloadKind(DeviceOffloadKind) {}
};
std::map<TCArgsKey, llvm::opt::DerivedArgList *> TCArgs;
@@ -103,7 +117,7 @@
std::vector<Optional<StringRef>> Redirects;
/// Whether we're compiling for diagnostic purposes.
- bool ForDiagnostics;
+ bool ForDiagnostics = false;
/// Whether an error during the parsing of the input args.
bool ContainsError;
@@ -123,12 +137,12 @@
}
/// Iterator that visits device toolchains of a given kind.
- typedef const std::multimap<Action::OffloadKind,
- const ToolChain *>::const_iterator
- const_offload_toolchains_iterator;
- typedef std::pair<const_offload_toolchains_iterator,
- const_offload_toolchains_iterator>
- const_offload_toolchains_range;
+ using const_offload_toolchains_iterator =
+ const std::multimap<Action::OffloadKind,
+ const ToolChain *>::const_iterator;
+ using const_offload_toolchains_range =
+ std::pair<const_offload_toolchains_iterator,
+ const_offload_toolchains_iterator>;
template <Action::OffloadKind Kind>
const_offload_toolchains_range getOffloadToolChains() const {
@@ -289,7 +303,7 @@
void Redirect(ArrayRef<Optional<StringRef>> Redirects);
};
-} // end namespace driver
-} // end namespace clang
+} // namespace driver
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_DRIVER_COMPILATION_H
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index 0e55dab..ca2ca30 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -456,8 +456,10 @@
/// ConstructAction - Construct the appropriate action to do for
/// \p Phase on the \p Input, taking in to account arguments
/// like -fsyntax-only or --analyze.
- Action *ConstructPhaseAction(Compilation &C, const llvm::opt::ArgList &Args,
- phases::ID Phase, Action *Input) const;
+ Action *ConstructPhaseAction(
+ Compilation &C, const llvm::opt::ArgList &Args, phases::ID Phase,
+ Action *Input,
+ Action::OffloadKind TargetDeviceOffloadKind = Action::OFK_None) const;
/// BuildJobsForAction - Construct the jobs to perform for the action \p A and
/// return an InputInfo for the result of running \p A. Will only construct
diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h
index b74b3b4..98c1edb 100644
--- a/include/clang/Driver/Job.h
+++ b/include/clang/Driver/Job.h
@@ -1,4 +1,4 @@
-//===--- Job.h - Commands to Execute ----------------------------*- C++ -*-===//
+//===- Job.h - Commands to Execute ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,21 +12,22 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Option/Option.h"
#include <memory>
-
-namespace llvm {
- class raw_ostream;
-}
+#include <string>
+#include <utility>
+#include <vector>
namespace clang {
namespace driver {
+
class Action;
-class Command;
-class Tool;
class InputInfo;
+class Tool;
// Re-export this as clang::driver::ArgStringList.
using llvm::opt::ArgStringList;
@@ -60,7 +61,7 @@
/// Response file name, if this command is set to use one, or nullptr
/// otherwise
- const char *ResponseFile;
+ const char *ResponseFile = nullptr;
/// The input file list in case we need to emit a file list instead of a
/// proper response file
@@ -92,7 +93,7 @@
// FIXME: This really shouldn't be copyable, but is currently copied in some
// error handling in Driver::generateCompilationDiagnostics.
Command(const Command &) = default;
- virtual ~Command() {}
+ virtual ~Command() = default;
virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo = nullptr) const;
@@ -165,10 +166,10 @@
/// JobList - A sequence of jobs to perform.
class JobList {
public:
- typedef SmallVector<std::unique_ptr<Command>, 4> list_type;
- typedef list_type::size_type size_type;
- typedef llvm::pointee_iterator<list_type::iterator> iterator;
- typedef llvm::pointee_iterator<list_type::const_iterator> const_iterator;
+ using list_type = SmallVector<std::unique_ptr<Command>, 4>;
+ using size_type = list_type::size_type;
+ using iterator = llvm::pointee_iterator<list_type::iterator>;
+ using const_iterator = llvm::pointee_iterator<list_type::const_iterator>;
private:
list_type Jobs;
@@ -193,7 +194,7 @@
const_iterator end() const { return Jobs.end(); }
};
-} // end namespace driver
-} // end namespace clang
+} // namespace driver
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_DRIVER_JOB_H
diff --git a/include/clang/Driver/Multilib.h b/include/clang/Driver/Multilib.h
index 36d2493..d148fad 100644
--- a/include/clang/Driver/Multilib.h
+++ b/include/clang/Driver/Multilib.h
@@ -1,4 +1,4 @@
-//===--- Multilib.h ---------------------------------------------*- C++ -*-===//
+//===- Multilib.h -----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,10 +11,14 @@
#define LLVM_CLANG_DRIVER_MULTILIB_H
#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/Option/Option.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
#include <functional>
#include <string>
+#include <utility>
#include <vector>
namespace clang {
@@ -24,7 +28,7 @@
/// by a command line flag
class Multilib {
public:
- typedef std::vector<std::string> flags_list;
+ using flags_list = std::vector<std::string>;
private:
std::string GCCSuffix;
@@ -33,8 +37,8 @@
flags_list Flags;
public:
- Multilib(StringRef GCCSuffix = "", StringRef OSSuffix = "",
- StringRef IncludeSuffix = "");
+ Multilib(StringRef GCCSuffix = {}, StringRef OSSuffix = {},
+ StringRef IncludeSuffix = {});
/// \brief Get the detected GCC installation path suffix for the multi-arch
/// target variant. Always starts with a '/', unless empty
@@ -43,6 +47,7 @@
(StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1));
return GCCSuffix;
}
+
/// Set the GCC installation path suffix.
Multilib &gccSuffix(StringRef S);
@@ -53,6 +58,7 @@
(StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1));
return OSSuffix;
}
+
/// Set the os path suffix.
Multilib &osSuffix(StringRef S);
@@ -63,6 +69,7 @@
(StringRef(IncludeSuffix).front() == '/' && IncludeSuffix.size() > 1));
return IncludeSuffix;
}
+
/// Set the include directory suffix
Multilib &includeSuffix(StringRef S);
@@ -102,14 +109,12 @@
class MultilibSet {
public:
- typedef std::vector<Multilib> multilib_list;
- typedef multilib_list::iterator iterator;
- typedef multilib_list::const_iterator const_iterator;
-
- typedef std::function<std::vector<std::string>(const Multilib &M)>
- IncludeDirsFunc;
-
- typedef llvm::function_ref<bool(const Multilib &)> FilterCallback;
+ using multilib_list = std::vector<Multilib>;
+ using iterator = multilib_list::iterator;
+ using const_iterator = multilib_list::const_iterator;
+ using IncludeDirsFunc =
+ std::function<std::vector<std::string>(const Multilib &M)>;
+ using FilterCallback = llvm::function_ref<bool(const Multilib &)>;
private:
multilib_list Multilibs;
@@ -117,7 +122,7 @@
IncludeDirsFunc FilePathsCallback;
public:
- MultilibSet() {}
+ MultilibSet() = default;
/// Add an optional Multilib segment
MultilibSet &Maybe(const Multilib &M);
@@ -135,6 +140,7 @@
/// Filter out some subset of the Multilibs using a user defined callback
MultilibSet &FilterOut(FilterCallback F);
+
/// Filter out those Multilibs whose gccSuffix matches the given expression
MultilibSet &FilterOut(const char *Regex);
@@ -165,12 +171,14 @@
IncludeCallback = std::move(F);
return *this;
}
+
const IncludeDirsFunc &includeDirsCallback() const { return IncludeCallback; }
MultilibSet &setFilePathsCallback(IncludeDirsFunc F) {
FilePathsCallback = std::move(F);
return *this;
}
+
const IncludeDirsFunc &filePathsCallback() const { return FilePathsCallback; }
private:
@@ -182,8 +190,8 @@
};
raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS);
-}
-}
-#endif
+} // namespace driver
+} // namespace clang
+#endif // LLVM_CLANG_DRIVER_MULTILIB_H
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 6925157..bcef961 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -418,9 +418,9 @@
def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group<T_Group>,
MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">;
def Tdata : JoinedOrSeparate<["-"], "Tdata">, Group<T_Group>,
- MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">;
+ MetaVarName<"<addr>">, HelpText<"Set starting address of DATA to <addr>">;
def Ttext : JoinedOrSeparate<["-"], "Ttext">, Group<T_Group>,
- MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">;
+ MetaVarName<"<addr>">, HelpText<"Set starting address of TEXT to <addr>">;
def T : JoinedOrSeparate<["-"], "T">, Group<T_Group>,
MetaVarName<"<script>">, HelpText<"Specify <script> as linker script">;
def U : JoinedOrSeparate<["-"], "U">, Group<Preprocessor_Group>,
@@ -2401,7 +2401,8 @@
def _for_linker : Separate<["--"], "for-linker">, Alias<Xlinker>;
def _force_link_EQ : Joined<["--"], "force-link=">, Alias<u>;
def _force_link : Separate<["--"], "force-link">, Alias<u>;
-def _help_hidden : Flag<["--"], "help-hidden">;
+def _help_hidden : Flag<["--"], "help-hidden">,
+ HelpText<"Display help for hidden options">;
def _imacros_EQ : Joined<["--"], "imacros=">, Alias<imacros>;
def _include_barrier : Flag<["--"], "include-barrier">, Alias<I_>;
def _include_directory_after_EQ : Joined<["--"], "include-directory-after=">, Alias<idirafter>;
@@ -2471,41 +2472,45 @@
def _write_user_dependencies : Flag<["--"], "write-user-dependencies">, Alias<MMD>;
def _ : Joined<["--"], "">, Flags<[Unsupported]>;
-def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group<m_hexagon_Features_Group>;
+// Hexagon feature flags.
+def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">,
+ Group<m_hexagon_Features_Group>;
def mv4 : Flag<["-"], "mv4">, Group<m_hexagon_Features_Group>,
- Alias<mcpu_EQ>, AliasArgs<["hexagonv4"]>;
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv4"]>;
def mv5 : Flag<["-"], "mv5">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>,
- AliasArgs<["hexagonv5"]>;
+ AliasArgs<["hexagonv5"]>;
def mv55 : Flag<["-"], "mv55">, Group<m_hexagon_Features_Group>,
- Alias<mcpu_EQ>, AliasArgs<["hexagonv55"]>;
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv55"]>;
def mv60 : Flag<["-"], "mv60">, Group<m_hexagon_Features_Group>,
- Alias<mcpu_EQ>, AliasArgs<["hexagonv60"]>;
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv60"]>;
def mv62 : Flag<["-"], "mv62">, Group<m_hexagon_Features_Group>,
- Alias<mcpu_EQ>, AliasArgs<["hexagonv62"]>;
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv62"]>;
def mv65 : Flag<["-"], "mv65">, Group<m_hexagon_Features_Group>,
- Alias<mcpu_EQ>, AliasArgs<["hexagonv65"]>;
-def mhexagon_hvx : Flag<[ "-" ], "mhvx">,
- Group<m_hexagon_Features_HVX_Group>,
- HelpText<"Enable Hexagon Vector eXtensions">;
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv65"]>;
+def mhexagon_hvx : Flag<[ "-" ], "mhvx">, Group<m_hexagon_Features_HVX_Group>,
+ HelpText<"Enable Hexagon Vector eXtensions">;
def mhexagon_hvx_EQ : Joined<[ "-" ], "mhvx=">,
- Group<m_hexagon_Features_HVX_Group>,
- HelpText<"Enable Hexagon Vector eXtensions">;
+ Group<m_hexagon_Features_HVX_Group>,
+ HelpText<"Enable Hexagon Vector eXtensions">;
def mno_hexagon_hvx : Flag<[ "-" ], "mno-hvx">,
- Group<m_hexagon_Features_HVX_Group>,
- HelpText<"Disable Hexagon Vector eXtensions">;
+ Group<m_hexagon_Features_HVX_Group>,
+ HelpText<"Disable Hexagon Vector eXtensions">;
def mhexagon_hvx_length_EQ : Joined<[ "-" ], "mhvx-length=">,
- Group<m_hexagon_Features_HVX_Group>,
- HelpText<"Set Hexagon Vector Length">, Values<"64B,128B">;
-// hvx-double deprecrated flag.
-def mhexagon_hvx_double : Flag<[ "-" ], "mhvx-double">,
- Group<m_hexagon_Features_HVX_Group>,
- HelpText<"Enable Hexagon Double Vector eXtensions">;
-def mno_hexagon_hvx_double
- : Flag<[ "-" ], "mno-hvx-double">,
- Group<m_hexagon_Features_HVX_Group>,
- HelpText<"Disable Hexagon Double Vector eXtensions">;
+ Group<m_hexagon_Features_HVX_Group>, HelpText<"Set Hexagon Vector Length">,
+ Values<"64B,128B">;
def ffixed_r19: Flag<["-"], "ffixed-r19">,
HelpText<"Reserve the r19 register (Hexagon only)">;
+def mpackets : Flag<["-"], "mpackets">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Enable generation of instruction packets">;
+def mno_packets : Flag<["-"], "mno-packets">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Disable generation of instruction packets">;
+// hvx-double deprecrated flag.
+def mhexagon_hvx_double : Flag<[ "-" ], "mhvx-double">,
+ Group<m_hexagon_Features_HVX_Group>,
+ HelpText<"Enable Hexagon Double Vector eXtensions">;
+def mno_hexagon_hvx_double : Flag<[ "-" ], "mno-hvx-double">,
+ Group<m_hexagon_Features_HVX_Group>,
+ HelpText<"Disable Hexagon Double Vector eXtensions">;
// X86 feature flags
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index 293fcf0..b1f7338 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -1,4 +1,4 @@
-//===--- ToolChain.h - Collections of tools for one platform ----*- C++ -*-===//
+//===- ToolChain.h - Collections of tools for one platform ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,59 +10,70 @@
#ifndef LLVM_CLANG_DRIVER_TOOLCHAIN_H
#define LLVM_CLANG_DRIVER_TOOLCHAIN_H
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/VersionTuple.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Multilib.h"
#include "clang/Driver/Types.h"
-#include "clang/Driver/Util.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/Option/Option.h"
#include "llvm/Target/TargetOptions.h"
+#include <cassert>
#include <memory>
#include <string>
+#include <utility>
namespace llvm {
namespace opt {
- class ArgList;
- class DerivedArgList;
- class InputArgList;
-}
-}
+
+class Arg;
+class ArgList;
+class DerivedArgList;
+
+} // namespace opt
+} // namespace llvm
namespace clang {
+
class ObjCRuntime;
+
namespace vfs {
+
class FileSystem;
-}
+
+} // namespace vfs
namespace driver {
- class Compilation;
- class CudaInstallationDetector;
- class Driver;
- class InputInfo;
- class JobAction;
- class RegisterEffectiveTriple;
- class SanitizerArgs;
- class Tool;
- class XRayArgs;
+
+class Driver;
+class InputInfo;
+class SanitizerArgs;
+class Tool;
+class XRayArgs;
/// Helper structure used to pass information extracted from clang executable
/// name such as `i686-linux-android-g++`.
-///
struct ParsedClangName {
/// Target part of the executable name, as `i686-linux-android`.
std::string TargetPrefix;
+
/// Driver mode part of the executable name, as `g++`.
std::string ModeSuffix;
- /// Corresponding driver mode argument, as '--driver-mode=g++'
- const char *DriverMode;
- /// True if TargetPrefix is recognized as a registered target name.
- bool TargetIsValid;
- ParsedClangName() : DriverMode(nullptr), TargetIsValid(false) {}
+ /// Corresponding driver mode argument, as '--driver-mode=g++'
+ const char *DriverMode = nullptr;
+
+ /// True if TargetPrefix is recognized as a registered target name.
+ bool TargetIsValid = false;
+
+ ParsedClangName() = default;
ParsedClangName(std::string Suffix, const char *Mode)
- : ModeSuffix(Suffix), DriverMode(Mode), TargetIsValid(false) {}
+ : ModeSuffix(Suffix), DriverMode(Mode) {}
ParsedClangName(std::string Target, std::string Suffix, const char *Mode,
bool IsRegistered)
: TargetPrefix(Target), ModeSuffix(Suffix), DriverMode(Mode),
@@ -72,7 +83,7 @@
/// ToolChain - Access to tools for a single platform.
class ToolChain {
public:
- typedef SmallVector<std::string, 16> path_list;
+ using path_list = SmallVector<std::string, 16>;
enum CXXStdlibType {
CST_Libcxx,
@@ -92,25 +103,28 @@
};
private:
+ friend class RegisterEffectiveTriple;
+
const Driver &D;
llvm::Triple Triple;
const llvm::opt::ArgList &Args;
+
// We need to initialize CachedRTTIArg before CachedRTTIMode
const llvm::opt::Arg *const CachedRTTIArg;
+
const RTTIMode CachedRTTIMode;
- /// The list of toolchain specific path prefixes to search for
- /// files.
+ /// The list of toolchain specific path prefixes to search for files.
path_list FilePaths;
- /// The list of toolchain specific path prefixes to search for
- /// programs.
+ /// The list of toolchain specific path prefixes to search for programs.
path_list ProgramPaths;
mutable std::unique_ptr<Tool> Clang;
mutable std::unique_ptr<Tool> Assemble;
mutable std::unique_ptr<Tool> Link;
mutable std::unique_ptr<Tool> OffloadBundler;
+
Tool *getClang() const;
Tool *getAssemble() const;
Tool *getLink() const;
@@ -128,8 +142,6 @@
EffectiveTriple = std::move(ET);
}
- friend class RegisterEffectiveTriple;
-
protected:
MultilibSet Multilibs;
@@ -231,7 +243,6 @@
/// e.g., argv[0]).
/// \return A structure of type ParsedClangName that contains the executable
/// name parts.
- ///
static ParsedClangName getTargetAndModeFromProgramName(StringRef ProgName);
// Tool access.
@@ -328,9 +339,7 @@
}
/// GetDefaultLinker - Get the default linker to use.
- virtual const char *getDefaultLinker() const {
- return "ld";
- }
+ virtual const char *getDefaultLinker() const { return "ld"; }
/// GetDefaultRuntimeLibType - Get the default runtime library variant to use.
virtual RuntimeLibType GetDefaultRuntimeLibType() const {
@@ -407,9 +416,7 @@
GetExceptionModel(const llvm::opt::ArgList &Args) const;
/// SupportsEmbeddedBitcode - Does this tool chain support embedded bitcode.
- virtual bool SupportsEmbeddedBitcode() const {
- return false;
- }
+ virtual bool SupportsEmbeddedBitcode() const { return false; }
/// getThreadModel() - Which thread model does this target use?
virtual std::string getThreadModel() const { return "posix"; }
@@ -500,6 +507,7 @@
/// This checks for presence of the -Ofast, -ffast-math or -funsafe-math flags.
virtual bool AddFastMathRuntimeIfAvailable(
const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const;
+
/// addProfileRTLibs - When -fprofile-instr-profile is specified, try to pass
/// a suitable profile runtime library to the linker.
virtual void addProfileRTLibs(const llvm::opt::ArgList &Args,
@@ -537,7 +545,8 @@
~RegisterEffectiveTriple() { TC.setEffectiveTriple(llvm::Triple()); }
};
-} // end namespace driver
-} // end namespace clang
+} // namespace driver
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_DRIVER_TOOLCHAIN_H
diff --git a/include/clang/Edit/Commit.h b/include/clang/Edit/Commit.h
index ac4bb47..a574b8e 100644
--- a/include/clang/Edit/Commit.h
+++ b/include/clang/Edit/Commit.h
@@ -1,4 +1,4 @@
-//===----- Commit.h - A unit of edits ---------------------------*- C++ -*-===//
+//===- Commit.h - A unit of edits -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,17 +10,22 @@
#ifndef LLVM_CLANG_EDIT_COMMIT_H
#define LLVM_CLANG_EDIT_COMMIT_H
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Edit/FileOffset.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
namespace clang {
- class LangOptions;
- class PPConditionalDirectiveRecord;
+
+class LangOptions;
+class PPConditionalDirectiveRecord;
+class SourceManager;
namespace edit {
- class EditedSource;
+
+class EditedSource;
class Commit {
public:
@@ -48,9 +53,9 @@
const SourceManager &SourceMgr;
const LangOptions &LangOpts;
const PPConditionalDirectiveRecord *PPRec;
- EditedSource *Editor;
+ EditedSource *Editor = nullptr;
- bool IsCommitable;
+ bool IsCommitable = true;
SmallVector<Edit, 8> CachedEdits;
llvm::BumpPtrAllocator StrAlloc;
@@ -59,21 +64,23 @@
explicit Commit(EditedSource &Editor);
Commit(const SourceManager &SM, const LangOptions &LangOpts,
const PPConditionalDirectiveRecord *PPRec = nullptr)
- : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(nullptr),
- IsCommitable(true) { }
+ : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec) {}
bool isCommitable() const { return IsCommitable; }
bool insert(SourceLocation loc, StringRef text, bool afterToken = false,
bool beforePreviousInsertions = false);
+
bool insertAfterToken(SourceLocation loc, StringRef text,
bool beforePreviousInsertions = false) {
return insert(loc, text, /*afterToken=*/true, beforePreviousInsertions);
}
+
bool insertBefore(SourceLocation loc, StringRef text) {
return insert(loc, text, /*afterToken=*/false,
/*beforePreviousInsertions=*/true);
}
+
bool insertFromRange(SourceLocation loc, CharSourceRange range,
bool afterToken = false,
bool beforePreviousInsertions = false);
@@ -92,21 +99,26 @@
return insertFromRange(loc, CharSourceRange::getTokenRange(TokenRange),
afterToken, beforePreviousInsertions);
}
+
bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after) {
return insertWrap(before, CharSourceRange::getTokenRange(TokenRange), after);
}
+
bool remove(SourceRange TokenRange) {
return remove(CharSourceRange::getTokenRange(TokenRange));
}
+
bool replace(SourceRange TokenRange, StringRef text) {
return replace(CharSourceRange::getTokenRange(TokenRange), text);
}
+
bool replaceWithInner(SourceRange TokenRange, SourceRange TokenInnerRange) {
return replaceWithInner(CharSourceRange::getTokenRange(TokenRange),
CharSourceRange::getTokenRange(TokenInnerRange));
}
- typedef SmallVectorImpl<Edit>::const_iterator edit_iterator;
+ using edit_iterator = SmallVectorImpl<Edit>::const_iterator;
+
edit_iterator edit_begin() const { return CachedEdits.begin(); }
edit_iterator edit_end() const { return CachedEdits.end(); }
@@ -136,8 +148,8 @@
SourceLocation *MacroEnd = nullptr) const;
};
-}
+} // namespace edit
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_EDIT_COMMIT_H
diff --git a/include/clang/Edit/EditedSource.h b/include/clang/Edit/EditedSource.h
index d95a0c2..3d33688 100644
--- a/include/clang/Edit/EditedSource.h
+++ b/include/clang/Edit/EditedSource.h
@@ -1,4 +1,4 @@
-//===----- EditedSource.h - Collection of source edits ----------*- C++ -*-===//
+//===- EditedSource.h - Collection of source edits --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,21 +11,27 @@
#define LLVM_CLANG_EDIT_EDITEDSOURCE_H
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Edit/FileOffset.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/Allocator.h"
#include <map>
#include <tuple>
+#include <utility>
namespace clang {
- class LangOptions;
- class PPConditionalDirectiveRecord;
+
+class LangOptions;
+class PPConditionalDirectiveRecord;
+class SourceManager;
namespace edit {
- class Commit;
- class EditsReceiver;
+
+class Commit;
+class EditsReceiver;
class EditedSource {
const SourceManager &SourceMgr;
@@ -34,17 +40,19 @@
struct FileEdit {
StringRef Text;
- unsigned RemoveLen;
+ unsigned RemoveLen = 0;
- FileEdit() : RemoveLen(0) {}
+ FileEdit() = default;
};
- typedef std::map<FileOffset, FileEdit> FileEditsTy;
+ using FileEditsTy = std::map<FileOffset, FileEdit>;
+
FileEditsTy FileEdits;
struct MacroArgUse {
IdentifierInfo *Identifier;
SourceLocation ImmediateExpansionLoc;
+
// Location of argument use inside the top-level macro
SourceLocation UseLoc;
@@ -65,11 +73,11 @@
public:
EditedSource(const SourceManager &SM, const LangOptions &LangOpts,
const PPConditionalDirectiveRecord *PPRec = nullptr)
- : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), IdentTable(LangOpts),
- StrAlloc() { }
+ : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), IdentTable(LangOpts) {}
const SourceManager &getSourceManager() const { return SourceMgr; }
const LangOptions &getLangOpts() const { return LangOpts; }
+
const PPConditionalDirectiveRecord *getPPCondDirectiveRecord() const {
return PPRec;
}
@@ -103,8 +111,8 @@
void finishedCommit();
};
-}
+} // namespace edit
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_EDIT_EDITEDSOURCE_H
diff --git a/include/clang/Edit/EditsReceiver.h b/include/clang/Edit/EditsReceiver.h
index 600ac28..4fd4347 100644
--- a/include/clang/Edit/EditsReceiver.h
+++ b/include/clang/Edit/EditsReceiver.h
@@ -1,4 +1,4 @@
-//===----- EditedSource.h - Collection of source edits ----------*- C++ -*-===//
+//===- EditedSource.h - Collection of source edits --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,25 +11,24 @@
#define LLVM_CLANG_EDIT_EDITSRECEIVER_H
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/StringRef.h"
namespace clang {
- class SourceLocation;
- class CharSourceRange;
-
namespace edit {
class EditsReceiver {
public:
- virtual ~EditsReceiver() { }
+ virtual ~EditsReceiver() = default;
virtual void insert(SourceLocation loc, StringRef text) = 0;
virtual void replace(CharSourceRange range, StringRef text) = 0;
+
/// \brief By default it calls replace with an empty string.
virtual void remove(CharSourceRange range);
};
-}
+} // namespace edit
+} // namespace clang
-} // end namespace clang
-
-#endif
+#endif // LLVM_CLANG_EDIT_EDITSRECEIVER_H
diff --git a/include/clang/Edit/FileOffset.h b/include/clang/Edit/FileOffset.h
index 0c1e72b..02c1b96 100644
--- a/include/clang/Edit/FileOffset.h
+++ b/include/clang/Edit/FileOffset.h
@@ -1,4 +1,4 @@
-//===----- FileOffset.h - Offset in a file ----------------------*- C++ -*-===//
+//===- FileOffset.h - Offset in a file --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,17 +11,18 @@
#define LLVM_CLANG_EDIT_FILEOFFSET_H
#include "clang/Basic/SourceLocation.h"
+#include <tuple>
namespace clang {
-
namespace edit {
class FileOffset {
FileID FID;
- unsigned Offs;
+ unsigned Offs = 0;
+
public:
- FileOffset() : Offs(0) { }
- FileOffset(FileID fid, unsigned offs) : FID(fid), Offs(offs) { }
+ FileOffset() = default;
+ FileOffset(FileID fid, unsigned offs) : FID(fid), Offs(offs) {}
bool isInvalid() const { return FID.isInvalid(); }
@@ -37,25 +38,29 @@
friend bool operator==(FileOffset LHS, FileOffset RHS) {
return LHS.FID == RHS.FID && LHS.Offs == RHS.Offs;
}
+
friend bool operator!=(FileOffset LHS, FileOffset RHS) {
return !(LHS == RHS);
}
+
friend bool operator<(FileOffset LHS, FileOffset RHS) {
return std::tie(LHS.FID, LHS.Offs) < std::tie(RHS.FID, RHS.Offs);
}
+
friend bool operator>(FileOffset LHS, FileOffset RHS) {
return RHS < LHS;
}
+
friend bool operator>=(FileOffset LHS, FileOffset RHS) {
return !(LHS < RHS);
}
+
friend bool operator<=(FileOffset LHS, FileOffset RHS) {
return !(RHS < LHS);
}
};
-}
+} // namespace edit
+} // namespace clang
-} // end namespace clang
-
-#endif
+#endif // LLVM_CLANG_EDIT_FILEOFFSET_H
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 5d04dcd..49c0da4 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -1,4 +1,4 @@
-//===--- ASTUnit.h - ASTUnit utility ----------------------------*- C++ -*-===//
+//===- ASTUnit.h - ASTUnit utility ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,8 +16,11 @@
#include "clang-c/Index.h"
#include "clang/AST/ASTContext.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Lex/HeaderSearchOptions.h"
@@ -26,48 +29,59 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Frontend/PrecompiledPreamble.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/MD5.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
#include <cassert>
+#include <cstddef>
+#include <cstdint>
#include <memory>
#include <string>
-#include <sys/types.h>
#include <utility>
#include <vector>
namespace llvm {
- class MemoryBuffer;
-}
+
+class MemoryBuffer;
+
+} // namespace llvm
namespace clang {
-class Sema;
+
class ASTContext;
+class ASTDeserializationListener;
+class ASTMutationListener;
class ASTReader;
-class CompilerInvocation;
class CompilerInstance;
+class CompilerInvocation;
class Decl;
-class DiagnosticsEngine;
class FileEntry;
class FileManager;
+class FrontendAction;
class HeaderSearch;
class InputKind;
class MemoryBufferCache;
-class Preprocessor;
-class PreprocessorOptions;
class PCHContainerOperations;
class PCHContainerReader;
+class Preprocessor;
+class PreprocessorOptions;
+class Sema;
class TargetInfo;
-class FrontendAction;
-class ASTDeserializationListener;
namespace vfs {
+
class FileSystem;
-}
+
+} // namespace vfs
/// \brief Utility class for loading a ASTContext from an AST file.
-///
class ASTUnit {
public:
struct StandaloneFixIt {
@@ -83,7 +97,7 @@
std::string Message;
std::string Filename;
unsigned LocOffset;
- std::vector<std::pair<unsigned, unsigned> > Ranges;
+ std::vector<std::pair<unsigned, unsigned>> Ranges;
std::vector<StandaloneFixIt> FixIts;
};
@@ -101,7 +115,7 @@
std::shared_ptr<HeaderSearchOptions> HSOpts;
std::shared_ptr<PreprocessorOptions> PPOpts;
IntrusiveRefCntPtr<ASTReader> Reader;
- bool HadModuleLoaderFatalFailure;
+ bool HadModuleLoaderFatalFailure = false;
struct ASTWriterData;
std::unique_ptr<ASTWriterData> WriterData;
@@ -126,22 +140,22 @@
// 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 = false;
/// \brief Whether to capture any diagnostics produced.
- bool CaptureDiagnostics;
+ bool CaptureDiagnostics = false;
/// \brief Track whether the main file was loaded from an AST or not.
bool MainFileIsAST;
/// \brief What kind of translation unit this AST represents.
- TranslationUnitKind TUKind;
+ TranslationUnitKind TUKind = TU_Complete;
/// \brief Whether we should time each operation.
bool WantTiming;
/// \brief Whether the ASTUnit should delete the remapped buffers.
- bool OwnsRemappedFileBuffers;
+ bool OwnsRemappedFileBuffers = true;
/// Track the top-level decls which appeared in an ASTUnit which was loaded
/// from a source file.
@@ -153,8 +167,8 @@
std::vector<Decl*> TopLevelDecls;
/// \brief Sorted (by file offset) vector of pairs of file offset/Decl.
- typedef SmallVector<std::pair<unsigned, Decl *>, 64> LocDeclsTy;
- typedef llvm::DenseMap<FileID, LocDeclsTy *> FileDeclsTy;
+ using LocDeclsTy = SmallVector<std::pair<unsigned, Decl *>, 64>;
+ using FileDeclsTy = llvm::DenseMap<FileID, LocDeclsTy *>;
/// \brief Map from FileID to the file-level declarations that it contains.
/// The files and decls are only local (and non-preamble) ones.
@@ -179,7 +193,7 @@
///
/// Diagnostics that come from the driver are retained from one parse to
/// the next.
- unsigned NumStoredDiagnosticsFromDriver;
+ unsigned NumStoredDiagnosticsFromDriver = 0;
/// \brief Counter that determines when we want to try building a
/// precompiled preamble.
@@ -190,7 +204,7 @@
/// we'll attempt to rebuild the precompiled header. This way, if
/// building the precompiled preamble fails, we won't try again for
/// some number of calls.
- unsigned PreambleRebuildCounter;
+ unsigned PreambleRebuildCounter = 0;
/// \brief Cache pairs "filename - source location"
///
@@ -200,7 +214,6 @@
/// of that loading. It must be cleared when preamble is recreated.
llvm::StringMap<SourceLocation> PreambleSrcLocCache;
-private:
/// The contents of the preamble.
llvm::Optional<PrecompiledPreamble> Preamble;
@@ -215,7 +228,7 @@
/// object when re-using the precompiled preamble. Note that only the
/// number of warnings matters, since we will not save the preamble
/// when any errors are present.
- unsigned NumWarningsInPreamble;
+ unsigned NumWarningsInPreamble = 0;
/// \brief A list of the serialization ID numbers for each of the top-level
/// declarations parsed within the precompiled preamble.
@@ -283,7 +296,7 @@
/// \brief Retrieve the mapping from formatted type names to unique type
/// identifiers.
- llvm::StringMap<unsigned> &getCachedCompletionTypes() {
+ llvm::StringMap<unsigned> &getCachedCompletionTypes() {
return CachedCompletionTypes;
}
@@ -318,18 +331,18 @@
///
/// This hash value is used to determine when we need to refresh the
/// global code-completion cache.
- unsigned CompletionCacheTopLevelHashValue;
+ unsigned CompletionCacheTopLevelHashValue = 0;
/// \brief A string hash of the top-level declaration and macro definition
/// names processed the last time that we reparsed the precompiled preamble.
///
/// This hash value is used to determine when we need to refresh the
/// global code-completion cache after a rebuild of the precompiled preamble.
- unsigned PreambleTopLevelHashValue;
+ unsigned PreambleTopLevelHashValue = 0;
/// \brief The current hash value for the top-level declaration and macro
/// definition names
- unsigned CurrentTopLevelHashValue;
+ unsigned CurrentTopLevelHashValue = 0;
/// \brief Bit used by CIndex to mark when a translation unit may be in an
/// inconsistent state, and is not safe to free.
@@ -342,9 +355,6 @@
/// \brief Clear out and deallocate
void ClearCachedCompletionResults();
- ASTUnit(const ASTUnit &) = delete;
- void operator=(const ASTUnit &) = delete;
-
explicit ASTUnit(bool MainFileIsAST);
bool Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
@@ -382,21 +392,23 @@
ConcurrencyState ConcurrencyCheckValue;
public:
+ friend class ConcurrencyCheck;
+
class ConcurrencyCheck {
ASTUnit &Self;
public:
- explicit ConcurrencyCheck(ASTUnit &Self)
- : Self(Self)
- {
+ explicit ConcurrencyCheck(ASTUnit &Self) : Self(Self) {
Self.ConcurrencyCheckValue.start();
}
+
~ConcurrencyCheck() {
Self.ConcurrencyCheckValue.finish();
}
};
- friend class ConcurrencyCheck;
+ ASTUnit(const ASTUnit &) = delete;
+ ASTUnit &operator=(const ASTUnit &) = delete;
~ASTUnit();
bool isMainFileAST() const { return MainFileIsAST; }
@@ -405,22 +417,23 @@
void setUnsafeToFree(bool Value) { UnsafeToFree = Value; }
const DiagnosticsEngine &getDiagnostics() const { return *Diagnostics; }
- DiagnosticsEngine &getDiagnostics() { return *Diagnostics; }
+ DiagnosticsEngine &getDiagnostics() { return *Diagnostics; }
const SourceManager &getSourceManager() const { return *SourceMgr; }
- SourceManager &getSourceManager() { return *SourceMgr; }
+ SourceManager &getSourceManager() { return *SourceMgr; }
const Preprocessor &getPreprocessor() const { return *PP; }
- Preprocessor &getPreprocessor() { return *PP; }
+ Preprocessor &getPreprocessor() { return *PP; }
std::shared_ptr<Preprocessor> getPreprocessorPtr() const { return PP; }
const ASTContext &getASTContext() const { return *Ctx; }
- ASTContext &getASTContext() { return *Ctx; }
+ ASTContext &getASTContext() { return *Ctx; }
void setASTContext(ASTContext *ctx) { Ctx = ctx; }
void setPreprocessor(std::shared_ptr<Preprocessor> pp);
bool hasSema() const { return (bool)TheSema; }
+
Sema &getSema() const {
assert(TheSema && "ASTUnit does not have a Sema object!");
return *TheSema;
@@ -442,7 +455,7 @@
}
const FileManager &getFileManager() const { return *FileMgr; }
- FileManager &getFileManager() { return *FileMgr; }
+ FileManager &getFileManager() { return *FileMgr; }
const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
@@ -465,7 +478,7 @@
/// \brief If this ASTUnit came from an AST file, returns the filename for it.
StringRef getASTFileName() const;
- typedef std::vector<Decl *>::iterator top_level_iterator;
+ using top_level_iterator = std::vector<Decl *>::iterator;
top_level_iterator top_level_begin() {
assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
@@ -549,20 +562,25 @@
}
// Retrieve the diagnostics associated with this AST
- typedef StoredDiagnostic *stored_diag_iterator;
- typedef const StoredDiagnostic *stored_diag_const_iterator;
+ using stored_diag_iterator = StoredDiagnostic *;
+ using stored_diag_const_iterator = const StoredDiagnostic *;
+
stored_diag_const_iterator stored_diag_begin() const {
return StoredDiagnostics.begin();
}
+
stored_diag_iterator stored_diag_begin() {
return StoredDiagnostics.begin();
}
+
stored_diag_const_iterator stored_diag_end() const {
return StoredDiagnostics.end();
}
+
stored_diag_iterator stored_diag_end() {
return StoredDiagnostics.end();
}
+
unsigned stored_diag_size() const { return StoredDiagnostics.size(); }
stored_diag_iterator stored_diag_afterDriver_begin() {
@@ -571,8 +589,8 @@
return StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver;
}
- typedef std::vector<CachedCodeCompletionResult>::iterator
- cached_completion_iterator;
+ using cached_completion_iterator =
+ std::vector<CachedCodeCompletionResult>::iterator;
cached_completion_iterator cached_completion_begin() {
return CachedCompletionResults.begin();
@@ -594,7 +612,7 @@
/// \brief Type for a function iterating over a number of declarations.
/// \returns true to continue iteration and false to abort.
- typedef bool (*DeclVisitorFn)(void *context, const Decl *D);
+ using DeclVisitorFn = bool (*)(void *context, const Decl *D);
/// \brief Iterate over local declarations (locally parsed if this is a parsed
/// source file or the loaded declarations of the primary module if this is an
@@ -620,7 +638,7 @@
/// \brief A mapping from a file name to the memory buffer that stores the
/// remapped contents of that file.
- typedef std::pair<std::string, llvm::MemoryBuffer *> RemappedFile;
+ using RemappedFile = std::pair<std::string, llvm::MemoryBuffer *>;
/// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation.
static std::unique_ptr<ASTUnit>
@@ -631,8 +649,10 @@
enum WhatToLoad {
/// Load options and the preprocessor state.
LoadPreprocessorOnly,
+
/// Load the AST, but do not restore Sema state.
LoadASTOnly,
+
/// Load everything, including Sema.
LoadEverything
};
@@ -676,7 +696,6 @@
IntrusiveRefCntPtr<vfs::FileSystem> VFS);
public:
-
/// \brief Create an ASTUnit from a source file, via a CompilerInvocation
/// object, by invoking the optionally provided ASTFrontendAction.
///
@@ -853,4 +872,4 @@
} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_ASTUNIT_H
diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def
index edf266f..adcbe36 100644
--- a/include/clang/Frontend/CodeGenOptions.def
+++ b/include/clang/Frontend/CodeGenOptions.def
@@ -138,9 +138,6 @@
CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is
///< enabled.
-/// A version of Clang that we should attempt to be ABI-compatible with.
-ENUM_CODEGENOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest)
-
VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index 8c4c932..f6efcaf 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -1,4 +1,4 @@
-//===-- CompilerInvocation.h - Compiler Invocation Helper Data --*- C++ -*-===//
+//===- CompilerInvocation.h - Compiler Invocation Helper Data ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,11 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_
-#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_
+#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
+#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/DependencyOutputOptions.h"
@@ -21,23 +22,27 @@
#include "clang/Frontend/PreprocessorOutputOptions.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include <memory>
#include <string>
namespace llvm {
+
class Triple;
namespace opt {
+
class ArgList;
-}
-}
+
+} // namespace opt
+
+} // namespace llvm
namespace clang {
-class PreprocessorOptions;
-class HeaderSearchOptions;
-class TargetOptions;
-class LangOptions;
-class CompilerInvocation;
+
class DiagnosticsEngine;
+class HeaderSearchOptions;
+class PreprocessorOptions;
+class TargetOptions;
/// \brief Fill out Opts based on the options given in Args.
///
@@ -52,8 +57,6 @@
bool DefaultShowOpt = true);
class CompilerInvocationBase {
- void operator=(const CompilerInvocationBase &) = delete;
-
public:
/// Options controlling the language variant.
std::shared_ptr<LangOptions> LangOpts;
@@ -71,24 +74,24 @@
std::shared_ptr<PreprocessorOptions> PreprocessorOpts;
CompilerInvocationBase();
- ~CompilerInvocationBase();
-
CompilerInvocationBase(const CompilerInvocationBase &X);
+ CompilerInvocationBase &operator=(const CompilerInvocationBase &) = delete;
+ ~CompilerInvocationBase();
LangOptions *getLangOpts() { return LangOpts.get(); }
const LangOptions *getLangOpts() const { return LangOpts.get(); }
TargetOptions &getTargetOpts() { return *TargetOpts.get(); }
- const TargetOptions &getTargetOpts() const {
- return *TargetOpts.get();
- }
+ const TargetOptions &getTargetOpts() const { return *TargetOpts.get(); }
DiagnosticOptions &getDiagnosticOpts() const { return *DiagnosticOpts; }
HeaderSearchOptions &getHeaderSearchOpts() { return *HeaderSearchOpts; }
+
const HeaderSearchOptions &getHeaderSearchOpts() const {
return *HeaderSearchOpts;
}
+
std::shared_ptr<HeaderSearchOptions> getHeaderSearchOptsPtr() const {
return HeaderSearchOpts;
}
@@ -96,7 +99,9 @@
std::shared_ptr<PreprocessorOptions> getPreprocessorOptsPtr() {
return PreprocessorOpts;
}
+
PreprocessorOptions &getPreprocessorOpts() { return *PreprocessorOpts; }
+
const PreprocessorOptions &getPreprocessorOpts() const {
return *PreprocessorOpts;
}
@@ -176,40 +181,35 @@
/// @name Option Subgroups
/// @{
- AnalyzerOptionsRef getAnalyzerOpts() const {
- return AnalyzerOpts;
- }
+ AnalyzerOptionsRef getAnalyzerOpts() const { return AnalyzerOpts; }
MigratorOptions &getMigratorOpts() { return MigratorOpts; }
- const MigratorOptions &getMigratorOpts() const {
- return MigratorOpts;
- }
+ const MigratorOptions &getMigratorOpts() const { return MigratorOpts; }
CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; }
- const CodeGenOptions &getCodeGenOpts() const {
- return CodeGenOpts;
- }
+ const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
DependencyOutputOptions &getDependencyOutputOpts() {
return DependencyOutputOpts;
}
+
const DependencyOutputOptions &getDependencyOutputOpts() const {
return DependencyOutputOpts;
}
FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
+
const FileSystemOptions &getFileSystemOpts() const {
return FileSystemOpts;
}
FrontendOptions &getFrontendOpts() { return FrontendOpts; }
- const FrontendOptions &getFrontendOpts() const {
- return FrontendOpts;
- }
+ const FrontendOptions &getFrontendOpts() const { return FrontendOpts; }
PreprocessorOutputOptions &getPreprocessorOutputOpts() {
return PreprocessorOutputOpts;
}
+
const PreprocessorOutputOptions &getPreprocessorOutputOpts() const {
return PreprocessorOutputOpts;
}
@@ -218,8 +218,10 @@
};
namespace vfs {
- class FileSystem;
-}
+
+class FileSystem;
+
+} // namespace vfs
IntrusiveRefCntPtr<vfs::FileSystem>
createVFSFromCompilerInvocation(const CompilerInvocation &CI,
@@ -230,6 +232,6 @@
DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<vfs::FileSystem> BaseFS);
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
diff --git a/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h
index e453d7d..0814569 100644
--- a/include/clang/Frontend/DiagnosticRenderer.h
+++ b/include/clang/Frontend/DiagnosticRenderer.h
@@ -1,4 +1,4 @@
-//===--- DiagnosticRenderer.h - Diagnostic Pretty-Printing ------*- C++ -*-===//
+//===- DiagnosticRenderer.h - Diagnostic Pretty-Printing --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,18 +17,21 @@
#define LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
namespace clang {
-class DiagnosticOptions;
class LangOptions;
class SourceManager;
-typedef llvm::PointerUnion<const Diagnostic *,
- const StoredDiagnostic *> DiagOrStoredDiag;
+using DiagOrStoredDiag =
+ llvm::PointerUnion<const Diagnostic *, const StoredDiagnostic *>;
/// \brief Class to encapsulate the logic for formatting a diagnostic message.
///
@@ -64,7 +67,7 @@
///
/// The level of the last diagnostic emitted. Used to detect level changes
/// which change the amount of information displayed.
- DiagnosticsEngine::Level LastLevel;
+ DiagnosticsEngine::Level LastLevel = DiagnosticsEngine::Ignored;
DiagnosticRenderer(const LangOptions &LangOpts,
DiagnosticOptions *DiagOpts);
@@ -97,7 +100,6 @@
virtual void endDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level) {}
-
private:
void emitBasicNote(StringRef Message);
void emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc,
@@ -142,7 +144,7 @@
public:
DiagnosticNoteRenderer(const LangOptions &LangOpts,
DiagnosticOptions *DiagOpts)
- : DiagnosticRenderer(LangOpts, DiagOpts) {}
+ : DiagnosticRenderer(LangOpts, DiagOpts) {}
~DiagnosticNoteRenderer() override;
@@ -156,5 +158,7 @@
virtual void emitNote(FullSourceLoc Loc, StringRef Message) = 0;
};
-} // end clang namespace
-#endif
+
+} // namespace clang
+
+#endif // LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index c609500..768957a 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -1,4 +1,4 @@
-//===--- FrontendOptions.h --------------------------------------*- C++ -*-===//
+//===- FrontendOptions.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,55 +14,124 @@
#include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Sema/CodeCompleteOptions.h"
#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <memory>
#include <string>
#include <vector>
#include <unordered_map>
namespace llvm {
+
class MemoryBuffer;
-}
+
+} // namespace llvm
namespace clang {
-class FileEntry;
namespace frontend {
- enum ActionKind {
- ASTDeclList, ///< Parse ASTs and list Decl nodes.
- ASTDump, ///< Parse ASTs and dump them.
- ASTPrint, ///< Parse ASTs and print them.
- ASTView, ///< Parse ASTs and view them in Graphviz.
- DumpRawTokens, ///< Dump out raw tokens.
- DumpTokens, ///< Dump out preprocessed tokens.
- EmitAssembly, ///< Emit a .s file.
- EmitBC, ///< Emit a .bc file.
- EmitHTML, ///< Translate input source into HTML.
- EmitLLVM, ///< Emit a .ll file.
- EmitLLVMOnly, ///< Generate LLVM IR, but do not emit anything.
- EmitCodeGenOnly, ///< Generate machine code, but don't emit anything.
- EmitObj, ///< Emit a .o file.
- FixIt, ///< Parse and apply any fixits to the source.
- GenerateModule, ///< Generate pre-compiled module from a module map.
- GenerateModuleInterface,///< Generate pre-compiled module from a C++ module
- ///< interface file.
- GeneratePCH, ///< Generate pre-compiled header.
- GeneratePTH, ///< Generate pre-tokenized header.
- InitOnly, ///< Only execute frontend initialization.
- ModuleFileInfo, ///< Dump information about a module file.
- VerifyPCH, ///< Load and verify that a PCH file is usable.
- ParseSyntaxOnly, ///< Parse and perform semantic analysis.
- PluginAction, ///< Run a plugin action, \see ActionName.
- PrintDeclContext, ///< Print DeclContext and their Decls.
- PrintPreamble, ///< Print the "preamble" of the input file
- PrintPreprocessedInput, ///< -E mode.
- RewriteMacros, ///< Expand macros but not \#includes.
- RewriteObjC, ///< ObjC->C Rewriter.
- RewriteTest, ///< Rewriter playground
- RunAnalysis, ///< Run one or more source code analyses.
- TemplightDump, ///< Dump template instantiations
- MigrateSource, ///< Run migrator.
- RunPreprocessorOnly ///< Just lex, no output.
- };
-}
+
+enum ActionKind {
+ /// Parse ASTs and list Decl nodes.
+ ASTDeclList,
+
+ /// Parse ASTs and dump them.
+ ASTDump,
+
+ /// Parse ASTs and print them.
+ ASTPrint,
+
+ /// Parse ASTs and view them in Graphviz.
+ ASTView,
+
+ /// Dump out raw tokens.
+ DumpRawTokens,
+
+ /// Dump out preprocessed tokens.
+ DumpTokens,
+
+ /// Emit a .s file.
+ EmitAssembly,
+
+ /// Emit a .bc file.
+ EmitBC,
+
+ /// Translate input source into HTML.
+ EmitHTML,
+
+ /// Emit a .ll file.
+ EmitLLVM,
+
+ /// Generate LLVM IR, but do not emit anything.
+ EmitLLVMOnly,
+
+ /// Generate machine code, but don't emit anything.
+ EmitCodeGenOnly,
+
+ /// Emit a .o file.
+ EmitObj,
+
+ /// Parse and apply any fixits to the source.
+ FixIt,
+
+ /// Generate pre-compiled module from a module map.
+ GenerateModule,
+
+ /// Generate pre-compiled module from a C++ module interface file.
+ GenerateModuleInterface,
+
+ /// Generate pre-compiled header.
+ GeneratePCH,
+
+ /// Generate pre-tokenized header.
+ GeneratePTH,
+
+ /// Only execute frontend initialization.
+ InitOnly,
+
+ /// Dump information about a module file.
+ ModuleFileInfo,
+
+ /// Load and verify that a PCH file is usable.
+ VerifyPCH,
+
+ /// Parse and perform semantic analysis.
+ ParseSyntaxOnly,
+
+ /// Run a plugin action, \see ActionName.
+ PluginAction,
+
+ /// Print DeclContext and their Decls.
+ PrintDeclContext,
+
+ /// Print the "preamble" of the input file
+ PrintPreamble,
+
+ /// -E mode.
+ PrintPreprocessedInput,
+
+ /// Expand macros but not \#includes.
+ RewriteMacros,
+
+ /// ObjC->C Rewriter.
+ RewriteObjC,
+
+ /// Rewriter playground
+ RewriteTest,
+
+ /// Run one or more source code analyses.
+ RunAnalysis,
+
+ /// Dump template instantiations
+ TemplightDump,
+
+ /// Run migrator.
+ MigrateSource,
+
+ /// Just lex, no output.
+ RunPreprocessorOnly
+};
+
+} // namespace frontend
/// The kind of a file that we've been handed as an input.
class InputKind {
@@ -119,6 +188,7 @@
InputKind getPreprocessed() const {
return InputKind(getLanguage(), getFormat(), true);
}
+
InputKind withFormat(Format F) const {
return InputKind(getLanguage(), F, isPreprocessed());
}
@@ -141,12 +211,12 @@
bool IsSystem = false;
public:
- FrontendInputFile() { }
+ FrontendInputFile() = default;
FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false)
- : File(File.str()), Kind(Kind), IsSystem(IsSystem) { }
+ : File(File.str()), Kind(Kind), IsSystem(IsSystem) {}
FrontendInputFile(llvm::MemoryBuffer *Buffer, InputKind Kind,
bool IsSystem = false)
- : Buffer(Buffer), Kind(Kind), IsSystem(IsSystem) { }
+ : Buffer(Buffer), Kind(Kind), IsSystem(IsSystem) {}
InputKind getKind() const { return Kind; }
bool isSystem() const { return IsSystem; }
@@ -160,6 +230,7 @@
assert(isFile());
return File;
}
+
llvm::MemoryBuffer *getBuffer() const {
assert(isBuffer());
return Buffer;
@@ -169,43 +240,67 @@
/// FrontendOptions - Options for controlling the behavior of the frontend.
class FrontendOptions {
public:
- unsigned DisableFree : 1; ///< Disable memory freeing on exit.
- unsigned RelocatablePCH : 1; ///< When generating PCH files,
- /// instruct the AST writer to create
- /// relocatable PCH files.
- unsigned ShowHelp : 1; ///< Show the -help text.
- unsigned ShowStats : 1; ///< Show frontend performance
- /// metrics and statistics.
- unsigned ShowTimers : 1; ///< Show timers for individual
- /// actions.
- unsigned ShowVersion : 1; ///< Show the -version text.
- unsigned FixWhatYouCan : 1; ///< Apply fixes even if there are
- /// unfixable errors.
- unsigned FixOnlyWarnings : 1; ///< Apply fixes only for warnings.
- unsigned FixAndRecompile : 1; ///< Apply fixes and recompile.
- unsigned FixToTemporaries : 1; ///< Apply fixes to temporary files.
- unsigned ARCMTMigrateEmitARCErrors : 1; /// Emit ARC errors even if the
- /// migrator can fix them
- unsigned SkipFunctionBodies : 1; ///< Skip over function bodies to
- /// speed up parsing in cases you do
- /// not need them (e.g. with code
- /// completion).
- unsigned UseGlobalModuleIndex : 1; ///< Whether we can use the
- ///< global module index if available.
- unsigned GenerateGlobalModuleIndex : 1; ///< Whether we can generate the
- ///< global module index if needed.
- unsigned ASTDumpDecls : 1; ///< Whether we include declaration
- ///< dumps in AST dumps.
- unsigned ASTDumpAll : 1; ///< Whether we deserialize all decls
- ///< when forming AST dumps.
- unsigned ASTDumpLookups : 1; ///< Whether we include lookup table
- ///< dumps in AST dumps.
- unsigned BuildingImplicitModule : 1; ///< Whether we are performing an
- ///< implicit module build.
- unsigned ModulesEmbedAllFiles : 1; ///< Whether we should embed all used
- ///< files into the PCM file.
- unsigned IncludeTimestamps : 1; ///< Whether timestamps should be
- ///< written to the produced PCH file.
+ /// Disable memory freeing on exit.
+ unsigned DisableFree : 1;
+
+ /// When generating PCH files, instruct the AST writer to create relocatable
+ /// PCH files.
+ unsigned RelocatablePCH : 1;
+
+ /// Show the -help text.
+ unsigned ShowHelp : 1;
+
+ /// Show frontend performance metrics and statistics.
+ unsigned ShowStats : 1;
+
+ /// Show timers for individual actions.
+ unsigned ShowTimers : 1;
+
+ /// Show the -version text.
+ unsigned ShowVersion : 1;
+
+ /// Apply fixes even if there are unfixable errors.
+ unsigned FixWhatYouCan : 1;
+
+ /// Apply fixes only for warnings.
+ unsigned FixOnlyWarnings : 1;
+
+ /// Apply fixes and recompile.
+ unsigned FixAndRecompile : 1;
+
+ /// Apply fixes to temporary files.
+ unsigned FixToTemporaries : 1;
+
+ /// Emit ARC errors even if the migrator can fix them.
+ unsigned ARCMTMigrateEmitARCErrors : 1;
+
+ /// Skip over function bodies to speed up parsing in cases you do not need
+ /// them (e.g. with code completion).
+ unsigned SkipFunctionBodies : 1;
+
+ /// Whether we can use the global module index if available.
+ unsigned UseGlobalModuleIndex : 1;
+
+ /// Whether we can generate the global module index if needed.
+ unsigned GenerateGlobalModuleIndex : 1;
+
+ /// Whether we include declaration dumps in AST dumps.
+ unsigned ASTDumpDecls : 1;
+
+ /// Whether we deserialize all decls when forming AST dumps.
+ unsigned ASTDumpAll : 1;
+
+ /// Whether we include lookup table dumps in AST dumps.
+ unsigned ASTDumpLookups : 1;
+
+ /// Whether we are performing an implicit module build.
+ unsigned BuildingImplicitModule : 1;
+
+ /// Whether we should embed all used files into the PCM file.
+ unsigned ModulesEmbedAllFiles : 1;
+
+ /// Whether timestamps should be written to the produced PCH file.
+ unsigned IncludeTimestamps : 1;
CodeCompleteOptions CodeCompleteOpts;
@@ -214,38 +309,53 @@
ARCMT_Check,
ARCMT_Modify,
ARCMT_Migrate
- } ARCMTAction;
+ } ARCMTAction = ARCMT_None;
enum {
ObjCMT_None = 0,
+
/// \brief Enable migration to modern ObjC literals.
ObjCMT_Literals = 0x1,
+
/// \brief Enable migration to modern ObjC subscripting.
ObjCMT_Subscripting = 0x2,
+
/// \brief Enable migration to modern ObjC readonly property.
ObjCMT_ReadonlyProperty = 0x4,
+
/// \brief Enable migration to modern ObjC readwrite property.
ObjCMT_ReadwriteProperty = 0x8,
+
/// \brief Enable migration to modern ObjC property.
ObjCMT_Property = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty),
+
/// \brief Enable annotation of ObjCMethods of all kinds.
ObjCMT_Annotation = 0x10,
+
/// \brief Enable migration of ObjC methods to 'instancetype'.
ObjCMT_Instancetype = 0x20,
+
/// \brief Enable migration to NS_ENUM/NS_OPTIONS macros.
ObjCMT_NsMacros = 0x40,
+
/// \brief Enable migration to add conforming protocols.
ObjCMT_ProtocolConformance = 0x80,
+
/// \brief prefer 'atomic' property over 'nonatomic'.
ObjCMT_AtomicProperty = 0x100,
+
/// \brief annotate property with NS_RETURNS_INNER_POINTER
ObjCMT_ReturnsInnerPointerProperty = 0x200,
+
/// \brief use NS_NONATOMIC_IOSONLY for property 'atomic' attribute
ObjCMT_NsAtomicIOSOnlyProperty = 0x400,
+
/// \brief Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
ObjCMT_DesignatedInitializer = 0x800,
+
/// \brief Enable converting setter/getter expressions to property-dot syntx.
ObjCMT_PropertyDotSyntax = 0x1000,
+
ObjCMT_MigrateDecls = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty |
ObjCMT_Annotation | ObjCMT_Instancetype |
ObjCMT_NsMacros | ObjCMT_ProtocolConformance |
@@ -254,7 +364,7 @@
ObjCMT_MigrateAll = (ObjCMT_Literals | ObjCMT_Subscripting |
ObjCMT_MigrateDecls | ObjCMT_PropertyDotSyntax)
};
- unsigned ObjCMTAction;
+ unsigned ObjCMTAction = ObjCMT_None;
std::string ObjCMTWhiteListPath;
std::string MTMigrateDir;
@@ -280,7 +390,7 @@
ParsedSourceLocation CodeCompletionAt;
/// The frontend action to perform.
- frontend::ActionKind ProgramAction;
+ frontend::ActionKind ProgramAction = frontend::ParseSyntaxOnly;
/// The name of the action to run when using a plugin action.
std::string ActionName;
@@ -329,17 +439,15 @@
std::string StatsFile;
public:
- FrontendOptions() :
- DisableFree(false), RelocatablePCH(false), ShowHelp(false),
- ShowStats(false), ShowTimers(false), ShowVersion(false),
- FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false),
- FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false),
- SkipFunctionBodies(false), UseGlobalModuleIndex(true),
- GenerateGlobalModuleIndex(true), ASTDumpDecls(false), ASTDumpLookups(false),
- BuildingImplicitModule(false), ModulesEmbedAllFiles(false),
- IncludeTimestamps(true), ARCMTAction(ARCMT_None),
- ObjCMTAction(ObjCMT_None), ProgramAction(frontend::ParseSyntaxOnly)
- {}
+ FrontendOptions()
+ : DisableFree(false), RelocatablePCH(false), ShowHelp(false),
+ ShowStats(false), ShowTimers(false), ShowVersion(false),
+ FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false),
+ FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false),
+ SkipFunctionBodies(false), UseGlobalModuleIndex(true),
+ GenerateGlobalModuleIndex(true), ASTDumpDecls(false),
+ ASTDumpLookups(false), BuildingImplicitModule(false),
+ ModulesEmbedAllFiles(false), IncludeTimestamps(true) {}
/// getInputKindForExtension - Return the appropriate input kind for a file
/// extension. For example, "c" would return InputKind::C.
@@ -349,6 +457,6 @@
static InputKind getInputKindForExtension(StringRef Extension);
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H
diff --git a/include/clang/Frontend/FrontendPluginRegistry.h b/include/clang/Frontend/FrontendPluginRegistry.h
index 9d7ee08..9a85e89 100644
--- a/include/clang/Frontend/FrontendPluginRegistry.h
+++ b/include/clang/Frontend/FrontendPluginRegistry.h
@@ -1,4 +1,4 @@
-//===-- FrontendAction.h - Pluggable Frontend Action Interface --*- C++ -*-===//
+//===- FrontendPluginRegistry.h ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,6 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
+// Pluggable Frontend Action Interface
+//
+//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
#define LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
@@ -16,8 +20,8 @@
namespace clang {
/// The frontend plugin registry.
-typedef llvm::Registry<PluginASTAction> FrontendPluginRegistry;
+using FrontendPluginRegistry = llvm::Registry<PluginASTAction>;
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
diff --git a/include/clang/Frontend/PrecompiledPreamble.h b/include/clang/Frontend/PrecompiledPreamble.h
index f1898f5..aa8fb82 100644
--- a/include/clang/Frontend/PrecompiledPreamble.h
+++ b/include/clang/Frontend/PrecompiledPreamble.h
@@ -289,7 +289,6 @@
PreambleIsEmpty = 1,
CouldntCreateTempFile,
CouldntCreateTargetInfo,
- CouldntCreateVFSOverlay,
BeginSourceFileFailed,
CouldntEmitPCH
};
diff --git a/include/clang/Frontend/SerializedDiagnosticReader.h b/include/clang/Frontend/SerializedDiagnosticReader.h
index 0747984..31637c2 100644
--- a/include/clang/Frontend/SerializedDiagnosticReader.h
+++ b/include/clang/Frontend/SerializedDiagnosticReader.h
@@ -1,4 +1,4 @@
-//===--- SerializedDiagnosticReader.h - Reads diagnostics -------*- C++ -*-===//
+//===- SerializedDiagnosticReader.h - Reads diagnostics ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,14 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FRONTEND_SERIALIZED_DIAGNOSTIC_READER_H_
-#define LLVM_CLANG_FRONTEND_SERIALIZED_DIAGNOSTIC_READER_H_
+#ifndef LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICREADER_H
+#define LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICREADER_H
#include "clang/Basic/LLVM.h"
#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorOr.h"
+#include <system_error>
namespace clang {
namespace serialized_diags {
@@ -47,6 +49,7 @@
unsigned Line;
unsigned Col;
unsigned Offset;
+
Location(unsigned FileID, unsigned Line, unsigned Col, unsigned Offset)
: FileID(FileID), Line(Line), Col(Col), Offset(Offset) {}
};
@@ -57,8 +60,8 @@
/// the various constructs that are found in serialized diagnostics.
class SerializedDiagnosticReader {
public:
- SerializedDiagnosticReader() {}
- virtual ~SerializedDiagnosticReader() {}
+ SerializedDiagnosticReader() = default;
+ virtual ~SerializedDiagnosticReader() = default;
/// \brief Read the diagnostics in \c File
std::error_code readDiagnostics(StringRef File);
@@ -78,53 +81,59 @@
protected:
/// \brief Visit the start of a diagnostic block.
- virtual std::error_code visitStartOfDiagnostic() {
- return std::error_code();
- }
+ virtual std::error_code visitStartOfDiagnostic() { return {}; }
+
/// \brief Visit the end of a diagnostic block.
- virtual std::error_code visitEndOfDiagnostic() { return std::error_code(); }
+ virtual std::error_code visitEndOfDiagnostic() { return {}; }
+
/// \brief Visit a category. This associates the category \c ID to a \c Name.
virtual std::error_code visitCategoryRecord(unsigned ID, StringRef Name) {
- return std::error_code();
+ return {};
}
+
/// \brief Visit a flag. This associates the flag's \c ID to a \c Name.
virtual std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) {
- return std::error_code();
+ return {};
}
+
/// \brief Visit a diagnostic.
virtual std::error_code
visitDiagnosticRecord(unsigned Severity, const Location &Location,
unsigned Category, unsigned Flag, StringRef Message) {
- return std::error_code();
+ return {};
}
+
/// \brief Visit a filename. This associates the file's \c ID to a \c Name.
virtual std::error_code visitFilenameRecord(unsigned ID, unsigned Size,
unsigned Timestamp,
StringRef Name) {
- return std::error_code();
+ return {};
}
+
/// \brief Visit a fixit hint.
virtual std::error_code
visitFixitRecord(const Location &Start, const Location &End, StringRef Text) {
- return std::error_code();
+ return {};
}
+
/// \brief Visit a source range.
virtual std::error_code visitSourceRangeRecord(const Location &Start,
const Location &End) {
- return std::error_code();
+ return {};
}
+
/// \brief Visit the version of the set of diagnostics.
- virtual std::error_code visitVersionRecord(unsigned Version) {
- return std::error_code();
- }
+ virtual std::error_code visitVersionRecord(unsigned Version) { return {}; }
};
-} // end serialized_diags namespace
-} // end clang namespace
+} // namespace serialized_diags
+} // namespace clang
namespace std {
+
template <>
struct is_error_code_enum<clang::serialized_diags::SDError> : std::true_type {};
-}
-#endif
+} // namespace std
+
+#endif // LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICREADER_H
diff --git a/include/clang/Frontend/TextDiagnosticBuffer.h b/include/clang/Frontend/TextDiagnosticBuffer.h
index 23f168e..2295f9d 100644
--- a/include/clang/Frontend/TextDiagnosticBuffer.h
+++ b/include/clang/Frontend/TextDiagnosticBuffer.h
@@ -1,4 +1,4 @@
-//===--- TextDiagnosticBuffer.h - Buffer Text Diagnostics -------*- C++ -*-===//
+//===- TextDiagnosticBuffer.h - Buffer Text Diagnostics ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,37 +15,41 @@
#define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include <cstddef>
+#include <string>
+#include <utility>
#include <vector>
namespace clang {
-class Preprocessor;
-class SourceManager;
-
class TextDiagnosticBuffer : public DiagnosticConsumer {
public:
- typedef std::vector<std::pair<SourceLocation, std::string> > DiagList;
- typedef DiagList::iterator iterator;
- typedef DiagList::const_iterator const_iterator;
+ using DiagList = std::vector<std::pair<SourceLocation, std::string>>;
+ using iterator = DiagList::iterator;
+ using const_iterator = DiagList::const_iterator;
+
private:
DiagList Errors, Warnings, Remarks, Notes;
+
/// All - All diagnostics in the order in which they were generated. That
/// order likely doesn't correspond to user input order, but it at least
/// keeps notes in the right places. Each pair in the vector is a diagnostic
/// level and an index into the corresponding DiagList above.
std::vector<std::pair<DiagnosticsEngine::Level, size_t>> All;
+
public:
- const_iterator err_begin() const { return Errors.begin(); }
- const_iterator err_end() const { return Errors.end(); }
+ const_iterator err_begin() const { return Errors.begin(); }
+ const_iterator err_end() const { return Errors.end(); }
const_iterator warn_begin() const { return Warnings.begin(); }
- const_iterator warn_end() const { return Warnings.end(); }
+ const_iterator warn_end() const { return Warnings.end(); }
const_iterator remark_begin() const { return Remarks.begin(); }
- const_iterator remark_end() const { return Remarks.end(); }
+ const_iterator remark_end() const { return Remarks.end(); }
const_iterator note_begin() const { return Notes.begin(); }
- const_iterator note_end() const { return Notes.end(); }
+ const_iterator note_end() const { return Notes.end(); }
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) override;
@@ -55,6 +59,6 @@
void FlushDiagnostics(DiagnosticsEngine &Diags) const;
};
-} // end namspace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index 8ccc319..47a5e91 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -1,4 +1,4 @@
-//===--- Utils.h - Misc utilities for the front-end -------------*- C++ -*-===//
+//===- Utils.h - Misc utilities for the front-end ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,45 +15,49 @@
#define LLVM_CLANG_FRONTEND_UTILS_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Option/OptSpecifier.h"
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <system_error>
#include <utility>
+#include <vector>
namespace llvm {
-class raw_fd_ostream;
+
class Triple;
namespace opt {
+
class ArgList;
-}
-}
+
+} // namespace opt
+
+} // namespace llvm
namespace clang {
-class ASTConsumer;
+
class ASTReader;
class CompilerInstance;
class CompilerInvocation;
-class Decl;
class DependencyOutputOptions;
class DiagnosticsEngine;
-class DiagnosticOptions;
class ExternalSemaSource;
-class FileManager;
+class FrontendOptions;
class HeaderSearch;
class HeaderSearchOptions;
-class IdentifierTable;
class LangOptions;
class PCHContainerReader;
class Preprocessor;
class PreprocessorOptions;
class PreprocessorOutputOptions;
-class SourceManager;
-class Stmt;
-class TargetInfo;
-class FrontendOptions;
/// Apply the header search options to get given HeaderSearch object.
void ApplyHeaderSearchOptions(HeaderSearch &HS,
@@ -68,7 +72,7 @@
const FrontendOptions &FEOpts);
/// DoPrintPreprocessedInput - Implement -E mode.
-void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream* OS,
+void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
const PreprocessorOutputOptions &Opts);
/// An interface for collecting the dependencies of a compilation. Users should
@@ -78,9 +82,11 @@
/// interface.
class DependencyCollector {
public:
+ virtual ~DependencyCollector();
+
virtual void attachToPreprocessor(Preprocessor &PP);
virtual void attachToASTReader(ASTReader &R);
- llvm::ArrayRef<std::string> getDependencies() const { return Dependencies; }
+ ArrayRef<std::string> getDependencies() const { return Dependencies; }
/// Called when a new file is seen. Return true if \p Filename should be added
/// to the list of dependencies.
@@ -88,17 +94,19 @@
/// The default implementation ignores <built-in> and system files.
virtual bool sawDependency(StringRef Filename, bool FromModule,
bool IsSystem, bool IsModuleFile, bool IsMissing);
+
/// Called when the end of the main file is reached.
- virtual void finishedMainFile() { }
+ virtual void finishedMainFile() {}
+
/// Return true if system files should be passed to sawDependency().
virtual bool needSystemDependencies() { return false; }
- virtual ~DependencyCollector();
-public: // implementation detail
+ // implementation detail
/// Add a dependency \p Filename if it has not been seen before and
/// sawDependency() returns true.
void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem,
bool IsModuleFile, bool IsMissing);
+
private:
llvm::StringSet<> Seen;
std::vector<std::string> Dependencies;
@@ -110,10 +118,13 @@
/// loaded.
class DependencyFileGenerator {
void *Impl; // Opaque implementation
+
DependencyFileGenerator(void *Impl);
+
public:
static DependencyFileGenerator *CreateAndAttachToPreprocessor(
Preprocessor &PP, const DependencyOutputOptions &Opts);
+
void AttachToASTReader(ASTReader &R);
};
@@ -124,15 +135,20 @@
bool HasErrors = false;
llvm::StringSet<> Seen;
vfs::YAMLVFSWriter VFSWriter;
-
llvm::StringMap<std::string> SymLinkMap;
bool getRealPath(StringRef SrcPath, SmallVectorImpl<char> &Result);
- std::error_code copyToRoot(StringRef Src, StringRef Dst = "");
+ std::error_code copyToRoot(StringRef Src, StringRef Dst = {});
+
public:
+ ModuleDependencyCollector(std::string DestDir)
+ : DestDir(std::move(DestDir)) {}
+ ~ModuleDependencyCollector() override { writeFileMap(); }
+
StringRef getDest() { return DestDir; }
bool insertSeen(StringRef Filename) { return Seen.insert(Filename).second; }
- void addFile(StringRef Filename, StringRef FileDst = "");
+ void addFile(StringRef Filename, StringRef FileDst = {});
+
void addFileMapping(StringRef VPath, StringRef RPath) {
VFSWriter.addFileMapping(VPath, RPath);
}
@@ -142,9 +158,6 @@
void writeFileMap();
bool hasErrors() { return HasErrors; }
- ModuleDependencyCollector(std::string DestDir)
- : DestDir(std::move(DestDir)) {}
- ~ModuleDependencyCollector() { writeFileMap(); }
};
/// AttachDependencyGraphGen - Create a dependency graph generator, and attach
@@ -167,7 +180,7 @@
void AttachHeaderIncludeGen(Preprocessor &PP,
const DependencyOutputOptions &DepOpts,
bool ShowAllHeaders = false,
- StringRef OutputPath = "",
+ StringRef OutputPath = {},
bool ShowDepth = true, bool MSStyle = false);
/// Cache tokens for use with PCH. Note that this requires a seekable stream.
@@ -221,6 +234,6 @@
BuryPointer(Ptr.release());
}
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_UTILS_H
diff --git a/include/clang/Frontend/VerifyDiagnosticConsumer.h b/include/clang/Frontend/VerifyDiagnosticConsumer.h
index 8d71fb9..45499b4 100644
--- a/include/clang/Frontend/VerifyDiagnosticConsumer.h
+++ b/include/clang/Frontend/VerifyDiagnosticConsumer.h
@@ -11,18 +11,24 @@
#define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/ADT/STLExtras.h"
-#include <climits>
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <limits>
#include <memory>
+#include <string>
+#include <vector>
namespace clang {
-class DiagnosticsEngine;
-class TextDiagnosticBuffer;
class FileEntry;
+class LangOptions;
+class SourceManager;
+class TextDiagnosticBuffer;
/// VerifyDiagnosticConsumer - Create a diagnostic client which will use
/// markers in the input source to check that all the emitted diagnostics match
@@ -153,7 +159,7 @@
public:
/// Constant representing n or more matches.
- static const unsigned MaxCount = UINT_MAX;
+ static const unsigned MaxCount = std::numeric_limits<unsigned>::max();
SourceLocation DirectiveLoc;
SourceLocation DiagnosticLoc;
@@ -161,7 +167,9 @@
unsigned Min, Max;
bool MatchAnyLine;
- virtual ~Directive() { }
+ Directive(const Directive &) = delete;
+ Directive &operator=(const Directive &) = delete;
+ virtual ~Directive() = default;
// Returns true if directive text is valid.
// Otherwise returns false and populates E.
@@ -173,22 +181,17 @@
protected:
Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max)
- : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
- Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) {
- assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
- assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) &&
- "DiagnosticLoc is invalid!");
+ : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
+ Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) {
+ assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
+ assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) &&
+ "DiagnosticLoc is invalid!");
}
-
- private:
- Directive(const Directive &) = delete;
- void operator=(const Directive &) = delete;
};
- typedef std::vector<std::unique_ptr<Directive>> DirectiveList;
+ using DirectiveList = std::vector<std::unique_ptr<Directive>>;
/// ExpectedData - owns directive objects and deletes on destructor.
- ///
struct ExpectedData {
DirectiveList Errors;
DirectiveList Warnings;
@@ -215,14 +218,15 @@
DiagnosticConsumer *PrimaryClient;
std::unique_ptr<DiagnosticConsumer> PrimaryClientOwner;
std::unique_ptr<TextDiagnosticBuffer> Buffer;
- const Preprocessor *CurrentPreprocessor;
- const LangOptions *LangOpts;
- SourceManager *SrcManager;
- unsigned ActiveSourceFiles;
+ const Preprocessor *CurrentPreprocessor = nullptr;
+ const LangOptions *LangOpts = nullptr;
+ SourceManager *SrcManager = nullptr;
+ unsigned ActiveSourceFiles = 0;
DirectiveStatus Status;
ExpectedData ED;
void CheckDiagnostics();
+
void setSourceManager(SourceManager &SM) {
assert((!SrcManager || SrcManager == &SM) && "SourceManager changed!");
SrcManager = &SM;
@@ -231,14 +235,18 @@
// These facilities are used for validation in debug builds.
class UnparsedFileStatus {
llvm::PointerIntPair<const FileEntry *, 1, bool> Data;
+
public:
UnparsedFileStatus(const FileEntry *File, bool FoundDirectives)
- : Data(File, FoundDirectives) {}
+ : Data(File, FoundDirectives) {}
+
const FileEntry *getFile() const { return Data.getPointer(); }
bool foundDirectives() const { return Data.getInt(); }
};
- typedef llvm::DenseMap<FileID, const FileEntry *> ParsedFilesMap;
- typedef llvm::DenseMap<FileID, UnparsedFileStatus> UnparsedFilesMap;
+
+ using ParsedFilesMap = llvm::DenseMap<FileID, const FileEntry *>;
+ using UnparsedFilesMap = llvm::DenseMap<FileID, UnparsedFileStatus>;
+
ParsedFilesMap ParsedFiles;
UnparsedFilesMap UnparsedFiles;
@@ -274,6 +282,6 @@
const Diagnostic &Info) override;
};
-} // end namspace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 3bf3855..0df9f3f 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -179,6 +179,7 @@
std::unique_ptr<PragmaHandler> MSSection;
std::unique_ptr<PragmaHandler> MSRuntimeChecks;
std::unique_ptr<PragmaHandler> MSIntrinsic;
+ std::unique_ptr<PragmaHandler> MSOptimize;
std::unique_ptr<PragmaHandler> CUDAForceHostDeviceHandler;
std::unique_ptr<PragmaHandler> OptimizeHandler;
std::unique_ptr<PragmaHandler> LoopHintHandler;
diff --git a/include/clang/Parse/RAIIObjectsForParser.h b/include/clang/Parse/RAIIObjectsForParser.h
index acaeb44..9a9453b 100644
--- a/include/clang/Parse/RAIIObjectsForParser.h
+++ b/include/clang/Parse/RAIIObjectsForParser.h
@@ -378,8 +378,6 @@
}
}
- enum { MaxDepth = 256 };
-
bool diagnoseOverflow();
bool diagnoseMissingClose();
diff --git a/include/clang/Rewrite/Core/DeltaTree.h b/include/clang/Rewrite/Core/DeltaTree.h
index fbffb38..f798e9f 100644
--- a/include/clang/Rewrite/Core/DeltaTree.h
+++ b/include/clang/Rewrite/Core/DeltaTree.h
@@ -1,4 +1,4 @@
-//===--- DeltaTree.h - B-Tree for Rewrite Delta tracking --------*- C++ -*-===//
+//===- DeltaTree.h - B-Tree for Rewrite Delta tracking ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,8 +14,6 @@
#ifndef LLVM_CLANG_REWRITE_CORE_DELTATREE_H
#define LLVM_CLANG_REWRITE_CORE_DELTATREE_H
-#include "llvm/Support/Compiler.h"
-
namespace clang {
/// DeltaTree - a multiway search tree (BTree) structure with some fancy
@@ -27,12 +25,14 @@
/// as well, without traversing the whole tree.
class DeltaTree {
void *Root; // "DeltaTreeNode *"
- void operator=(const DeltaTree &) = delete;
+
public:
DeltaTree();
// Note: Currently we only support copying when the RHS is empty.
DeltaTree(const DeltaTree &RHS);
+
+ DeltaTree &operator=(const DeltaTree &) = delete;
~DeltaTree();
/// getDeltaAt - Return the accumulated delta at the specified file offset.
@@ -45,6 +45,7 @@
/// into the current DeltaTree at offset FileIndex.
void AddDelta(unsigned FileIndex, int Delta);
};
-} // end namespace clang
-#endif
+} // namespace clang
+
+#endif // LLVM_CLANG_REWRITE_CORE_DELTATREE_H
diff --git a/include/clang/Rewrite/Core/RewriteBuffer.h b/include/clang/Rewrite/Core/RewriteBuffer.h
index d69c69b..1e69054 100644
--- a/include/clang/Rewrite/Core/RewriteBuffer.h
+++ b/include/clang/Rewrite/Core/RewriteBuffer.h
@@ -1,4 +1,4 @@
-//===--- RewriteBuffer.h - Buffer rewriting interface -----------*- C++ -*-===//
+//===- RewriteBuffer.h - Buffer rewriting interface -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,7 +16,6 @@
#include "llvm/ADT/StringRef.h"
namespace clang {
- class Rewriter;
/// RewriteBuffer - As code is rewritten, SourceBuffer's from the original
/// input with modifications get a new RewriteBuffer associated with them. The
@@ -26,12 +25,16 @@
/// locations after the insertion point have to be mapped.
class RewriteBuffer {
friend class Rewriter;
+
/// Deltas - Keep track of all the deltas in the source code due to insertions
/// and deletions.
DeltaTree Deltas;
+
RewriteRope Buffer;
+
public:
- typedef RewriteRope::const_iterator iterator;
+ using iterator = RewriteRope::const_iterator;
+
iterator begin() const { return Buffer.begin(); }
iterator end() const { return Buffer.end(); }
unsigned size() const { return Buffer.size(); }
@@ -61,7 +64,6 @@
/// InsertText - Insert some text at the specified point, where the offset in
/// the buffer is specified relative to the original SourceBuffer. The
/// text is inserted after the specified location.
- ///
void InsertText(unsigned OrigOffset, StringRef Str,
bool InsertAfter = true);
@@ -87,8 +89,7 @@
void ReplaceText(unsigned OrigOffset, unsigned OrigLength,
StringRef NewStr);
-private: // Methods only usable by Rewriter.
-
+private:
/// getMappedOffset - Given an offset into the original SourceBuffer that this
/// RewriteBuffer is based on, map it into the offset space of the
/// RewriteBuffer. If AfterInserts is true and if the OrigOffset indicates a
@@ -112,6 +113,6 @@
}
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_REWRITE_CORE_REWRITEBUFFER_H
diff --git a/include/clang/Rewrite/Core/RewriteRope.h b/include/clang/Rewrite/Core/RewriteRope.h
index 5002554..2a0e0a4 100644
--- a/include/clang/Rewrite/Core/RewriteRope.h
+++ b/include/clang/Rewrite/Core/RewriteRope.h
@@ -1,4 +1,4 @@
-//===--- RewriteRope.h - Rope specialized for rewriter ----------*- C++ -*-===//
+//===- RewriteRope.h - Rope specialized for rewriter ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,13 +16,13 @@
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstddef>
-#include <cstring>
#include <iterator>
+#include <utility>
namespace clang {
+
//===--------------------------------------------------------------------===//
// RopeRefCountString Class
//===--------------------------------------------------------------------===//
@@ -58,11 +58,10 @@
/// different offsets) which is a nice constant time operation.
struct RopePiece {
llvm::IntrusiveRefCntPtr<RopeRefCountString> StrData;
- unsigned StartOffs;
- unsigned EndOffs;
+ unsigned StartOffs = 0;
+ unsigned EndOffs = 0;
- RopePiece() : StrData(nullptr), StartOffs(0), EndOffs(0) {}
-
+ RopePiece() = default;
RopePiece(llvm::IntrusiveRefCntPtr<RopeRefCountString> Str, unsigned Start,
unsigned End)
: StrData(std::move(Str)), StartOffs(Start), EndOffs(End) {}
@@ -88,18 +87,18 @@
class RopePieceBTreeIterator :
public std::iterator<std::forward_iterator_tag, const char, ptrdiff_t> {
/// CurNode - The current B+Tree node that we are inspecting.
- const void /*RopePieceBTreeLeaf*/ *CurNode;
+ const void /*RopePieceBTreeLeaf*/ *CurNode = nullptr;
+
/// CurPiece - The current RopePiece in the B+Tree node that we're
/// inspecting.
- const RopePiece *CurPiece;
+ const RopePiece *CurPiece = nullptr;
+
/// CurChar - The current byte in the RopePiece we are pointing to.
- unsigned CurChar;
+ unsigned CurChar = 0;
+
public:
- // begin iterator.
+ RopePieceBTreeIterator() = default;
RopePieceBTreeIterator(const void /*RopePieceBTreeNode*/ *N);
- // end iterator
- RopePieceBTreeIterator()
- : CurNode(nullptr), CurPiece(nullptr), CurChar(0) {}
char operator*() const {
return (*CurPiece)[CurChar];
@@ -119,7 +118,8 @@
MoveToNextPiece();
return *this;
}
- inline RopePieceBTreeIterator operator++(int) { // Postincrement
+
+ RopePieceBTreeIterator operator++(int) { // Postincrement
RopePieceBTreeIterator tmp = *this; ++*this; return tmp;
}
@@ -136,13 +136,15 @@
class RopePieceBTree {
void /*RopePieceBTreeNode*/ *Root;
- void operator=(const RopePieceBTree &) = delete;
+
public:
RopePieceBTree();
RopePieceBTree(const RopePieceBTree &RHS);
+ RopePieceBTree &operator=(const RopePieceBTree &) = delete;
~RopePieceBTree();
- typedef RopePieceBTreeIterator iterator;
+ using iterator = RopePieceBTreeIterator;
+
iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }
unsigned size() const;
@@ -168,19 +170,18 @@
/// We allocate space for string data out of a buffer of size AllocChunkSize.
/// This keeps track of how much space is left.
llvm::IntrusiveRefCntPtr<RopeRefCountString> AllocBuffer;
- unsigned AllocOffs;
enum { AllocChunkSize = 4080 };
+ unsigned AllocOffs = AllocChunkSize;
public:
- RewriteRope() : AllocBuffer(nullptr), AllocOffs(AllocChunkSize) {}
- RewriteRope(const RewriteRope &RHS)
- : Chunks(RHS.Chunks), AllocBuffer(nullptr), AllocOffs(AllocChunkSize) {
- }
+ RewriteRope() = default;
+ RewriteRope(const RewriteRope &RHS) : Chunks(RHS.Chunks) {}
- typedef RopePieceBTree::iterator iterator;
- typedef RopePieceBTree::iterator const_iterator;
+ using iterator = RopePieceBTree::iterator;
+ using const_iterator = RopePieceBTree::iterator;
+
iterator begin() const { return Chunks.begin(); }
- iterator end() const { return Chunks.end(); }
+ iterator end() const { return Chunks.end(); }
unsigned size() const { return Chunks.size(); }
void clear() {
@@ -209,6 +210,6 @@
RopePiece MakeRopeString(const char *Start, const char *End);
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H
diff --git a/include/clang/Rewrite/Core/Rewriter.h b/include/clang/Rewrite/Core/Rewriter.h
index 800372e..cf33cd6 100644
--- a/include/clang/Rewrite/Core/Rewriter.h
+++ b/include/clang/Rewrite/Core/Rewriter.h
@@ -1,4 +1,4 @@
-//===--- Rewriter.h - Code rewriting interface ------------------*- C++ -*-===//
+//===- Rewriter.h - Code rewriting interface --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,52 +15,55 @@
#ifndef LLVM_CLANG_REWRITE_CORE_REWRITER_H
#define LLVM_CLANG_REWRITE_CORE_REWRITER_H
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Rewrite/Core/RewriteBuffer.h"
-#include <cstring>
+#include "llvm/ADT/StringRef.h"
#include <map>
#include <string>
namespace clang {
- class LangOptions;
- class SourceManager;
+
+class LangOptions;
+class SourceManager;
/// Rewriter - This is the main interface to the rewrite buffers. Its primary
/// job is to dispatch high-level requests to the low-level RewriteBuffers that
/// are involved.
class Rewriter {
- SourceManager *SourceMgr;
- const LangOptions *LangOpts;
+ SourceManager *SourceMgr = nullptr;
+ const LangOptions *LangOpts = nullptr;
std::map<FileID, RewriteBuffer> RewriteBuffers;
+
public:
struct RewriteOptions {
/// \brief Given a source range, true to include previous inserts at the
/// beginning of the range as part of the range itself (true by default).
- bool IncludeInsertsAtBeginOfRange;
+ bool IncludeInsertsAtBeginOfRange = true;
+
/// \brief Given a source range, true to include previous inserts at the
/// end of the range as part of the range itself (true by default).
- bool IncludeInsertsAtEndOfRange;
+ bool IncludeInsertsAtEndOfRange = true;
+
/// \brief If true and removing some text leaves a blank line
/// also remove the empty line (false by default).
- bool RemoveLineIfEmpty;
+ bool RemoveLineIfEmpty = false;
- RewriteOptions()
- : IncludeInsertsAtBeginOfRange(true),
- IncludeInsertsAtEndOfRange(true),
- RemoveLineIfEmpty(false) { }
+ RewriteOptions() {}
};
- typedef std::map<FileID, RewriteBuffer>::iterator buffer_iterator;
- typedef std::map<FileID, RewriteBuffer>::const_iterator const_buffer_iterator;
+ using buffer_iterator = std::map<FileID, RewriteBuffer>::iterator;
+ using const_buffer_iterator = std::map<FileID, RewriteBuffer>::const_iterator;
+ explicit Rewriter() = default;
explicit Rewriter(SourceManager &SM, const LangOptions &LO)
- : SourceMgr(&SM), LangOpts(&LO) {}
- explicit Rewriter() : SourceMgr(nullptr), LangOpts(nullptr) {}
+ : SourceMgr(&SM), LangOpts(&LO) {}
void setSourceMgr(SourceManager &SM, const LangOptions &LO) {
SourceMgr = &SM;
LangOpts = &LO;
}
+
SourceManager &getSourceMgr() const { return *SourceMgr; }
const LangOptions &getLangOpts() const { return *LangOpts; }
@@ -82,7 +85,6 @@
/// in different buffers, this returns an empty string.
///
/// Note that this method is not particularly efficient.
- ///
std::string getRewrittenText(SourceRange Range) const;
/// InsertText - Insert the specified string at the specified location in the
@@ -190,6 +192,6 @@
unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const;
};
-} // end namespace clang
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_REWRITE_CORE_REWRITER_H
diff --git a/include/clang/Rewrite/Core/TokenRewriter.h b/include/clang/Rewrite/Core/TokenRewriter.h
index 0f71e81..ab2c2c8 100644
--- a/include/clang/Rewrite/Core/TokenRewriter.h
+++ b/include/clang/Rewrite/Core/TokenRewriter.h
@@ -1,4 +1,4 @@
-//===--- TokenRewriter.h - Token-based Rewriter -----------------*- C++ -*-===//
+//===- TokenRewriter.h - Token-based Rewriter -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,13 +17,16 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Token.h"
+#include <cassert>
#include <list>
#include <map>
#include <memory>
namespace clang {
- class LangOptions;
- class ScratchBuffer;
+
+class LangOptions;
+class ScratchBuffer;
+class SourceManager;
class TokenRewriter {
/// TokenList - This is the list of raw tokens that make up this file. Each
@@ -31,7 +34,7 @@
std::list<Token> TokenList;
/// TokenRefTy - This is the type used to refer to a token in the TokenList.
- typedef std::list<Token>::iterator TokenRefTy;
+ using TokenRefTy = std::list<Token>::iterator;
/// TokenAtLoc - This map indicates which token exists at a specific
/// SourceLocation. Since each token has a unique SourceLocation, this is a
@@ -40,23 +43,24 @@
std::map<SourceLocation, TokenRefTy> TokenAtLoc;
/// ScratchBuf - This is the buffer that we create scratch tokens from.
- ///
std::unique_ptr<ScratchBuffer> ScratchBuf;
- TokenRewriter(const TokenRewriter &) = delete;
- void operator=(const TokenRewriter &) = delete;
public:
/// TokenRewriter - This creates a TokenRewriter for the file with the
/// specified FileID.
TokenRewriter(FileID FID, SourceManager &SM, const LangOptions &LO);
+
+ TokenRewriter(const TokenRewriter &) = delete;
+ TokenRewriter &operator=(const TokenRewriter &) = delete;
~TokenRewriter();
- typedef std::list<Token>::const_iterator token_iterator;
+ using token_iterator = std::list<Token>::const_iterator;
+
token_iterator token_begin() const { return TokenList.begin(); }
token_iterator token_end() const { return TokenList.end(); }
-
token_iterator AddTokenBefore(token_iterator I, const char *Val);
+
token_iterator AddTokenAfter(token_iterator I, const char *Val) {
assert(I != token_end() && "Cannot insert after token_end()!");
return AddTokenBefore(++I, Val);
@@ -72,8 +76,6 @@
TokenRefTy AddToken(const Token &T, TokenRefTy Where);
};
+} // namespace clang
-
-} // end namespace clang
-
-#endif
+#endif // LLVM_CLANG_REWRITE_CORE_TOKENREWRITER_H
diff --git a/include/clang/Rewrite/Frontend/FixItRewriter.h b/include/clang/Rewrite/Frontend/FixItRewriter.h
index 3b1b31e..18ab776 100644
--- a/include/clang/Rewrite/Frontend/FixItRewriter.h
+++ b/include/clang/Rewrite/Frontend/FixItRewriter.h
@@ -1,4 +1,4 @@
-//===--- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ----*- C++ -*-===//
+//===- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,24 +12,28 @@
// then forwards any diagnostics to the adapted diagnostic client.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
#define LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Edit/EditedSource.h"
#include "clang/Rewrite/Core/Rewriter.h"
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
namespace clang {
+class LangOptions;
class SourceManager;
-class FileEntry;
class FixItOptions {
public:
- FixItOptions() : InPlace(false), FixWhatYouCan(false),
- FixOnlyWarnings(false), Silent(false) { }
-
+ FixItOptions() = default;
virtual ~FixItOptions();
/// \brief This file is about to be rewritten. Return the name of the file
@@ -38,23 +42,22 @@
/// \param fd out parameter for file descriptor. After the call it may be set
/// to an open file descriptor for the returned filename, or it will be -1
/// otherwise.
- ///
virtual std::string RewriteFilename(const std::string &Filename, int &fd) = 0;
/// True if files should be updated in place. RewriteFilename is only called
/// if this is false.
- bool InPlace;
+ bool InPlace = false;
/// \brief Whether to abort fixing a file when not all errors could be fixed.
- bool FixWhatYouCan;
+ bool FixWhatYouCan = false;
/// \brief Whether to only fix warnings and not errors.
- bool FixOnlyWarnings;
+ bool FixOnlyWarnings = false;
/// \brief If true, only pass the diagnostic to the actual diagnostic consumer
/// if it is an error or a fixit was applied as part of the diagnostic.
/// It basically silences warnings without accompanying fixits.
- bool Silent;
+ bool Silent = false;
};
class FixItRewriter : public DiagnosticConsumer {
@@ -77,14 +80,12 @@
FixItOptions *FixItOpts;
/// \brief The number of rewriter failures.
- unsigned NumFailures;
+ unsigned NumFailures = 0;
/// \brief Whether the previous diagnostic was not passed to the consumer.
- bool PrevDiagSilenced;
+ bool PrevDiagSilenced = false;
public:
- typedef Rewriter::buffer_iterator iterator;
-
/// \brief Initialize a new fix-it rewriter.
FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
const LangOptions &LangOpts, FixItOptions *FixItOpts);
@@ -97,6 +98,8 @@
return Rewrite.getRewriteBufferFor(ID) != nullptr;
}
+ using iterator = Rewriter::buffer_iterator;
+
// Iteration over files with changes.
iterator buffer_begin() { return Rewrite.buffer_begin(); }
iterator buffer_end() { return Rewrite.buffer_end(); }
@@ -110,7 +113,7 @@
///
/// \returns true if there was an error, false otherwise.
bool WriteFixedFiles(
- std::vector<std::pair<std::string, std::string> > *RewrittenFiles=nullptr);
+ std::vector<std::pair<std::string, std::string>> *RewrittenFiles = nullptr);
/// IncludeInDiagnosticCounts - This method (whose default implementation
/// returns true) indicates whether the diagnostics handled by this
@@ -127,6 +130,6 @@
void Diag(SourceLocation Loc, unsigned DiagID);
};
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h
index c4db8e2..ce2a950 100644
--- a/include/clang/Sema/DelayedDiagnostic.h
+++ b/include/clang/Sema/DelayedDiagnostic.h
@@ -31,6 +31,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Sema/Sema.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
@@ -138,7 +139,7 @@
void Destroy();
static DelayedDiagnostic makeAvailability(AvailabilityResult AR,
- SourceLocation Loc,
+ ArrayRef<SourceLocation> Locs,
const NamedDecl *ReferringDecl,
const NamedDecl *OffendingDecl,
const ObjCInterfaceDecl *UnknownObjCClass,
@@ -146,7 +147,6 @@
StringRef Msg,
bool ObjCPropertyAccess);
-
static DelayedDiagnostic makeAccess(SourceLocation Loc,
const AccessedEntity &Entity) {
DelayedDiagnostic DD;
@@ -194,6 +194,12 @@
return StringRef(AvailabilityData.Message, AvailabilityData.MessageLen);
}
+ ArrayRef<SourceLocation> getAvailabilitySelectorLocs() const {
+ assert(Kind == Availability && "Not an availability diagnostic.");
+ return llvm::makeArrayRef(AvailabilityData.SelectorLocs,
+ AvailabilityData.NumSelectorLocs);
+ }
+
AvailabilityResult getAvailabilityResult() const {
assert(Kind == Availability && "Not an availability diagnostic.");
return AvailabilityData.AR;
@@ -238,6 +244,8 @@
const ObjCPropertyDecl *ObjCProperty;
const char *Message;
size_t MessageLen;
+ SourceLocation *SelectorLocs;
+ size_t NumSelectorLocs;
AvailabilityResult AR;
bool ObjCPropertyAccess;
};
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
index 28ae40b..5a49881 100644
--- a/include/clang/Sema/Overload.h
+++ b/include/clang/Sema/Overload.h
@@ -74,55 +74,55 @@
/// ImplicitConversionKind - The kind of implicit conversion used to
/// convert an argument to a parameter's type. The enumerator values
- /// match with Table 9 of (C++ 13.3.3.1.1) and are listed such that
- /// better conversion kinds have smaller values.
+ /// match with the table titled 'Conversions' in [over.ics.scs] and are listed
+ /// such that better conversion kinds have smaller values.
enum ImplicitConversionKind {
/// Identity conversion (no conversion)
ICK_Identity = 0,
- /// Lvalue-to-rvalue conversion (C++ 4.1)
+ /// Lvalue-to-rvalue conversion (C++ [conv.lval])
ICK_Lvalue_To_Rvalue,
- /// Array-to-pointer conversion (C++ 4.2)
+ /// Array-to-pointer conversion (C++ [conv.array])
ICK_Array_To_Pointer,
- /// Function-to-pointer (C++ 4.3)
+ /// Function-to-pointer (C++ [conv.array])
ICK_Function_To_Pointer,
- /// Function pointer conversion (C++17 4.13)
+ /// Function pointer conversion (C++17 [conv.fctptr])
ICK_Function_Conversion,
- /// Qualification conversions (C++ 4.4)
+ /// Qualification conversions (C++ [conv.qual])
ICK_Qualification,
- /// Integral promotions (C++ 4.5)
+ /// Integral promotions (C++ [conv.prom])
ICK_Integral_Promotion,
- /// Floating point promotions (C++ 4.6)
+ /// Floating point promotions (C++ [conv.fpprom])
ICK_Floating_Promotion,
/// Complex promotions (Clang extension)
ICK_Complex_Promotion,
- /// Integral conversions (C++ 4.7)
+ /// Integral conversions (C++ [conv.integral])
ICK_Integral_Conversion,
- /// Floating point conversions (C++ 4.8)
+ /// Floating point conversions (C++ [conv.double]
ICK_Floating_Conversion,
/// Complex conversions (C99 6.3.1.6)
ICK_Complex_Conversion,
- /// Floating-integral conversions (C++ 4.9)
+ /// Floating-integral conversions (C++ [conv.fpint])
ICK_Floating_Integral,
- /// Pointer conversions (C++ 4.10)
+ /// Pointer conversions (C++ [conv.ptr])
ICK_Pointer_Conversion,
- /// Pointer-to-member conversions (C++ 4.11)
+ /// Pointer-to-member conversions (C++ [conv.mem])
ICK_Pointer_Member,
- /// Boolean conversions (C++ 4.12)
+ /// Boolean conversions (C++ [conv.bool])
ICK_Boolean_Conversion,
/// Conversions between compatible types in C99
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index 35fdd74..744be7e 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -469,6 +469,132 @@
void Clear();
};
+class Capture {
+ // There are three categories of capture: capturing 'this', capturing
+ // local variables, and C++1y initialized captures (which can have an
+ // arbitrary initializer, and don't really capture in the traditional
+ // sense at all).
+ //
+ // There are three ways to capture a local variable:
+ // - capture by copy in the C++11 sense,
+ // - capture by reference in the C++11 sense, and
+ // - __block capture.
+ // Lambdas explicitly specify capture by copy or capture by reference.
+ // For blocks, __block capture applies to variables with that annotation,
+ // variables of reference type are captured by reference, and other
+ // variables are captured by copy.
+ enum CaptureKind {
+ Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA
+ };
+ enum {
+ IsNestedCapture = 0x1,
+ IsThisCaptured = 0x2
+ };
+
+ /// The variable being captured (if we are not capturing 'this') and whether
+ /// this is a nested capture, and whether we are capturing 'this'
+ llvm::PointerIntPair<VarDecl*, 2> VarAndNestedAndThis;
+
+ /// Expression to initialize a field of the given type, and the kind of
+ /// capture (if this is a capture and not an init-capture). The expression
+ /// is only required if we are capturing ByVal and the variable's type has
+ /// a non-trivial copy constructor.
+ llvm::PointerIntPair<void *, 2, CaptureKind> InitExprAndCaptureKind;
+
+ /// \brief The source location at which the first capture occurred.
+ SourceLocation Loc;
+
+ /// \brief The location of the ellipsis that expands a parameter pack.
+ SourceLocation EllipsisLoc;
+
+ /// \brief The type as it was captured, which is in effect the type of the
+ /// non-static data member that would hold the capture.
+ QualType CaptureType;
+
+ /// \brief Whether an explicit capture has been odr-used in the body of the
+ /// lambda.
+ bool ODRUsed = false;
+
+ /// \brief Whether an explicit capture has been non-odr-used in the body of
+ /// the lambda.
+ bool NonODRUsed = false;
+
+public:
+ Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,
+ SourceLocation Loc, SourceLocation EllipsisLoc,
+ QualType CaptureType, Expr *Cpy)
+ : VarAndNestedAndThis(Var, IsNested ? IsNestedCapture : 0),
+ InitExprAndCaptureKind(
+ Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef
+ : Cap_ByCopy),
+ Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {}
+
+ enum IsThisCapture { ThisCapture };
+ Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
+ QualType CaptureType, Expr *Cpy, const bool ByCopy)
+ : VarAndNestedAndThis(
+ nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))),
+ InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef),
+ Loc(Loc), CaptureType(CaptureType) {}
+
+ bool isThisCapture() const {
+ return VarAndNestedAndThis.getInt() & IsThisCaptured;
+ }
+
+ bool isVariableCapture() const {
+ return !isThisCapture() && !isVLATypeCapture();
+ }
+
+ bool isCopyCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByCopy;
+ }
+
+ bool isReferenceCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByRef;
+ }
+
+ bool isBlockCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_Block;
+ }
+
+ bool isVLATypeCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_VLA;
+ }
+
+ bool isNested() const {
+ return VarAndNestedAndThis.getInt() & IsNestedCapture;
+ }
+
+ bool isODRUsed() const { return ODRUsed; }
+ bool isNonODRUsed() const { return NonODRUsed; }
+ void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; }
+
+ VarDecl *getVariable() const {
+ assert(isVariableCapture());
+ return VarAndNestedAndThis.getPointer();
+ }
+
+ /// \brief Retrieve the location at which this variable was captured.
+ SourceLocation getLocation() const { return Loc; }
+
+ /// \brief Retrieve the source location of the ellipsis, whose presence
+ /// indicates that the capture is a pack expansion.
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+ /// \brief Retrieve the capture type for this capture, which is effectively
+ /// the type of the non-static data member in the lambda/block structure
+ /// that would store this capture.
+ QualType getCaptureType() const {
+ assert(!isThisCapture());
+ return CaptureType;
+ }
+
+ Expr *getInitExpr() const {
+ assert(!isVLATypeCapture() && "no init expression for type capture");
+ return static_cast<Expr *>(InitExprAndCaptureKind.getPointer());
+ }
+};
+
class CapturingScopeInfo : public FunctionScopeInfo {
protected:
CapturingScopeInfo(const CapturingScopeInfo&) = default;
@@ -481,132 +607,6 @@
ImplicitCaptureStyle ImpCaptureStyle;
- class Capture {
- // There are three categories of capture: capturing 'this', capturing
- // local variables, and C++1y initialized captures (which can have an
- // arbitrary initializer, and don't really capture in the traditional
- // sense at all).
- //
- // There are three ways to capture a local variable:
- // - capture by copy in the C++11 sense,
- // - capture by reference in the C++11 sense, and
- // - __block capture.
- // Lambdas explicitly specify capture by copy or capture by reference.
- // For blocks, __block capture applies to variables with that annotation,
- // variables of reference type are captured by reference, and other
- // variables are captured by copy.
- enum CaptureKind {
- Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA
- };
- enum {
- IsNestedCapture = 0x1,
- IsThisCaptured = 0x2
- };
-
- /// The variable being captured (if we are not capturing 'this') and whether
- /// this is a nested capture, and whether we are capturing 'this'
- llvm::PointerIntPair<VarDecl*, 2> VarAndNestedAndThis;
-
- /// Expression to initialize a field of the given type, and the kind of
- /// capture (if this is a capture and not an init-capture). The expression
- /// is only required if we are capturing ByVal and the variable's type has
- /// a non-trivial copy constructor.
- llvm::PointerIntPair<void *, 2, CaptureKind> InitExprAndCaptureKind;
-
- /// \brief The source location at which the first capture occurred.
- SourceLocation Loc;
-
- /// \brief The location of the ellipsis that expands a parameter pack.
- SourceLocation EllipsisLoc;
-
- /// \brief The type as it was captured, which is in effect the type of the
- /// non-static data member that would hold the capture.
- QualType CaptureType;
-
- /// \brief Whether an explicit capture has been odr-used in the body of the
- /// lambda.
- bool ODRUsed = false;
-
- /// \brief Whether an explicit capture has been non-odr-used in the body of
- /// the lambda.
- bool NonODRUsed = false;
-
- public:
- Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,
- SourceLocation Loc, SourceLocation EllipsisLoc,
- QualType CaptureType, Expr *Cpy)
- : VarAndNestedAndThis(Var, IsNested ? IsNestedCapture : 0),
- InitExprAndCaptureKind(
- Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef
- : Cap_ByCopy),
- Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {}
-
- enum IsThisCapture { ThisCapture };
- Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
- QualType CaptureType, Expr *Cpy, const bool ByCopy)
- : VarAndNestedAndThis(
- nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))),
- InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef),
- Loc(Loc), CaptureType(CaptureType) {}
-
- bool isThisCapture() const {
- return VarAndNestedAndThis.getInt() & IsThisCaptured;
- }
-
- bool isVariableCapture() const {
- return !isThisCapture() && !isVLATypeCapture();
- }
-
- bool isCopyCapture() const {
- return InitExprAndCaptureKind.getInt() == Cap_ByCopy;
- }
-
- bool isReferenceCapture() const {
- return InitExprAndCaptureKind.getInt() == Cap_ByRef;
- }
-
- bool isBlockCapture() const {
- return InitExprAndCaptureKind.getInt() == Cap_Block;
- }
-
- bool isVLATypeCapture() const {
- return InitExprAndCaptureKind.getInt() == Cap_VLA;
- }
-
- bool isNested() const {
- return VarAndNestedAndThis.getInt() & IsNestedCapture;
- }
-
- bool isODRUsed() const { return ODRUsed; }
- bool isNonODRUsed() const { return NonODRUsed; }
- void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; }
-
- VarDecl *getVariable() const {
- assert(isVariableCapture());
- return VarAndNestedAndThis.getPointer();
- }
-
- /// \brief Retrieve the location at which this variable was captured.
- SourceLocation getLocation() const { return Loc; }
-
- /// \brief Retrieve the source location of the ellipsis, whose presence
- /// indicates that the capture is a pack expansion.
- SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
-
- /// \brief Retrieve the capture type for this capture, which is effectively
- /// the type of the non-static data member in the lambda/block structure
- /// that would store this capture.
- QualType getCaptureType() const {
- assert(!isThisCapture());
- return CaptureType;
- }
-
- Expr *getInitExpr() const {
- assert(!isVLATypeCapture() && "no init expression for type capture");
- return static_cast<Expr *>(InitExprAndCaptureKind.getPointer());
- }
- };
-
CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style)
: FunctionScopeInfo(Diag), ImpCaptureStyle(Style) {}
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 35599bf..a668253 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -30,7 +30,6 @@
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/ExpressionTraits.h"
-#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/PragmaKinds.h"
@@ -45,7 +44,6 @@
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/Ownership.h"
#include "clang/Sema/Scope.h"
-#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/TypoCorrection.h"
#include "clang/Sema/Weak.h"
#include "llvm/ADT/ArrayRef.h"
@@ -201,6 +199,7 @@
namespace sema {
class AccessedEntity;
class BlockScopeInfo;
+ class Capture;
class CapturedRegionScopeInfo;
class CapturingScopeInfo;
class CompoundScopeInfo;
@@ -529,12 +528,10 @@
/// full expression.
llvm::SmallPtrSet<Expr*, 2> MaybeODRUseExprs;
+ std::unique_ptr<sema::FunctionScopeInfo> PreallocatedFunctionScope;
+
/// \brief Stack containing information about each of the nested
/// function, block, and method scopes that are currently active.
- ///
- /// This array is never empty. Clients should ignore the first
- /// element, which is used to cache a single FunctionScopeInfo
- /// that's used to parse every top-level function.
SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
typedef LazyVector<TypedefNameDecl *, ExternalSemaSource,
@@ -549,7 +546,7 @@
/// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
std::unique_ptr<CXXFieldCollector> FieldCollector;
- typedef llvm::SmallSetVector<const NamedDecl*, 16> NamedDeclSetType;
+ typedef llvm::SmallSetVector<NamedDecl *, 16> NamedDeclSetType;
/// \brief Set containing all declared private fields that are not used.
NamedDeclSetType UnusedPrivateFields;
@@ -1319,26 +1316,14 @@
const BlockExpr *blkExpr = nullptr);
sema::FunctionScopeInfo *getCurFunction() const {
- return FunctionScopes.back();
+ return FunctionScopes.empty() ? nullptr : FunctionScopes.back();
}
- sema::FunctionScopeInfo *getEnclosingFunction() const {
- if (FunctionScopes.empty())
- return nullptr;
+ sema::FunctionScopeInfo *getEnclosingFunction() const;
- for (int e = FunctionScopes.size()-1; e >= 0; --e) {
- if (isa<sema::BlockScopeInfo>(FunctionScopes[e]))
- continue;
- return FunctionScopes[e];
- }
- return nullptr;
- }
-
- template <typename ExprT>
- void recordUseOfEvaluatedWeak(const ExprT *E, bool IsRead=true) {
- if (!isUnevaluatedContext())
- getCurFunction()->recordUseOfWeak(E, IsRead);
- }
+ void setFunctionHasBranchIntoScope();
+ void setFunctionHasBranchProtectedScope();
+ void setFunctionHasIndirectGoto();
void PushCompoundScope(bool IsStmtExpr);
void PopCompoundScope();
@@ -1864,8 +1849,8 @@
void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S);
bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info);
bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
- DeclarationName Name,
- SourceLocation Loc);
+ DeclarationName Name, SourceLocation Loc,
+ bool IsTemplateId);
void
diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
SourceLocation FallbackLoc,
@@ -3338,8 +3323,8 @@
bool CheckRegparmAttr(const AttributeList &attr, unsigned &value);
bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
const FunctionDecl *FD = nullptr);
- bool CheckNoReturnAttr(const AttributeList &attr);
- bool CheckNoCallerSavedRegsAttr(const AttributeList &attr);
+ bool CheckAttrTarget(const AttributeList &CurrAttr);
+ bool CheckAttrNoArgs(const AttributeList &CurrAttr);
bool checkStringLiteralArgumentAttr(const AttributeList &Attr,
unsigned ArgNum, StringRef &Str,
SourceLocation *ArgLocation = nullptr);
@@ -3810,10 +3795,18 @@
RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD,
SourceLocation Loc,
unsigned NumParams);
+
+ enum CopyElisionSemanticsKind {
+ CES_Strict = 0,
+ CES_AllowParameters = 1,
+ CES_AllowDifferentTypes = 2,
+ CES_Default = (CES_AllowParameters | CES_AllowDifferentTypes),
+ };
+
VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E,
- bool AllowParamOrMoveConstructible);
+ CopyElisionSemanticsKind CESK);
bool isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
- bool AllowParamOrMoveConstructible);
+ CopyElisionSemanticsKind CESK);
StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
Scope *CurScope);
@@ -3954,7 +3947,7 @@
void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
- void DiagnoseAvailabilityOfDecl(NamedDecl *D, SourceLocation Loc,
+ void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
bool AvoidPartialAvailabilityChecks = false);
@@ -3969,7 +3962,7 @@
// Expression Parsing Callbacks: SemaExpr.cpp.
bool CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid);
- bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
+ bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass = nullptr,
bool ObjCPropertyAccess = false,
bool AvoidPartialAvailabilityChecks = false);
@@ -5553,10 +5546,10 @@
Scope *CurScope);
/// \brief Does copying/destroying the captured variable have side effects?
- bool CaptureHasSideEffects(const sema::LambdaScopeInfo::Capture &From);
+ bool CaptureHasSideEffects(const sema::Capture &From);
/// \brief Diagnose if an explicit lambda capture is unused.
- void DiagnoseUnusedLambdaCapture(const sema::LambdaScopeInfo::Capture &From);
+ void DiagnoseUnusedLambdaCapture(const sema::Capture &From);
/// \brief Complete a lambda-expression having processed and attached the
/// lambda body.
@@ -6377,9 +6370,8 @@
QualType InstantiatedParamType, Expr *Arg,
TemplateArgument &Converted,
CheckTemplateArgumentKind CTAK = CTAK_Specified);
- bool CheckTemplateArgument(TemplateTemplateParmDecl *Param,
- TemplateArgumentLoc &Arg,
- unsigned ArgumentPackIndex);
+ bool CheckTemplateTemplateArgument(TemplateParameterList *Params,
+ TemplateArgumentLoc &Arg);
ExprResult
BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
@@ -7558,6 +7550,10 @@
/// but have not yet been performed.
std::deque<PendingImplicitInstantiation> PendingInstantiations;
+ /// Queue of implicit template instantiations that cannot be performed
+ /// eagerly.
+ SmallVector<PendingImplicitInstantiation, 1> LateParsedInstantiations;
+
class GlobalEagerInstantiationScope {
public:
GlobalEagerInstantiationScope(Sema &S, bool Enabled)
@@ -7715,6 +7711,10 @@
StmtResult SubstStmt(Stmt *S,
const MultiLevelTemplateArgumentList &TemplateArgs);
+ TemplateParameterList *
+ SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
Decl *SubstDecl(Decl *D, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs);
@@ -10380,6 +10380,8 @@
ExprResult SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult);
ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult,
AtomicExpr::AtomicOp Op);
+ ExprResult SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult,
+ bool IsDelete);
bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
llvm::APSInt &Result);
bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
diff --git a/include/clang/Sema/SemaLambda.h b/include/clang/Sema/SemaLambda.h
index df40b13..ec16dc8 100644
--- a/include/clang/Sema/SemaLambda.h
+++ b/include/clang/Sema/SemaLambda.h
@@ -15,9 +15,13 @@
#ifndef LLVM_CLANG_SEMA_SEMALAMBDA_H
#define LLVM_CLANG_SEMA_SEMALAMBDA_H
+
#include "clang/AST/ASTLambda.h"
-#include "clang/Sema/ScopeInfo.h"
+
namespace clang {
+namespace sema {
+class FunctionScopeInfo;
+}
class Sema;
/// \brief Examines the FunctionScopeInfo stack to determine the nearest
diff --git a/include/clang/Serialization/ContinuousRangeMap.h b/include/clang/Serialization/ContinuousRangeMap.h
index 24bfadd..5a5093a 100644
--- a/include/clang/Serialization/ContinuousRangeMap.h
+++ b/include/clang/Serialization/ContinuousRangeMap.h
@@ -117,7 +117,7 @@
Builder &operator=(const Builder&) = delete;
~Builder() {
- std::sort(Self.Rep.begin(), Self.Rep.end(), Compare());
+ llvm::sort(Self.Rep.begin(), Self.Rep.end(), Compare());
std::unique(Self.Rep.begin(), Self.Rep.end(),
[](const_reference A, const_reference B) {
// FIXME: we should not allow any duplicate keys, but there are a lot of
diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 3b94a9b..e26cc6f 100644
--- a/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -218,6 +218,14 @@
} // end "nullability"
+let ParentPackage = APIModeling in {
+
+def TrustNonnullChecker : Checker<"TrustNonnull">,
+ HelpText<"Trust that returns from framework methods annotated with _Nonnull are not null">,
+ DescFile<"TrustNonnullChecker.cpp">;
+
+}
+
//===----------------------------------------------------------------------===//
// Evaluate "builtin" functions.
//===----------------------------------------------------------------------===//
@@ -608,14 +616,17 @@
HelpText<"Warn about improper use of '[super dealloc]' in Objective-C">,
DescFile<"ObjCSuperDeallocChecker.cpp">;
+def AutoreleaseWriteChecker : Checker<"AutoreleaseWrite">,
+ HelpText<"Warn about potentially crashing writes to autoreleasing objects from different autoreleasing pools in Objective-C">,
+ DescFile<"ObjCAutoreleaseWriteChecker.cpp">;
} // end "osx.cocoa"
-let ParentPackage = OSXAlpha in {
+let ParentPackage = Performance in {
-def GCDAsyncSemaphoreChecker : Checker<"GCDAsyncSemaphore">,
- HelpText<"Checker for performance anti-pattern when using semaphors from async API">,
- DescFile<"GCDAsyncSemaphoreChecker.cpp">;
-} // end "alpha.osx"
+def GCDAntipattern : Checker<"GCDAntipattern">,
+ HelpText<"Check for performance anti-patterns when using Grand Central Dispatch">,
+ DescFile<"GCDAntipatternChecker.cpp">;
+} // end "optin.performance"
let ParentPackage = CocoaAlpha in {
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 767ec02..e8a918e 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -1,4 +1,4 @@
-//===--- AnalyzerOptions.h - Analysis Engine Options ------------*- C++ -*-===//
+//===- AnalyzerOptions.h - Analysis Engine Options --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,18 +19,18 @@
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include <string>
+#include <utility>
#include <vector>
namespace clang {
-class ASTConsumer;
-class DiagnosticsEngine;
-class Preprocessor;
-class LangOptions;
namespace ento {
+
class CheckerBase;
-}
+
+} // namespace ento
/// Analysis - Set of available source code analyses.
enum Analyses {
@@ -123,20 +123,20 @@
class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
public:
- typedef llvm::StringMap<std::string> ConfigTable;
+ using ConfigTable = llvm::StringMap<std::string>;
static std::vector<StringRef>
getRegisteredCheckers(bool IncludeExperimental = false);
/// \brief Pair of checker name and enable/disable.
- std::vector<std::pair<std::string, bool> > CheckersControlList;
+ std::vector<std::pair<std::string, bool>> CheckersControlList;
/// \brief A key-value table of use-specified configuration values.
ConfigTable Config;
- AnalysisStores AnalysisStoreOpt;
- AnalysisConstraints AnalysisConstraintsOpt;
- AnalysisDiagClients AnalysisDiagOpt;
- AnalysisPurgeMode AnalysisPurgeOpt;
+ AnalysisStores AnalysisStoreOpt = RegionStoreModel;
+ AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel;
+ AnalysisDiagClients AnalysisDiagOpt = PD_HTML;
+ AnalysisPurgeMode AnalysisPurgeOpt = PurgeStmt;
std::string AnalyzeSpecificFunction;
@@ -147,7 +147,6 @@
/// \brief The maximum number of times the analyzer visits a block.
unsigned maxBlockVisitOnPath;
-
/// \brief Disable all analyzer checks.
///
/// This flag allows one to disable analyzer checks on the code processed by
@@ -183,10 +182,11 @@
unsigned NoRetryExhausted : 1;
/// \brief The inlining stack depth limit.
- unsigned InlineMaxStackDepth;
+ // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
+ unsigned InlineMaxStackDepth = 5;
/// \brief The mode of function selection used during inlining.
- AnalysisInliningMode InliningMode;
+ AnalysisInliningMode InliningMode = NoRedundancy;
enum class ExplorationStrategyKind {
DFS,
@@ -198,14 +198,15 @@
};
private:
-
- ExplorationStrategyKind ExplorationStrategy;
+ ExplorationStrategyKind ExplorationStrategy = ExplorationStrategyKind::NotSet;
/// \brief Describes the kinds for high-level analyzer mode.
enum UserModeKind {
UMK_NotSet = 0,
+
/// Perform shallow but fast analyzes.
UMK_Shallow = 1,
+
/// Perform deep analyzes.
UMK_Deep = 2
};
@@ -213,10 +214,10 @@
/// Controls the high-level analyzer mode, which influences the default
/// settings for some of the lower-level config options (such as IPAMode).
/// \sa getUserMode
- UserModeKind UserMode;
+ UserModeKind UserMode = UMK_NotSet;
/// Controls the mode of inter-procedural analysis.
- IPAKind IPAMode;
+ IPAKind IPAMode = IPAK_NotSet;
/// Controls which C++ member functions will be considered for inlining.
CXXInlineableMemberKind CXXMemberInliningMode;
@@ -239,6 +240,9 @@
/// \sa mayInlineCXXStandardLibrary
Optional<bool> InlineCXXStandardLibrary;
+ /// \sa includeScopesInCFG
+ Optional<bool> IncludeScopesInCFG;
+
/// \sa mayInlineTemplateFunctions
Optional<bool> InlineTemplateFunctions;
@@ -345,6 +349,15 @@
bool SearchInParents = false);
public:
+ AnalyzerOptions()
+ : DisableAllChecks(false), ShowCheckerHelp(false),
+ ShowEnabledCheckerList(false), AnalyzeAll(false),
+ AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false),
+ eagerlyAssumeBinOpBifurcation(false), TrimGraph(false),
+ visualizeExplodedGraphWithGraphViz(false),
+ visualizeExplodedGraphWithUbiGraph(false), UnoptimizedCFG(false),
+ PrintStats(false), NoRetryExhausted(false), CXXMemberInliningMode() {}
+
/// Interprets an option's string value as a boolean. The "true" string is
/// interpreted as true and the "false" string is interpreted as false.
///
@@ -471,6 +484,12 @@
/// which accepts the values "true" and "false".
bool includeRichConstructorsInCFG();
+ /// Returns whether or not scope information should be included in the CFG.
+ ///
+ /// This is controlled by the 'cfg-scope-info' config option, which accepts
+ /// the values "true" and "false".
+ bool includeScopesInCFG();
+
/// Returns whether or not C++ standard library functions may be considered
/// for inlining.
///
@@ -657,38 +676,10 @@
/// This is an experimental feature to inline functions from another
/// translation units.
bool naiveCTUEnabled();
-
-public:
- AnalyzerOptions() :
- AnalysisStoreOpt(RegionStoreModel),
- AnalysisConstraintsOpt(RangeConstraintsModel),
- AnalysisDiagOpt(PD_HTML),
- AnalysisPurgeOpt(PurgeStmt),
- DisableAllChecks(0),
- ShowCheckerHelp(0),
- ShowEnabledCheckerList(0),
- AnalyzeAll(0),
- AnalyzerDisplayProgress(0),
- AnalyzeNestedBlocks(0),
- eagerlyAssumeBinOpBifurcation(0),
- TrimGraph(0),
- visualizeExplodedGraphWithGraphViz(0),
- visualizeExplodedGraphWithUbiGraph(0),
- UnoptimizedCFG(0),
- PrintStats(0),
- NoRetryExhausted(0),
- // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
- InlineMaxStackDepth(5),
- InliningMode(NoRedundancy),
- ExplorationStrategy(ExplorationStrategyKind::NotSet),
- UserMode(UMK_NotSet),
- IPAMode(IPAK_NotSet),
- CXXMemberInliningMode() {}
-
};
-typedef IntrusiveRefCntPtr<AnalyzerOptions> AnalyzerOptionsRef;
+using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>;
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index a5febd8..73a88d2 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -1,4 +1,4 @@
-//===--- BugReporter.h - Generate PathDiagnostics --------------*- C++ -*-===//
+//===- BugReporter.h - Generate PathDiagnostics -----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,36 +15,51 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/iterator_range.h"
+#include <cassert>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
namespace clang {
+class AnalyzerOptions;
class ASTContext;
+class Decl;
class DiagnosticsEngine;
+class LocationContext;
+class SourceManager;
class Stmt;
-class ParentMap;
namespace ento {
-class PathDiagnostic;
-class ExplodedNode;
-class ExplodedGraph;
-class BugReport;
-class BugReporter;
-class BugReporterContext;
-class ExprEngine;
class BugType;
+class CheckerBase;
+class ExplodedGraph;
+class ExplodedNode;
+class ExprEngine;
+class MemRegion;
+class SValBuilder;
//===----------------------------------------------------------------------===//
// Interface for individual bug reports.
@@ -56,37 +71,39 @@
public:
class NodeResolver {
virtual void anchor();
+
public:
- virtual ~NodeResolver() {}
+ virtual ~NodeResolver() = default;
+
virtual const ExplodedNode*
getOriginalNode(const ExplodedNode *N) = 0;
};
- typedef const SourceRange *ranges_iterator;
- typedef SmallVector<std::unique_ptr<BugReporterVisitor>, 8> VisitorList;
- typedef VisitorList::iterator visitor_iterator;
- typedef SmallVector<StringRef, 2> ExtraTextList;
- typedef SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4> NoteList;
+ using ranges_iterator = const SourceRange *;
+ using VisitorList = SmallVector<std::unique_ptr<BugReporterVisitor>, 8>;
+ using visitor_iterator = VisitorList::iterator;
+ using ExtraTextList = SmallVector<StringRef, 2>;
+ using NoteList = SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4>;
protected:
- friend class BugReporter;
friend class BugReportEquivClass;
+ friend class BugReporter;
BugType& BT;
- const Decl *DeclWithIssue;
+ const Decl *DeclWithIssue = nullptr;
std::string ShortDescription;
std::string Description;
PathDiagnosticLocation Location;
PathDiagnosticLocation UniqueingLocation;
const Decl *UniqueingDecl;
- const ExplodedNode *ErrorNode;
+ const ExplodedNode *ErrorNode = nullptr;
SmallVector<SourceRange, 4> Ranges;
ExtraTextList ExtraText;
NoteList Notes;
- typedef llvm::DenseSet<SymbolRef> Symbols;
- typedef llvm::DenseSet<const MemRegion *> Regions;
+ using Symbols = llvm::DenseSet<SymbolRef>;
+ using Regions = llvm::DenseSet<const MemRegion *>;
/// A (stack of) a set of symbols that are registered with this
/// report as being "interesting", and thus used to help decide which
@@ -115,18 +132,18 @@
/// Used for clients to tell if the report's configuration has changed
/// since the last time they checked.
- unsigned ConfigurationChangeToken;
+ unsigned ConfigurationChangeToken = 0;
/// When set, this flag disables all callstack pruning from a diagnostic
/// path. This is useful for some reports that want maximum fidelty
/// when reporting an issue.
- bool DoNotPrunePath;
+ bool DoNotPrunePath = false;
/// Used to track unique reasons why a bug report might be invalid.
///
/// \sa markInvalid
/// \sa removeInvalidation
- typedef std::pair<const void *, const void *> InvalidationRecord;
+ using InvalidationRecord = std::pair<const void *, const void *>;
/// If non-empty, this bug report is likely a false positive and should not be
/// shown to the user.
@@ -146,18 +163,15 @@
public:
BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
- : BT(bt), DeclWithIssue(nullptr), Description(desc), ErrorNode(errornode),
- ConfigurationChangeToken(0), DoNotPrunePath(false) {}
+ : BT(bt), Description(desc), ErrorNode(errornode) {}
BugReport(BugType& bt, StringRef shortDesc, StringRef desc,
const ExplodedNode *errornode)
- : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc),
- Description(desc), ErrorNode(errornode), ConfigurationChangeToken(0),
- DoNotPrunePath(false) {}
+ : BT(bt), ShortDescription(shortDesc), Description(desc),
+ ErrorNode(errornode) {}
BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l)
- : BT(bt), DeclWithIssue(nullptr), Description(desc), Location(l),
- ErrorNode(nullptr), ConfigurationChangeToken(0), DoNotPrunePath(false) {}
+ : BT(bt), Description(desc), Location(l) {}
/// \brief Create a BugReport with a custom uniqueing location.
///
@@ -168,11 +182,8 @@
/// the allocation site, rather then the location where the bug is reported.
BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode,
PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
- : BT(bt), DeclWithIssue(nullptr), Description(desc),
- UniqueingLocation(LocationToUnique),
- UniqueingDecl(DeclToUnique),
- ErrorNode(errornode), ConfigurationChangeToken(0),
- DoNotPrunePath(false) {}
+ : BT(bt), Description(desc), UniqueingLocation(LocationToUnique),
+ UniqueingDecl(DeclToUnique), ErrorNode(errornode) {}
virtual ~BugReport();
@@ -356,10 +367,11 @@
//===----------------------------------------------------------------------===//
class BugReportEquivClass : public llvm::FoldingSetNode {
+ friend class BugReporter;
+
/// List of *owned* BugReport objects.
llvm::ilist<BugReport> Reports;
- friend class BugReporter;
void AddReport(std::unique_ptr<BugReport> R) {
Reports.push_back(R.release());
}
@@ -373,8 +385,8 @@
Reports.front().Profile(ID);
}
- typedef llvm::ilist<BugReport>::iterator iterator;
- typedef llvm::ilist<BugReport>::const_iterator const_iterator;
+ using iterator = llvm::ilist<BugReport>::iterator;
+ using const_iterator = llvm::ilist<BugReport>::const_iterator;
iterator begin() { return Reports.begin(); }
iterator end() { return Reports.end(); }
@@ -390,11 +402,12 @@
class BugReporterData {
public:
virtual ~BugReporterData();
+
virtual DiagnosticsEngine& getDiagnostic() = 0;
virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
virtual ASTContext &getASTContext() = 0;
- virtual SourceManager& getSourceManager() = 0;
- virtual AnalyzerOptions& getAnalyzerOptions() = 0;
+ virtual SourceManager &getSourceManager() = 0;
+ virtual AnalyzerOptions &getAnalyzerOptions() = 0;
};
/// BugReporter is a utility class for generating PathDiagnostics for analysis.
@@ -405,7 +418,8 @@
enum Kind { BaseBRKind, GRBugReporterKind };
private:
- typedef llvm::ImmutableSet<BugType*> BugTypesTy;
+ using BugTypesTy = llvm::ImmutableSet<BugType *>;
+
BugTypesTy::Factory F;
BugTypesTy BugTypes;
@@ -423,16 +437,17 @@
/// The set of bug reports tracked by the BugReporter.
llvm::FoldingSet<BugReportEquivClass> EQClasses;
+
/// A vector of BugReports for tracking the allocated pointers and cleanup.
std::vector<BugReportEquivClass *> EQClassesVector;
protected:
- BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k),
- D(d) {}
+ BugReporter(BugReporterData& d, Kind k)
+ : BugTypes(F.getEmptySet()), kind(k), D(d) {}
public:
- BugReporter(BugReporterData& d) : BugTypes(F.getEmptySet()), kind(BaseBRKind),
- D(d) {}
+ BugReporter(BugReporterData& d)
+ : BugTypes(F.getEmptySet()), kind(BaseBRKind), D(d) {}
virtual ~BugReporter();
/// \brief Generate and flush diagnostics for all bug reports.
@@ -449,20 +464,20 @@
}
/// \brief Iterator over the set of BugTypes tracked by the BugReporter.
- typedef BugTypesTy::iterator iterator;
+ using iterator = BugTypesTy::iterator;
iterator begin() { return BugTypes.begin(); }
iterator end() { return BugTypes.end(); }
/// \brief Iterator over the set of BugReports tracked by the BugReporter.
- typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator;
+ using EQClasses_iterator = llvm::FoldingSet<BugReportEquivClass>::iterator;
EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); }
EQClasses_iterator EQClasses_end() { return EQClasses.end(); }
ASTContext &getContext() { return D.getASTContext(); }
- SourceManager& getSourceManager() { return D.getSourceManager(); }
+ SourceManager &getSourceManager() { return D.getSourceManager(); }
- AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); }
+ AnalyzerOptions &getAnalyzerOptions() { return D.getAnalyzerOptions(); }
virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic,
PathDiagnosticConsumer &PC,
@@ -501,9 +516,10 @@
// FIXME: Get rid of GRBugReporter. It's the wrong abstraction.
class GRBugReporter : public BugReporter {
ExprEngine& Eng;
+
public:
GRBugReporter(BugReporterData& d, ExprEngine& eng)
- : BugReporter(d, GRBugReporterKind), Eng(eng) {}
+ : BugReporter(d, GRBugReporterKind), Eng(eng) {}
~GRBugReporter() override;
@@ -537,12 +553,14 @@
};
class BugReporterContext {
- virtual void anchor();
GRBugReporter &BR;
+
+ virtual void anchor();
+
public:
BugReporterContext(GRBugReporter& br) : BR(br) {}
- virtual ~BugReporterContext() {}
+ virtual ~BugReporterContext() = default;
GRBugReporter& getBugReporter() { return BR; }
@@ -552,7 +570,7 @@
return BR.getStateManager();
}
- SValBuilder& getSValBuilder() {
+ SValBuilder &getSValBuilder() {
return getStateManager().getSValBuilder();
}
@@ -567,8 +585,8 @@
virtual BugReport::NodeResolver& getNodeResolver() = 0;
};
-} // end GR namespace
+} // namespace ento
-} // end clang namespace
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
index 2043896..cb70c32 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
@@ -1,4 +1,4 @@
-//===--- BugReporterVisitors.h - Generate PathDiagnostics -------*- C++ -*-===//
+//===- BugReporterVisitors.h - Generate PathDiagnostics ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,11 +15,20 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
+#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
namespace clang {
+
+class BinaryOperator;
class CFGBlock;
+class DeclRefExpr;
+class Expr;
+class Stmt;
namespace ento {
@@ -99,7 +108,7 @@
: public BugReporterVisitorImpl<FindLastStoreBRVisitor> {
const MemRegion *R;
SVal V;
- bool Satisfied;
+ bool Satisfied = false;
/// If the visitor is tracking the value directly responsible for the
/// bug, we are going to employ false positive suppression.
@@ -113,10 +122,7 @@
FindLastStoreBRVisitor(KnownSVal V, const MemRegion *R,
bool InEnableNullFPSuppression)
- : R(R),
- V(V),
- Satisfied(false),
- EnableNullFPSuppression(InEnableNullFPSuppression) {}
+ : R(R), V(V), EnableNullFPSuppression(InEnableNullFPSuppression) {}
void Profile(llvm::FoldingSetNodeID &ID) const override;
@@ -130,18 +136,17 @@
: public BugReporterVisitorImpl<TrackConstraintBRVisitor> {
DefinedSVal Constraint;
bool Assumption;
- bool IsSatisfied;
+ bool IsSatisfied = false;
bool IsZeroCheck;
/// We should start tracking from the last node along the path in which the
/// value is constrained.
- bool IsTrackingTurnedOn;
+ bool IsTrackingTurnedOn = false;
public:
TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
- : Constraint(constraint), Assumption(assumption), IsSatisfied(false),
- IsZeroCheck(!Assumption && Constraint.getAs<Loc>()),
- IsTrackingTurnedOn(false) {}
+ : Constraint(constraint), Assumption(assumption),
+ IsZeroCheck(!Assumption && Constraint.getAs<Loc>()) {}
void Profile(llvm::FoldingSetNodeID &ID) const override;
@@ -157,7 +162,6 @@
private:
/// Checks if the constraint is valid in the current state.
bool isUnderconstrained(const ExplodedNode *N) const;
-
};
/// \class NilReceiverBRVisitor
@@ -165,7 +169,6 @@
class NilReceiverBRVisitor final
: public BugReporterVisitorImpl<NilReceiverBRVisitor> {
public:
-
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int x = 0;
ID.AddPointer(&x);
@@ -184,7 +187,6 @@
/// Visitor that tries to report interesting diagnostics from conditions.
class ConditionBRVisitor final
: public BugReporterVisitorImpl<ConditionBRVisitor> {
-
// FIXME: constexpr initialization isn't supported by MSVC2013.
static const char *const GenericTrueMessage;
static const char *const GenericFalseMessage;
@@ -277,7 +279,6 @@
/// if the region's contents are not modified/accessed by the call.
class UndefOrNullArgVisitor final
: public BugReporterVisitorImpl<UndefOrNullArgVisitor> {
-
/// The interesting memory region this visitor is tracking.
const MemRegion *R;
@@ -303,14 +304,14 @@
DefinedSVal V;
/// Track if we found the node where the constraint was first added.
- bool IsSatisfied;
+ bool IsSatisfied = false;
/// Since the visitors can be registered on nodes previous to the last
/// node in the BugReport, but the path traversal always starts with the last
/// node, the visitor invariant (that we start with a node in which V is null)
/// might not hold when node visitation starts. We are going to start tracking
/// from the last node in which the value is null.
- bool IsTrackingTurnedOn;
+ bool IsTrackingTurnedOn = false;
public:
SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N);
@@ -328,12 +329,11 @@
};
class CXXSelfAssignmentBRVisitor final
- : public BugReporterVisitorImpl<CXXSelfAssignmentBRVisitor> {
-
- bool Satisfied;
+ : public BugReporterVisitorImpl<CXXSelfAssignmentBRVisitor> {
+ bool Satisfied = false;
public:
- CXXSelfAssignmentBRVisitor() : Satisfied(false) {}
+ CXXSelfAssignmentBRVisitor() = default;
void Profile(llvm::FoldingSetNodeID &ID) const override {}
@@ -370,10 +370,10 @@
const Stmt *GetRetValExpr(const ExplodedNode *N);
bool isDeclRefExprToReference(const Expr *E);
+} // namespace bugreporter
-} // end namespace clang
-} // end namespace ento
-} // end namespace bugreporter
+} // namespace ento
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index 2adc09c..421369e 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -1,4 +1,4 @@
-//===--- PathDiagnostic.h - Path-Specific Diagnostic Handling ---*- C++ -*-===//
+//===- PathDiagnostic.h - Path-Specific Diagnostic Handling -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,39 +14,49 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
-#include "clang/Analysis/ProgramPoint.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
#include <deque>
#include <iterator>
#include <list>
#include <map>
+#include <memory>
#include <set>
#include <string>
+#include <utility>
#include <vector>
namespace clang {
-class ConditionalOperator;
+
class AnalysisDeclContext;
class BinaryOperator;
-class CompoundStmt;
+class CallEnter;
+class CallExitEnd;
+class CallExpr;
+class ConditionalOperator;
class Decl;
+class Expr;
class LocationContext;
class MemberExpr;
-class ParentMap;
class ProgramPoint;
class SourceManager;
-class Stmt;
-class CallExpr;
namespace ento {
class ExplodedNode;
class SymExpr;
-typedef const SymExpr* SymbolRef;
+
+using SymbolRef = const SymExpr *;
//===----------------------------------------------------------------------===//
// High-level interface for handlers of path-sensitive diagnostics.
@@ -60,7 +70,7 @@
public:
PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}
- typedef std::vector<std::pair<StringRef, StringRef> > ConsumerFiles;
+ using ConsumerFiles = std::vector<std::pair<StringRef, StringRef>>;
/// \brief A vector of <consumer,file> pairs.
ConsumerFiles files;
@@ -90,8 +100,9 @@
private:
virtual void anchor();
+
public:
- PathDiagnosticConsumer() : flushed(false) {}
+ PathDiagnosticConsumer() = default;
virtual ~PathDiagnosticConsumer();
void FlushDiagnostics(FilesMade *FilesMade);
@@ -104,6 +115,7 @@
void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D);
enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive };
+
virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
virtual bool supportsLogicalOpControlFlow() const { return false; }
@@ -112,7 +124,7 @@
virtual bool supportsCrossFileDiagnostics() const { return false; }
protected:
- bool flushed;
+ bool flushed = false;
llvm::FoldingSet<PathDiagnostic> Diags;
};
@@ -122,31 +134,28 @@
class PathDiagnosticRange : public SourceRange {
public:
- bool isPoint;
+ bool isPoint = false;
PathDiagnosticRange(SourceRange R, bool isP = false)
- : SourceRange(R), isPoint(isP) {}
-
- PathDiagnosticRange() : isPoint(false) {}
+ : SourceRange(R), isPoint(isP) {}
+ PathDiagnosticRange() = default;
};
-typedef llvm::PointerUnion<const LocationContext*, AnalysisDeclContext*>
- LocationOrAnalysisDeclContext;
+using LocationOrAnalysisDeclContext =
+ llvm::PointerUnion<const LocationContext *, AnalysisDeclContext *>;
class PathDiagnosticLocation {
private:
- enum Kind { RangeK, SingleLocK, StmtK, DeclK } K;
- const Stmt *S;
- const Decl *D;
- const SourceManager *SM;
+ enum Kind { RangeK, SingleLocK, StmtK, DeclK } K = SingleLocK;
+
+ const Stmt *S = nullptr;
+ const Decl *D = nullptr;
+ const SourceManager *SM = nullptr;
FullSourceLoc Loc;
PathDiagnosticRange Range;
- PathDiagnosticLocation(SourceLocation L, const SourceManager &sm,
- Kind kind)
- : K(kind), S(nullptr), D(nullptr), SM(&sm),
- Loc(genLocation(L)), Range(genRange()) {
- }
+ PathDiagnosticLocation(SourceLocation L, const SourceManager &sm, Kind kind)
+ : K(kind), SM(&sm), Loc(genLocation(L)), Range(genRange()) {}
FullSourceLoc genLocation(
SourceLocation L = SourceLocation(),
@@ -157,18 +166,15 @@
public:
/// Create an invalid location.
- PathDiagnosticLocation()
- : K(SingleLocK), S(nullptr), D(nullptr), SM(nullptr) {}
+ PathDiagnosticLocation() = default;
/// Create a location corresponding to the given statement.
PathDiagnosticLocation(const Stmt *s,
const SourceManager &sm,
LocationOrAnalysisDeclContext lac)
- : K(s->getLocStart().isValid() ? StmtK : SingleLocK),
- S(K == StmtK ? s : nullptr),
- D(nullptr), SM(&sm),
- Loc(genLocation(SourceLocation(), lac)),
- Range(genRange(lac)) {
+ : K(s->getLocStart().isValid() ? StmtK : SingleLocK),
+ S(K == StmtK ? s : nullptr), SM(&sm),
+ Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) {
assert(K == SingleLocK || S);
assert(K == SingleLocK || Loc.isValid());
assert(K == SingleLocK || Range.isValid());
@@ -176,8 +182,7 @@
/// Create a location corresponding to the given declaration.
PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
- : K(DeclK), S(nullptr), D(d), SM(&sm),
- Loc(genLocation()), Range(genRange()) {
+ : K(DeclK), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) {
assert(D);
assert(Loc.isValid());
assert(Range.isValid());
@@ -187,8 +192,7 @@
///
/// This should only be used if there are no more appropriate constructors.
PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm)
- : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm), Loc(loc, sm),
- Range(genRange()) {
+ : SM(&sm), Loc(loc, sm), Range(genRange()) {
assert(Loc.isValid());
assert(Range.isValid());
}
@@ -250,7 +254,7 @@
const SourceManager &SM);
/// Create a location corresponding to the given valid ExplodedNode.
- static PathDiagnosticLocation create(const ProgramPoint& P,
+ static PathDiagnosticLocation create(const ProgramPoint &P,
const SourceManager &SMng);
/// Create a location corresponding to the next valid ExplodedNode as end
@@ -310,10 +314,11 @@
class PathDiagnosticLocationPair {
private:
PathDiagnosticLocation Start, End;
+
public:
PathDiagnosticLocationPair(const PathDiagnosticLocation &start,
const PathDiagnosticLocation &end)
- : Start(start), End(end) {}
+ : Start(start), End(end) {}
const PathDiagnosticLocation &getStart() const { return Start; }
const PathDiagnosticLocation &getEnd() const { return End; }
@@ -348,7 +353,7 @@
/// \brief In the containing bug report, this piece is the last piece from
/// the main source file.
- bool LastInMainSourceFile;
+ bool LastInMainSourceFile = false;
/// A constant string that can be used to tag the PathDiagnosticPiece,
/// typically with the identification of the creator. The actual pointer
@@ -358,16 +363,14 @@
std::vector<SourceRange> ranges;
- PathDiagnosticPiece() = delete;
- PathDiagnosticPiece(const PathDiagnosticPiece &P) = delete;
- void operator=(const PathDiagnosticPiece &P) = delete;
-
protected:
PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below);
-
PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
public:
+ PathDiagnosticPiece() = delete;
+ PathDiagnosticPiece(const PathDiagnosticPiece &) = delete;
+ PathDiagnosticPiece &operator=(const PathDiagnosticPiece &) = delete;
virtual ~PathDiagnosticPiece();
StringRef getString() const { return str; }
@@ -422,8 +425,8 @@
class PathPieces : public std::list<std::shared_ptr<PathDiagnosticPiece>> {
void flattenTo(PathPieces &Primary, PathPieces &Current,
bool ShouldFlattenMacros) const;
-public:
+public:
PathPieces flatten(bool ShouldFlattenMacros) const {
PathPieces Result;
flattenTo(Result, Result, ShouldFlattenMacros);
@@ -436,12 +439,13 @@
class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
private:
PathDiagnosticLocation Pos;
+
public:
PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos,
StringRef s,
PathDiagnosticPiece::Kind k,
bool addPosRange = true)
- : PathDiagnosticPiece(s, k), Pos(pos) {
+ : PathDiagnosticPiece(s, k), Pos(pos) {
assert(Pos.isValid() && Pos.asLocation().isValid() &&
"PathDiagnosticSpotPiece's must have a valid location.");
if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
@@ -483,7 +487,7 @@
public:
StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
- ~StackHintGeneratorForSymbol() override {}
+ ~StackHintGeneratorForSymbol() override = default;
/// \brief Search the call expression for the symbol Sym and dispatch the
/// 'getMessageForX()' methods to construct a specific message.
@@ -492,9 +496,11 @@
/// Produces the message of the following form:
/// 'Msg via Nth parameter'
virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);
+
virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
return Msg;
}
+
virtual std::string getMessageForSymbolNotFound() {
return Msg;
}
@@ -513,9 +519,8 @@
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,
StringRef s, bool addPosRange = true,
StackHintGenerator *stackHint = nullptr)
- : PathDiagnosticSpotPiece(pos, s, Event, addPosRange),
- CallStackHint(stackHint) {}
-
+ : PathDiagnosticSpotPiece(pos, s, Event, addPosRange),
+ CallStackHint(stackHint) {}
~PathDiagnosticEventPiece() override;
/// Mark the diagnostic piece as being potentially prunable. This
@@ -539,30 +544,19 @@
std::string getCallStackMessage(const ExplodedNode *N) {
if (CallStackHint)
return CallStackHint->getMessage(N);
- return "";
+ return {};
}
void dump() const override;
- static inline bool classof(const PathDiagnosticPiece *P) {
+ static bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Event;
}
};
class PathDiagnosticCallPiece : public PathDiagnosticPiece {
- PathDiagnosticCallPiece(const Decl *callerD,
- const PathDiagnosticLocation &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), IsCalleeAnAutosynthesizedPropertyAccessor(false),
- path(oldPath) {}
-
const Decl *Caller;
- const Decl *Callee;
+ const Decl *Callee = nullptr;
// Flag signifying that this diagnostic has only call enter and no matching
// call exit.
@@ -570,12 +564,20 @@
// Flag signifying that the callee function is an Objective-C autosynthesized
// property getter or setter.
- bool IsCalleeAnAutosynthesizedPropertyAccessor;
+ bool IsCalleeAnAutosynthesizedPropertyAccessor = false;
// The custom string, which should appear after the call Return Diagnostic.
// TODO: Should we allow multiple diagnostics?
std::string CallStackMessage;
+ PathDiagnosticCallPiece(const Decl *callerD,
+ const PathDiagnosticLocation &callReturnPos)
+ : PathDiagnosticPiece(Call), Caller(callerD), NoExit(false),
+ callReturn(callReturnPos) {}
+ PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
+ : PathDiagnosticPiece(Call), Caller(caller), NoExit(true),
+ path(oldPath) {}
+
public:
PathDiagnosticLocation callEnter;
PathDiagnosticLocation callEnterWithin;
@@ -590,13 +592,9 @@
void setCallee(const CallEnter &CE, const SourceManager &SM);
bool hasCallStackMessage() { return !CallStackMessage.empty(); }
- void setCallStackMessage(StringRef st) {
- CallStackMessage = st;
- }
+ void setCallStackMessage(StringRef st) { CallStackMessage = st; }
- PathDiagnosticLocation getLocation() const override {
- return callEnter;
- }
+ PathDiagnosticLocation getLocation() const override { return callEnter; }
std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent() const;
std::shared_ptr<PathDiagnosticEventPiece>
@@ -606,8 +604,8 @@
void flattenLocations() override {
callEnter.flatten();
callReturn.flatten();
- for (PathPieces::iterator I = path.begin(),
- E = path.end(); I != E; ++I) (*I)->flattenLocations();
+ for (const auto &I : path)
+ I->flattenLocations();
}
static std::shared_ptr<PathDiagnosticCallPiece>
@@ -621,28 +619,29 @@
void Profile(llvm::FoldingSetNodeID &ID) const override;
- static inline bool classof(const PathDiagnosticPiece *P) {
+ static bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Call;
}
};
class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece {
std::vector<PathDiagnosticLocationPair> LPairs;
+
public:
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
const PathDiagnosticLocation &endPos,
StringRef s)
- : PathDiagnosticPiece(s, ControlFlow) {
- LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
- }
+ : PathDiagnosticPiece(s, ControlFlow) {
+ LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
+ }
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
const PathDiagnosticLocation &endPos)
- : PathDiagnosticPiece(ControlFlow) {
- LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
- }
+ : PathDiagnosticPiece(ControlFlow) {
+ LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
+ }
- ~PathDiagnosticControlFlowPiece() override;
+ ~PathDiagnosticControlFlowPiece() override;
PathDiagnosticLocation getStartLocation() const {
assert(!LPairs.empty() &&
@@ -670,20 +669,23 @@
return getStartLocation();
}
- typedef std::vector<PathDiagnosticLocationPair>::iterator iterator;
+ using iterator = std::vector<PathDiagnosticLocationPair>::iterator;
+
iterator begin() { return LPairs.begin(); }
- iterator end() { return LPairs.end(); }
+ iterator end() { return LPairs.end(); }
void flattenLocations() override {
- for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten();
+ for (auto &I : *this)
+ I.flatten();
}
- typedef std::vector<PathDiagnosticLocationPair>::const_iterator
- const_iterator;
- const_iterator begin() const { return LPairs.begin(); }
- const_iterator end() const { return LPairs.end(); }
+ using const_iterator =
+ std::vector<PathDiagnosticLocationPair>::const_iterator;
- static inline bool classof(const PathDiagnosticPiece *P) {
+ const_iterator begin() const { return LPairs.begin(); }
+ const_iterator end() const { return LPairs.end(); }
+
+ static bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == ControlFlow;
}
@@ -695,8 +697,7 @@
class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece {
public:
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
- : PathDiagnosticSpotPiece(pos, "", Macro) {}
-
+ : PathDiagnosticSpotPiece(pos, "", Macro) {}
~PathDiagnosticMacroPiece() override;
PathPieces subPieces;
@@ -705,11 +706,11 @@
void flattenLocations() override {
PathDiagnosticSpotPiece::flattenLocations();
- for (PathPieces::iterator I = subPieces.begin(),
- E = subPieces.end(); I != E; ++I) (*I)->flattenLocations();
+ for (const auto &I : subPieces)
+ I->flattenLocations();
}
- static inline bool classof(const PathDiagnosticPiece *P) {
+ static bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Macro;
}
@@ -723,10 +724,9 @@
PathDiagnosticNotePiece(const PathDiagnosticLocation &Pos, StringRef S,
bool AddPosRange = true)
: PathDiagnosticSpotPiece(Pos, S, Note, AddPosRange) {}
-
~PathDiagnosticNotePiece() override;
- static inline bool classof(const PathDiagnosticPiece *P) {
+ static bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Note;
}
@@ -736,7 +736,7 @@
};
/// File IDs mapped to sets of line numbers.
-typedef std::map<unsigned, std::set<unsigned>> FilesToLineNumsMap;
+using FilesToLineNumsMap = std::map<unsigned, std::set<unsigned>>;
/// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
/// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
@@ -764,14 +764,13 @@
/// Lines executed in the path.
std::unique_ptr<FilesToLineNumsMap> ExecutedLines;
- PathDiagnostic() = delete;
public:
+ PathDiagnostic() = delete;
PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue,
StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
StringRef category, PathDiagnosticLocation LocationToUnique,
const Decl *DeclToUnique,
std::unique_ptr<FilesToLineNumsMap> ExecutedLines);
-
~PathDiagnostic();
const PathPieces &path;
@@ -822,9 +821,11 @@
void resetDiagnosticLocationToMainFile();
StringRef getVerboseDescription() const { return VerboseDesc; }
+
StringRef getShortDescription() const {
return ShortDesc.empty() ? VerboseDesc : ShortDesc;
}
+
StringRef getCheckName() const { return CheckName; }
StringRef getBugType() const { return BugType; }
StringRef getCategory() const { return Category; }
@@ -834,15 +835,18 @@
/// where the bug manifests.
const Decl *getDeclWithIssue() const { return DeclWithIssue; }
- typedef std::deque<std::string>::const_iterator meta_iterator;
+ using meta_iterator = std::deque<std::string>::const_iterator;
+
meta_iterator meta_begin() const { return OtherDesc.begin(); }
meta_iterator meta_end() const { return OtherDesc.end(); }
void addMeta(StringRef s) { OtherDesc.push_back(s); }
- typedef FilesToLineNumsMap::const_iterator filesmap_iterator;
+ using filesmap_iterator = FilesToLineNumsMap::const_iterator;
+
filesmap_iterator executedLines_begin() const {
return ExecutedLines->begin();
}
+
filesmap_iterator executedLines_end() const { return ExecutedLines->end(); }
PathDiagnosticLocation getLocation() const {
@@ -862,8 +866,8 @@
void flattenLocations() {
Loc.flatten();
- for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end();
- I != E; ++I) (*I)->flattenLocations();
+ for (const auto &I : pathImpl)
+ I->flattenLocations();
}
/// Profiles the diagnostic, independent of the path it references.
@@ -879,8 +883,8 @@
void FullProfile(llvm::FoldingSetNodeID &ID) const;
};
-} // end GR namespace
+} // namespace ento
-} //end clang namespace
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
index 8dda636..7f34a7a 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
@@ -21,6 +21,8 @@
class Expr;
class VarDecl;
+class QualType;
+class AttributedType;
namespace ento {
@@ -42,6 +44,25 @@
std::pair<const clang::VarDecl *, const clang::Expr *>
parseAssignment(const Stmt *S);
+// Do not reorder! The getMostNullable method relies on the order.
+// Optimization: Most pointers expected to be unspecified. When a symbol has an
+// unspecified or nonnull type non of the rules would indicate any problem for
+// that symbol. For this reason only nullable and contradicted nullability are
+// stored for a symbol. When a symbol is already contradicted, it can not be
+// casted back to nullable.
+enum class Nullability : char {
+ Contradicted, // Tracked nullability is contradicted by an explicit cast. Do
+ // not report any nullability related issue for this symbol.
+ // This nullability is propagated aggressively to avoid false
+ // positive results. See the comment on getMostNullable method.
+ Nullable,
+ Unspecified,
+ Nonnull
+};
+
+/// Get nullability annotation for a given type.
+Nullability getNullabilityAnnotation(QualType Type);
+
} // end GR namespace
} // end clang namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index e7f79ac..7d3f117 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -774,6 +774,14 @@
const LocationContext *FromLC,
const LocationContext *ToLC);
+ /// Adds an initialized temporary and/or a materialization, whichever is
+ /// necessary, by looking at the whole construction context. Handles
+ /// function return values, which need the construction context of the parent
+ /// stack frame, automagically.
+ ProgramStateRef addAllNecessaryTemporaryInfo(
+ ProgramStateRef State, const ConstructionContext *CC,
+ const LocationContext *LC, const MemRegion *R);
+
/// Store the region returned by operator new() so that the constructor
/// that follows it knew what location to initialize. The value should be
/// cleared once the respective CXXNewExpr CFGStmt element is processed.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index 29e44b3..0f507fd 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -195,7 +195,7 @@
void dump() const;
SymExpr::symbol_iterator symbol_begin() const {
- const SymExpr *SE = getAsSymbolicExpression();
+ const SymExpr *SE = getAsSymbol(/*IncludeBaseRegions=*/true);
if (SE)
return SE->symbol_begin();
else
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
index 3169791..7df8f37 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
@@ -87,7 +87,7 @@
static std::unique_ptr<WorkList> makeUnexploredFirstPriorityQueue();
};
-} // end GR namespace
+} // end ento namespace
} // end clang namespace
diff --git a/include/clang/Tooling/ArgumentsAdjusters.h b/include/clang/Tooling/ArgumentsAdjusters.h
index 4eb0225..a288f87 100644
--- a/include/clang/Tooling/ArgumentsAdjusters.h
+++ b/include/clang/Tooling/ArgumentsAdjusters.h
@@ -1,4 +1,4 @@
-//===--- ArgumentsAdjusters.h - Command line arguments adjuster -*- C++ -*-===//
+//===- ArgumentsAdjusters.h - Command line arguments adjuster ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file declares typedef ArgumentsAdjuster and functions to create several
+// This file declares type ArgumentsAdjuster and functions to create several
// useful argument adjusters.
// ArgumentsAdjusters modify command line arguments obtained from a compilation
// database before they are used to run a frontend action.
@@ -27,14 +27,14 @@
namespace tooling {
/// \brief A sequence of command line arguments.
-typedef std::vector<std::string> CommandLineArguments;
+using CommandLineArguments = std::vector<std::string>;
/// \brief A prototype of a command line adjuster.
///
/// Command line argument adjuster is responsible for command line arguments
/// modification before the arguments are used to run a frontend action.
-typedef std::function<CommandLineArguments(
- const CommandLineArguments &, StringRef Filename)> ArgumentsAdjuster;
+using ArgumentsAdjuster = std::function<CommandLineArguments(
+ const CommandLineArguments &, StringRef Filename)>;
/// \brief Gets an argument adjuster that converts input command line arguments
/// to the "syntax check only" variant.
@@ -70,4 +70,3 @@
} // namespace clang
#endif // LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
-
diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h
index bc3e67b..55e1131 100644
--- a/include/clang/Tooling/CompilationDatabase.h
+++ b/include/clang/Tooling/CompilationDatabase.h
@@ -1,4 +1,4 @@
-//===--- CompilationDatabase.h - --------------------------------*- C++ -*-===//
+//===- CompilationDatabase.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -34,6 +34,7 @@
#include "llvm/ADT/Twine.h"
#include <memory>
#include <string>
+#include <utility>
#include <vector>
namespace clang {
@@ -41,13 +42,11 @@
/// \brief Specifies the working directory and command of a compilation.
struct CompileCommand {
- CompileCommand() {}
+ CompileCommand() = default;
CompileCommand(Twine Directory, Twine Filename,
std::vector<std::string> CommandLine, Twine Output)
- : Directory(Directory.str()),
- Filename(Filename.str()),
- CommandLine(std::move(CommandLine)),
- Output(Output.str()){}
+ : Directory(Directory.str()), Filename(Filename.str()),
+ CommandLine(std::move(CommandLine)), Output(Output.str()){}
/// \brief The working directory the command was executed from.
std::string Directory;
@@ -113,7 +112,7 @@
/// A compilation database representing the project would return both command
/// lines for a.cc and b.cc and only the first command line for t.cc.
virtual std::vector<CompileCommand> getCompileCommands(
- StringRef FilePath) const = 0;
+ StringRef FilePath) const = 0;
/// \brief Returns the list of all files available in the compilation database.
///
@@ -214,7 +213,7 @@
std::vector<CompileCommand> CompileCommands;
};
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H
diff --git a/include/clang/Tooling/CompilationDatabasePluginRegistry.h b/include/clang/Tooling/CompilationDatabasePluginRegistry.h
index 7323ec8..051a08e 100644
--- a/include/clang/Tooling/CompilationDatabasePluginRegistry.h
+++ b/include/clang/Tooling/CompilationDatabasePluginRegistry.h
@@ -1,4 +1,4 @@
-//===--- CompilationDatabasePluginRegistry.h - ------------------*- C++ -*-===//
+//===- CompilationDatabasePluginRegistry.h ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,12 +16,10 @@
namespace clang {
namespace tooling {
-class CompilationDatabasePlugin;
+using CompilationDatabasePluginRegistry =
+ llvm::Registry<CompilationDatabasePlugin>;
-typedef llvm::Registry<CompilationDatabasePlugin>
- CompilationDatabasePluginRegistry;
+} // namespace tooling
+} // namespace clang
-} // end namespace tooling
-} // end namespace clang
-
-#endif
+#endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H
diff --git a/include/clang/Tooling/Core/Replacement.h b/include/clang/Tooling/Core/Replacement.h
index 3fea9ae..146d6aa 100644
--- a/include/clang/Tooling/Core/Replacement.h
+++ b/include/clang/Tooling/Core/Replacement.h
@@ -1,4 +1,4 @@
-//===--- Replacement.h - Framework for clang refactoring tools --*- C++ -*-===//
+//===- Replacement.h - Framework for clang refactoring tools ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,29 +19,32 @@
#ifndef LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
#define LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <set>
#include <string>
#include <system_error>
+#include <utility>
#include <vector>
namespace clang {
+class FileManager;
class Rewriter;
+class SourceManager;
namespace tooling {
/// \brief A source range independent of the \c SourceManager.
class Range {
public:
- Range() : Offset(0), Length(0) {}
+ Range() = default;
Range(unsigned Offset, unsigned Length) : Offset(Offset), Length(Length) {}
/// \brief Accessors.
@@ -70,8 +73,8 @@
/// @}
private:
- unsigned Offset;
- unsigned Length;
+ unsigned Offset = 0;
+ unsigned Length = 0;
};
/// \brief A text replacement.
@@ -186,9 +189,11 @@
}
replacement_error Err;
+
// A new replacement, which is to expected be added into a set of
// replacements, that is causing problem.
llvm::Optional<Replacement> NewReplacement;
+
// An existing replacement in a replacements set that is causing problem.
llvm::Optional<Replacement> ExistingReplacement;
};
@@ -203,12 +208,12 @@
/// Two replacements are considered conflicts if they overlap or have the same
/// offset (i.e. order-dependent).
class Replacements {
- private:
- typedef std::set<Replacement> ReplacementsImpl;
+private:
+ using ReplacementsImpl = std::set<Replacement>;
- public:
- typedef ReplacementsImpl::const_iterator const_iterator;
- typedef ReplacementsImpl::const_reverse_iterator const_reverse_iterator;
+public:
+ using const_iterator = ReplacementsImpl::const_iterator;
+ using const_reverse_iterator = ReplacementsImpl::const_reverse_iterator;
Replacements() = default;
@@ -283,7 +288,6 @@
return Replaces == RHS.Replaces;
}
-
private:
Replacements(const_iterator Begin, const_iterator End)
: Replaces(Begin, End) {}
@@ -329,6 +333,7 @@
struct TranslationUnitReplacements {
/// Name of the main source for the translation unit.
std::string MainSourceFile;
+
std::vector<Replacement> Replacements;
};
@@ -360,7 +365,8 @@
setFromSourceRange(Sources, Range, ReplacementText, LangOpts);
}
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+
+} // namespace clang
#endif // LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
diff --git a/include/clang/Tooling/FileMatchTrie.h b/include/clang/Tooling/FileMatchTrie.h
index 882979e..74f30d9 100644
--- a/include/clang/Tooling/FileMatchTrie.h
+++ b/include/clang/Tooling/FileMatchTrie.h
@@ -1,4 +1,4 @@
-//===--- FileMatchTrie.h - --------------------------------------*- C++ -*-===//
+//===- FileMatchTrie.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,20 +16,19 @@
#define LLVM_CLANG_TOOLING_FILEMATCHTRIE_H
#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
#include <memory>
-namespace llvm {
-class StringRef;
-}
-
namespace clang {
namespace tooling {
+class FileMatchTrieNode;
+
struct PathComparator {
- virtual ~PathComparator() {}
+ virtual ~PathComparator() = default;
+
virtual bool equivalent(StringRef FileA, StringRef FileB) const = 0;
};
-class FileMatchTrieNode;
/// \brief A trie to efficiently match against the entries of the compilation
/// database in order of matching suffix length.
@@ -78,13 +77,13 @@
/// written to 'Error'.
StringRef findEquivalent(StringRef FileName,
raw_ostream &Error) const;
+
private:
FileMatchTrieNode *Root;
std::unique_ptr<PathComparator> Comparator;
};
+} // namespace tooling
+} // namespace clang
-} // end namespace tooling
-} // end namespace clang
-
-#endif
+#endif // LLVM_CLANG_TOOLING_FILEMATCHTRIE_H
diff --git a/include/clang/Tooling/JSONCompilationDatabase.h b/include/clang/Tooling/JSONCompilationDatabase.h
index 9a68662..bc4748f 100644
--- a/include/clang/Tooling/JSONCompilationDatabase.h
+++ b/include/clang/Tooling/JSONCompilationDatabase.h
@@ -1,4 +1,4 @@
-//===--- JSONCompilationDatabase.h - ----------------------------*- C++ -*-===//
+//===- JSONCompilationDatabase.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,6 +18,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/FileMatchTrie.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -25,6 +26,8 @@
#include "llvm/Support/YAMLParser.h"
#include <memory>
#include <string>
+#include <tuple>
+#include <utility>
#include <vector>
namespace clang {
@@ -110,10 +113,10 @@
// Otherwise, each entry in the command line vector is a literal
// argument to the compiler.
// The output field may be a nullptr.
- typedef std::tuple<llvm::yaml::ScalarNode *,
- llvm::yaml::ScalarNode *,
- std::vector<llvm::yaml::ScalarNode *>,
- llvm::yaml::ScalarNode *> CompileCommandRef;
+ using CompileCommandRef =
+ std::tuple<llvm::yaml::ScalarNode *, llvm::yaml::ScalarNode *,
+ std::vector<llvm::yaml::ScalarNode *>,
+ llvm::yaml::ScalarNode *>;
/// \brief Converts the given array of CompileCommandRefs to CompileCommands.
void getCommands(ArrayRef<CompileCommandRef> CommandsRef,
@@ -134,7 +137,7 @@
llvm::yaml::Stream YAMLStream;
};
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H
diff --git a/include/clang/Tooling/ToolExecutorPluginRegistry.h b/include/clang/Tooling/ToolExecutorPluginRegistry.h
index 11ba895..921689d 100644
--- a/include/clang/Tooling/ToolExecutorPluginRegistry.h
+++ b/include/clang/Tooling/ToolExecutorPluginRegistry.h
@@ -1,4 +1,4 @@
-//===--- ToolExecutorPluginRegistry.h - -------------------------*- C++ -*-===//
+//===- ToolExecutorPluginRegistry.h -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,9 +16,9 @@
namespace clang {
namespace tooling {
-typedef llvm::Registry<ToolExecutorPlugin> ToolExecutorPluginRegistry;
+using ToolExecutorPluginRegistry = llvm::Registry<ToolExecutorPlugin>;
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+} // namespace clang
#endif // LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h
index 8ddfef3..24b4a2e 100644
--- a/include/clang/Tooling/Tooling.h
+++ b/include/clang/Tooling/Tooling.h
@@ -1,4 +1,4 @@
-//===--- Tooling.h - Framework for standalone Clang tools -------*- C++ -*-===//
+//===- Tooling.h - Framework for standalone Clang tools ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -31,34 +31,42 @@
#define LLVM_CLANG_TOOLING_TOOLING_H
#include "clang/AST/ASTConsumer.h"
-#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
-#include "clang/Driver/Util.h"
+#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/PCHContainerOperations.h"
-#include "clang/Lex/ModuleLoader.h"
#include "clang/Tooling/ArgumentsAdjusters.h"
-#include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Option/Option.h"
#include <memory>
#include <string>
+#include <utility>
#include <vector>
namespace clang {
-namespace driver {
-class Compilation;
-} // end namespace driver
-
+class CompilerInstance;
class CompilerInvocation;
+class DiagnosticConsumer;
+class DiagnosticsEngine;
class SourceManager;
-class FrontendAction;
+
+namespace driver {
+
+class Compilation;
+
+} // namespace driver
namespace tooling {
+class CompilationDatabase;
+
/// \brief Interface to process a clang::CompilerInvocation.
///
/// If your tool is based on FrontendAction, you should be deriving from
@@ -69,7 +77,7 @@
/// \brief Perform an action for an invocation.
virtual bool
- runInvocation(std::shared_ptr<clang::CompilerInvocation> Invocation,
+ runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
FileManager *Files,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) = 0;
@@ -86,7 +94,7 @@
~FrontendActionFactory() override;
/// \brief Invokes the compiler with a FrontendAction created by create().
- bool runInvocation(std::shared_ptr<clang::CompilerInvocation> Invocation,
+ bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
FileManager *Files,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) override;
@@ -94,7 +102,7 @@
/// \brief Returns a new clang::FrontendAction.
///
/// The caller takes ownership of the returned action.
- virtual clang::FrontendAction *create() = 0;
+ virtual FrontendAction *create() = 0;
};
/// \brief Returns a new FrontendActionFactory for a given type.
@@ -112,7 +120,7 @@
/// newFrontendActionFactory.
class SourceFileCallbacks {
public:
- virtual ~SourceFileCallbacks() {}
+ virtual ~SourceFileCallbacks() = default;
/// \brief Called before a source file is processed by a FrontEndAction.
/// \see clang::FrontendAction::BeginSourceFileAction
@@ -149,14 +157,14 @@
/// clang modules.
///
/// \return - True if 'ToolAction' was successfully executed.
-bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
+bool runToolOnCode(FrontendAction *ToolAction, const Twine &Code,
const Twine &FileName = "input.cc",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>());
/// The first part of the pair is the filename, the second part the
/// file-content.
-typedef std::vector<std::pair<std::string, std::string>> FileContentMappings;
+using FileContentMappings = std::vector<std::pair<std::string, std::string>>;
/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and
/// with additional other flags.
@@ -172,7 +180,7 @@
///
/// \return - True if 'ToolAction' was successfully executed.
bool runToolOnCodeWithArgs(
- clang::FrontendAction *ToolAction, const Twine &Code,
+ FrontendAction *ToolAction, const Twine &Code,
const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
const Twine &ToolName = "clang-tool",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
@@ -265,8 +273,8 @@
void addFileMappingsTo(SourceManager &SourceManager);
bool runInvocation(const char *BinaryName,
- clang::driver::Compilation *Compilation,
- std::shared_ptr<clang::CompilerInvocation> Invocation,
+ driver::Compilation *Compilation,
+ std::shared_ptr<CompilerInvocation> Invocation,
std::shared_ptr<PCHContainerOperations> PCHContainerOps);
std::vector<std::string> CommandLine;
@@ -276,7 +284,7 @@
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
// Maps <file name> -> <file content>.
llvm::StringMap<StringRef> MappedFileContents;
- DiagnosticConsumer *DiagConsumer;
+ DiagnosticConsumer *DiagConsumer = nullptr;
};
/// \brief Utility to run a FrontendAction over a set of files.
@@ -287,7 +295,7 @@
/// a frontend action. One could install an additional command line
/// arguments adjuster by calling the appendArgumentsAdjuster() method.
class ClangTool {
- public:
+public:
/// \brief Constructs a clang tool to run over a list of files.
///
/// \param Compilations The CompilationDatabase which contains the compile
@@ -354,20 +362,22 @@
llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem;
llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
llvm::IntrusiveRefCntPtr<FileManager> Files;
+
// Contains a list of pairs (<file name>, <file content>).
- std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
+ std::vector<std::pair<StringRef, StringRef>> MappedFileContents;
+
llvm::StringSet<> SeenWorkingDirectories;
ArgumentsAdjuster ArgsAdjuster;
- DiagnosticConsumer *DiagConsumer;
+ DiagnosticConsumer *DiagConsumer = nullptr;
};
template <typename T>
std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() {
class SimpleFrontendActionFactory : public FrontendActionFactory {
public:
- clang::FrontendAction *create() override { return new T; }
+ FrontendAction *create() override { return new T; }
};
return std::unique_ptr<FrontendActionFactory>(
@@ -381,36 +391,37 @@
public:
explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory,
SourceFileCallbacks *Callbacks)
- : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
+ : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
- clang::FrontendAction *create() override {
+ FrontendAction *create() override {
return new ConsumerFactoryAdaptor(ConsumerFactory, Callbacks);
}
private:
- class ConsumerFactoryAdaptor : public clang::ASTFrontendAction {
+ class ConsumerFactoryAdaptor : public ASTFrontendAction {
public:
ConsumerFactoryAdaptor(FactoryT *ConsumerFactory,
SourceFileCallbacks *Callbacks)
- : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
+ : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
- std::unique_ptr<clang::ASTConsumer>
- CreateASTConsumer(clang::CompilerInstance &, StringRef) override {
+ std::unique_ptr<ASTConsumer>
+ CreateASTConsumer(CompilerInstance &, StringRef) override {
return ConsumerFactory->newASTConsumer();
}
protected:
bool BeginSourceFileAction(CompilerInstance &CI) override {
- if (!clang::ASTFrontendAction::BeginSourceFileAction(CI))
+ if (!ASTFrontendAction::BeginSourceFileAction(CI))
return false;
if (Callbacks)
return Callbacks->handleBeginSource(CI);
return true;
}
+
void EndSourceFileAction() override {
if (Callbacks)
Callbacks->handleEndSource();
- clang::ASTFrontendAction::EndSourceFileAction();
+ ASTFrontendAction::EndSourceFileAction();
}
private:
@@ -463,11 +474,11 @@
StringRef InvokedAs);
/// \brief Creates a \c CompilerInvocation.
-clang::CompilerInvocation *newInvocation(
- clang::DiagnosticsEngine *Diagnostics,
- const llvm::opt::ArgStringList &CC1Args);
+CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics,
+ const llvm::opt::ArgStringList &CC1Args);
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+
+} // namespace clang
#endif // LLVM_CLANG_TOOLING_TOOLING_H
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 5039be3..ea96a07 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2186,7 +2186,7 @@
}
}
- std::sort(
+ llvm::sort(
Bases.begin(), Bases.end(), [&](const std::pair<QualType, int64_t> &L,
const std::pair<QualType, int64_t> &R) {
return Layout.getBaseClassOffset(L.first->getAsCXXRecordDecl()) <
@@ -2643,9 +2643,11 @@
}
bool ASTContext::isParamDestroyedInCallee(QualType T) const {
- return getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee() ||
- T.hasTrivialABIOverride() ||
- T.isDestructedType() == QualType::DK_nontrivial_c_struct;
+ if (getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee())
+ return true;
+ if (const auto *RT = T->getBaseElementTypeUnsafe()->getAs<RecordType>())
+ return RT->getDecl()->isParamDestroyedInCallee();
+ return false;
}
/// getComplexType - Return the uniqued reference to the type for a complex
@@ -8241,6 +8243,8 @@
return QualType();
if (lbaseInfo.getNoCallerSavedRegs() != rbaseInfo.getNoCallerSavedRegs())
return QualType();
+ if (lbaseInfo.getNoCfCheck() != rbaseInfo.getNoCfCheck())
+ return QualType();
// FIXME: some uses, e.g. conditional exprs, really want this to be 'both'.
bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
@@ -9402,8 +9406,7 @@
return false;
} else if (isa<PragmaCommentDecl>(D))
return true;
- else if (isa<OMPThreadPrivateDecl>(D) ||
- D->hasAttr<OMPDeclareTargetDeclAttr>())
+ else if (isa<OMPThreadPrivateDecl>(D))
return true;
else if (isa<PragmaDetectMismatchDecl>(D))
return true;
@@ -9492,6 +9495,15 @@
if (DeclMustBeEmitted(BindingVD))
return true;
+ // If the decl is marked as `declare target`, it should be emitted.
+ for (const auto *Decl : D->redecls()) {
+ if (!Decl->hasAttrs())
+ continue;
+ if (const auto *Attr = Decl->getAttr<OMPDeclareTargetDeclAttr>())
+ if (Attr->getMapType() != OMPDeclareTargetDeclAttr::MT_Link)
+ return true;
+ }
+
return false;
}
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index e264d05..0ac2908 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -1602,7 +1602,7 @@
void ASTDumper::VisitClassScopeFunctionSpecializationDecl(
const ClassScopeFunctionSpecializationDecl *D) {
- dumpDeclRef(D->getSpecialization());
+ dumpDecl(D->getSpecialization());
if (D->hasExplicitTemplateArgs())
dumpTemplateArgumentListInfo(D->templateArgs());
}
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index ac262e7..6b9260d 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -1105,7 +1105,6 @@
= FromData.HasConstexprNonCopyMoveConstructor;
ToData.HasDefaultedDefaultConstructor
= FromData.HasDefaultedDefaultConstructor;
- ToData.CanPassInRegisters = FromData.CanPassInRegisters;
ToData.DefaultedDefaultConstructorIsConstexpr
= FromData.DefaultedDefaultConstructorIsConstexpr;
ToData.HasConstexprDefaultConstructor
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index b640dcc..4fb687d 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -27,6 +27,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/ODRHash.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Stmt.h"
@@ -76,6 +77,24 @@
return D->getASTContext().getPrimaryMergedDecl(D);
}
+void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
+ SourceLocation Loc = this->Loc;
+ if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
+ if (Loc.isValid()) {
+ Loc.print(OS, Context.getSourceManager());
+ OS << ": ";
+ }
+ OS << Message;
+
+ if (auto *ND = dyn_cast_or_null<NamedDecl>(TheDecl)) {
+ OS << " '";
+ ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true);
+ OS << "'";
+ }
+
+ OS << '\n';
+}
+
// Defined here so that it can be inlined into its direct callers.
bool Decl::isOutOfLine() const {
return !getLexicalDeclContext()->Equals(getDeclContext());
@@ -3931,7 +3950,8 @@
HasObjectMember(false), HasVolatileMember(false),
LoadedFieldsFromExternalStorage(false),
NonTrivialToPrimitiveDefaultInitialize(false),
- NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false) {
+ NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false),
+ CanPassInRegisters(true), ParamDestroyedInCallee(false) {
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
}
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 487386f..1e1ee43 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -93,7 +93,6 @@
DeclaredNonTrivialSpecialMembersForCall(0), HasIrrelevantDestructor(true),
HasConstexprNonCopyMoveConstructor(false),
HasDefaultedDefaultConstructor(false),
- CanPassInRegisters(true),
DefaultedDefaultConstructorIsConstexpr(true),
HasConstexprDefaultConstructor(false),
HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
@@ -802,7 +801,17 @@
struct DefinitionData &Data = data();
Data.PlainOldData = false;
Data.HasTrivialSpecialMembers = 0;
- Data.HasTrivialSpecialMembersForCall = 0;
+
+ // __strong or __weak fields do not make special functions non-trivial
+ // for the purpose of calls.
+ Qualifiers::ObjCLifetime LT = T.getQualifiers().getObjCLifetime();
+ if (LT != Qualifiers::OCL_Strong && LT != Qualifiers::OCL_Weak)
+ data().HasTrivialSpecialMembersForCall = 0;
+
+ // Structs with __weak fields should never be passed directly.
+ if (LT == Qualifiers::OCL_Weak)
+ setCanPassInRegisters(false);
+
Data.HasIrrelevantDestructor = false;
} else if (!Context.getLangOpts().ObjCAutoRefCount) {
setHasObjectMember(true);
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index a7949b3..8854f78 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
@@ -56,11 +57,11 @@
begin()[Idx] = P;
if (!P->isTemplateParameterPack()) {
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
if (NTTP->getType()->containsUnexpandedParameterPack())
ContainsUnexpandedParameterPack = true;
- if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
+ if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
if (TTP->getTemplateParameters()->containsUnexpandedParameterPack())
ContainsUnexpandedParameterPack = true;
@@ -118,11 +119,9 @@
return 0;
const NamedDecl *FirstParm = getParam(0);
- if (const TemplateTypeParmDecl *TTP
- = dyn_cast<TemplateTypeParmDecl>(FirstParm))
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(FirstParm))
return TTP->getDepth();
- else if (const NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(FirstParm))
+ else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(FirstParm))
return NTTP->getDepth();
else
return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth();
@@ -133,7 +132,7 @@
for (NamedDecl *P : *Params) {
P->setDeclContext(Owner);
- if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
+ if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner);
}
}
@@ -258,7 +257,7 @@
RedeclarableTemplateDecl::CommonBase *
FunctionTemplateDecl::newCommon(ASTContext &C) const {
- Common *CommonPtr = new (C) Common;
+ auto *CommonPtr = new (C) Common;
C.addDestruction(CommonPtr);
return CommonPtr;
}
@@ -318,8 +317,8 @@
return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
}
- ConstrainedTemplateDeclInfo *const CTDI = new (C) ConstrainedTemplateDeclInfo;
- ClassTemplateDecl *const New =
+ auto *const CTDI = new (C) ConstrainedTemplateDeclInfo;
+ auto *const New =
new (C, DC) ClassTemplateDecl(CTDI, C, DC, L, Name, Params, Decl);
New->setAssociatedConstraints(AssociatedConstraints);
return New;
@@ -349,7 +348,7 @@
RedeclarableTemplateDecl::CommonBase *
ClassTemplateDecl::newCommon(ASTContext &C) const {
- Common *CommonPtr = new (C) Common;
+ auto *CommonPtr = new (C) Common;
C.addDestruction(CommonPtr);
return CommonPtr;
}
@@ -453,8 +452,8 @@
SourceLocation KeyLoc, SourceLocation NameLoc,
unsigned D, unsigned P, IdentifierInfo *Id,
bool Typename, bool ParameterPack) {
- TemplateTypeParmDecl *TTPDecl =
- new (C, DC) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename);
+ auto *TTPDecl =
+ new (C, DC) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename);
QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl);
TTPDecl->setTypeForDecl(TTPType.getTypePtr());
return TTPDecl;
@@ -709,7 +708,7 @@
ClassTemplateDecl *SpecializedTemplate,
ArrayRef<TemplateArgument> Args,
ClassTemplateSpecializationDecl *PrevDecl) {
- ClassTemplateSpecializationDecl *Result =
+ auto *Result =
new (Context, DC) ClassTemplateSpecializationDecl(
Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
SpecializedTemplate, Args, PrevDecl);
@@ -722,7 +721,7 @@
ClassTemplateSpecializationDecl *
ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- ClassTemplateSpecializationDecl *Result =
+ auto *Result =
new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
Result->MayHaveOutOfDateDef = false;
return Result;
@@ -732,7 +731,7 @@
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
- auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this);
+ const auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this);
if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
PS ? PS->getTemplateArgsAsWritten() : nullptr) {
printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy);
@@ -744,8 +743,8 @@
ClassTemplateDecl *
ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
- if (SpecializedPartialSpecialization *PartialSpec
- = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ if (const auto *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
return SpecializedTemplate.get<ClassTemplateDecl*>();
}
@@ -770,7 +769,7 @@
// uses ExplicitInfo to record the TypeAsWritten, but the source
// locations should be retrieved from the instantiation pattern.
using CTPSDecl = ClassTemplatePartialSpecializationDecl;
- CTPSDecl *ctpsd = const_cast<CTPSDecl*>(cast<CTPSDecl>(this));
+ auto *ctpsd = const_cast<CTPSDecl *>(cast<CTPSDecl>(this));
CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember();
assert(inst_from != nullptr);
return inst_from->getSourceRange();
@@ -782,9 +781,9 @@
inst_from = getInstantiatedFrom();
if (inst_from.isNull())
return getSpecializedTemplate()->getSourceRange();
- if (ClassTemplateDecl *ctd = inst_from.dyn_cast<ClassTemplateDecl*>())
+ if (const auto *ctd = inst_from.dyn_cast<ClassTemplateDecl *>())
return ctd->getSourceRange();
- return inst_from.get<ClassTemplatePartialSpecializationDecl*>()
+ return inst_from.get<ClassTemplatePartialSpecializationDecl *>()
->getSourceRange();
}
}
@@ -826,7 +825,7 @@
const ASTTemplateArgumentListInfo *ASTArgInfos =
ASTTemplateArgumentListInfo::Create(Context, ArgInfos);
- ClassTemplatePartialSpecializationDecl *Result = new (Context, DC)
+ auto *Result = new (Context, DC)
ClassTemplatePartialSpecializationDecl(Context, TK, DC, StartLoc, IdLoc,
Params, SpecializedTemplate, Args,
ASTArgInfos, PrevDecl);
@@ -840,8 +839,7 @@
ClassTemplatePartialSpecializationDecl *
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- ClassTemplatePartialSpecializationDecl *Result =
- new (C, ID) ClassTemplatePartialSpecializationDecl(C);
+ auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C);
Result->MayHaveOutOfDateDef = false;
return Result;
}
@@ -887,7 +885,7 @@
RedeclarableTemplateDecl::CommonBase *
TypeAliasTemplateDecl::newCommon(ASTContext &C) const {
- Common *CommonPtr = new (C) Common;
+ auto *CommonPtr = new (C) Common;
C.addDestruction(CommonPtr);
return CommonPtr;
}
@@ -950,7 +948,7 @@
RedeclarableTemplateDecl::CommonBase *
VarTemplateDecl::newCommon(ASTContext &C) const {
- Common *CommonPtr = new (C) Common;
+ auto *CommonPtr = new (C) Common;
C.addDestruction(CommonPtr);
return CommonPtr;
}
@@ -1048,7 +1046,7 @@
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
- auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this);
+ const auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this);
if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
PS ? PS->getTemplateArgsAsWritten() : nullptr) {
printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy);
@@ -1059,7 +1057,7 @@
}
VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
- if (SpecializedPartialSpecialization *PartialSpec =
+ if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
return SpecializedTemplate.get<VarTemplateDecl *>();
@@ -1104,7 +1102,7 @@
const ASTTemplateArgumentListInfo *ASTArgInfos
= ASTTemplateArgumentListInfo::Create(Context, ArgInfos);
- VarTemplatePartialSpecializationDecl *Result =
+ auto *Result =
new (Context, DC) VarTemplatePartialSpecializationDecl(
Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo,
S, Args, ASTArgInfos);
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 1813dfb..57c8850 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -2049,6 +2049,10 @@
case GenericSelectionExprClass:
return cast<GenericSelectionExpr>(this)->getResultExpr()->
isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
+ case CoawaitExprClass:
+ case CoyieldExprClass:
+ return cast<CoroutineSuspendExpr>(this)->getResumeExpr()->
+ isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
case ChooseExprClass:
return cast<ChooseExpr>(this)->getChosenSubExpr()->
isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 135e70e..84ac4da 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -63,14 +63,22 @@
static QualType getType(APValue::LValueBase B) {
if (!B) return QualType();
- if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>())
+ if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) {
// FIXME: It's unclear where we're supposed to take the type from, and
- // this actually matters for arrays of unknown bound. Using the type of
- // the most recent declaration isn't clearly correct in general. Eg:
+ // this actually matters for arrays of unknown bound. Eg:
//
// extern int arr[]; void f() { extern int arr[3]; };
// constexpr int *p = &arr[1]; // valid?
- return cast<ValueDecl>(D->getMostRecentDecl())->getType();
+ //
+ // For now, we take the array bound from the most recent declaration.
+ for (auto *Redecl = cast<ValueDecl>(D->getMostRecentDecl()); Redecl;
+ Redecl = cast_or_null<ValueDecl>(Redecl->getPreviousDecl())) {
+ QualType T = Redecl->getType();
+ if (!T->isIncompleteArrayType())
+ return T;
+ }
+ return D->getType();
+ }
const Expr *Base = B.get<const Expr*>();
@@ -5467,8 +5475,8 @@
llvm::APInt &Result) {
const AllocSizeAttr *AllocSize = getAllocSizeAttr(Call);
- assert(AllocSize && AllocSize->elemSizeParam().isValid());
- unsigned SizeArgNo = AllocSize->elemSizeParam().getASTIndex();
+ assert(AllocSize && AllocSize->getElemSizeParam().isValid());
+ unsigned SizeArgNo = AllocSize->getElemSizeParam().getASTIndex();
unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType());
if (Call->getNumArgs() <= SizeArgNo)
return false;
@@ -5486,13 +5494,13 @@
if (!EvaluateAsSizeT(Call->getArg(SizeArgNo), SizeOfElem))
return false;
- if (!AllocSize->numElemsParam().isValid()) {
+ if (!AllocSize->getNumElemsParam().isValid()) {
Result = std::move(SizeOfElem);
return true;
}
APSInt NumberOfElems;
- unsigned NumArgNo = AllocSize->numElemsParam().getASTIndex();
+ unsigned NumArgNo = AllocSize->getNumElemsParam().getASTIndex();
if (!EvaluateAsSizeT(Call->getArg(NumArgNo), NumberOfElems))
return false;
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index d6d3792..0f22bf2 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -323,7 +323,7 @@
AdditionalAbiTags->end());
}
- std::sort(TagList.begin(), TagList.end());
+ llvm::sort(TagList.begin(), TagList.end());
TagList.erase(std::unique(TagList.begin(), TagList.end()), TagList.end());
writeSortedUniqueAbiTags(Out, TagList);
@@ -339,7 +339,7 @@
}
const AbiTagList &getSortedUniqueUsedAbiTags() {
- std::sort(UsedAbiTags.begin(), UsedAbiTags.end());
+ llvm::sort(UsedAbiTags.begin(), UsedAbiTags.end());
UsedAbiTags.erase(std::unique(UsedAbiTags.begin(), UsedAbiTags.end()),
UsedAbiTags.end());
return UsedAbiTags;
@@ -2628,6 +2628,7 @@
case CC_OpenCLKernel:
case CC_PreserveMost:
case CC_PreserveAll:
+ case CC_CUDAKernel:
// FIXME: we should be mangling all of the above.
return "";
@@ -2688,7 +2689,7 @@
// Mangle CV-qualifiers, if present. These are 'this' qualifiers,
// e.g. "const" in "int (A::*)() const".
- mangleQualifiers(Qualifiers::fromCVRMask(T->getTypeQuals()));
+ mangleQualifiers(Qualifiers::fromCVRUMask(T->getTypeQuals()));
// Mangle instantiation-dependent exception-specification, if present,
// per cxx-abi-dev proposal on 2016-10-11.
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 068254a..06936f0 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -135,7 +135,8 @@
bool shouldMangleStringLiteral(const StringLiteral *SL) override;
void mangleCXXName(const NamedDecl *D, raw_ostream &Out) override;
void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
- raw_ostream &) override;
+ const MethodVFTableLocation &ML,
+ raw_ostream &Out) override;
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
raw_ostream &) override;
void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
@@ -290,16 +291,15 @@
raw_ostream &getStream() const { return Out; }
- void mangle(const NamedDecl *D, StringRef Prefix = "\01?");
+ void mangle(const NamedDecl *D, StringRef Prefix = "?");
void mangleName(const NamedDecl *ND);
void mangleFunctionEncoding(const FunctionDecl *FD, bool ShouldMangle);
void mangleVariableEncoding(const VarDecl *VD);
void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD);
void mangleMemberFunctionPointer(const CXXRecordDecl *RD,
const CXXMethodDecl *MD);
- void mangleVirtualMemPtrThunk(
- const CXXMethodDecl *MD,
- const MicrosoftVTableContext::MethodVFTableLocation &ML);
+ void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ const MethodVFTableLocation &ML);
void mangleNumber(int64_t Number);
void mangleTagTypeKind(TagTypeKind TK);
void mangleArtificalTagType(TagTypeKind TK, StringRef UnqualifiedName,
@@ -607,7 +607,7 @@
if (MD->isVirtual()) {
MicrosoftVTableContext *VTContext =
cast<MicrosoftVTableContext>(getASTContext().getVTableContext());
- const MicrosoftVTableContext::MethodVFTableLocation &ML =
+ const MethodVFTableLocation &ML =
VTContext->getMethodVFTableLocation(GlobalDecl(MD));
mangleVirtualMemPtrThunk(MD, ML);
NVOffset = ML.VFPtrOffset.getQuantity();
@@ -644,8 +644,7 @@
}
void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk(
- const CXXMethodDecl *MD,
- const MicrosoftVTableContext::MethodVFTableLocation &ML) {
+ const CXXMethodDecl *MD, const MethodVFTableLocation &ML) {
// Get the vftable offset.
CharUnits PointerWidth = getASTContext().toCharUnitsFromBits(
getASTContext().getTargetInfo().getPointerWidth(0));
@@ -2775,17 +2774,12 @@
}
}
-void
-MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
- raw_ostream &Out) {
- MicrosoftVTableContext *VTContext =
- cast<MicrosoftVTableContext>(getASTContext().getVTableContext());
- const MicrosoftVTableContext::MethodVFTableLocation &ML =
- VTContext->getMethodVFTableLocation(GlobalDecl(MD));
-
+void MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(
+ const CXXMethodDecl *MD, const MethodVFTableLocation &ML,
+ raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01?";
+ Mangler.getStream() << '?';
Mangler.mangleVirtualMemPtrThunk(MD, ML);
}
@@ -2794,7 +2788,7 @@
raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01?";
+ Mangler.getStream() << '?';
Mangler.mangleName(MD);
mangleThunkThisAdjustment(MD, Thunk.This, Mangler, MHO);
if (!Thunk.Return.isEmpty())
@@ -2815,7 +2809,7 @@
assert(Type == Dtor_Deleting);
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type);
- Mangler.getStream() << "\01??_E";
+ Mangler.getStream() << "??_E";
Mangler.mangleName(DD->getParent());
mangleThunkThisAdjustment(DD, Adjustment, Mangler, MHO);
Mangler.mangleFunctionType(DD->getType()->castAs<FunctionProtoType>(), DD);
@@ -2831,9 +2825,9 @@
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
if (Derived->hasAttr<DLLImportAttr>())
- Mangler.getStream() << "\01??_S";
+ Mangler.getStream() << "??_S";
else
- Mangler.getStream() << "\01??_7";
+ Mangler.getStream() << "??_7";
Mangler.mangleName(Derived);
Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const.
for (const CXXRecordDecl *RD : BasePath)
@@ -2850,7 +2844,7 @@
// is always '7' for vbtables.
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??_8";
+ Mangler.getStream() << "??_8";
Mangler.mangleName(Derived);
Mangler.getStream() << "7B"; // '7' for vbtable, 'B' for const.
for (const CXXRecordDecl *RD : BasePath)
@@ -2861,7 +2855,7 @@
void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??_R0";
+ Mangler.getStream() << "??_R0";
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
Mangler.getStream() << "@8";
}
@@ -2877,7 +2871,7 @@
const CXXRecordDecl *SrcRD, const CXXRecordDecl *DstRD, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??_K";
+ Mangler.getStream() << "??_K";
Mangler.mangleName(SrcRD);
Mangler.getStream() << "$C";
Mangler.mangleName(DstRD);
@@ -2923,7 +2917,7 @@
msvc_hashing_ostream MHO(Stream);
mangleCXXRTTI(T, MHO);
}
- Mangler.getStream() << RTTIMangling.substr(1);
+ Mangler.getStream() << RTTIMangling;
// VS2015 CTP6 omits the copy-constructor in the mangled name. This name is,
// in fact, superfluous but I'm not sure the change was made consciously.
@@ -2935,7 +2929,7 @@
msvc_hashing_ostream MHO(Stream);
mangleCXXCtor(CD, CT, MHO);
}
- Mangler.getStream() << CopyCtorMangling.substr(1);
+ Mangler.getStream() << CopyCtorMangling;
Mangler.getStream() << Size;
if (VBPtrOffset == -1) {
@@ -2954,7 +2948,7 @@
uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??_R1";
+ Mangler.getStream() << "??_R1";
Mangler.mangleNumber(NVOffset);
Mangler.mangleNumber(VBPtrOffset);
Mangler.mangleNumber(VBTableOffset);
@@ -2967,7 +2961,7 @@
const CXXRecordDecl *Derived, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??_R2";
+ Mangler.getStream() << "??_R2";
Mangler.mangleName(Derived);
Mangler.getStream() << "8";
}
@@ -2976,7 +2970,7 @@
const CXXRecordDecl *Derived, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??_R3";
+ Mangler.getStream() << "??_R3";
Mangler.mangleName(Derived);
Mangler.getStream() << "8";
}
@@ -2992,16 +2986,16 @@
llvm::raw_svector_ostream Stream(VFTableMangling);
mangleCXXVFTable(Derived, BasePath, Stream);
- if (VFTableMangling.startswith("\01??@")) {
+ if (VFTableMangling.startswith("??@")) {
assert(VFTableMangling.endswith("@"));
Out << VFTableMangling << "??_R4@";
return;
}
- assert(VFTableMangling.startswith("\01??_7") ||
- VFTableMangling.startswith("\01??_S"));
+ assert(VFTableMangling.startswith("??_7") ||
+ VFTableMangling.startswith("??_S"));
- Out << "\01??_R4" << StringRef(VFTableMangling).drop_front(5);
+ Out << "??_R4" << StringRef(VFTableMangling).drop_front(4);
}
void MicrosoftMangleContextImpl::mangleSEHFilterExpression(
@@ -3012,7 +3006,7 @@
// so the numbering here doesn't have to be the same across TUs.
//
// <mangled-name> ::= ?filt$ <filter-number> @0
- Mangler.getStream() << "\01?filt$" << SEHFilterIds[EnclosingDecl]++ << "@0@";
+ Mangler.getStream() << "?filt$" << SEHFilterIds[EnclosingDecl]++ << "@0@";
Mangler.mangleName(EnclosingDecl);
}
@@ -3024,7 +3018,7 @@
// so the numbering here doesn't have to be the same across TUs.
//
// <mangled-name> ::= ?fin$ <filter-number> @0
- Mangler.getStream() << "\01?fin$" << SEHFinallyIds[EnclosingDecl]++ << "@0@";
+ Mangler.getStream() << "?fin$" << SEHFinallyIds[EnclosingDecl]++ << "@0@";
Mangler.mangleName(EnclosingDecl);
}
@@ -3057,7 +3051,7 @@
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01?$RT" << ManglingNumber << '@';
+ Mangler.getStream() << "?$RT" << ManglingNumber << '@';
Mangler.mangle(VD, "");
}
@@ -3066,7 +3060,7 @@
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01?$TSS" << GuardNum << '@';
+ Mangler.getStream() << "?$TSS" << GuardNum << '@';
Mangler.mangleNestedName(VD);
Mangler.getStream() << "@4HA";
}
@@ -3088,9 +3082,9 @@
bool Visible = VD->isExternallyVisible();
if (Visible) {
- Mangler.getStream() << (VD->getTLSKind() ? "\01??__J" : "\01??_B");
+ Mangler.getStream() << (VD->getTLSKind() ? "??__J" : "??_B");
} else {
- Mangler.getStream() << "\01?$S1@";
+ Mangler.getStream() << "?$S1@";
}
unsigned ScopeDepth = 0;
if (Visible && !getNextDiscriminator(VD, ScopeDepth))
@@ -3110,7 +3104,7 @@
raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
- Mangler.getStream() << "\01??__" << CharCode;
+ Mangler.getStream() << "??__" << CharCode;
Mangler.mangleName(D);
if (D->isStaticDataMember()) {
Mangler.mangleVariableEncoding(D);
@@ -3156,7 +3150,7 @@
// <literal> ::= '??_C@_' <char-type> <literal-length> <encoded-crc>
// <encoded-string> '@'
MicrosoftCXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "\01??_C@_";
+ Mangler.getStream() << "??_C@_";
// <char-type>: The "kind" of string literal is encoded into the mangled name.
if (SL->isWide())
diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp
index 528e32a..57745f2 100644
--- a/lib/AST/ODRHash.cpp
+++ b/lib/AST/ODRHash.cpp
@@ -642,6 +642,24 @@
VisitFunctionType(T);
}
+ void VisitPointerType(const PointerType *T) {
+ AddQualType(T->getPointeeType());
+ VisitType(T);
+ }
+
+ void VisitReferenceType(const ReferenceType *T) {
+ AddQualType(T->getPointeeTypeAsWritten());
+ VisitType(T);
+ }
+
+ void VisitLValueReferenceType(const LValueReferenceType *T) {
+ VisitReferenceType(T);
+ }
+
+ void VisitRValueReferenceType(const RValueReferenceType *T) {
+ VisitReferenceType(T);
+ }
+
void VisitTypedefType(const TypedefType *T) {
AddDecl(T->getDecl());
QualType UnderlyingType = T->getDecl()->getUnderlyingType();
diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp
index d8882c9..bc57b20 100644
--- a/lib/AST/ParentMap.cpp
+++ b/lib/AST/ParentMap.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtObjC.h"
#include "llvm/ADT/DenseMap.h"
using namespace clang;
@@ -193,6 +194,8 @@
return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
case Stmt::SwitchStmtClass:
return DirectChild == cast<SwitchStmt>(P)->getCond();
+ case Stmt::ObjCForCollectionStmtClass:
+ return DirectChild == cast<ObjCForCollectionStmt>(P)->getCollection();
case Stmt::ReturnStmtClass:
return true;
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index da7fdb0..c2733f2 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -29,6 +29,7 @@
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
@@ -228,7 +229,7 @@
/// This method should never be used when type qualifiers are meaningful.
const Type *Type::getArrayElementTypeNoTypeQual() const {
// If this is directly an array type, return it.
- if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
+ if (const auto *ATy = dyn_cast<ArrayType>(this))
return ATy->getElementType().getTypePtr();
// If the canonical form of this type isn't the right kind, reject it.
@@ -264,7 +265,7 @@
#define ABSTRACT_TYPE(Class, Parent)
#define TYPE(Class, Parent) \
case Type::Class: { \
- const Class##Type *ty = cast<Class##Type>(this); \
+ const auto *ty = cast<Class##Type>(this); \
if (!ty->isSugared()) return QualType(ty, 0); \
return ty->desugar(); \
}
@@ -283,7 +284,7 @@
#define ABSTRACT_TYPE(Class, Parent)
#define TYPE(Class, Parent) \
case Type::Class: { \
- const Class##Type *Ty = cast<Class##Type>(CurTy); \
+ const auto *Ty = cast<Class##Type>(CurTy); \
if (!Ty->isSugared()) \
return SplitQualType(Ty, Qs); \
Cur = Ty->desugar(); \
@@ -312,7 +313,7 @@
#define ABSTRACT_TYPE(Class, Parent)
#define TYPE(Class, Parent) \
case Type::Class: { \
- const Class##Type *ty = cast<Class##Type>(split.Ty); \
+ const auto *ty = cast<Class##Type>(split.Ty); \
if (!ty->isSugared()) goto done; \
next = ty->desugar(); \
break; \
@@ -335,7 +336,7 @@
QualType QualType::IgnoreParens(QualType T) {
// FIXME: this seems inherently un-qualifiers-safe.
- while (const ParenType *PT = T->getAs<ParenType>())
+ while (const auto *PT = T->getAs<ParenType>())
T = PT->getInnerType();
return T;
}
@@ -345,13 +346,13 @@
/// reaches a T or a non-sugared type.
template<typename T> static const T *getAsSugar(const Type *Cur) {
while (true) {
- if (const T *Sugar = dyn_cast<T>(Cur))
+ if (const auto *Sugar = dyn_cast<T>(Cur))
return Sugar;
switch (Cur->getTypeClass()) {
#define ABSTRACT_TYPE(Class, Parent)
#define TYPE(Class, Parent) \
case Type::Class: { \
- const Class##Type *Ty = cast<Class##Type>(Cur); \
+ const auto *Ty = cast<Class##Type>(Cur); \
if (!Ty->isSugared()) return 0; \
Cur = Ty->desugar().getTypePtr(); \
break; \
@@ -384,7 +385,7 @@
#define ABSTRACT_TYPE(Class, Parent)
#define TYPE(Class, Parent) \
case Class: { \
- const Class##Type *Ty = cast<Class##Type>(Cur); \
+ const auto *Ty = cast<Class##Type>(Cur); \
if (!Ty->isSugared()) return Cur; \
Cur = Ty->desugar().getTypePtr(); \
break; \
@@ -395,28 +396,31 @@
}
bool Type::isClassType() const {
- if (const RecordType *RT = getAs<RecordType>())
+ if (const auto *RT = getAs<RecordType>())
return RT->getDecl()->isClass();
return false;
}
bool Type::isStructureType() const {
- if (const RecordType *RT = getAs<RecordType>())
+ if (const auto *RT = getAs<RecordType>())
return RT->getDecl()->isStruct();
return false;
}
+
bool Type::isObjCBoxableRecordType() const {
- if (const RecordType *RT = getAs<RecordType>())
+ if (const auto *RT = getAs<RecordType>())
return RT->getDecl()->hasAttr<ObjCBoxableAttr>();
return false;
}
+
bool Type::isInterfaceType() const {
- if (const RecordType *RT = getAs<RecordType>())
+ if (const auto *RT = getAs<RecordType>())
return RT->getDecl()->isInterface();
return false;
}
+
bool Type::isStructureOrClassType() const {
- if (const RecordType *RT = getAs<RecordType>()) {
+ if (const auto *RT = getAs<RecordType>()) {
RecordDecl *RD = RT->getDecl();
return RD->isStruct() || RD->isClass() || RD->isInterface();
}
@@ -424,19 +428,19 @@
}
bool Type::isVoidPointerType() const {
- if (const PointerType *PT = getAs<PointerType>())
+ if (const auto *PT = getAs<PointerType>())
return PT->getPointeeType()->isVoidType();
return false;
}
bool Type::isUnionType() const {
- if (const RecordType *RT = getAs<RecordType>())
+ if (const auto *RT = getAs<RecordType>())
return RT->getDecl()->isUnion();
return false;
}
bool Type::isComplexType() const {
- if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
+ if (const auto *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->getElementType()->isFloatingType();
return false;
}
@@ -447,37 +451,37 @@
}
const ComplexType *Type::getAsComplexIntegerType() const {
- if (const ComplexType *Complex = getAs<ComplexType>())
+ if (const auto *Complex = getAs<ComplexType>())
if (Complex->getElementType()->isIntegerType())
return Complex;
return nullptr;
}
QualType Type::getPointeeType() const {
- if (const PointerType *PT = getAs<PointerType>())
+ if (const auto *PT = getAs<PointerType>())
return PT->getPointeeType();
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ if (const auto *OPT = getAs<ObjCObjectPointerType>())
return OPT->getPointeeType();
- if (const BlockPointerType *BPT = getAs<BlockPointerType>())
+ if (const auto *BPT = getAs<BlockPointerType>())
return BPT->getPointeeType();
- if (const ReferenceType *RT = getAs<ReferenceType>())
+ if (const auto *RT = getAs<ReferenceType>())
return RT->getPointeeType();
- if (const MemberPointerType *MPT = getAs<MemberPointerType>())
+ if (const auto *MPT = getAs<MemberPointerType>())
return MPT->getPointeeType();
- if (const DecayedType *DT = getAs<DecayedType>())
+ if (const auto *DT = getAs<DecayedType>())
return DT->getPointeeType();
- return QualType();
+ return {};
}
const RecordType *Type::getAsStructureType() const {
// If this is directly a structure type, return it.
- if (const RecordType *RT = dyn_cast<RecordType>(this)) {
+ if (const auto *RT = dyn_cast<RecordType>(this)) {
if (RT->getDecl()->isStruct())
return RT;
}
// If the canonical form of this type isn't the right kind, reject it.
- if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
+ if (const auto *RT = dyn_cast<RecordType>(CanonicalType)) {
if (!RT->getDecl()->isStruct())
return nullptr;
@@ -490,13 +494,13 @@
const RecordType *Type::getAsUnionType() const {
// If this is directly a union type, return it.
- if (const RecordType *RT = dyn_cast<RecordType>(this)) {
+ if (const auto *RT = dyn_cast<RecordType>(this)) {
if (RT->getDecl()->isUnion())
return RT;
}
// If the canonical form of this type isn't the right kind, reject it.
- if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
+ if (const auto *RT = dyn_cast<RecordType>(CanonicalType)) {
if (!RT->getDecl()->isUnion())
return nullptr;
@@ -512,7 +516,7 @@
const ObjCObjectType *&bound) const {
bound = nullptr;
- const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>();
+ const auto *OPT = getAs<ObjCObjectPointerType>();
if (!OPT)
return false;
@@ -535,7 +539,7 @@
}
bool Type::isObjCClassOrClassKindOfType() const {
- const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>();
+ const auto *OPT = getAs<ObjCObjectPointerType>();
if (!OPT)
return false;
@@ -560,7 +564,7 @@
bool Type::isObjCInertUnsafeUnretainedType() const {
const Type *cur = this;
while (true) {
- if (auto attributed = dyn_cast<AttributedType>(cur)) {
+ if (const auto attributed = dyn_cast<AttributedType>(cur)) {
if (attributed->getAttrKind() ==
AttributedType::attr_objc_inert_unsafe_unretained)
return true;
@@ -622,7 +626,7 @@
return true;
// Otherwise, check whether the base type is specialized.
- if (auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
+ if (const auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
// Terminate when we reach an interface type.
if (isa<ObjCInterfaceType>(objcObject))
return false;
@@ -640,7 +644,7 @@
return getTypeArgsAsWritten();
// Look at the base type, which might have type arguments.
- if (auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
+ if (const auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
// Terminate when we reach an interface type.
if (isa<ObjCInterfaceType>(objcObject))
return {};
@@ -657,7 +661,7 @@
return true;
// Look at the base type, which might have type arguments.
- if (auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
+ if (const auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
// Terminate when we reach an interface type.
if (isa<ObjCInterfaceType>(objcObject))
return false;
@@ -677,10 +681,8 @@
// Recursively strip __kindof.
SplitQualType splitBaseType = getBaseType().split();
QualType baseType(splitBaseType.Ty, 0);
- if (const ObjCObjectType *baseObj
- = splitBaseType.Ty->getAs<ObjCObjectType>()) {
+ if (const auto *baseObj = splitBaseType.Ty->getAs<ObjCObjectType>())
baseType = baseObj->stripObjCKindOfTypeAndQuals(ctx);
- }
return ctx.getObjCObjectType(ctx.getQualifiedType(baseType,
splitBaseType.Quals),
@@ -733,7 +735,7 @@
QualType VisitComplexType(const ComplexType *T) {
QualType elementType = recurse(T->getElementType());
if (elementType.isNull())
- return QualType();
+ return {};
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
@@ -744,7 +746,7 @@
QualType VisitPointerType(const PointerType *T) {
QualType pointeeType = recurse(T->getPointeeType());
if (pointeeType.isNull())
- return QualType();
+ return {};
if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr())
return QualType(T, 0);
@@ -755,7 +757,7 @@
QualType VisitBlockPointerType(const BlockPointerType *T) {
QualType pointeeType = recurse(T->getPointeeType());
if (pointeeType.isNull())
- return QualType();
+ return {};
if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr())
return QualType(T, 0);
@@ -766,7 +768,7 @@
QualType VisitLValueReferenceType(const LValueReferenceType *T) {
QualType pointeeType = recurse(T->getPointeeTypeAsWritten());
if (pointeeType.isNull())
- return QualType();
+ return {};
if (pointeeType.getAsOpaquePtr()
== T->getPointeeTypeAsWritten().getAsOpaquePtr())
@@ -778,7 +780,7 @@
QualType VisitRValueReferenceType(const RValueReferenceType *T) {
QualType pointeeType = recurse(T->getPointeeTypeAsWritten());
if (pointeeType.isNull())
- return QualType();
+ return {};
if (pointeeType.getAsOpaquePtr()
== T->getPointeeTypeAsWritten().getAsOpaquePtr())
@@ -790,7 +792,7 @@
QualType VisitMemberPointerType(const MemberPointerType *T) {
QualType pointeeType = recurse(T->getPointeeType());
if (pointeeType.isNull())
- return QualType();
+ return {};
if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr())
return QualType(T, 0);
@@ -801,7 +803,7 @@
QualType VisitConstantArrayType(const ConstantArrayType *T) {
QualType elementType = recurse(T->getElementType());
if (elementType.isNull())
- return QualType();
+ return {};
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
@@ -814,7 +816,7 @@
QualType VisitVariableArrayType(const VariableArrayType *T) {
QualType elementType = recurse(T->getElementType());
if (elementType.isNull())
- return QualType();
+ return {};
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
@@ -828,7 +830,7 @@
QualType VisitIncompleteArrayType(const IncompleteArrayType *T) {
QualType elementType = recurse(T->getElementType());
if (elementType.isNull())
- return QualType();
+ return {};
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
@@ -840,7 +842,7 @@
QualType VisitVectorType(const VectorType *T) {
QualType elementType = recurse(T->getElementType());
if (elementType.isNull())
- return QualType();
+ return {};
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
@@ -852,7 +854,7 @@
QualType VisitExtVectorType(const ExtVectorType *T) {
QualType elementType = recurse(T->getElementType());
if (elementType.isNull())
- return QualType();
+ return {};
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
@@ -863,7 +865,7 @@
QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
QualType returnType = recurse(T->getReturnType());
if (returnType.isNull())
- return QualType();
+ return {};
if (returnType.getAsOpaquePtr() == T->getReturnType().getAsOpaquePtr())
return QualType(T, 0);
@@ -874,7 +876,7 @@
QualType VisitFunctionProtoType(const FunctionProtoType *T) {
QualType returnType = recurse(T->getReturnType());
if (returnType.isNull())
- return QualType();
+ return {};
// Transform parameter types.
SmallVector<QualType, 4> paramTypes;
@@ -882,7 +884,7 @@
for (auto paramType : T->getParamTypes()) {
QualType newParamType = recurse(paramType);
if (newParamType.isNull())
- return QualType();
+ return {};
if (newParamType.getAsOpaquePtr() != paramType.getAsOpaquePtr())
paramChanged = true;
@@ -898,10 +900,9 @@
for (auto exceptionType : info.ExceptionSpec.Exceptions) {
QualType newExceptionType = recurse(exceptionType);
if (newExceptionType.isNull())
- return QualType();
+ return {};
- if (newExceptionType.getAsOpaquePtr()
- != exceptionType.getAsOpaquePtr())
+ if (newExceptionType.getAsOpaquePtr() != exceptionType.getAsOpaquePtr())
exceptionChanged = true;
exceptionTypes.push_back(newExceptionType);
@@ -923,7 +924,7 @@
QualType VisitParenType(const ParenType *T) {
QualType innerType = recurse(T->getInnerType());
if (innerType.isNull())
- return QualType();
+ return {};
if (innerType.getAsOpaquePtr() == T->getInnerType().getAsOpaquePtr())
return QualType(T, 0);
@@ -937,11 +938,11 @@
QualType VisitAdjustedType(const AdjustedType *T) {
QualType originalType = recurse(T->getOriginalType());
if (originalType.isNull())
- return QualType();
+ return {};
QualType adjustedType = recurse(T->getAdjustedType());
if (adjustedType.isNull())
- return QualType();
+ return {};
if (originalType.getAsOpaquePtr()
== T->getOriginalType().getAsOpaquePtr() &&
@@ -954,7 +955,7 @@
QualType VisitDecayedType(const DecayedType *T) {
QualType originalType = recurse(T->getOriginalType());
if (originalType.isNull())
- return QualType();
+ return {};
if (originalType.getAsOpaquePtr()
== T->getOriginalType().getAsOpaquePtr())
@@ -976,11 +977,11 @@
QualType VisitAttributedType(const AttributedType *T) {
QualType modifiedType = recurse(T->getModifiedType());
if (modifiedType.isNull())
- return QualType();
+ return {};
QualType equivalentType = recurse(T->getEquivalentType());
if (equivalentType.isNull())
- return QualType();
+ return {};
if (modifiedType.getAsOpaquePtr()
== T->getModifiedType().getAsOpaquePtr() &&
@@ -995,7 +996,7 @@
QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
QualType replacementType = recurse(T->getReplacementType());
if (replacementType.isNull())
- return QualType();
+ return {};
if (replacementType.getAsOpaquePtr()
== T->getReplacementType().getAsOpaquePtr())
@@ -1014,7 +1015,7 @@
QualType deducedType = recurse(T->getDeducedType());
if (deducedType.isNull())
- return QualType();
+ return {};
if (deducedType.getAsOpaquePtr()
== T->getDeducedType().getAsOpaquePtr())
@@ -1030,7 +1031,7 @@
QualType VisitObjCObjectType(const ObjCObjectType *T) {
QualType baseType = recurse(T->getBaseType());
if (baseType.isNull())
- return QualType();
+ return {};
// Transform type arguments.
bool typeArgChanged = false;
@@ -1038,7 +1039,7 @@
for (auto typeArg : T->getTypeArgsAsWritten()) {
QualType newTypeArg = recurse(typeArg);
if (newTypeArg.isNull())
- return QualType();
+ return {};
if (newTypeArg.getAsOpaquePtr() != typeArg.getAsOpaquePtr())
typeArgChanged = true;
@@ -1061,7 +1062,7 @@
QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
QualType pointeeType = recurse(T->getPointeeType());
if (pointeeType.isNull())
- return QualType();
+ return {};
if (pointeeType.getAsOpaquePtr()
== T->getPointeeType().getAsOpaquePtr())
@@ -1073,7 +1074,7 @@
QualType VisitAtomicType(const AtomicType *T) {
QualType valueType = recurse(T->getValueType());
if (valueType.isNull())
- return QualType();
+ return {};
if (valueType.getAsOpaquePtr()
== T->getValueType().getAsOpaquePtr())
@@ -1184,7 +1185,7 @@
typeArgs,
ObjCSubstitutionContext::Result);
if (returnType.isNull())
- return QualType();
+ return {};
// Handle non-prototyped functions, which only substitute into the result
// type.
@@ -1209,7 +1210,7 @@
typeArgs,
ObjCSubstitutionContext::Parameter);
if (newParamType.isNull())
- return QualType();
+ return {};
if (newParamType.getAsOpaquePtr() != paramType.getAsOpaquePtr())
paramChanged = true;
@@ -1228,7 +1229,7 @@
typeArgs,
ObjCSubstitutionContext::Ordinary);
if (newExceptionType.isNull())
- return QualType();
+ return {};
if (newExceptionType.getAsOpaquePtr()
!= exceptionType.getAsOpaquePtr())
@@ -1262,7 +1263,7 @@
ctx, typeArgs,
ObjCSubstitutionContext::Ordinary);
if (newTypeArg.isNull())
- return QualType();
+ return {};
if (newTypeArg.getAsOpaquePtr() != typeArg.getAsOpaquePtr()) {
// If we're substituting based on an unspecialized context type,
@@ -1335,7 +1336,7 @@
}
QualType QualType::getAtomicUnqualifiedType() const {
- if (auto AT = getTypePtr()->getAs<AtomicType>())
+ if (const auto AT = getTypePtr()->getAs<AtomicType>())
return AT->getValueType().getUnqualifiedType();
return getUnqualifiedType();
}
@@ -1343,12 +1344,12 @@
Optional<ArrayRef<QualType>> Type::getObjCSubstitutions(
const DeclContext *dc) const {
// Look through method scopes.
- if (auto method = dyn_cast<ObjCMethodDecl>(dc))
+ if (const auto method = dyn_cast<ObjCMethodDecl>(dc))
dc = method->getDeclContext();
// Find the class or category in which the type we're substituting
// was declared.
- const ObjCInterfaceDecl *dcClassDecl = dyn_cast<ObjCInterfaceDecl>(dc);
+ const auto *dcClassDecl = dyn_cast<ObjCInterfaceDecl>(dc);
const ObjCCategoryDecl *dcCategoryDecl = nullptr;
ObjCTypeParamList *dcTypeParams = nullptr;
if (dcClassDecl) {
@@ -1525,7 +1526,7 @@
// There is no sugar for ObjCObjectType's, just return the canonical
// type pointer if it is the right class. There is no typedef information to
// return and these cannot be Address-space qualified.
- if (const ObjCObjectType *T = getAs<ObjCObjectType>())
+ if (const auto *T = getAs<ObjCObjectType>())
if (T->getNumProtocols() && T->getInterface())
return T;
return nullptr;
@@ -1538,7 +1539,7 @@
const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
// There is no sugar for ObjCQualifiedIdType's, just return the canonical
// type pointer if it is the right class.
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) {
+ if (const auto *OPT = getAs<ObjCObjectPointerType>()) {
if (OPT->isObjCQualifiedIdType())
return OPT;
}
@@ -1548,7 +1549,7 @@
const ObjCObjectPointerType *Type::getAsObjCQualifiedClassType() const {
// There is no sugar for ObjCQualifiedClassType's, just return the canonical
// type pointer if it is the right class.
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) {
+ if (const auto *OPT = getAs<ObjCObjectPointerType>()) {
if (OPT->isObjCQualifiedClassType())
return OPT;
}
@@ -1556,7 +1557,7 @@
}
const ObjCObjectType *Type::getAsObjCInterfaceType() const {
- if (const ObjCObjectType *OT = getAs<ObjCObjectType>()) {
+ if (const auto *OT = getAs<ObjCObjectType>()) {
if (OT->getInterface())
return OT;
}
@@ -1564,7 +1565,7 @@
}
const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const {
- if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) {
+ if (const auto *OPT = getAs<ObjCObjectPointerType>()) {
if (OPT->getInterfaceType())
return OPT;
}
@@ -1573,14 +1574,14 @@
const CXXRecordDecl *Type::getPointeeCXXRecordDecl() const {
QualType PointeeType;
- if (const PointerType *PT = getAs<PointerType>())
+ if (const auto *PT = getAs<PointerType>())
PointeeType = PT->getPointeeType();
- else if (const ReferenceType *RT = getAs<ReferenceType>())
+ else if (const auto *RT = getAs<ReferenceType>())
PointeeType = RT->getPointeeType();
else
return nullptr;
- if (const RecordType *RT = PointeeType->getAs<RecordType>())
+ if (const auto *RT = PointeeType->getAs<RecordType>())
return dyn_cast<CXXRecordDecl>(RT->getDecl());
return nullptr;
@@ -1693,7 +1694,7 @@
}
bool Type::hasIntegerRepresentation() const {
- if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
+ if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isIntegerType();
else
return isIntegerType();
@@ -1719,20 +1720,20 @@
///
/// \returns true if the type is considered an integral type, false otherwise.
bool Type::isIntegralType(const ASTContext &Ctx) const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Int128;
// Complete enum types are integral in C.
if (!Ctx.getLangOpts().CPlusPlus)
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->isComplete();
return false;
}
bool Type::isIntegralOrUnscopedEnumerationType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Int128;
@@ -1740,14 +1741,14 @@
// enumeration type in the sense required here.
// C++0x: However, if the underlying type of the enum is fixed, it is
// considered complete.
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
return false;
}
bool Type::isCharType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Char_U ||
BT->getKind() == BuiltinType::UChar ||
BT->getKind() == BuiltinType::Char_S ||
@@ -1756,20 +1757,20 @@
}
bool Type::isWideCharType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::WChar_S ||
BT->getKind() == BuiltinType::WChar_U;
return false;
}
bool Type::isChar16Type() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Char16;
return false;
}
bool Type::isChar32Type() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Char32;
return false;
}
@@ -1777,7 +1778,7 @@
/// \brief Determine whether this type is any of the built-in character
/// types.
bool Type::isAnyCharacterType() const {
- const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType);
+ const auto *BT = dyn_cast<BuiltinType>(CanonicalType);
if (!BT) return false;
switch (BT->getKind()) {
default: return false;
@@ -1797,7 +1798,7 @@
/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
/// an enum decl which has a signed representation
bool Type::isSignedIntegerType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Char_S &&
BT->getKind() <= BuiltinType::Int128;
}
@@ -1813,12 +1814,12 @@
}
bool Type::isSignedIntegerOrEnumerationType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Char_S &&
BT->getKind() <= BuiltinType::Int128;
}
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) {
if (ET->getDecl()->isComplete())
return ET->getDecl()->getIntegerType()->isSignedIntegerType();
}
@@ -1827,7 +1828,7 @@
}
bool Type::hasSignedIntegerRepresentation() const {
- if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
+ if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isSignedIntegerOrEnumerationType();
else
return isSignedIntegerOrEnumerationType();
@@ -1837,12 +1838,12 @@
/// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], an enum
/// decl which has an unsigned representation
bool Type::isUnsignedIntegerType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::UInt128;
}
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) {
// Incomplete enum types are not treated as integer types.
// FIXME: In C++, enum types are never integer types.
if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped())
@@ -1853,12 +1854,12 @@
}
bool Type::isUnsignedIntegerOrEnumerationType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::UInt128;
}
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) {
if (ET->getDecl()->isComplete())
return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
}
@@ -1867,48 +1868,48 @@
}
bool Type::hasUnsignedIntegerRepresentation() const {
- if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
+ if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isUnsignedIntegerOrEnumerationType();
else
return isUnsignedIntegerOrEnumerationType();
}
bool Type::isFloatingType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Half &&
BT->getKind() <= BuiltinType::Float128;
- if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
+ if (const auto *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->getElementType()->isFloatingType();
return false;
}
bool Type::hasFloatingRepresentation() const {
- if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
+ if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isFloatingType();
else
return isFloatingType();
}
bool Type::isRealFloatingType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->isFloatingPoint();
return false;
}
bool Type::isRealType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Float128;
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
return false;
}
bool Type::isArithmeticType() const {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Float128;
- if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
// GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
// If a body isn't seen by the time we get here, return false.
//
@@ -1923,7 +1924,7 @@
assert(isScalarType());
const Type *T = CanonicalType.getTypePtr();
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) {
+ if (const auto *BT = dyn_cast<BuiltinType>(T)) {
if (BT->getKind() == BuiltinType::Bool) return STK_Bool;
if (BT->getKind() == BuiltinType::NullPtr) return STK_CPointer;
if (BT->isInteger()) return STK_Integral;
@@ -1940,7 +1941,7 @@
} else if (isa<EnumType>(T)) {
assert(cast<EnumType>(T)->getDecl()->isComplete());
return STK_Integral;
- } else if (const ComplexType *CT = dyn_cast<ComplexType>(T)) {
+ } else if (const auto *CT = dyn_cast<ComplexType>(T)) {
if (CT->getElementType()->isRealFloatingType())
return STK_FloatingComplex;
return STK_IntegralComplex;
@@ -1959,8 +1960,8 @@
/// subsumes the notion of C aggregates (C99 6.2.5p21) because it also
/// includes union types.
bool Type::isAggregateType() const {
- if (const RecordType *Record = dyn_cast<RecordType>(CanonicalType)) {
- if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(Record->getDecl()))
+ if (const auto *Record = dyn_cast<RecordType>(CanonicalType)) {
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(Record->getDecl()))
return ClassDecl->isAggregate();
return true;
@@ -2099,8 +2100,8 @@
return true;
case Type::Record:
- if (CXXRecordDecl *ClassDecl
- = dyn_cast<CXXRecordDecl>(cast<RecordType>(CanonicalType)->getDecl()))
+ if (const auto *ClassDecl =
+ dyn_cast<CXXRecordDecl>(cast<RecordType>(CanonicalType)->getDecl()))
return ClassDecl->isPOD();
// C struct/union is POD.
@@ -2138,9 +2139,8 @@
// As an extension, Clang treats vector types as Scalar types.
if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
return true;
- if (const RecordType *RT = CanonicalType->getAs<RecordType>()) {
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (const auto *RT = CanonicalType->getAs<RecordType>()) {
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
// C++11 [class]p6:
// A trivial class is a class that has a default constructor,
// has no non-trivial default constructors, and is trivially
@@ -2182,9 +2182,8 @@
if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
return true;
- if (const RecordType *RT = CanonicalType->getAs<RecordType>()) {
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (const auto *RT = CanonicalType->getAs<RecordType>()) {
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
if (!ClassDecl->isTriviallyCopyable()) return false;
}
@@ -2195,12 +2194,6 @@
return false;
}
-bool QualType::hasTrivialABIOverride() const {
- if (const auto *RD = getTypePtr()->getAsCXXRecordDecl())
- return RD->hasTrivialABIOverride();
- return false;
-}
-
bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const {
return !Context.getLangOpts().ObjCAutoRefCount &&
Context.getLangOpts().ObjCWeak &&
@@ -2214,11 +2207,14 @@
if (RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize())
return PDIK_Struct;
- Qualifiers::ObjCLifetime Lifetime = getQualifiers().getObjCLifetime();
- if (Lifetime == Qualifiers::OCL_Strong)
+ switch (getQualifiers().getObjCLifetime()) {
+ case Qualifiers::OCL_Strong:
return PDIK_ARCStrong;
-
- return PDIK_Trivial;
+ case Qualifiers::OCL_Weak:
+ return PDIK_ARCWeak;
+ default:
+ return PDIK_Trivial;
+ }
}
QualType::PrimitiveCopyKind QualType::isNonTrivialToPrimitiveCopy() const {
@@ -2228,10 +2224,14 @@
return PCK_Struct;
Qualifiers Qs = getQualifiers();
- if (Qs.getObjCLifetime() == Qualifiers::OCL_Strong)
+ switch (Qs.getObjCLifetime()) {
+ case Qualifiers::OCL_Strong:
return PCK_ARCStrong;
-
- return Qs.hasVolatile() ? PCK_VolatileTrivial : PCK_Trivial;
+ case Qualifiers::OCL_Weak:
+ return PCK_ARCWeak;
+ default:
+ return Qs.hasVolatile() ? PCK_VolatileTrivial : PCK_Trivial;
+ }
}
QualType::PrimitiveCopyKind
@@ -2239,6 +2239,17 @@
return isNonTrivialToPrimitiveCopy();
}
+bool QualType::canPassInRegisters() const {
+ if (const auto *RT =
+ getTypePtr()->getBaseElementTypeUnsafe()->getAs<RecordType>())
+ return RT->getDecl()->canPassInRegisters();
+
+ if (getQualifiers().getObjCLifetime() == Qualifiers::OCL_Weak)
+ return false;
+
+ return true;
+}
+
bool Type::isLiteralType(const ASTContext &Ctx) const {
if (isDependentType())
return false;
@@ -2275,7 +2286,7 @@
if (BaseTy->isReferenceType())
return true;
// -- a class type that has all of the following properties:
- if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
+ if (const auto *RT = BaseTy->getAs<RecordType>()) {
// -- a trivial destructor,
// -- every constructor call and full-expression in the
// brace-or-equal-initializers for non-static data members (if any)
@@ -2286,15 +2297,14 @@
// -- all non-static data members and base classes of literal types
//
// We resolve DR1361 by ignoring the second bullet.
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
return ClassDecl->isLiteral();
return true;
}
// We treat _Atomic T as a literal type if T is a literal type.
- if (const AtomicType *AT = BaseTy->getAs<AtomicType>())
+ if (const auto *AT = BaseTy->getAs<AtomicType>())
return AT->getValueType()->isLiteralType(Ctx);
// If this type hasn't been deduced yet, then conservatively assume that
@@ -2323,9 +2333,8 @@
// As an extension, Clang treats vector types as Scalar types.
if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true;
- if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ if (const auto *RT = BaseTy->getAs<RecordType>()) {
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
if (!ClassDecl->isStandardLayout())
return false;
@@ -2363,9 +2372,8 @@
// As an extension, Clang treats vector types as Scalar types.
if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true;
- if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
- if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (const auto *RT = BaseTy->getAs<RecordType>()) {
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
// C++11 [class]p10:
// A POD struct is a non-union class that is both a trivial class [...]
if (!ClassDecl->isTrivial()) return false;
@@ -2393,8 +2401,8 @@
}
bool Type::isAlignValT() const {
- if (auto *ET = getAs<EnumType>()) {
- auto *II = ET->getDecl()->getIdentifier();
+ if (const auto *ET = getAs<EnumType>()) {
+ IdentifierInfo *II = ET->getDecl()->getIdentifier();
if (II && II->isStr("align_val_t") && ET->getDecl()->isInStdNamespace())
return true;
}
@@ -2402,8 +2410,8 @@
}
bool Type::isStdByteType() const {
- if (auto *ET = getAs<EnumType>()) {
- auto *II = ET->getDecl()->getIdentifier();
+ if (const auto *ET = getAs<EnumType>()) {
+ IdentifierInfo *II = ET->getDecl()->getIdentifier();
if (II && II->isStr("byte") && ET->getDecl()->isInStdNamespace())
return true;
}
@@ -2411,7 +2419,7 @@
}
bool Type::isPromotableIntegerType() const {
- if (const BuiltinType *BT = getAs<BuiltinType>())
+ if (const auto *BT = getAs<BuiltinType>())
switch (BT->getKind()) {
case BuiltinType::Bool:
case BuiltinType::Char_S:
@@ -2431,7 +2439,7 @@
// Enumerated types are promotable to their compatible integer types
// (C99 6.3.1.1) a.k.a. its underlying type (C++ [conv.prom]p2).
- if (const EnumType *ET = getAs<EnumType>()){
+ if (const auto *ET = getAs<EnumType>()){
if (this->isDependentType() || ET->getDecl()->getPromotionType().isNull()
|| ET->getDecl()->isScoped())
return false;
@@ -2538,7 +2546,7 @@
StringRef TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
switch (Keyword) {
- case ETK_None: return "";
+ case ETK_None: return {};
case ETK_Typename: return "typename";
case ETK_Class: return "class";
case ETK_Struct: return "struct";
@@ -2586,12 +2594,12 @@
bool Type::isElaboratedTypeSpecifier() const {
ElaboratedTypeKeyword Keyword;
- if (const ElaboratedType *Elab = dyn_cast<ElaboratedType>(this))
+ if (const auto *Elab = dyn_cast<ElaboratedType>(this))
Keyword = Elab->getKeyword();
- else if (const DependentNameType *DepName = dyn_cast<DependentNameType>(this))
+ else if (const auto *DepName = dyn_cast<DependentNameType>(this))
Keyword = DepName->getKeyword();
- else if (const DependentTemplateSpecializationType *DepTST =
- dyn_cast<DependentTemplateSpecializationType>(this))
+ else if (const auto *DepTST =
+ dyn_cast<DependentTemplateSpecializationType>(this))
Keyword = DepTST->getKeyword();
else
return false;
@@ -2706,7 +2714,7 @@
}
QualType QualType::getNonLValueExprType(const ASTContext &Context) const {
- if (const ReferenceType *RefType = getTypePtr()->getAs<ReferenceType>())
+ if (const auto *RefType = getTypePtr()->getAs<ReferenceType>())
return RefType->getPointeeType();
// C++0x [basic.lval]:
@@ -2740,6 +2748,7 @@
case CC_Swift: return "swiftcall";
case CC_PreserveMost: return "preserve_most";
case CC_PreserveAll: return "preserve_all";
+ case CC_CUDAKernel: return "cuda_kernel";
}
llvm_unreachable("Invalid calling convention.");
@@ -2764,7 +2773,7 @@
FunctionTypeBits.RefQualifier = epi.RefQualifier;
// Fill in the trailing argument array.
- QualType *argSlot = reinterpret_cast<QualType*>(this+1);
+ auto *argSlot = reinterpret_cast<QualType *>(this+1);
for (unsigned i = 0; i != NumParams; ++i) {
if (params[i]->isDependentType())
setDependent();
@@ -2795,7 +2804,7 @@
}
} else if (getExceptionSpecType() == EST_ComputedNoexcept) {
// Store the noexcept expression and context.
- Expr **noexSlot = reinterpret_cast<Expr **>(argSlot + NumParams);
+ auto **noexSlot = reinterpret_cast<Expr **>(argSlot + NumParams);
*noexSlot = epi.ExceptionSpec.NoexceptExpr;
if (epi.ExceptionSpec.NoexceptExpr) {
@@ -2809,8 +2818,7 @@
} else if (getExceptionSpecType() == EST_Uninstantiated) {
// Store the function decl from which we will resolve our
// exception specification.
- FunctionDecl **slot =
- reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
+ auto **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
slot[0] = epi.ExceptionSpec.SourceDecl;
slot[1] = epi.ExceptionSpec.SourceTemplate;
// This exception specification doesn't make the type dependent, because
@@ -2818,8 +2826,7 @@
} else if (getExceptionSpecType() == EST_Unevaluated) {
// Store the function decl from which we will resolve our
// exception specification.
- FunctionDecl **slot =
- reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
+ auto **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
slot[0] = epi.ExceptionSpec.SourceDecl;
}
@@ -2837,7 +2844,7 @@
}
if (epi.ExtParameterInfos) {
- ExtParameterInfo *extParamInfos =
+ auto *extParamInfos =
const_cast<ExtParameterInfo *>(getExtParameterInfosBuffer());
for (unsigned i = 0; i != NumParams; ++i)
extParamInfos[i] = epi.ExtParameterInfos[i];
@@ -3080,7 +3087,7 @@
if (FieldTy.isConstQualified())
return true;
FieldTy = FieldTy.getCanonicalType();
- if (const RecordType *FieldRecTy = FieldTy->getAs<RecordType>())
+ if (const auto *FieldRecTy = FieldTy->getAs<RecordType>())
if (FieldRecTy->hasConstFields())
return true;
}
@@ -3129,6 +3136,7 @@
case AttributedType::attr_uptr:
case AttributedType::attr_objc_kindof:
case AttributedType::attr_ns_returns_retained:
+ case AttributedType::attr_nocf_check:
return false;
}
llvm_unreachable("bad attributed type kind");
@@ -3166,6 +3174,7 @@
case attr_nullable:
case attr_null_unspecified:
case attr_objc_kindof:
+ case attr_nocf_check:
return false;
case attr_pcs:
@@ -3261,8 +3270,7 @@
T.getKind() == TemplateName::SubstTemplateTemplateParmPack) &&
"Unexpected template name for TemplateSpecializationType");
- TemplateArgument *TemplateArgs
- = reinterpret_cast<TemplateArgument *>(this + 1);
+ auto *TemplateArgs = reinterpret_cast<TemplateArgument *>(this + 1);
for (const TemplateArgument &Arg : Args) {
// Update instantiation-dependent and variably-modified bits.
// If the canonical type exists and is non-dependent, the template
@@ -3284,7 +3292,7 @@
// Store the aliased type if this is a type alias template specialization.
if (TypeAlias) {
- TemplateArgument *Begin = reinterpret_cast<TemplateArgument *>(this + 1);
+ auto *Begin = reinterpret_cast<TemplateArgument *>(this + 1);
*reinterpret_cast<QualType*>(Begin + getNumArgs()) = AliasedType;
}
}
@@ -3482,7 +3490,7 @@
case Type::RValueReference:
return Cache::get(cast<ReferenceType>(T)->getPointeeType());
case Type::MemberPointer: {
- const MemberPointerType *MPT = cast<MemberPointerType>(T);
+ const auto *MPT = cast<MemberPointerType>(T);
return merge(Cache::get(MPT->getClass()),
Cache::get(MPT->getPointeeType()));
}
@@ -3496,7 +3504,7 @@
case Type::FunctionNoProto:
return Cache::get(cast<FunctionType>(T)->getReturnType());
case Type::FunctionProto: {
- const FunctionProtoType *FPT = cast<FunctionProtoType>(T);
+ const auto *FPT = cast<FunctionProtoType>(T);
CachedProperties result = Cache::get(FPT->getReturnType());
for (const auto &ai : FPT->param_types())
result = merge(result, Cache::get(ai));
@@ -3566,7 +3574,7 @@
case Type::RValueReference:
return computeTypeLinkageInfo(cast<ReferenceType>(T)->getPointeeType());
case Type::MemberPointer: {
- const MemberPointerType *MPT = cast<MemberPointerType>(T);
+ const auto *MPT = cast<MemberPointerType>(T);
LinkageInfo LV = computeTypeLinkageInfo(MPT->getClass());
LV.merge(computeTypeLinkageInfo(MPT->getPointeeType()));
return LV;
@@ -3581,7 +3589,7 @@
case Type::FunctionNoProto:
return computeTypeLinkageInfo(cast<FunctionType>(T)->getReturnType());
case Type::FunctionProto: {
- const FunctionProtoType *FPT = cast<FunctionProtoType>(T);
+ const auto *FPT = cast<FunctionProtoType>(T);
LinkageInfo LV = computeTypeLinkageInfo(FPT->getReturnType());
for (const auto &ai : FPT->param_types())
LV.merge(computeTypeLinkageInfo(ai));
@@ -3776,7 +3784,7 @@
}
bool Type::isBlockCompatibleObjCPointerType(ASTContext &ctx) const {
- const ObjCObjectPointerType *objcPtr = getAs<ObjCObjectPointerType>();
+ const auto *objcPtr = getAs<ObjCObjectPointerType>();
if (!objcPtr)
return false;
@@ -3821,11 +3829,10 @@
const Type *canon = getCanonicalTypeInternal().getTypePtr();
// Walk down to the base type. We don't care about qualifiers for this.
- while (const ArrayType *array = dyn_cast<ArrayType>(canon))
+ while (const auto *array = dyn_cast<ArrayType>(canon))
canon = array->getElementType().getTypePtr();
- if (const ObjCObjectPointerType *opt
- = dyn_cast<ObjCObjectPointerType>(canon)) {
+ if (const auto *opt = dyn_cast<ObjCObjectPointerType>(canon)) {
// Class and Class<Protocol> don't require retention.
if (opt->getObjectType()->isObjCClass())
return true;
@@ -3837,7 +3844,7 @@
bool Type::isObjCNSObjectType() const {
const Type *cur = this;
while (true) {
- if (const TypedefType *typedefType = dyn_cast<TypedefType>(cur))
+ if (const auto *typedefType = dyn_cast<TypedefType>(cur))
return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
// Single-step desugar until we run out of sugar.
@@ -3848,7 +3855,7 @@
}
bool Type::isObjCIndependentClassType() const {
- if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
+ if (const auto *typedefType = dyn_cast<TypedefType>(this))
return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>();
return false;
}
@@ -3862,11 +3869,11 @@
bool Type::isObjCIndirectLifetimeType() const {
if (isObjCLifetimeType())
return true;
- if (const PointerType *OPT = getAs<PointerType>())
+ if (const auto *OPT = getAs<PointerType>())
return OPT->getPointeeType()->isObjCIndirectLifetimeType();
- if (const ReferenceType *Ref = getAs<ReferenceType>())
+ if (const auto *Ref = getAs<ReferenceType>())
return Ref->getPointeeType()->isObjCIndirectLifetimeType();
- if (const MemberPointerType *MemPtr = getAs<MemberPointerType>())
+ if (const auto *MemPtr = getAs<MemberPointerType>())
return MemPtr->getPointeeType()->isObjCIndirectLifetimeType();
return false;
}
@@ -3888,7 +3895,7 @@
/// \brief Determine whether the given type T is a "bridgeable" C type.
bool Type::isCARCBridgableType() const {
- const PointerType *Pointer = getAs<PointerType>();
+ const auto *Pointer = getAs<PointerType>();
if (!Pointer)
return false;
@@ -3899,9 +3906,9 @@
bool Type::hasSizedVLAType() const {
if (!isVariablyModifiedType()) return false;
- if (const PointerType *ptr = getAs<PointerType>())
+ if (const auto *ptr = getAs<PointerType>())
return ptr->getPointeeType()->hasSizedVLAType();
- if (const ReferenceType *ref = getAs<ReferenceType>())
+ if (const auto *ref = getAs<ReferenceType>())
return ref->getPointeeType()->hasSizedVLAType();
if (const ArrayType *arr = getAsArrayTypeUnsafe()) {
if (isa<VariableArrayType>(arr) &&
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index c28ada7..fe67f4e 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -780,6 +780,10 @@
case CC_OpenCLKernel:
// Do nothing. These CCs are not available as attributes.
break;
+ case CC_CUDAKernel:
+ // ToDo: print this before the function.
+ OS << " __global__";
+ break;
case CC_Swift:
OS << " __attribute__((swiftcall))";
break;
@@ -801,6 +805,8 @@
<< Info.getRegParm() << ")))";
if (Info.getNoCallerSavedRegs())
OS << " __attribute__((no_caller_saved_registers))";
+ if (Info.getNoCfCheck())
+ OS << " __attribute__((nocf_check))";
}
void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T,
@@ -1396,7 +1402,7 @@
// FIXME: When Sema learns to form this AttributedType, avoid printing the
// attribute again in printFunctionProtoAfter.
case AttributedType::attr_noreturn: OS << "noreturn"; break;
-
+ case AttributedType::attr_nocf_check: OS << "nocf_check"; break;
case AttributedType::attr_cdecl: OS << "cdecl"; break;
case AttributedType::attr_fastcall: OS << "fastcall"; break;
case AttributedType::attr_stdcall: OS << "stdcall"; break;
diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
index 347c516..5f1ccdf 100644
--- a/lib/AST/VTableBuilder.cpp
+++ b/lib/AST/VTableBuilder.cpp
@@ -2105,8 +2105,8 @@
const CXXMethodDecl *MD = I.second;
ThunkInfoVectorTy ThunksVector = Thunks[MD];
- std::sort(ThunksVector.begin(), ThunksVector.end(),
- [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
+ llvm::sort(ThunksVector.begin(), ThunksVector.end(),
+ [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
assert(LHS.Method == nullptr && RHS.Method == nullptr);
return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
});
@@ -2206,9 +2206,9 @@
else
this->VTableIndices = OwningArrayRef<size_t>(VTableIndices);
- std::sort(this->VTableThunks.begin(), this->VTableThunks.end(),
- [](const VTableLayout::VTableThunkTy &LHS,
- const VTableLayout::VTableThunkTy &RHS) {
+ llvm::sort(this->VTableThunks.begin(), this->VTableThunks.end(),
+ [](const VTableLayout::VTableThunkTy &LHS,
+ const VTableLayout::VTableThunkTy &RHS) {
assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
"Different thunks should have unique indices!");
return LHS.first < RHS.first;
@@ -2367,8 +2367,6 @@
class VFTableBuilder {
public:
- typedef MicrosoftVTableContext::MethodVFTableLocation MethodVFTableLocation;
-
typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
MethodVFTableLocationsTy;
@@ -3344,8 +3342,8 @@
PathsSorted.reserve(Paths.size());
for (auto& P : Paths)
PathsSorted.push_back(*P);
- std::sort(PathsSorted.begin(), PathsSorted.end(),
- [](const VPtrInfo &LHS, const VPtrInfo &RHS) {
+ llvm::sort(PathsSorted.begin(), PathsSorted.end(),
+ [](const VPtrInfo &LHS, const VPtrInfo &RHS) {
return LHS.MangledPath < RHS.MangledPath;
});
bool Changed = false;
@@ -3544,6 +3542,18 @@
}
}
+static bool vfptrIsEarlierInMDC(const ASTRecordLayout &Layout,
+ const MethodVFTableLocation &LHS,
+ const MethodVFTableLocation &RHS) {
+ CharUnits L = LHS.VFPtrOffset;
+ CharUnits R = RHS.VFPtrOffset;
+ if (LHS.VBase)
+ L += Layout.getVBaseClassOffset(LHS.VBase);
+ if (RHS.VBase)
+ R += Layout.getVBaseClassOffset(RHS.VBase);
+ return L < R;
+}
+
void MicrosoftVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
assert(RD->isDynamicClass());
@@ -3574,12 +3584,15 @@
EmptyAddressPointsMap);
Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
for (const auto &Loc : Builder.vtable_locations()) {
- GlobalDecl GD = Loc.first;
- MethodVFTableLocation NewLoc = Loc.second;
- auto M = NewMethodLocations.find(GD);
- if (M == NewMethodLocations.end() || NewLoc < M->second)
- NewMethodLocations[GD] = NewLoc;
+ auto Insert = NewMethodLocations.insert(Loc);
+ if (!Insert.second) {
+ const MethodVFTableLocation &NewLoc = Loc.second;
+ MethodVFTableLocation &OldLoc = Insert.first->second;
+ if (vfptrIsEarlierInMDC(Layout, NewLoc, OldLoc))
+ OldLoc = NewLoc;
+ }
}
}
@@ -3717,7 +3730,7 @@
return *VFTableLayouts[id];
}
-const MicrosoftVTableContext::MethodVFTableLocation &
+const MethodVFTableLocation &
MicrosoftVTableContext::getMethodVFTableLocation(GlobalDecl GD) {
assert(cast<CXXMethodDecl>(GD.getDecl())->isVirtual() &&
"Only use this method for virtual methods or dtors");
diff --git a/lib/ASTMatchers/ASTMatchersInternal.cpp b/lib/ASTMatchers/ASTMatchersInternal.cpp
index 0bcdd8e..06d032e 100644
--- a/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -38,6 +38,16 @@
namespace clang {
namespace ast_matchers {
+
+AST_MATCHER_P(ObjCMessageExpr, hasAnySelectorMatcher, std::vector<std::string>,
+ Matches) {
+ std::string SelString = Node.getSelector().getAsString();
+ for (const std::string &S : Matches)
+ if (S == SelString)
+ return true;
+ return false;
+}
+
namespace internal {
bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode,
@@ -315,12 +325,22 @@
return false;
}
-Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs) {
+inline static
+std::vector<std::string> vectorFromRefs(ArrayRef<const StringRef *> NameRefs) {
std::vector<std::string> Names;
for (auto *Name : NameRefs)
Names.emplace_back(*Name);
- return internal::Matcher<NamedDecl>(
- new internal::HasNameMatcher(std::move(Names)));
+ return Names;
+}
+
+Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs) {
+ std::vector<std::string> Names = vectorFromRefs(NameRefs);
+ return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Names));
+}
+
+Matcher<ObjCMessageExpr> hasAnySelectorFunc(
+ ArrayRef<const StringRef *> NameRefs) {
+ return hasAnySelectorMatcher(vectorFromRefs(NameRefs));
}
HasNameMatcher::HasNameMatcher(std::vector<std::string> N)
@@ -393,7 +413,8 @@
/// Return true if there are still any patterns left.
bool consumeNameSuffix(StringRef NodeName, bool CanSkip) {
for (size_t I = 0; I < Patterns.size();) {
- if (internal::consumeNameSuffix(Patterns[I].P, NodeName) ||
+ if (::clang::ast_matchers::internal::consumeNameSuffix(Patterns[I].P,
+ NodeName) ||
CanSkip) {
++I;
} else {
@@ -739,6 +760,9 @@
const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef,
internal::hasAnyNameFunc>
hasAnyName = {};
+const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>, StringRef,
+ internal::hasAnySelectorFunc>
+ hasAnySelector = {};
const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> has = {};
const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher>
hasDescendant = {};
diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp
index 89e1a26..8b7448c 100644
--- a/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -619,8 +619,8 @@
P.parseExpressionImpl(&Dummy);
// Sort by specificity, then by name.
- std::sort(P.Completions.begin(), P.Completions.end(),
- [](const MatcherCompletion &A, const MatcherCompletion &B) {
+ llvm::sort(P.Completions.begin(), P.Completions.end(),
+ [](const MatcherCompletion &A, const MatcherCompletion &B) {
if (A.Specificity != B.Specificity)
return A.Specificity > B.Specificity;
return A.TypedText < B.TypedText;
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index 79aa4e6..afc5f6a 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -286,6 +286,7 @@
REGISTER_MATCHER(hasReturnValue);
REGISTER_MATCHER(hasRHS);
REGISTER_MATCHER(hasSelector);
+ REGISTER_MATCHER(hasAnySelector);
REGISTER_MATCHER(hasSingleDecl);
REGISTER_MATCHER(hasSize);
REGISTER_MATCHER(hasSizeExpr);
@@ -322,6 +323,7 @@
REGISTER_MATCHER(isAnyPointer);
REGISTER_MATCHER(isArray);
REGISTER_MATCHER(isArrow);
+ REGISTER_MATCHER(isAssignmentOperator);
REGISTER_MATCHER(isBaseInitializer);
REGISTER_MATCHER(isBitField);
REGISTER_MATCHER(isCatchAll);
diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp
index 2b8259b..2bdcac4 100644
--- a/lib/Analysis/AnalysisDeclContext.cpp
+++ b/lib/Analysis/AnalysisDeclContext.cpp
@@ -1,4 +1,4 @@
-//== AnalysisDeclContext.cpp - Analysis context for Path Sens analysis -*- C++ -*-//
+//===- AnalysisDeclContext.cpp - Analysis context for Path Sens analysis --===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,68 +7,71 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines AnalysisDeclContext, a class that manages the analysis context
-// data for path sensitive analysis.
+// This file defines AnalysisDeclContext, a class that manages the analysis
+// context data for path sensitive analysis.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/LambdaCapture.h"
#include "clang/AST/ParentMap.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
-#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
#include "clang/Analysis/BodyFarm.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <memory>
using namespace clang;
-typedef llvm::DenseMap<const void *, ManagedAnalysis *> ManagedAnalysisMap;
+using ManagedAnalysisMap = llvm::DenseMap<const void *, ManagedAnalysis *>;
AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
const Decl *d,
const CFG::BuildOptions &buildOptions)
- : Manager(Mgr),
- D(d),
- cfgBuildOptions(buildOptions),
- forcedBlkExprs(nullptr),
- builtCFG(false),
- builtCompleteCFG(false),
- ReferencedBlockVars(nullptr),
- ManagedAnalyses(nullptr)
-{
+ : Manager(Mgr), D(d), cfgBuildOptions(buildOptions) {
cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
}
AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
const Decl *d)
-: Manager(Mgr),
- D(d),
- forcedBlkExprs(nullptr),
- builtCFG(false),
- builtCompleteCFG(false),
- ReferencedBlockVars(nullptr),
- ManagedAnalyses(nullptr)
-{
+ : Manager(Mgr), D(d) {
cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
}
AnalysisDeclContextManager::AnalysisDeclContextManager(
ASTContext &ASTCtx, bool useUnoptimizedCFG, bool addImplicitDtors,
bool addInitializers, bool addTemporaryDtors, bool addLifetime,
- bool addLoopExit, bool synthesizeBodies, bool addStaticInitBranch,
- bool addCXXNewAllocator, bool addRichCXXConstructors,
- CodeInjector *injector)
+ bool addLoopExit, bool addScopes, bool synthesizeBodies,
+ bool addStaticInitBranch, bool addCXXNewAllocator,
+ bool addRichCXXConstructors, CodeInjector *injector)
: Injector(injector), FunctionBodyFarm(ASTCtx, injector),
SynthesizeBodies(synthesizeBodies) {
cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
@@ -77,6 +80,7 @@
cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
cfgBuildOptions.AddLifetime = addLifetime;
cfgBuildOptions.AddLoopExit = addLoopExit;
+ cfgBuildOptions.AddScopes = addScopes;
cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors;
@@ -86,7 +90,7 @@
Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
IsAutosynthesized = false;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
Stmt *Body = FD->getBody();
if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
Body = CoroBody->getBody();
@@ -99,7 +103,7 @@
}
return Body;
}
- else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
Stmt *Body = MD->getBody();
if (Manager && Manager->synthesizeBodies()) {
Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(MD);
@@ -109,10 +113,9 @@
}
}
return Body;
- } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ } else if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->getBody();
- else if (const FunctionTemplateDecl *FunTmpl
- = dyn_cast_or_null<FunctionTemplateDecl>(D))
+ else if (const auto *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
return FunTmpl->getTemplatedDecl()->getBody();
llvm_unreachable("unknown code decl");
@@ -141,9 +144,9 @@
}
const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->getSelfDecl();
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+ if (const auto *BD = dyn_cast<BlockDecl>(D)) {
// See if 'self' was captured by the block.
for (const auto &I : BD->captures()) {
const VarDecl *VD = I.getVariable();
@@ -160,7 +163,7 @@
if (!parent->isLambda())
return nullptr;
- for (const LambdaCapture &LC : parent->captures()) {
+ for (const auto &LC : parent->captures()) {
if (!LC.capturesVariable())
continue;
@@ -176,7 +179,7 @@
if (!forcedBlkExprs)
forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs();
// Default construct an entry for 'stmt'.
- if (const Expr *e = dyn_cast<Expr>(stmt))
+ if (const auto *e = dyn_cast<Expr>(stmt))
stmt = e->IgnoreParens();
(void) (*forcedBlkExprs)[stmt];
}
@@ -184,7 +187,7 @@
const CFGBlock *
AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) {
assert(forcedBlkExprs);
- if (const Expr *e = dyn_cast<Expr>(stmt))
+ if (const auto *e = dyn_cast<Expr>(stmt))
stmt = e->IgnoreParens();
CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
forcedBlkExprs->find(stmt);
@@ -268,13 +271,13 @@
}
void AnalysisDeclContext::dumpCFG(bool ShowColors) {
- getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
+ getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
}
ParentMap &AnalysisDeclContext::getParentMap() {
if (!PM) {
PM.reset(new ParentMap(getBody()));
- if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
+ if (const auto *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
for (const auto *I : C->inits()) {
PM->addStmt(I->getInit());
}
@@ -294,7 +297,7 @@
}
AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
// that has the body.
FD->hasBody(FD);
@@ -317,7 +320,7 @@
const BlockInvocationContext *
AnalysisDeclContext::getBlockInvocationContext(const LocationContext *parent,
- const clang::BlockDecl *BD,
+ const BlockDecl *BD,
const void *ContextData) {
return getLocationContextManager().getBlockInvocationContext(this, parent,
BD, ContextData);
@@ -325,7 +328,7 @@
bool AnalysisDeclContext::isInStdNamespace(const Decl *D) {
const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext();
- const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
+ const auto *ND = dyn_cast<NamespaceDecl>(DC);
if (!ND)
return false;
@@ -338,7 +341,7 @@
return ND->isStdNamespace();
}
-LocationContextManager & AnalysisDeclContext::getLocationContextManager() {
+LocationContextManager &AnalysisDeclContext::getLocationContextManager() {
assert(Manager &&
"Cannot create LocationContexts without an AnalysisDeclContextManager!");
return Manager->getLocationContextManager();
@@ -401,7 +404,7 @@
llvm::FoldingSetNodeID ID;
StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
void *InsertPos;
- StackFrameContext *L =
+ auto *L =
cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
if (!L) {
L = new StackFrameContext(ctx, parent, s, blk, idx);
@@ -425,7 +428,7 @@
llvm::FoldingSetNodeID ID;
BlockInvocationContext::Profile(ID, ctx, parent, BD, ContextData);
void *InsertPos;
- BlockInvocationContext *L =
+ auto *L =
cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
InsertPos));
if (!L) {
@@ -442,7 +445,7 @@
const StackFrameContext *LocationContext::getCurrentStackFrame() const {
const LocationContext *LC = this;
while (LC) {
- if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC))
+ if (const auto *SFC = dyn_cast<StackFrameContext>(LC))
return SFC;
LC = LC->getParent();
}
@@ -485,12 +488,11 @@
unsigned Frame = 0;
for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
-
switch (LCtx->getKind()) {
case StackFrame:
OS << Indent << '#' << Frame << ' ';
++Frame;
- if (const NamedDecl *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
+ if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
OS << "Calling " << D->getQualifiedNameAsString();
else
OS << "Calling anonymous code";
@@ -525,25 +527,27 @@
//===----------------------------------------------------------------------===//
namespace {
+
class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
- BumpVector<const VarDecl*> &BEVals;
+ BumpVector<const VarDecl *> &BEVals;
BumpVectorContext &BC;
- llvm::SmallPtrSet<const VarDecl*, 4> Visited;
- llvm::SmallPtrSet<const DeclContext*, 4> IgnoredContexts;
+ llvm::SmallPtrSet<const VarDecl *, 4> Visited;
+ llvm::SmallPtrSet<const DeclContext *, 4> IgnoredContexts;
+
public:
FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
BumpVectorContext &bc)
- : BEVals(bevals), BC(bc) {}
+ : BEVals(bevals), BC(bc) {}
void VisitStmt(Stmt *S) {
- for (Stmt *Child : S->children())
+ for (auto *Child : S->children())
if (Child)
Visit(Child);
}
void VisitDeclRefExpr(DeclRefExpr *DR) {
// Non-local variables are also directly modified.
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
if (!VD->hasLocalStorage()) {
if (Visited.insert(VD).second)
BEVals.push_back(VD, BC);
@@ -561,15 +565,16 @@
for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(),
et = PE->semantics_end(); it != et; ++it) {
Expr *Semantic = *it;
- if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
+ if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
Semantic = OVE->getSourceExpr();
Visit(Semantic);
}
}
};
-} // end anonymous namespace
-typedef BumpVector<const VarDecl*> DeclVec;
+} // namespace
+
+using DeclVec = BumpVector<const VarDecl *>;
static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
void *&Vec,
@@ -615,7 +620,7 @@
// Cleanup.
//===----------------------------------------------------------------------===//
-ManagedAnalysis::~ManagedAnalysis() {}
+ManagedAnalysis::~ManagedAnalysis() = default;
AnalysisDeclContext::~AnalysisDeclContext() {
delete forcedBlkExprs;
@@ -628,7 +633,7 @@
}
}
-LocationContext::~LocationContext() {}
+LocationContext::~LocationContext() = default;
LocationContextManager::~LocationContextManager() {
clear();
@@ -641,7 +646,5 @@
++I;
delete LC;
}
-
Contexts.clear();
}
-
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index ae18278..34d4016 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -234,6 +234,13 @@
assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
return &Scope->Vars[VarIter - 1];
}
+
+ const VarDecl *getFirstVarInScope() const {
+ assert(Scope && "Dereferencing invalid iterator is not allowed");
+ assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
+ return Scope->Vars[0];
+ }
+
VarDecl *operator*() const {
return *this->operator->();
}
@@ -267,6 +274,7 @@
int distance(const_iterator L);
const_iterator shared_parent(const_iterator L);
+ bool pointsToFirstDeclaredVar() { return VarIter == 1; }
};
private:
@@ -475,10 +483,13 @@
// Information about the currently visited C++ object construction site.
// This is set in the construction trigger and read when the constructor
- // itself is being visited.
- llvm::DenseMap<CXXConstructExpr *, const ConstructionContextLayer *>
+ // or a function that returns an object by value is being visited.
+ llvm::DenseMap<Expr *, const ConstructionContextLayer *>
ConstructionContextMap;
+ using DeclsWithEndedScopeSetTy = llvm::SmallSetVector<VarDecl *, 16>;
+ DeclsWithEndedScopeSetTy DeclsWithEndedScope;
+
bool badCFG = false;
const CFG::BuildOptions &BuildOpts;
@@ -576,6 +587,12 @@
CFGBlock *VisitChildren(Stmt *S);
CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc);
+ void maybeAddScopeBeginForVarDecl(CFGBlock *B, const VarDecl *VD,
+ const Stmt *S) {
+ if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
+ appendScopeBegin(B, VD, S);
+ }
+
/// When creating the CFG for temporary destructors, we want to mirror the
/// branch structure of the corresponding constructor calls.
/// Thus, while visiting a statement for temporary destructors, we keep a
@@ -656,7 +673,7 @@
// Remember to apply the construction context based on the current \p Layer
// when constructing the CFG element for \p CE.
void consumeConstructionContext(const ConstructionContextLayer *Layer,
- CXXConstructExpr *CE);
+ Expr *E);
// Scan \p Child statement to find constructors in it, while keeping in mind
// that its parent statement is providing a partial construction context
@@ -667,9 +684,9 @@
Stmt *Child);
// Unset the construction context after consuming it. This is done immediately
- // after adding the CFGConstructor element, so there's no need to
- // do this manually in every Visit... function.
- void cleanupConstructionContext(CXXConstructExpr *CE);
+ // after adding the CFGConstructor or CFGCXXRecordTypedCall element, so
+ // there's no need to do this manually in every Visit... function.
+ void cleanupConstructionContext(Expr *E);
void autoCreateBlock() { if (!Block) Block = createBlock(); }
CFGBlock *createBlock(bool add_successor = true);
@@ -688,6 +705,11 @@
void addAutomaticObjHandling(LocalScope::const_iterator B,
LocalScope::const_iterator E, Stmt *S);
void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD);
+ void addScopesEnd(LocalScope::const_iterator B, LocalScope::const_iterator E,
+ Stmt *S);
+
+ void getDeclsWithEndedScope(LocalScope::const_iterator B,
+ LocalScope::const_iterator E, Stmt *S);
// Local scopes creation.
LocalScope* createOrReuseLocalScope(LocalScope* Scope);
@@ -714,12 +736,34 @@
if (BuildOpts.AddRichCXXConstructors) {
if (const ConstructionContextLayer *Layer =
ConstructionContextMap.lookup(CE)) {
- const ConstructionContext *CC =
- ConstructionContext::createFromLayers(cfg->getBumpVectorContext(),
- Layer);
- B->appendConstructor(CE, CC, cfg->getBumpVectorContext());
cleanupConstructionContext(CE);
- return;
+ if (const auto *CC = ConstructionContext::createFromLayers(
+ cfg->getBumpVectorContext(), Layer)) {
+ B->appendConstructor(CE, CC, cfg->getBumpVectorContext());
+ return;
+ }
+ }
+ }
+
+ // No valid construction context found. Fall back to statement.
+ B->appendStmt(CE, cfg->getBumpVectorContext());
+ }
+
+ void appendCall(CFGBlock *B, CallExpr *CE) {
+ if (alwaysAdd(CE) && cachedEntry)
+ cachedEntry->second = B;
+
+ if (BuildOpts.AddRichCXXConstructors) {
+ if (CFGCXXRecordTypedCall::isCXXRecordTypedCall(CE, *Context)) {
+ if (const ConstructionContextLayer *Layer =
+ ConstructionContextMap.lookup(CE)) {
+ cleanupConstructionContext(CE);
+ if (const auto *CC = ConstructionContext::createFromLayers(
+ cfg->getBumpVectorContext(), Layer)) {
+ B->appendCXXRecordTypedCall(CE, CC, cfg->getBumpVectorContext());
+ return;
+ }
+ }
}
}
@@ -770,6 +814,11 @@
LocalScope::const_iterator B,
LocalScope::const_iterator E);
+ const VarDecl *
+ prependAutomaticObjScopeEndWithTerminator(CFGBlock *Blk,
+ LocalScope::const_iterator B,
+ LocalScope::const_iterator E);
+
void addSuccessor(CFGBlock *B, CFGBlock *S, bool IsReachable = true) {
B->addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable),
cfg->getBumpVectorContext());
@@ -782,6 +831,26 @@
cfg->getBumpVectorContext());
}
+ void appendScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
+ if (BuildOpts.AddScopes)
+ B->appendScopeBegin(VD, S, cfg->getBumpVectorContext());
+ }
+
+ void prependScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
+ if (BuildOpts.AddScopes)
+ B->prependScopeBegin(VD, S, cfg->getBumpVectorContext());
+ }
+
+ void appendScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
+ if (BuildOpts.AddScopes)
+ B->appendScopeEnd(VD, S, cfg->getBumpVectorContext());
+ }
+
+ void prependScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
+ if (BuildOpts.AddScopes)
+ B->prependScopeEnd(VD, S, cfg->getBumpVectorContext());
+ }
+
/// \brief Find a relational comparison with an expression evaluating to a
/// boolean and a constant other than 0 and 1.
/// e.g. if ((x < y) == 10)
@@ -1162,16 +1231,16 @@
}
void CFGBuilder::consumeConstructionContext(
- const ConstructionContextLayer *Layer, CXXConstructExpr *CE) {
+ const ConstructionContextLayer *Layer, Expr *E) {
if (const ConstructionContextLayer *PreviouslyStoredLayer =
- ConstructionContextMap.lookup(CE)) {
+ ConstructionContextMap.lookup(E)) {
(void)PreviouslyStoredLayer;
// We might have visited this child when we were finding construction
// contexts within its parents.
assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
"Already within a different construction context!");
} else {
- ConstructionContextMap[CE] = Layer;
+ ConstructionContextMap[E] = Layer;
}
}
@@ -1189,6 +1258,18 @@
consumeConstructionContext(Layer, cast<CXXConstructExpr>(Child));
break;
}
+ // FIXME: This, like the main visit, doesn't support CUDAKernelCallExpr.
+ // FIXME: An isa<> would look much better but this whole switch is a
+ // workaround for an internal compiler error in MSVC 2015 (see r326021).
+ case Stmt::CallExprClass:
+ case Stmt::CXXMemberCallExprClass:
+ case Stmt::CXXOperatorCallExprClass:
+ case Stmt::UserDefinedLiteralClass: {
+ auto *CE = cast<CallExpr>(Child);
+ if (CFGCXXRecordTypedCall::isCXXRecordTypedCall(CE, *Context))
+ consumeConstructionContext(Layer, CE);
+ break;
+ }
case Stmt::ExprWithCleanupsClass: {
auto *Cleanups = cast<ExprWithCleanups>(Child);
findConstructionContexts(Layer, Cleanups->getSubExpr());
@@ -1201,9 +1282,14 @@
}
case Stmt::ImplicitCastExprClass: {
auto *Cast = cast<ImplicitCastExpr>(Child);
- // TODO: We need to support CK_ConstructorConversion, maybe other kinds?
- if (Cast->getCastKind() == CK_NoOp)
+ // Should we support other implicit cast kinds?
+ switch (Cast->getCastKind()) {
+ case CK_NoOp:
+ case CK_ConstructorConversion:
findConstructionContexts(Layer, Cast->getSubExpr());
+ default:
+ break;
+ }
break;
}
case Stmt::CXXBindTemporaryExprClass: {
@@ -1216,6 +1302,15 @@
}
case Stmt::ConditionalOperatorClass: {
auto *CO = cast<ConditionalOperator>(Child);
+ if (!dyn_cast_or_null<MaterializeTemporaryExpr>(Layer->getTriggerStmt())) {
+ // If the object returned by the conditional operator is not going to be a
+ // temporary object that needs to be immediately materialized, then
+ // it must be C++17 with its mandatory copy elision. Do not yet promise
+ // to support this case.
+ assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
+ Context->getLangOpts().CPlusPlus17);
+ break;
+ }
findConstructionContexts(Layer, CO->getLHS());
findConstructionContexts(Layer, CO->getRHS());
break;
@@ -1225,12 +1320,12 @@
}
}
-void CFGBuilder::cleanupConstructionContext(CXXConstructExpr *CE) {
+void CFGBuilder::cleanupConstructionContext(Expr *E) {
assert(BuildOpts.AddRichCXXConstructors &&
"We should not be managing construction contexts!");
- assert(ConstructionContextMap.count(CE) &&
+ assert(ConstructionContextMap.count(E) &&
"Cannot exit construction context without the context!");
- ConstructionContextMap.erase(CE);
+ ConstructionContextMap.erase(E);
}
@@ -1294,6 +1389,9 @@
JT.scopePosition);
prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
JT.scopePosition);
+ const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator(
+ B, I->scopePosition, JT.scopePosition);
+ appendScopeBegin(JT.block, VD, G);
addSuccessor(B, JT.block);
}
@@ -1451,9 +1549,34 @@
appendLoopExit(Block, LoopStmt);
}
+void CFGBuilder::getDeclsWithEndedScope(LocalScope::const_iterator B,
+ LocalScope::const_iterator E, Stmt *S) {
+ if (!BuildOpts.AddScopes)
+ return;
+
+ if (B == E)
+ return;
+
+ // To go from B to E, one first goes up the scopes from B to P
+ // then sideways in one scope from P to P' and then down
+ // the scopes from P' to E.
+ // The lifetime of all objects between B and P end.
+ LocalScope::const_iterator P = B.shared_parent(E);
+ int Dist = B.distance(P);
+ if (Dist <= 0)
+ return;
+
+ for (LocalScope::const_iterator I = B; I != P; ++I)
+ if (I.pointsToFirstDeclaredVar())
+ DeclsWithEndedScope.insert(*I);
+}
+
void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
LocalScope::const_iterator E,
Stmt *S) {
+ getDeclsWithEndedScope(B, E, S);
+ if (BuildOpts.AddScopes)
+ addScopesEnd(B, E, S);
if (BuildOpts.AddImplicitDtors)
addAutomaticObjDtors(B, E, S);
if (BuildOpts.AddLifetime)
@@ -1505,6 +1628,23 @@
appendLifetimeEnds(Block, *I, S);
}
+/// Add to current block markers for ending scopes.
+void CFGBuilder::addScopesEnd(LocalScope::const_iterator B,
+ LocalScope::const_iterator E, Stmt *S) {
+ // If implicit destructors are enabled, we'll add scope ends in
+ // addAutomaticObjDtors.
+ if (BuildOpts.AddImplicitDtors)
+ return;
+
+ autoCreateBlock();
+
+ for (auto I = DeclsWithEndedScope.rbegin(), E = DeclsWithEndedScope.rend();
+ I != E; ++I)
+ appendScopeEnd(Block, *I, S);
+
+ return;
+}
+
/// addAutomaticObjDtors - Add to current block automatic objects destructors
/// for objects in range of local scope positions. Use S as trigger statement
/// for destructors.
@@ -1528,6 +1668,15 @@
for (SmallVectorImpl<VarDecl*>::reverse_iterator I = Decls.rbegin(),
E = Decls.rend();
I != E; ++I) {
+ if (hasTrivialDestructor(*I)) {
+ // If AddScopes is enabled and *I is a first variable in a scope, add a
+ // ScopeEnd marker in a Block.
+ if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I)) {
+ autoCreateBlock();
+ appendScopeEnd(Block, *I, S);
+ }
+ continue;
+ }
// If this destructor is marked as a no-return destructor, we need to
// create a new block for the destructor which does not have as a successor
// anything built thus far: control won't flow out of this block.
@@ -1542,6 +1691,9 @@
else
autoCreateBlock();
+ // Add ScopeEnd just after automatic obj destructor.
+ if (BuildOpts.AddScopes && DeclsWithEndedScope.count(*I))
+ appendScopeEnd(Block, *I, S);
appendAutomaticObjDtor(Block, *I, S);
}
}
@@ -1604,7 +1756,8 @@
/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement
/// that should create implicit scope (e.g. if/else substatements).
void CFGBuilder::addLocalScopeForStmt(Stmt *S) {
- if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
+ if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
+ !BuildOpts.AddScopes)
return;
LocalScope *Scope = nullptr;
@@ -1629,7 +1782,8 @@
/// reuse Scope if not NULL.
LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,
LocalScope* Scope) {
- if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
+ if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
+ !BuildOpts.AddScopes)
return Scope;
for (auto *DI : DS->decls())
@@ -1681,7 +1835,8 @@
LocalScope* Scope) {
assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
"AddImplicitDtors and AddLifetime cannot be used at the same time");
- if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
+ if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
+ !BuildOpts.AddScopes)
return Scope;
// Check if variable is local.
@@ -1694,7 +1849,7 @@
}
if (BuildOpts.AddImplicitDtors) {
- if (!hasTrivialDestructor(VD)) {
+ if (!hasTrivialDestructor(VD) || BuildOpts.AddScopes) {
// Add the variable to scope
Scope = createOrReuseLocalScope(Scope);
Scope->addVar(VD);
@@ -1754,6 +1909,26 @@
InsertPos = Blk->insertLifetimeEnds(InsertPos, *I, Blk->getTerminator());
}
+/// prependAutomaticObjScopeEndWithTerminator - Prepend scope end CFGElements for
+/// variables with automatic storage duration to CFGBlock's elements vector.
+/// Elements will be prepended to physical beginning of the vector which
+/// happens to be logical end. Use blocks terminator as statement that specifies
+/// where scope ends.
+const VarDecl *
+CFGBuilder::prependAutomaticObjScopeEndWithTerminator(
+ CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
+ if (!BuildOpts.AddScopes)
+ return nullptr;
+ BumpVectorContext &C = cfg->getBumpVectorContext();
+ CFGBlock::iterator InsertPos =
+ Blk->beginScopeEndInsert(Blk->end(), 1, C);
+ LocalScope::const_iterator PlaceToInsert = B;
+ for (LocalScope::const_iterator I = B; I != E; ++I)
+ PlaceToInsert = I;
+ Blk->insertScopeEnd(InsertPos, *PlaceToInsert, Blk->getTerminator());
+ return *PlaceToInsert;
+}
+
/// Visit - Walk the subtree of a statement and add extra
/// blocks for ternary operators, &&, and ||. We also process "," and
/// DeclStmts (which may contain nested control-flow).
@@ -2228,7 +2403,10 @@
}
if (!NoReturn && !AddEHEdge) {
- return VisitStmt(C, asc.withAlwaysAdd(true));
+ autoCreateBlock();
+ appendCall(Block, C);
+
+ return VisitChildren(C);
}
if (Block) {
@@ -2242,7 +2420,7 @@
else
Block = createBlock();
- appendStmt(Block, C);
+ appendCall(Block, C);
if (AddEHEdge) {
// Add exceptional edges.
@@ -2487,6 +2665,8 @@
LastBlock = newBlock;
}
+ maybeAddScopeBeginForVarDecl(Block, VD, DS);
+
// Remove variable from local scope.
if (ScopePos && VD == *ScopePos)
++ScopePos;
@@ -2951,6 +3131,7 @@
do {
Expr *C = F->getCond();
+ SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
// Specially handle logical operators, which have a slightly
// more optimal CFG representation.
@@ -2984,6 +3165,7 @@
appendStmt(Block, F->getConditionVariableDeclStmt());
EntryConditionBlock = addStmt(Init);
assert(Block == EntryConditionBlock);
+ maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
}
}
@@ -3010,6 +3192,8 @@
// If the loop contains initialization, create a new block for those
// statements. This block can also contain statements that precede the loop.
if (Stmt *I = F->getInit()) {
+ SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
+ ScopePos = LoopBeginScopePos;
Block = createBlock();
return addStmt(I);
}
@@ -3306,6 +3490,7 @@
appendStmt(Block, W->getConditionVariableDeclStmt());
EntryConditionBlock = addStmt(Init);
assert(Block == EntryConditionBlock);
+ maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
}
}
@@ -3631,6 +3816,7 @@
autoCreateBlock();
appendStmt(Block, Terminator->getConditionVariableDeclStmt());
LastBlock = addStmt(Init);
+ maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);
}
}
@@ -4376,6 +4562,9 @@
case CFGElement::LifetimeEnds:
case CFGElement::Statement:
case CFGElement::Constructor:
+ case CFGElement::CXXRecordTypedCall:
+ case CFGElement::ScopeBegin:
+ case CFGElement::ScopeEnd:
llvm_unreachable("getDestructorDecl should only be used with "
"ImplicitDtors");
case CFGElement::AutomaticObjectDtor: {
@@ -4726,6 +4915,70 @@
OS << " (Member initializer)";
}
+static void print_construction_context(raw_ostream &OS,
+ StmtPrinterHelper &Helper,
+ const ConstructionContext *CC) {
+ const Stmt *S1 = nullptr, *S2 = nullptr;
+ switch (CC->getKind()) {
+ case ConstructionContext::SimpleConstructorInitializerKind: {
+ OS << ", ";
+ const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);
+ print_initializer(OS, Helper, SICC->getCXXCtorInitializer());
+ break;
+ }
+ case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: {
+ OS << ", ";
+ const auto *CICC =
+ cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);
+ print_initializer(OS, Helper, CICC->getCXXCtorInitializer());
+ S2 = CICC->getCXXBindTemporaryExpr();
+ break;
+ }
+ case ConstructionContext::SimpleVariableKind: {
+ const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC);
+ S1 = SDSCC->getDeclStmt();
+ break;
+ }
+ case ConstructionContext::CXX17ElidedCopyVariableKind: {
+ const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);
+ S1 = CDSCC->getDeclStmt();
+ S2 = CDSCC->getCXXBindTemporaryExpr();
+ break;
+ }
+ case ConstructionContext::NewAllocatedObjectKind: {
+ const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
+ S1 = NECC->getCXXNewExpr();
+ break;
+ }
+ case ConstructionContext::SimpleReturnedValueKind: {
+ const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC);
+ S1 = RSCC->getReturnStmt();
+ break;
+ }
+ case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {
+ const auto *RSCC =
+ cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);
+ S1 = RSCC->getReturnStmt();
+ S2 = RSCC->getCXXBindTemporaryExpr();
+ break;
+ }
+ case ConstructionContext::TemporaryObjectKind: {
+ const auto *TOCC = cast<TemporaryObjectConstructionContext>(CC);
+ S1 = TOCC->getCXXBindTemporaryExpr();
+ S2 = TOCC->getMaterializedTemporaryExpr();
+ break;
+ }
+ }
+ if (S1) {
+ OS << ", ";
+ Helper.handledStmt(const_cast<Stmt *>(S1), OS);
+ }
+ if (S2) {
+ OS << ", ";
+ Helper.handledStmt(const_cast<Stmt *>(S2), OS);
+ }
+}
+
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
const CFGElement &E) {
if (Optional<CFGStmt> CS = E.getAs<CFGStmt>()) {
@@ -4755,54 +5008,22 @@
}
S->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
- if (isa<CXXOperatorCallExpr>(S)) {
+ if (auto VTC = E.getAs<CFGCXXRecordTypedCall>()) {
+ if (isa<CXXOperatorCallExpr>(S))
+ OS << " (OperatorCall)";
+ OS << " (CXXRecordTypedCall";
+ print_construction_context(OS, Helper, VTC->getConstructionContext());
+ OS << ")";
+ } else if (isa<CXXOperatorCallExpr>(S)) {
OS << " (OperatorCall)";
} else if (isa<CXXBindTemporaryExpr>(S)) {
OS << " (BindTemporary)";
} else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) {
- OS << " (CXXConstructExpr, ";
+ OS << " (CXXConstructExpr";
if (Optional<CFGConstructor> CE = E.getAs<CFGConstructor>()) {
- const ConstructionContext *CC = CE->getConstructionContext();
- const Stmt *S1 = nullptr, *S2 = nullptr;
- switch (CC->getKind()) {
- case ConstructionContext::ConstructorInitializerKind: {
- const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC);
- print_initializer(OS, Helper, ICC->getCXXCtorInitializer());
- OS << ", ";
- break;
- }
- case ConstructionContext::SimpleVariableKind: {
- const auto *DSCC = cast<SimpleVariableConstructionContext>(CC);
- S1 = DSCC->getDeclStmt();
- break;
- }
- case ConstructionContext::NewAllocatedObjectKind: {
- const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
- S1 = NECC->getCXXNewExpr();
- break;
- }
- case ConstructionContext::ReturnedValueKind: {
- const auto *RSCC = cast<ReturnedValueConstructionContext>(CC);
- S1 = RSCC->getReturnStmt();
- break;
- }
- case ConstructionContext::TemporaryObjectKind: {
- const auto *TOCC = cast<TemporaryObjectConstructionContext>(CC);
- S1 = TOCC->getCXXBindTemporaryExpr();
- S2 = TOCC->getMaterializedTemporaryExpr();
- break;
- }
- }
- if (S1) {
- Helper.handledStmt(const_cast<Stmt *>(S1), OS);
- OS << ", ";
- }
- if (S2) {
- Helper.handledStmt(const_cast<Stmt *>(S2), OS);
- OS << ", ";
- }
+ print_construction_context(OS, Helper, CE->getConstructionContext());
}
- OS << CCE->getType().getAsString() << ")";
+ OS << ", " << CCE->getType().getAsString() << ")";
} else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) {
OS << " (" << CE->getStmtClassName() << ", "
<< CE->getCastKindName()
@@ -4836,6 +5057,16 @@
} else if (Optional<CFGLoopExit> LE = E.getAs<CFGLoopExit>()) {
const Stmt *LoopStmt = LE->getLoopStmt();
OS << LoopStmt->getStmtClassName() << " (LoopExit)\n";
+ } else if (Optional<CFGScopeBegin> SB = E.getAs<CFGScopeBegin>()) {
+ OS << "CFGScopeBegin(";
+ if (const VarDecl *VD = SB->getVarDecl())
+ OS << VD->getQualifiedNameAsString();
+ OS << ")\n";
+ } else if (Optional<CFGScopeEnd> SE = E.getAs<CFGScopeEnd>()) {
+ OS << "CFGScopeEnd(";
+ if (const VarDecl *VD = SE->getVarDecl())
+ OS << VD->getQualifiedNameAsString();
+ OS << ")\n";
} else if (Optional<CFGNewAllocator> NE = E.getAs<CFGNewAllocator>()) {
OS << "CFGNewAllocator(";
if (const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
diff --git a/lib/Analysis/CFGReachabilityAnalysis.cpp b/lib/Analysis/CFGReachabilityAnalysis.cpp
index 4ae135f..6f557e0 100644
--- a/lib/Analysis/CFGReachabilityAnalysis.cpp
+++ b/lib/Analysis/CFGReachabilityAnalysis.cpp
@@ -1,4 +1,4 @@
-//==- CFGReachabilityAnalysis.cpp - Basic reachability analysis --*- C++ -*-==//
+//===- CFGReachabilityAnalysis.cpp - Basic reachability analysis ----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,18 +13,19 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/SmallVector.h"
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVector.h"
using namespace clang;
-CFGReverseBlockReachabilityAnalysis::CFGReverseBlockReachabilityAnalysis(const CFG &cfg)
- : analyzed(cfg.getNumBlockIDs(), false) {}
+CFGReverseBlockReachabilityAnalysis::CFGReverseBlockReachabilityAnalysis(
+ const CFG &cfg)
+ : analyzed(cfg.getNumBlockIDs(), false) {}
bool CFGReverseBlockReachabilityAnalysis::isReachable(const CFGBlock *Src,
const CFGBlock *Dst) {
-
const unsigned DstBlockID = Dst->getBlockID();
// If we haven't analyzed the destination node, run the analysis now
diff --git a/lib/Analysis/ConstructionContext.cpp b/lib/Analysis/ConstructionContext.cpp
index aea329b..9f3c00b 100644
--- a/lib/Analysis/ConstructionContext.cpp
+++ b/lib/Analysis/ConstructionContext.cpp
@@ -48,15 +48,13 @@
if (const Stmt *S = TopLayer->getTriggerStmt()) {
if (const auto *DS = dyn_cast<DeclStmt>(S)) {
assert(TopLayer->isLast());
- auto *CC =
- C.getAllocator().Allocate<SimpleVariableConstructionContext>();
- return new (CC) SimpleVariableConstructionContext(DS);
- } else if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
+ return create<SimpleVariableConstructionContext>(C, DS);
+ }
+ if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
assert(TopLayer->isLast());
- auto *CC =
- C.getAllocator().Allocate<NewAllocatedObjectConstructionContext>();
- return new (CC) NewAllocatedObjectConstructionContext(NE);
- } else if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(S)) {
+ return create<NewAllocatedObjectConstructionContext>(C, NE);
+ }
+ if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(S)) {
const MaterializeTemporaryExpr *MTE = nullptr;
assert(BTE->getType().getCanonicalType()
->getAsCXXRecordDecl()->hasNonTrivialDestructor());
@@ -64,29 +62,62 @@
// lifetime extension on the parent layer.
if (const ConstructionContextLayer *ParentLayer = TopLayer->getParent()) {
assert(ParentLayer->isLast());
- MTE = cast<MaterializeTemporaryExpr>(ParentLayer->getTriggerStmt());
+ // C++17 *requires* elision of the constructor at the return site
+ // and at variable/member initialization site, while previous standards
+ // were allowing an optional elidable constructor.
+ // This is the C++17 copy-elided construction into a ctor initializer.
+ if (const CXXCtorInitializer *I = ParentLayer->getTriggerInit()) {
+ return create<
+ CXX17ElidedCopyConstructorInitializerConstructionContext>(C,
+ I, BTE);
+ }
+ assert(ParentLayer->getTriggerStmt() &&
+ "Non-statement-based layers have been handled above!");
+ // This is the normal, non-C++17 case: a temporary object which has
+ // both destruction and materialization info attached to it in the AST.
+ if ((MTE = dyn_cast<MaterializeTemporaryExpr>(
+ ParentLayer->getTriggerStmt()))) {
+ return create<TemporaryObjectConstructionContext>(C, BTE, MTE);
+ }
+ // This is C++17 copy-elided construction into return statement.
+ if (auto *RS = dyn_cast<ReturnStmt>(ParentLayer->getTriggerStmt())) {
+ assert(!RS->getRetValue()->getType().getCanonicalType()
+ ->getAsCXXRecordDecl()->hasTrivialDestructor());
+ return create<CXX17ElidedCopyReturnedValueConstructionContext>(C,
+ RS, BTE);
+ }
+ // This is C++17 copy-elided construction into a simple variable.
+ if (auto *DS = dyn_cast<DeclStmt>(ParentLayer->getTriggerStmt())) {
+ assert(!cast<VarDecl>(DS->getSingleDecl())->getType()
+ .getCanonicalType()->getAsCXXRecordDecl()
+ ->hasTrivialDestructor());
+ return create<CXX17ElidedCopyVariableConstructionContext>(C, DS, BTE);
+ }
+ llvm_unreachable("Unexpected construction context with destructor!");
}
- auto *CC =
- C.getAllocator().Allocate<TemporaryObjectConstructionContext>();
- return new (CC) TemporaryObjectConstructionContext(BTE, MTE);
- } else if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) {
- assert(MTE->getType().getCanonicalType()
- ->getAsCXXRecordDecl()->hasTrivialDestructor());
- assert(TopLayer->isLast());
- auto *CC =
- C.getAllocator().Allocate<TemporaryObjectConstructionContext>();
- return new (CC) TemporaryObjectConstructionContext(nullptr, MTE);
- } else if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
- assert(TopLayer->isLast());
- auto *CC =
- C.getAllocator().Allocate<ReturnedValueConstructionContext>();
- return new (CC) ReturnedValueConstructionContext(RS);
+ // A temporary object that doesn't require materialization.
+ return create<TemporaryObjectConstructionContext>(C, BTE, /*MTE=*/nullptr);
}
+ if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) {
+ // If the object requires destruction and is not lifetime-extended,
+ // then it must have a BTE within its MTE.
+ // FIXME: This should be an assertion.
+ if (!(MTE->getType().getCanonicalType()
+ ->getAsCXXRecordDecl()->hasTrivialDestructor() ||
+ MTE->getStorageDuration() != SD_FullExpression))
+ return nullptr;
+
+ assert(TopLayer->isLast());
+ return create<TemporaryObjectConstructionContext>(C, nullptr, MTE);
+ }
+ if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
+ assert(TopLayer->isLast());
+ return create<SimpleReturnedValueConstructionContext>(C, RS);
+ }
+ llvm_unreachable("Unexpected construction context with statement!");
} else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) {
assert(TopLayer->isLast());
- auto *CC =
- C.getAllocator().Allocate<ConstructorInitializerConstructionContext>();
- return new (CC) ConstructorInitializerConstructionContext(I);
+ return create<SimpleConstructorInitializerConstructionContext>(C, I);
}
llvm_unreachable("Unexpected construction context!");
}
diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp
index 96edad0..a46386e 100644
--- a/lib/Analysis/Consumed.cpp
+++ b/lib/Analysis/Consumed.cpp
@@ -1,4 +1,4 @@
-//===- Consumed.cpp --------------------------------------------*- C++ --*-===//
+//===- Consumed.cpp -------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,21 +13,29 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/Consumed.h"
-#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/AST/StmtCXX.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
#include <memory>
+#include <utility>
// TODO: Adjust states of args to constructors in the same way that arguments to
// function calls are handled.
@@ -49,7 +57,7 @@
using namespace consumed;
// Key method definition
-ConsumedWarningsHandlerBase::~ConsumedWarningsHandlerBase() {}
+ConsumedWarningsHandlerBase::~ConsumedWarningsHandlerBase() = default;
static SourceLocation getFirstStmtLoc(const CFGBlock *Block) {
// Find the source location of the first statement in the block, if the block
@@ -63,7 +71,7 @@
if (Block->succ_size() == 1 && *Block->succ_begin())
return getFirstStmtLoc(*Block->succ_begin());
- return SourceLocation();
+ return {};
}
static SourceLocation getLastStmtLoc(const CFGBlock *Block) {
@@ -109,7 +117,6 @@
static bool isCallableInState(const CallableWhenAttr *CWAttr,
ConsumedState State) {
-
for (const auto &S : CWAttr->callableStates()) {
ConsumedState MappedAttrState = CS_None;
@@ -134,7 +141,6 @@
return false;
}
-
static bool isConsumableType(const QualType &QT) {
if (QT->isPointerType() || QT->isReferenceType())
return false;
@@ -161,7 +167,6 @@
return false;
}
-
static bool isKnownState(ConsumedState State) {
switch (State) {
case CS_Unconsumed:
@@ -270,11 +275,13 @@
}
namespace {
+
struct VarTestResult {
const VarDecl *Var;
ConsumedState TestsFor;
};
-} // end anonymous::VarTestResult
+
+} // namespace
namespace clang {
namespace consumed {
@@ -292,7 +299,7 @@
IT_BinTest,
IT_Var,
IT_Tmp
- } InfoType;
+ } InfoType = IT_None;
struct BinTestTy {
const BinaryOperator *Source;
@@ -310,22 +317,19 @@
};
public:
- PropagationInfo() : InfoType(IT_None) {}
-
+ PropagationInfo() = default;
PropagationInfo(const VarTestResult &VarTest)
- : InfoType(IT_VarTest), VarTest(VarTest) {}
-
+ : InfoType(IT_VarTest), VarTest(VarTest) {}
+
PropagationInfo(const VarDecl *Var, ConsumedState TestsFor)
- : InfoType(IT_VarTest) {
-
+ : InfoType(IT_VarTest) {
VarTest.Var = Var;
VarTest.TestsFor = TestsFor;
}
PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
const VarTestResult <est, const VarTestResult &RTest)
- : InfoType(IT_BinTest) {
-
+ : InfoType(IT_BinTest) {
BinTest.Source = Source;
BinTest.EOp = EOp;
BinTest.LTest = LTest;
@@ -335,8 +339,7 @@
PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
const VarDecl *LVar, ConsumedState LTestsFor,
const VarDecl *RVar, ConsumedState RTestsFor)
- : InfoType(IT_BinTest) {
-
+ : InfoType(IT_BinTest) {
BinTest.Source = Source;
BinTest.EOp = EOp;
BinTest.LTest.Var = LVar;
@@ -346,38 +349,37 @@
}
PropagationInfo(ConsumedState State)
- : InfoType(IT_State), State(State) {}
-
+ : InfoType(IT_State), State(State) {}
PropagationInfo(const VarDecl *Var) : InfoType(IT_Var), Var(Var) {}
PropagationInfo(const CXXBindTemporaryExpr *Tmp)
- : InfoType(IT_Tmp), Tmp(Tmp) {}
+ : InfoType(IT_Tmp), Tmp(Tmp) {}
- const ConsumedState & getState() const {
+ const ConsumedState &getState() const {
assert(InfoType == IT_State);
return State;
}
- const VarTestResult & getVarTest() const {
+ const VarTestResult &getVarTest() const {
assert(InfoType == IT_VarTest);
return VarTest;
}
- const VarTestResult & getLTest() const {
+ const VarTestResult &getLTest() const {
assert(InfoType == IT_BinTest);
return BinTest.LTest;
}
- const VarTestResult & getRTest() const {
+ const VarTestResult &getRTest() const {
assert(InfoType == IT_BinTest);
return BinTest.RTest;
}
- const VarDecl * getVar() const {
+ const VarDecl *getVar() const {
assert(InfoType == IT_Var);
return Var;
}
- const CXXBindTemporaryExpr * getTmp() const {
+ const CXXBindTemporaryExpr *getTmp() const {
assert(InfoType == IT_Tmp);
return Tmp;
}
@@ -405,12 +407,12 @@
return BinTest.Source;
}
- inline bool isValid() const { return InfoType != IT_None; }
- inline bool isState() const { return InfoType == IT_State; }
- inline bool isVarTest() const { return InfoType == IT_VarTest; }
- inline bool isBinTest() const { return InfoType == IT_BinTest; }
- inline bool isVar() const { return InfoType == IT_Var; }
- inline bool isTmp() const { return InfoType == IT_Tmp; }
+ bool isValid() const { return InfoType != IT_None; }
+ bool isState() const { return InfoType == IT_State; }
+ bool isVarTest() const { return InfoType == IT_VarTest; }
+ bool isBinTest() const { return InfoType == IT_BinTest; }
+ bool isVar() const { return InfoType == IT_Var; }
+ bool isTmp() const { return InfoType == IT_Tmp; }
bool isTest() const {
return InfoType == IT_VarTest || InfoType == IT_BinTest;
@@ -433,15 +435,17 @@
BinTest.LTest.Var, invertConsumedUnconsumed(BinTest.LTest.TestsFor),
BinTest.RTest.Var, invertConsumedUnconsumed(BinTest.RTest.TestsFor));
} else {
- return PropagationInfo();
+ return {};
}
}
};
-static inline void
+} // namespace consumed
+} // namespace clang
+
+static void
setStateForVarOrTmp(ConsumedStateMap *StateMap, const PropagationInfo &PInfo,
ConsumedState State) {
-
assert(PInfo.isVar() || PInfo.isTmp());
if (PInfo.isVar())
@@ -450,12 +454,14 @@
StateMap->setState(PInfo.getTmp(), State);
}
+namespace clang {
+namespace consumed {
+
class ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {
-
- typedef llvm::DenseMap<const Stmt *, PropagationInfo> MapType;
- typedef std::pair<const Stmt *, PropagationInfo> PairType;
- typedef MapType::iterator InfoEntry;
- typedef MapType::const_iterator ConstInfoEntry;
+ using MapType = llvm::DenseMap<const Stmt *, PropagationInfo>;
+ using PairType= std::pair<const Stmt *, PropagationInfo>;
+ using InfoEntry = MapType::iterator;
+ using ConstInfoEntry = MapType::const_iterator;
AnalysisDeclContext &AC;
ConsumedAnalyzer &Analyzer;
@@ -463,17 +469,19 @@
MapType PropagationMap;
InfoEntry findInfo(const Expr *E) {
- if (auto Cleanups = dyn_cast<ExprWithCleanups>(E))
+ if (const auto Cleanups = dyn_cast<ExprWithCleanups>(E))
if (!Cleanups->cleanupsHaveSideEffects())
E = Cleanups->getSubExpr();
return PropagationMap.find(E->IgnoreParens());
}
+
ConstInfoEntry findInfo(const Expr *E) const {
- if (auto Cleanups = dyn_cast<ExprWithCleanups>(E))
+ if (const auto Cleanups = dyn_cast<ExprWithCleanups>(E))
if (!Cleanups->cleanupsHaveSideEffects())
E = Cleanups->getSubExpr();
return PropagationMap.find(E->IgnoreParens());
}
+
void insertInfo(const Expr *E, const PropagationInfo &PI) {
PropagationMap.insert(PairType(E->IgnoreParens(), PI));
}
@@ -517,7 +525,7 @@
if (Entry != PropagationMap.end())
return Entry->second;
else
- return PropagationInfo();
+ return {};
}
void reset(ConsumedStateMap *NewStateMap) {
@@ -525,6 +533,8 @@
}
};
+} // namespace consumed
+} // namespace clang
void ConsumedStmtVisitor::forwardInfo(const Expr *From, const Expr *To) {
InfoEntry Entry = findInfo(From);
@@ -532,7 +542,6 @@
insertInfo(To, Entry->second);
}
-
// Create a new state for To, which is initialized to the state of From.
// If NS is not CS_None, sets the state of From to NS.
void ConsumedStmtVisitor::copyInfo(const Expr *From, const Expr *To,
@@ -548,7 +557,6 @@
}
}
-
// Get the ConsumedState for From
ConsumedState ConsumedStmtVisitor::getInfo(const Expr *From) {
InfoEntry Entry = findInfo(From);
@@ -559,7 +567,6 @@
return CS_None;
}
-
// If we already have info for To then update it, otherwise create a new entry.
void ConsumedStmtVisitor::setInfo(const Expr *To, ConsumedState NS) {
InfoEntry Entry = findInfo(To);
@@ -572,8 +579,6 @@
}
}
-
-
void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
const FunctionDecl *FunDecl,
SourceLocation BlameLoc) {
@@ -592,7 +597,6 @@
Analyzer.WarningsHandler.warnUseInInvalidState(
FunDecl->getNameAsString(), PInfo.getVar()->getNameAsString(),
stateToString(VarState), BlameLoc);
-
} else {
ConsumedState TmpState = PInfo.getAsState(StateMap);
@@ -604,7 +608,6 @@
}
}
-
// Factors out common behavior for function, method, and operator calls.
// Check parameters and set parameter state if necessary.
// Returns true if the state of ObjArg is set, or false otherwise.
@@ -681,7 +684,6 @@
return false;
}
-
void ConsumedStmtVisitor::propagateReturnType(const Expr *Call,
const FunctionDecl *Fun) {
QualType RetType = Fun->getCallResultType();
@@ -699,7 +701,6 @@
}
}
-
void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
switch (BinOp->getOpcode()) {
case BO_LAnd:
@@ -711,7 +712,6 @@
if (LEntry != PropagationMap.end() && LEntry->second.isVarTest()) {
LTest = LEntry->second.getVarTest();
-
} else {
LTest.Var = nullptr;
LTest.TestsFor = CS_None;
@@ -719,7 +719,6 @@
if (REntry != PropagationMap.end() && REntry->second.isVarTest()) {
RTest = REntry->second.getVarTest();
-
} else {
RTest.Var = nullptr;
RTest.TestsFor = CS_None;
@@ -728,7 +727,6 @@
if (!(LTest.Var == nullptr && RTest.Var == nullptr))
PropagationMap.insert(PairType(BinOp, PropagationInfo(BinOp,
static_cast<EffectiveOp>(BinOp->getOpcode() == BO_LOr), LTest, RTest)));
-
break;
}
@@ -805,7 +803,6 @@
}
}
-
void ConsumedStmtVisitor::VisitCXXMemberCallExpr(
const CXXMemberCallExpr *Call) {
CXXMethodDecl* MD = Call->getMethodDecl();
@@ -816,12 +813,9 @@
propagateReturnType(Call, MD);
}
-
void ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
const CXXOperatorCallExpr *Call) {
-
- const FunctionDecl *FunDecl =
- dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
+ const auto *FunDecl = dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
if (!FunDecl) return;
if (Call->getOperator() == OO_Equal) {
@@ -831,7 +825,7 @@
return;
}
- if (const CXXMemberCallExpr *MCall = dyn_cast<CXXMemberCallExpr>(Call))
+ if (const auto *MCall = dyn_cast<CXXMemberCallExpr>(Call))
handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl);
else
handleCall(Call, Call->getArg(0), FunDecl);
@@ -840,7 +834,7 @@
}
void ConsumedStmtVisitor::VisitDeclRefExpr(const DeclRefExpr *DeclRef) {
- if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
+ if (const auto *Var = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
if (StateMap->getState(Var) != consumed::CS_None)
PropagationMap.insert(PairType(DeclRef, PropagationInfo(Var)));
}
@@ -851,13 +845,12 @@
VisitVarDecl(cast<VarDecl>(DI));
if (DeclS->isSingleDecl())
- if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl()))
+ if (const auto *Var = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl()))
PropagationMap.insert(PairType(DeclS, PropagationInfo(Var)));
}
void ConsumedStmtVisitor::VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *Temp) {
-
forwardInfo(Temp->GetTemporaryExpr(), Temp);
}
@@ -865,7 +858,6 @@
forwardInfo(MExpr->getBase(), MExpr);
}
-
void ConsumedStmtVisitor::VisitParmVarDecl(const ParmVarDecl *Param) {
QualType ParamType = Param->getType();
ConsumedState ParamState = consumed::CS_None;
@@ -943,10 +935,6 @@
StateMap->setState(Var, consumed::CS_Unknown);
}
}
-}} // end clang::consumed::ConsumedStmtVisitor
-
-namespace clang {
-namespace consumed {
static void splitVarStateForIf(const IfStmt *IfNode, const VarTestResult &Test,
ConsumedStateMap *ThenStates,
@@ -956,10 +944,8 @@
if (VarState == CS_Unknown) {
ThenStates->setState(Test.Var, Test.TestsFor);
ElseStates->setState(Test.Var, invertConsumedUnconsumed(Test.TestsFor));
-
} else if (VarState == invertConsumedUnconsumed(Test.TestsFor)) {
ThenStates->markUnreachable();
-
} else if (VarState == Test.TestsFor) {
ElseStates->markUnreachable();
}
@@ -978,28 +964,22 @@
if (PInfo.testEffectiveOp() == EO_And) {
if (LState == CS_Unknown) {
ThenStates->setState(LTest.Var, LTest.TestsFor);
-
} else if (LState == invertConsumedUnconsumed(LTest.TestsFor)) {
ThenStates->markUnreachable();
-
} else if (LState == LTest.TestsFor && isKnownState(RState)) {
if (RState == RTest.TestsFor)
ElseStates->markUnreachable();
else
ThenStates->markUnreachable();
}
-
} else {
if (LState == CS_Unknown) {
ElseStates->setState(LTest.Var,
invertConsumedUnconsumed(LTest.TestsFor));
-
} else if (LState == LTest.TestsFor) {
ElseStates->markUnreachable();
-
} else if (LState == invertConsumedUnconsumed(LTest.TestsFor) &&
isKnownState(RState)) {
-
if (RState == RTest.TestsFor)
ElseStates->markUnreachable();
else
@@ -1014,7 +994,6 @@
ThenStates->setState(RTest.Var, RTest.TestsFor);
else if (RState == invertConsumedUnconsumed(RTest.TestsFor))
ThenStates->markUnreachable();
-
} else {
if (RState == CS_Unknown)
ElseStates->setState(RTest.Var,
@@ -1027,7 +1006,6 @@
bool ConsumedBlockInfo::allBackEdgesVisited(const CFGBlock *CurrBlock,
const CFGBlock *TargetBlock) {
-
assert(CurrBlock && "Block pointer must not be NULL");
assert(TargetBlock && "TargetBlock pointer must not be NULL");
@@ -1043,7 +1021,6 @@
void ConsumedBlockInfo::addInfo(
const CFGBlock *Block, ConsumedStateMap *StateMap,
std::unique_ptr<ConsumedStateMap> &OwnedStateMap) {
-
assert(Block && "Block pointer must not be NULL");
auto &Entry = StateMapsArray[Block->getBlockID()];
@@ -1058,7 +1035,6 @@
void ConsumedBlockInfo::addInfo(const CFGBlock *Block,
std::unique_ptr<ConsumedStateMap> StateMap) {
-
assert(Block && "Block pointer must not be NULL");
auto &Entry = StateMapsArray[Block->getBlockID()];
@@ -1119,7 +1095,7 @@
for (const auto &DM : VarMap) {
if (isa<ParmVarDecl>(DM.first)) {
- const ParmVarDecl *Param = cast<ParmVarDecl>(DM.first);
+ const auto *Param = cast<ParmVarDecl>(DM.first);
const ReturnTypestateAttr *RTA = Param->getAttr<ReturnTypestateAttr>();
if (!RTA)
@@ -1226,7 +1202,7 @@
void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC,
const FunctionDecl *D) {
QualType ReturnType;
- if (const CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
ASTContext &CurrContext = AC.getASTContext();
ReturnType = Constructor->getThisType(CurrContext)->getPointeeType();
} else
@@ -1256,14 +1232,12 @@
bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
const ConsumedStmtVisitor &Visitor) {
-
std::unique_ptr<ConsumedStateMap> FalseStates(
new ConsumedStateMap(*CurrStates));
PropagationInfo PInfo;
- if (const IfStmt *IfNode =
- dyn_cast_or_null<IfStmt>(CurrBlock->getTerminator().getStmt())) {
-
+ if (const auto *IfNode =
+ dyn_cast_or_null<IfStmt>(CurrBlock->getTerminator().getStmt())) {
const Expr *Cond = IfNode->getCond();
PInfo = Visitor.getInfo(Cond);
@@ -1275,19 +1249,15 @@
FalseStates->setSource(Cond);
splitVarStateForIf(IfNode, PInfo.getVarTest(), CurrStates.get(),
FalseStates.get());
-
} else if (PInfo.isBinTest()) {
CurrStates->setSource(PInfo.testSourceNode());
FalseStates->setSource(PInfo.testSourceNode());
splitVarStateForIfBinOp(PInfo, CurrStates.get(), FalseStates.get());
-
} else {
return false;
}
-
- } else if (const BinaryOperator *BinOp =
- dyn_cast_or_null<BinaryOperator>(CurrBlock->getTerminator().getStmt())) {
-
+ } else if (const auto *BinOp =
+ dyn_cast_or_null<BinaryOperator>(CurrBlock->getTerminator().getStmt())) {
PInfo = Visitor.getInfo(BinOp->getLHS());
if (!PInfo.isVarTest()) {
if ((BinOp = dyn_cast_or_null<BinaryOperator>(BinOp->getLHS()))) {
@@ -1295,7 +1265,6 @@
if (!PInfo.isVarTest())
return false;
-
} else {
return false;
}
@@ -1320,7 +1289,6 @@
else if (VarState == Test.TestsFor)
FalseStates->markUnreachable();
}
-
} else {
return false;
}
@@ -1339,7 +1307,7 @@
}
void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
- const FunctionDecl *D = dyn_cast_or_null<FunctionDecl>(AC.getDecl());
+ const auto *D = dyn_cast_or_null<FunctionDecl>(AC.getDecl());
if (!D)
return;
@@ -1368,7 +1336,6 @@
if (!CurrStates) {
continue;
-
} else if (!CurrStates->isReachable()) {
CurrStates = nullptr;
continue;
@@ -1423,7 +1390,6 @@
for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
SE = CurrBlock->succ_end(); SI != SE; ++SI) {
-
if (*SI == nullptr) continue;
if (BlockInfo.isBackEdge(CurrBlock, *SI)) {
@@ -1452,4 +1418,3 @@
WarningsHandler.emitDiagnostics();
}
-}} // end namespace clang::consumed
diff --git a/lib/Analysis/Dominators.cpp b/lib/Analysis/Dominators.cpp
index 0e02c6d..1b7dd8c 100644
--- a/lib/Analysis/Dominators.cpp
+++ b/lib/Analysis/Dominators.cpp
@@ -1,4 +1,4 @@
-//=- Dominators.cpp - Implementation of dominators tree for Clang CFG C++ -*-=//
+//===- Dominators.cpp - Implementation of dominators tree for Clang CFG ---===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,4 +11,4 @@
using namespace clang;
-void DominatorTree::anchor() { }
+void DominatorTree::anchor() {}
diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index 4752c2b..f557a74 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -563,7 +563,7 @@
it != ei; ++it) {
vec.push_back(it->first);
}
- std::sort(vec.begin(), vec.end(), [](const CFGBlock *A, const CFGBlock *B) {
+ llvm::sort(vec.begin(), vec.end(), [](const CFGBlock *A, const CFGBlock *B) {
return A->getBlockID() < B->getBlockID();
});
@@ -583,7 +583,8 @@
declVec.push_back(*si);
}
- std::sort(declVec.begin(), declVec.end(), [](const Decl *A, const Decl *B) {
+ llvm::sort(declVec.begin(), declVec.end(),
+ [](const Decl *A, const Decl *B) {
return A->getLocStart() < B->getLocStart();
});
diff --git a/lib/Analysis/PostOrderCFGView.cpp b/lib/Analysis/PostOrderCFGView.cpp
index 5a3c8182..124424b 100644
--- a/lib/Analysis/PostOrderCFGView.cpp
+++ b/lib/Analysis/PostOrderCFGView.cpp
@@ -1,4 +1,4 @@
-//===- PostOrderCFGView.cpp - Post order view of CFG blocks -------*- C++ --*-//
+//===- PostOrderCFGView.cpp - Post order view of CFG blocks ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,10 +12,12 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
using namespace clang;
-void PostOrderCFGView::anchor() { }
+void PostOrderCFGView::anchor() {}
PostOrderCFGView::PostOrderCFGView(const CFG *cfg) {
Blocks.reserve(cfg->getNumBlockIDs());
@@ -46,4 +48,3 @@
unsigned b2V = (b2It == POV.BlockOrder.end()) ? 0 : b2It->second;
return b1V > b2V;
}
-
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index f81d916..685d1ae 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -1,4 +1,4 @@
-//===- ThreadSafety.cpp ----------------------------------------*- C++ --*-===//
+//===- ThreadSafety.cpp ---------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,41 +17,59 @@
#include "clang/Analysis/Analyses/ThreadSafety.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtCXX.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
-#include "clang/Analysis/Analyses/ThreadSafetyLogical.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
+#include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
-#include "clang/Analysis/CFGStmtMap.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ImmutableMap.h"
-#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
-#include <ostream>
-#include <sstream>
+#include <cassert>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <string>
+#include <type_traits>
#include <utility>
#include <vector>
+
using namespace clang;
using namespace threadSafety;
// Key method definition
-ThreadSafetyHandler::~ThreadSafetyHandler() {}
+ThreadSafetyHandler::~ThreadSafetyHandler() = default;
namespace {
-class TILPrinter :
- public til::PrettyPrinter<TILPrinter, llvm::raw_ostream> {};
+class TILPrinter :
+ public til::PrettyPrinter<TILPrinter, llvm::raw_ostream> {};
+
+} // namespace
/// Issue a warning about an invalid lock expression
static void warnInvalidLock(ThreadSafetyHandler &Handler,
@@ -66,6 +84,8 @@
Handler.handleInvalidLockExp(Kind, Loc);
}
+namespace {
+
/// \brief A set of CapabilityInfo objects, which are compiled from the
/// requires attributes on a function.
class CapExprSet : public SmallVector<CapabilityExpr, 4> {
@@ -94,23 +114,29 @@
/// shared.
class FactEntry : public CapabilityExpr {
private:
- LockKind LKind; ///< exclusive or shared
- SourceLocation AcquireLoc; ///< where it was acquired.
- bool Asserted; ///< true if the lock was asserted
- bool Declared; ///< true if the lock was declared
+ /// Exclusive or shared.
+ LockKind LKind;
+
+ /// Where it was acquired.
+ SourceLocation AcquireLoc;
+
+ /// True if the lock was asserted.
+ bool Asserted;
+
+ /// True if the lock was declared.
+ bool Declared;
public:
FactEntry(const CapabilityExpr &CE, LockKind LK, SourceLocation Loc,
bool Asrt, bool Declrd = false)
: CapabilityExpr(CE), LKind(LK), AcquireLoc(Loc), Asserted(Asrt),
Declared(Declrd) {}
+ virtual ~FactEntry() = default;
- virtual ~FactEntry() {}
-
- LockKind kind() const { return LKind; }
- SourceLocation loc() const { return AcquireLoc; }
- bool asserted() const { return Asserted; }
- bool declared() const { return Declared; }
+ LockKind kind() const { return LKind; }
+ SourceLocation loc() const { return AcquireLoc; }
+ bool asserted() const { return Asserted; }
+ bool declared() const { return Declared; }
void setDeclared(bool D) { Declared = D; }
@@ -129,8 +155,7 @@
}
};
-
-typedef unsigned short FactID;
+using FactID = unsigned short;
/// \brief FactManager manages the memory for all facts that are created during
/// the analysis of a single routine.
@@ -148,7 +173,6 @@
FactEntry &operator[](FactID F) { return *Facts[F]; }
};
-
/// \brief A FactSet is the set of facts that are known to be true at a
/// particular program point. FactSets must be small, because they are
/// frequently copied, and are thus implemented as a set of indices into a
@@ -158,25 +182,25 @@
/// may involve partial pattern matches, rather than exact matches.
class FactSet {
private:
- typedef SmallVector<FactID, 4> FactVec;
+ using FactVec = SmallVector<FactID, 4>;
FactVec FactIDs;
public:
- typedef FactVec::iterator iterator;
- typedef FactVec::const_iterator const_iterator;
+ using iterator = FactVec::iterator;
+ using const_iterator = FactVec::const_iterator;
- iterator begin() { return FactIDs.begin(); }
+ iterator begin() { return FactIDs.begin(); }
const_iterator begin() const { return FactIDs.begin(); }
- iterator end() { return FactIDs.end(); }
+ iterator end() { return FactIDs.end(); }
const_iterator end() const { return FactIDs.end(); }
bool isEmpty() const { return FactIDs.size() == 0; }
// Return true if the set contains only negative facts
bool isEmpty(FactManager &FactMan) const {
- for (FactID FID : *this) {
+ for (const auto FID : *this) {
if (!FactMan[FID].negative())
return false;
}
@@ -247,28 +271,30 @@
};
class ThreadSafetyAnalyzer;
+
} // namespace
namespace clang {
namespace threadSafety {
+
class BeforeSet {
private:
- typedef SmallVector<const ValueDecl*, 4> BeforeVect;
+ using BeforeVect = SmallVector<const ValueDecl *, 4>;
struct BeforeInfo {
- BeforeInfo() : Visited(0) {}
- BeforeInfo(BeforeInfo &&) = default;
-
BeforeVect Vect;
- int Visited;
+ int Visited = 0;
+
+ BeforeInfo() = default;
+ BeforeInfo(BeforeInfo &&) = default;
};
- typedef llvm::DenseMap<const ValueDecl *, std::unique_ptr<BeforeInfo>>
- BeforeMap;
- typedef llvm::DenseMap<const ValueDecl*, bool> CycleMap;
+ using BeforeMap =
+ llvm::DenseMap<const ValueDecl *, std::unique_ptr<BeforeInfo>>;
+ using CycleMap = llvm::DenseMap<const ValueDecl *, bool>;
public:
- BeforeSet() { }
+ BeforeSet() = default;
BeforeInfo* insertAttrExprs(const ValueDecl* Vd,
ThreadSafetyAnalyzer& Analyzer);
@@ -283,15 +309,18 @@
private:
BeforeMap BMap;
- CycleMap CycMap;
+ CycleMap CycMap;
};
-} // end namespace threadSafety
-} // end namespace clang
+
+} // namespace threadSafety
+} // namespace clang
namespace {
-typedef llvm::ImmutableMap<const NamedDecl*, unsigned> LocalVarContext;
+
class LocalVariableMap;
+using LocalVarContext = llvm::ImmutableMap<const NamedDecl *, unsigned>;
+
/// A side (entry or exit) of a CFG node.
enum CFGBlockSide { CBS_Entry, CBS_Exit };
@@ -299,33 +328,46 @@
/// maintained for each block in the CFG. See LocalVariableMap for more
/// information about the contexts.
struct CFGBlockInfo {
- FactSet EntrySet; // Lockset held at entry to block
- FactSet ExitSet; // Lockset held at exit from block
- LocalVarContext EntryContext; // Context held at entry to block
- LocalVarContext ExitContext; // Context held at exit from block
- SourceLocation EntryLoc; // Location of first statement in block
- SourceLocation ExitLoc; // Location of last statement in block.
- unsigned EntryIndex; // Used to replay contexts later
- bool Reachable; // Is this block reachable?
+ // Lockset held at entry to block
+ FactSet EntrySet;
+
+ // Lockset held at exit from block
+ FactSet ExitSet;
+
+ // Context held at entry to block
+ LocalVarContext EntryContext;
+
+ // Context held at exit from block
+ LocalVarContext ExitContext;
+
+ // Location of first statement in block
+ SourceLocation EntryLoc;
+
+ // Location of last statement in block.
+ SourceLocation ExitLoc;
+
+ // Used to replay contexts later
+ unsigned EntryIndex;
+
+ // Is this block reachable?
+ bool Reachable = false;
const FactSet &getSet(CFGBlockSide Side) const {
return Side == CBS_Entry ? EntrySet : ExitSet;
}
+
SourceLocation getLocation(CFGBlockSide Side) const {
return Side == CBS_Entry ? EntryLoc : ExitLoc;
}
private:
CFGBlockInfo(LocalVarContext EmptyCtx)
- : EntryContext(EmptyCtx), ExitContext(EmptyCtx), Reachable(false)
- { }
+ : EntryContext(EmptyCtx), ExitContext(EmptyCtx) {}
public:
static CFGBlockInfo getEmptyBlockInfo(LocalVariableMap &M);
};
-
-
// A LocalVariableMap maintains a map from local variables to their currently
// valid definitions. It provides SSA-like functionality when traversing the
// CFG. Like SSA, each definition or assignment to a variable is assigned a
@@ -341,7 +383,7 @@
// that Context to look up the definitions of variables.
class LocalVariableMap {
public:
- typedef LocalVarContext Context;
+ using Context = LocalVarContext;
/// A VarDefinition consists of an expression, representing the value of the
/// variable, along with the context in which that expression should be
@@ -351,30 +393,35 @@
public:
friend class LocalVariableMap;
- const NamedDecl *Dec; // The original declaration for this variable.
- const Expr *Exp; // The expression for this variable, OR
- unsigned Ref; // Reference to another VarDefinition
- Context Ctx; // The map with which Exp should be interpreted.
+ // The original declaration for this variable.
+ const NamedDecl *Dec;
+
+ // The expression for this variable, OR
+ const Expr *Exp = nullptr;
+
+ // Reference to another VarDefinition
+ unsigned Ref = 0;
+
+ // The map with which Exp should be interpreted.
+ Context Ctx;
bool isReference() { return !Exp; }
private:
// Create ordinary variable definition
VarDefinition(const NamedDecl *D, const Expr *E, Context C)
- : Dec(D), Exp(E), Ref(0), Ctx(C)
- { }
+ : Dec(D), Exp(E), Ctx(C) {}
// Create reference to previous definition
VarDefinition(const NamedDecl *D, unsigned R, Context C)
- : Dec(D), Exp(nullptr), Ref(R), Ctx(C)
- { }
+ : Dec(D), Ref(R), Ctx(C) {}
};
private:
Context::Factory ContextFactory;
std::vector<VarDefinition> VarDefinitions;
std::vector<unsigned> CtxIndices;
- std::vector<std::pair<Stmt*, Context> > SavedContexts;
+ std::vector<std::pair<Stmt *, Context>> SavedContexts;
public:
LocalVariableMap() {
@@ -471,12 +518,14 @@
std::vector<CFGBlockInfo> &BlockInfo);
protected:
+ friend class VarMapBuilder;
+
// Get the current context index
unsigned getContextIndex() { return SavedContexts.size()-1; }
// Save the current context for later replay
void saveContext(Stmt *S, Context C) {
- SavedContexts.push_back(std::make_pair(S,C));
+ SavedContexts.push_back(std::make_pair(S, C));
}
// Adds a new definition to the given context, and returns a new context.
@@ -533,16 +582,16 @@
Context intersectContexts(Context C1, Context C2);
Context createReferenceContext(Context C);
void intersectBackEdge(Context C1, Context C2);
-
- friend class VarMapBuilder;
};
+} // namespace
// This has to be defined after LocalVariableMap.
CFGBlockInfo CFGBlockInfo::getEmptyBlockInfo(LocalVariableMap &M) {
return CFGBlockInfo(M.getEmptyContext());
}
+namespace {
/// Visitor which builds a LocalVariableMap
class VarMapBuilder : public StmtVisitor<VarMapBuilder> {
@@ -551,12 +600,13 @@
LocalVariableMap::Context Ctx;
VarMapBuilder(LocalVariableMap *VM, LocalVariableMap::Context C)
- : VMap(VM), Ctx(C) {}
+ : VMap(VM), Ctx(C) {}
void VisitDeclStmt(DeclStmt *S);
void VisitBinaryOperator(BinaryOperator *BO);
};
+} // namespace
// Add new local variables to the variable map
void VarMapBuilder::VisitDeclStmt(DeclStmt *S) {
@@ -586,8 +636,8 @@
Expr *LHSExp = BO->getLHS()->IgnoreParenCasts();
// Update the variable map and current context.
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHSExp)) {
- ValueDecl *VDec = DRE->getDecl();
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(LHSExp)) {
+ const ValueDecl *VDec = DRE->getDecl();
if (Ctx.lookup(VDec)) {
if (BO->getOpcode() == BO_Assign)
Ctx = VMap->updateDefinition(VDec, BO->getRHS(), Ctx);
@@ -599,7 +649,6 @@
}
}
-
// Computes the intersection of two contexts. The intersection is the
// set of variables which have the same definition in both contexts;
// variables with different definitions are discarded.
@@ -642,7 +691,6 @@
}
}
-
// Traverse the CFG in topological order, so all predecessors of a block
// (excluding back-edges) are visited before the block itself. At
// each point in the code, we calculate a Context, which holds the set of
@@ -680,7 +728,6 @@
// while (b) { x -> x2, y -> y1 | [1st:] x2=x1; [2nd:] x2=NULL; }
// x = x+1; { x -> x3, y -> y1 | x3 = x2 + 1, ... }
// ... { y -> y1 | x3 = 2, x2 = 1, ... }
-//
void LocalVariableMap::traverseCFG(CFG *CFGraph,
const PostOrderCFGView *SortedGraph,
std::vector<CFGBlockInfo> &BlockInfo) {
@@ -731,12 +778,11 @@
// Visit all the statements in the basic block.
VarMapBuilder VMapBuilder(this, CurrBlockInfo->EntryContext);
- for (CFGBlock::const_iterator BI = CurrBlock->begin(),
- BE = CurrBlock->end(); BI != BE; ++BI) {
- switch (BI->getKind()) {
+ for (const auto &BI : *CurrBlock) {
+ switch (BI.getKind()) {
case CFGElement::Statement: {
- CFGStmt CS = BI->castAs<CFGStmt>();
- VMapBuilder.Visit(const_cast<Stmt*>(CS.getStmt()));
+ CFGStmt CS = BI.castAs<CFGStmt>();
+ VMapBuilder.Visit(const_cast<Stmt *>(CS.getStmt()));
break;
}
default:
@@ -790,10 +836,9 @@
if (CurrBlockInfo->ExitLoc.isValid()) {
// This block contains at least one statement. Find the source location
// of the first statement in the block.
- for (CFGBlock::const_iterator BI = CurrBlock->begin(),
- BE = CurrBlock->end(); BI != BE; ++BI) {
+ for (const auto &BI : *CurrBlock) {
// FIXME: Handle other CFGElement kinds.
- if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>()) {
+ if (Optional<CFGStmt> CS = BI.getAs<CFGStmt>()) {
CurrBlockInfo->EntryLoc = CS->getStmt()->getLocStart();
break;
}
@@ -808,9 +853,12 @@
}
}
+namespace {
+
class LockableFactEntry : public FactEntry {
private:
- bool Managed; ///< managed by ScopedLockable object
+ /// managed by ScopedLockable object
+ bool Managed;
public:
LockableFactEntry(const CapabilityExpr &CE, LockKind LK, SourceLocation Loc,
@@ -857,7 +905,7 @@
handleRemovalFromIntersection(const FactSet &FSet, FactManager &FactMan,
SourceLocation JoinLoc, LockErrorKind LEK,
ThreadSafetyHandler &Handler) const override {
- for (const til::SExpr *UnderlyingMutex : UnderlyingMutexes) {
+ for (const auto *UnderlyingMutex : UnderlyingMutexes) {
if (FSet.findLock(FactMan, CapabilityExpr(UnderlyingMutex, false))) {
// If this scoped lock manages another mutex, and if the underlying
// mutex is still held, then warn about the underlying mutex.
@@ -872,7 +920,7 @@
bool FullyRemove, ThreadSafetyHandler &Handler,
StringRef DiagKind) const override {
assert(!Cp.negative() && "Managing object cannot be negative.");
- for (const til::SExpr *UnderlyingMutex : UnderlyingMutexes) {
+ for (const auto *UnderlyingMutex : UnderlyingMutexes) {
CapabilityExpr UnderCp(UnderlyingMutex, false);
auto UnderEntry = llvm::make_unique<LockableFactEntry>(
!UnderCp, LK_Exclusive, UnlockLoc);
@@ -909,17 +957,17 @@
threadSafety::til::MemRegionRef Arena;
threadSafety::SExprBuilder SxBuilder;
- ThreadSafetyHandler &Handler;
- const CXXMethodDecl *CurrentMethod;
- LocalVariableMap LocalVarMap;
- FactManager FactMan;
+ ThreadSafetyHandler &Handler;
+ const CXXMethodDecl *CurrentMethod;
+ LocalVariableMap LocalVarMap;
+ FactManager FactMan;
std::vector<CFGBlockInfo> BlockInfo;
- BeforeSet* GlobalBeforeSet;
+ BeforeSet *GlobalBeforeSet;
public:
ThreadSafetyAnalyzer(ThreadSafetyHandler &H, BeforeSet* Bset)
- : Arena(&Bpa), SxBuilder(Arena), Handler(H), GlobalBeforeSet(Bset) {}
+ : Arena(&Bpa), SxBuilder(Arena), Handler(H), GlobalBeforeSet(Bset) {}
bool inCurrentScope(const CapabilityExpr &CapE);
@@ -959,6 +1007,7 @@
void runAnalysis(AnalysisDeclContext &AC);
};
+
} // namespace
/// Process acquired_before and acquired_after attributes on Vd.
@@ -975,10 +1024,10 @@
Info = InfoPtr.get();
}
- for (Attr* At : Vd->attrs()) {
+ for (const auto *At : Vd->attrs()) {
switch (At->getKind()) {
case attr::AcquiredBefore: {
- auto *A = cast<AcquiredBeforeAttr>(At);
+ const auto *A = cast<AcquiredBeforeAttr>(At);
// Read exprs from the attribute, and add them to BeforeVect.
for (const auto *Arg : A->args()) {
@@ -986,7 +1035,7 @@
Analyzer.SxBuilder.translateAttrExpr(Arg, nullptr);
if (const ValueDecl *Cpvd = Cp.valueDecl()) {
Info->Vect.push_back(Cpvd);
- auto It = BMap.find(Cpvd);
+ const auto It = BMap.find(Cpvd);
if (It == BMap.end())
insertAttrExprs(Cpvd, Analyzer);
}
@@ -994,7 +1043,7 @@
break;
}
case attr::AcquiredAfter: {
- auto *A = cast<AcquiredAfterAttr>(At);
+ const auto *A = cast<AcquiredAfterAttr>(At);
// Read exprs from the attribute, and add them to BeforeVect.
for (const auto *Arg : A->args()) {
@@ -1055,7 +1104,7 @@
InfoVect.push_back(Info);
Info->Visited = 1;
- for (auto *Vdb : Info->Vect) {
+ for (const auto *Vdb : Info->Vect) {
// Exclude mutexes in our immediate before set.
if (FSet.containsMutexDecl(Analyzer.FactMan, Vdb)) {
StringRef L1 = StartVd->getName();
@@ -1077,12 +1126,10 @@
traverse(StartVd);
- for (auto* Info : InfoVect)
+ for (auto *Info : InfoVect)
Info->Visited = 0;
}
-
-
/// \brief Gets the value decl pointer from DeclRefExprs or MemberExprs.
static const ValueDecl *getValueDecl(const Expr *Exp) {
if (const auto *CE = dyn_cast<ImplicitCastExpr>(Exp))
@@ -1098,10 +1145,11 @@
}
namespace {
+
template <typename Ty>
class has_arg_iterator_range {
- typedef char yes[1];
- typedef char no[2];
+ using yes = char[1];
+ using no = char[2];
template <typename Inner>
static yes& test(Inner *I, decltype(I->args()) * = nullptr);
@@ -1112,6 +1160,7 @@
public:
static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
};
+
} // namespace
static StringRef ClassifyDiagnostic(const CapabilityAttr *A) {
@@ -1163,19 +1212,17 @@
return "mutex";
}
-
-inline bool ThreadSafetyAnalyzer::inCurrentScope(const CapabilityExpr &CapE) {
+bool ThreadSafetyAnalyzer::inCurrentScope(const CapabilityExpr &CapE) {
if (!CurrentMethod)
return false;
- if (auto *P = dyn_cast_or_null<til::Project>(CapE.sexpr())) {
- auto *VD = P->clangDecl();
+ if (const auto *P = dyn_cast_or_null<til::Project>(CapE.sexpr())) {
+ const auto *VD = P->clangDecl();
if (VD)
return VD->getDeclContext() == CurrentMethod->getDeclContext();
}
return false;
}
-
/// \brief Add a new lock to the lockset, warning if the lock is already there.
/// \param ReqAttr -- true if this is part of an initial Requires attribute.
void ThreadSafetyAnalyzer::addLock(FactSet &FSet,
@@ -1214,7 +1261,6 @@
}
}
-
/// \brief Remove a lock from the lockset, warning if the lock is not there.
/// \param UnlockLoc The source location of the unlock (only used in error msg)
void ThreadSafetyAnalyzer::removeLock(FactSet &FSet, const CapabilityExpr &Cp,
@@ -1241,7 +1287,6 @@
DiagKind);
}
-
/// \brief Extract the list of mutexIDs from the attribute on an expression,
/// and push them onto Mtxs, discarding any duplicates.
template <typename AttrType>
@@ -1273,7 +1318,6 @@
}
}
-
/// \brief Extract the list of mutexIDs from a trylock attribute. If the
/// trylock applies to the given edge, then push them onto Mtxs, discarding
/// any duplicates.
@@ -1285,9 +1329,9 @@
Expr *BrE, bool Neg) {
// Find out which branch has the lock
bool branch = false;
- if (CXXBoolLiteralExpr *BLE = dyn_cast_or_null<CXXBoolLiteralExpr>(BrE))
+ if (const auto *BLE = dyn_cast_or_null<CXXBoolLiteralExpr>(BrE))
branch = BLE->getValue();
- else if (IntegerLiteral *ILE = dyn_cast_or_null<IntegerLiteral>(BrE))
+ else if (const auto *ILE = dyn_cast_or_null<IntegerLiteral>(BrE))
branch = ILE->getValue().getBoolValue();
int branchnum = branch ? 0 : 1;
@@ -1307,19 +1351,17 @@
if (isa<CXXNullPtrLiteralExpr>(E) || isa<GNUNullExpr>(E)) {
TCond = false;
return true;
- } else if (CXXBoolLiteralExpr *BLE = dyn_cast<CXXBoolLiteralExpr>(E)) {
+ } else if (const auto *BLE = dyn_cast<CXXBoolLiteralExpr>(E)) {
TCond = BLE->getValue();
return true;
- } else if (IntegerLiteral *ILE = dyn_cast<IntegerLiteral>(E)) {
+ } else if (const auto *ILE = dyn_cast<IntegerLiteral>(E)) {
TCond = ILE->getValue().getBoolValue();
return true;
- } else if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) {
+ } else if (auto *CE = dyn_cast<ImplicitCastExpr>(E))
return getStaticBooleanValue(CE->getSubExpr(), TCond);
- }
return false;
}
-
// If Cond can be traced back to a function call, return the call expression.
// The negate variable should be called with false, and will be set to true
// if the function call is negated, e.g. if (!mu.tryLock(...))
@@ -1329,30 +1371,26 @@
if (!Cond)
return nullptr;
- if (const CallExpr *CallExp = dyn_cast<CallExpr>(Cond)) {
+ if (const auto *CallExp = dyn_cast<CallExpr>(Cond))
return CallExp;
- }
- else if (const ParenExpr *PE = dyn_cast<ParenExpr>(Cond)) {
+ else if (const auto *PE = dyn_cast<ParenExpr>(Cond))
return getTrylockCallExpr(PE->getSubExpr(), C, Negate);
- }
- else if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(Cond)) {
+ else if (const auto *CE = dyn_cast<ImplicitCastExpr>(Cond))
return getTrylockCallExpr(CE->getSubExpr(), C, Negate);
- }
- else if (const ExprWithCleanups* EWC = dyn_cast<ExprWithCleanups>(Cond)) {
+ else if (const auto *EWC = dyn_cast<ExprWithCleanups>(Cond))
return getTrylockCallExpr(EWC->getSubExpr(), C, Negate);
- }
- else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Cond)) {
+ else if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) {
const Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C);
return getTrylockCallExpr(E, C, Negate);
}
- else if (const UnaryOperator *UOP = dyn_cast<UnaryOperator>(Cond)) {
+ else if (const auto *UOP = dyn_cast<UnaryOperator>(Cond)) {
if (UOP->getOpcode() == UO_LNot) {
Negate = !Negate;
return getTrylockCallExpr(UOP->getSubExpr(), C, Negate);
}
return nullptr;
}
- else if (const BinaryOperator *BOP = dyn_cast<BinaryOperator>(Cond)) {
+ else if (const auto *BOP = dyn_cast<BinaryOperator>(Cond)) {
if (BOP->getOpcode() == BO_EQ || BOP->getOpcode() == BO_NE) {
if (BOP->getOpcode() == BO_NE)
Negate = !Negate;
@@ -1373,15 +1411,13 @@
// LHS must have been evaluated in a different block.
return getTrylockCallExpr(BOP->getRHS(), C, Negate);
}
- if (BOP->getOpcode() == BO_LOr) {
+ if (BOP->getOpcode() == BO_LOr)
return getTrylockCallExpr(BOP->getRHS(), C, Negate);
- }
return nullptr;
}
return nullptr;
}
-
/// \brief Find the lockset that holds on the edge between PredBlock
/// and CurrBlock. The edge set is the exit set of PredBlock (passed
/// as the ExitSet parameter) plus any trylocks, which are conditionally held.
@@ -1400,12 +1436,11 @@
const LocalVarContext &LVarCtx = PredBlockInfo->ExitContext;
StringRef CapDiagKind = "mutex";
- CallExpr *Exp =
- const_cast<CallExpr*>(getTrylockCallExpr(Cond, LVarCtx, Negate));
+ auto *Exp = const_cast<CallExpr *>(getTrylockCallExpr(Cond, LVarCtx, Negate));
if (!Exp)
return;
- NamedDecl *FunDecl = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
+ auto *FunDecl = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
if(!FunDecl || !FunDecl->hasAttrs())
return;
@@ -1413,19 +1448,17 @@
CapExprSet SharedLocksToAdd;
// If the condition is a call to a Trylock function, then grab the attributes
- for (auto *Attr : FunDecl->attrs()) {
+ for (const auto *Attr : FunDecl->attrs()) {
switch (Attr->getKind()) {
case attr::ExclusiveTrylockFunction: {
- ExclusiveTrylockFunctionAttr *A =
- cast<ExclusiveTrylockFunctionAttr>(Attr);
+ const auto *A = cast<ExclusiveTrylockFunctionAttr>(Attr);
getMutexIDs(ExclusiveLocksToAdd, A, Exp, FunDecl,
PredBlock, CurrBlock, A->getSuccessValue(), Negate);
CapDiagKind = ClassifyDiagnostic(A);
break;
}
case attr::SharedTrylockFunction: {
- SharedTrylockFunctionAttr *A =
- cast<SharedTrylockFunctionAttr>(Attr);
+ const auto *A = cast<SharedTrylockFunctionAttr>(Attr);
getMutexIDs(SharedLocksToAdd, A, Exp, FunDecl,
PredBlock, CurrBlock, A->getSuccessValue(), Negate);
CapDiagKind = ClassifyDiagnostic(A);
@@ -1449,6 +1482,7 @@
}
namespace {
+
/// \brief We use this class to visit different types of expressions in
/// CFGBlocks, and build up the lockset.
/// An expression may cause us to add or remove locks from the lockset, or else
@@ -1478,12 +1512,8 @@
public:
BuildLockset(ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info)
- : StmtVisitor<BuildLockset>(),
- Analyzer(Anlzr),
- FSet(Info.EntrySet),
- LVarCtx(Info.EntryContext),
- CtxIndex(Info.EntryIndex)
- {}
+ : StmtVisitor<BuildLockset>(), Analyzer(Anlzr), FSet(Info.EntrySet),
+ LVarCtx(Info.EntryContext), CtxIndex(Info.EntryIndex) {}
void VisitUnaryOperator(UnaryOperator *UO);
void VisitBinaryOperator(BinaryOperator *BO);
@@ -1492,6 +1522,7 @@
void VisitCXXConstructExpr(CXXConstructExpr *Exp);
void VisitDeclStmt(DeclStmt *S);
};
+
} // namespace
/// \brief Warn if the LSet does not contain a lock sufficient to protect access
@@ -1600,19 +1631,19 @@
break;
}
- if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Exp)) {
+ if (const auto *UO = dyn_cast<UnaryOperator>(Exp)) {
// For dereferences
- if (UO->getOpcode() == clang::UO_Deref)
+ if (UO->getOpcode() == UO_Deref)
checkPtAccess(UO->getSubExpr(), AK, POK);
return;
}
- if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(Exp)) {
+ if (const auto *AE = dyn_cast<ArraySubscriptExpr>(Exp)) {
checkPtAccess(AE->getLHS(), AK, POK);
return;
}
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(Exp)) {
+ if (const auto *ME = dyn_cast<MemberExpr>(Exp)) {
if (ME->isArrow())
checkPtAccess(ME->getBase(), AK, POK);
else
@@ -1632,17 +1663,16 @@
ClassifyDiagnostic(I), Loc);
}
-
/// \brief Checks pt_guarded_by and pt_guarded_var attributes.
/// POK is the same operationKind that was passed to checkAccess.
void BuildLockset::checkPtAccess(const Expr *Exp, AccessKind AK,
ProtectedOperationKind POK) {
while (true) {
- if (const ParenExpr *PE = dyn_cast<ParenExpr>(Exp)) {
+ if (const auto *PE = dyn_cast<ParenExpr>(Exp)) {
Exp = PE->getSubExpr();
continue;
}
- if (const CastExpr *CE = dyn_cast<CastExpr>(Exp)) {
+ if (const auto *CE = dyn_cast<CastExpr>(Exp)) {
if (CE->getCastKind() == CK_ArrayToPointerDecay) {
// If it's an actual array, and not a pointer, then it's elements
// are protected by GUARDED_BY, not PT_GUARDED_BY;
@@ -1692,7 +1722,7 @@
// Figure out if we're constructing an object of scoped lockable class
bool isScopedVar = false;
if (VD) {
- if (const CXXConstructorDecl *CD = dyn_cast<const CXXConstructorDecl>(D)) {
+ if (const auto *CD = dyn_cast<const CXXConstructorDecl>(D)) {
const CXXRecordDecl* PD = CD->getParent();
if (PD && PD->hasAttr<ScopedLockableAttr>())
isScopedVar = true;
@@ -1700,12 +1730,12 @@
}
for(Attr *Atconst : D->attrs()) {
- Attr* At = const_cast<Attr*>(Atconst);
+ auto *At = const_cast<Attr *>(Atconst);
switch (At->getKind()) {
// When we encounter a lock function, we need to add the lock to our
// lockset.
case attr::AcquireCapability: {
- auto *A = cast<AcquireCapabilityAttr>(At);
+ const auto *A = cast<AcquireCapabilityAttr>(At);
Analyzer->getMutexIDs(A->isShared() ? SharedLocksToAdd
: ExclusiveLocksToAdd,
A, Exp, D, VD);
@@ -1718,7 +1748,7 @@
// a warning if it is already there, and will not generate a warning
// if it is not removed.
case attr::AssertExclusiveLock: {
- AssertExclusiveLockAttr *A = cast<AssertExclusiveLockAttr>(At);
+ const auto *A = cast<AssertExclusiveLockAttr>(At);
CapExprSet AssertLocks;
Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
@@ -1730,7 +1760,7 @@
break;
}
case attr::AssertSharedLock: {
- AssertSharedLockAttr *A = cast<AssertSharedLockAttr>(At);
+ const auto *A = cast<AssertSharedLockAttr>(At);
CapExprSet AssertLocks;
Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
@@ -1743,7 +1773,7 @@
}
case attr::AssertCapability: {
- AssertCapabilityAttr *A = cast<AssertCapabilityAttr>(At);
+ const auto *A = cast<AssertCapabilityAttr>(At);
CapExprSet AssertLocks;
Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
for (const auto &AssertLock : AssertLocks)
@@ -1759,7 +1789,7 @@
// When we encounter an unlock function, we need to remove unlocked
// mutexes from the lockset, and flag a warning if they are not there.
case attr::ReleaseCapability: {
- auto *A = cast<ReleaseCapabilityAttr>(At);
+ const auto *A = cast<ReleaseCapabilityAttr>(At);
if (A->isGeneric())
Analyzer->getMutexIDs(GenericLocksToRemove, A, Exp, D, VD);
else if (A->isShared())
@@ -1772,7 +1802,7 @@
}
case attr::RequiresCapability: {
- RequiresCapabilityAttr *A = cast<RequiresCapabilityAttr>(At);
+ const auto *A = cast<RequiresCapabilityAttr>(At);
for (auto *Arg : A->args()) {
warnIfMutexNotHeld(D, Exp, A->isShared() ? AK_Read : AK_Written, Arg,
POK_FunctionCall, ClassifyDiagnostic(A),
@@ -1788,7 +1818,7 @@
}
case attr::LocksExcluded: {
- LocksExcludedAttr *A = cast<LocksExcludedAttr>(At);
+ const auto *A = cast<LocksExcludedAttr>(At);
for (auto *Arg : A->args())
warnIfMutexHeld(D, Exp, Arg, ClassifyDiagnostic(A));
break;
@@ -1838,19 +1868,17 @@
Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Generic, CapDiagKind);
}
-
/// \brief For unary operations which read and write a variable, we need to
/// check whether we hold any required mutexes. Reads are checked in
/// VisitCastExpr.
void BuildLockset::VisitUnaryOperator(UnaryOperator *UO) {
switch (UO->getOpcode()) {
- case clang::UO_PostDec:
- case clang::UO_PostInc:
- case clang::UO_PreDec:
- case clang::UO_PreInc: {
+ case UO_PostDec:
+ case UO_PostInc:
+ case UO_PreDec:
+ case UO_PreInc:
checkAccess(UO->getSubExpr(), AK_Written);
break;
- }
default:
break;
}
@@ -1869,7 +1897,6 @@
checkAccess(BO->getLHS(), AK_Written);
}
-
/// Whenever we do an LValue to Rvalue cast, we are reading a variable and
/// need to ensure we hold any required mutexes.
/// FIXME: Deal with non-primitive types.
@@ -1879,23 +1906,21 @@
checkAccess(CE->getSubExpr(), AK_Read);
}
-
void BuildLockset::VisitCallExpr(CallExpr *Exp) {
bool ExamineArgs = true;
bool OperatorFun = false;
- if (CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(Exp)) {
- MemberExpr *ME = dyn_cast<MemberExpr>(CE->getCallee());
+ if (const auto *CE = dyn_cast<CXXMemberCallExpr>(Exp)) {
+ const auto *ME = dyn_cast<MemberExpr>(CE->getCallee());
// ME can be null when calling a method pointer
- CXXMethodDecl *MD = CE->getMethodDecl();
+ const CXXMethodDecl *MD = CE->getMethodDecl();
if (ME && MD) {
if (ME->isArrow()) {
- if (MD->isConst()) {
+ if (MD->isConst())
checkPtAccess(CE->getImplicitObjectArgument(), AK_Read);
- } else { // FIXME -- should be AK_Written
+ else // FIXME -- should be AK_Written
checkPtAccess(CE->getImplicitObjectArgument(), AK_Read);
- }
} else {
if (MD->isConst())
checkAccess(CE->getImplicitObjectArgument(), AK_Read);
@@ -1903,7 +1928,7 @@
checkAccess(CE->getImplicitObjectArgument(), AK_Read);
}
}
- } else if (CXXOperatorCallExpr *OE = dyn_cast<CXXOperatorCallExpr>(Exp)) {
+ } else if (const auto *OE = dyn_cast<CXXOperatorCallExpr>(Exp)) {
OperatorFun = true;
auto OEop = OE->getOperator();
@@ -1938,13 +1963,11 @@
if (ExamineArgs) {
if (FunctionDecl *FD = Exp->getDirectCallee()) {
-
// NO_THREAD_SAFETY_ANALYSIS does double duty here. Normally it
// only turns off checking within the body of a function, but we also
// use it to turn off checking in arguments to the function. This
// could result in some false negatives, but the alternative is to
// create yet another attribute.
- //
if (!FD->hasAttr<NoThreadSafetyAnalysisAttr>()) {
unsigned Fn = FD->getNumParams();
unsigned Cn = Exp->getNumArgs();
@@ -1976,7 +1999,7 @@
}
}
- NamedDecl *D = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
+ auto *D = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
if(!D || !D->hasAttrs())
return;
handleCall(Exp, D);
@@ -1998,7 +2021,7 @@
// pick the first declared such constructor rather than trying to guess which
// one is more appropriate.
CXXConstructorDecl *CopyCtor = nullptr;
- for (CXXConstructorDecl *Ctor : RD->ctors()) {
+ for (auto *Ctor : RD->ctors()) {
if (Ctor->isDeleted())
continue;
if (Ctor->isMoveConstructor())
@@ -2023,7 +2046,7 @@
LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, S, LVarCtx);
for (auto *D : S->getDeclGroup()) {
- if (VarDecl *VD = dyn_cast_or_null<VarDecl>(D)) {
+ if (auto *VD = dyn_cast_or_null<VarDecl>(D)) {
Expr *E = VD->getInit();
if (!E)
continue;
@@ -2035,8 +2058,8 @@
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
E = BTE->getSubExpr();
- if (CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E)) {
- NamedDecl *CtorD = dyn_cast_or_null<NamedDecl>(CE->getConstructor());
+ if (const auto *CE = dyn_cast<CXXConstructExpr>(E)) {
+ const auto *CtorD = dyn_cast_or_null<NamedDecl>(CE->getConstructor());
if (!CtorD || !CtorD->hasAttrs())
continue;
handleCall(E, CtorD, VD);
@@ -2058,8 +2081,6 @@
}
}
-
-
/// \brief Compute the intersection of two locksets and issue warnings for any
/// locks in the symmetric difference.
///
@@ -2122,7 +2143,6 @@
}
}
-
// Return true if block B never continues to its successors.
static bool neverReturns(const CFGBlock *B) {
if (B->hasNoReturnElement())
@@ -2138,7 +2158,6 @@
return false;
}
-
/// \brief Check a function's CFG for thread-safety violations.
///
/// We traverse the blocks in the CFG, compute the set of mutexes that are held
@@ -2156,7 +2175,7 @@
CFG *CFGraph = walker.getGraph();
const NamedDecl *D = walker.getDecl();
- const FunctionDecl *CurrentFunction = dyn_cast<FunctionDecl>(D);
+ const auto *CurrentFunction = dyn_cast<FunctionDecl>(D);
CurrentMethod = dyn_cast<CXXMethodDecl>(D);
if (D->hasAttr<NoThreadSafetyAnalysisAttr>())
@@ -2275,7 +2294,6 @@
SmallVector<CFGBlock *, 8> SpecialBlocks;
for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(),
PE = CurrBlock->pred_end(); PI != PE; ++PI) {
-
// if *PI -> CurrBlock is a back edge
if (*PI == nullptr || !VisitedBlocks.alreadySet(*PI))
continue;
@@ -2352,24 +2370,23 @@
BuildLockset LocksetBuilder(this, *CurrBlockInfo);
// Visit all the statements in the basic block.
- for (CFGBlock::const_iterator BI = CurrBlock->begin(),
- BE = CurrBlock->end(); BI != BE; ++BI) {
- switch (BI->getKind()) {
+ for (const auto &BI : *CurrBlock) {
+ switch (BI.getKind()) {
case CFGElement::Statement: {
- CFGStmt CS = BI->castAs<CFGStmt>();
- LocksetBuilder.Visit(const_cast<Stmt*>(CS.getStmt()));
+ CFGStmt CS = BI.castAs<CFGStmt>();
+ LocksetBuilder.Visit(const_cast<Stmt *>(CS.getStmt()));
break;
}
// Ignore BaseDtor, MemberDtor, and TemporaryDtor for now.
case CFGElement::AutomaticObjectDtor: {
- CFGAutomaticObjDtor AD = BI->castAs<CFGAutomaticObjDtor>();
- CXXDestructorDecl *DD = const_cast<CXXDestructorDecl *>(
+ CFGAutomaticObjDtor AD = BI.castAs<CFGAutomaticObjDtor>();
+ auto *DD = const_cast<CXXDestructorDecl *>(
AD.getDestructorDecl(AC.getASTContext()));
if (!DD->hasAttrs())
break;
// Create a dummy expression,
- VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl());
+ auto *VD = const_cast<VarDecl *>(AD.getVarDecl());
DeclRefExpr DRE(VD, false, VD->getType().getNonReferenceType(),
VK_LValue, AD.getTriggerStmt()->getLocEnd());
LocksetBuilder.handleCall(&DRE, DD);
@@ -2387,7 +2404,6 @@
// Lockset held at the beginning of FirstLoopBlock in the EntryLockSets map.
for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
SE = CurrBlock->succ_end(); SI != SE; ++SI) {
-
// if CurrBlock -> *SI is *not* a back edge
if (*SI == nullptr || !VisitedBlocks.alreadySet(*SI))
continue;
@@ -2435,7 +2451,6 @@
Handler.leaveFunction(CurrentFunction);
}
-
/// \brief Check a function's CFG for thread-safety violations.
///
/// We traverse the blocks in the CFG, compute the set of mutexes that are held
diff --git a/lib/Analysis/ThreadSafetyCommon.cpp b/lib/Analysis/ThreadSafetyCommon.cpp
index 99284f0..1376a89 100644
--- a/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/lib/Analysis/ThreadSafetyCommon.cpp
@@ -1,4 +1,4 @@
-//===- ThreadSafetyCommon.cpp -----------------------------------*- C++ -*-===//
+//===- ThreadSafetyCommon.cpp ---------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,24 +13,32 @@
#include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtCXX.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
-#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
-#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
-#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
#include <algorithm>
+#include <cassert>
+#include <string>
+#include <utility>
using namespace clang;
using namespace threadSafety;
// From ThreadSafetyUtil.h
-std::string threadSafety::getSourceLiteralString(const clang::Expr *CE) {
+std::string threadSafety::getSourceLiteralString(const Expr *CE) {
switch (CE->getStmtClass()) {
case Stmt::IntegerLiteralClass:
return cast<IntegerLiteral>(CE)->getValue().toString(10, true);
@@ -59,7 +67,7 @@
return false;
}
-typedef SExprBuilder::CallingContext CallingContext;
+using CallingContext = SExprBuilder::CallingContext;
til::SExpr *SExprBuilder::lookupStmt(const Stmt *S) {
auto It = SMap.find(S);
@@ -74,7 +82,7 @@
}
static bool isCalleeArrow(const Expr *E) {
- const MemberExpr *ME = dyn_cast<MemberExpr>(E->IgnoreParenCasts());
+ const auto *ME = dyn_cast<MemberExpr>(E->IgnoreParenCasts());
return ME ? ME->isArrow() : false;
}
@@ -97,20 +105,18 @@
// Examine DeclExp to find SelfArg and FunArgs, which are used to substitute
// for formal parameters when we call buildMutexID later.
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(DeclExp)) {
+ if (const auto *ME = dyn_cast<MemberExpr>(DeclExp)) {
Ctx.SelfArg = ME->getBase();
Ctx.SelfArrow = ME->isArrow();
- } else if (const CXXMemberCallExpr *CE =
- dyn_cast<CXXMemberCallExpr>(DeclExp)) {
+ } else if (const auto *CE = dyn_cast<CXXMemberCallExpr>(DeclExp)) {
Ctx.SelfArg = CE->getImplicitObjectArgument();
Ctx.SelfArrow = isCalleeArrow(CE->getCallee());
Ctx.NumArgs = CE->getNumArgs();
Ctx.FunArgs = CE->getArgs();
- } else if (const CallExpr *CE = dyn_cast<CallExpr>(DeclExp)) {
+ } else if (const auto *CE = dyn_cast<CallExpr>(DeclExp)) {
Ctx.NumArgs = CE->getNumArgs();
Ctx.FunArgs = CE->getArgs();
- } else if (const CXXConstructExpr *CE =
- dyn_cast<CXXConstructExpr>(DeclExp)) {
+ } else if (const auto *CE = dyn_cast<CXXConstructExpr>(DeclExp)) {
Ctx.SelfArg = nullptr; // Will be set below
Ctx.NumArgs = CE->getNumArgs();
Ctx.FunArgs = CE->getArgs();
@@ -147,7 +153,7 @@
if (!AttrExp)
return CapabilityExpr(nullptr, false);
- if (auto* SLit = dyn_cast<StringLiteral>(AttrExp)) {
+ if (const auto* SLit = dyn_cast<StringLiteral>(AttrExp)) {
if (SLit->getString() == StringRef("*"))
// The "*" expr is a universal lock, which essentially turns off
// checks until it is removed from the lockset.
@@ -158,13 +164,13 @@
}
bool Neg = false;
- if (auto *OE = dyn_cast<CXXOperatorCallExpr>(AttrExp)) {
+ if (const auto *OE = dyn_cast<CXXOperatorCallExpr>(AttrExp)) {
if (OE->getOperator() == OO_Exclaim) {
Neg = true;
AttrExp = OE->getArg(0);
}
}
- else if (auto *UO = dyn_cast<UnaryOperator>(AttrExp)) {
+ else if (const auto *UO = dyn_cast<UnaryOperator>(AttrExp)) {
if (UO->getOpcode() == UO_LNot) {
Neg = true;
AttrExp = UO->getSubExpr();
@@ -179,7 +185,7 @@
return CapabilityExpr(nullptr, false);
// Hack to deal with smart pointers -- strip off top-level pointer casts.
- if (auto *CE = dyn_cast_or_null<til::Cast>(E)) {
+ if (const auto *CE = dyn_cast_or_null<til::Cast>(E)) {
if (CE->castOpcode() == til::CAST_objToPtr)
return CapabilityExpr(CE->expr(), Neg);
}
@@ -254,7 +260,7 @@
default:
break;
}
- if (const CastExpr *CE = dyn_cast<CastExpr>(S))
+ if (const auto *CE = dyn_cast<CastExpr>(S))
return translateCastExpr(CE, Ctx);
return new (Arena) til::Undefined(S);
@@ -262,11 +268,11 @@
til::SExpr *SExprBuilder::translateDeclRefExpr(const DeclRefExpr *DRE,
CallingContext *Ctx) {
- const ValueDecl *VD = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
+ const auto *VD = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
// Function parameters require substitution and/or renaming.
- if (const ParmVarDecl *PV = dyn_cast_or_null<ParmVarDecl>(VD)) {
- const FunctionDecl *FD =
+ if (const auto *PV = dyn_cast_or_null<ParmVarDecl>(VD)) {
+ const auto *FD =
cast<FunctionDecl>(PV->getDeclContext())->getCanonicalDecl();
unsigned I = PV->getFunctionScopeIndex();
@@ -294,13 +300,13 @@
}
static const ValueDecl *getValueDeclFromSExpr(const til::SExpr *E) {
- if (auto *V = dyn_cast<til::Variable>(E))
+ if (const auto *V = dyn_cast<til::Variable>(E))
return V->clangDecl();
- if (auto *Ph = dyn_cast<til::Phi>(E))
+ if (const auto *Ph = dyn_cast<til::Phi>(E))
return Ph->clangDecl();
- if (auto *P = dyn_cast<til::Project>(E))
+ if (const auto *P = dyn_cast<til::Project>(E))
return P->clangDecl();
- if (auto *L = dyn_cast<til::LiteralPtr>(E))
+ if (const auto *L = dyn_cast<til::LiteralPtr>(E))
return L->clangDecl();
return nullptr;
}
@@ -309,7 +315,7 @@
auto *VD = getValueDeclFromSExpr(E);
if (VD && VD->getType()->isPointerType())
return true;
- if (auto *C = dyn_cast<til::Cast>(E))
+ if (const auto *C = dyn_cast<til::Cast>(E))
return C->castOpcode() == til::CAST_objToPtr;
return false;
@@ -333,9 +339,8 @@
til::SExpr *BE = translate(ME->getBase(), Ctx);
til::SExpr *E = new (Arena) til::SApply(BE);
- const ValueDecl *D =
- cast<ValueDecl>(ME->getMemberDecl()->getCanonicalDecl());
- if (auto *VD = dyn_cast<CXXMethodDecl>(D))
+ const auto *D = cast<ValueDecl>(ME->getMemberDecl()->getCanonicalDecl());
+ if (const auto *VD = dyn_cast<CXXMethodDecl>(D))
D = getFirstVirtualDecl(VD);
til::Project *P = new (Arena) til::Project(E, D);
@@ -356,7 +361,7 @@
LRCallCtx.SelfArg = SelfE;
LRCallCtx.NumArgs = CE->getNumArgs();
LRCallCtx.FunArgs = CE->getArgs();
- return const_cast<til::SExpr*>(
+ return const_cast<til::SExpr *>(
translateAttrExpr(At->getArg(), &LRCallCtx).sexpr());
}
}
@@ -407,10 +412,10 @@
case UO_PreDec:
return new (Arena) til::Undefined(UO);
- case UO_AddrOf: {
+ case UO_AddrOf:
if (CapabilityExprMode) {
// interpret &Graph::mu_ as an existential.
- if (DeclRefExpr* DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr())) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr())) {
if (DRE->getDecl()->isCXXInstanceMember()) {
// This is a pointer-to-member expression, e.g. &MyClass::mu_.
// We interpret this syntax specially, as a wildcard.
@@ -421,7 +426,6 @@
}
// otherwise, & is a no-op
return translate(UO->getSubExpr(), Ctx);
- }
// We treat these as no-ops
case UO_Deref:
@@ -470,7 +474,7 @@
const ValueDecl *VD = nullptr;
til::SExpr *CV = nullptr;
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHS)) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
VD = DRE->getDecl();
CV = lookupVarDecl(VD);
}
@@ -533,10 +537,10 @@
til::SExpr *SExprBuilder::translateCastExpr(const CastExpr *CE,
CallingContext *Ctx) {
- clang::CastKind K = CE->getCastKind();
+ CastKind K = CE->getCastKind();
switch (K) {
case CK_LValueToRValue: {
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
til::SExpr *E0 = lookupVarDecl(DRE->getDecl());
if (E0)
return E0;
@@ -584,16 +588,15 @@
til::SExpr *
SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) {
DeclGroupRef DGrp = S->getDeclGroup();
- for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
- if (VarDecl *VD = dyn_cast_or_null<VarDecl>(*I)) {
+ for (auto I : DGrp) {
+ if (auto *VD = dyn_cast_or_null<VarDecl>(I)) {
Expr *E = VD->getInit();
til::SExpr* SE = translate(E, Ctx);
// Add local variables with trivial type to the variable map
QualType T = VD->getType();
- if (T.isTrivialType(VD->getASTContext())) {
+ if (T.isTrivialType(VD->getASTContext()))
return addVarDecl(VD, SE);
- }
else {
// TODO: add alloca
}
@@ -632,7 +635,7 @@
static void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD) {
if (!E)
return;
- if (til::Variable *V = dyn_cast<til::Variable>(E)) {
+ if (auto *V = dyn_cast<til::Variable>(E)) {
if (!V->clangDecl())
V->setClangDecl(VD);
}
@@ -672,7 +675,7 @@
if (CurrE->block() == CurrentBB) {
// We already have a Phi node in the current block,
// so just add the new variable to the Phi node.
- til::Phi *Ph = dyn_cast<til::Phi>(CurrE);
+ auto *Ph = dyn_cast<til::Phi>(CurrE);
assert(Ph && "Expecting Phi node.");
if (E)
Ph->values()[ArgIndex] = E;
@@ -690,9 +693,8 @@
Ph->setClangDecl(CurrentLVarMap[i].first);
// If E is from a back-edge, or either E or CurrE are incomplete, then
// mark this node as incomplete; we may need to remove it later.
- if (!E || isIncompletePhi(E) || isIncompletePhi(CurrE)) {
+ if (!E || isIncompletePhi(E) || isIncompletePhi(CurrE))
Ph->setStatus(til::Phi::PH_Incomplete);
- }
// Add Phi node to current block, and update CurrentLVarMap[i]
CurrentArguments.push_back(Ph);
@@ -721,7 +723,7 @@
unsigned MSz = Map.size();
unsigned Sz = std::min(ESz, MSz);
- for (unsigned i=0; i<Sz; ++i) {
+ for (unsigned i = 0; i < Sz; ++i) {
if (CurrentLVarMap[i].first != Map[i].first) {
// We've reached the end of variables in common.
CurrentLVarMap.makeWritable();
@@ -758,9 +760,8 @@
unsigned Sz = CurrentLVarMap.size();
unsigned NPreds = CurrentBB->numPredecessors();
- for (unsigned i=0; i < Sz; ++i) {
+ for (unsigned i = 0; i < Sz; ++i)
makePhiNodeVar(i, NPreds, nullptr);
- }
}
// Update the phi nodes that were initially created for a back edge
@@ -772,7 +773,7 @@
assert(ArgIndex > 0 && ArgIndex < BB->numPredecessors());
for (til::SExpr *PE : BB->arguments()) {
- til::Phi *Ph = dyn_cast_or_null<til::Phi>(PE);
+ auto *Ph = dyn_cast_or_null<til::Phi>(PE);
assert(Ph && "Expecting Phi Node.");
assert(Ph->values()[ArgIndex] == nullptr && "Wrong index for back edge.");
diff --git a/lib/Analysis/ThreadSafetyTIL.cpp b/lib/Analysis/ThreadSafetyTIL.cpp
index cd7cdc6..798bbfb 100644
--- a/lib/Analysis/ThreadSafetyTIL.cpp
+++ b/lib/Analysis/ThreadSafetyTIL.cpp
@@ -1,4 +1,4 @@
-//===- ThreadSafetyTIL.cpp -------------------------------------*- C++ --*-===//
+//===- ThreadSafetyTIL.cpp ------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,7 +8,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
-#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstddef>
+
using namespace clang;
using namespace threadSafety;
using namespace til;
@@ -19,7 +23,7 @@
case UOP_BitNot: return "~";
case UOP_LogicNot: return "!";
}
- return "";
+ return {};
}
StringRef til::getBinaryOpcodeString(TIL_BinaryOpcode Op) {
@@ -42,10 +46,9 @@
case BOP_LogicAnd: return "&&";
case BOP_LogicOr: return "||";
}
- return "";
+ return {};
}
-
SExpr* Future::force() {
Status = FS_evaluating;
Result = compute();
@@ -53,13 +56,12 @@
return Result;
}
-
unsigned BasicBlock::addPredecessor(BasicBlock *Pred) {
unsigned Idx = Predecessors.size();
Predecessors.reserveCheck(1, Arena);
Predecessors.push_back(Pred);
- for (SExpr *E : Args) {
- if (Phi* Ph = dyn_cast<Phi>(E)) {
+ for (auto *E : Args) {
+ if (auto *Ph = dyn_cast<Phi>(E)) {
Ph->values().reserveCheck(1, Arena);
Ph->values().push_back(nullptr);
}
@@ -67,28 +69,26 @@
return Idx;
}
-
void BasicBlock::reservePredecessors(unsigned NumPreds) {
Predecessors.reserve(NumPreds, Arena);
- for (SExpr *E : Args) {
- if (Phi* Ph = dyn_cast<Phi>(E)) {
+ for (auto *E : Args) {
+ if (auto *Ph = dyn_cast<Phi>(E)) {
Ph->values().reserve(NumPreds, Arena);
}
}
}
-
// If E is a variable, then trace back through any aliases or redundant
// Phi nodes to find the canonical definition.
const SExpr *til::getCanonicalVal(const SExpr *E) {
while (true) {
- if (auto *V = dyn_cast<Variable>(E)) {
+ if (const auto *V = dyn_cast<Variable>(E)) {
if (V->kind() == Variable::VK_Let) {
E = V->definition();
continue;
}
}
- if (const Phi *Ph = dyn_cast<Phi>(E)) {
+ if (const auto *Ph = dyn_cast<Phi>(E)) {
if (Ph->status() == Phi::PH_SingleVal) {
E = Ph->values()[0];
continue;
@@ -99,7 +99,6 @@
return E;
}
-
// If E is a variable, then trace back through any aliases or redundant
// Phi nodes to find the canonical definition.
// The non-const version will simplify incomplete Phi nodes.
@@ -129,7 +128,6 @@
}
}
-
// Trace the arguments of an incomplete Phi node to see if they have the same
// canonical definition. If so, mark the Phi node as redundant.
// getCanonicalVal() will recursively call simplifyIncompletePhi().
@@ -140,7 +138,7 @@
Ph->setStatus(Phi::PH_MultiVal);
SExpr *E0 = simplifyToCanonicalVal(Ph->values()[0]);
- for (unsigned i=1, n=Ph->values().size(); i<n; ++i) {
+ for (unsigned i = 1, n = Ph->values().size(); i < n; ++i) {
SExpr *Ei = simplifyToCanonicalVal(Ph->values()[i]);
if (Ei == Ph)
continue; // Recursive reference to itself. Don't count.
@@ -151,7 +149,6 @@
Ph->setStatus(Phi::PH_SingleVal);
}
-
// Renumbers the arguments and instructions to have unique, sequential IDs.
int BasicBlock::renumberInstrs(int ID) {
for (auto *Arg : Args)
@@ -166,7 +163,7 @@
// Each block will be written into the Blocks array in order, and its BlockID
// will be set to the index in the array. Sorting should start from the entry
// block, and ID should be the total number of blocks.
-int BasicBlock::topologicalSort(SimpleArray<BasicBlock*>& Blocks, int ID) {
+int BasicBlock::topologicalSort(SimpleArray<BasicBlock *> &Blocks, int ID) {
if (Visited) return ID;
Visited = true;
for (auto *Block : successors())
@@ -258,7 +255,6 @@
PostDominatorNode.SizeOfSubTree = 1;
}
-
// Renumber instructions in all blocks
void SCFG::renumberInstrs() {
int InstrID = 0;
@@ -266,7 +262,6 @@
InstrID = Block->renumberInstrs(InstrID);
}
-
static inline void computeNodeSize(BasicBlock *B,
BasicBlock::TopologyNode BasicBlock::*TN) {
BasicBlock::TopologyNode *N = &(B->*TN);
@@ -287,7 +282,6 @@
}
}
-
// Normalizes a CFG. Normalization has a few major components:
// 1) Removing unreachable blocks.
// 2) Computing dominators and post-dominators
diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp
index 5f11d8a..feccf84 100644
--- a/lib/Analysis/UninitializedValues.cpp
+++ b/lib/Analysis/UninitializedValues.cpp
@@ -1,4 +1,4 @@
-//==- UninitializedValues.cpp - Find Uninitialized Values -------*- C++ --*-==//
+//===- UninitializedValues.cpp - Find Uninitialized Values ----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,23 +11,31 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/ASTContext.h"
+#include "clang/Analysis/Analyses/UninitializedValues.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
-#include "clang/Analysis/Analyses/UninitializedValues.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PackedVector.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/SaveAndRestore.h"
-#include <utility>
+#include "llvm/Support/Casting.h"
+#include <algorithm>
+#include <cassert>
using namespace clang;
@@ -48,10 +56,12 @@
//====------------------------------------------------------------------------//
namespace {
+
class DeclToIndex {
llvm::DenseMap<const VarDecl *, unsigned> map;
+
public:
- DeclToIndex() {}
+ DeclToIndex() = default;
/// Compute the actual mapping from declarations to bits.
void computeMap(const DeclContext &dc);
@@ -62,7 +72,8 @@
/// Returns the bit vector index for a given declaration.
Optional<unsigned> getValueIndex(const VarDecl *d) const;
};
-}
+
+} // namespace
void DeclToIndex::computeMap(const DeclContext &dc) {
unsigned count = 0;
@@ -96,25 +107,28 @@
static bool isUninitialized(const Value v) {
return v >= Uninitialized;
}
+
static bool isAlwaysUninit(const Value v) {
return v == Uninitialized;
}
namespace {
-typedef llvm::PackedVector<Value, 2, llvm::SmallBitVector> ValueVector;
+using ValueVector = llvm::PackedVector<Value, 2, llvm::SmallBitVector>;
class CFGBlockValues {
const CFG &cfg;
SmallVector<ValueVector, 8> vals;
ValueVector scratch;
DeclToIndex declToIndex;
+
public:
CFGBlockValues(const CFG &cfg);
unsigned getNumEntries() const { return declToIndex.size(); }
void computeSetOfDeclarations(const DeclContext &dc);
+
ValueVector &getValueVector(const CFGBlock *block) {
return vals[block->getBlockID()];
}
@@ -138,7 +152,8 @@
return getValueVector(block)[idx.getValue()];
}
};
-} // end anonymous namespace
+
+} // namespace
CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) {}
@@ -150,17 +165,16 @@
if (!n)
return;
vals.resize(n);
- for (unsigned i = 0; i < n; ++i)
- vals[i].resize(decls);
+ for (auto &val : vals)
+ val.resize(decls);
}
#if DEBUG_LOGGING
static void printVector(const CFGBlock *block, ValueVector &bv,
unsigned num) {
llvm::errs() << block->getBlockID() << " :";
- for (unsigned i = 0; i < bv.size(); ++i) {
- llvm::errs() << ' ' << bv[i];
- }
+ for (const auto &i : bv)
+ llvm::errs() << ' ' << i;
llvm::errs() << " : " << num << '\n';
}
#endif
@@ -204,28 +218,31 @@
//====------------------------------------------------------------------------//
namespace {
+
class DataflowWorklist {
PostOrderCFGView::iterator PO_I, PO_E;
SmallVector<const CFGBlock *, 20> worklist;
llvm::BitVector enqueuedBlocks;
+
public:
DataflowWorklist(const CFG &cfg, PostOrderCFGView &view)
- : PO_I(view.begin()), PO_E(view.end()),
- enqueuedBlocks(cfg.getNumBlockIDs(), true) {
- // Treat the first block as already analyzed.
- if (PO_I != PO_E) {
- assert(*PO_I == &cfg.getEntry());
- enqueuedBlocks[(*PO_I)->getBlockID()] = false;
- ++PO_I;
- }
- }
+ : PO_I(view.begin()), PO_E(view.end()),
+ enqueuedBlocks(cfg.getNumBlockIDs(), true) {
+ // Treat the first block as already analyzed.
+ if (PO_I != PO_E) {
+ assert(*PO_I == &cfg.getEntry());
+ enqueuedBlocks[(*PO_I)->getBlockID()] = false;
+ ++PO_I;
+ }
+ }
void enqueueSuccessors(const CFGBlock *block);
const CFGBlock *dequeue();
};
-}
-void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) {
+} // namespace
+
+void DataflowWorklist::enqueueSuccessors(const CFGBlock *block) {
for (CFGBlock::const_succ_iterator I = block->succ_begin(),
E = block->succ_end(); I != E; ++I) {
const CFGBlock *Successor = *I;
@@ -250,9 +267,8 @@
B = *PO_I;
++PO_I;
}
- else {
+ else
return nullptr;
- }
assert(enqueuedBlocks[B->getBlockID()] == true);
enqueuedBlocks[B->getBlockID()] = false;
@@ -264,9 +280,11 @@
//====------------------------------------------------------------------------//
namespace {
+
class FindVarResult {
const VarDecl *vd;
const DeclRefExpr *dr;
+
public:
FindVarResult(const VarDecl *vd, const DeclRefExpr *dr) : vd(vd), dr(dr) {}
@@ -274,10 +292,12 @@
const VarDecl *getDecl() const { return vd; }
};
+} // namespace
+
static const Expr *stripCasts(ASTContext &C, const Expr *Ex) {
while (Ex) {
Ex = Ex->IgnoreParenNoopCasts(C);
- if (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
+ if (const auto *CE = dyn_cast<CastExpr>(Ex)) {
if (CE->getCastKind() == CK_LValueBitCast) {
Ex = CE->getSubExpr();
continue;
@@ -291,14 +311,16 @@
/// If E is an expression comprising a reference to a single variable, find that
/// variable.
static FindVarResult findVar(const Expr *E, const DeclContext *DC) {
- if (const DeclRefExpr *DRE =
- dyn_cast<DeclRefExpr>(stripCasts(DC->getParentASTContext(), E)))
- if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (const auto *DRE =
+ dyn_cast<DeclRefExpr>(stripCasts(DC->getParentASTContext(), E)))
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
if (isTrackedVar(VD, DC))
return FindVarResult(VD, DRE);
return FindVarResult(nullptr, nullptr);
}
+namespace {
+
/// \brief Classify each DeclRefExpr as an initialization or a use. Any
/// DeclRefExpr which isn't explicitly classified will be assumed to have
/// escaped the analysis and will be treated as an initialization.
@@ -313,7 +335,7 @@
private:
const DeclContext *DC;
- llvm::DenseMap<const DeclRefExpr*, Class> Classification;
+ llvm::DenseMap<const DeclRefExpr *, Class> Classification;
bool isTrackedVar(const VarDecl *VD) const {
return ::isTrackedVar(VD, DC);
@@ -338,21 +360,22 @@
if (I != Classification.end())
return I->second;
- const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
if (!VD || !isTrackedVar(VD))
return Ignore;
return Init;
}
};
-}
+
+} // namespace
static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) {
if (VD->getType()->isRecordType())
return nullptr;
if (Expr *Init = VD->getInit()) {
- const DeclRefExpr *DRE
- = dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init));
+ const auto *DRE =
+ dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init));
if (DRE && DRE->getDecl() == VD)
return DRE;
}
@@ -362,32 +385,31 @@
void ClassifyRefs::classify(const Expr *E, Class C) {
// The result of a ?: could also be an lvalue.
E = E->IgnoreParens();
- if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
+ if (const auto *CO = dyn_cast<ConditionalOperator>(E)) {
classify(CO->getTrueExpr(), C);
classify(CO->getFalseExpr(), C);
return;
}
- if (const BinaryConditionalOperator *BCO =
- dyn_cast<BinaryConditionalOperator>(E)) {
+ if (const auto *BCO = dyn_cast<BinaryConditionalOperator>(E)) {
classify(BCO->getFalseExpr(), C);
return;
}
- if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
+ if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) {
classify(OVE->getSourceExpr(), C);
return;
}
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
- if (VarDecl *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) {
+ if (const auto *ME = dyn_cast<MemberExpr>(E)) {
+ if (const auto *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) {
if (!VD->isStaticDataMember())
classify(ME->getBase(), C);
}
return;
}
- if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
switch (BO->getOpcode()) {
case BO_PtrMemD:
case BO_PtrMemI:
@@ -408,7 +430,7 @@
void ClassifyRefs::VisitDeclStmt(DeclStmt *DS) {
for (auto *DI : DS->decls()) {
- VarDecl *VD = dyn_cast<VarDecl>(DI);
+ auto *VD = dyn_cast<VarDecl>(DI);
if (VD && isTrackedVar(VD))
if (const DeclRefExpr *DRE = getSelfInitExpr(VD))
Classification[DRE] = SelfInit;
@@ -457,7 +479,7 @@
classify((*I), Ignore);
} else if (isPointerToConst((*I)->getType())) {
const Expr *Ex = stripCasts(DC->getParentASTContext(), *I);
- const UnaryOperator *UO = dyn_cast<UnaryOperator>(Ex);
+ const auto *UO = dyn_cast<UnaryOperator>(Ex);
if (UO && UO->getOpcode() == UO_AddrOf)
Ex = UO->getSubExpr();
classify(Ex, Ignore);
@@ -468,7 +490,7 @@
void ClassifyRefs::VisitCastExpr(CastExpr *CE) {
if (CE->getCastKind() == CK_LValueToRValue)
classify(CE->getSubExpr(), Use);
- else if (CStyleCastExpr *CSE = dyn_cast<CStyleCastExpr>(CE)) {
+ else if (const auto *CSE = dyn_cast<CStyleCastExpr>(CE)) {
if (CSE->getType()->isVoidType()) {
// Squelch any detected load of an uninitialized value if
// we cast it to void.
@@ -483,6 +505,7 @@
//====------------------------------------------------------------------------//
namespace {
+
class TransferFunctions : public StmtVisitor<TransferFunctions> {
CFGBlockValues &vals;
const CFG &cfg;
@@ -497,9 +520,9 @@
const CFGBlock *block, AnalysisDeclContext &ac,
const ClassifyRefs &classification,
UninitVariablesHandler &handler)
- : vals(vals), cfg(cfg), block(block), ac(ac),
- classification(classification), objCNoRet(ac.getASTContext()),
- handler(handler) {}
+ : vals(vals), cfg(cfg), block(block), ac(ac),
+ classification(classification), objCNoRet(ac.getASTContext()),
+ handler(handler) {}
void reportUse(const Expr *ex, const VarDecl *vd);
@@ -627,8 +650,7 @@
// Scan the frontier, looking for blocks where the variable was
// uninitialized.
- for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
- const CFGBlock *Block = *BI;
+ for (const auto *Block : cfg) {
unsigned BlockID = Block->getBlockID();
const Stmt *Term = Block->getTerminator();
if (SuccsVisited[BlockID] && SuccsVisited[BlockID] < Block->succ_size() &&
@@ -668,7 +690,8 @@
return Use;
}
};
-}
+
+} // namespace
void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) {
Value v = vals[vd];
@@ -678,8 +701,8 @@
void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) {
// This represents an initialization of the 'element' value.
- if (DeclStmt *DS = dyn_cast<DeclStmt>(FS->getElement())) {
- const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
+ if (const auto *DS = dyn_cast<DeclStmt>(FS->getElement())) {
+ const auto *VD = cast<VarDecl>(DS->getSingleDecl());
if (isTrackedVar(VD))
vals[VD] = Initialized;
}
@@ -748,7 +771,7 @@
void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
for (auto *DI : DS->decls()) {
- VarDecl *VD = dyn_cast<VarDecl>(DI);
+ auto *VD = dyn_cast<VarDecl>(DI);
if (VD && isTrackedVar(VD)) {
if (getSelfInitExpr(VD)) {
// If the initializer consists solely of a reference to itself, we
@@ -815,34 +838,32 @@
}
// Apply the transfer function.
TransferFunctions tf(vals, cfg, block, ac, classification, handler);
- for (CFGBlock::const_iterator I = block->begin(), E = block->end();
- I != E; ++I) {
- if (Optional<CFGStmt> cs = I->getAs<CFGStmt>())
- tf.Visit(const_cast<Stmt*>(cs->getStmt()));
+ for (const auto &I : *block) {
+ if (Optional<CFGStmt> cs = I.getAs<CFGStmt>())
+ tf.Visit(const_cast<Stmt *>(cs->getStmt()));
}
return vals.updateValueVectorWithScratch(block);
}
+namespace {
+
/// PruneBlocksHandler is a special UninitVariablesHandler that is used
/// to detect when a CFGBlock has any *potential* use of an uninitialized
/// variable. It is mainly used to prune out work during the final
/// reporting pass.
-namespace {
struct PruneBlocksHandler : public UninitVariablesHandler {
- PruneBlocksHandler(unsigned numBlocks)
- : hadUse(numBlocks, false), hadAnyUse(false),
- currentBlock(0) {}
-
- ~PruneBlocksHandler() override {}
-
/// Records if a CFGBlock had a potential use of an uninitialized variable.
llvm::BitVector hadUse;
/// Records if any CFGBlock had a potential use of an uninitialized variable.
- bool hadAnyUse;
+ bool hadAnyUse = false;
/// The current block to scribble use information.
- unsigned currentBlock;
+ unsigned currentBlock = 0;
+
+ PruneBlocksHandler(unsigned numBlocks) : hadUse(numBlocks, false) {}
+
+ ~PruneBlocksHandler() override = default;
void handleUseOfUninitVariable(const VarDecl *vd,
const UninitUse &use) override {
@@ -858,7 +879,8 @@
hadAnyUse = true;
}
};
-}
+
+} // namespace
void clang::runUninitializedVariablesAnalysis(
const DeclContext &dc,
@@ -881,7 +903,7 @@
const CFGBlock &entry = cfg.getEntry();
ValueVector &vec = vals.getValueVector(&entry);
const unsigned n = vals.getNumEntries();
- for (unsigned j = 0; j < n ; ++j) {
+ for (unsigned j = 0; j < n; ++j) {
vec[j] = Uninitialized;
}
@@ -909,13 +931,11 @@
return;
// Run through the blocks one more time, and report uninitialized variables.
- for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
- const CFGBlock *block = *BI;
+ for (const auto *block : cfg)
if (PBH.hadUse[block->getBlockID()]) {
runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, handler);
++stats.NumBlockVisits;
}
- }
}
-UninitVariablesHandler::~UninitVariablesHandler() {}
+UninitVariablesHandler::~UninitVariablesHandler() = default;
diff --git a/lib/Basic/FileSystemStatCache.cpp b/lib/Basic/FileSystemStatCache.cpp
index 799df1d..ebee326 100644
--- a/lib/Basic/FileSystemStatCache.cpp
+++ b/lib/Basic/FileSystemStatCache.cpp
@@ -1,4 +1,4 @@
-//===--- FileSystemStatCache.cpp - Caching for 'stat' calls ---------------===//
+//===- FileSystemStatCache.cpp - Caching for 'stat' calls -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,11 +13,14 @@
#include "clang/Basic/FileSystemStatCache.h"
#include "clang/Basic/VirtualFileSystem.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/Path.h"
+#include <utility>
using namespace clang;
-void FileSystemStatCache::anchor() { }
+void FileSystemStatCache::anchor() {}
static void copyStatusToFileData(const vfs::Status &Status,
FileData &Data) {
diff --git a/lib/Basic/ObjCRuntime.cpp b/lib/Basic/ObjCRuntime.cpp
index 133c669..15f38d1 100644
--- a/lib/Basic/ObjCRuntime.cpp
+++ b/lib/Basic/ObjCRuntime.cpp
@@ -1,4 +1,4 @@
-//===- ObjCRuntime.cpp - Objective-C Runtime Handling -----------*- C++ -*-===//
+//===- ObjCRuntime.cpp - Objective-C Runtime Handling ---------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,8 +11,13 @@
// target Objective-C runtime.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/VersionTuple.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstddef>
+#include <string>
using namespace clang;
diff --git a/lib/Basic/Sanitizers.cpp b/lib/Basic/Sanitizers.cpp
index 91b6b2d..8faf17b 100644
--- a/lib/Basic/Sanitizers.cpp
+++ b/lib/Basic/Sanitizers.cpp
@@ -1,4 +1,4 @@
-//===--- Sanitizers.cpp - C Language Family Language Options ----*- C++ -*-===//
+//===- Sanitizers.cpp - C Language Family Language Options ----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,9 +10,8 @@
// This file defines the classes from Sanitizers.h
//
//===----------------------------------------------------------------------===//
+
#include "clang/Basic/Sanitizers.h"
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index ddd292c..497ae34 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -32,6 +32,7 @@
TLSSupported = true;
VLASupported = true;
NoAsmVariants = false;
+ HasLegalHalfType = false;
HasFloat128 = false;
PointerWidth = PointerAlign = 32;
BoolWidth = BoolAlign = 8;
@@ -356,6 +357,14 @@
return true;
}
+TargetInfo::CallingConvKind
+TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
+ if (getCXXABI() != TargetCXXABI::Microsoft &&
+ (ClangABICompat4 || getTriple().getOS() == llvm::Triple::PS4))
+ return CCK_ClangABI4OrPS4;
+ return CCK_Default;
+}
+
LangAS TargetInfo::getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const {
switch (TK) {
case OCLTK_Image:
diff --git a/lib/Basic/Targets/AArch64.cpp b/lib/Basic/Targets/AArch64.cpp
index 51e6830..394be5a 100644
--- a/lib/Basic/Targets/AArch64.cpp
+++ b/lib/Basic/Targets/AArch64.cpp
@@ -49,6 +49,8 @@
IntMaxType = SignedLong;
}
+ // All AArch64 implementations support ARMv8 FP, which makes half a legal type.
+ HasLegalHalfType = true;
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
MaxVectorAlign = 128;
@@ -306,7 +308,40 @@
}
const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
- {{"w31"}, "wsp"}, {{"x29"}, "fp"}, {{"x30"}, "lr"}, {{"x31"}, "sp"},
+ {{"w31"}, "wsp"},
+ {{"x31"}, "sp"},
+ // GCC rN registers are aliases of xN registers.
+ {{"r0"}, "x0"},
+ {{"r1"}, "x1"},
+ {{"r2"}, "x2"},
+ {{"r3"}, "x3"},
+ {{"r4"}, "x4"},
+ {{"r5"}, "x5"},
+ {{"r6"}, "x6"},
+ {{"r7"}, "x7"},
+ {{"r8"}, "x8"},
+ {{"r9"}, "x9"},
+ {{"r10"}, "x10"},
+ {{"r11"}, "x11"},
+ {{"r12"}, "x12"},
+ {{"r13"}, "x13"},
+ {{"r14"}, "x14"},
+ {{"r15"}, "x15"},
+ {{"r16"}, "x16"},
+ {{"r17"}, "x17"},
+ {{"r18"}, "x18"},
+ {{"r19"}, "x19"},
+ {{"r20"}, "x20"},
+ {{"r21"}, "x21"},
+ {{"r22"}, "x22"},
+ {{"r23"}, "x23"},
+ {{"r24"}, "x24"},
+ {{"r25"}, "x25"},
+ {{"r26"}, "x26"},
+ {{"r27"}, "x27"},
+ {{"r28"}, "x28"},
+ {{"r29", "x29"}, "fp"},
+ {{"r30", "x30"}, "lr"},
// The S/D/Q and W/X registers overlap, but aren't really aliases; we
// don't want to substitute one of these for a different-sized one.
};
diff --git a/lib/Basic/Targets/AMDGPU.cpp b/lib/Basic/Targets/AMDGPU.cpp
index a926722..d956d13 100644
--- a/lib/Basic/Targets/AMDGPU.cpp
+++ b/lib/Basic/Targets/AMDGPU.cpp
@@ -30,12 +30,12 @@
static const char *const DataLayoutStringR600 =
"e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
- "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5";
+ "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5";
static const char *const DataLayoutStringAMDGCN =
"e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32"
"-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
- "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5";
+ "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5";
const LangASMap AMDGPUTargetInfo::AMDGPUDefIsGenMap = {
Generic, // Default
diff --git a/lib/Basic/Targets/AMDGPU.h b/lib/Basic/Targets/AMDGPU.h
index 603c9b2..f7c4776 100644
--- a/lib/Basic/Targets/AMDGPU.h
+++ b/lib/Basic/Targets/AMDGPU.h
@@ -285,6 +285,19 @@
return true;
}
+ // \p Constraint will be left pointing at the last character of
+ // the constraint. In practice, it won't be changed unless the
+ // constraint is longer than one character.
+ std::string convertConstraint(const char *&Constraint) const override {
+ const char *Begin = Constraint;
+ TargetInfo::ConstraintInfo Info("", "");
+ if (validateAsmConstraint(Constraint, Info))
+ return std::string(Begin).substr(0, Constraint - Begin + 1);
+
+ Constraint = Begin;
+ return std::string(1, *Constraint);
+ }
+
bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
diff --git a/lib/Basic/Targets/ARM.cpp b/lib/Basic/Targets/ARM.cpp
index 3f2d31d..736c235 100644
--- a/lib/Basic/Targets/ARM.cpp
+++ b/lib/Basic/Targets/ARM.cpp
@@ -419,6 +419,8 @@
Unaligned = 0;
} else if (Feature == "+fp16") {
HW_FP |= HW_FP_HP;
+ } else if (Feature == "+fullfp16") {
+ HasLegalHalfType = true;
}
}
HW_FP &= ~HW_FP_remove;
@@ -710,6 +712,15 @@
if (Opts.UnsafeFPMath)
Builder.defineMacro("__ARM_FP_FAST", "1");
+ // Armv8.2-A FP16 vector intrinsic
+ if ((FPU & NeonFPU) && HasLegalHalfType)
+ Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
+
+ // Armv8.2-A FP16 scalar intrinsics
+ if (HasLegalHalfType)
+ Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
+
+
switch (ArchKind) {
default:
break;
@@ -960,6 +971,8 @@
return CCCR_Ignore;
case CC_C:
case CC_OpenCLKernel:
+ case CC_PreserveMost:
+ case CC_PreserveAll:
return CCCR_OK;
default:
return CCCR_Warning;
diff --git a/lib/Basic/Targets/OSTargets.h b/lib/Basic/Targets/OSTargets.h
index 05fcd93..70bf1e6 100644
--- a/lib/Basic/Targets/OSTargets.h
+++ b/lib/Basic/Targets/OSTargets.h
@@ -485,6 +485,7 @@
default:
case llvm::Triple::x86_64:
this->MCountName = ".mcount";
+ this->NewAlign = 256;
break;
}
}
diff --git a/lib/Basic/Targets/X86.h b/lib/Basic/Targets/X86.h
index 660e584..f802940 100644
--- a/lib/Basic/Targets/X86.h
+++ b/lib/Basic/Targets/X86.h
@@ -728,6 +728,11 @@
Builder.defineMacro("_M_X64", "100");
Builder.defineMacro("_M_AMD64", "100");
}
+
+ TargetInfo::CallingConvKind
+ getCallingConvKind(bool ClangABICompat4) const override {
+ return CCK_MicrosoftX86_64;
+ }
};
// x86-64 MinGW target
diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp
index 9d44597..a854576 100644
--- a/lib/Basic/VirtualFileSystem.cpp
+++ b/lib/Basic/VirtualFileSystem.cpp
@@ -1,4 +1,4 @@
-//===- VirtualFileSystem.cpp - Virtual File System Layer --------*- C++ -*-===//
+//===- VirtualFileSystem.cpp - Virtual File System Layer ------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,30 +6,57 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
// This file implements the VirtualFileSystem interface.
+//
//===----------------------------------------------------------------------===//
#include "clang/Basic/VirtualFileSystem.h"
-#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Chrono.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/YAMLParser.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
#include <atomic>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <limits>
+#include <map>
#include <memory>
+#include <string>
+#include <system_error>
#include <utility>
+#include <vector>
using namespace clang;
-using namespace clang::vfs;
+using namespace vfs;
using namespace llvm;
+
using llvm::sys::fs::file_status;
using llvm::sys::fs::file_type;
using llvm::sys::fs::perms;
@@ -38,13 +65,13 @@
Status::Status(const file_status &Status)
: UID(Status.getUniqueID()), MTime(Status.getLastModificationTime()),
User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()),
- Type(Status.type()), Perms(Status.permissions()), IsVFSMapped(false) {}
+ Type(Status.type()), Perms(Status.permissions()) {}
Status::Status(StringRef Name, UniqueID UID, sys::TimePoint<> MTime,
uint32_t User, uint32_t Group, uint64_t Size, file_type Type,
perms Perms)
: Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size),
- Type(Type), Perms(Perms), IsVFSMapped(false) {}
+ Type(Type), Perms(Perms) {}
Status Status::copyWithNewName(const Status &In, StringRef NewName) {
return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
@@ -62,28 +89,34 @@
assert(isStatusKnown() && Other.isStatusKnown());
return getUniqueID() == Other.getUniqueID();
}
+
bool Status::isDirectory() const {
return Type == file_type::directory_file;
}
+
bool Status::isRegularFile() const {
return Type == file_type::regular_file;
}
+
bool Status::isOther() const {
return exists() && !isRegularFile() && !isDirectory() && !isSymlink();
}
+
bool Status::isSymlink() const {
return Type == file_type::symlink_file;
}
+
bool Status::isStatusKnown() const {
return Type != file_type::status_error;
}
+
bool Status::exists() const {
return isStatusKnown() && Type != file_type::file_not_found;
}
-File::~File() {}
+File::~File() = default;
-FileSystem::~FileSystem() {}
+FileSystem::~FileSystem() = default;
ErrorOr<std::unique_ptr<MemoryBuffer>>
FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize,
@@ -97,7 +130,7 @@
std::error_code FileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
if (llvm::sys::path::is_absolute(Path))
- return std::error_code();
+ return {};
auto WorkingDir = getCurrentWorkingDirectory();
if (!WorkingDir)
@@ -118,6 +151,7 @@
static bool pathHasTraversal(StringRef Path) {
using namespace llvm::sys;
+
for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path)))
if (isTraversalComponent(Comp))
return true;
@@ -130,12 +164,15 @@
//===-----------------------------------------------------------------------===/
namespace {
+
/// \brief Wrapper around a raw file descriptor.
class RealFile : public File {
+ friend class RealFileSystem;
+
int FD;
Status S;
std::string RealName;
- friend class RealFileSystem;
+
RealFile(int FD, StringRef NewName, StringRef NewRealPathName)
: FD(FD), S(NewName, {}, {}, {}, {}, {},
llvm::sys::fs::file_type::status_error, {}),
@@ -145,6 +182,7 @@
public:
~RealFile() override;
+
ErrorOr<Status> status() override;
ErrorOr<std::string> getName() override;
ErrorOr<std::unique_ptr<MemoryBuffer>> getBuffer(const Twine &Name,
@@ -153,7 +191,9 @@
bool IsVolatile) override;
std::error_code close() override;
};
-} // end anonymous namespace
+
+} // namespace
+
RealFile::~RealFile() { close(); }
ErrorOr<Status> RealFile::status() {
@@ -186,6 +226,7 @@
}
namespace {
+
/// \brief The file system according to your operating system.
class RealFileSystem : public FileSystem {
public:
@@ -196,7 +237,8 @@
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
};
-} // end anonymous namespace
+
+} // namespace
ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
sys::fs::file_status RealStatus;
@@ -238,8 +280,10 @@
}
namespace {
+
class RealFSDirIter : public clang::vfs::detail::DirIterImpl {
llvm::sys::fs::directory_iterator Iter;
+
public:
RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
if (!EC && Iter != llvm::sys::fs::directory_iterator()) {
@@ -264,7 +308,8 @@
return EC;
}
};
-}
+
+} // namespace
directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
std::error_code &EC) {
@@ -274,6 +319,7 @@
//===-----------------------------------------------------------------------===/
// OverlayFileSystem implementation
//===-----------------------------------------------------------------------===/
+
OverlayFileSystem::OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> BaseFS) {
FSList.push_back(std::move(BaseFS));
}
@@ -311,17 +357,19 @@
// All file systems are synchronized, just take the first working directory.
return FSList.front()->getCurrentWorkingDirectory();
}
+
std::error_code
OverlayFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
for (auto &FS : FSList)
if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
return EC;
- return std::error_code();
+ return {};
}
-clang::vfs::detail::DirIterImpl::~DirIterImpl() { }
+clang::vfs::detail::DirIterImpl::~DirIterImpl() = default;
namespace {
+
class OverlayFSDirIterImpl : public clang::vfs::detail::DirIterImpl {
OverlayFileSystem &Overlays;
std::string Path;
@@ -340,7 +388,7 @@
if (CurrentDirIter != directory_iterator())
break; // found
}
- return std::error_code();
+ return {};
}
std::error_code incrementDirIter(bool IsFirstTime) {
@@ -379,7 +427,8 @@
std::error_code increment() override { return incrementImpl(false); }
};
-} // end anonymous namespace
+
+} // namespace
directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir,
std::error_code &EC) {
@@ -389,6 +438,7 @@
namespace clang {
namespace vfs {
+
namespace detail {
enum InMemoryNodeKind { IME_File, IME_Directory };
@@ -402,13 +452,15 @@
public:
InMemoryNode(Status Stat, InMemoryNodeKind Kind)
: Stat(std::move(Stat)), Kind(Kind) {}
- virtual ~InMemoryNode() {}
+ virtual ~InMemoryNode() = default;
+
const Status &getStatus() const { return Stat; }
InMemoryNodeKind getKind() const { return Kind; }
virtual std::string toString(unsigned Indent) const = 0;
};
namespace {
+
class InMemoryFile : public InMemoryNode {
std::unique_ptr<llvm::MemoryBuffer> Buffer;
@@ -417,9 +469,11 @@
: InMemoryNode(std::move(Stat), IME_File), Buffer(std::move(Buffer)) {}
llvm::MemoryBuffer *getBuffer() { return Buffer.get(); }
+
std::string toString(unsigned Indent) const override {
return (std::string(Indent, ' ') + getStatus().getName() + "\n").str();
}
+
static bool classof(const InMemoryNode *N) {
return N->getKind() == IME_File;
}
@@ -433,6 +487,7 @@
explicit InMemoryFileAdaptor(InMemoryFile &Node) : Node(Node) {}
llvm::ErrorOr<Status> status() override { return Node.getStatus(); }
+
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
bool IsVolatile) override {
@@ -440,9 +495,11 @@
return llvm::MemoryBuffer::getMemBuffer(
Buf->getBuffer(), Buf->getBufferIdentifier(), RequiresNullTerminator);
}
- std::error_code close() override { return std::error_code(); }
+
+ std::error_code close() override { return {}; }
};
-} // end anonymous namespace
+
+} // namespace
class InMemoryDirectory : public InMemoryNode {
std::map<std::string, std::unique_ptr<InMemoryNode>> Entries;
@@ -450,34 +507,38 @@
public:
InMemoryDirectory(Status Stat)
: InMemoryNode(std::move(Stat), IME_Directory) {}
+
InMemoryNode *getChild(StringRef Name) {
auto I = Entries.find(Name);
if (I != Entries.end())
return I->second.get();
return nullptr;
}
+
InMemoryNode *addChild(StringRef Name, std::unique_ptr<InMemoryNode> Child) {
return Entries.insert(make_pair(Name, std::move(Child)))
.first->second.get();
}
- typedef decltype(Entries)::const_iterator const_iterator;
+ using const_iterator = decltype(Entries)::const_iterator;
+
const_iterator begin() const { return Entries.begin(); }
const_iterator end() const { return Entries.end(); }
std::string toString(unsigned Indent) const override {
std::string Result =
(std::string(Indent, ' ') + getStatus().getName() + "\n").str();
- for (const auto &Entry : Entries) {
+ for (const auto &Entry : Entries)
Result += Entry.second->toString(Indent + 2);
- }
return Result;
}
+
static bool classof(const InMemoryNode *N) {
return N->getKind() == IME_Directory;
}
};
-}
+
+} // namespace detail
InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
: Root(new detail::InMemoryDirectory(
@@ -486,7 +547,7 @@
llvm::sys::fs::perms::all_all))),
UseNormalizedPaths(UseNormalizedPaths) {}
-InMemoryFileSystem::~InMemoryFileSystem() {}
+InMemoryFileSystem::~InMemoryFileSystem() = default;
std::string InMemoryFileSystem::toString() const {
return Root->toString(/*Indent=*/0);
@@ -645,13 +706,15 @@
}
namespace {
+
/// Adaptor from InMemoryDir::iterator to directory_iterator.
class InMemoryDirIterator : public clang::vfs::detail::DirIterImpl {
detail::InMemoryDirectory::const_iterator I;
detail::InMemoryDirectory::const_iterator E;
public:
- InMemoryDirIterator() {}
+ InMemoryDirIterator() = default;
+
explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir)
: I(Dir.begin()), E(Dir.end()) {
if (I != E)
@@ -663,10 +726,11 @@
// When we're at the end, make CurrentEntry invalid and DirIterImpl will do
// the rest.
CurrentEntry = I != E ? I->second->getStatus() : Status();
- return std::error_code();
+ return {};
}
};
-} // end anonymous namespace
+
+} // namespace
directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir,
std::error_code &EC) {
@@ -697,10 +761,11 @@
if (!Path.empty())
WorkingDirectory = Path.str();
- return std::error_code();
+ return {};
}
-}
-}
+
+} // namespace vfs
+} // namespace clang
//===-----------------------------------------------------------------------===/
// RedirectingFileSystem implementation
@@ -719,8 +784,9 @@
std::string Name;
public:
- virtual ~Entry();
Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
+ virtual ~Entry() = default;
+
StringRef getName() const { return Name; }
EntryKind getKind() const { return Kind; }
};
@@ -737,14 +803,20 @@
S(std::move(S)) {}
RedirectingDirectoryEntry(StringRef Name, Status S)
: Entry(EK_Directory, Name), S(std::move(S)) {}
+
Status getStatus() { return S; }
+
void addContent(std::unique_ptr<Entry> Content) {
Contents.push_back(std::move(Content));
}
+
Entry *getLastContent() const { return Contents.back().get(); }
- typedef decltype(Contents)::iterator iterator;
+
+ using iterator = decltype(Contents)::iterator;
+
iterator contents_begin() { return Contents.begin(); }
iterator contents_end() { return Contents.end(); }
+
static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
};
@@ -755,21 +827,27 @@
NK_External,
NK_Virtual
};
+
private:
std::string ExternalContentsPath;
NameKind UseName;
+
public:
RedirectingFileEntry(StringRef Name, StringRef ExternalContentsPath,
NameKind UseName)
: Entry(EK_File, Name), ExternalContentsPath(ExternalContentsPath),
UseName(UseName) {}
+
StringRef getExternalContentsPath() const { return ExternalContentsPath; }
+
/// \brief whether to use the external path as the name for this file.
bool useExternalName(bool GlobalUseExternalName) const {
return UseName == NK_NotSet ? GlobalUseExternalName
: (UseName == NK_External);
}
+
NameKind getUseName() const { return UseName; }
+
static bool classof(const Entry *E) { return E->getKind() == EK_File; }
};
@@ -785,6 +863,7 @@
RedirectingDirectoryEntry::iterator Begin,
RedirectingDirectoryEntry::iterator End,
std::error_code &EC);
+
std::error_code increment() override;
};
@@ -844,10 +923,14 @@
/// /path/to/file). However, any directory that contains more than one child
/// must be uniquely represented by a directory entry.
class RedirectingFileSystem : public vfs::FileSystem {
+ friend class RedirectingFileSystemParser;
+
/// The root(s) of the virtual file system.
std::vector<std::unique_ptr<Entry>> Roots;
+
/// \brief The file system to use for external references.
IntrusiveRefCntPtr<FileSystem> ExternalFS;
+
/// If IsRelativeOverlay is set, this represents the directory
/// path that should be prefixed to each 'external-contents' entry
/// when reading from YAML files.
@@ -888,8 +971,6 @@
true;
#endif
- friend class RedirectingFileSystemParser;
-
private:
RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS)
: ExternalFS(std::move(ExternalFS)) {}
@@ -919,6 +1000,7 @@
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
return ExternalFS->getCurrentWorkingDirectory();
}
+
std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
return ExternalFS->setCurrentWorkingDirectory(Path);
}
@@ -927,17 +1009,17 @@
ErrorOr<Entry *> E = lookupPath(Dir);
if (!E) {
EC = E.getError();
- return directory_iterator();
+ return {};
}
ErrorOr<Status> S = status(Dir, *E);
if (!S) {
EC = S.getError();
- return directory_iterator();
+ return {};
}
if (!S->isDirectory()) {
EC = std::error_code(static_cast<int>(errc::not_a_directory),
std::system_category());
- return directory_iterator();
+ return {};
}
auto *D = cast<RedirectingDirectoryEntry>(*E);
@@ -959,7 +1041,7 @@
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void dump() const {
- for (const std::unique_ptr<Entry> &Root : Roots)
+ for (const auto &Root : Roots)
dumpEntry(Root.get());
}
@@ -979,7 +1061,6 @@
}
}
#endif
-
};
/// \brief A helper class to hold the common YAML parsing state.
@@ -993,7 +1074,8 @@
// false on error
bool parseScalarString(yaml::Node *N, StringRef &Result,
SmallVectorImpl<char> &Storage) {
- yaml::ScalarNode *S = dyn_cast<yaml::ScalarNode>(N);
+ const auto *S = dyn_cast<yaml::ScalarNode>(N);
+
if (!S) {
error(N, "expected string");
return false;
@@ -1024,11 +1106,13 @@
}
struct KeyStatus {
- KeyStatus(bool Required=false) : Required(Required), Seen(false) {}
bool Required;
- bool Seen;
+ bool Seen = false;
+
+ KeyStatus(bool Required = false) : Required(Required) {}
};
- typedef std::pair<StringRef, KeyStatus> KeyStatusPair;
+
+ using KeyStatusPair = std::pair<StringRef, KeyStatus>;
// false on error
bool checkDuplicateOrUnknownKey(yaml::Node *KeyNode, StringRef Key,
@@ -1048,11 +1132,9 @@
// false on error
bool checkMissingKeys(yaml::Node *Obj, DenseMap<StringRef, KeyStatus> &Keys) {
- for (DenseMap<StringRef, KeyStatus>::iterator I = Keys.begin(),
- E = Keys.end();
- I != E; ++I) {
- if (I->second.Required && !I->second.Seen) {
- error(Obj, Twine("missing key '") + I->first + "'");
+ for (const auto &I : Keys) {
+ if (I.second.Required && !I.second.Seen) {
+ error(Obj, Twine("missing key '") + I.first + "'");
return false;
}
}
@@ -1062,7 +1144,7 @@
Entry *lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name,
Entry *ParentEntry = nullptr) {
if (!ParentEntry) { // Look for a existent root
- for (const std::unique_ptr<Entry> &Root : FS->Roots) {
+ for (const auto &Root : FS->Roots) {
if (Name.equals(Root->getName())) {
ParentEntry = Root.get();
return ParentEntry;
@@ -1125,7 +1207,7 @@
}
std::unique_ptr<Entry> parseEntry(yaml::Node *N, RedirectingFileSystem *FS) {
- yaml::MappingNode *M = dyn_cast<yaml::MappingNode>(N);
+ auto *M = dyn_cast<yaml::MappingNode>(N);
if (!M) {
error(N, "expected mapping node for file or directory entry");
return nullptr;
@@ -1148,21 +1230,20 @@
auto UseExternalName = RedirectingFileEntry::NK_NotSet;
EntryKind Kind;
- for (yaml::MappingNode::iterator I = M->begin(), E = M->end(); I != E;
- ++I) {
+ for (auto &I : *M) {
StringRef Key;
// Reuse the buffer for key and value, since we don't look at key after
// parsing value.
SmallString<256> Buffer;
- if (!parseScalarString(I->getKey(), Key, Buffer))
+ if (!parseScalarString(I.getKey(), Key, Buffer))
return nullptr;
- if (!checkDuplicateOrUnknownKey(I->getKey(), Key, Keys))
+ if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
return nullptr;
StringRef Value;
if (Key == "name") {
- if (!parseScalarString(I->getValue(), Value, Buffer))
+ if (!parseScalarString(I.getValue(), Value, Buffer))
return nullptr;
if (FS->UseCanonicalizedPaths) {
@@ -1176,47 +1257,44 @@
Name = Value;
}
} else if (Key == "type") {
- if (!parseScalarString(I->getValue(), Value, Buffer))
+ if (!parseScalarString(I.getValue(), Value, Buffer))
return nullptr;
if (Value == "file")
Kind = EK_File;
else if (Value == "directory")
Kind = EK_Directory;
else {
- error(I->getValue(), "unknown value for 'type'");
+ error(I.getValue(), "unknown value for 'type'");
return nullptr;
}
} else if (Key == "contents") {
if (HasContents) {
- error(I->getKey(),
+ error(I.getKey(),
"entry already has 'contents' or 'external-contents'");
return nullptr;
}
HasContents = true;
- yaml::SequenceNode *Contents =
- dyn_cast<yaml::SequenceNode>(I->getValue());
+ auto *Contents = dyn_cast<yaml::SequenceNode>(I.getValue());
if (!Contents) {
// FIXME: this is only for directories, what about files?
- error(I->getValue(), "expected array");
+ error(I.getValue(), "expected array");
return nullptr;
}
- for (yaml::SequenceNode::iterator I = Contents->begin(),
- E = Contents->end();
- I != E; ++I) {
- if (std::unique_ptr<Entry> E = parseEntry(&*I, FS))
+ for (auto &I : *Contents) {
+ if (std::unique_ptr<Entry> E = parseEntry(&I, FS))
EntryArrayContents.push_back(std::move(E));
else
return nullptr;
}
} else if (Key == "external-contents") {
if (HasContents) {
- error(I->getKey(),
+ error(I.getKey(),
"entry already has 'contents' or 'external-contents'");
return nullptr;
}
HasContents = true;
- if (!parseScalarString(I->getValue(), Value, Buffer))
+ if (!parseScalarString(I.getValue(), Value, Buffer))
return nullptr;
SmallString<256> FullPath;
@@ -1238,7 +1316,7 @@
ExternalContentsPath = FullPath.str();
} else if (Key == "use-external-name") {
bool Val;
- if (!parseScalarBool(I->getValue(), Val))
+ if (!parseScalarBool(I.getValue(), Val))
return nullptr;
UseExternalName = Val ? RedirectingFileEntry::NK_External
: RedirectingFileEntry::NK_Virtual;
@@ -1311,7 +1389,7 @@
// false on error
bool parse(yaml::Node *Root, RedirectingFileSystem *FS) {
- yaml::MappingNode *Top = dyn_cast<yaml::MappingNode>(Root);
+ auto *Top = dyn_cast<yaml::MappingNode>(Root);
if (!Top) {
error(Root, "expected mapping node");
return false;
@@ -1330,26 +1408,24 @@
std::vector<std::unique_ptr<Entry>> RootEntries;
// Parse configuration and 'roots'
- for (yaml::MappingNode::iterator I = Top->begin(), E = Top->end(); I != E;
- ++I) {
+ for (auto &I : *Top) {
SmallString<10> KeyBuffer;
StringRef Key;
- if (!parseScalarString(I->getKey(), Key, KeyBuffer))
+ if (!parseScalarString(I.getKey(), Key, KeyBuffer))
return false;
- if (!checkDuplicateOrUnknownKey(I->getKey(), Key, Keys))
+ if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
return false;
if (Key == "roots") {
- yaml::SequenceNode *Roots = dyn_cast<yaml::SequenceNode>(I->getValue());
+ auto *Roots = dyn_cast<yaml::SequenceNode>(I.getValue());
if (!Roots) {
- error(I->getValue(), "expected array");
+ error(I.getValue(), "expected array");
return false;
}
- for (yaml::SequenceNode::iterator I = Roots->begin(), E = Roots->end();
- I != E; ++I) {
- if (std::unique_ptr<Entry> E = parseEntry(&*I, FS))
+ for (auto &I : *Roots) {
+ if (std::unique_ptr<Entry> E = parseEntry(&I, FS))
RootEntries.push_back(std::move(E));
else
return false;
@@ -1357,32 +1433,32 @@
} else if (Key == "version") {
StringRef VersionString;
SmallString<4> Storage;
- if (!parseScalarString(I->getValue(), VersionString, Storage))
+ if (!parseScalarString(I.getValue(), VersionString, Storage))
return false;
int Version;
if (VersionString.getAsInteger<int>(10, Version)) {
- error(I->getValue(), "expected integer");
+ error(I.getValue(), "expected integer");
return false;
}
if (Version < 0) {
- error(I->getValue(), "invalid version number");
+ error(I.getValue(), "invalid version number");
return false;
}
if (Version != 0) {
- error(I->getValue(), "version mismatch, expected 0");
+ error(I.getValue(), "version mismatch, expected 0");
return false;
}
} else if (Key == "case-sensitive") {
- if (!parseScalarBool(I->getValue(), FS->CaseSensitive))
+ if (!parseScalarBool(I.getValue(), FS->CaseSensitive))
return false;
} else if (Key == "overlay-relative") {
- if (!parseScalarBool(I->getValue(), FS->IsRelativeOverlay))
+ if (!parseScalarBool(I.getValue(), FS->IsRelativeOverlay))
return false;
} else if (Key == "use-external-names") {
- if (!parseScalarBool(I->getValue(), FS->UseExternalNames))
+ if (!parseScalarBool(I.getValue(), FS->UseExternalNames))
return false;
} else if (Key == "ignore-non-existent-contents") {
- if (!parseScalarBool(I->getValue(), FS->IgnoreNonExistentContents))
+ if (!parseScalarBool(I.getValue(), FS->IgnoreNonExistentContents))
return false;
} else {
llvm_unreachable("key missing from Keys");
@@ -1398,22 +1474,20 @@
// Now that we sucessefully parsed the YAML file, canonicalize the internal
// representation to a proper directory tree so that we can search faster
// inside the VFS.
- for (std::unique_ptr<Entry> &E : RootEntries)
+ for (auto &E : RootEntries)
uniqueOverlayTree(FS, E.get());
return true;
}
};
-} // end of anonymous namespace
-Entry::~Entry() = default;
+} // namespace
RedirectingFileSystem *
RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
SourceMgr::DiagHandlerTy DiagHandler,
StringRef YAMLFilePath, void *DiagContext,
IntrusiveRefCntPtr<FileSystem> ExternalFS) {
-
SourceMgr SM;
yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
@@ -1473,7 +1547,7 @@
sys::path::const_iterator Start = sys::path::begin(Path);
sys::path::const_iterator End = sys::path::end(Path);
- for (const std::unique_ptr<Entry> &Root : Roots) {
+ for (const auto &Root : Roots) {
ErrorOr<Entry *> Result = lookupPath(Start, End, Root.get());
if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
return Result;
@@ -1557,6 +1631,7 @@
}
namespace {
+
/// Provide a file wrapper with an overriden status.
class FileWithFixedStatus : public File {
std::unique_ptr<File> InnerFile;
@@ -1568,14 +1643,17 @@
ErrorOr<Status> status() override { return S; }
ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+
getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
bool IsVolatile) override {
return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
IsVolatile);
}
+
std::error_code close() override { return InnerFile->close(); }
};
-} // end anonymous namespace
+
+} // namespace
ErrorOr<std::unique_ptr<File>>
RedirectingFileSystem::openFileForRead(const Twine &Path) {
@@ -1670,11 +1748,13 @@
}
namespace {
+
class JSONWriter {
llvm::raw_ostream &OS;
SmallVector<StringRef, 16> DirStack;
- inline unsigned getDirIndent() { return 4 * DirStack.size(); }
- inline unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
+
+ unsigned getDirIndent() { return 4 * DirStack.size(); }
+ unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
bool containedIn(StringRef Parent, StringRef Path);
StringRef containedPart(StringRef Parent, StringRef Path);
void startDirectory(StringRef Path);
@@ -1683,14 +1763,17 @@
public:
JSONWriter(llvm::raw_ostream &OS) : OS(OS) {}
+
void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames,
Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative,
Optional<bool> IgnoreNonExistentContents, StringRef OverlayDir);
};
-}
+
+} // namespace
bool JSONWriter::containedIn(StringRef Parent, StringRef Path) {
using namespace llvm::sys;
+
// Compare each path component.
auto IParent = path::begin(Parent), EParent = path::end(Parent);
for (auto IChild = path::begin(Path), EChild = path::end(Path);
@@ -1812,8 +1895,8 @@
}
void YAMLVFSWriter::write(llvm::raw_ostream &OS) {
- std::sort(Mappings.begin(), Mappings.end(),
- [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {
+ llvm::sort(Mappings.begin(), Mappings.end(),
+ [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {
return LHS.VPath < RHS.VPath;
});
@@ -1868,7 +1951,7 @@
if (Current == End)
CurrentEntry = Status();
- return std::error_code();
+ return {};
}
vfs::recursive_directory_iterator::recursive_directory_iterator(FileSystem &FS_,
diff --git a/lib/CodeGen/ABIInfo.h b/lib/CodeGen/ABIInfo.h
index fa0461f..feed383 100644
--- a/lib/CodeGen/ABIInfo.h
+++ b/lib/CodeGen/ABIInfo.h
@@ -53,12 +53,9 @@
CodeGen::CodeGenTypes &CGT;
protected:
llvm::CallingConv::ID RuntimeCC;
- llvm::CallingConv::ID BuiltinCC;
public:
ABIInfo(CodeGen::CodeGenTypes &cgt)
- : CGT(cgt),
- RuntimeCC(llvm::CallingConv::C),
- BuiltinCC(llvm::CallingConv::C) {}
+ : CGT(cgt), RuntimeCC(llvm::CallingConv::C) {}
virtual ~ABIInfo();
@@ -77,11 +74,6 @@
return RuntimeCC;
}
- /// Return the calling convention to use for compiler builtins
- llvm::CallingConv::ID getBuiltinCC() const {
- return BuiltinCC;
- }
-
virtual void computeInfo(CodeGen::CGFunctionInfo &FI) const = 0;
/// EmitVAArg - Emit the target dependent code to load a value of
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index f2733ce..02b1b1b 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -46,16 +46,17 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Coroutines.h"
-#include "llvm/Transforms/GCOVProfiler.h"
#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/Instrumentation/BoundsChecking.h"
+#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/GVN.h"
+#include "llvm/Transforms/Utils.h"
#include "llvm/Transforms/Utils/NameAnonGlobals.h"
#include "llvm/Transforms/Utils/SymbolRewriter.h"
#include <memory>
diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp
index 3d24e1f..7e685d2 100644
--- a/lib/CodeGen/CGAtomic.cpp
+++ b/lib/CodeGen/CGAtomic.cpp
@@ -1160,7 +1160,7 @@
if (UseOptimizedLibcall && Res.getScalarVal()) {
llvm::Value *ResVal = Res.getScalarVal();
if (PostOp) {
- llvm::Value *LoadVal1 = Args[1].RV.getScalarVal();
+ llvm::Value *LoadVal1 = Args[1].getRValue(*this).getScalarVal();
ResVal = Builder.CreateBinOp(PostOp, ResVal, LoadVal1);
}
if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch)
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 6695860..1a69049 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -307,25 +307,12 @@
assert(elementTypes.empty());
if (CGM.getLangOpts().OpenCL) {
- // The header is basically 'struct { int; int; generic void *;
+ // The header is basically 'struct { int; int;
// custom_fields; }'. Assert that struct is packed.
- auto GenericAS =
- CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic);
- auto GenPtrAlign =
- CharUnits::fromQuantity(CGM.getTarget().getPointerAlign(GenericAS) / 8);
- auto GenPtrSize =
- CharUnits::fromQuantity(CGM.getTarget().getPointerWidth(GenericAS) / 8);
- assert(CGM.getIntSize() <= GenPtrSize);
- assert(CGM.getIntAlign() <= GenPtrAlign);
- assert((2 * CGM.getIntSize()).isMultipleOf(GenPtrAlign));
elementTypes.push_back(CGM.IntTy); /* total size */
elementTypes.push_back(CGM.IntTy); /* align */
- elementTypes.push_back(
- CGM.getOpenCLRuntime()
- .getGenericVoidPointerType()); /* invoke function */
- unsigned Offset =
- 2 * CGM.getIntSize().getQuantity() + GenPtrSize.getQuantity();
- unsigned BlockAlign = GenPtrAlign.getQuantity();
+ unsigned Offset = 2 * CGM.getIntSize().getQuantity();
+ unsigned BlockAlign = CGM.getIntAlign().getQuantity();
if (auto *Helper =
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
for (auto I : Helper->getCustomFieldTypes()) /* custom fields */ {
@@ -771,20 +758,12 @@
llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL;
- auto GenVoidPtrTy =
- IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy;
- LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default;
- auto GenVoidPtrSize = CharUnits::fromQuantity(
- CGM.getTarget().getPointerWidth(
- CGM.getContext().getTargetAddressSpace(GenVoidPtrAddr)) /
- 8);
// Using the computed layout, generate the actual block function.
bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda();
CodeGenFunction BlockCGF{CGM, true};
BlockCGF.SanOpts = SanOpts;
auto *InvokeFn = BlockCGF.GenerateBlockFunction(
CurGD, blockInfo, LocalDeclMap, isLambdaConv, blockInfo.CanBeGlobal);
- auto *blockFn = llvm::ConstantExpr::getPointerCast(InvokeFn, GenVoidPtrTy);
// If there is nothing to capture, we can emit this as a global block.
if (blockInfo.CanBeGlobal)
@@ -853,11 +832,12 @@
llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()),
getIntSize(), "block.align");
}
- addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
- if (!IsOpenCL)
+ if (!IsOpenCL) {
+ addHeaderField(llvm::ConstantExpr::getBitCast(InvokeFn, VoidPtrTy),
+ getPointerSize(), "block.invoke");
addHeaderField(descriptor, getPointerSize(), "block.descriptor");
- else if (auto *Helper =
- CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
+ } else if (auto *Helper =
+ CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {
addHeaderField(
I.first,
@@ -1060,38 +1040,23 @@
}
llvm::Type *CodeGenModule::getGenericBlockLiteralType() {
+ assert(!getLangOpts().OpenCL && "OpenCL does not need this");
+
if (GenericBlockLiteralType)
return GenericBlockLiteralType;
llvm::Type *BlockDescPtrTy = getBlockDescriptorType();
- if (getLangOpts().OpenCL) {
- // struct __opencl_block_literal_generic {
- // int __size;
- // int __align;
- // __generic void *__invoke;
- // /* custom fields */
- // };
- SmallVector<llvm::Type *, 8> StructFields(
- {IntTy, IntTy, getOpenCLRuntime().getGenericVoidPointerType()});
- if (auto *Helper = getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
- for (auto I : Helper->getCustomFieldTypes())
- StructFields.push_back(I);
- }
- GenericBlockLiteralType = llvm::StructType::create(
- StructFields, "struct.__opencl_block_literal_generic");
- } else {
- // struct __block_literal_generic {
- // void *__isa;
- // int __flags;
- // int __reserved;
- // void (*__invoke)(void *);
- // struct __block_descriptor *__descriptor;
- // };
- GenericBlockLiteralType =
- llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy,
- IntTy, IntTy, VoidPtrTy, BlockDescPtrTy);
- }
+ // struct __block_literal_generic {
+ // void *__isa;
+ // int __flags;
+ // int __reserved;
+ // void (*__invoke)(void *);
+ // struct __block_descriptor *__descriptor;
+ // };
+ GenericBlockLiteralType =
+ llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy,
+ IntTy, IntTy, VoidPtrTy, BlockDescPtrTy);
return GenericBlockLiteralType;
}
@@ -1102,27 +1067,21 @@
E->getCallee()->getType()->getAs<BlockPointerType>();
llvm::Value *BlockPtr = EmitScalarExpr(E->getCallee());
+ llvm::Value *FuncPtr;
- // Get a pointer to the generic block literal.
- // For OpenCL we generate generic AS void ptr to be able to reuse the same
- // block definition for blocks with captures generated as private AS local
- // variables and without captures generated as global AS program scope
- // variables.
- unsigned AddrSpace = 0;
- if (getLangOpts().OpenCL)
- AddrSpace = getContext().getTargetAddressSpace(LangAS::opencl_generic);
+ if (!CGM.getLangOpts().OpenCL) {
+ // Get a pointer to the generic block literal.
+ llvm::Type *BlockLiteralTy =
+ llvm::PointerType::get(CGM.getGenericBlockLiteralType(), 0);
- llvm::Type *BlockLiteralTy =
- llvm::PointerType::get(CGM.getGenericBlockLiteralType(), AddrSpace);
+ // Bitcast the callee to a block literal.
+ BlockPtr =
+ Builder.CreatePointerCast(BlockPtr, BlockLiteralTy, "block.literal");
- // Bitcast the callee to a block literal.
- BlockPtr =
- Builder.CreatePointerCast(BlockPtr, BlockLiteralTy, "block.literal");
-
- // Get the function pointer from the literal.
- llvm::Value *FuncPtr =
- Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr,
- CGM.getLangOpts().OpenCL ? 2 : 3);
+ // Get the function pointer from the literal.
+ FuncPtr =
+ Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr, 3);
+ }
// Add the block literal.
CallArgList Args;
@@ -1145,7 +1104,11 @@
EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arguments());
// Load the function.
- llvm::Value *Func = Builder.CreateAlignedLoad(FuncPtr, getPointerAlign());
+ llvm::Value *Func;
+ if (CGM.getLangOpts().OpenCL)
+ Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());
+ else
+ Func = Builder.CreateAlignedLoad(FuncPtr, getPointerAlign());
const FunctionType *FuncTy = FnType->castAs<FunctionType>();
const CGFunctionInfo &FnInfo =
@@ -1254,14 +1217,14 @@
// Reserved
fields.addInt(CGM.IntTy, 0);
+
+ // Function
+ fields.add(blockFn);
} else {
fields.addInt(CGM.IntTy, blockInfo.BlockSize.getQuantity());
fields.addInt(CGM.IntTy, blockInfo.BlockAlign.getQuantity());
}
- // Function
- fields.add(blockFn);
-
if (!IsOpenCL) {
// Descriptor
fields.add(buildBlockDescriptor(CGM, blockInfo));
@@ -1562,6 +1525,9 @@
case QualType::PCK_Struct:
return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct,
BlockFieldFlags());
+ case QualType::PCK_ARCWeak:
+ // We need to register __weak direct captures with the runtime.
+ return std::make_pair(BlockCaptureEntityKind::ARCWeak, Flags);
case QualType::PCK_ARCStrong:
// We need to retain the copied value for __strong direct captures.
// If it's a block pointer, we have to copy the block and assign that to
@@ -1579,10 +1545,6 @@
// Special rules for ARC captures:
Qualifiers QS = T.getQualifiers();
- // We need to register __weak direct captures with the runtime.
- if (QS.getObjCLifetime() == Qualifiers::OCL_Weak)
- return std::make_pair(BlockCaptureEntityKind::ARCWeak, Flags);
-
// Non-ARC captures of retainable pointers are strong and
// therefore require a call to _Block_object_assign.
if (!QS.getObjCLifetime() && !LangOpts.ObjCAutoRefCount)
@@ -2623,11 +2585,11 @@
}
}
- if (!CGM.getLangOpts().BlocksRuntimeOptional)
- return;
-
- if (GV->isDeclaration() && GV->hasExternalLinkage())
+ if (CGM.getLangOpts().BlocksRuntimeOptional && GV->isDeclaration() &&
+ GV->hasExternalLinkage())
GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
+
+ CGM.setDSOLocal(GV);
}
llvm::Constant *CodeGenModule::getBlockObjectDispose() {
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 49dfc60..79e571c 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -2611,11 +2611,12 @@
case Builtin::BI__builtin_addressof:
return RValue::get(EmitLValue(E->getArg(0)).getPointer());
case Builtin::BI__builtin_operator_new:
- return EmitBuiltinNewDeleteCall(FD->getType()->castAs<FunctionProtoType>(),
- E->getArg(0), false);
+ return EmitBuiltinNewDeleteCall(
+ E->getCallee()->getType()->castAs<FunctionProtoType>(), E, false);
case Builtin::BI__builtin_operator_delete:
- return EmitBuiltinNewDeleteCall(FD->getType()->castAs<FunctionProtoType>(),
- E->getArg(0), true);
+ return EmitBuiltinNewDeleteCall(
+ E->getCallee()->getType()->castAs<FunctionProtoType>(), E, true);
+
case Builtin::BI__noop:
// __noop always evaluates to an integer literal zero.
return RValue::get(ConstantInt::get(IntTy, 0));
@@ -3441,7 +3442,7 @@
static llvm::VectorType *GetNeonType(CodeGenFunction *CGF,
NeonTypeFlags TypeFlags,
- llvm::Triple::ArchType Arch,
+ bool HasLegalHalfType=true,
bool V1Ty=false) {
int IsQuad = TypeFlags.isQuad();
switch (TypeFlags.getEltType()) {
@@ -3452,9 +3453,7 @@
case NeonTypeFlags::Poly16:
return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
case NeonTypeFlags::Float16:
- // FIXME: Only AArch64 backend can so far properly handle half types.
- // Remove else part once ARM backend support for half is complete.
- if (Arch == llvm::Triple::aarch64)
+ if (HasLegalHalfType)
return llvm::VectorType::get(CGF->HalfTy, V1Ty ? 1 : (4 << IsQuad));
else
return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
@@ -3620,13 +3619,24 @@
NEONMAP1(vcaleq_v, arm_neon_vacge, 0),
NEONMAP1(vcalt_v, arm_neon_vacgt, 0),
NEONMAP1(vcaltq_v, arm_neon_vacgt, 0),
+ NEONMAP0(vceqz_v),
+ NEONMAP0(vceqzq_v),
+ NEONMAP0(vcgez_v),
+ NEONMAP0(vcgezq_v),
+ NEONMAP0(vcgtz_v),
+ NEONMAP0(vcgtzq_v),
+ NEONMAP0(vclez_v),
+ NEONMAP0(vclezq_v),
NEONMAP1(vcls_v, arm_neon_vcls, Add1ArgType),
NEONMAP1(vclsq_v, arm_neon_vcls, Add1ArgType),
+ NEONMAP0(vcltz_v),
+ NEONMAP0(vcltzq_v),
NEONMAP1(vclz_v, ctlz, Add1ArgType),
NEONMAP1(vclzq_v, ctlz, Add1ArgType),
NEONMAP1(vcnt_v, ctpop, Add1ArgType),
NEONMAP1(vcntq_v, ctpop, Add1ArgType),
NEONMAP1(vcvt_f16_f32, arm_neon_vcvtfp2hf, 0),
+ NEONMAP0(vcvt_f16_v),
NEONMAP1(vcvt_f32_f16, arm_neon_vcvthf2fp, 0),
NEONMAP0(vcvt_f32_v),
NEONMAP2(vcvt_n_f16_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
@@ -3690,6 +3700,7 @@
NEONMAP1(vcvtpq_u16_v, arm_neon_vcvtpu, 0),
NEONMAP1(vcvtpq_u32_v, arm_neon_vcvtpu, 0),
NEONMAP1(vcvtpq_u64_v, arm_neon_vcvtpu, 0),
+ NEONMAP0(vcvtq_f16_v),
NEONMAP0(vcvtq_f32_v),
NEONMAP2(vcvtq_n_f16_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvtq_n_f32_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
@@ -3858,8 +3869,18 @@
NEONMAP1(vcaleq_v, aarch64_neon_facge, 0),
NEONMAP1(vcalt_v, aarch64_neon_facgt, 0),
NEONMAP1(vcaltq_v, aarch64_neon_facgt, 0),
+ NEONMAP0(vceqz_v),
+ NEONMAP0(vceqzq_v),
+ NEONMAP0(vcgez_v),
+ NEONMAP0(vcgezq_v),
+ NEONMAP0(vcgtz_v),
+ NEONMAP0(vcgtzq_v),
+ NEONMAP0(vclez_v),
+ NEONMAP0(vclezq_v),
NEONMAP1(vcls_v, aarch64_neon_cls, Add1ArgType),
NEONMAP1(vclsq_v, aarch64_neon_cls, Add1ArgType),
+ NEONMAP0(vcltz_v),
+ NEONMAP0(vcltzq_v),
NEONMAP1(vclz_v, ctlz, Add1ArgType),
NEONMAP1(vclzq_v, ctlz, Add1ArgType),
NEONMAP1(vcnt_v, ctpop, Add1ArgType),
@@ -4338,8 +4359,9 @@
NeonTypeFlags Type(NeonTypeConst.getZExtValue());
bool Usgn = Type.isUnsigned();
bool Quad = Type.isQuad();
+ const bool HasLegalHalfType = getTarget().hasLegalHalfType();
- llvm::VectorType *VTy = GetNeonType(this, Type, Arch);
+ llvm::VectorType *VTy = GetNeonType(this, Type, HasLegalHalfType);
llvm::Type *Ty = VTy;
if (!Ty)
return nullptr;
@@ -4404,6 +4426,26 @@
Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
return EmitNeonCall(F, Ops, NameHint);
}
+ case NEON::BI__builtin_neon_vceqz_v:
+ case NEON::BI__builtin_neon_vceqzq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OEQ,
+ ICmpInst::ICMP_EQ, "vceqz");
+ case NEON::BI__builtin_neon_vcgez_v:
+ case NEON::BI__builtin_neon_vcgezq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGE,
+ ICmpInst::ICMP_SGE, "vcgez");
+ case NEON::BI__builtin_neon_vclez_v:
+ case NEON::BI__builtin_neon_vclezq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLE,
+ ICmpInst::ICMP_SLE, "vclez");
+ case NEON::BI__builtin_neon_vcgtz_v:
+ case NEON::BI__builtin_neon_vcgtzq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGT,
+ ICmpInst::ICMP_SGT, "vcgtz");
+ case NEON::BI__builtin_neon_vcltz_v:
+ case NEON::BI__builtin_neon_vcltzq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLT,
+ ICmpInst::ICMP_SLT, "vcltz");
case NEON::BI__builtin_neon_vclz_v:
case NEON::BI__builtin_neon_vclzq_v:
// We generate target-independent intrinsic, which needs a second argument
@@ -4413,13 +4455,15 @@
case NEON::BI__builtin_neon_vcvt_f32_v:
case NEON::BI__builtin_neon_vcvtq_f32_v:
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, Quad), Arch);
+ Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, Quad),
+ HasLegalHalfType);
return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
case NEON::BI__builtin_neon_vcvt_f16_v:
case NEON::BI__builtin_neon_vcvtq_f16_v:
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float16, false, Quad), Arch);
+ Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float16, false, Quad),
+ HasLegalHalfType);
return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
case NEON::BI__builtin_neon_vcvt_n_f16_v:
@@ -5528,7 +5572,8 @@
bool usgn = Type.isUnsigned();
bool rightShift = false;
- llvm::VectorType *VTy = GetNeonType(this, Type, Arch);
+ llvm::VectorType *VTy = GetNeonType(this, Type,
+ getTarget().hasLegalHalfType());
llvm::Type *Ty = VTy;
if (!Ty)
return nullptr;
@@ -5774,7 +5819,7 @@
// Determine the type of this overloaded NEON intrinsic.
NeonTypeFlags Type(Result.getZExtValue());
- llvm::VectorType *Ty = GetNeonType(&CGF, Type, Arch);
+ llvm::VectorType *Ty = GetNeonType(&CGF, Type);
if (!Ty)
return nullptr;
@@ -6828,7 +6873,7 @@
}
}
- llvm::VectorType *VTy = GetNeonType(this, Type, Arch);
+ llvm::VectorType *VTy = GetNeonType(this, Type);
llvm::Type *Ty = VTy;
if (!Ty)
return nullptr;
@@ -6893,7 +6938,7 @@
Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy);
llvm::Type *VTy = GetNeonType(this,
- NeonTypeFlags(NeonTypeFlags::Float64, false, true), Arch);
+ NeonTypeFlags(NeonTypeFlags::Float64, false, true));
Ops[2] = Builder.CreateBitCast(Ops[2], VTy);
Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
Value *F = CGM.getIntrinsic(Intrinsic::fma, DoubleTy);
@@ -7109,37 +7154,17 @@
Int = Intrinsic::trunc;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndz");
}
- case NEON::BI__builtin_neon_vceqz_v:
- case NEON::BI__builtin_neon_vceqzq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OEQ,
- ICmpInst::ICMP_EQ, "vceqz");
- case NEON::BI__builtin_neon_vcgez_v:
- case NEON::BI__builtin_neon_vcgezq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGE,
- ICmpInst::ICMP_SGE, "vcgez");
- case NEON::BI__builtin_neon_vclez_v:
- case NEON::BI__builtin_neon_vclezq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLE,
- ICmpInst::ICMP_SLE, "vclez");
- case NEON::BI__builtin_neon_vcgtz_v:
- case NEON::BI__builtin_neon_vcgtzq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGT,
- ICmpInst::ICMP_SGT, "vcgtz");
- case NEON::BI__builtin_neon_vcltz_v:
- case NEON::BI__builtin_neon_vcltzq_v:
- return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLT,
- ICmpInst::ICMP_SLT, "vcltz");
case NEON::BI__builtin_neon_vcvt_f64_v:
case NEON::BI__builtin_neon_vcvtq_f64_v:
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad), Arch);
+ Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad));
return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
case NEON::BI__builtin_neon_vcvt_f64_f32: {
assert(Type.getEltType() == NeonTypeFlags::Float64 && quad &&
"unexpected vcvt_f64_f32 builtin");
NeonTypeFlags SrcFlag = NeonTypeFlags(NeonTypeFlags::Float32, false, false);
- Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag, Arch));
+ Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag));
return Builder.CreateFPExt(Ops[0], Ty, "vcvt");
}
@@ -7147,7 +7172,7 @@
assert(Type.getEltType() == NeonTypeFlags::Float32 &&
"unexpected vcvt_f32_f64 builtin");
NeonTypeFlags SrcFlag = NeonTypeFlags(NeonTypeFlags::Float64, false, true);
- Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag, Arch));
+ Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag));
return Builder.CreateFPTrunc(Ops[0], Ty, "vcvt");
}
@@ -7236,6 +7261,16 @@
Int = Intrinsic::aarch64_neon_fmulx;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmulx");
}
+ case NEON::BI__builtin_neon_vmulxh_lane_f16:
+ case NEON::BI__builtin_neon_vmulxh_laneq_f16: {
+ // vmulx_lane should be mapped to Neon scalar mulx after
+ // extracting the scalar element
+ Ops.push_back(EmitScalarExpr(E->getArg(2)));
+ Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract");
+ Ops.pop_back();
+ Int = Intrinsic::aarch64_neon_fmulx;
+ return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vmulx");
+ }
case NEON::BI__builtin_neon_vmul_lane_v:
case NEON::BI__builtin_neon_vmul_laneq_v: {
// v1f64 vmul_lane should be mapped to Neon scalar mul lane
@@ -7244,7 +7279,7 @@
Quad = true;
Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
llvm::Type *VTy = GetNeonType(this,
- NeonTypeFlags(NeonTypeFlags::Float64, false, Quad), Arch);
+ NeonTypeFlags(NeonTypeFlags::Float64, false, Quad));
Ops[1] = Builder.CreateBitCast(Ops[1], VTy);
Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract");
Value *Result = Builder.CreateFMul(Ops[0], Ops[1]);
@@ -10502,31 +10537,30 @@
unsigned NumResults;
switch (BuiltinID) {
case NVPTX::BI__hmma_m16n16k16_ld_a:
- IID = isColMajor ? Intrinsic::nvvm_wmma_load_a_f16_col_stride
- : Intrinsic::nvvm_wmma_load_a_f16_row_stride;
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_load_a_f16_col_stride
+ : Intrinsic::nvvm_wmma_m16n16k16_load_a_f16_row_stride;
NumResults = 8;
break;
case NVPTX::BI__hmma_m16n16k16_ld_b:
- IID = isColMajor ? Intrinsic::nvvm_wmma_load_b_f16_col_stride
- : Intrinsic::nvvm_wmma_load_b_f16_row_stride;
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_load_b_f16_col_stride
+ : Intrinsic::nvvm_wmma_m16n16k16_load_b_f16_row_stride;
NumResults = 8;
break;
case NVPTX::BI__hmma_m16n16k16_ld_c_f16:
- IID = isColMajor ? Intrinsic::nvvm_wmma_load_c_f16_col_stride
- : Intrinsic::nvvm_wmma_load_c_f16_row_stride;
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_load_c_f16_col_stride
+ : Intrinsic::nvvm_wmma_m16n16k16_load_c_f16_row_stride;
NumResults = 4;
break;
case NVPTX::BI__hmma_m16n16k16_ld_c_f32:
- IID = isColMajor ? Intrinsic::nvvm_wmma_load_c_f32_col_stride
- : Intrinsic::nvvm_wmma_load_c_f32_row_stride;
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_load_c_f32_col_stride
+ : Intrinsic::nvvm_wmma_m16n16k16_load_c_f32_row_stride;
NumResults = 8;
break;
default:
llvm_unreachable("Unexpected builtin ID.");
}
Value *Result =
- Builder.CreateCall(CGM.getIntrinsic(IID),
- {Builder.CreatePointerCast(Src, VoidPtrTy), Ldm});
+ Builder.CreateCall(CGM.getIntrinsic(IID, Src->getType()), {Src, Ldm});
// Save returned values.
for (unsigned i = 0; i < NumResults; ++i) {
@@ -10554,21 +10588,20 @@
// for some reason nvcc builtins use _c_.
switch (BuiltinID) {
case NVPTX::BI__hmma_m16n16k16_st_c_f16:
- IID = isColMajor ? Intrinsic::nvvm_wmma_store_d_f16_col_stride
- : Intrinsic::nvvm_wmma_store_d_f16_row_stride;
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_store_d_f16_col_stride
+ : Intrinsic::nvvm_wmma_m16n16k16_store_d_f16_row_stride;
NumResults = 4;
break;
case NVPTX::BI__hmma_m16n16k16_st_c_f32:
- IID = isColMajor ? Intrinsic::nvvm_wmma_store_d_f32_col_stride
- : Intrinsic::nvvm_wmma_store_d_f32_row_stride;
+ IID = isColMajor ? Intrinsic::nvvm_wmma_m16n16k16_store_d_f32_col_stride
+ : Intrinsic::nvvm_wmma_m16n16k16_store_d_f32_row_stride;
break;
default:
llvm_unreachable("Unexpected builtin ID.");
}
- Function *Intrinsic = CGM.getIntrinsic(IID);
+ Function *Intrinsic = CGM.getIntrinsic(IID, Dst->getType());
llvm::Type *ParamType = Intrinsic->getFunctionType()->getParamType(1);
- SmallVector<Value *, 10> Values;
- Values.push_back(Builder.CreatePointerCast(Dst, VoidPtrTy));
+ SmallVector<Value *, 10> Values = {Dst};
for (unsigned i = 0; i < NumResults; ++i) {
Value *V = Builder.CreateAlignedLoad(
Builder.CreateGEP(Src.getPointer(), llvm::ConstantInt::get(IntTy, i)),
@@ -10580,8 +10613,8 @@
return Result;
}
- // BI__hmma_m16n16k16_mma_<Dtype><CType>(d, a, b, c, layout, satf)
- // --> Intrinsic::nvvm_wmma_mma_sync<layout A,B><DType><CType><Satf>
+ // BI__hmma_m16n16k16_mma_<Dtype><CType>(d, a, b, c, layout, satf) -->
+ // Intrinsic::nvvm_wmma_m16n16k16_mma_sync<layout A,B><DType><CType><Satf>
case NVPTX::BI__hmma_m16n16k16_mma_f16f16:
case NVPTX::BI__hmma_m16n16k16_mma_f32f16:
case NVPTX::BI__hmma_m16n16k16_mma_f32f32:
@@ -10602,15 +10635,15 @@
bool Satf = SatfArg.getSExtValue();
// clang-format off
-#define MMA_VARIANTS(type) {{ \
- Intrinsic::nvvm_wmma_mma_sync_row_row_##type, \
- Intrinsic::nvvm_wmma_mma_sync_row_row_##type##_satfinite, \
- Intrinsic::nvvm_wmma_mma_sync_row_col_##type, \
- Intrinsic::nvvm_wmma_mma_sync_row_col_##type##_satfinite, \
- Intrinsic::nvvm_wmma_mma_sync_col_row_##type, \
- Intrinsic::nvvm_wmma_mma_sync_col_row_##type##_satfinite, \
- Intrinsic::nvvm_wmma_mma_sync_col_col_##type, \
- Intrinsic::nvvm_wmma_mma_sync_col_col_##type##_satfinite \
+#define MMA_VARIANTS(type) {{ \
+ Intrinsic::nvvm_wmma_m16n16k16_mma_row_row_##type, \
+ Intrinsic::nvvm_wmma_m16n16k16_mma_row_row_##type##_satfinite, \
+ Intrinsic::nvvm_wmma_m16n16k16_mma_row_col_##type, \
+ Intrinsic::nvvm_wmma_m16n16k16_mma_row_col_##type##_satfinite, \
+ Intrinsic::nvvm_wmma_m16n16k16_mma_col_row_##type, \
+ Intrinsic::nvvm_wmma_m16n16k16_mma_col_row_##type##_satfinite, \
+ Intrinsic::nvvm_wmma_m16n16k16_mma_col_col_##type, \
+ Intrinsic::nvvm_wmma_m16n16k16_mma_col_col_##type##_satfinite \
}}
// clang-format on
@@ -10739,6 +10772,93 @@
SmallVector<llvm::Value *, 4> Ops;
Intrinsic::ID ID = Intrinsic::not_intrinsic;
+ auto MakeCircLd = [&](unsigned IntID, bool HasImm = true) {
+ // The base pointer is passed by address, so it needs to be loaded.
+ Address BP = EmitPointerWithAlignment(E->getArg(0));
+ BP = Address(Builder.CreateBitCast(BP.getPointer(), Int8PtrPtrTy),
+ BP.getAlignment());
+ llvm::Value *Base = Builder.CreateLoad(BP);
+ // Operands are Base, Increment, Modifier, Start.
+ if (HasImm)
+ Ops = { Base, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)),
+ EmitScalarExpr(E->getArg(3)) };
+ else
+ Ops = { Base, EmitScalarExpr(E->getArg(1)),
+ EmitScalarExpr(E->getArg(2)) };
+
+ llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(IntID), Ops);
+ llvm::Value *NewBase = Builder.CreateExtractValue(Result, 1);
+ llvm::Value *LV = Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)),
+ NewBase->getType()->getPointerTo());
+ Address Dest = EmitPointerWithAlignment(E->getArg(0));
+ // The intrinsic generates two results. The new value for the base pointer
+ // needs to be stored.
+ Builder.CreateAlignedStore(NewBase, LV, Dest.getAlignment());
+ return Builder.CreateExtractValue(Result, 0);
+ };
+
+ auto MakeCircSt = [&](unsigned IntID, bool HasImm = true) {
+ // The base pointer is passed by address, so it needs to be loaded.
+ Address BP = EmitPointerWithAlignment(E->getArg(0));
+ BP = Address(Builder.CreateBitCast(BP.getPointer(), Int8PtrPtrTy),
+ BP.getAlignment());
+ llvm::Value *Base = Builder.CreateLoad(BP);
+ // Operands are Base, Increment, Modifier, Value, Start.
+ if (HasImm)
+ Ops = { Base, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)),
+ EmitScalarExpr(E->getArg(3)), EmitScalarExpr(E->getArg(4)) };
+ else
+ Ops = { Base, EmitScalarExpr(E->getArg(1)),
+ EmitScalarExpr(E->getArg(2)), EmitScalarExpr(E->getArg(3)) };
+
+ llvm::Value *NewBase = Builder.CreateCall(CGM.getIntrinsic(IntID), Ops);
+ llvm::Value *LV = Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)),
+ NewBase->getType()->getPointerTo());
+ Address Dest = EmitPointerWithAlignment(E->getArg(0));
+ // The intrinsic generates one result, which is the new value for the base
+ // pointer. It needs to be stored.
+ return Builder.CreateAlignedStore(NewBase, LV, Dest.getAlignment());
+ };
+
+ // Handle the conversion of bit-reverse load intrinsics to bit code.
+ // The intrinsic call after this function only reads from memory and the
+ // write to memory is dealt by the store instruction.
+ auto MakeBrevLd = [&](unsigned IntID, llvm::Type *DestTy) {
+ // The intrinsic generates one result, which is the new value for the base
+ // pointer. It needs to be returned. The result of the load instruction is
+ // passed to intrinsic by address, so the value needs to be stored.
+ llvm::Value *BaseAddress =
+ Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), Int8PtrTy);
+
+ // Expressions like &(*pt++) will be incremented per evaluation.
+ // EmitPointerWithAlignment and EmitScalarExpr evaluates the expression
+ // per call.
+ Address DestAddr = EmitPointerWithAlignment(E->getArg(1));
+ DestAddr = Address(Builder.CreateBitCast(DestAddr.getPointer(), Int8PtrTy),
+ DestAddr.getAlignment());
+ llvm::Value *DestAddress = DestAddr.getPointer();
+
+ // Operands are Base, Dest, Modifier.
+ // The intrinsic format in LLVM IR is defined as
+ // { ValueType, i8* } (i8*, i32).
+ Ops = {BaseAddress, EmitScalarExpr(E->getArg(2))};
+
+ llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(IntID), Ops);
+ // The value needs to be stored as the variable is passed by reference.
+ llvm::Value *DestVal = Builder.CreateExtractValue(Result, 0);
+
+ // The store needs to be truncated to fit the destination type.
+ // While i32 and i64 are natively supported on Hexagon, i8 and i16 needs
+ // to be handled with stores of respective destination type.
+ DestVal = Builder.CreateTrunc(DestVal, DestTy);
+
+ llvm::Value *DestForStore =
+ Builder.CreateBitCast(DestAddress, DestVal->getType()->getPointerTo());
+ Builder.CreateAlignedStore(DestVal, DestForStore, DestAddr.getAlignment());
+ // The updated value of the base pointer is returned.
+ return Builder.CreateExtractValue(Result, 1);
+ };
+
switch (BuiltinID) {
case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry:
case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B: {
@@ -10784,6 +10904,64 @@
Builder.CreateAlignedStore(Vprd, Base, Dest.getAlignment());
return Builder.CreateExtractValue(Result, 0);
}
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrub_pci:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrub_pci);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrb_pci:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrb_pci);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadruh_pci:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadruh_pci);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrh_pci:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrh_pci);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadri_pci:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadri_pci);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrd_pci:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrd_pci);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrub_pcr:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrub_pcr, /*HasImm=*/false);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrb_pcr:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrb_pcr, /*HasImm=*/false);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadruh_pcr:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadruh_pcr, /*HasImm=*/false);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrh_pcr:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrh_pcr, /*HasImm=*/false);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadri_pcr:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadri_pcr, /*HasImm=*/false);
+ case Hexagon::BI__builtin_HEXAGON_L2_loadrd_pcr:
+ return MakeCircLd(Intrinsic::hexagon_L2_loadrd_pcr, /*HasImm=*/false);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerb_pci:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerb_pci);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerh_pci:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerh_pci);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerf_pci:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerf_pci);
+ case Hexagon::BI__builtin_HEXAGON_S2_storeri_pci:
+ return MakeCircSt(Intrinsic::hexagon_S2_storeri_pci);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerd_pci:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerd_pci);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerb_pcr:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerb_pcr, /*HasImm=*/false);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerh_pcr:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerh_pcr, /*HasImm=*/false);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerf_pcr:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerf_pcr, /*HasImm=*/false);
+ case Hexagon::BI__builtin_HEXAGON_S2_storeri_pcr:
+ return MakeCircSt(Intrinsic::hexagon_S2_storeri_pcr, /*HasImm=*/false);
+ case Hexagon::BI__builtin_HEXAGON_S2_storerd_pcr:
+ return MakeCircSt(Intrinsic::hexagon_S2_storerd_pcr, /*HasImm=*/false);
+ case Hexagon::BI__builtin_brev_ldub:
+ return MakeBrevLd(Intrinsic::hexagon_L2_loadrub_pbr, Int8Ty);
+ case Hexagon::BI__builtin_brev_ldb:
+ return MakeBrevLd(Intrinsic::hexagon_L2_loadrb_pbr, Int8Ty);
+ case Hexagon::BI__builtin_brev_lduh:
+ return MakeBrevLd(Intrinsic::hexagon_L2_loadruh_pbr, Int16Ty);
+ case Hexagon::BI__builtin_brev_ldh:
+ return MakeBrevLd(Intrinsic::hexagon_L2_loadrh_pbr, Int16Ty);
+ case Hexagon::BI__builtin_brev_ldw:
+ return MakeBrevLd(Intrinsic::hexagon_L2_loadri_pbr, Int32Ty);
+ case Hexagon::BI__builtin_brev_ldd:
+ return MakeBrevLd(Intrinsic::hexagon_L2_loadrd_pbr, Int64Ty);
+ default:
+ break;
} // switch
return nullptr;
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 738c635..dfae7d5 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -242,6 +242,11 @@
if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
GD = GlobalDecl(CD, toCXXCtorType(Type));
} else {
+ // Always alias equivalent complete destructors to base destructors in the
+ // MS ABI.
+ if (getTarget().getCXXABI().isMicrosoft() &&
+ Type == StructorType::Complete && MD->getParent()->getNumVBases() == 0)
+ Type = StructorType::Base;
GD = GlobalDecl(cast<CXXDestructorDecl>(MD), toCXXDtorType(Type));
}
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
index a27c3e9..0611749 100644
--- a/lib/CodeGen/CGCXXABI.cpp
+++ b/lib/CodeGen/CGCXXABI.cpp
@@ -287,6 +287,20 @@
return nullptr;
}
+void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const {
+ // Assume the base C++ ABI has no special rules for destructor variants.
+ CGM.setDLLImportDLLExport(GV, Dtor);
+}
+
+llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage(
+ GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const {
+ // Delegate back to CGM by default.
+ return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage,
+ /*isConstantVariable=*/false);
+}
+
bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
return false;
}
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index 65a4c3d..1e4e132 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -319,6 +319,14 @@
virtual bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
CXXDtorType DT) const = 0;
+ virtual void setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const;
+
+ virtual llvm::GlobalValue::LinkageTypes
+ getCXXDestructorLinkage(GVALinkage Linkage, const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const;
+
/// Emit destructor variants required by this ABI.
virtual void EmitCXXDestructors(const CXXDestructorDecl *D) = 0;
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index ebba250..148a12e 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -29,15 +29,15 @@
#include "clang/CodeGen/SwiftCallingConv.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Analysis/Utils/Local.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Attributes.h"
-#include "llvm/IR/CallingConv.h"
#include "llvm/IR/CallSite.h"
+#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
-#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicInst.h"
-#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/IR/Intrinsics.h"
using namespace clang;
using namespace CodeGen;
@@ -64,6 +64,7 @@
case CC_PreserveMost: return llvm::CallingConv::PreserveMost;
case CC_PreserveAll: return llvm::CallingConv::PreserveAll;
case CC_Swift: return llvm::CallingConv::Swift;
+ case CC_CUDAKernel: return CGM.getTargetCodeGenInfo().getCUDAKernelCallingConv();
}
}
@@ -803,6 +804,7 @@
FI->NoReturn = info.getNoReturn();
FI->ReturnsRetained = info.getProducesResult();
FI->NoCallerSavedRegs = info.getNoCallerSavedRegs();
+ FI->NoCfCheck = info.getNoCfCheck();
FI->Required = required;
FI->HasRegParm = info.getHasRegParm();
FI->RegParm = info.getRegParm();
@@ -1040,42 +1042,49 @@
}
void CodeGenFunction::ExpandTypeToArgs(
- QualType Ty, RValue RV, llvm::FunctionType *IRFuncTy,
+ QualType Ty, CallArg Arg, llvm::FunctionType *IRFuncTy,
SmallVectorImpl<llvm::Value *> &IRCallArgs, unsigned &IRCallArgPos) {
auto Exp = getTypeExpansion(Ty, getContext());
if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) {
- forConstantArrayExpansion(*this, CAExp, RV.getAggregateAddress(),
- [&](Address EltAddr) {
- RValue EltRV =
- convertTempToRValue(EltAddr, CAExp->EltTy, SourceLocation());
- ExpandTypeToArgs(CAExp->EltTy, EltRV, IRFuncTy, IRCallArgs, IRCallArgPos);
- });
+ Address Addr = Arg.hasLValue() ? Arg.getKnownLValue().getAddress()
+ : Arg.getKnownRValue().getAggregateAddress();
+ forConstantArrayExpansion(
+ *this, CAExp, Addr, [&](Address EltAddr) {
+ CallArg EltArg = CallArg(
+ convertTempToRValue(EltAddr, CAExp->EltTy, SourceLocation()),
+ CAExp->EltTy);
+ ExpandTypeToArgs(CAExp->EltTy, EltArg, IRFuncTy, IRCallArgs,
+ IRCallArgPos);
+ });
} else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) {
- Address This = RV.getAggregateAddress();
+ Address This = Arg.hasLValue() ? Arg.getKnownLValue().getAddress()
+ : Arg.getKnownRValue().getAggregateAddress();
for (const CXXBaseSpecifier *BS : RExp->Bases) {
// Perform a single step derived-to-base conversion.
Address Base =
GetAddressOfBaseClass(This, Ty->getAsCXXRecordDecl(), &BS, &BS + 1,
/*NullCheckValue=*/false, SourceLocation());
- RValue BaseRV = RValue::getAggregate(Base);
+ CallArg BaseArg = CallArg(RValue::getAggregate(Base), BS->getType());
// Recurse onto bases.
- ExpandTypeToArgs(BS->getType(), BaseRV, IRFuncTy, IRCallArgs,
+ ExpandTypeToArgs(BS->getType(), BaseArg, IRFuncTy, IRCallArgs,
IRCallArgPos);
}
LValue LV = MakeAddrLValue(This, Ty);
for (auto FD : RExp->Fields) {
- RValue FldRV = EmitRValueForField(LV, FD, SourceLocation());
- ExpandTypeToArgs(FD->getType(), FldRV, IRFuncTy, IRCallArgs,
+ CallArg FldArg =
+ CallArg(EmitRValueForField(LV, FD, SourceLocation()), FD->getType());
+ ExpandTypeToArgs(FD->getType(), FldArg, IRFuncTy, IRCallArgs,
IRCallArgPos);
}
} else if (isa<ComplexExpansion>(Exp.get())) {
- ComplexPairTy CV = RV.getComplexVal();
+ ComplexPairTy CV = Arg.getKnownRValue().getComplexVal();
IRCallArgs[IRCallArgPos++] = CV.first;
IRCallArgs[IRCallArgPos++] = CV.second;
} else {
assert(isa<NoExpansion>(Exp.get()));
+ auto RV = Arg.getKnownRValue();
assert(RV.isScalar() &&
"Unexpected non-scalar rvalue during struct expansion.");
@@ -1843,13 +1852,15 @@
RetAttrs.addAttribute(llvm::Attribute::NonNull);
if (TargetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
FuncAttrs.addAttribute("no_caller_saved_registers");
+ if (TargetDecl->hasAttr<AnyX86NoCfCheckAttr>())
+ FuncAttrs.addAttribute(llvm::Attribute::NoCfCheck);
HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>();
if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) {
Optional<unsigned> NumElemsParam;
- if (AllocSize->numElemsParam().isValid())
- NumElemsParam = AllocSize->numElemsParam().getLLVMIndex();
- FuncAttrs.addAllocSizeAttr(AllocSize->elemSizeParam().getLLVMIndex(),
+ if (AllocSize->getNumElemsParam().isValid())
+ NumElemsParam = AllocSize->getNumElemsParam().getLLVMIndex();
+ FuncAttrs.addAllocSizeAttr(AllocSize->getElemSizeParam().getLLVMIndex(),
NumElemsParam);
}
}
@@ -3417,13 +3428,17 @@
assert(InitialArgSize + 1 == Args.size() &&
"The code below depends on only adding one arg per EmitCallArg");
(void)InitialArgSize;
- RValue RVArg = Args.back().RV;
- EmitNonNullArgCheck(RVArg, ArgTypes[Idx], (*Arg)->getExprLoc(), AC,
- ParamsToSkip + Idx);
- // @llvm.objectsize should never have side-effects and shouldn't need
- // destruction/cleanups, so we can safely "emit" it after its arg,
- // regardless of right-to-leftness
- MaybeEmitImplicitObjectSize(Idx, *Arg, RVArg);
+ // Since pointer argument are never emitted as LValue, it is safe to emit
+ // non-null argument check for r-value only.
+ if (!Args.back().hasLValue()) {
+ RValue RVArg = Args.back().getKnownRValue();
+ EmitNonNullArgCheck(RVArg, ArgTypes[Idx], (*Arg)->getExprLoc(), AC,
+ ParamsToSkip + Idx);
+ // @llvm.objectsize should never have side-effects and shouldn't need
+ // destruction/cleanups, so we can safely "emit" it after its arg,
+ // regardless of right-to-leftness
+ MaybeEmitImplicitObjectSize(Idx, *Arg, RVArg);
+ }
}
if (!LeftToRight) {
@@ -3470,6 +3485,31 @@
} // end anonymous namespace
+RValue CallArg::getRValue(CodeGenFunction &CGF) const {
+ if (!HasLV)
+ return RV;
+ LValue Copy = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty), Ty);
+ CGF.EmitAggregateCopy(Copy, LV, Ty, LV.isVolatile());
+ IsUsed = true;
+ return RValue::getAggregate(Copy.getAddress());
+}
+
+void CallArg::copyInto(CodeGenFunction &CGF, Address Addr) const {
+ LValue Dst = CGF.MakeAddrLValue(Addr, Ty);
+ if (!HasLV && RV.isScalar())
+ CGF.EmitStoreOfScalar(RV.getScalarVal(), Dst, /*init=*/true);
+ else if (!HasLV && RV.isComplex())
+ CGF.EmitStoreOfComplex(RV.getComplexVal(), Dst, /*init=*/true);
+ else {
+ auto Addr = HasLV ? LV.getAddress() : RV.getAggregateAddress();
+ LValue SrcLV = CGF.MakeAddrLValue(Addr, Ty);
+ CGF.EmitAggregateCopy(Dst, SrcLV, Ty,
+ HasLV ? LV.isVolatileQualified()
+ : RV.isVolatileQualified());
+ }
+ IsUsed = true;
+}
+
void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
QualType type) {
DisableDebugLocationUpdates Dis(*this, E);
@@ -3501,24 +3541,13 @@
else
Slot = CreateAggTemp(type, "agg.tmp");
- bool DestroyedInCallee = true, NeedsEHCleanup = true;
- if (const auto *RD = type->getAsCXXRecordDecl()) {
- DestroyedInCallee =
- RD && RD->hasNonTrivialDestructor() &&
- (CGM.getCXXABI().getRecordArgABI(RD) != CGCXXABI::RAA_Default ||
- RD->hasTrivialABIOverride());
- } else {
- NeedsEHCleanup = needsEHCleanup(type.isDestructedType());
- }
-
- if (DestroyedInCallee)
- Slot.setExternallyDestructed();
+ Slot.setExternallyDestructed();
EmitAggExpr(E, Slot);
RValue RV = Slot.asRValue();
args.add(RV, type);
- if (DestroyedInCallee && NeedsEHCleanup) {
+ if (type->getAsCXXRecordDecl() || needsEHCleanup(type.isDestructedType())) {
// Create a no-op GEP between the placeholder and the cleanup so we can
// RAUW it successfully. It also serves as a marker of the first
// instruction where the cleanup is active.
@@ -3535,15 +3564,7 @@
cast<CastExpr>(E)->getCastKind() == CK_LValueToRValue) {
LValue L = EmitLValue(cast<CastExpr>(E)->getSubExpr());
assert(L.isSimple());
- if (L.getAlignment() >= getContext().getTypeAlignInChars(type)) {
- args.add(L.asAggregateRValue(), type, /*NeedsCopy*/true);
- } else {
- // We can't represent a misaligned lvalue in the CallArgList, so copy
- // to an aligned temporary now.
- LValue Dest = MakeAddrLValue(CreateMemTemp(type), type);
- EmitAggregateCopy(Dest, L, type, L.isVolatile());
- args.add(RValue::getAggregate(Dest.getAddress()), type);
- }
+ args.addUncopiedAggregate(L, type);
return;
}
@@ -3701,16 +3722,6 @@
return llvm::CallSite(Inst);
}
-/// \brief Store a non-aggregate value to an address to initialize it. For
-/// initialization, a non-atomic store will be used.
-static void EmitInitStoreOfNonAggregate(CodeGenFunction &CGF, RValue Src,
- LValue Dst) {
- if (Src.isScalar())
- CGF.EmitStoreOfScalar(Src.getScalarVal(), Dst, /*init=*/true);
- else
- CGF.EmitStoreOfComplex(Src.getComplexVal(), Dst, /*init=*/true);
-}
-
void CodeGenFunction::deferPlaceholderReplacement(llvm::Instruction *Old,
llvm::Value *New) {
DeferredReplacements.push_back(std::make_pair(Old, New));
@@ -3771,7 +3782,7 @@
// If the call returns a temporary with struct return, create a temporary
// alloca to hold the result, unless one is given to us.
Address SRetPtr = Address::invalid();
- size_t UnusedReturnSize = 0;
+ llvm::Value *UnusedReturnSizePtr = nullptr;
if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) {
if (!ReturnValue.isNull()) {
SRetPtr = ReturnValue.getValue();
@@ -3780,8 +3791,7 @@
if (HaveInsertPoint() && ReturnValue.isUnused()) {
uint64_t size =
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
- if (EmitLifetimeStart(size, SRetPtr.getPointer()))
- UnusedReturnSize = size;
+ UnusedReturnSizePtr = EmitLifetimeStart(size, SRetPtr.getPointer());
}
}
if (IRFunctionArgs.hasSRetArg()) {
@@ -3803,7 +3813,6 @@
for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
I != E; ++I, ++info_it, ++ArgNo) {
const ABIArgInfo &ArgInfo = info_it->info;
- RValue RV = I->RV;
// Insert a padding argument to ensure proper alignment.
if (IRFunctionArgs.hasPaddingArg(ArgNo))
@@ -3817,13 +3826,16 @@
case ABIArgInfo::InAlloca: {
assert(NumIRArgs == 0);
assert(getTarget().getTriple().getArch() == llvm::Triple::x86);
- if (RV.isAggregate()) {
+ if (I->isAggregate()) {
// Replace the placeholder with the appropriate argument slot GEP.
+ Address Addr = I->hasLValue()
+ ? I->getKnownLValue().getAddress()
+ : I->getKnownRValue().getAggregateAddress();
llvm::Instruction *Placeholder =
- cast<llvm::Instruction>(RV.getAggregatePointer());
+ cast<llvm::Instruction>(Addr.getPointer());
CGBuilderTy::InsertPoint IP = Builder.saveIP();
Builder.SetInsertPoint(Placeholder);
- Address Addr = createInAllocaStructGEP(ArgInfo.getInAllocaFieldIndex());
+ Addr = createInAllocaStructGEP(ArgInfo.getInAllocaFieldIndex());
Builder.restoreIP(IP);
deferPlaceholderReplacement(Placeholder, Addr.getPointer());
} else {
@@ -3836,22 +3848,20 @@
// from {}* to (%struct.foo*)*.
if (Addr.getType() != MemType)
Addr = Builder.CreateBitCast(Addr, MemType);
- LValue argLV = MakeAddrLValue(Addr, I->Ty);
- EmitInitStoreOfNonAggregate(*this, RV, argLV);
+ I->copyInto(*this, Addr);
}
break;
}
case ABIArgInfo::Indirect: {
assert(NumIRArgs == 1);
- if (RV.isScalar() || RV.isComplex()) {
+ if (!I->isAggregate()) {
// Make a temporary alloca to pass the argument.
Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
"indirect-arg-temp", false);
IRCallArgs[FirstIRArg] = Addr.getPointer();
- LValue argLV = MakeAddrLValue(Addr, I->Ty);
- EmitInitStoreOfNonAggregate(*this, RV, argLV);
+ I->copyInto(*this, Addr);
} else {
// We want to avoid creating an unnecessary temporary+copy here;
// however, we need one in three cases:
@@ -3859,32 +3869,51 @@
// source. (This case doesn't occur on any common architecture.)
// 2. If the argument is byval, RV is not sufficiently aligned, and
// we cannot force it to be sufficiently aligned.
- // 3. If the argument is byval, but RV is located in an address space
- // different than that of the argument (0).
- Address Addr = RV.getAggregateAddress();
+ // 3. If the argument is byval, but RV is not located in default
+ // or alloca address space.
+ Address Addr = I->hasLValue()
+ ? I->getKnownLValue().getAddress()
+ : I->getKnownRValue().getAggregateAddress();
+ llvm::Value *V = Addr.getPointer();
CharUnits Align = ArgInfo.getIndirectAlign();
const llvm::DataLayout *TD = &CGM.getDataLayout();
- const unsigned RVAddrSpace = Addr.getType()->getAddressSpace();
- const unsigned ArgAddrSpace =
- (FirstIRArg < IRFuncTy->getNumParams()
- ? IRFuncTy->getParamType(FirstIRArg)->getPointerAddressSpace()
- : 0);
- if ((!ArgInfo.getIndirectByVal() && I->NeedsCopy) ||
- (ArgInfo.getIndirectByVal() && Addr.getAlignment() < Align &&
- llvm::getOrEnforceKnownAlignment(Addr.getPointer(),
- Align.getQuantity(), *TD)
- < Align.getQuantity()) ||
- (ArgInfo.getIndirectByVal() && (RVAddrSpace != ArgAddrSpace))) {
+
+ assert((FirstIRArg >= IRFuncTy->getNumParams() ||
+ IRFuncTy->getParamType(FirstIRArg)->getPointerAddressSpace() ==
+ TD->getAllocaAddrSpace()) &&
+ "indirect argument must be in alloca address space");
+
+ bool NeedCopy = false;
+
+ if (Addr.getAlignment() < Align &&
+ llvm::getOrEnforceKnownAlignment(V, Align.getQuantity(), *TD) <
+ Align.getQuantity()) {
+ NeedCopy = true;
+ } else if (I->hasLValue()) {
+ auto LV = I->getKnownLValue();
+ auto AS = LV.getAddressSpace();
+ if ((!ArgInfo.getIndirectByVal() &&
+ (LV.getAlignment() >=
+ getContext().getTypeAlignInChars(I->Ty))) ||
+ (ArgInfo.getIndirectByVal() &&
+ ((AS != LangAS::Default && AS != LangAS::opencl_private &&
+ AS != CGM.getASTAllocaAddressSpace())))) {
+ NeedCopy = true;
+ }
+ }
+ if (NeedCopy) {
// Create an aligned temporary, and copy to it.
Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
"byval-temp", false);
IRCallArgs[FirstIRArg] = AI.getPointer();
- LValue Dest = MakeAddrLValue(AI, I->Ty);
- LValue Src = MakeAddrLValue(Addr, I->Ty);
- EmitAggregateCopy(Dest, Src, I->Ty, RV.isVolatileQualified());
+ I->copyInto(*this, AI);
} else {
// Skip the extra memcpy call.
- IRCallArgs[FirstIRArg] = Addr.getPointer();
+ auto *T = V->getType()->getPointerElementType()->getPointerTo(
+ CGM.getDataLayout().getAllocaAddrSpace());
+ IRCallArgs[FirstIRArg] = getTargetHooks().performAddrSpaceCast(
+ *this, V, LangAS::Default, CGM.getASTAllocaAddressSpace(), T,
+ true);
}
}
break;
@@ -3901,10 +3930,12 @@
ArgInfo.getDirectOffset() == 0) {
assert(NumIRArgs == 1);
llvm::Value *V;
- if (RV.isScalar())
- V = RV.getScalarVal();
+ if (!I->isAggregate())
+ V = I->getKnownRValue().getScalarVal();
else
- V = Builder.CreateLoad(RV.getAggregateAddress());
+ V = Builder.CreateLoad(
+ I->hasLValue() ? I->getKnownLValue().getAddress()
+ : I->getKnownRValue().getAggregateAddress());
// Implement swifterror by copying into a new swifterror argument.
// We'll write back in the normal path out of the call.
@@ -3942,12 +3973,12 @@
// FIXME: Avoid the conversion through memory if possible.
Address Src = Address::invalid();
- if (RV.isScalar() || RV.isComplex()) {
+ if (!I->isAggregate()) {
Src = CreateMemTemp(I->Ty, "coerce");
- LValue SrcLV = MakeAddrLValue(Src, I->Ty);
- EmitInitStoreOfNonAggregate(*this, RV, SrcLV);
+ I->copyInto(*this, Src);
} else {
- Src = RV.getAggregateAddress();
+ Src = I->hasLValue() ? I->getKnownLValue().getAddress()
+ : I->getKnownRValue().getAggregateAddress();
}
// If the value is offset in memory, apply the offset now.
@@ -4001,22 +4032,23 @@
llvm::Value *tempSize = nullptr;
Address addr = Address::invalid();
- if (RV.isAggregate()) {
- addr = RV.getAggregateAddress();
+ if (I->isAggregate()) {
+ addr = I->hasLValue() ? I->getKnownLValue().getAddress()
+ : I->getKnownRValue().getAggregateAddress();
+
} else {
+ RValue RV = I->getKnownRValue();
assert(RV.isScalar()); // complex should always just be direct
llvm::Type *scalarType = RV.getScalarVal()->getType();
auto scalarSize = CGM.getDataLayout().getTypeAllocSize(scalarType);
auto scalarAlign = CGM.getDataLayout().getPrefTypeAlignment(scalarType);
- tempSize = llvm::ConstantInt::get(CGM.Int64Ty, scalarSize);
-
// Materialize to a temporary.
addr = CreateTempAlloca(RV.getScalarVal()->getType(),
CharUnits::fromQuantity(std::max(layout->getAlignment(),
scalarAlign)));
- EmitLifetimeStart(scalarSize, addr.getPointer());
+ tempSize = EmitLifetimeStart(scalarSize, addr.getPointer());
Builder.CreateStore(RV.getScalarVal(), addr);
}
@@ -4042,7 +4074,7 @@
case ABIArgInfo::Expand:
unsigned IRArgPos = FirstIRArg;
- ExpandTypeToArgs(I->Ty, RV, IRFuncTy, IRCallArgs, IRArgPos);
+ ExpandTypeToArgs(I->Ty, *I, IRFuncTy, IRCallArgs, IRArgPos);
assert(IRArgPos == FirstIRArg + NumIRArgs);
break;
}
@@ -4190,6 +4222,15 @@
CannotThrow = Attrs.hasAttribute(llvm::AttributeList::FunctionIndex,
llvm::Attribute::NoUnwind);
}
+
+ // If we made a temporary, be sure to clean up after ourselves. Note that we
+ // can't depend on being inside of an ExprWithCleanups, so we need to manually
+ // pop this cleanup later on. Being eager about this is OK, since this
+ // temporary is 'invisible' outside of the callee.
+ if (UnusedReturnSizePtr)
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr,
+ UnusedReturnSizePtr);
+
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
SmallVector<llvm::OperandBundleDef, 1> BundleList =
@@ -4243,9 +4284,8 @@
// insertion point; this allows the rest of IRGen to discard
// unreachable code.
if (CS.doesNotReturn()) {
- if (UnusedReturnSize)
- EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
- SRetPtr.getPointer());
+ if (UnusedReturnSizePtr)
+ PopCleanupBlock();
// Strip away the noreturn attribute to better diagnose unreachable UB.
if (SanOpts.has(SanitizerKind::Unreachable)) {
@@ -4314,9 +4354,8 @@
case ABIArgInfo::InAlloca:
case ABIArgInfo::Indirect: {
RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation());
- if (UnusedReturnSize)
- EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
- SRetPtr.getPointer());
+ if (UnusedReturnSizePtr)
+ PopCleanupBlock();
return ret;
}
@@ -4394,7 +4433,8 @@
OffsetValue);
} else if (const auto *AA = TargetDecl->getAttr<AllocAlignAttr>()) {
llvm::Value *ParamVal =
- CallArgs[AA->paramIndex().getLLVMIndex()].RV.getScalarVal();
+ CallArgs[AA->getParamIndex().getLLVMIndex()].getRValue(
+ *this).getScalarVal();
EmitAlignmentAssumption(Ret.getScalarVal(), ParamVal);
}
}
diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h
index 495baf0..da042e9 100644
--- a/lib/CodeGen/CGCall.h
+++ b/lib/CodeGen/CGCall.h
@@ -213,18 +213,52 @@
};
struct CallArg {
- RValue RV;
+ private:
+ union {
+ RValue RV;
+ LValue LV; /// The argument is semantically a load from this l-value.
+ };
+ bool HasLV;
+
+ /// A data-flow flag to make sure getRValue and/or copyInto are not
+ /// called twice for duplicated IR emission.
+ mutable bool IsUsed;
+
+ public:
QualType Ty;
- bool NeedsCopy;
- CallArg(RValue rv, QualType ty, bool needscopy)
- : RV(rv), Ty(ty), NeedsCopy(needscopy)
- { }
+ CallArg(RValue rv, QualType ty)
+ : RV(rv), HasLV(false), IsUsed(false), Ty(ty) {}
+ CallArg(LValue lv, QualType ty)
+ : LV(lv), HasLV(true), IsUsed(false), Ty(ty) {}
+ bool hasLValue() const { return HasLV; }
+ QualType getType() const { return Ty; }
+
+ /// \returns an independent RValue. If the CallArg contains an LValue,
+ /// a temporary copy is returned.
+ RValue getRValue(CodeGenFunction &CGF) const;
+
+ LValue getKnownLValue() const {
+ assert(HasLV && !IsUsed);
+ return LV;
+ }
+ RValue getKnownRValue() const {
+ assert(!HasLV && !IsUsed);
+ return RV;
+ }
+ void setRValue(RValue _RV) {
+ assert(!HasLV);
+ RV = _RV;
+ }
+
+ bool isAggregate() const { return HasLV || RV.isAggregate(); }
+
+ void copyInto(CodeGenFunction &CGF, Address A) const;
};
/// CallArgList - Type for representing both the value and type of
/// arguments in a call.
class CallArgList :
- public SmallVector<CallArg, 16> {
+ public SmallVector<CallArg, 8> {
public:
CallArgList() : StackBase(nullptr) {}
@@ -248,8 +282,10 @@
llvm::Instruction *IsActiveIP;
};
- void add(RValue rvalue, QualType type, bool needscopy = false) {
- push_back(CallArg(rvalue, type, needscopy));
+ void add(RValue rvalue, QualType type) { push_back(CallArg(rvalue, type)); }
+
+ void addUncopiedAggregate(LValue LV, QualType type) {
+ push_back(CallArg(LV, type));
}
/// Add all the arguments from another CallArgList to this one. After doing
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 56bd250..4ba5c06 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -2077,7 +2077,8 @@
assert(Args.size() == 2 && "unexpected argcount for trivial ctor");
QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType();
- Address Src(Args[1].RV.getScalarVal(), getNaturalTypeAlignment(SrcTy));
+ Address Src(Args[1].getRValue(*this).getScalarVal(),
+ getNaturalTypeAlignment(SrcTy));
LValue SrcLVal = MakeAddrLValue(Src, SrcTy);
QualType DestTy = getContext().getTypeDeclType(ClassDecl);
LValue DestLVal = MakeAddrLValue(This, DestTy);
@@ -2131,8 +2132,7 @@
const CXXConstructorDecl *D, bool ForVirtualBase, Address This,
bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) {
CallArgList Args;
- CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType(getContext()),
- /*NeedsCopy=*/false);
+ CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType(getContext()));
// Forward the parameters.
if (InheritedFromVBase &&
@@ -2196,7 +2196,7 @@
assert(Args.size() >= Params.size() && "too few arguments for call");
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
if (I < Params.size() && isa<ImplicitParamDecl>(Params[I])) {
- const RValue &RV = Args[I].RV;
+ const RValue &RV = Args[I].getRValue(*this);
assert(!RV.isComplex() && "complex indirect params not supported");
ParamValue Val = RV.isScalar()
? ParamValue::forDirect(RV.getScalarVal())
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 4cb9b2d..0f7ac72 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1000,19 +1000,30 @@
return llvm::dwarf::DW_CC_LLVM_vectorcall;
case CC_X86Pascal:
return llvm::dwarf::DW_CC_BORLAND_pascal;
-
- // FIXME: Create new DW_CC_ codes for these calling conventions.
case CC_Win64:
+ return llvm::dwarf::DW_CC_LLVM_Win64;
case CC_X86_64SysV:
+ return llvm::dwarf::DW_CC_LLVM_X86_64SysV;
case CC_AAPCS:
+ return llvm::dwarf::DW_CC_LLVM_AAPCS;
case CC_AAPCS_VFP:
+ return llvm::dwarf::DW_CC_LLVM_AAPCS_VFP;
case CC_IntelOclBicc:
+ return llvm::dwarf::DW_CC_LLVM_IntelOclBicc;
case CC_SpirFunction:
+ return llvm::dwarf::DW_CC_LLVM_SpirFunction;
case CC_OpenCLKernel:
+ return llvm::dwarf::DW_CC_LLVM_OpenCLKernel;
case CC_Swift:
+ return llvm::dwarf::DW_CC_LLVM_Swift;
case CC_PreserveMost:
+ return llvm::dwarf::DW_CC_LLVM_PreserveMost;
case CC_PreserveAll:
+ return llvm::dwarf::DW_CC_LLVM_PreserveAll;
case CC_X86RegCall:
+ return llvm::dwarf::DW_CC_LLVM_X86RegCall;
+ case CC_CUDAKernel:
+ // ToDo: Add llvm::dwarf::DW_CC_LLVM_CUDAKernel;
return 0;
}
return 0;
@@ -1405,7 +1416,7 @@
// deleting dtor.
const auto *DD = dyn_cast<CXXDestructorDecl>(Method);
GlobalDecl GD = DD ? GlobalDecl(DD, Dtor_Deleting) : GlobalDecl(Method);
- MicrosoftVTableContext::MethodVFTableLocation ML =
+ const MethodVFTableLocation &ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
VIndex = ML.Index;
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 52294c2..cf99606 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -285,8 +285,11 @@
// never defer them.
assert(isa<ObjCMethodDecl>(DC) && "unexpected parent code decl");
}
- if (GD.getDecl())
+ if (GD.getDecl()) {
+ // Disable emission of the parent function for the OpenMP device codegen.
+ CGOpenMPRuntime::DisableAutoDeclareTargetRAII NoDeclTarget(*this);
(void)GetAddrOfGlobal(GD);
+ }
return Addr;
}
@@ -464,13 +467,11 @@
}
};
- struct DestroyNRVOVariable final : EHScopeStack::Cleanup {
- DestroyNRVOVariable(Address addr,
- const CXXDestructorDecl *Dtor,
- llvm::Value *NRVOFlag)
- : Dtor(Dtor), NRVOFlag(NRVOFlag), Loc(addr) {}
+ template <class Derived>
+ struct DestroyNRVOVariable : EHScopeStack::Cleanup {
+ DestroyNRVOVariable(Address addr, llvm::Value *NRVOFlag)
+ : NRVOFlag(NRVOFlag), Loc(addr) {}
- const CXXDestructorDecl *Dtor;
llvm::Value *NRVOFlag;
Address Loc;
@@ -489,13 +490,40 @@
CGF.EmitBlock(RunDtorBB);
}
- CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
- /*ForVirtualBase=*/false,
- /*Delegating=*/false,
- Loc);
+ static_cast<Derived *>(this)->emitDestructorCall(CGF);
if (NRVO) CGF.EmitBlock(SkipDtorBB);
}
+
+ virtual ~DestroyNRVOVariable() = default;
+ };
+
+ struct DestroyNRVOVariableCXX final
+ : DestroyNRVOVariable<DestroyNRVOVariableCXX> {
+ DestroyNRVOVariableCXX(Address addr, const CXXDestructorDecl *Dtor,
+ llvm::Value *NRVOFlag)
+ : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, NRVOFlag),
+ Dtor(Dtor) {}
+
+ const CXXDestructorDecl *Dtor;
+
+ void emitDestructorCall(CodeGenFunction &CGF) {
+ CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
+ /*ForVirtualBase=*/false,
+ /*Delegating=*/false, Loc);
+ }
+ };
+
+ struct DestroyNRVOVariableC final
+ : DestroyNRVOVariable<DestroyNRVOVariableC> {
+ DestroyNRVOVariableC(Address addr, llvm::Value *NRVOFlag, QualType Ty)
+ : DestroyNRVOVariable<DestroyNRVOVariableC>(addr, NRVOFlag), Ty(Ty) {}
+
+ QualType Ty;
+
+ void emitDestructorCall(CodeGenFunction &CGF) {
+ CGF.destroyNonTrivialCStruct(CGF, Loc, Ty);
+ }
};
struct CallStackRestore final : EHScopeStack::Cleanup {
@@ -1068,16 +1096,27 @@
}
// A normal fixed sized variable becomes an alloca in the entry block,
- // unless it's an NRVO variable.
+ // unless:
+ // - it's an NRVO variable.
+ // - we are compiling OpenMP and it's an OpenMP local variable.
- if (NRVO) {
+ Address OpenMPLocalAddr =
+ getLangOpts().OpenMP
+ ? CGM.getOpenMPRuntime().getAddressOfLocalVariable(*this, &D)
+ : Address::invalid();
+ if (getLangOpts().OpenMP && OpenMPLocalAddr.isValid()) {
+ address = OpenMPLocalAddr;
+ } else if (NRVO) {
// The named return value optimization: allocate this variable in the
// return slot, so that we can elide the copy when returning this
// variable (C++0x [class.copy]p34).
address = ReturnValue;
if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
- if (!cast<CXXRecordDecl>(RecordTy->getDecl())->hasTrivialDestructor()) {
+ const auto *RD = RecordTy->getDecl();
+ const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
+ if ((CXXRD && !CXXRD->hasTrivialDestructor()) ||
+ RD->isNonTrivialToPrimitiveDestroy()) {
// Create a flag that is used to indicate when the NRVO was applied
// to this variable. Set it to zero to indicate that NRVO was not
// applied.
@@ -1450,8 +1489,8 @@
if (emission.NRVOFlag) {
assert(!type->isArrayType());
CXXDestructorDecl *dtor = type->getAsCXXRecordDecl()->getDestructor();
- EHStack.pushCleanup<DestroyNRVOVariable>(cleanupKind, addr,
- dtor, emission.NRVOFlag);
+ EHStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr, dtor,
+ emission.NRVOFlag);
return;
}
break;
@@ -1473,6 +1512,12 @@
case QualType::DK_nontrivial_c_struct:
destroyer = CodeGenFunction::destroyNonTrivialCStruct;
+ if (emission.NRVOFlag) {
+ assert(!type->isArrayType());
+ EHStack.pushCleanup<DestroyNRVOVariableC>(cleanupKind, addr,
+ emission.NRVOFlag, type);
+ return;
+ }
break;
}
@@ -1882,6 +1927,22 @@
llvm::Type *IRTy = ConvertTypeForMem(Ty)->getPointerTo(AS);
if (DeclPtr.getType() != IRTy)
DeclPtr = Builder.CreateBitCast(DeclPtr, IRTy, D.getName());
+ // Indirect argument is in alloca address space, which may be different
+ // from the default address space.
+ auto AllocaAS = CGM.getASTAllocaAddressSpace();
+ auto *V = DeclPtr.getPointer();
+ auto SrcLangAS = getLangOpts().OpenCL ? LangAS::opencl_private : AllocaAS;
+ auto DestLangAS =
+ getLangOpts().OpenCL ? LangAS::opencl_private : LangAS::Default;
+ if (SrcLangAS != DestLangAS) {
+ assert(getContext().getTargetAddressSpace(SrcLangAS) ==
+ CGM.getDataLayout().getAllocaAddrSpace());
+ auto DestAS = getContext().getTargetAddressSpace(DestLangAS);
+ auto *T = V->getType()->getPointerElementType()->getPointerTo(DestAS);
+ DeclPtr = Address(getTargetHooks().performAddrSpaceCast(
+ *this, V, SrcLangAS, DestLangAS, T, true),
+ DeclPtr.getAlignment());
+ }
// Push a destructor cleanup for this parameter if the ABI requires it.
// Don't push a cleanup in a thunk for a method that will also emit a
@@ -1896,9 +1957,18 @@
}
}
} else {
- // Otherwise, create a temporary to hold the value.
- DeclPtr = CreateMemTemp(Ty, getContext().getDeclAlign(&D),
- D.getName() + ".addr");
+ // Check if the parameter address is controlled by OpenMP runtime.
+ Address OpenMPLocalAddr =
+ getLangOpts().OpenMP
+ ? CGM.getOpenMPRuntime().getAddressOfLocalVariable(*this, &D)
+ : Address::invalid();
+ if (getLangOpts().OpenMP && OpenMPLocalAddr.isValid()) {
+ DeclPtr = OpenMPLocalAddr;
+ } else {
+ // Otherwise, create a temporary to hold the value.
+ DeclPtr = CreateMemTemp(Ty, getContext().getDeclAlign(&D),
+ D.getName() + ".addr");
+ }
DoStore = true;
}
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 4050499..d6e97dd 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -379,6 +379,10 @@
D->hasAttr<CUDASharedAttr>()))
return;
+ if (getLangOpts().OpenMP &&
+ getOpenMPRuntime().emitDeclareTargetVarDefinition(D, Addr, PerformInit))
+ return;
+
// Check if we've already initialized this decl.
auto I = DelayedCXXInitPosition.find(D);
if (I != DelayedCXXInitPosition.end() && I->second == ~0U)
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 1978d27..2be3e25 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -65,7 +65,7 @@
if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015))
name = "__std_terminate";
else
- name = "\01?terminate@@YAXXZ";
+ name = "?terminate@@YAXXZ";
} else if (getLangOpts().ObjC1 &&
getLangOpts().ObjCRuntime.hasTerminate())
name = "objc_terminate";
@@ -116,6 +116,10 @@
const LangOptions &L) {
if (L.SjLjExceptions)
return EHPersonality::GNU_C_SJLJ;
+ if (L.DWARFExceptions)
+ return EHPersonality::GNU_C;
+ if (T.isWindowsMSVCEnvironment())
+ return EHPersonality::MSVC_CxxFrameHandler3;
if (L.SEHExceptions)
return EHPersonality::GNU_C_SEH;
return EHPersonality::GNU_C;
@@ -129,6 +133,8 @@
case ObjCRuntime::MacOSX:
case ObjCRuntime::iOS:
case ObjCRuntime::WatchOS:
+ if (T.isWindowsMSVCEnvironment())
+ return EHPersonality::MSVC_CxxFrameHandler3;
return EHPersonality::NeXT_ObjC;
case ObjCRuntime::GNUstep:
if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
@@ -149,6 +155,10 @@
const LangOptions &L) {
if (L.SjLjExceptions)
return EHPersonality::GNU_CPlusPlus_SJLJ;
+ if (L.DWARFExceptions)
+ return EHPersonality::GNU_CPlusPlus;
+ if (T.isWindowsMSVCEnvironment())
+ return EHPersonality::MSVC_CxxFrameHandler3;
if (L.SEHExceptions)
return EHPersonality::GNU_CPlusPlus_SEH;
return EHPersonality::GNU_CPlusPlus;
@@ -199,25 +209,9 @@
if (FD && FD->usesSEHTry())
return getSEHPersonalityMSVC(T);
- // Try to pick a personality function that is compatible with MSVC if we're
- // not compiling Obj-C. Obj-C users better have an Obj-C runtime that supports
- // the GCC-style personality function.
- if (T.isWindowsMSVCEnvironment() && !L.ObjC1) {
- if (L.SjLjExceptions)
- return EHPersonality::GNU_CPlusPlus_SJLJ;
- if (L.DWARFExceptions)
- return EHPersonality::GNU_CPlusPlus;
- return EHPersonality::MSVC_CxxFrameHandler3;
- }
-
- if (L.CPlusPlus && L.ObjC1)
- return getObjCXXPersonality(T, L);
- else if (L.CPlusPlus)
- return getCXXPersonality(T, L);
- else if (L.ObjC1)
- return getObjCPersonality(T, L);
- else
- return getCPersonality(T, L);
+ if (L.ObjC1)
+ return L.CPlusPlus ? getObjCXXPersonality(T, L) : getObjCPersonality(T, L);
+ return L.CPlusPlus ? getCXXPersonality(T, L) : getCPersonality(T, L);
}
const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) {
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index d8fc270..4c6f4df 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -187,7 +187,7 @@
llvm_unreachable("bad evaluation kind");
}
-/// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result will
+/// EmitAnyExprToTemp - Similar to EmitAnyExpr(), however, the result will
/// always be accessible even if no aggregate location is provided.
RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E) {
AggValueSlot AggSlot = AggValueSlot::ignored();
@@ -2210,6 +2210,22 @@
return CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl);
}
+static Address emitDeclTargetLinkVarDeclLValue(CodeGenFunction &CGF,
+ const VarDecl *VD, QualType T) {
+ for (const auto *D : VD->redecls()) {
+ if (!VD->hasAttrs())
+ continue;
+ if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
+ if (Attr->getMapType() == OMPDeclareTargetDeclAttr::MT_Link) {
+ QualType PtrTy = CGF.getContext().getPointerType(VD->getType());
+ Address Addr =
+ CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
+ return CGF.EmitLoadOfPointer(Addr, PtrTy->castAs<PointerType>());
+ }
+ }
+ return Address::invalid();
+}
+
Address
CodeGenFunction::EmitLoadOfReference(LValue RefLVal,
LValueBaseInfo *PointeeBaseInfo,
@@ -2259,6 +2275,13 @@
if (VD->getTLSKind() == VarDecl::TLS_Dynamic &&
CGF.CGM.getCXXABI().usesThreadWrapperFunction())
return CGF.CGM.getCXXABI().EmitThreadLocalVarDeclLValue(CGF, VD, T);
+ // Check if the variable is marked as declare target with link clause in
+ // device codegen.
+ if (CGF.getLangOpts().OpenMPIsDevice) {
+ Address Addr = emitDeclTargetLinkVarDeclLValue(CGF, VD, T);
+ if (Addr.isValid())
+ return CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl);
+ }
llvm::Value *V = CGF.CGM.GetAddrOfGlobalVar(VD);
llvm::Type *RealVarTy = CGF.getTypes().ConvertTypeForMem(VD->getType());
@@ -2952,6 +2975,7 @@
bool WithDiag = !CGM.getCodeGenOpts().SanitizeTrap.has(Kind);
llvm::CallInst *CheckCall;
+ llvm::Constant *SlowPathFn;
if (WithDiag) {
llvm::Constant *Info = llvm::ConstantStruct::getAnon(StaticArgs);
auto *InfoPtr =
@@ -2960,20 +2984,20 @@
InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr);
- llvm::Constant *SlowPathDiagFn = CGM.getModule().getOrInsertFunction(
+ SlowPathFn = CGM.getModule().getOrInsertFunction(
"__cfi_slowpath_diag",
llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy},
false));
CheckCall = Builder.CreateCall(
- SlowPathDiagFn,
- {TypeId, Ptr, Builder.CreateBitCast(InfoPtr, Int8PtrTy)});
+ SlowPathFn, {TypeId, Ptr, Builder.CreateBitCast(InfoPtr, Int8PtrTy)});
} else {
- llvm::Constant *SlowPathFn = CGM.getModule().getOrInsertFunction(
+ SlowPathFn = CGM.getModule().getOrInsertFunction(
"__cfi_slowpath",
llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy}, false));
CheckCall = Builder.CreateCall(SlowPathFn, {TypeId, Ptr});
}
+ CGM.setDSOLocal(cast<llvm::GlobalValue>(SlowPathFn->stripPointerCasts()));
CheckCall->setDoesNotThrow();
EmitBlock(Cont);
@@ -2987,6 +3011,7 @@
llvm::Function *F = llvm::Function::Create(
llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy}, false),
llvm::GlobalValue::WeakAnyLinkage, "__cfi_check", M);
+ CGM.setDSOLocal(F);
llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", F);
// FIXME: consider emitting an intrinsic call like
// call void @llvm.cfi_check(i64 %0, i8* %1, i8* %2)
@@ -4167,7 +4192,35 @@
LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) {
assert(OpaqueValueMappingData::shouldBindAsLValue(e));
- return getOpaqueLValueMapping(e);
+ return getOrCreateOpaqueLValueMapping(e);
+}
+
+LValue
+CodeGenFunction::getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e) {
+ assert(OpaqueValueMapping::shouldBindAsLValue(e));
+
+ llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
+ it = OpaqueLValues.find(e);
+
+ if (it != OpaqueLValues.end())
+ return it->second;
+
+ assert(e->isUnique() && "LValue for a nonunique OVE hasn't been emitted");
+ return EmitLValue(e->getSourceExpr());
+}
+
+RValue
+CodeGenFunction::getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e) {
+ assert(!OpaqueValueMapping::shouldBindAsLValue(e));
+
+ llvm::DenseMap<const OpaqueValueExpr*,RValue>::iterator
+ it = OpaqueRValues.find(e);
+
+ if (it != OpaqueRValues.end())
+ return it->second;
+
+ assert(e->isUnique() && "RValue for a nonunique OVE hasn't been emitted");
+ return EmitAnyExpr(e->getSourceExpr());
}
RValue CodeGenFunction::EmitRValueForField(LValue LV,
@@ -4719,6 +4772,12 @@
// If this semantic expression is an opaque value, bind it
// to the result of its source expression.
if (const auto *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
+ // Skip unique OVEs.
+ if (ov->isUnique()) {
+ assert(ov != resultExpr &&
+ "A unique OVE cannot be used as the result expression");
+ continue;
+ }
// If this is the result expression, we may need to evaluate
// directly into the slot.
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 394336e..9590868 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -23,6 +23,7 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicInst.h"
using namespace clang;
using namespace CodeGen;
@@ -37,23 +38,6 @@
AggValueSlot Dest;
bool IsResultUnused;
- /// We want to use 'dest' as the return slot except under two
- /// conditions:
- /// - The destination slot requires garbage collection, so we
- /// need to use the GC API.
- /// - The destination slot is potentially aliased.
- bool shouldUseDestForReturnSlot() const {
- return !(Dest.requiresGCollection() || Dest.isPotentiallyAliased());
- }
-
- ReturnValueSlot getReturnValueSlot() const {
- if (!shouldUseDestForReturnSlot())
- return ReturnValueSlot();
-
- return ReturnValueSlot(Dest.getAddress(), Dest.isVolatile(),
- IsResultUnused);
- }
-
AggValueSlot EnsureSlot(QualType T) {
if (!Dest.isIgnored()) return Dest;
return CGF.CreateAggTemp(T, "agg.tmp.ensured");
@@ -63,6 +47,15 @@
Dest = CGF.CreateAggTemp(T, "agg.tmp.ensured");
}
+ // Calls `Fn` with a valid return value slot, potentially creating a temporary
+ // to do so. If a temporary is created, an appropriate copy into `Dest` will
+ // be emitted, as will lifetime markers.
+ //
+ // The given function should take a ReturnValueSlot, and return an RValue that
+ // points to said slot.
+ void withReturnValueSlot(const Expr *E,
+ llvm::function_ref<RValue(ReturnValueSlot)> Fn);
+
public:
AggExprEmitter(CodeGenFunction &cgf, AggValueSlot Dest, bool IsResultUnused)
: CGF(cgf), Builder(CGF.Builder), Dest(Dest),
@@ -242,34 +235,65 @@
return Record->hasObjectMember();
}
-/// \brief Perform the final move to DestPtr if for some reason
-/// getReturnValueSlot() didn't use it directly.
-///
-/// The idea is that you do something like this:
-/// RValue Result = EmitSomething(..., getReturnValueSlot());
-/// EmitMoveFromReturnSlot(E, Result);
-///
-/// If nothing interferes, this will cause the result to be emitted
-/// directly into the return value slot. Otherwise, a final move
-/// will be performed.
-void AggExprEmitter::EmitMoveFromReturnSlot(const Expr *E, RValue src) {
- // Push destructor if the result is ignored and the type is a C struct that
- // is non-trivial to destroy.
- QualType Ty = E->getType();
- if (Dest.isIgnored() &&
- Ty.isDestructedType() == QualType::DK_nontrivial_c_struct)
- CGF.pushDestroy(Ty.isDestructedType(), src.getAggregateAddress(), Ty);
+void AggExprEmitter::withReturnValueSlot(
+ const Expr *E, llvm::function_ref<RValue(ReturnValueSlot)> EmitCall) {
+ QualType RetTy = E->getType();
+ bool RequiresDestruction =
+ Dest.isIgnored() &&
+ RetTy.isDestructedType() == QualType::DK_nontrivial_c_struct;
- if (shouldUseDestForReturnSlot()) {
- // Logically, Dest.getAddr() should equal Src.getAggregateAddr().
- // The possibility of undef rvalues complicates that a lot,
- // though, so we can't really assert.
- return;
+ // If it makes no observable difference, save a memcpy + temporary.
+ //
+ // We need to always provide our own temporary if destruction is required.
+ // Otherwise, EmitCall will emit its own, notice that it's "unused", and end
+ // its lifetime before we have the chance to emit a proper destructor call.
+ bool UseTemp = Dest.isPotentiallyAliased() || Dest.requiresGCollection() ||
+ (RequiresDestruction && !Dest.getAddress().isValid());
+
+ Address RetAddr = Address::invalid();
+
+ EHScopeStack::stable_iterator LifetimeEndBlock;
+ llvm::Value *LifetimeSizePtr = nullptr;
+ llvm::IntrinsicInst *LifetimeStartInst = nullptr;
+ if (!UseTemp) {
+ RetAddr = Dest.getAddress();
+ } else {
+ RetAddr = CGF.CreateMemTemp(RetTy);
+ uint64_t Size =
+ CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy));
+ LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAddr.getPointer());
+ if (LifetimeSizePtr) {
+ LifetimeStartInst =
+ cast<llvm::IntrinsicInst>(std::prev(Builder.GetInsertPoint()));
+ assert(LifetimeStartInst->getIntrinsicID() ==
+ llvm::Intrinsic::lifetime_start &&
+ "Last insertion wasn't a lifetime.start?");
+
+ CGF.pushFullExprCleanup<CodeGenFunction::CallLifetimeEnd>(
+ NormalEHLifetimeMarker, RetAddr, LifetimeSizePtr);
+ LifetimeEndBlock = CGF.EHStack.stable_begin();
+ }
}
- // Otherwise, copy from there to the destination.
- assert(Dest.getPointer() != src.getAggregatePointer());
- EmitFinalDestCopy(E->getType(), src);
+ RValue Src =
+ EmitCall(ReturnValueSlot(RetAddr, Dest.isVolatile(), IsResultUnused));
+
+ if (RequiresDestruction)
+ CGF.pushDestroy(RetTy.isDestructedType(), Src.getAggregateAddress(), RetTy);
+
+ if (!UseTemp)
+ return;
+
+ assert(Dest.getPointer() != Src.getAggregatePointer());
+ EmitFinalDestCopy(E->getType(), Src);
+
+ if (!RequiresDestruction && LifetimeStartInst) {
+ // If there's no dtor to run, the copy was the last use of our temporary.
+ // Since we're not guaranteed to be in an ExprWithCleanups, clean up
+ // eagerly.
+ CGF.DeactivateCleanupBlock(LifetimeEndBlock, LifetimeStartInst);
+ CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAddr.getPointer());
+ }
}
/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
@@ -606,7 +630,11 @@
}
void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
- EmitFinalDestCopy(e->getType(), CGF.getOpaqueLValueMapping(e));
+ // If this is a unique OVE, just visit its source expression.
+ if (e->isUnique())
+ Visit(e->getSourceExpr());
+ else
+ EmitFinalDestCopy(e->getType(), CGF.getOrCreateOpaqueLValueMapping(e));
}
void
@@ -828,13 +856,15 @@
return;
}
- RValue RV = CGF.EmitCallExpr(E, getReturnValueSlot());
- EmitMoveFromReturnSlot(E, RV);
+ withReturnValueSlot(E, [&](ReturnValueSlot Slot) {
+ return CGF.EmitCallExpr(E, Slot);
+ });
}
void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
- RValue RV = CGF.EmitObjCMessageExpr(E, getReturnValueSlot());
- EmitMoveFromReturnSlot(E, RV);
+ withReturnValueSlot(E, [&](ReturnValueSlot Slot) {
+ return CGF.EmitObjCMessageExpr(E, Slot);
+ });
}
void AggExprEmitter::VisitBinComma(const BinaryOperator *E) {
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 9f70ef3..56c5e68 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -265,7 +265,7 @@
// when it isn't necessary; just produce the proper effect here.
LValue RHS = isa<CXXOperatorCallExpr>(CE)
? MakeNaturalAlignAddrLValue(
- (*RtlArgs)[0].RV.getScalarVal(),
+ (*RtlArgs)[0].getRValue(*this).getScalarVal(),
(*(CE->arg_begin() + 1))->getType())
: EmitLValue(*CE->arg_begin());
EmitAggregateAssign(This, RHS, CE->getType());
@@ -1307,19 +1307,19 @@
}
RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
- const Expr *Arg,
+ const CallExpr *TheCall,
bool IsDelete) {
CallArgList Args;
- const Stmt *ArgS = Arg;
- EmitCallArgs(Args, *Type->param_type_begin(), llvm::makeArrayRef(ArgS));
+ EmitCallArgs(Args, Type->getParamTypes(), TheCall->arguments());
// Find the allocation or deallocation function that we're calling.
ASTContext &Ctx = getContext();
DeclarationName Name = Ctx.DeclarationNames
.getCXXOperatorName(IsDelete ? OO_Delete : OO_New);
+
for (auto *Decl : Ctx.getTranslationUnitDecl()->lookup(Name))
if (auto *FD = dyn_cast<FunctionDecl>(Decl))
if (Ctx.hasSameType(FD->getType(), QualType(Type, 0)))
- return EmitNewDeleteCall(*this, cast<FunctionDecl>(Decl), Type, Args);
+ return EmitNewDeleteCall(*this, FD, Type, Args);
llvm_unreachable("predeclared global operator new/delete is missing");
}
@@ -1490,7 +1490,7 @@
AllocAlign);
for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {
auto &Arg = NewArgs[I + NumNonPlacementArgs];
- Cleanup->setPlacementArg(I, Arg.RV, Arg.Ty);
+ Cleanup->setPlacementArg(I, Arg.getRValue(CGF), Arg.Ty);
}
return;
@@ -1521,8 +1521,8 @@
AllocAlign);
for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {
auto &Arg = NewArgs[I + NumNonPlacementArgs];
- Cleanup->setPlacementArg(I, DominatingValue<RValue>::save(CGF, Arg.RV),
- Arg.Ty);
+ Cleanup->setPlacementArg(
+ I, DominatingValue<RValue>::save(CGF, Arg.getRValue(CGF)), Arg.Ty);
}
CGF.initFullExprCleanup();
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 9094d3f..3af2d7f 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -155,8 +155,9 @@
}
ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
if (E->isGLValue())
- return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc());
- return CGF.getOpaqueRValueMapping(E).getComplexVal();
+ return EmitLoadOfLValue(CGF.getOrCreateOpaqueLValueMapping(E),
+ E->getExprLoc());
+ return CGF.getOrCreateOpaqueRValueMapping(E).getComplexVal();
}
ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) {
@@ -628,7 +629,7 @@
llvm::Instruction *Call;
RValue Res = CGF.EmitCall(FuncInfo, Callee, ReturnValueSlot(), Args, &Call);
- cast<llvm::CallInst>(Call)->setCallingConv(CGF.CGM.getBuiltinCC());
+ cast<llvm::CallInst>(Call)->setCallingConv(CGF.CGM.getRuntimeCC());
return Res.getComplexVal();
}
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 2a0dd4a..bed37d6 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -422,10 +422,11 @@
Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {
if (E->isGLValue())
- return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc());
+ return EmitLoadOfLValue(CGF.getOrCreateOpaqueLValueMapping(E),
+ E->getExprLoc());
// Otherwise, assume the mapping is the scalar directly.
- return CGF.getOpaqueRValueMapping(E).getScalarVal();
+ return CGF.getOrCreateOpaqueRValueMapping(E).getScalarVal();
}
Value *emitConstant(const CodeGenFunction::ConstantEmission &Constant,
diff --git a/lib/CodeGen/CGGPUBuiltin.cpp b/lib/CodeGen/CGGPUBuiltin.cpp
index 48156b1..b5375ff 100644
--- a/lib/CodeGen/CGGPUBuiltin.cpp
+++ b/lib/CodeGen/CGGPUBuiltin.cpp
@@ -83,8 +83,9 @@
/* ParamsToSkip = */ 0);
// We don't know how to emit non-scalar varargs.
- if (std::any_of(Args.begin() + 1, Args.end(),
- [](const CallArg &A) { return !A.RV.isScalar(); })) {
+ if (std::any_of(Args.begin() + 1, Args.end(), [&](const CallArg &A) {
+ return !A.getRValue(*this).isScalar();
+ })) {
CGM.ErrorUnsupported(E, "non-scalar arg to printf");
return RValue::get(llvm::ConstantInt::get(IntTy, 0));
}
@@ -97,7 +98,7 @@
} else {
llvm::SmallVector<llvm::Type *, 8> ArgTypes;
for (unsigned I = 1, NumArgs = Args.size(); I < NumArgs; ++I)
- ArgTypes.push_back(Args[I].RV.getScalarVal()->getType());
+ ArgTypes.push_back(Args[I].getRValue(*this).getScalarVal()->getType());
// Using llvm::StructType is correct only because printf doesn't accept
// aggregates. If we had to handle aggregates here, we'd have to manually
@@ -109,7 +110,7 @@
for (unsigned I = 1, NumArgs = Args.size(); I < NumArgs; ++I) {
llvm::Value *P = Builder.CreateStructGEP(AllocaTy, Alloca, I - 1);
- llvm::Value *Arg = Args[I].RV.getScalarVal();
+ llvm::Value *Arg = Args[I].getRValue(*this).getScalarVal();
Builder.CreateAlignedStore(Arg, P, DL.getPrefTypeAlignment(Arg->getType()));
}
BufferPtr = Builder.CreatePointerCast(Alloca, llvm::Type::getInt8PtrTy(Ctx));
@@ -117,6 +118,6 @@
// Invoke vprintf and return.
llvm::Function* VprintfFunc = GetVprintfDeclaration(CGM.getModule());
- return RValue::get(
- Builder.CreateCall(VprintfFunc, {Args[0].RV.getScalarVal(), BufferPtr}));
+ return RValue::get(Builder.CreateCall(
+ VprintfFunc, {Args[0].getRValue(*this).getScalarVal(), BufferPtr}));
}
diff --git a/lib/CodeGen/CGNonTrivialStruct.cpp b/lib/CodeGen/CGNonTrivialStruct.cpp
index 3b0b173..731938a 100644
--- a/lib/CodeGen/CGNonTrivialStruct.cpp
+++ b/lib/CodeGen/CGNonTrivialStruct.cpp
@@ -77,6 +77,8 @@
switch (PDIK) {
case QualType::PDIK_ARCStrong:
return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
+ case QualType::PDIK_ARCWeak:
+ return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
case QualType::PDIK_Struct:
return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
case QualType::PDIK_Trivial:
@@ -108,6 +110,8 @@
switch (PCK) {
case QualType::PCK_ARCStrong:
return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
+ case QualType::PCK_ARCWeak:
+ return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
case QualType::PCK_Struct:
return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
case QualType::PCK_Trivial:
@@ -141,11 +145,6 @@
template <class... Ts> void visitTrivial(Ts... Args) {}
- template <class... Ts> void visitARCWeak(Ts... Args) {
- // FIXME: remove this when visitARCWeak is implemented in the subclasses.
- llvm_unreachable("weak field is not expected");
- }
-
template <class... Ts> void visitCXXDestructor(Ts... Args) {
llvm_unreachable("field of a C++ struct type is not expected");
}
@@ -245,6 +244,13 @@
appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
}
+ void visitARCWeak(QualType FT, const FieldDecl *FD,
+ CharUnits CurStructOffset) {
+ appendStr("_w");
+ CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
+ appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));
+ }
+
void visitStruct(QualType QT, const FieldDecl *FD,
CharUnits CurStructOffset) {
CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
@@ -615,6 +621,12 @@
*CGF, getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT);
}
+ void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 1> Addrs) {
+ CGF->destroyARCWeak(
+ *CGF, getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT);
+ }
+
void callSpecialFunction(QualType FT, CharUnits Offset,
std::array<Address, 1> Addrs) {
CGF->callCStructDestructor(
@@ -636,6 +648,12 @@
getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT);
}
+ void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 1> Addrs) {
+ CGF->EmitNullInitialization(
+ getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT);
+ }
+
template <class FieldKind, size_t... Is>
void visitArray(FieldKind FK, QualType QT, const FieldDecl *FD,
CharUnits CurStackOffset, std::array<Address, 1> Addrs) {
@@ -678,6 +696,14 @@
llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);
CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);
}
+
+ void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 2> Addrs) {
+ Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
+ CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);
+ }
+
void callSpecialFunction(QualType FT, CharUnits Offset,
std::array<Address, 2> Addrs) {
CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
@@ -700,6 +726,14 @@
CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),
/* isInitialization */ true);
}
+
+ void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 2> Addrs) {
+ Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
+ CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);
+ }
+
void callSpecialFunction(QualType FT, CharUnits Offset,
std::array<Address, 2> Addrs) {
CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),
@@ -720,6 +754,14 @@
CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,
false);
}
+
+ void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 2> Addrs) {
+ Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
+ CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
+ }
+
void callSpecialFunction(QualType FT, CharUnits Offset,
std::array<Address, 2> Addrs) {
CGF->callCStructCopyAssignmentOperator(
@@ -747,6 +789,13 @@
CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime);
}
+ void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 2> Addrs) {
+ Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
+ Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
+ CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);
+ }
+
void callSpecialFunction(QualType FT, CharUnits Offset,
std::array<Address, 2> Addrs) {
CGF->callCStructMoveAssignmentOperator(
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index e812ef3..a8dd96f 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -2034,7 +2034,7 @@
// Call the marker asm if we made one, which we do only at -O0.
if (marker)
- CGF.Builder.CreateCall(marker);
+ CGF.Builder.CreateCall(marker, None, CGF.getBundlesForFunclet(marker));
}
/// Retain the given object which is the result of a function call.
@@ -2307,6 +2307,21 @@
"objc_copyWeak");
}
+void CodeGenFunction::emitARCCopyAssignWeak(QualType Ty, Address DstAddr,
+ Address SrcAddr) {
+ llvm::Value *Object = EmitARCLoadWeakRetained(SrcAddr);
+ Object = EmitObjCConsumeObject(Ty, Object);
+ EmitARCStoreWeak(DstAddr, Object, false);
+}
+
+void CodeGenFunction::emitARCMoveAssignWeak(QualType Ty, Address DstAddr,
+ Address SrcAddr) {
+ llvm::Value *Object = EmitARCLoadWeakRetained(SrcAddr);
+ Object = EmitObjCConsumeObject(Ty, Object);
+ EmitARCStoreWeak(DstAddr, Object, false);
+ EmitARCDestroyWeak(SrcAddr);
+}
+
/// Produce the code to do a objc_autoreleasepool_push.
/// call i8* \@objc_autoreleasePoolPush(void)
llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() {
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 5a025ce..a6b6c38 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -1441,7 +1441,7 @@
}
// Reset the receiver in case the lookup modified it
- ActualArgs[0] = CallArg(RValue::get(Receiver), ASTIdTy, false);
+ ActualArgs[0] = CallArg(RValue::get(Receiver), ASTIdTy);
imp = EnforceType(Builder, imp, MSI.MessengerType);
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index c3793b2..64f40e1 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -1708,7 +1708,7 @@
e = Method->param_end(); i != e; ++i, ++I) {
const ParmVarDecl *ParamDecl = (*i);
if (ParamDecl->hasAttr<NSConsumedAttr>()) {
- RValue RV = I->RV;
+ RValue RV = I->getRValue(CGF);
assert(RV.isScalar() &&
"NullReturnState::complete - arg not on object");
CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
@@ -7071,7 +7071,7 @@
CGF.getPointerAlign());
// Update the message ref argument.
- args[1].RV = RValue::get(mref.getPointer());
+ args[1].setRValue(RValue::get(mref.getPointer()));
// Load the function to call from the message ref table.
Address calleeAddr =
diff --git a/lib/CodeGen/CGOpenCLRuntime.cpp b/lib/CodeGen/CGOpenCLRuntime.cpp
index 6d0089d..15a2221 100644
--- a/lib/CodeGen/CGOpenCLRuntime.cpp
+++ b/lib/CodeGen/CGOpenCLRuntime.cpp
@@ -112,6 +112,25 @@
CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic));
}
+// Get the block literal from an expression derived from the block expression.
+// OpenCL v2.0 s6.12.5:
+// Block variable declarations are implicitly qualified with const. Therefore
+// all block variables must be initialized at declaration time and may not be
+// reassigned.
+static const BlockExpr *getBlockExpr(const Expr *E) {
+ if (auto Cast = dyn_cast<CastExpr>(E)) {
+ E = Cast->getSubExpr();
+ }
+ if (auto DR = dyn_cast<DeclRefExpr>(E)) {
+ E = cast<VarDecl>(DR->getDecl())->getInit();
+ }
+ E = E->IgnoreImplicit();
+ if (auto Cast = dyn_cast<CastExpr>(E)) {
+ E = Cast->getSubExpr();
+ }
+ return cast<BlockExpr>(E);
+}
+
/// Record emitted llvm invoke function and llvm block literal for the
/// corresponding block expression.
void CGOpenCLRuntime::recordBlockInfo(const BlockExpr *E,
@@ -126,21 +145,15 @@
EnqueuedBlockMap[E].Kernel = nullptr;
}
+llvm::Function *CGOpenCLRuntime::getInvokeFunction(const Expr *E) {
+ return EnqueuedBlockMap[getBlockExpr(E)].InvokeFunc;
+}
+
CGOpenCLRuntime::EnqueuedBlockInfo
CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) {
CGF.EmitScalarExpr(E);
- // The block literal may be assigned to a const variable. Chasing down
- // to get the block literal.
- if (auto DR = dyn_cast<DeclRefExpr>(E)) {
- E = cast<VarDecl>(DR->getDecl())->getInit();
- }
- E = E->IgnoreImplicit();
- if (auto Cast = dyn_cast<CastExpr>(E)) {
- E = Cast->getSubExpr();
- }
- auto *Block = cast<BlockExpr>(E);
-
+ const BlockExpr *Block = getBlockExpr(E);
assert(EnqueuedBlockMap.find(Block) != EnqueuedBlockMap.end() &&
"Block expression not emitted");
diff --git a/lib/CodeGen/CGOpenCLRuntime.h b/lib/CodeGen/CGOpenCLRuntime.h
index c0088b5..14fd1f1 100644
--- a/lib/CodeGen/CGOpenCLRuntime.h
+++ b/lib/CodeGen/CGOpenCLRuntime.h
@@ -87,6 +87,10 @@
/// \param Block block literal emitted for the block expression.
void recordBlockInfo(const BlockExpr *E, llvm::Function *InvokeF,
llvm::Value *Block);
+
+ /// \return LLVM block invoke function emitted for an expression derived from
+ /// the block expression.
+ llvm::Function *getInvokeFunction(const Expr *E);
};
}
diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
index f9dab90..acb683e 100644
--- a/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -893,6 +893,17 @@
CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
}
+static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
+isDeclareTargetDeclaration(const ValueDecl *VD) {
+ for (const auto *D : VD->redecls()) {
+ if (!D->hasAttrs())
+ continue;
+ if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
+ return Attr->getMapType();
+ }
+ return llvm::None;
+}
+
LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
return CGF.EmitOMPSharedLValue(E);
}
@@ -2326,6 +2337,35 @@
return CGM.CreateRuntimeFunction(FnTy, Name);
}
+Address CGOpenMPRuntime::getAddrOfDeclareTargetLink(const VarDecl *VD) {
+ if (CGM.getLangOpts().OpenMPSimd)
+ return Address::invalid();
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ isDeclareTargetDeclaration(VD);
+ if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
+ SmallString<64> PtrName;
+ {
+ llvm::raw_svector_ostream OS(PtrName);
+ OS << CGM.getMangledName(GlobalDecl(VD)) << "_decl_tgt_link_ptr";
+ }
+ llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
+ if (!Ptr) {
+ QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
+ Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
+ PtrName);
+ if (!CGM.getLangOpts().OpenMPIsDevice) {
+ auto *GV = cast<llvm::GlobalVariable>(Ptr);
+ GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ GV->setInitializer(CGM.GetAddrOfGlobal(VD));
+ }
+ CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ptr));
+ registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
+ }
+ return Address(Ptr, CGM.getContext().getDeclAlign(VD));
+ }
+ return Address::invalid();
+}
+
llvm::Constant *
CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
assert(!CGM.getLangOpts().OpenMPUseTLS ||
@@ -2489,6 +2529,139 @@
return nullptr;
}
+/// \brief Obtain information that uniquely identifies a target entry. This
+/// consists of the file and device IDs as well as line number associated with
+/// the relevant entry source location.
+static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
+ unsigned &DeviceID, unsigned &FileID,
+ unsigned &LineNum) {
+
+ auto &SM = C.getSourceManager();
+
+ // The loc should be always valid and have a file ID (the user cannot use
+ // #pragma directives in macros)
+
+ assert(Loc.isValid() && "Source location is expected to be always valid.");
+ assert(Loc.isFileID() && "Source location is expected to refer to a file.");
+
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+ assert(PLoc.isValid() && "Source location is expected to be always valid.");
+
+ llvm::sys::fs::UniqueID ID;
+ if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
+ llvm_unreachable("Source file with target region no longer exists!");
+
+ DeviceID = ID.getDevice();
+ FileID = ID.getFile();
+ LineNum = PLoc.getLine();
+}
+
+bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
+ llvm::GlobalVariable *Addr,
+ bool PerformInit) {
+ Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ isDeclareTargetDeclaration(VD);
+ if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link)
+ return false;
+ VD = VD->getDefinition(CGM.getContext());
+ if (VD && !DeclareTargetWithDefinition.insert(VD).second)
+ return CGM.getLangOpts().OpenMPIsDevice;
+
+ QualType ASTTy = VD->getType();
+
+ SourceLocation Loc = VD->getCanonicalDecl()->getLocStart();
+ // Produce the unique prefix to identify the new target regions. We use
+ // the source location of the variable declaration which we know to not
+ // conflict with any target region.
+ unsigned DeviceID;
+ unsigned FileID;
+ unsigned Line;
+ getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
+ SmallString<128> Buffer, Out;
+ {
+ llvm::raw_svector_ostream OS(Buffer);
+ OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
+ << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
+ }
+
+ const Expr *Init = VD->getAnyInitializer();
+ if (CGM.getLangOpts().CPlusPlus && PerformInit) {
+ llvm::Constant *Ctor;
+ llvm::Constant *ID;
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ // Generate function that re-emits the declaration's initializer into
+ // the threadprivate copy of the variable VD
+ CodeGenFunction CtorCGF(CGM);
+
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
+ llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
+ llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
+ FTy, Twine(Buffer, "_ctor"), FI, Loc);
+ auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
+ CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
+ FunctionArgList(), Loc, Loc);
+ auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
+ CtorCGF.EmitAnyExprToMem(Init,
+ Address(Addr, CGM.getContext().getDeclAlign(VD)),
+ Init->getType().getQualifiers(),
+ /*IsInitializer=*/true);
+ CtorCGF.FinishFunction();
+ Ctor = Fn;
+ ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
+ } else {
+ Ctor = new llvm::GlobalVariable(
+ CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage,
+ llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
+ ID = Ctor;
+ }
+
+ // Register the information for the entry associated with the constructor.
+ Out.clear();
+ OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
+ DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
+ ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
+ }
+ if (VD->getType().isDestructedType() != QualType::DK_none) {
+ llvm::Constant *Dtor;
+ llvm::Constant *ID;
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ // Generate function that emits destructor call for the threadprivate
+ // copy of the variable VD
+ CodeGenFunction DtorCGF(CGM);
+
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
+ llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
+ llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
+ FTy, Twine(Buffer, "_dtor"), FI, Loc);
+ auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
+ DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
+ FunctionArgList(), Loc, Loc);
+ // Create a scope with an artificial location for the body of this
+ // function.
+ auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
+ DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
+ ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
+ DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
+ DtorCGF.FinishFunction();
+ Dtor = Fn;
+ ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
+ } else {
+ Dtor = new llvm::GlobalVariable(
+ CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage,
+ llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
+ ID = Dtor;
+ }
+ // Register the information for the entry associated with the destructor.
+ Out.clear();
+ OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
+ DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
+ ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
+ }
+ return CGM.getLangOpts().OpenMPIsDevice;
+}
+
Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
QualType VarType,
StringRef Name) {
@@ -3328,8 +3501,8 @@
} // anonymous namespace
bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
- // FIXME: Add other entries type when they become supported.
- return OffloadEntriesTargetRegion.empty();
+ return OffloadEntriesTargetRegion.empty() &&
+ OffloadEntriesDeviceGlobalVar.empty();
}
/// \brief Initialize target region entry.
@@ -3342,7 +3515,7 @@
"code generation.");
OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
- /*Flags=*/0);
+ OMPTargetRegionEntryTargetRegion);
++OffloadingEntriesNum;
}
@@ -3350,7 +3523,7 @@
registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
StringRef ParentName, unsigned LineNum,
llvm::Constant *Addr, llvm::Constant *ID,
- int32_t Flags) {
+ OMPTargetRegionEntryKind Flags) {
// If we are emitting code for a target, the entry is already initialized,
// only has to be registered.
if (CGM.getLangOpts().OpenMPIsDevice) {
@@ -3362,10 +3535,10 @@
Entry.setAddress(Addr);
Entry.setID(ID);
Entry.setFlags(Flags);
- return;
} else {
- OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID, Flags);
+ OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
+ ++OffloadingEntriesNum;
}
}
@@ -3393,35 +3566,55 @@
void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
const OffloadTargetRegionEntryInfoActTy &Action) {
// Scan all target region entries and perform the provided action.
- for (auto &D : OffloadEntriesTargetRegion)
- for (auto &F : D.second)
- for (auto &P : F.second)
- for (auto &L : P.second)
+ for (const auto &D : OffloadEntriesTargetRegion)
+ for (const auto &F : D.second)
+ for (const auto &P : F.second)
+ for (const auto &L : P.second)
Action(D.first, F.first, P.first(), L.first, L.second);
}
-/// \brief Create a Ctor/Dtor-like function whose body is emitted through
-/// \a Codegen. This is used to emit the two functions that register and
-/// unregister the descriptor of the current compilation unit.
-static llvm::Function *
-createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name,
- const RegionCodeGenTy &Codegen) {
- auto &C = CGM.getContext();
- FunctionArgList Args;
- ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other);
- Args.push_back(&DummyPtr);
+void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
+ initializeDeviceGlobalVarEntryInfo(StringRef Name,
+ OMPTargetGlobalVarEntryKind Flags,
+ unsigned Order) {
+ assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
+ "only required for the device "
+ "code generation.");
+ OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
+ ++OffloadingEntriesNum;
+}
- CodeGenFunction CGF(CGM);
- // Disable debug info for global (de-)initializer because they are not part of
- // some particular construct.
- CGF.disableDebugInfo();
- auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
- auto FTy = CGM.getTypes().GetFunctionType(FI);
- auto *Fn = CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI);
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args);
- Codegen(CGF);
- CGF.FinishFunction();
- return Fn;
+void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
+ registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
+ CharUnits VarSize,
+ OMPTargetGlobalVarEntryKind Flags,
+ llvm::GlobalValue::LinkageTypes Linkage) {
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
+ assert(Entry.isValid() && Entry.getFlags() == Flags &&
+ "Entry not initialized!");
+ assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
+ "Resetting with the new address.");
+ if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName))
+ return;
+ Entry.setAddress(Addr);
+ Entry.setVarSize(VarSize);
+ Entry.setLinkage(Linkage);
+ } else {
+ if (hasDeviceGlobalVarEntryInfo(VarName))
+ return;
+ OffloadEntriesDeviceGlobalVar.try_emplace(
+ VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
+ ++OffloadingEntriesNum;
+ }
+}
+
+void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
+ actOnDeviceGlobalVarEntriesInfo(
+ const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
+ // Scan all target region entries and perform the provided action.
+ for (const auto &E : OffloadEntriesDeviceGlobalVar)
+ Action(E.getKey(), E.getValue());
}
llvm::Function *
@@ -3460,8 +3653,8 @@
ConstantInitBuilder DeviceImagesBuilder(CGM);
auto DeviceImagesEntries = DeviceImagesBuilder.beginArray(DeviceImageTy);
- for (unsigned i = 0; i < Devices.size(); ++i) {
- StringRef T = Devices[i].getTriple();
+ for (llvm::Triple Device : Devices) {
+ StringRef T = Device.getTriple();
auto *ImgBegin = new llvm::GlobalVariable(
M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
/*Initializer=*/nullptr,
@@ -3508,25 +3701,45 @@
// Emit code to register or unregister the descriptor at execution
// startup or closing, respectively.
- // Create a variable to drive the registration and unregistration of the
- // 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, ImplicitParamDecl::Other);
+ llvm::Function *UnRegFn;
+ {
+ FunctionArgList Args;
+ ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other);
+ Args.push_back(&DummyPtr);
- auto *UnRegFn = createOffloadingBinaryDescriptorFunction(
- CGM, ".omp_offloading.descriptor_unreg",
- [&](CodeGenFunction &CGF, PrePostActionTy &) {
- CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
- Desc);
- });
- auto *RegFn = createOffloadingBinaryDescriptorFunction(
- CGM, ".omp_offloading.descriptor_reg",
- [&](CodeGenFunction &CGF, PrePostActionTy &) {
- CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib),
- Desc);
- CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
- });
+ CodeGenFunction CGF(CGM);
+ // Disable debug info for global (de-)initializer because they are not part
+ // of some particular construct.
+ CGF.disableDebugInfo();
+ auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
+ auto FTy = CGM.getTypes().GetFunctionType(FI);
+ UnRegFn = CGM.CreateGlobalInitOrDestructFunction(
+ FTy, ".omp_offloading.descriptor_unreg", FI);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, UnRegFn, FI, Args);
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
+ Desc);
+ CGF.FinishFunction();
+ }
+ llvm::Function *RegFn;
+ {
+ CodeGenFunction CGF(CGM);
+ // Disable debug info for global (de-)initializer because they are not part
+ // of some particular construct.
+ CGF.disableDebugInfo();
+ auto &FI = CGM.getTypes().arrangeNullaryFunction();
+ llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
+ RegFn = CGM.CreateGlobalInitOrDestructFunction(
+ FTy, ".omp_offloading.descriptor_reg", FI);
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, RegFn, FI, FunctionArgList());
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib), Desc);
+ // Create a variable to drive the registration and unregistration of the
+ // descriptor, so we can reuse the logic that emits Ctors and Dtors.
+ ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(),
+ SourceLocation(), nullptr, C.CharTy,
+ ImplicitParamDecl::Other);
+ CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
+ CGF.FinishFunction();
+ }
if (CGM.supportsCOMDAT()) {
// It is sufficient to call registration function only once, so create a
// COMDAT group for registration/unregistration functions and associated
@@ -3543,9 +3756,9 @@
return RegFn;
}
-void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID,
- llvm::Constant *Addr, uint64_t Size,
- int32_t Flags) {
+void CGOpenMPRuntime::createOffloadEntry(
+ llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
+ llvm::GlobalValue::LinkageTypes Linkage) {
StringRef Name = Addr->getName();
auto *TgtOffloadEntryType = cast<llvm::StructType>(
CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()));
@@ -3578,8 +3791,8 @@
EntryInit.addInt(CGM.Int32Ty, Flags);
EntryInit.addInt(CGM.Int32Ty, 0);
llvm::GlobalVariable *Entry = EntryInit.finishAndCreateGlobal(
- Twine(".omp_offloading.entry.") + Name, Align,
- /*constant*/ true, llvm::GlobalValue::ExternalLinkage);
+ Twine(".omp_offloading.entry.", Name), Align,
+ /*Constant=*/true, Linkage);
// The entry has to be created in the section the linker expects it to be.
Entry->setSection(".omp_offloading.entries");
@@ -3601,61 +3814,96 @@
llvm::Module &M = CGM.getModule();
llvm::LLVMContext &C = M.getContext();
- SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
+ SmallVector<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
OrderedEntries(OffloadEntriesInfoManager.size());
+ // Auxiliary methods to create metadata values and strings.
+ auto &&GetMDInt = [&C](unsigned V) {
+ return llvm::ConstantAsMetadata::get(
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), V));
+ };
+
+ auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
+
// Create the offloading info metadata node.
llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
- // Auxiliary methods to create metadata values and strings.
- auto getMDInt = [&](unsigned v) {
- return llvm::ConstantAsMetadata::get(
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v));
- };
-
- auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); };
-
// Create function that emits metadata for each target region entry;
- auto &&TargetRegionMetadataEmitter = [&](
- unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line,
- OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
- llvm::SmallVector<llvm::Metadata *, 32> Ops;
- // Generate metadata for target regions. Each entry of this metadata
- // contains:
- // - Entry 0 -> Kind of this type of metadata (0).
- // - Entry 1 -> Device ID of the file where the entry was identified.
- // - Entry 2 -> File ID of the file where the entry was identified.
- // - Entry 3 -> Mangled name of the function where the entry was identified.
- // - Entry 4 -> Line in the file where the entry was identified.
- // - Entry 5 -> Order the entry was created.
- // The first element of the metadata node is the kind.
- Ops.push_back(getMDInt(E.getKind()));
- Ops.push_back(getMDInt(DeviceID));
- Ops.push_back(getMDInt(FileID));
- Ops.push_back(getMDString(ParentName));
- Ops.push_back(getMDInt(Line));
- Ops.push_back(getMDInt(E.getOrder()));
+ auto &&TargetRegionMetadataEmitter =
+ [&C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
+ unsigned DeviceID, unsigned FileID, StringRef ParentName,
+ unsigned Line,
+ const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
+ // Generate metadata for target regions. Each entry of this metadata
+ // contains:
+ // - Entry 0 -> Kind of this type of metadata (0).
+ // - Entry 1 -> Device ID of the file where the entry was identified.
+ // - Entry 2 -> File ID of the file where the entry was identified.
+ // - Entry 3 -> Mangled name of the function where the entry was
+ // identified.
+ // - Entry 4 -> Line in the file where the entry was identified.
+ // - Entry 5 -> Order the entry was created.
+ // The first element of the metadata node is the kind.
+ llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
+ GetMDInt(FileID), GetMDString(ParentName),
+ GetMDInt(Line), GetMDInt(E.getOrder())};
- // Save this entry in the right position of the ordered entries array.
- OrderedEntries[E.getOrder()] = &E;
+ // Save this entry in the right position of the ordered entries array.
+ OrderedEntries[E.getOrder()] = &E;
- // Add metadata to the named metadata node.
- MD->addOperand(llvm::MDNode::get(C, Ops));
- };
+ // Add metadata to the named metadata node.
+ MD->addOperand(llvm::MDNode::get(C, Ops));
+ };
OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
TargetRegionMetadataEmitter);
- for (auto *E : OrderedEntries) {
+ // Create function that emits metadata for each device global variable entry;
+ auto &&DeviceGlobalVarMetadataEmitter =
+ [&C, &OrderedEntries, &GetMDInt, &GetMDString,
+ MD](StringRef MangledName,
+ const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
+ &E) {
+ // Generate metadata for global variables. Each entry of this metadata
+ // contains:
+ // - Entry 0 -> Kind of this type of metadata (1).
+ // - Entry 1 -> Mangled name of the variable.
+ // - Entry 2 -> Declare target kind.
+ // - Entry 3 -> Order the entry was created.
+ // The first element of the metadata node is the kind.
+ llvm::Metadata *Ops[] = {
+ GetMDInt(E.getKind()), GetMDString(MangledName),
+ GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
+
+ // Save this entry in the right position of the ordered entries array.
+ OrderedEntries[E.getOrder()] = &E;
+
+ // Add metadata to the named metadata node.
+ MD->addOperand(llvm::MDNode::get(C, Ops));
+ };
+
+ OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
+ DeviceGlobalVarMetadataEmitter);
+
+ for (const auto *E : OrderedEntries) {
assert(E && "All ordered entries must exist!");
- if (auto *CE =
+ if (const auto *CE =
dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
E)) {
assert(CE->getID() && CE->getAddress() &&
"Entry ID and Addr are invalid!");
- createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0);
- } else
+ createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
+ CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
+ } else if (const auto *CE =
+ dyn_cast<OffloadEntriesInfoManagerTy::
+ OffloadEntryInfoDeviceGlobalVar>(E)) {
+ assert(CE->getAddress() && "Entry Addr is invalid!");
+ createOffloadEntry(CE->getAddress(), CE->getAddress(),
+ CE->getVarSize().getQuantity(), CE->getFlags(),
+ CE->getLinkage());
+ } else {
llvm_unreachable("Unsupported entry kind.");
+ }
}
}
@@ -3687,27 +3935,35 @@
return;
for (llvm::MDNode *MN : MD->operands()) {
- auto getMDInt = [&](unsigned Idx) {
+ auto GetMDInt = [MN](unsigned Idx) {
llvm::ConstantAsMetadata *V =
cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
};
- auto getMDString = [&](unsigned Idx) {
+ auto GetMDString = [MN](unsigned Idx) {
llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx));
return V->getString();
};
- switch (getMDInt(0)) {
+ switch (GetMDInt(0)) {
default:
llvm_unreachable("Unexpected metadata!");
break;
case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
- OFFLOAD_ENTRY_INFO_TARGET_REGION:
+ OffloadingEntryInfoTargetRegion:
OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
- /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2),
- /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4),
- /*Order=*/getMDInt(5));
+ /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
+ /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
+ /*Order=*/GetMDInt(5));
+ break;
+ case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
+ OffloadingEntryInfoDeviceGlobalVar:
+ OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
+ /*MangledName=*/GetMDString(1),
+ static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
+ /*Flags=*/GetMDInt(2)),
+ /*Order=*/GetMDInt(3));
break;
}
}
@@ -5422,6 +5678,9 @@
CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
CGF, CGM.getContext().VoidPtrTy,
generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
+ SharedAddr = CGF.EmitLoadOfPointer(
+ SharedAddr,
+ CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
} else {
SharedLVal = CGF.MakeNaturalAlignAddrLValue(
@@ -5835,33 +6094,6 @@
}
}
-/// \brief Obtain information that uniquely identifies a target entry. This
-/// consists of the file and device IDs as well as line number associated with
-/// the relevant entry source location.
-static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
- unsigned &DeviceID, unsigned &FileID,
- unsigned &LineNum) {
-
- auto &SM = C.getSourceManager();
-
- // The loc should be always valid and have a file ID (the user cannot use
- // #pragma directives in macros)
-
- assert(Loc.isValid() && "Source location is expected to be always valid.");
- assert(Loc.isFileID() && "Source location is expected to refer to a file.");
-
- PresumedLoc PLoc = SM.getPresumedLoc(Loc);
- assert(PLoc.isValid() && "Source location is expected to be always valid.");
-
- llvm::sys::fs::UniqueID ID;
- if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
- llvm_unreachable("Source file with target region no longer exists!");
-
- DeviceID = ID.getDevice();
- FileID = ID.getFile();
- LineNum = PLoc.getLine();
-}
-
void CGOpenMPRuntime::emitTargetOutlinedFunction(
const OMPExecutableDirective &D, StringRef ParentName,
llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
@@ -5934,7 +6166,7 @@
// Register the information for the entry associated with this target region.
OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
- /*Flags=*/0);
+ OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
}
/// discard all CompoundStmts intervening between two constructs
@@ -6317,6 +6549,50 @@
return ConstLength.getSExtValue() != 1;
}
+ /// \brief Return the adjusted map modifiers if the declaration a capture
+ /// refers to appears in a first-private clause. This is expected to be used
+ /// only with directives that start with 'target'.
+ unsigned adjustMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap,
+ unsigned CurrentModifiers) {
+ assert(Cap.capturesVariable() && "Expected capture by reference only!");
+
+ // A first private variable captured by reference will use only the
+ // 'private ptr' and 'map to' flag. Return the right flags if the captured
+ // declaration is known as first-private in this handler.
+ if (FirstPrivateDecls.count(Cap.getCapturedVar()))
+ return MappableExprsHandler::OMP_MAP_PRIVATE |
+ MappableExprsHandler::OMP_MAP_TO;
+ // Reduction variable will use only the 'private ptr' and 'map to_from'
+ // flag.
+ if (ReductionDecls.count(Cap.getCapturedVar())) {
+ return MappableExprsHandler::OMP_MAP_TO |
+ MappableExprsHandler::OMP_MAP_FROM;
+ }
+
+ // We didn't modify anything.
+ return CurrentModifiers;
+ }
+
+public:
+ MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
+ : CurDir(Dir), CGF(CGF) {
+ // Extract firstprivate clause information.
+ for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
+ for (const auto *D : C->varlists())
+ FirstPrivateDecls.insert(
+ cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
+ for (const auto *C : Dir.getClausesOfKind<OMPReductionClause>()) {
+ for (const auto *D : C->varlists()) {
+ ReductionDecls.insert(
+ cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
+ }
+ }
+ // Extract device pointer clause information.
+ for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
+ for (auto L : C->component_lists())
+ DevPointersMap[L.first].push_back(L.second);
+ }
+
/// \brief Generate the base pointers, section pointers, sizes and map type
/// bits for the provided map type, map modifier, and expression components.
/// \a IsFirstComponent should be set to true if the provided set of
@@ -6442,6 +6718,7 @@
// Track if the map information being generated is the first for a capture.
bool IsCaptureFirstInfo = IsFirstComponentList;
+ bool IsLink = false; // Is this variable a "declare target link"?
// Scan the components from the base to the complete expression.
auto CI = Components.rbegin();
@@ -6461,6 +6738,20 @@
// The base is the reference to the variable.
// BP = &Var.
BP = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getPointer();
+ if (const auto *VD =
+ dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
+ if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ isDeclareTargetDeclaration(VD)) {
+ assert(*Res == OMPDeclareTargetDeclAttr::MT_Link &&
+ "Declare target link is expected.");
+ // Avoid warning in release build.
+ (void)*Res;
+ IsLink = true;
+ BP = CGF.CGM.getOpenMPRuntime()
+ .getAddrOfDeclareTargetLink(VD)
+ .getPointer();
+ }
+ }
// If the variable is a pointer and is being dereferenced (i.e. is not
// the last component), the base has to be the pointer itself, not its
@@ -6549,9 +6840,10 @@
// same expression except for the first one. We also need to signal
// this map is the first one that relates with the current capture
// (there is a set of entries for each capture).
- Types.push_back(DefaultFlags | getMapTypeBits(MapType, MapTypeModifier,
- !IsExpressionFirstInfo,
- IsCaptureFirstInfo));
+ Types.push_back(DefaultFlags |
+ getMapTypeBits(MapType, MapTypeModifier,
+ !IsExpressionFirstInfo || IsLink,
+ IsCaptureFirstInfo && !IsLink));
// If we have a final array section, we are done with this expression.
if (IsFinalArraySection)
@@ -6567,50 +6859,6 @@
}
}
- /// \brief Return the adjusted map modifiers if the declaration a capture
- /// refers to appears in a first-private clause. This is expected to be used
- /// only with directives that start with 'target'.
- unsigned adjustMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap,
- unsigned CurrentModifiers) {
- assert(Cap.capturesVariable() && "Expected capture by reference only!");
-
- // A first private variable captured by reference will use only the
- // 'private ptr' and 'map to' flag. Return the right flags if the captured
- // declaration is known as first-private in this handler.
- if (FirstPrivateDecls.count(Cap.getCapturedVar()))
- return MappableExprsHandler::OMP_MAP_PRIVATE |
- MappableExprsHandler::OMP_MAP_TO;
- // Reduction variable will use only the 'private ptr' and 'map to_from'
- // flag.
- if (ReductionDecls.count(Cap.getCapturedVar())) {
- return MappableExprsHandler::OMP_MAP_TO |
- MappableExprsHandler::OMP_MAP_FROM;
- }
-
- // We didn't modify anything.
- return CurrentModifiers;
- }
-
-public:
- MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
- : CurDir(Dir), CGF(CGF) {
- // Extract firstprivate clause information.
- for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
- for (const auto *D : C->varlists())
- FirstPrivateDecls.insert(
- cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
- for (const auto *C : Dir.getClausesOfKind<OMPReductionClause>()) {
- for (const auto *D : C->varlists()) {
- ReductionDecls.insert(
- cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
- }
- }
- // Extract device pointer clause information.
- for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
- for (auto L : C->component_lists())
- DevPointersMap[L.first].push_back(L.second);
- }
-
/// \brief Generate all the base pointers, section pointers, sizes and map
/// types for the extracted mappable expressions. Also, for each item that
/// relates with a device pointer, a pair of the relevant declaration and
@@ -7251,6 +7499,25 @@
Sizes.append(CurSizes.begin(), CurSizes.end());
MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
}
+ // Map other list items in the map clause which are not captured variables
+ // but "declare target link" global variables.
+ for (const auto *C : D.getClausesOfKind<OMPMapClause>()) {
+ for (auto L : C->component_lists()) {
+ if (!L.first)
+ continue;
+ const auto *VD = dyn_cast<VarDecl>(L.first);
+ if (!VD)
+ continue;
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ isDeclareTargetDeclaration(VD);
+ if (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
+ continue;
+ MEHandler.generateInfoForComponentList(
+ C->getMapType(), C->getMapTypeModifier(), L.second, BasePointers,
+ Pointers, Sizes, MapTypes, /*IsFirstComponentList=*/true,
+ C->isImplicit());
+ }
+ }
TargetDataInfo Info;
// Fill up the arrays and create the arguments.
@@ -7402,10 +7669,8 @@
// Try to detect target regions in the function.
scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD));
- // We should not emit any function other that the ones created during the
- // scanning. Therefore, we signal that this function is completely dealt
- // with.
- return true;
+ // Do not to emit function if it is not marked as declare target.
+ return !isDeclareTargetDeclaration(&FD);
}
bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
@@ -7430,9 +7695,43 @@
}
}
- // 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;
+ // Do not to emit variable if it is not marked as declare target.
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ isDeclareTargetDeclaration(cast<VarDecl>(GD.getDecl()));
+ return !Res || *Res == OMPDeclareTargetDeclAttr::MT_Link;
+}
+
+void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
+ llvm::Constant *Addr) {
+ if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ isDeclareTargetDeclaration(VD)) {
+ OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
+ StringRef VarName;
+ CharUnits VarSize;
+ llvm::GlobalValue::LinkageTypes Linkage;
+ switch (*Res) {
+ case OMPDeclareTargetDeclAttr::MT_To:
+ Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
+ VarName = CGM.getMangledName(VD);
+ VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
+ Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
+ break;
+ case OMPDeclareTargetDeclAttr::MT_Link:
+ // Map type 'to' because we do not map the original variable but the
+ // reference.
+ Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
+ if (!CGM.getLangOpts().OpenMPIsDevice) {
+ Addr =
+ cast<llvm::Constant>(getAddrOfDeclareTargetLink(VD).getPointer());
+ }
+ VarName = Addr->getName();
+ VarSize = CGM.getPointerSize();
+ Linkage = llvm::GlobalValue::WeakAnyLinkage;
+ break;
+ }
+ OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
+ VarName, Addr, VarSize, Flags, Linkage);
+ }
}
bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
@@ -7443,6 +7742,45 @@
return emitTargetGlobalVariable(GD);
}
+CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
+ CodeGenModule &CGM)
+ : CGM(CGM) {
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
+ CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
+ }
+}
+
+CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
+ if (CGM.getLangOpts().OpenMPIsDevice)
+ CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
+}
+
+bool CGOpenMPRuntime::markAsGlobalTarget(const FunctionDecl *D) {
+ if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
+ return true;
+
+ const FunctionDecl *FD = D->getCanonicalDecl();
+ // Do not to emit function if it is marked as declare target as it was already
+ // emitted.
+ if (isDeclareTargetDeclaration(D)) {
+ if (D->hasBody() && AlreadyEmittedTargetFunctions.count(FD) == 0) {
+ if (auto *F = dyn_cast_or_null<llvm::Function>(
+ CGM.GetGlobalValue(CGM.getMangledName(D))))
+ return !F->isDeclaration();
+ return false;
+ }
+ return true;
+ }
+
+ // Do not mark member functions except for static.
+ if (const auto *Method = dyn_cast<CXXMethodDecl>(FD))
+ if (!Method->isStatic())
+ return true;
+
+ return !AlreadyEmittedTargetFunctions.insert(FD).second;
+}
+
llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
// If we have offloading in the current module, we need to emit the entries
// now and register the offloading descriptor.
@@ -8097,6 +8435,11 @@
return CGF.GetAddrOfLocalVar(NativeParam);
}
+Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
+ const VarDecl *VD) {
+ return Address::invalid();
+}
+
llvm::Value *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h
index 179d9b4..51c3305 100644
--- a/lib/CodeGen/CGOpenMPRuntime.h
+++ b/lib/CodeGen/CGOpenMPRuntime.h
@@ -199,13 +199,26 @@
};
class CGOpenMPRuntime {
+public:
+ /// Allows to disable automatic handling of functions used in target regions
+ /// as those marked as `omp declare target`.
+ class DisableAutoDeclareTargetRAII {
+ CodeGenModule &CGM;
+ bool SavedShouldMarkAsGlobal;
+
+ public:
+ DisableAutoDeclareTargetRAII(CodeGenModule &CGM);
+ ~DisableAutoDeclareTargetRAII();
+ };
+
protected:
CodeGenModule &CGM;
/// \brief Creates offloading entry for the provided entry ID \a ID,
/// address \a Addr, size \a Size, and flags \a Flags.
virtual void createOffloadEntry(llvm::Constant *ID, llvm::Constant *Addr,
- uint64_t Size, int32_t Flags = 0);
+ uint64_t Size, int32_t Flags,
+ llvm::GlobalValue::LinkageTypes Linkage);
/// \brief Helper to emit outlined function for 'target' directive.
/// \param D Directive to emit.
@@ -256,6 +269,10 @@
void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *Callee,
ArrayRef<llvm::Value *> Args = llvm::None) const;
+ /// \brief Emits address of the word in a memory where current thread id is
+ /// stored.
+ virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc);
+
private:
/// \brief Default const ident_t object used for initialization of all other
/// ident_t objects.
@@ -372,106 +389,187 @@
CodeGenModule &CGM;
/// \brief Number of entries registered so far.
- unsigned OffloadingEntriesNum;
+ unsigned OffloadingEntriesNum = 0;
public:
/// Base class of the entries info.
class OffloadEntryInfo {
public:
- /// Kind of a given entry. Currently, only target regions are
- /// supported.
+ /// Kind of a given entry.
enum OffloadingEntryInfoKinds : unsigned {
- // Entry is a target region.
- OFFLOAD_ENTRY_INFO_TARGET_REGION = 0,
- // Invalid entry info.
- OFFLOAD_ENTRY_INFO_INVALID = ~0u
+ /// Entry is a target region.
+ OffloadingEntryInfoTargetRegion = 0,
+ /// Entry is a declare target variable.
+ OffloadingEntryInfoDeviceGlobalVar = 1,
+ /// Invalid entry info.
+ OffloadingEntryInfoInvalid = ~0u
};
- OffloadEntryInfo()
- : Flags(0), Order(~0u), Kind(OFFLOAD_ENTRY_INFO_INVALID) {}
+ protected:
+ OffloadEntryInfo() = delete;
+ explicit OffloadEntryInfo(OffloadingEntryInfoKinds Kind) : Kind(Kind) {}
explicit OffloadEntryInfo(OffloadingEntryInfoKinds Kind, unsigned Order,
- int32_t Flags)
+ uint32_t Flags)
: Flags(Flags), Order(Order), Kind(Kind) {}
+ ~OffloadEntryInfo() = default;
+ public:
bool isValid() const { return Order != ~0u; }
unsigned getOrder() const { return Order; }
OffloadingEntryInfoKinds getKind() const { return Kind; }
- int32_t getFlags() const { return Flags; }
- void setFlags(int32_t NewFlags) { Flags = NewFlags; }
+ uint32_t getFlags() const { return Flags; }
+ void setFlags(uint32_t NewFlags) { Flags = NewFlags; }
+ llvm::Constant *getAddress() const {
+ return cast_or_null<llvm::Constant>(Addr);
+ }
+ void setAddress(llvm::Constant *V) {
+ assert(!Addr.pointsToAliveValue() && "Address has been set before!");
+ Addr = V;
+ }
static bool classof(const OffloadEntryInfo *Info) { return true; }
private:
+ /// Address of the entity that has to be mapped for offloading.
+ llvm::WeakTrackingVH Addr;
+
/// Flags associated with the device global.
- int32_t Flags;
+ uint32_t Flags = 0u;
/// Order this entry was emitted.
- unsigned Order;
+ unsigned Order = ~0u;
- OffloadingEntryInfoKinds Kind;
+ OffloadingEntryInfoKinds Kind = OffloadingEntryInfoInvalid;
};
- /// \brief Return true if a there are no entries defined.
+ /// Return true if a there are no entries defined.
bool empty() const;
- /// \brief Return number of entries defined so far.
+ /// Return number of entries defined so far.
unsigned size() const { return OffloadingEntriesNum; }
- OffloadEntriesInfoManagerTy(CodeGenModule &CGM)
- : CGM(CGM), OffloadingEntriesNum(0) {}
+ OffloadEntriesInfoManagerTy(CodeGenModule &CGM) : CGM(CGM) {}
- ///
- /// Target region entries related.
- ///
- /// \brief Target region entries info.
- class OffloadEntryInfoTargetRegion : public OffloadEntryInfo {
- // \brief Address of the entity that has to be mapped for offloading.
- llvm::Constant *Addr;
- // \brief Address that can be used as the ID of the entry.
- llvm::Constant *ID;
+ //
+ // Target region entries related.
+ //
+
+ /// Kind of the target registry entry.
+ enum OMPTargetRegionEntryKind : uint32_t {
+ /// Mark the entry as target region.
+ OMPTargetRegionEntryTargetRegion = 0x0,
+ /// Mark the entry as a global constructor.
+ OMPTargetRegionEntryCtor = 0x02,
+ /// Mark the entry as a global destructor.
+ OMPTargetRegionEntryDtor = 0x04,
+ };
+
+ /// Target region entries info.
+ class OffloadEntryInfoTargetRegion final : public OffloadEntryInfo {
+ /// Address that can be used as the ID of the entry.
+ llvm::Constant *ID = nullptr;
public:
OffloadEntryInfoTargetRegion()
- : OffloadEntryInfo(OFFLOAD_ENTRY_INFO_TARGET_REGION, ~0u,
- /*Flags=*/0),
- Addr(nullptr), ID(nullptr) {}
+ : OffloadEntryInfo(OffloadingEntryInfoTargetRegion) {}
explicit OffloadEntryInfoTargetRegion(unsigned Order,
llvm::Constant *Addr,
- llvm::Constant *ID, int32_t Flags)
- : OffloadEntryInfo(OFFLOAD_ENTRY_INFO_TARGET_REGION, Order, Flags),
- Addr(Addr), ID(ID) {}
-
- llvm::Constant *getAddress() const { return Addr; }
- llvm::Constant *getID() const { return ID; }
- void setAddress(llvm::Constant *V) {
- assert(!Addr && "Address as been set before!");
- Addr = V;
+ llvm::Constant *ID,
+ OMPTargetRegionEntryKind Flags)
+ : OffloadEntryInfo(OffloadingEntryInfoTargetRegion, Order, Flags),
+ ID(ID) {
+ setAddress(Addr);
}
+
+ llvm::Constant *getID() const { return ID; }
void setID(llvm::Constant *V) {
- assert(!ID && "ID as been set before!");
+ assert(!ID && "ID has been set before!");
ID = V;
}
static bool classof(const OffloadEntryInfo *Info) {
- return Info->getKind() == OFFLOAD_ENTRY_INFO_TARGET_REGION;
+ return Info->getKind() == OffloadingEntryInfoTargetRegion;
}
};
- /// \brief Initialize target region entry.
+
+ /// Initialize target region entry.
void initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
StringRef ParentName, unsigned LineNum,
unsigned Order);
- /// \brief Register target region entry.
+ /// Register target region entry.
void registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
StringRef ParentName, unsigned LineNum,
llvm::Constant *Addr, llvm::Constant *ID,
- int32_t Flags);
- /// \brief Return true if a target region entry with the provided
- /// information exists.
+ OMPTargetRegionEntryKind Flags);
+ /// Return true if a target region entry with the provided information
+ /// exists.
bool hasTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
StringRef ParentName, unsigned LineNum) const;
/// brief Applies action \a Action on all registered entries.
typedef llvm::function_ref<void(unsigned, unsigned, StringRef, unsigned,
- OffloadEntryInfoTargetRegion &)>
+ const OffloadEntryInfoTargetRegion &)>
OffloadTargetRegionEntryInfoActTy;
void actOnTargetRegionEntriesInfo(
const OffloadTargetRegionEntryInfoActTy &Action);
+ //
+ // Device global variable entries related.
+ //
+
+ /// Kind of the global variable entry..
+ enum OMPTargetGlobalVarEntryKind : uint32_t {
+ /// Mark the entry as a to declare target.
+ OMPTargetGlobalVarEntryTo = 0x0,
+ };
+
+ /// Device global variable entries info.
+ class OffloadEntryInfoDeviceGlobalVar final : public OffloadEntryInfo {
+ /// Type of the global variable.
+ CharUnits VarSize;
+ llvm::GlobalValue::LinkageTypes Linkage;
+
+ public:
+ OffloadEntryInfoDeviceGlobalVar()
+ : OffloadEntryInfo(OffloadingEntryInfoDeviceGlobalVar) {}
+ explicit OffloadEntryInfoDeviceGlobalVar(unsigned Order,
+ OMPTargetGlobalVarEntryKind Flags)
+ : OffloadEntryInfo(OffloadingEntryInfoDeviceGlobalVar, Order, Flags) {}
+ explicit OffloadEntryInfoDeviceGlobalVar(
+ unsigned Order, llvm::Constant *Addr, CharUnits VarSize,
+ OMPTargetGlobalVarEntryKind Flags,
+ llvm::GlobalValue::LinkageTypes Linkage)
+ : OffloadEntryInfo(OffloadingEntryInfoDeviceGlobalVar, Order, Flags),
+ VarSize(VarSize), Linkage(Linkage) {
+ setAddress(Addr);
+ }
+
+ CharUnits getVarSize() const { return VarSize; }
+ void setVarSize(CharUnits Size) { VarSize = Size; }
+ llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; }
+ void setLinkage(llvm::GlobalValue::LinkageTypes LT) { Linkage = LT; }
+ static bool classof(const OffloadEntryInfo *Info) {
+ return Info->getKind() == OffloadingEntryInfoDeviceGlobalVar;
+ }
+ };
+
+ /// Initialize device global variable entry.
+ void initializeDeviceGlobalVarEntryInfo(StringRef Name,
+ OMPTargetGlobalVarEntryKind Flags,
+ unsigned Order);
+
+ /// Register device global variable entry.
+ void
+ registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
+ CharUnits VarSize,
+ OMPTargetGlobalVarEntryKind Flags,
+ llvm::GlobalValue::LinkageTypes Linkage);
+ /// Checks if the variable with the given name has been registered already.
+ bool hasDeviceGlobalVarEntryInfo(StringRef VarName) const {
+ return OffloadEntriesDeviceGlobalVar.count(VarName) > 0;
+ }
+ /// Applies action \a Action on all registered entries.
+ typedef llvm::function_ref<void(StringRef,
+ const OffloadEntryInfoDeviceGlobalVar &)>
+ OffloadDeviceGlobalVarEntryInfoActTy;
+ void actOnDeviceGlobalVarEntriesInfo(
+ const OffloadDeviceGlobalVarEntryInfoActTy &Action);
+
private:
// Storage for target region entries kind. The storage is to be indexed by
// file ID, device ID, parent function name and line number.
@@ -485,9 +583,17 @@
OffloadEntriesTargetRegionPerDevice;
typedef OffloadEntriesTargetRegionPerDevice OffloadEntriesTargetRegionTy;
OffloadEntriesTargetRegionTy OffloadEntriesTargetRegion;
+ /// Storage for device global variable entries kind. The storage is to be
+ /// indexed by mangled name.
+ typedef llvm::StringMap<OffloadEntryInfoDeviceGlobalVar>
+ OffloadEntriesDeviceGlobalVarTy;
+ OffloadEntriesDeviceGlobalVarTy OffloadEntriesDeviceGlobalVar;
};
OffloadEntriesInfoManagerTy OffloadEntriesInfoManager;
+ bool ShouldMarkAsGlobal = true;
+ llvm::SmallDenseSet<const FunctionDecl *> AlreadyEmittedTargetFunctions;
+
/// \brief Creates and registers offloading binary descriptor for the current
/// compilation unit. The function that does the registration is returned.
llvm::Function *createOffloadingBinaryDescriptorRegistration();
@@ -549,10 +655,6 @@
/// \return Cache variable for the specified threadprivate.
llvm::Constant *getOrCreateThreadPrivateCache(const VarDecl *VD);
- /// \brief Emits address of the word in a memory where current thread id is
- /// stored.
- virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc);
-
/// \brief Gets (if variable with the given name already exist) or creates
/// internal global variable with the specified Name. The created variable has
/// linkage CommonLinkage by default and is initialized by null value.
@@ -565,6 +667,9 @@
/// \brief Set of threadprivate variables with the generated initializer.
llvm::SmallPtrSet<const VarDecl *, 4> ThreadPrivateWithDefinition;
+ /// Set of declare target variables with the generated initializer.
+ llvm::SmallPtrSet<const VarDecl *, 4> DeclareTargetWithDefinition;
+
/// \brief Emits initialization code for the threadprivate variables.
/// \param VDAddr Address of the global variable \a VD.
/// \param Ctor Pointer to a global init function for \a VD.
@@ -676,7 +781,7 @@
/// \brief Cleans up references to the objects in finished function.
///
- void functionFinished(CodeGenFunction &CGF);
+ virtual void functionFinished(CodeGenFunction &CGF);
/// \brief Emits code for parallel or serial call of the \a OutlinedFn with
/// variables captured in a record which address is stored in \a
@@ -937,6 +1042,10 @@
Address VDAddr,
SourceLocation Loc);
+ /// Returns the address of the variable marked as declare target with link
+ /// clause.
+ virtual Address getAddrOfDeclareTargetLink(const VarDecl *VD);
+
/// \brief Emit a code for initialization of threadprivate variable. It emits
/// a call to runtime library which adds initial value to the newly created
/// threadprivate variable (if it is not constant) and registers destructor
@@ -950,6 +1059,14 @@
SourceLocation Loc, bool PerformInit,
CodeGenFunction *CGF = nullptr);
+ /// \brief Emit a code for initialization of declare target variable.
+ /// \param VD Declare target variable.
+ /// \param Addr Address of the global variable \a VD.
+ /// \param PerformInit true if initialization expression is not constant.
+ virtual bool emitDeclareTargetVarDefinition(const VarDecl *VD,
+ llvm::GlobalVariable *Addr,
+ bool PerformInit);
+
/// Creates artificial threadprivate variable with name \p Name and type \p
/// VarType.
/// \param VarType Type of the artificial threadprivate variable.
@@ -1225,6 +1342,11 @@
/// \param GD Variable declaration to emit.
virtual bool emitTargetGlobalVariable(GlobalDecl GD);
+ /// Checks if the provided global decl \a GD is a declare target variable and
+ /// registers it when emitting code for the host.
+ virtual void registerTargetGlobalVariable(const VarDecl *VD,
+ llvm::Constant *Addr);
+
/// \brief Emit the global \a GD if it is meaningful for the target. Returns
/// if it was emitted successfully.
/// \param GD Global to scan.
@@ -1362,6 +1484,19 @@
emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc,
llvm::Value *OutlinedFn,
ArrayRef<llvm::Value *> Args = llvm::None) const;
+
+ /// Emits OpenMP-specific function prolog.
+ /// Required for device constructs.
+ virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {}
+
+ /// Gets the OpenMP-specific address of the local variable.
+ virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF,
+ const VarDecl *VD);
+
+ /// Marks the declaration as alread emitted for the device code and returns
+ /// true, if it was marked already, and false, otherwise.
+ bool markAsGlobalTarget(const FunctionDecl *D);
+
};
/// Class supports emissionof SIMD-only code.
diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
index 8ebfa3a..75d3ba7 100644
--- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
+++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
@@ -13,9 +13,11 @@
//===----------------------------------------------------------------------===//
#include "CGOpenMPRuntimeNVPTX.h"
-#include "clang/AST/DeclOpenMP.h"
#include "CodeGenFunction.h"
+#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/StmtOpenMP.h"
+#include "clang/AST/StmtVisitor.h"
+#include "llvm/ADT/SmallPtrSet.h"
using namespace clang;
using namespace CodeGen;
@@ -33,11 +35,11 @@
/// \brief Call to void __kmpc_spmd_kernel_deinit();
OMPRTL_NVPTX__kmpc_spmd_kernel_deinit,
/// \brief Call to void __kmpc_kernel_prepare_parallel(void
- /// *outlined_function, void ***args, kmp_int32 nArgs, int16_t
+ /// *outlined_function, int16_t
/// IsOMPRuntimeInitialized);
OMPRTL_NVPTX__kmpc_kernel_prepare_parallel,
- /// \brief Call to bool __kmpc_kernel_parallel(void **outlined_function, void
- /// ***args, int16_t IsOMPRuntimeInitialized);
+ /// \brief Call to bool __kmpc_kernel_parallel(void **outlined_function,
+ /// int16_t IsOMPRuntimeInitialized);
OMPRTL_NVPTX__kmpc_kernel_parallel,
/// \brief Call to void __kmpc_kernel_end_parallel();
OMPRTL_NVPTX__kmpc_kernel_end_parallel,
@@ -70,7 +72,21 @@
/// index, int32_t width, int32_t reduce))
OMPRTL_NVPTX__kmpc_teams_reduce_nowait,
/// \brief Call to __kmpc_nvptx_end_reduce_nowait(int32_t global_tid);
- OMPRTL_NVPTX__kmpc_end_reduce_nowait
+ OMPRTL_NVPTX__kmpc_end_reduce_nowait,
+ /// \brief Call to void __kmpc_data_sharing_init_stack();
+ OMPRTL_NVPTX__kmpc_data_sharing_init_stack,
+ /// \brief Call to void* __kmpc_data_sharing_push_stack(size_t size,
+ /// int16_t UseSharedMemory);
+ OMPRTL_NVPTX__kmpc_data_sharing_push_stack,
+ /// \brief Call to void __kmpc_data_sharing_pop_stack(void *a);
+ OMPRTL_NVPTX__kmpc_data_sharing_pop_stack,
+ /// \brief Call to void __kmpc_begin_sharing_variables(void ***args,
+ /// size_t n_args);
+ OMPRTL_NVPTX__kmpc_begin_sharing_variables,
+ /// \brief Call to void __kmpc_end_sharing_variables();
+ OMPRTL_NVPTX__kmpc_end_sharing_variables,
+ /// \brief Call to void __kmpc_get_shared_variables(void ***GlobalArgs)
+ OMPRTL_NVPTX__kmpc_get_shared_variables,
};
/// Pre(post)-action for different OpenMP constructs specialized for NVPTX.
@@ -149,6 +165,292 @@
/// barrier.
NB_Parallel = 1,
};
+
+/// Get the list of variables that can escape their declaration context.
+class CheckVarsEscapingDeclContext final
+ : public ConstStmtVisitor<CheckVarsEscapingDeclContext> {
+ CodeGenFunction &CGF;
+ llvm::SetVector<const ValueDecl *> EscapedDecls;
+ llvm::SetVector<const ValueDecl *> EscapedVariableLengthDecls;
+ llvm::SmallPtrSet<const Decl *, 4> EscapedParameters;
+ bool AllEscaped = false;
+ RecordDecl *GlobalizedRD = nullptr;
+ llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> MappedDeclsFields;
+
+ static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
+ isDeclareTargetDeclaration(const ValueDecl *VD) {
+ for (const auto *D : VD->redecls()) {
+ if (!D->hasAttrs())
+ continue;
+ if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
+ return Attr->getMapType();
+ }
+ return llvm::None;
+ }
+
+ void markAsEscaped(const ValueDecl *VD) {
+ // Do not globalize declare target variables.
+ if (isDeclareTargetDeclaration(VD))
+ return;
+ VD = cast<ValueDecl>(VD->getCanonicalDecl());
+ // Variables captured by value must be globalized.
+ if (auto *CSI = CGF.CapturedStmtInfo) {
+ if (const FieldDecl *FD = CSI->lookup(cast<VarDecl>(VD))) {
+ if (!FD->hasAttrs())
+ return;
+ const auto *Attr = FD->getAttr<OMPCaptureKindAttr>();
+ if (!Attr)
+ return;
+ if (!isOpenMPPrivate(
+ static_cast<OpenMPClauseKind>(Attr->getCaptureKind())) ||
+ Attr->getCaptureKind() == OMPC_map)
+ return;
+ if (FD->getType()->isReferenceType())
+ return;
+ assert(!VD->getType()->isVariablyModifiedType() &&
+ "Parameter captured by value with variably modified type");
+ EscapedParameters.insert(VD);
+ }
+ }
+ if (VD->getType()->isVariablyModifiedType())
+ EscapedVariableLengthDecls.insert(VD);
+ else
+ EscapedDecls.insert(VD);
+ }
+
+ void VisitValueDecl(const ValueDecl *VD) {
+ if (VD->getType()->isLValueReferenceType())
+ markAsEscaped(VD);
+ if (const auto *VarD = dyn_cast<VarDecl>(VD)) {
+ if (!isa<ParmVarDecl>(VarD) && VarD->hasInit()) {
+ const bool SavedAllEscaped = AllEscaped;
+ AllEscaped = VD->getType()->isLValueReferenceType();
+ Visit(VarD->getInit());
+ AllEscaped = SavedAllEscaped;
+ }
+ }
+ }
+ void VisitOpenMPCapturedStmt(const CapturedStmt *S) {
+ if (!S)
+ return;
+ for (const auto &C : S->captures()) {
+ if (C.capturesVariable() && !C.capturesVariableByCopy()) {
+ const ValueDecl *VD = C.getCapturedVar();
+ markAsEscaped(VD);
+ if (isa<OMPCapturedExprDecl>(VD))
+ VisitValueDecl(VD);
+ }
+ }
+ }
+
+ typedef std::pair<CharUnits /*Align*/, const ValueDecl *> VarsDataTy;
+ static bool stable_sort_comparator(const VarsDataTy P1, const VarsDataTy P2) {
+ return P1.first > P2.first;
+ }
+
+ void buildRecordForGlobalizedVars() {
+ assert(!GlobalizedRD &&
+ "Record for globalized variables is built already.");
+ if (EscapedDecls.empty())
+ return;
+ ASTContext &C = CGF.getContext();
+ SmallVector<VarsDataTy, 4> GlobalizedVars;
+ for (const auto *D : EscapedDecls)
+ GlobalizedVars.emplace_back(C.getDeclAlign(D), D);
+ std::stable_sort(GlobalizedVars.begin(), GlobalizedVars.end(),
+ stable_sort_comparator);
+ // Build struct _globalized_locals_ty {
+ // /* globalized vars */
+ // };
+ GlobalizedRD = C.buildImplicitRecord("_globalized_locals_ty");
+ GlobalizedRD->startDefinition();
+ for (const auto &Pair : GlobalizedVars) {
+ const ValueDecl *VD = Pair.second;
+ QualType Type = VD->getType();
+ if (Type->isLValueReferenceType())
+ Type = C.getPointerType(Type.getNonReferenceType());
+ else
+ Type = Type.getNonReferenceType();
+ SourceLocation Loc = VD->getLocation();
+ auto *Field = FieldDecl::Create(
+ C, GlobalizedRD, Loc, Loc, VD->getIdentifier(), Type,
+ C.getTrivialTypeSourceInfo(Type, SourceLocation()),
+ /*BW=*/nullptr, /*Mutable=*/false,
+ /*InitStyle=*/ICIS_NoInit);
+ Field->setAccess(AS_public);
+ GlobalizedRD->addDecl(Field);
+ if (VD->hasAttrs()) {
+ for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
+ E(VD->getAttrs().end());
+ I != E; ++I)
+ Field->addAttr(*I);
+ }
+ MappedDeclsFields.try_emplace(VD, Field);
+ }
+ GlobalizedRD->completeDefinition();
+ }
+
+public:
+ CheckVarsEscapingDeclContext(CodeGenFunction &CGF) : CGF(CGF) {}
+ virtual ~CheckVarsEscapingDeclContext() = default;
+ void VisitDeclStmt(const DeclStmt *S) {
+ if (!S)
+ return;
+ for (const auto *D : S->decls())
+ if (const auto *VD = dyn_cast_or_null<ValueDecl>(D))
+ VisitValueDecl(VD);
+ }
+ void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
+ if (!D)
+ return;
+ if (D->hasAssociatedStmt()) {
+ if (const auto *S =
+ dyn_cast_or_null<CapturedStmt>(D->getAssociatedStmt()))
+ VisitOpenMPCapturedStmt(S);
+ }
+ }
+ void VisitCapturedStmt(const CapturedStmt *S) {
+ if (!S)
+ return;
+ for (const auto &C : S->captures()) {
+ if (C.capturesVariable() && !C.capturesVariableByCopy()) {
+ const ValueDecl *VD = C.getCapturedVar();
+ markAsEscaped(VD);
+ if (isa<OMPCapturedExprDecl>(VD))
+ VisitValueDecl(VD);
+ }
+ }
+ }
+ void VisitLambdaExpr(const LambdaExpr *E) {
+ if (!E)
+ return;
+ for (const auto &C : E->captures()) {
+ if (C.capturesVariable()) {
+ if (C.getCaptureKind() == LCK_ByRef) {
+ const ValueDecl *VD = C.getCapturedVar();
+ markAsEscaped(VD);
+ if (E->isInitCapture(&C) || isa<OMPCapturedExprDecl>(VD))
+ VisitValueDecl(VD);
+ }
+ }
+ }
+ }
+ void VisitBlockExpr(const BlockExpr *E) {
+ if (!E)
+ return;
+ for (const auto &C : E->getBlockDecl()->captures()) {
+ if (C.isByRef()) {
+ const VarDecl *VD = C.getVariable();
+ markAsEscaped(VD);
+ if (isa<OMPCapturedExprDecl>(VD) || VD->isInitCapture())
+ VisitValueDecl(VD);
+ }
+ }
+ }
+ void VisitCallExpr(const CallExpr *E) {
+ if (!E)
+ return;
+ for (const Expr *Arg : E->arguments()) {
+ if (!Arg)
+ continue;
+ if (Arg->isLValue()) {
+ const bool SavedAllEscaped = AllEscaped;
+ AllEscaped = true;
+ Visit(Arg);
+ AllEscaped = SavedAllEscaped;
+ } else
+ Visit(Arg);
+ }
+ Visit(E->getCallee());
+ }
+ void VisitDeclRefExpr(const DeclRefExpr *E) {
+ if (!E)
+ return;
+ const ValueDecl *VD = E->getDecl();
+ if (AllEscaped)
+ markAsEscaped(VD);
+ if (isa<OMPCapturedExprDecl>(VD))
+ VisitValueDecl(VD);
+ else if (const auto *VarD = dyn_cast<VarDecl>(VD))
+ if (VarD->isInitCapture())
+ VisitValueDecl(VD);
+ }
+ void VisitUnaryOperator(const UnaryOperator *E) {
+ if (!E)
+ return;
+ if (E->getOpcode() == UO_AddrOf) {
+ const bool SavedAllEscaped = AllEscaped;
+ AllEscaped = true;
+ Visit(E->getSubExpr());
+ AllEscaped = SavedAllEscaped;
+ } else
+ Visit(E->getSubExpr());
+ }
+ void VisitImplicitCastExpr(const ImplicitCastExpr *E) {
+ if (!E)
+ return;
+ if (E->getCastKind() == CK_ArrayToPointerDecay) {
+ const bool SavedAllEscaped = AllEscaped;
+ AllEscaped = true;
+ Visit(E->getSubExpr());
+ AllEscaped = SavedAllEscaped;
+ } else
+ Visit(E->getSubExpr());
+ }
+ void VisitExpr(const Expr *E) {
+ if (!E)
+ return;
+ bool SavedAllEscaped = AllEscaped;
+ if (!E->isLValue())
+ AllEscaped = false;
+ for (const auto *Child : E->children())
+ if (Child)
+ Visit(Child);
+ AllEscaped = SavedAllEscaped;
+ }
+ void VisitStmt(const Stmt *S) {
+ if (!S)
+ return;
+ for (const auto *Child : S->children())
+ if (Child)
+ Visit(Child);
+ }
+
+ /// Returns the record that handles all the escaped local variables and used
+ /// instead of their original storage.
+ const RecordDecl *getGlobalizedRecord() {
+ if (!GlobalizedRD)
+ buildRecordForGlobalizedVars();
+ return GlobalizedRD;
+ }
+
+ /// Returns the field in the globalized record for the escaped variable.
+ const FieldDecl *getFieldForGlobalizedVar(const ValueDecl *VD) const {
+ assert(GlobalizedRD &&
+ "Record for globalized variables must be generated already.");
+ auto I = MappedDeclsFields.find(VD);
+ if (I == MappedDeclsFields.end())
+ return nullptr;
+ return I->getSecond();
+ }
+
+ /// Returns the list of the escaped local variables/parameters.
+ ArrayRef<const ValueDecl *> getEscapedDecls() const {
+ return EscapedDecls.getArrayRef();
+ }
+
+ /// Checks if the escaped local variable is actually a parameter passed by
+ /// value.
+ const llvm::SmallPtrSetImpl<const Decl *> &getEscapedParameters() const {
+ return EscapedParameters;
+ }
+
+ /// Returns the list of the escaped variables with the variably modified
+ /// types.
+ ArrayRef<const ValueDecl *> getEscapedVariableLengthDecls() const {
+ return EscapedVariableLengthDecls.getArrayRef();
+ }
+};
} // anonymous namespace
/// Get the GPU warp size.
@@ -336,7 +638,7 @@
Bld.CreateCondBr(IsWorker, WorkerBB, MasterCheckBB);
CGF.EmitBlock(WorkerBB);
- emitOutlinedFunctionCall(CGF, WST.Loc, WST.WorkerFn);
+ emitCall(CGF, WST.Loc, WST.WorkerFn);
CGF.EmitBranch(EST.ExitBB);
CGF.EmitBlock(MasterCheckBB);
@@ -345,6 +647,7 @@
Bld.CreateCondBr(IsMaster, MasterBB, EST.ExitBB);
CGF.EmitBlock(MasterBB);
+ // SEQUENTIAL (MASTER) REGION START
// First action in sequential region:
// Initialize the state of the OpenMP runtime library on the GPU.
// TODO: Optimize runtime initialization and pass in correct value.
@@ -352,10 +655,21 @@
Bld.getInt16(/*RequiresOMPRuntime=*/1)};
CGF.EmitRuntimeCall(
createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_init), Args);
+
+ // For data sharing, we need to initialize the stack.
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_data_sharing_init_stack));
+
+ emitGenericVarsProlog(CGF, WST.Loc);
}
void CGOpenMPRuntimeNVPTX::emitGenericEntryFooter(CodeGenFunction &CGF,
EntryFunctionState &EST) {
+ emitGenericVarsEpilog(CGF);
+ if (!CGF.HaveInsertPoint())
+ return;
+
if (!EST.ExitBB)
EST.ExitBB = CGF.createBasicBlock(".exit");
@@ -501,6 +815,11 @@
// Wait for parallel work
syncCTAThreads(CGF);
+ // For data sharing, we need to initialize the stack for workers.
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_data_sharing_init_stack));
+
Address WorkFn =
CGF.CreateDefaultAlignTempAlloca(CGF.Int8PtrTy, /*Name=*/"work_fn");
Address ExecStatus =
@@ -508,11 +827,8 @@
CGF.InitTempAlloca(ExecStatus, Bld.getInt8(/*C=*/0));
CGF.InitTempAlloca(WorkFn, llvm::Constant::getNullValue(CGF.Int8PtrTy));
- // Set up shared arguments
- Address SharedArgs =
- CGF.CreateDefaultAlignTempAlloca(CGF.Int8PtrPtrTy, "shared_args");
// TODO: Optimize runtime initialization and pass in correct value.
- llvm::Value *Args[] = {WorkFn.getPointer(), SharedArgs.getPointer(),
+ llvm::Value *Args[] = {WorkFn.getPointer(),
/*RequiresOMPRuntime=*/Bld.getInt16(1)};
llvm::Value *Ret = CGF.EmitRuntimeCall(
createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_parallel), Args);
@@ -532,9 +848,6 @@
// Signal start of parallel region.
CGF.EmitBlock(ExecuteBB);
- // Current context
- ASTContext &Ctx = CGF.getContext();
-
// Process work items: outlined parallel functions.
for (auto *W : Work) {
// Try to match this outlined function.
@@ -551,18 +864,11 @@
CGF.EmitBlock(ExecuteFNBB);
// Insert call to work function via shared wrapper. The shared
- // wrapper takes exactly three arguments:
+ // wrapper takes two arguments:
// - the parallelism level;
- // - the master thread ID;
- // - the list of references to shared arguments.
- //
- // TODO: Assert that the function is a wrapper function.s
- Address Capture = CGF.EmitLoadOfPointer(SharedArgs,
- Ctx.getPointerType(
- Ctx.getPointerType(Ctx.VoidPtrTy)).castAs<PointerType>());
- emitOutlinedFunctionCall(CGF, WST.Loc, W,
- {Bld.getInt16(/*ParallelLevel=*/0),
- getMasterThreadID(CGF), Capture.getPointer()});
+ // - the thread ID;
+ emitCall(CGF, WST.Loc, W,
+ {Bld.getInt16(/*ParallelLevel=*/0), getThreadID(CGF, WST.Loc)});
// Go to end of parallel region.
CGF.EmitBranch(TerminateBB);
@@ -630,21 +936,17 @@
}
case OMPRTL_NVPTX__kmpc_kernel_prepare_parallel: {
/// Build void __kmpc_kernel_prepare_parallel(
- /// void *outlined_function, void ***args, kmp_int32 nArgs, int16_t
- /// IsOMPRuntimeInitialized);
- llvm::Type *TypeParams[] = {CGM.Int8PtrTy,
- CGM.Int8PtrPtrTy->getPointerTo(0), CGM.Int32Ty,
- CGM.Int16Ty};
+ /// void *outlined_function, int16_t IsOMPRuntimeInitialized);
+ llvm::Type *TypeParams[] = {CGM.Int8PtrTy, CGM.Int16Ty};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_prepare_parallel");
break;
}
case OMPRTL_NVPTX__kmpc_kernel_parallel: {
- /// Build bool __kmpc_kernel_parallel(void **outlined_function, void
- /// ***args, int16_t IsOMPRuntimeInitialized);
- llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy,
- CGM.Int8PtrPtrTy->getPointerTo(0), CGM.Int16Ty};
+ /// Build bool __kmpc_kernel_parallel(void **outlined_function,
+ /// int16_t IsOMPRuntimeInitialized);
+ llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy, CGM.Int16Ty};
llvm::Type *RetTy = CGM.getTypes().ConvertType(CGM.getContext().BoolTy);
llvm::FunctionType *FnTy =
llvm::FunctionType::get(RetTy, TypeParams, /*isVarArg*/ false);
@@ -773,13 +1075,64 @@
FnTy, /*Name=*/"__kmpc_nvptx_end_reduce_nowait");
break;
}
+ case OMPRTL_NVPTX__kmpc_data_sharing_init_stack: {
+ /// Build void __kmpc_data_sharing_init_stack();
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_data_sharing_init_stack");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_data_sharing_push_stack: {
+ // Build void *__kmpc_data_sharing_push_stack(size_t size,
+ // int16_t UseSharedMemory);
+ llvm::Type *TypeParams[] = {CGM.SizeTy, CGM.Int16Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(
+ FnTy, /*Name=*/"__kmpc_data_sharing_push_stack");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_data_sharing_pop_stack: {
+ // Build void __kmpc_data_sharing_pop_stack(void *a);
+ llvm::Type *TypeParams[] = {CGM.VoidPtrTy};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy,
+ /*Name=*/"__kmpc_data_sharing_pop_stack");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_begin_sharing_variables: {
+ /// Build void __kmpc_begin_sharing_variables(void ***args,
+ /// size_t n_args);
+ llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy->getPointerTo(), CGM.SizeTy};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_begin_sharing_variables");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_end_sharing_variables: {
+ /// Build void __kmpc_end_sharing_variables();
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_sharing_variables");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_get_shared_variables: {
+ /// Build void __kmpc_get_shared_variables(void ***GlobalArgs);
+ llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy->getPointerTo()};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_get_shared_variables");
+ break;
+ }
}
return RTLFn;
}
void CGOpenMPRuntimeNVPTX::createOffloadEntry(llvm::Constant *ID,
llvm::Constant *Addr,
- uint64_t Size, int32_t) {
+ uint64_t Size, int32_t,
+ llvm::GlobalValue::LinkageTypes) {
auto *F = dyn_cast<llvm::Function>(Addr);
// TODO: Add support for global variables on the device after declare target
// support.
@@ -862,13 +1215,30 @@
llvm::Value *CGOpenMPRuntimeNVPTX::emitParallelOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
+ SourceLocation Loc = D.getLocStart();
- auto *OutlinedFun = cast<llvm::Function>(
- CGOpenMPRuntime::emitParallelOutlinedFunction(
+ // Emit target region as a standalone region.
+ class NVPTXPrePostActionTy : public PrePostActionTy {
+ SourceLocation &Loc;
+
+ public:
+ NVPTXPrePostActionTy(SourceLocation &Loc) : Loc(Loc) {}
+ void Enter(CodeGenFunction &CGF) override {
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
+ .emitGenericVarsProlog(CGF, Loc);
+ }
+ void Exit(CodeGenFunction &CGF) override {
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
+ .emitGenericVarsEpilog(CGF);
+ }
+ } Action(Loc);
+ CodeGen.setAction(Action);
+ auto *OutlinedFun =
+ cast<llvm::Function>(CGOpenMPRuntime::emitParallelOutlinedFunction(
D, ThreadIDVar, InnermostKind, CodeGen));
if (!isInSpmdExecutionMode()) {
llvm::Function *WrapperFun =
- createDataSharingWrapper(OutlinedFun, D);
+ createParallelDataSharingWrapper(OutlinedFun, D);
WrapperFunctionsMap[OutlinedFun] = WrapperFun;
}
@@ -878,7 +1248,24 @@
llvm::Value *CGOpenMPRuntimeNVPTX::emitTeamsOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
+ SourceLocation Loc = D.getLocStart();
+ // Emit target region as a standalone region.
+ class NVPTXPrePostActionTy : public PrePostActionTy {
+ SourceLocation &Loc;
+
+ public:
+ NVPTXPrePostActionTy(SourceLocation &Loc) : Loc(Loc) {}
+ void Enter(CodeGenFunction &CGF) override {
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
+ .emitGenericVarsProlog(CGF, Loc);
+ }
+ void Exit(CodeGenFunction &CGF) override {
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
+ .emitGenericVarsEpilog(CGF);
+ }
+ } Action(Loc);
+ CodeGen.setAction(Action);
llvm::Value *OutlinedFunVal = CGOpenMPRuntime::emitTeamsOutlinedFunction(
D, ThreadIDVar, InnermostKind, CodeGen);
llvm::Function *OutlinedFun = cast<llvm::Function>(OutlinedFunVal);
@@ -889,6 +1276,113 @@
return OutlinedFun;
}
+void CGOpenMPRuntimeNVPTX::emitGenericVarsProlog(CodeGenFunction &CGF,
+ SourceLocation Loc) {
+ CGBuilderTy &Bld = CGF.Builder;
+
+ const auto I = FunctionGlobalizedDecls.find(CGF.CurFn);
+ if (I == FunctionGlobalizedDecls.end())
+ return;
+ if (const RecordDecl *GlobalizedVarsRecord = I->getSecond().GlobalRecord) {
+ QualType RecTy = CGM.getContext().getRecordType(GlobalizedVarsRecord);
+
+ // Recover pointer to this function's global record. The runtime will
+ // handle the specifics of the allocation of the memory.
+ // Use actual memory size of the record including the padding
+ // for alignment purposes.
+ unsigned Alignment =
+ CGM.getContext().getTypeAlignInChars(RecTy).getQuantity();
+ unsigned GlobalRecordSize =
+ CGM.getContext().getTypeSizeInChars(RecTy).getQuantity();
+ GlobalRecordSize = llvm::alignTo(GlobalRecordSize, Alignment);
+ // TODO: allow the usage of shared memory to be controlled by
+ // the user, for now, default to global.
+ llvm::Value *GlobalRecordSizeArg[] = {
+ llvm::ConstantInt::get(CGM.SizeTy, GlobalRecordSize),
+ CGF.Builder.getInt16(/*UseSharedMemory=*/0)};
+ llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_data_sharing_push_stack),
+ GlobalRecordSizeArg);
+ llvm::Value *GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ GlobalRecValue, CGF.ConvertTypeForMem(RecTy)->getPointerTo());
+ LValue Base =
+ CGF.MakeNaturalAlignPointeeAddrLValue(GlobalRecCastAddr, RecTy);
+ I->getSecond().GlobalRecordAddr = GlobalRecValue;
+
+ // Emit the "global alloca" which is a GEP from the global declaration
+ // record using the pointer returned by the runtime.
+ for (auto &Rec : I->getSecond().LocalVarData) {
+ bool EscapedParam = I->getSecond().EscapedParameters.count(Rec.first);
+ llvm::Value *ParValue;
+ if (EscapedParam) {
+ const auto *VD = cast<VarDecl>(Rec.first);
+ LValue ParLVal =
+ CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
+ ParValue = CGF.EmitLoadOfScalar(ParLVal, Loc);
+ }
+ const FieldDecl *FD = Rec.second.first;
+ LValue VarAddr = CGF.EmitLValueForField(Base, FD);
+ Rec.second.second = VarAddr.getAddress();
+ if (EscapedParam) {
+ const auto *VD = cast<VarDecl>(Rec.first);
+ CGF.EmitStoreOfScalar(ParValue, VarAddr);
+ I->getSecond().MappedParams->setVarAddr(CGF, VD, VarAddr.getAddress());
+ }
+ }
+ }
+ for (const ValueDecl *VD : I->getSecond().EscapedVariableLengthDecls) {
+ // Recover pointer to this function's global record. The runtime will
+ // handle the specifics of the allocation of the memory.
+ // Use actual memory size of the record including the padding
+ // for alignment purposes.
+ auto &Bld = CGF.Builder;
+ llvm::Value *Size = CGF.getTypeSize(VD->getType());
+ CharUnits Align = CGM.getContext().getDeclAlign(VD);
+ Size = Bld.CreateNUWAdd(
+ Size, llvm::ConstantInt::get(CGF.SizeTy, Align.getQuantity() - 1));
+ llvm::Value *AlignVal =
+ llvm::ConstantInt::get(CGF.SizeTy, Align.getQuantity());
+ Size = Bld.CreateUDiv(Size, AlignVal);
+ Size = Bld.CreateNUWMul(Size, AlignVal);
+ // TODO: allow the usage of shared memory to be controlled by
+ // the user, for now, default to global.
+ llvm::Value *GlobalRecordSizeArg[] = {
+ Size, CGF.Builder.getInt16(/*UseSharedMemory=*/0)};
+ llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_data_sharing_push_stack),
+ GlobalRecordSizeArg);
+ llvm::Value *GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ GlobalRecValue, CGF.ConvertTypeForMem(VD->getType())->getPointerTo());
+ LValue Base = CGF.MakeAddrLValue(GlobalRecCastAddr, VD->getType(),
+ CGM.getContext().getDeclAlign(VD),
+ AlignmentSource::Decl);
+ I->getSecond().MappedParams->setVarAddr(CGF, cast<VarDecl>(VD),
+ Base.getAddress());
+ I->getSecond().EscapedVariableLengthDeclsAddrs.emplace_back(GlobalRecValue);
+ }
+ I->getSecond().MappedParams->apply(CGF);
+}
+
+void CGOpenMPRuntimeNVPTX::emitGenericVarsEpilog(CodeGenFunction &CGF) {
+ const auto I = FunctionGlobalizedDecls.find(CGF.CurFn);
+ if (I != FunctionGlobalizedDecls.end()) {
+ I->getSecond().MappedParams->restore(CGF);
+ if (!CGF.HaveInsertPoint())
+ return;
+ for (llvm::Value *Addr :
+ llvm::reverse(I->getSecond().EscapedVariableLengthDeclsAddrs)) {
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_data_sharing_pop_stack),
+ Addr);
+ }
+ if (I->getSecond().GlobalRecordAddr) {
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_data_sharing_pop_stack),
+ I->getSecond().GlobalRecordAddr);
+ }
+ }
+}
+
void CGOpenMPRuntimeNVPTX::emitTeamsCall(CodeGenFunction &CGF,
const OMPExecutableDirective &D,
SourceLocation Loc,
@@ -897,12 +1391,12 @@
if (!CGF.HaveInsertPoint())
return;
- Address ZeroAddr =
- CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
- /*Name*/ ".zero.addr");
+ Address ZeroAddr = CGF.CreateMemTemp(
+ CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1),
+ /*Name*/ ".zero.addr");
CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
- OutlinedFnArgs.push_back(ZeroAddr.getPointer());
+ OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).getPointer());
OutlinedFnArgs.push_back(ZeroAddr.getPointer());
OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
@@ -925,55 +1419,60 @@
ArrayRef<llvm::Value *> CapturedVars, const Expr *IfCond) {
llvm::Function *Fn = cast<llvm::Function>(OutlinedFn);
llvm::Function *WFn = WrapperFunctionsMap[Fn];
+
assert(WFn && "Wrapper function does not exist!");
// Force inline this outlined function at its call site.
Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
- auto &&L0ParallelGen = [this, WFn, &CapturedVars](CodeGenFunction &CGF,
+ auto &&L0ParallelGen = [this, WFn, CapturedVars](CodeGenFunction &CGF,
PrePostActionTy &) {
CGBuilderTy &Bld = CGF.Builder;
llvm::Value *ID = Bld.CreateBitOrPointerCast(WFn, CGM.Int8PtrTy);
+ // Prepare for parallel region. Indicate the outlined function.
+ llvm::Value *Args[] = {ID, /*RequiresOMPRuntime=*/Bld.getInt16(1)};
+ CGF.EmitRuntimeCall(createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_kernel_prepare_parallel),
+ Args);
+
+ // Create a private scope that will globalize the arguments
+ // passed from the outside of the target region.
+ CodeGenFunction::OMPPrivateScope PrivateArgScope(CGF);
+
+ // There's somehting to share.
if (!CapturedVars.empty()) {
- // There's somehting to share, add the attribute
- CGF.CurFn->addFnAttr("has-nvptx-shared-depot");
// Prepare for parallel region. Indicate the outlined function.
Address SharedArgs =
- CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy,
- "shared_args");
+ CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy, "shared_arg_refs");
llvm::Value *SharedArgsPtr = SharedArgs.getPointer();
- // TODO: Optimize runtime initialization and pass in correct value.
- llvm::Value *Args[] = {ID, SharedArgsPtr,
- Bld.getInt32(CapturedVars.size()),
- /*RequiresOMPRuntime=*/Bld.getInt16(1)};
- CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_prepare_parallel),
- Args);
+ llvm::Value *DataSharingArgs[] = {
+ SharedArgsPtr,
+ llvm::ConstantInt::get(CGM.SizeTy, CapturedVars.size())};
+ CGF.EmitRuntimeCall(createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_begin_sharing_variables),
+ DataSharingArgs);
+ // Store variable address in a list of references to pass to workers.
unsigned Idx = 0;
ASTContext &Ctx = CGF.getContext();
+ Address SharedArgListAddress = CGF.EmitLoadOfPointer(SharedArgs,
+ Ctx.getPointerType(Ctx.getPointerType(Ctx.VoidPtrTy))
+ .castAs<PointerType>());
for (llvm::Value *V : CapturedVars) {
Address Dst = Bld.CreateConstInBoundsGEP(
- CGF.EmitLoadOfPointer(SharedArgs,
- Ctx.getPointerType(
- Ctx.getPointerType(Ctx.VoidPtrTy)).castAs<PointerType>()),
- Idx, CGF.getPointerSize());
- llvm::Value *PtrV = Bld.CreateBitCast(V, CGF.VoidPtrTy);
+ SharedArgListAddress, Idx, CGF.getPointerSize());
+ llvm::Value * PtrV;
+ if (V->getType()->isIntegerTy())
+ PtrV = Bld.CreateIntToPtr(V, CGF.VoidPtrTy);
+ else
+ PtrV = Bld.CreatePointerBitCastOrAddrSpaceCast(V, CGF.VoidPtrTy);
CGF.EmitStoreOfScalar(PtrV, Dst, /*Volatile=*/false,
- Ctx.getPointerType(Ctx.VoidPtrTy));
- Idx++;
+ Ctx.getPointerType(Ctx.VoidPtrTy));
+ ++Idx;
}
- } else {
- // TODO: Optimize runtime initialization and pass in correct value.
- llvm::Value *Args[] = {
- ID, llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy->getPointerTo(0)),
- /*nArgs=*/Bld.getInt32(0), /*RequiresOMPRuntime=*/Bld.getInt16(1)};
- CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_prepare_parallel),
- Args);
}
// Activate workers. This barrier is used by the master to signal
@@ -988,6 +1487,10 @@
// The master waits at this barrier until all workers are done.
syncCTAThreads(CGF);
+ if (!CapturedVars.empty())
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_end_sharing_variables));
+
// Remember for post-processing in worker loop.
Work.emplace_back(WFn);
};
@@ -996,17 +1499,20 @@
auto *ThreadID = getThreadID(CGF, Loc);
llvm::Value *Args[] = {RTLoc, ThreadID};
- auto &&SeqGen = [this, Fn, &CapturedVars, &Args, Loc](CodeGenFunction &CGF,
- PrePostActionTy &) {
- auto &&CodeGen = [this, Fn, &CapturedVars, Loc](CodeGenFunction &CGF,
- PrePostActionTy &Action) {
+ auto &&SeqGen = [this, Fn, CapturedVars, &Args, Loc](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ auto &&CodeGen = [this, Fn, CapturedVars, Loc](CodeGenFunction &CGF,
+ PrePostActionTy &Action) {
Action.Enter(CGF);
llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
- OutlinedFnArgs.push_back(
- llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo()));
- OutlinedFnArgs.push_back(
- llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo()));
+ Address ZeroAddr =
+ CGF.CreateMemTemp(CGF.getContext().getIntTypeForBitwidth(
+ /*DestWidth=*/32, /*Signed=*/1),
+ ".zero.addr");
+ CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
+ OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).getPointer());
+ OutlinedFnArgs.push_back(ZeroAddr.getPointer());
OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
emitOutlinedFunctionCall(CGF, Loc, Fn, OutlinedFnArgs);
};
@@ -1044,56 +1550,60 @@
CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1),
".zero.addr");
CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
- OutlinedFnArgs.push_back(ZeroAddr.getPointer());
+ OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).getPointer());
OutlinedFnArgs.push_back(ZeroAddr.getPointer());
OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
}
/// Cast value to the specified type.
-static llvm::Value *
-castValueToType(CodeGenFunction &CGF, llvm::Value *Val, llvm::Type *CastTy,
- llvm::Optional<bool> IsSigned = llvm::None) {
- if (Val->getType() == CastTy)
+static llvm::Value *castValueToType(CodeGenFunction &CGF, llvm::Value *Val,
+ QualType ValTy, QualType CastTy,
+ SourceLocation Loc) {
+ assert(!CGF.getContext().getTypeSizeInChars(CastTy).isZero() &&
+ "Cast type must sized.");
+ assert(!CGF.getContext().getTypeSizeInChars(ValTy).isZero() &&
+ "Val type must sized.");
+ llvm::Type *LLVMCastTy = CGF.ConvertTypeForMem(CastTy);
+ if (ValTy == CastTy)
return Val;
- if (Val->getType()->getPrimitiveSizeInBits() > 0 &&
- CastTy->getPrimitiveSizeInBits() > 0 &&
- Val->getType()->getPrimitiveSizeInBits() ==
- CastTy->getPrimitiveSizeInBits())
- return CGF.Builder.CreateBitCast(Val, CastTy);
- if (IsSigned.hasValue() && CastTy->isIntegerTy() &&
- Val->getType()->isIntegerTy())
- return CGF.Builder.CreateIntCast(Val, CastTy, *IsSigned);
- Address CastItem = CGF.CreateTempAlloca(
- CastTy,
- CharUnits::fromQuantity(
- CGF.CGM.getDataLayout().getPrefTypeAlignment(Val->getType())));
+ if (CGF.getContext().getTypeSizeInChars(ValTy) ==
+ CGF.getContext().getTypeSizeInChars(CastTy))
+ return CGF.Builder.CreateBitCast(Val, LLVMCastTy);
+ if (CastTy->isIntegerType() && ValTy->isIntegerType())
+ return CGF.Builder.CreateIntCast(Val, LLVMCastTy,
+ CastTy->hasSignedIntegerRepresentation());
+ Address CastItem = CGF.CreateMemTemp(CastTy);
Address ValCastItem = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
CastItem, Val->getType()->getPointerTo(CastItem.getAddressSpace()));
- CGF.Builder.CreateStore(Val, ValCastItem);
- return CGF.Builder.CreateLoad(CastItem);
+ CGF.EmitStoreOfScalar(Val, ValCastItem, /*Volatile=*/false, ValTy);
+ return CGF.EmitLoadOfScalar(CastItem, /*Volatile=*/false, CastTy, Loc);
}
/// This function creates calls to one of two shuffle functions to copy
/// variables between lanes in a warp.
static llvm::Value *createRuntimeShuffleFunction(CodeGenFunction &CGF,
llvm::Value *Elem,
- llvm::Value *Offset) {
+ QualType ElemType,
+ llvm::Value *Offset,
+ SourceLocation Loc) {
auto &CGM = CGF.CGM;
auto &Bld = CGF.Builder;
CGOpenMPRuntimeNVPTX &RT =
*(static_cast<CGOpenMPRuntimeNVPTX *>(&CGM.getOpenMPRuntime()));
- unsigned Size = CGM.getDataLayout().getTypeStoreSize(Elem->getType());
- assert(Size <= 8 && "Unsupported bitwidth in shuffle instruction.");
+ CharUnits Size = CGF.getContext().getTypeSizeInChars(ElemType);
+ assert(Size.getQuantity() <= 8 &&
+ "Unsupported bitwidth in shuffle instruction.");
- OpenMPRTLFunctionNVPTX ShuffleFn = Size <= 4
+ OpenMPRTLFunctionNVPTX ShuffleFn = Size.getQuantity() <= 4
? OMPRTL_NVPTX__kmpc_shuffle_int32
: OMPRTL_NVPTX__kmpc_shuffle_int64;
// Cast all types to 32- or 64-bit values before calling shuffle routines.
- llvm::Type *CastTy = Size <= 4 ? CGM.Int32Ty : CGM.Int64Ty;
- llvm::Value *ElemCast = castValueToType(CGF, Elem, CastTy, /*isSigned=*/true);
+ QualType CastTy = CGF.getContext().getIntTypeForBitwidth(
+ Size.getQuantity() <= 4 ? 32 : 64, /*Signed=*/1);
+ llvm::Value *ElemCast = castValueToType(CGF, Elem, ElemType, CastTy, Loc);
auto *WarpSize =
Bld.CreateIntCast(getNVPTXWarpSize(CGF), CGM.Int16Ty, /*isSigned=*/true);
@@ -1101,7 +1611,7 @@
CGF.EmitRuntimeCall(RT.createNVPTXRuntimeFunction(ShuffleFn),
{ElemCast, Offset, WarpSize});
- return castValueToType(CGF, ShuffledVal, Elem->getType(), /*isSigned=*/true);
+ return castValueToType(CGF, ShuffledVal, CastTy, ElemType, Loc);
}
namespace {
@@ -1255,8 +1765,11 @@
// Now that all active lanes have read the element in the
// Reduce list, shuffle over the value from the remote lane.
- if (ShuffleInElement)
- Elem = createRuntimeShuffleFunction(CGF, Elem, RemoteLaneOffset);
+ if (ShuffleInElement) {
+ Elem =
+ createRuntimeShuffleFunction(CGF, Elem, Private->getType(),
+ RemoteLaneOffset, Private->getExprLoc());
+ }
DestElementAddr = Bld.CreateElementBitCast(DestElementAddr,
SrcElementAddr.getElementType());
@@ -2401,8 +2914,8 @@
continue;
}
llvm::Value *TargetArg = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- NativeArg, NativeArg->getType()->getPointerElementType()->getPointerTo(
- /*AddrSpace=*/0));
+ NativeArg,
+ NativeArg->getType()->getPointerElementType()->getPointerTo());
TargetArgs.emplace_back(
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TargetArg, TargetType));
}
@@ -2413,10 +2926,10 @@
/// and controls the arguments which are passed to this function.
/// The wrapper ensures that the outlined function is called
/// with the correct arguments when data is shared.
-llvm::Function *CGOpenMPRuntimeNVPTX::createDataSharingWrapper(
+llvm::Function *CGOpenMPRuntimeNVPTX::createParallelDataSharingWrapper(
llvm::Function *OutlinedParallelFn, const OMPExecutableDirective &D) {
ASTContext &Ctx = CGM.getContext();
- const CapturedStmt &CS = *D.getCapturedStmt(OMPD_parallel);
+ const auto &CS = *D.getCapturedStmt(OMPD_parallel);
// Create a function that takes as argument the source thread.
FunctionArgList WrapperArgs;
@@ -2424,20 +2937,14 @@
Ctx.getIntTypeForBitwidth(/*DestWidth=*/16, /*Signed=*/false);
QualType Int32QTy =
Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false);
- QualType Int32PtrQTy = Ctx.getPointerType(Int32QTy);
- QualType VoidPtrPtrQTy = Ctx.getPointerType(Ctx.VoidPtrTy);
ImplicitParamDecl ParallelLevelArg(Ctx, /*DC=*/nullptr, D.getLocStart(),
/*Id=*/nullptr, Int16QTy,
ImplicitParamDecl::Other);
ImplicitParamDecl WrapperArg(Ctx, /*DC=*/nullptr, D.getLocStart(),
/*Id=*/nullptr, Int32QTy,
ImplicitParamDecl::Other);
- ImplicitParamDecl SharedArgsList(Ctx, /*DC=*/nullptr, D.getLocStart(),
- /*Id=*/nullptr, VoidPtrPtrQTy,
- ImplicitParamDecl::Other);
WrapperArgs.emplace_back(&ParallelLevelArg);
WrapperArgs.emplace_back(&WrapperArg);
- WrapperArgs.emplace_back(&SharedArgsList);
auto &CGFI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, WrapperArgs);
@@ -2455,51 +2962,167 @@
const auto *RD = CS.getCapturedRecordDecl();
auto CurField = RD->field_begin();
+ Address ZeroAddr = CGF.CreateMemTemp(
+ CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1),
+ /*Name*/ ".zero.addr");
+ CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
// Get the array of arguments.
SmallVector<llvm::Value *, 8> Args;
- // TODO: suppport SIMD and pass actual values
- Args.emplace_back(llvm::ConstantPointerNull::get(
- CGM.Int32Ty->getPointerTo()));
- Args.emplace_back(llvm::ConstantPointerNull::get(
- CGM.Int32Ty->getPointerTo()));
+ Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).getPointer());
+ Args.emplace_back(ZeroAddr.getPointer());
CGBuilderTy &Bld = CGF.Builder;
auto CI = CS.capture_begin();
- // Load the start of the array
- auto SharedArgs =
- CGF.EmitLoadOfPointer(CGF.GetAddrOfLocalVar(&SharedArgsList),
- VoidPtrPtrQTy->castAs<PointerType>());
+ // Use global memory for data sharing.
+ // Handle passing of global args to workers.
+ Address GlobalArgs =
+ CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy, "global_args");
+ llvm::Value *GlobalArgsPtr = GlobalArgs.getPointer();
+ llvm::Value *DataSharingArgs[] = {GlobalArgsPtr};
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_get_shared_variables),
+ DataSharingArgs);
- // For each captured variable
- for (unsigned I = 0; I < CS.capture_size(); ++I, ++CI, ++CurField) {
- // Name of captured variable
- StringRef Name;
- if (CI->capturesThis())
- Name = "this";
- else
- Name = CI->getCapturedVar()->getName();
-
- // We retrieve the CLANG type of the argument. We use it to create
- // an alloca which will give us the LLVM type.
- QualType ElemTy = CurField->getType();
- // If this is a capture by copy the element type has to be the pointer to
- // the data.
- if (CI->capturesVariableByCopy())
- ElemTy = Ctx.getPointerType(ElemTy);
-
- // Get shared address of the captured variable.
- Address ArgAddress = Bld.CreateConstInBoundsGEP(
- SharedArgs, I, CGF.getPointerSize());
- Address TypedArgAddress = Bld.CreateBitCast(
- ArgAddress, CGF.ConvertTypeForMem(Ctx.getPointerType(ElemTy)));
- llvm::Value *Arg = CGF.EmitLoadOfScalar(TypedArgAddress,
- /*Volatile=*/false, Int32PtrQTy, SourceLocation());
- Args.emplace_back(Arg);
+ // Retrieve the shared variables from the list of references returned
+ // by the runtime. Pass the variables to the outlined function.
+ Address SharedArgListAddress = Address::invalid();
+ if (CS.capture_size() > 0 ||
+ isOpenMPLoopBoundSharingDirective(D.getDirectiveKind())) {
+ SharedArgListAddress = CGF.EmitLoadOfPointer(
+ GlobalArgs, CGF.getContext()
+ .getPointerType(CGF.getContext().getPointerType(
+ CGF.getContext().VoidPtrTy))
+ .castAs<PointerType>());
+ }
+ unsigned Idx = 0;
+ if (isOpenMPLoopBoundSharingDirective(D.getDirectiveKind())) {
+ Address Src = Bld.CreateConstInBoundsGEP(SharedArgListAddress, Idx,
+ CGF.getPointerSize());
+ Address TypedAddress = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ Src, CGF.SizeTy->getPointerTo());
+ llvm::Value *LB = CGF.EmitLoadOfScalar(
+ TypedAddress,
+ /*Volatile=*/false,
+ CGF.getContext().getPointerType(CGF.getContext().getSizeType()),
+ cast<OMPLoopDirective>(D).getLowerBoundVariable()->getExprLoc());
+ Args.emplace_back(LB);
+ ++Idx;
+ Src = Bld.CreateConstInBoundsGEP(SharedArgListAddress, Idx,
+ CGF.getPointerSize());
+ TypedAddress = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ Src, CGF.SizeTy->getPointerTo());
+ llvm::Value *UB = CGF.EmitLoadOfScalar(
+ TypedAddress,
+ /*Volatile=*/false,
+ CGF.getContext().getPointerType(CGF.getContext().getSizeType()),
+ cast<OMPLoopDirective>(D).getUpperBoundVariable()->getExprLoc());
+ Args.emplace_back(UB);
+ ++Idx;
+ }
+ if (CS.capture_size() > 0) {
+ ASTContext &CGFContext = CGF.getContext();
+ for (unsigned I = 0, E = CS.capture_size(); I < E; ++I, ++CI, ++CurField) {
+ QualType ElemTy = CurField->getType();
+ Address Src = Bld.CreateConstInBoundsGEP(SharedArgListAddress, I + Idx,
+ CGF.getPointerSize());
+ Address TypedAddress = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ Src, CGF.ConvertTypeForMem(CGFContext.getPointerType(ElemTy)));
+ llvm::Value *Arg = CGF.EmitLoadOfScalar(TypedAddress,
+ /*Volatile=*/false,
+ CGFContext.getPointerType(ElemTy),
+ CI->getLocation());
+ if (CI->capturesVariableByCopy()) {
+ Arg = castValueToType(CGF, Arg, ElemTy, CGFContext.getUIntPtrType(),
+ CI->getLocation());
+ }
+ Args.emplace_back(Arg);
+ }
}
emitOutlinedFunctionCall(CGF, D.getLocStart(), OutlinedParallelFn, Args);
CGF.FinishFunction();
return Fn;
}
+
+void CGOpenMPRuntimeNVPTX::emitFunctionProlog(CodeGenFunction &CGF,
+ const Decl *D) {
+ assert(D && "Expected function or captured|block decl.");
+ assert(FunctionGlobalizedDecls.count(CGF.CurFn) == 0 &&
+ "Function is registered already.");
+ const Stmt *Body = nullptr;
+ bool NeedToDelayGlobalization = false;
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ Body = FD->getBody();
+ } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
+ Body = BD->getBody();
+ } else if (const auto *CD = dyn_cast<CapturedDecl>(D)) {
+ Body = CD->getBody();
+ NeedToDelayGlobalization = CGF.CapturedStmtInfo->getKind() == CR_OpenMP;
+ }
+ if (!Body)
+ return;
+ CheckVarsEscapingDeclContext VarChecker(CGF);
+ VarChecker.Visit(Body);
+ const RecordDecl *GlobalizedVarsRecord = VarChecker.getGlobalizedRecord();
+ ArrayRef<const ValueDecl *> EscapedVariableLengthDecls =
+ VarChecker.getEscapedVariableLengthDecls();
+ if (!GlobalizedVarsRecord && EscapedVariableLengthDecls.empty())
+ return;
+ auto I = FunctionGlobalizedDecls.try_emplace(CGF.CurFn).first;
+ I->getSecond().MappedParams =
+ llvm::make_unique<CodeGenFunction::OMPMapVars>();
+ I->getSecond().GlobalRecord = GlobalizedVarsRecord;
+ I->getSecond().EscapedParameters.insert(
+ VarChecker.getEscapedParameters().begin(),
+ VarChecker.getEscapedParameters().end());
+ I->getSecond().EscapedVariableLengthDecls.append(
+ EscapedVariableLengthDecls.begin(), EscapedVariableLengthDecls.end());
+ DeclToAddrMapTy &Data = I->getSecond().LocalVarData;
+ for (const ValueDecl *VD : VarChecker.getEscapedDecls()) {
+ assert(VD->isCanonicalDecl() && "Expected canonical declaration");
+ const FieldDecl *FD = VarChecker.getFieldForGlobalizedVar(VD);
+ Data.insert(std::make_pair(VD, std::make_pair(FD, Address::invalid())));
+ }
+ if (!NeedToDelayGlobalization) {
+ emitGenericVarsProlog(CGF, D->getLocStart());
+ struct GlobalizationScope final : EHScopeStack::Cleanup {
+ GlobalizationScope() = default;
+
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
+ .emitGenericVarsEpilog(CGF);
+ }
+ };
+ CGF.EHStack.pushCleanup<GlobalizationScope>(NormalAndEHCleanup);
+ }
+}
+
+Address CGOpenMPRuntimeNVPTX::getAddressOfLocalVariable(CodeGenFunction &CGF,
+ const VarDecl *VD) {
+ VD = VD->getCanonicalDecl();
+ auto I = FunctionGlobalizedDecls.find(CGF.CurFn);
+ if (I == FunctionGlobalizedDecls.end())
+ return Address::invalid();
+ auto VDI = I->getSecond().LocalVarData.find(VD);
+ if (VDI != I->getSecond().LocalVarData.end())
+ return VDI->second.second;
+ if (VD->hasAttrs()) {
+ for (specific_attr_iterator<OMPReferencedVarAttr> IT(VD->attr_begin()),
+ E(VD->attr_end());
+ IT != E; ++IT) {
+ auto VDI = I->getSecond().LocalVarData.find(
+ cast<VarDecl>(cast<DeclRefExpr>(IT->getRef())->getDecl())
+ ->getCanonicalDecl());
+ if (VDI != I->getSecond().LocalVarData.end())
+ return VDI->second.second;
+ }
+ }
+ return Address::invalid();
+}
+
+void CGOpenMPRuntimeNVPTX::functionFinished(CodeGenFunction &CGF) {
+ FunctionGlobalizedDecls.erase(CGF.CurFn);
+ CGOpenMPRuntime::functionFinished(CGF);
+}
diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.h b/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
index 6ee2b7a..fdb9d17 100644
--- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
+++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
@@ -61,6 +61,12 @@
/// function.
void emitGenericEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST);
+ /// Helper for generic variables globalization prolog.
+ void emitGenericVarsProlog(CodeGenFunction &CGF, SourceLocation Loc);
+
+ /// Helper for generic variables globalization epilog.
+ void emitGenericVarsEpilog(CodeGenFunction &CGF);
+
/// \brief Helper for Spmd mode target directive's entry function.
void emitSpmdEntryHeader(CodeGenFunction &CGF, EntryFunctionState &EST,
const OMPExecutableDirective &D);
@@ -75,7 +81,8 @@
/// \brief Creates offloading entry for the provided entry ID \a ID,
/// address \a Addr, size \a Size, and flags \a Flags.
void createOffloadEntry(llvm::Constant *ID, llvm::Constant *Addr,
- uint64_t Size, int32_t Flags = 0) override;
+ uint64_t Size, int32_t Flags,
+ llvm::GlobalValue::LinkageTypes Linkage) override;
/// \brief Emit outlined function specialized for the Fork-Join
/// programming model for applicable target directives on the NVPTX device.
@@ -289,6 +296,14 @@
CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn,
ArrayRef<llvm::Value *> Args = llvm::None) const override;
+ /// Emits OpenMP-specific function prolog.
+ /// Required for device constructs.
+ void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) override;
+
+ /// Gets the OpenMP-specific address of the local variable.
+ Address getAddressOfLocalVariable(CodeGenFunction &CGF,
+ const VarDecl *VD) override;
+
/// Target codegen is specialized based on two programming models: the
/// 'generic' fork-join model of OpenMP, and a more GPU efficient 'spmd'
/// model for constructs like 'target parallel' that support it.
@@ -300,6 +315,10 @@
Unknown,
};
+ /// Cleans up references to the objects in finished function.
+ ///
+ void functionFinished(CodeGenFunction &CGF) override;
+
private:
// Track the execution mode when codegening directives within a target
// region. The appropriate mode (generic/spmd) is set on entry to the
@@ -314,9 +333,26 @@
/// and controls the parameters which are passed to this function.
/// The wrapper ensures that the outlined function is called
/// with the correct arguments when data is shared.
- llvm::Function *
- createDataSharingWrapper(llvm::Function *OutlinedParallelFn,
- const OMPExecutableDirective &D);
+ llvm::Function *createParallelDataSharingWrapper(
+ llvm::Function *OutlinedParallelFn, const OMPExecutableDirective &D);
+
+ /// The map of local variables to their addresses in the global memory.
+ using DeclToAddrMapTy = llvm::MapVector<const Decl *,
+ std::pair<const FieldDecl *, Address>>;
+ /// Set of the parameters passed by value escaping OpenMP context.
+ using EscapedParamsTy = llvm::SmallPtrSet<const Decl *, 4>;
+ struct FunctionData {
+ DeclToAddrMapTy LocalVarData;
+ EscapedParamsTy EscapedParameters;
+ llvm::SmallVector<const ValueDecl*, 4> EscapedVariableLengthDecls;
+ llvm::SmallVector<llvm::Value *, 4> EscapedVariableLengthDeclsAddrs;
+ const RecordDecl *GlobalRecord = nullptr;
+ llvm::Value *GlobalRecordAddr = nullptr;
+ std::unique_ptr<CodeGenFunction::OMPMapVars> MappedParams;
+ };
+ /// Maps the function to the list of the globalized variables with their
+ /// addresses.
+ llvm::SmallDenseMap<llvm::Function *, FunctionData> FunctionGlobalizedDecls;
};
} // CodeGen namespace.
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 86c0964..b89d9f0 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -608,7 +608,7 @@
EmitStmt(S.getInit());
if (S.getConditionVariable())
- EmitAutoVarDecl(*S.getConditionVariable());
+ EmitDecl(*S.getConditionVariable());
// If the condition constant folds and can be elided, try to avoid emitting
// the condition and the dead arm of the if/else.
@@ -705,7 +705,7 @@
RunCleanupsScope ConditionScope(*this);
if (S.getConditionVariable())
- EmitAutoVarDecl(*S.getConditionVariable());
+ EmitDecl(*S.getConditionVariable());
// Evaluate the conditional in the while header. C99 6.8.5.1: The
// evaluation of the controlling expression takes place before each
@@ -865,7 +865,7 @@
// If the for statement has a condition scope, emit the local variable
// declaration.
if (S.getConditionVariable()) {
- EmitAutoVarDecl(*S.getConditionVariable());
+ EmitDecl(*S.getConditionVariable());
}
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
@@ -1574,7 +1574,7 @@
// Emit the condition variable if needed inside the entire cleanup scope
// used by this special case for constant folded switches.
if (S.getConditionVariable())
- EmitAutoVarDecl(*S.getConditionVariable());
+ EmitDecl(*S.getConditionVariable());
// At this point, we are no longer "within" a switch instance, so
// we can temporarily enforce this to ensure that any embedded case
@@ -1603,7 +1603,7 @@
EmitStmt(S.getInit());
if (S.getConditionVariable())
- EmitAutoVarDecl(*S.getConditionVariable());
+ EmitDecl(*S.getConditionVariable());
llvm::Value *CondV = EmitScalarExpr(S.getCond());
// Create basic block to hold stuff that comes after switch
@@ -1926,7 +1926,7 @@
// Simplify the output constraint.
std::string OutputConstraint(S.getOutputConstraint(i));
OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1,
- getTarget());
+ getTarget(), &OutputConstraintInfos);
const Expr *OutExpr = S.getOutputExpr(i);
OutExpr = OutExpr->IgnoreParenNoopCasts(getContext());
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index d9b4fa8..1246e5a 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -120,18 +120,18 @@
/// of used expression from loop statement.
class OMPLoopScope : public CodeGenFunction::RunCleanupsScope {
void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopDirective &S) {
- CodeGenFunction::OMPPrivateScope PreCondScope(CGF);
+ CodeGenFunction::OMPMapVars PreCondVars;
for (auto *E : S.counters()) {
const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- (void)PreCondScope.addPrivate(VD, [&CGF, VD]() {
- return CGF.CreateMemTemp(VD->getType().getNonReferenceType());
- });
+ (void)PreCondVars.setVarAddr(
+ CGF, VD, CGF.CreateMemTemp(VD->getType().getNonReferenceType()));
}
- (void)PreCondScope.Privatize();
+ (void)PreCondVars.apply(CGF);
if (auto *PreInits = cast_or_null<DeclStmt>(S.getPreInits())) {
for (const auto *I : PreInits->decls())
CGF.EmitVarDecl(cast<VarDecl>(*I));
}
+ PreCondVars.restore(CGF);
}
public:
@@ -585,6 +585,7 @@
/*RegisterCastedArgsOnly=*/true,
CapturedStmtInfo->getHelperName());
CodeGenFunction WrapperCGF(CGM, /*suppressNewContext=*/true);
+ WrapperCGF.CapturedStmtInfo = CapturedStmtInfo;
Args.clear();
LocalAddrs.clear();
VLASizes.clear();
@@ -1261,7 +1262,8 @@
void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
// Emit parallel region as a standalone region.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPPrivateScope PrivateScope(CGF);
bool Copyins = CGF.EmitOMPCopyinClause(S);
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
@@ -1475,25 +1477,25 @@
for (auto *E : S.counters()) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
- (void)LoopScope.addPrivate(VD, [&]() -> Address {
- // Emit var without initialization.
- if (!LocalDeclMap.count(PrivateVD)) {
- auto VarEmission = EmitAutoVarAlloca(*PrivateVD);
- EmitAutoVarCleanups(VarEmission);
- }
- DeclRefExpr DRE(const_cast<VarDecl *>(PrivateVD),
- /*RefersToEnclosingVariableOrCapture=*/false,
- (*I)->getType(), VK_LValue, (*I)->getExprLoc());
- return EmitLValue(&DRE).getAddress();
+ // Emit var without initialization.
+ auto VarEmission = EmitAutoVarAlloca(*PrivateVD);
+ EmitAutoVarCleanups(VarEmission);
+ LocalDeclMap.erase(PrivateVD);
+ (void)LoopScope.addPrivate(VD, [&VarEmission]() {
+ return VarEmission.getAllocatedAddress();
});
if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) ||
VD->hasGlobalStorage()) {
- (void)LoopScope.addPrivate(PrivateVD, [&]() -> Address {
+ (void)LoopScope.addPrivate(PrivateVD, [this, VD, E]() {
DeclRefExpr DRE(const_cast<VarDecl *>(VD),
LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD),
E->getType(), VK_LValue, E->getExprLoc());
return EmitLValue(&DRE).getAddress();
});
+ } else {
+ (void)LoopScope.addPrivate(PrivateVD, [&VarEmission]() {
+ return VarEmission.getAllocatedAddress();
+ });
}
++I;
}
@@ -1611,9 +1613,9 @@
}
}
Address OrigAddr = Address::invalid();
- if (CED)
+ if (CED) {
OrigAddr = EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress();
- else {
+ } else {
DeclRefExpr DRE(const_cast<VarDecl *>(PrivateVD),
/*RefersToEnclosingVariableOrCapture=*/false,
(*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc());
@@ -2099,7 +2101,8 @@
const OMPLoopDirective &S,
CodeGenFunction::JumpDest LoopExit) {
auto &&CGInlinedWorksharingLoop = [&S](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
bool HasCancel = false;
if (!isOpenMPSimdDirective(S.getDirectiveKind())) {
if (const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
@@ -2681,7 +2684,8 @@
const OMPParallelForDirective &S) {
// Emit directive as a combined directive that consists of two implicit
// directives: 'parallel' with 'for' directive.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPCancelStackRAII CancelRegion(CGF, OMPD_parallel_for, S.hasCancel());
CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
emitDispatchForLoopBounds);
@@ -2694,7 +2698,8 @@
const OMPParallelForSimdDirective &S) {
// Emit directive as a combined directive that consists of two implicit
// directives: 'parallel' with 'for' directive.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
emitDispatchForLoopBounds);
};
@@ -2706,7 +2711,8 @@
const OMPParallelSectionsDirective &S) {
// Emit directive as a combined directive that consists of two implicit
// directives: 'parallel' with 'sections' directive.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
CGF.EmitSections(S);
};
emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen,
@@ -2886,6 +2892,11 @@
for (unsigned Cnt = 0, E = Data.ReductionVars.size(); Cnt < E; ++Cnt) {
RedCG.emitSharedLValue(CGF, Cnt);
RedCG.emitAggregateType(CGF, Cnt);
+ // FIXME: This must removed once the runtime library is fixed.
+ // Emit required threadprivate variables for
+ // initilizer/combiner/finalizer.
+ CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getLocStart(),
+ RedCG, Cnt);
Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
CGF, S.getLocStart(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
Replacement =
@@ -2898,11 +2909,6 @@
Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
Scope.addPrivate(RedCG.getBaseDecl(Cnt),
[Replacement]() { return Replacement; });
- // FIXME: This must removed once the runtime library is fixed.
- // Emit required threadprivate variables for
- // initilizer/combiner/finalizer.
- CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getLocStart(),
- RedCG, Cnt);
}
}
// Privatize all private variables except for in_reduction items.
@@ -2935,6 +2941,11 @@
RedCG.emitAggregateType(CGF, Cnt);
// The taskgroup descriptor variable is always implicit firstprivate and
// privatized already during procoessing of the firstprivates.
+ // FIXME: This must removed once the runtime library is fixed.
+ // Emit required threadprivate variables for
+ // initilizer/combiner/finalizer.
+ CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getLocStart(),
+ RedCG, Cnt);
llvm::Value *ReductionsPtr =
CGF.EmitLoadOfScalar(CGF.EmitLValue(TaskgroupDescriptors[Cnt]),
TaskgroupDescriptors[Cnt]->getExprLoc());
@@ -2949,11 +2960,6 @@
Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
InRedScope.addPrivate(RedCG.getBaseDecl(Cnt),
[Replacement]() { return Replacement; });
- // FIXME: This must removed once the runtime library is fixed.
- // Emit required threadprivate variables for
- // initilizer/combiner/finalizer.
- CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getLocStart(),
- RedCG, Cnt);
}
}
(void)InRedScope.Privatize();
@@ -3913,6 +3919,16 @@
assert(isOpenMPTargetExecutionDirective(S.getDirectiveKind()));
CodeGenModule &CGM = CGF.CGM;
+ // On device emit this construct as inlined code.
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ OMPLexicalScope Scope(CGF, S, OMPD_target);
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ CGF, OMPD_target, [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
+ });
+ return;
+ }
+
llvm::Function *Fn = nullptr;
llvm::Constant *FnID = nullptr;
@@ -3965,12 +3981,12 @@
static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S,
PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
CGF.EmitOMPPrivateClause(S, PrivateScope);
(void)PrivateScope.Privatize();
- Action.Enter(CGF);
CGF.EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
}
@@ -4022,7 +4038,8 @@
void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &S) {
// Emit teams region as a standalone region.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPPrivateScope PrivateScope(CGF);
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
CGF.EmitOMPPrivateClause(S, PrivateScope);
@@ -4042,12 +4059,12 @@
Action.Enter(CGF);
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
CGF.EmitOMPPrivateClause(S, PrivateScope);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
- Action.Enter(CGF);
CGF.EmitStmt(CS->getCapturedStmt());
CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
};
@@ -4088,7 +4105,8 @@
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4133,7 +4151,8 @@
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4177,7 +4196,8 @@
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4198,7 +4218,8 @@
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4220,7 +4241,8 @@
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4242,7 +4264,8 @@
// Emit teams region as a standalone region.
auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4266,7 +4289,8 @@
// Emit teams region as a standalone region.
auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4317,7 +4341,8 @@
// Emit teams region as a standalone region.
auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
@@ -4588,7 +4613,8 @@
// Get the captured statement associated with the 'parallel' region.
auto *CS = S.getCapturedStmt(OMPD_parallel);
Action.Enter(CGF);
- auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
CGF.EmitOMPPrivateClause(S, PrivateScope);
@@ -4632,7 +4658,8 @@
Action.Enter(CGF);
// Emit directive as a combined directive that consists of two implicit
// directives: 'parallel' with 'for' directive.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
CodeGenFunction::OMPCancelStackRAII CancelRegion(
CGF, OMPD_target_parallel_for, S.hasCancel());
CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
@@ -4672,7 +4699,8 @@
Action.Enter(CGF);
// Emit directive as a combined directive that consists of two implicit
// directives: 'parallel' with 'for' directive.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
emitDispatchForLoopBounds);
};
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 4fb749f..d898417 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -992,8 +992,8 @@
AP.second.AddressPointIndex));
// Sort the bit set entries for determinism.
- std::sort(BitsetEntries.begin(), BitsetEntries.end(),
- [this](const BSEntry &E1, const BSEntry &E2) {
+ llvm::sort(BitsetEntries.begin(), BitsetEntries.end(),
+ [this](const BSEntry &E1, const BSEntry &E2) {
if (&E1 == &E2)
return false;
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index 7d07ea4..a32be19 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -193,7 +193,7 @@
// The alignment to use when accessing this lvalue. (For vector elements,
// this is the alignment of the whole vector.)
- int64_t Alignment;
+ unsigned Alignment;
// objective-c's ivar
bool Ivar:1;
@@ -215,13 +215,13 @@
// to make the default bitfield pattern all-zeroes.
bool ImpreciseLifetime : 1;
- LValueBaseInfo BaseInfo;
- TBAAAccessInfo TBAAInfo;
-
// This flag shows if a nontemporal load/stores should be used when accessing
// this lvalue.
bool Nontemporal : 1;
+ LValueBaseInfo BaseInfo;
+ TBAAAccessInfo TBAAInfo;
+
Expr *BaseIvarExp;
private:
@@ -231,7 +231,10 @@
"initializing l-value with zero alignment!");
this->Type = Type;
this->Quals = Quals;
- this->Alignment = Alignment.getQuantity();
+ const unsigned MaxAlign = 1U << 31;
+ this->Alignment = Alignment.getQuantity() <= MaxAlign
+ ? Alignment.getQuantity()
+ : MaxAlign;
assert(this->Alignment == Alignment.getQuantity() &&
"Alignment exceeds allowed max!");
this->BaseInfo = BaseInfo;
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 2f814a7..3d7b906 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -862,6 +862,10 @@
if (SanOpts.has(SanitizerKind::SafeStack))
Fn->addFnAttr(llvm::Attribute::SafeStack);
+ // Apply fuzzing attribute to the function.
+ if (SanOpts.hasOneOf(SanitizerKind::Fuzzer | SanitizerKind::FuzzerNoLink))
+ Fn->addFnAttr(llvm::Attribute::OptForFuzzing);
+
// Ignore TSan memory acesses from within ObjC/ObjC++ dealloc, initialize,
// .cxx_destruct, __destroy_helper_block_ and all of their calees at run time.
if (SanOpts.has(SanitizerKind::Thread)) {
@@ -1067,6 +1071,11 @@
EmitStartEHSpec(CurCodeDecl);
PrologueCleanupDepth = EHStack.stable_begin();
+
+ // Emit OpenMP specific initialization of the device functions.
+ if (getLangOpts().OpenMP && CurCodeDecl)
+ CGM.getOpenMPRuntime().emitFunctionProlog(*this, CurCodeDecl);
+
EmitFunctionProlog(*CurFnInfo, CurFn, Args);
if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index ca2a8d9..7cdec6e 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -693,57 +693,107 @@
typedef llvm::DenseMap<const Decl *, Address> DeclMapTy;
- /// \brief The scope used to remap some variables as private in the OpenMP
- /// loop body (or other captured region emitted without outlining), and to
- /// restore old vars back on exit.
- class OMPPrivateScope : public RunCleanupsScope {
+ /// The class used to assign some variables some temporarily addresses.
+ class OMPMapVars {
DeclMapTy SavedLocals;
- DeclMapTy SavedPrivates;
-
- private:
- OMPPrivateScope(const OMPPrivateScope &) = delete;
- void operator=(const OMPPrivateScope &) = delete;
+ DeclMapTy SavedTempAddresses;
+ OMPMapVars(const OMPMapVars &) = delete;
+ void operator=(const OMPMapVars &) = delete;
public:
- /// \brief Enter a new OpenMP private scope.
- explicit OMPPrivateScope(CodeGenFunction &CGF) : RunCleanupsScope(CGF) {}
+ explicit OMPMapVars() = default;
+ ~OMPMapVars() {
+ assert(SavedLocals.empty() && "Did not restored original addresses.");
+ };
- /// \brief Registers \a LocalVD variable as a private and apply \a
- /// PrivateGen function for it to generate corresponding private variable.
- /// \a PrivateGen returns an address of the generated private variable.
- /// \return true if the variable is registered as private, false if it has
- /// been privatized already.
- bool
- addPrivate(const VarDecl *LocalVD,
- llvm::function_ref<Address()> PrivateGen) {
- assert(PerformCleanup && "adding private to dead scope");
-
+ /// Sets the address of the variable \p LocalVD to be \p TempAddr in
+ /// function \p CGF.
+ /// \return true if at least one variable was set already, false otherwise.
+ bool setVarAddr(CodeGenFunction &CGF, const VarDecl *LocalVD,
+ Address TempAddr) {
LocalVD = LocalVD->getCanonicalDecl();
// Only save it once.
if (SavedLocals.count(LocalVD)) return false;
// Copy the existing local entry to SavedLocals.
auto it = CGF.LocalDeclMap.find(LocalVD);
- if (it != CGF.LocalDeclMap.end()) {
- SavedLocals.insert({LocalVD, it->second});
- } else {
- SavedLocals.insert({LocalVD, Address::invalid()});
- }
+ if (it != CGF.LocalDeclMap.end())
+ SavedLocals.try_emplace(LocalVD, it->second);
+ else
+ SavedLocals.try_emplace(LocalVD, Address::invalid());
// Generate the private entry.
- Address Addr = PrivateGen();
QualType VarTy = LocalVD->getType();
if (VarTy->isReferenceType()) {
Address Temp = CGF.CreateMemTemp(VarTy);
- CGF.Builder.CreateStore(Addr.getPointer(), Temp);
- Addr = Temp;
+ CGF.Builder.CreateStore(TempAddr.getPointer(), Temp);
+ TempAddr = Temp;
}
- SavedPrivates.insert({LocalVD, Addr});
+ SavedTempAddresses.try_emplace(LocalVD, TempAddr);
return true;
}
- /// \brief Privatizes local variables previously registered as private.
+ /// Applies new addresses to the list of the variables.
+ /// \return true if at least one variable is using new address, false
+ /// otherwise.
+ bool apply(CodeGenFunction &CGF) {
+ copyInto(SavedTempAddresses, CGF.LocalDeclMap);
+ SavedTempAddresses.clear();
+ return !SavedLocals.empty();
+ }
+
+ /// Restores original addresses of the variables.
+ void restore(CodeGenFunction &CGF) {
+ if (!SavedLocals.empty()) {
+ copyInto(SavedLocals, CGF.LocalDeclMap);
+ SavedLocals.clear();
+ }
+ }
+
+ private:
+ /// Copy all the entries in the source map over the corresponding
+ /// entries in the destination, which must exist.
+ static void copyInto(const DeclMapTy &Src, DeclMapTy &Dest) {
+ for (auto &Pair : Src) {
+ if (!Pair.second.isValid()) {
+ Dest.erase(Pair.first);
+ continue;
+ }
+
+ auto I = Dest.find(Pair.first);
+ if (I != Dest.end())
+ I->second = Pair.second;
+ else
+ Dest.insert(Pair);
+ }
+ }
+ };
+
+ /// The scope used to remap some variables as private in the OpenMP loop body
+ /// (or other captured region emitted without outlining), and to restore old
+ /// vars back on exit.
+ class OMPPrivateScope : public RunCleanupsScope {
+ OMPMapVars MappedVars;
+ OMPPrivateScope(const OMPPrivateScope &) = delete;
+ void operator=(const OMPPrivateScope &) = delete;
+
+ public:
+ /// Enter a new OpenMP private scope.
+ explicit OMPPrivateScope(CodeGenFunction &CGF) : RunCleanupsScope(CGF) {}
+
+ /// Registers \p LocalVD variable as a private and apply \p PrivateGen
+ /// function for it to generate corresponding private variable. \p
+ /// PrivateGen returns an address of the generated private variable.
+ /// \return true if the variable is registered as private, false if it has
+ /// been privatized already.
+ bool addPrivate(const VarDecl *LocalVD,
+ llvm::function_ref<Address()> PrivateGen) {
+ assert(PerformCleanup && "adding private to dead scope");
+ return MappedVars.setVarAddr(CGF, LocalVD, PrivateGen());
+ }
+
+ /// Privatizes local variables previously registered as private.
/// Registration is separate from the actual privatization to allow
/// initializers use values of the original variables, not the private one.
/// This is important, for example, if the private variable is a class
@@ -751,19 +801,14 @@
/// variables. But at initialization original variables must be used, not
/// private copies.
/// \return true if at least one variable was privatized, false otherwise.
- bool Privatize() {
- copyInto(SavedPrivates, CGF.LocalDeclMap);
- SavedPrivates.clear();
- return !SavedLocals.empty();
- }
+ bool Privatize() { return MappedVars.apply(CGF); }
void ForceCleanup() {
RunCleanupsScope::ForceCleanup();
- copyInto(SavedLocals, CGF.LocalDeclMap);
- SavedLocals.clear();
+ MappedVars.restore(CGF);
}
- /// \brief Exit scope - all the mapped variables are restored.
+ /// Exit scope - all the mapped variables are restored.
~OMPPrivateScope() {
if (PerformCleanup)
ForceCleanup();
@@ -774,25 +819,6 @@
VD = VD->getCanonicalDecl();
return !VD->isLocalVarDeclOrParm() && CGF.LocalDeclMap.count(VD) > 0;
}
-
- private:
- /// Copy all the entries in the source map over the corresponding
- /// entries in the destination, which must exist.
- static void copyInto(const DeclMapTy &src, DeclMapTy &dest) {
- for (auto &pair : src) {
- if (!pair.second.isValid()) {
- dest.erase(pair.first);
- continue;
- }
-
- auto it = dest.find(pair.first);
- if (it != dest.end()) {
- it->second = pair.second;
- } else {
- dest.insert(pair);
- }
- }
- }
};
/// \brief Takes the old cleanup stack size and emits the cleanup blocks
@@ -2122,27 +2148,13 @@
return it->second;
}
- /// getOpaqueLValueMapping - Given an opaque value expression (which
- /// must be mapped to an l-value), return its mapping.
- const LValue &getOpaqueLValueMapping(const OpaqueValueExpr *e) {
- assert(OpaqueValueMapping::shouldBindAsLValue(e));
+ /// Given an opaque value expression, return its LValue mapping if it exists,
+ /// otherwise create one.
+ LValue getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e);
- llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
- it = OpaqueLValues.find(e);
- assert(it != OpaqueLValues.end() && "no mapping for opaque value!");
- return it->second;
- }
-
- /// getOpaqueRValueMapping - Given an opaque value expression (which
- /// must be mapped to an r-value), return its mapping.
- const RValue &getOpaqueRValueMapping(const OpaqueValueExpr *e) {
- assert(!OpaqueValueMapping::shouldBindAsLValue(e));
-
- llvm::DenseMap<const OpaqueValueExpr*,RValue>::iterator
- it = OpaqueRValues.find(e);
- assert(it != OpaqueRValues.end() && "no mapping for opaque value!");
- return it->second;
- }
+ /// Given an opaque value expression, return its RValue mapping if it exists,
+ /// otherwise create one.
+ RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e);
/// Get the index of the current ArrayInitLoopExpr, if any.
llvm::Value *getArrayInitIndex() { return ArrayInitIndex; }
@@ -2344,7 +2356,7 @@
CharUnits CookieSize = CharUnits());
RValue EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
- const Expr *Arg, bool IsDelete);
+ const CallExpr *TheCallExpr, bool IsDelete);
llvm::Value *EmitCXXTypeidExpr(const CXXTypeidExpr *E);
llvm::Value *EmitDynamicCast(Address V, const CXXDynamicCastExpr *DCE);
@@ -3525,6 +3537,8 @@
llvm::Value *EmitARCLoadWeak(Address addr);
llvm::Value *EmitARCLoadWeakRetained(Address addr);
llvm::Value *EmitARCStoreWeak(Address addr, llvm::Value *value, bool ignored);
+ void emitARCCopyAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr);
+ void emitARCMoveAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr);
void EmitARCCopyWeak(Address dst, Address src);
void EmitARCMoveWeak(Address dst, Address src);
llvm::Value *EmitARCRetainAutorelease(QualType type, llvm::Value *value);
@@ -3873,10 +3887,10 @@
void ExpandTypeFromArgs(QualType Ty, LValue Dst,
SmallVectorImpl<llvm::Value *>::iterator &AI);
- /// ExpandTypeToArgs - Expand an RValue \arg RV, with the LLVM type for \arg
+ /// ExpandTypeToArgs - Expand an CallArg \arg Arg, with the LLVM type for \arg
/// Ty, into individual arguments on the provided vector \arg IRCallArgs,
/// starting at index \arg IRCallArgPos. See ABIArgInfo::Expand.
- void ExpandTypeToArgs(QualType Ty, RValue RV, llvm::FunctionType *IRFuncTy,
+ void ExpandTypeToArgs(QualType Ty, CallArg Arg, llvm::FunctionType *IRFuncTy,
SmallVectorImpl<llvm::Value *> &IRCallArgs,
unsigned &IRCallArgPos);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index de38105..dcdb0db 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -123,7 +123,6 @@
ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace();
RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC();
- BuiltinCC = getTargetCodeGenInfo().getABIInfo().getBuiltinCC();
if (LangOpts.ObjC1)
createObjCRuntime();
@@ -409,13 +408,15 @@
if (llvm::Function *CudaDtorFunction = CUDARuntime->makeModuleDtorFunction())
AddGlobalDtor(CudaDtorFunction);
}
- if (OpenMPRuntime)
+ if (OpenMPRuntime) {
if (llvm::Function *OpenMPRegistrationFunction =
OpenMPRuntime->emitRegistrationFunction()) {
auto ComdatKey = OpenMPRegistrationFunction->hasComdat() ?
OpenMPRegistrationFunction : nullptr;
AddGlobalCtor(OpenMPRegistrationFunction, 0, ComdatKey);
}
+ OpenMPRuntime->clear();
+ }
if (PGOReader) {
getModule().setProfileSummary(PGOReader->getSummary().getMD(VMContext));
if (PGOStats.hasDiagnostics())
@@ -707,7 +708,8 @@
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
return;
}
-
+ if (!D)
+ return;
// Set visibility for definitions.
LinkageInfo LV = D->getLinkageAndVisibility();
if (LV.isVisibilityExplicit() || !GV->isDeclarationForLinker())
@@ -785,19 +787,17 @@
void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV,
GlobalDecl GD) const {
const auto *D = dyn_cast<NamedDecl>(GD.getDecl());
+ // C++ destructors have a few C++ ABI specific special cases.
if (const auto *Dtor = dyn_cast_or_null<CXXDestructorDecl>(D)) {
- if (getCXXABI().useThunkForDtorVariant(Dtor, GD.getDtorType())) {
- // Don't dllexport/import destructor thunks.
- GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
- return;
- }
+ getCXXABI().setCXXDestructorDLLStorage(GV, Dtor, GD.getDtorType());
+ return;
}
setDLLImportDLLExport(GV, D);
}
void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV,
const NamedDecl *D) const {
- if (D->isExternallyVisible()) {
+ if (D && D->isExternallyVisible()) {
if (D->hasAttr<DLLImportAttr>())
GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
else if (D->hasAttr<DLLExportAttr>() && !GV->isDeclarationForLinker())
@@ -1073,14 +1073,8 @@
GVALinkage Linkage = getContext().GetGVALinkageForFunction(D);
- if (isa<CXXDestructorDecl>(D) &&
- getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D),
- GD.getDtorType())) {
- // Destructor variants in the Microsoft C++ ABI are always internal or
- // linkonce_odr thunks emitted on an as-needed basis.
- return Linkage == GVA_Internal ? llvm::GlobalValue::InternalLinkage
- : llvm::GlobalValue::LinkOnceODRLinkage;
- }
+ if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(D))
+ return getCXXABI().getCXXDestructorLinkage(Linkage, Dtor, GD.getDtorType());
if (isa<CXXConstructorDecl>(D) &&
cast<CXXConstructorDecl>(D)->isInheritingConstructor() &&
@@ -1302,7 +1296,7 @@
AddedAttr = true;
}
if (!Features.empty()) {
- std::sort(Features.begin(), Features.end());
+ llvm::sort(Features.begin(), Features.end());
Attrs.addAttribute("target-features", llvm::join(Features, ","));
AddedAttr = true;
}
@@ -1928,6 +1922,7 @@
/*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name);
if (supportsCOMDAT())
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
+ setDSOLocal(GV);
return ConstantAddress(GV, Alignment);
}
@@ -2382,6 +2377,12 @@
// Any attempts to use a MultiVersion function should result in retrieving
// the iFunc instead. Name Mangling will handle the rest of the changes.
if (const FunctionDecl *FD = cast_or_null<FunctionDecl>(D)) {
+ // For the device mark the function as one that should be emitted.
+ if (getLangOpts().OpenMPIsDevice && OpenMPRuntime &&
+ !OpenMPRuntime->markAsGlobalTarget(FD) && FD->isDefined() &&
+ !DontDefer && !IsForDefinition)
+ addDeferredDeclToEmit(GD);
+
if (FD->isMultiVersion() && FD->getAttr<TargetAttr>()->isDefaultVersion()) {
UpdateMultiVersionNames(GD, FD);
if (!IsForDefinition)
@@ -2399,8 +2400,10 @@
}
// Handle dropped DLL attributes.
- if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>())
+ if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>()) {
Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ setDSOLocal(Entry);
+ }
// If there are two attempts to define the same mangled name, issue an
// error.
@@ -2551,6 +2554,16 @@
Ty = getTypes().ConvertFunctionType(CanonTy, FD);
}
+ // Devirtualized destructor calls may come through here instead of via
+ // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead
+ // of the complete destructor when necessary.
+ if (const auto *DD = dyn_cast<CXXDestructorDecl>(GD.getDecl())) {
+ if (getTarget().getCXXABI().isMicrosoft() &&
+ GD.getDtorType() == Dtor_Complete &&
+ DD->getParent()->getNumVBases() == 0)
+ GD = GlobalDecl(DD, Dtor_Base);
+ }
+
StringRef MangledName = getMangledName(GD);
return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer,
/*IsThunk=*/false, llvm::AttributeList(),
@@ -2572,7 +2585,7 @@
// Demangle the premangled name from getTerminateFn()
IdentifierInfo &CXXII =
- (Name == "_ZSt9terminatev" || Name == "\01?terminate@@YAXXZ")
+ (Name == "_ZSt9terminatev" || Name == "?terminate@@YAXXZ")
? C.Idents.get("terminate")
: C.Idents.get(Name);
@@ -2619,6 +2632,7 @@
F->setLinkage(llvm::GlobalValue::ExternalLinkage);
}
}
+ setDSOLocal(F);
}
}
@@ -2630,13 +2644,7 @@
llvm::Constant *
CodeGenModule::CreateBuiltinFunction(llvm::FunctionType *FTy, StringRef Name,
llvm::AttributeList ExtraAttrs) {
- llvm::Constant *C =
- GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false,
- /*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs);
- if (auto *F = dyn_cast<llvm::Function>(C))
- if (F->empty())
- F->setCallingConv(getBuiltinCC());
- return C;
+ return CreateRuntimeFunction(FTy, Name, ExtraAttrs, true);
}
/// isTypeConstant - Determine whether an object of this type can be emitted
@@ -2687,6 +2695,9 @@
if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>())
Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ if (LangOpts.OpenMP && !LangOpts.OpenMPSimd && D)
+ getOpenMPRuntime().registerTargetGlobalVariable(D, Entry);
+
if (Entry->getType() == Ty)
return Entry;
@@ -2755,6 +2766,9 @@
// Handle things which are present even on external declarations.
if (D) {
+ if (LangOpts.OpenMP && !LangOpts.OpenMPSimd)
+ getOpenMPRuntime().registerTargetGlobalVariable(D, GV);
+
// FIXME: This code is overly simple and should be merged with other global
// handling.
GV->setConstant(isTypeConstant(D->getType(), false));
@@ -2943,7 +2957,10 @@
llvm::Constant *
CodeGenModule::CreateRuntimeVariable(llvm::Type *Ty,
StringRef Name) {
- return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), nullptr);
+ auto *Ret =
+ GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), nullptr);
+ setDSOLocal(cast<llvm::GlobalValue>(Ret->stripPointerCasts()));
+ return Ret;
}
void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) {
@@ -3071,6 +3088,12 @@
if (getLangOpts().OpenCL && ASTTy->isSamplerT())
return;
+ // If this is OpenMP device, check if it is legal to emit this global
+ // normally.
+ if (LangOpts.OpenMPIsDevice && OpenMPRuntime &&
+ OpenMPRuntime->emitTargetGlobalVariable(D))
+ return;
+
llvm::Constant *Init = nullptr;
CXXRecordDecl *RD = ASTTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
bool NeedsGlobalCtor = false;
@@ -3794,14 +3817,13 @@
if (!CFConstantStringClassRef) {
llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
Ty = llvm::ArrayType::get(Ty, 0);
- llvm::Constant *GV =
- CreateRuntimeVariable(Ty, "__CFConstantStringClassReference");
+ llvm::GlobalValue *GV = cast<llvm::GlobalValue>(
+ CreateRuntimeVariable(Ty, "__CFConstantStringClassReference"));
if (getTriple().isOSBinFormatCOFF()) {
IdentifierInfo &II = getContext().Idents.get(GV->getName());
TranslationUnitDecl *TUDecl = getContext().getTranslationUnitDecl();
DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
- llvm::GlobalValue *CGV = cast<llvm::GlobalValue>(GV);
const VarDecl *VD = nullptr;
for (const auto &Result : DC->lookup(&II))
@@ -3809,13 +3831,14 @@
break;
if (!VD || !VD->hasAttr<DLLExportAttr>()) {
- CGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
- CGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
} else {
- CGV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
- CGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
}
}
+ setDSOLocal(GV);
// Decay array -> ptr
CFConstantStringClassRef =
@@ -3999,6 +4022,7 @@
assert(CGM.supportsCOMDAT() && "Only COFF uses weak string literals");
GV->setComdat(M.getOrInsertComdat(GV->getName()));
}
+ CGM.setDSOLocal(GV);
return GV;
}
@@ -4663,9 +4687,7 @@
/// to such functions with an unmangled name from inline assembly within the
/// same translation unit.
void CodeGenModule::EmitStaticExternCAliases() {
- // Don't do anything if we're generating CUDA device code -- the NVPTX
- // assembly target doesn't support aliases.
- if (Context.getTargetInfo().getTriple().isNVPTX())
+ if (!getTargetCodeGenInfo().shouldEmitStaticExternCAliases())
return;
for (auto &I : StaticExternCValues) {
IdentifierInfo *Name = I.first;
diff --git a/lib/CodeGen/CodeGenTypeCache.h b/lib/CodeGen/CodeGenTypeCache.h
index fb096ac..901aed6 100644
--- a/lib/CodeGen/CodeGenTypeCache.h
+++ b/lib/CodeGen/CodeGenTypeCache.h
@@ -112,8 +112,6 @@
llvm::CallingConv::ID RuntimeCC;
llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
- llvm::CallingConv::ID BuiltinCC;
- llvm::CallingConv::ID getBuiltinCC() const { return BuiltinCC; }
LangAS getASTAllocaAddressSpace() const { return ASTAllocaAddressSpace; }
};
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index 3b45e57..55e74cd 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -63,13 +63,6 @@
bool classifyReturnType(CGFunctionInfo &FI) const override;
bool passClassIndirect(const CXXRecordDecl *RD) const {
- // Clang <= 4 used the pre-C++11 rule, which ignores move operations.
- // The PS4 platform ABI follows the behavior of Clang 3.2.
- if (CGM.getCodeGenOpts().getClangABICompat() <=
- CodeGenOptions::ClangABI::Ver4 ||
- CGM.getTriple().getOS() == llvm::Triple::PS4)
- return RD->hasNonTrivialDestructorForCall() ||
- RD->hasNonTrivialCopyConstructorForCall();
return !canCopyArgument(RD);
}
@@ -1474,8 +1467,7 @@
llvm::Value *VTT =
CGF.GetVTTParameter(GlobalDecl(D, Type), ForVirtualBase, Delegating);
QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
- Args.insert(Args.begin() + 1,
- CallArg(RValue::get(VTT), VTTTy, /*needscopy=*/false));
+ Args.insert(Args.begin() + 1, CallArg(RValue::get(VTT), VTTTy));
return AddedStructorArgs::prefix(1); // Added one arg.
}
@@ -2399,8 +2391,10 @@
CGM.SetLLVMFunctionAttributes(nullptr, FI, cast<llvm::Function>(Init));
}
- if (Init)
+ if (Init) {
Init->setVisibility(Var->getVisibility());
+ Init->setDSOLocal(Var->isDSOLocal());
+ }
llvm::LLVMContext &Context = CGM.getModule().getContext();
llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper);
@@ -2614,10 +2608,8 @@
/*Constant=*/true,
llvm::GlobalValue::ExternalLinkage, nullptr,
Name);
- if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
- CGM.setGVProperties(GV, RD);
- }
+ const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+ CGM.setGVProperties(GV, RD);
}
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
@@ -2949,6 +2941,7 @@
llvm::Constant *VTable =
CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy);
+ CGM.setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts()));
llvm::Type *PtrDiffTy =
CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index 43c061e..e80c3b3 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -216,13 +216,21 @@
return DT != Dtor_Base;
}
+ void setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const override;
+
+ llvm::GlobalValue::LinkageTypes
+ getCXXDestructorLinkage(GVALinkage Linkage, const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const override;
+
void EmitCXXDestructors(const CXXDestructorDecl *D) override;
const CXXRecordDecl *
getThisArgumentTypeForMethod(const CXXMethodDecl *MD) override {
MD = MD->getCanonicalDecl();
if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD)) {
- MicrosoftVTableContext::MethodVFTableLocation ML =
+ const MethodVFTableLocation &ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD);
// The vbases might be ordered differently in the final overrider object
// and the complete object, so the "this" argument may sometimes point to
@@ -515,10 +523,12 @@
if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name))
return GV;
- return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty,
- /*isConstant=*/true,
- llvm::GlobalValue::ExternalLinkage,
- /*Initializer=*/nullptr, Name);
+ auto *GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty,
+ /*isConstant=*/true,
+ llvm::GlobalValue::ExternalLinkage,
+ /*Initializer=*/nullptr, Name);
+ CGM.setDSOLocal(GV);
+ return GV;
}
llvm::Constant *getImageRelativeConstant(llvm::Constant *PtrVal) {
@@ -606,9 +616,8 @@
const VBTableGlobals &enumerateVBTables(const CXXRecordDecl *RD);
/// \brief Generate a thunk for calling a virtual member function MD.
- llvm::Function *EmitVirtualMemPtrThunk(
- const CXXMethodDecl *MD,
- const MicrosoftVTableContext::MethodVFTableLocation &ML);
+ llvm::Function *EmitVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ const MethodVFTableLocation &ML);
public:
llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override;
@@ -819,60 +828,7 @@
return RAA_Default;
case llvm::Triple::x86_64:
- bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
- bool DtorIsTrivialForCall = false;
-
- // If a class has at least one non-deleted, trivial copy constructor, it
- // is passed according to the C ABI. Otherwise, it is passed indirectly.
- //
- // Note: This permits classes with non-trivial copy or move ctors to be
- // passed in registers, so long as they *also* have a trivial copy ctor,
- // which is non-conforming.
- if (RD->needsImplicitCopyConstructor()) {
- if (!RD->defaultedCopyConstructorIsDeleted()) {
- if (RD->hasTrivialCopyConstructor())
- CopyCtorIsTrivial = true;
- if (RD->hasTrivialCopyConstructorForCall())
- CopyCtorIsTrivialForCall = true;
- }
- } else {
- for (const CXXConstructorDecl *CD : RD->ctors()) {
- if (CD->isCopyConstructor() && !CD->isDeleted()) {
- if (CD->isTrivial())
- CopyCtorIsTrivial = true;
- if (CD->isTrivialForCall())
- CopyCtorIsTrivialForCall = true;
- }
- }
- }
-
- if (RD->needsImplicitDestructor()) {
- if (!RD->defaultedDestructorIsDeleted() &&
- RD->hasTrivialDestructorForCall())
- DtorIsTrivialForCall = true;
- } else if (const auto *D = RD->getDestructor()) {
- if (!D->isDeleted() && D->isTrivialForCall())
- DtorIsTrivialForCall = true;
- }
-
- // If the copy ctor and dtor are both trivial-for-calls, pass direct.
- if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)
- return RAA_Default;
-
- // If a class has a destructor, we'd really like to pass it indirectly
- // because it allows us to elide copies. Unfortunately, MSVC makes that
- // impossible for small types, which it will pass in a single register or
- // stack slot. Most objects with dtors are large-ish, so handle that early.
- // We can't call out all large objects as being indirect because there are
- // multiple x64 calling conventions and the C++ ABI code shouldn't dictate
- // how we pass large POD types.
-
- // Note: This permits small classes with nontrivial destructors to be
- // passed in registers, which is non-conforming.
- if (CopyCtorIsTrivial &&
- getContext().getTypeSize(RD->getTypeForDecl()) <= 64)
- return RAA_Default;
- return RAA_Indirect;
+ return !canCopyArgument(RD) ? RAA_Indirect : RAA_Default;
}
llvm_unreachable("invalid enum");
@@ -1196,15 +1152,16 @@
unsigned AS = getThisAddress(CGF).getAddressSpace();
llvm::Value *Int8This = nullptr; // Initialize lazily.
- for (VBOffsets::const_iterator I = VBaseMap.begin(), E = VBaseMap.end();
- I != E; ++I) {
+ for (const CXXBaseSpecifier &S : RD->vbases()) {
+ const CXXRecordDecl *VBase = S.getType()->getAsCXXRecordDecl();
+ auto I = VBaseMap.find(VBase);
+ assert(I != VBaseMap.end());
if (!I->second.hasVtorDisp())
continue;
llvm::Value *VBaseOffset =
- GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, I->first);
- uint64_t ConstantVBaseOffset =
- Layout.getVBaseClassOffset(I->first).getQuantity();
+ GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, VBase);
+ uint64_t ConstantVBaseOffset = I->second.VBaseOffset.getQuantity();
// vtorDisp_for_vbase = vbptr[vbase_idx] - offsetof(RD, vbase).
llvm::Value *VtorDispValue = Builder.CreateSub(
@@ -1309,6 +1266,52 @@
return Added;
}
+void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const {
+ // Deleting destructor variants are never imported or exported. Give them the
+ // default storage class.
+ if (DT == Dtor_Deleting) {
+ GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ } else {
+ const NamedDecl *ND = Dtor;
+ CGM.setDLLImportDLLExport(GV, ND);
+ }
+}
+
+llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage(
+ GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const {
+ // Internal things are always internal, regardless of attributes. After this,
+ // we know the thunk is externally visible.
+ if (Linkage == GVA_Internal)
+ return llvm::GlobalValue::InternalLinkage;
+
+ switch (DT) {
+ case Dtor_Base:
+ // The base destructor most closely tracks the user-declared constructor, so
+ // we delegate back to the normal declarator case.
+ return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage,
+ /*isConstantVariable=*/false);
+ case Dtor_Complete:
+ // The complete destructor is like an inline function, but it may be
+ // imported and therefore must be exported as well. This requires changing
+ // the linkage if a DLL attribute is present.
+ if (Dtor->hasAttr<DLLExportAttr>())
+ return llvm::GlobalValue::WeakODRLinkage;
+ if (Dtor->hasAttr<DLLImportAttr>())
+ return llvm::GlobalValue::AvailableExternallyLinkage;
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+ case Dtor_Deleting:
+ // Deleting destructors are like inline functions. They have vague linkage
+ // and are emitted everywhere they are used. They are internal if the class
+ // is internal.
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+ case Dtor_Comdat:
+ llvm_unreachable("MS C++ ABI does not support comdat dtors");
+ }
+ llvm_unreachable("invalid dtor type");
+}
+
void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
// The TU defining a dtor is only guaranteed to emit a base destructor. All
// other destructor variants are delegating thunks.
@@ -1332,7 +1335,7 @@
LookupGD = GlobalDecl(DD, Dtor_Deleting);
}
- MicrosoftVTableContext::MethodVFTableLocation ML =
+ const MethodVFTableLocation &ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
CharUnits Adjustment = ML.VFPtrOffset;
@@ -1381,7 +1384,7 @@
// with the base one, so look up the deleting one instead.
LookupGD = GlobalDecl(DD, Dtor_Deleting);
}
- MicrosoftVTableContext::MethodVFTableLocation ML =
+ const MethodVFTableLocation &ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
CharUnits StaticOffset = ML.VFPtrOffset;
@@ -1537,8 +1540,7 @@
}
RValue RV = RValue::get(MostDerivedArg);
if (FPT->isVariadic()) {
- Args.insert(Args.begin() + 1,
- CallArg(RV, getContext().IntTy, /*needscopy=*/false));
+ Args.insert(Args.begin() + 1, CallArg(RV, getContext().IntTy));
return AddedStructorArgs::prefix(1);
}
Args.add(RV, getContext().IntTy);
@@ -1549,6 +1551,12 @@
const CXXDestructorDecl *DD,
CXXDtorType Type, bool ForVirtualBase,
bool Delegating, Address This) {
+ // Use the base destructor variant in place of the complete destructor variant
+ // if the class has no virtual bases. This effectively implements some of the
+ // -mconstructor-aliases optimization, but as part of the MS C++ ABI.
+ if (Type == Dtor_Complete && DD->getParent()->getNumVBases() == 0)
+ Type = Dtor_Base;
+
CGCallee Callee = CGCallee::forDirect(
CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)),
DD);
@@ -1842,8 +1850,7 @@
llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty, MethodDecl->getParent());
MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();
- MicrosoftVTableContext::MethodVFTableLocation ML =
- VFTContext.getMethodVFTableLocation(GD);
+ const MethodVFTableLocation &ML = VFTContext.getMethodVFTableLocation(GD);
// Compute the identity of the most derived class whose virtual table is
// located at the MethodVFTableLocation ML.
@@ -1928,16 +1935,16 @@
return VBGlobals;
}
-llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk(
- const CXXMethodDecl *MD,
- const MicrosoftVTableContext::MethodVFTableLocation &ML) {
+llvm::Function *
+MicrosoftCXXABI::EmitVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ const MethodVFTableLocation &ML) {
assert(!isa<CXXConstructorDecl>(MD) && !isa<CXXDestructorDecl>(MD) &&
"can't form pointers to ctors or virtual dtors");
// Calculate the mangled name.
SmallString<256> ThunkName;
llvm::raw_svector_ostream Out(ThunkName);
- getMangleContext().mangleVirtualMemPtrThunk(MD, Out);
+ getMangleContext().mangleVirtualMemPtrThunk(MD, ML, Out);
// If the thunk has been generated previously, just return it.
if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))
@@ -2751,7 +2758,7 @@
FirstField = CGM.GetAddrOfFunction(MD, Ty);
} else {
auto &VTableContext = CGM.getMicrosoftVTableContext();
- MicrosoftVTableContext::MethodVFTableLocation ML =
+ const MethodVFTableLocation &ML =
VTableContext.getMethodVFTableLocation(MD);
FirstField = EmitVirtualMemPtrThunk(MD, ML);
// Include the vfptr adjustment if the method is in a non-primary vftable.
@@ -3369,7 +3376,7 @@
// mangled into them so they can be aggressively deduplicated by the linker.
static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) {
- StringRef MangledName("\01??_7type_info@@6B@");
+ StringRef MangledName("??_7type_info@@6B@");
if (auto VTable = CGM.getModule().getNamedGlobal(MangledName))
return VTable;
return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
@@ -3821,19 +3828,12 @@
static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl *dtor,
StructorType dtorType) {
- // The complete destructor is equivalent to the base destructor for
- // classes with no virtual bases, so try to emit it as an alias.
- if (!dtor->getParent()->getNumVBases() &&
- (dtorType == StructorType::Complete || dtorType == StructorType::Base)) {
- bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias(
- GlobalDecl(dtor, Dtor_Complete), GlobalDecl(dtor, Dtor_Base));
- if (ProducedAlias) {
- if (dtorType == StructorType::Complete)
- return;
- if (dtor->isVirtual())
- CGM.getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete));
- }
- }
+ // Emit the base destructor if the base and complete (vbase) destructors are
+ // equivalent. This effectively implements -mconstructor-aliases as part of
+ // the ABI.
+ if (dtorType == StructorType::Complete &&
+ dtor->getParent()->getNumVBases() == 0)
+ dtorType = StructorType::Base;
// The base destructor is equivalent to the base destructor of its
// base class if there is exactly one non-virtual base class with a
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index aadbd30..02dd214 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -140,8 +140,11 @@
static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT,
CGCXXABI &CXXABI) {
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
+ if (!RD) {
+ if (!RT->getDecl()->canPassInRegisters())
+ return CGCXXABI::RAA_Indirect;
return CGCXXABI::RAA_Default;
+ }
return CXXABI.getRecordArgABI(RD);
}
@@ -153,6 +156,20 @@
return getRecordArgABI(RT, CXXABI);
}
+static bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI,
+ const ABIInfo &Info) {
+ QualType Ty = FI.getReturnType();
+
+ if (const auto *RT = Ty->getAs<RecordType>())
+ if (!isa<CXXRecordDecl>(RT->getDecl()) &&
+ !RT->getDecl()->canPassInRegisters()) {
+ FI.getReturnInfo() = Info.getNaturalAlignIndirect(Ty);
+ return true;
+ }
+
+ return CXXABI.classifyReturnType(FI);
+}
+
/// Pass transparent unions as if they were the type of the first element. Sema
/// should ensure that all elements of the union have the same "machine type".
static QualType useFirstFieldIfTransparentUnion(QualType Ty) {
@@ -414,6 +431,10 @@
return llvm::CallingConv::SPIR_KERNEL;
}
+unsigned TargetCodeGenInfo::getCUDAKernelCallingConv() const {
+ return llvm::CallingConv::C;
+}
+
llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM,
llvm::PointerType *T, QualType QT) const {
return llvm::ConstantPointerNull::get(T);
@@ -1749,7 +1770,7 @@
} else
State.FreeRegs = DefaultNumRegisterParameters;
- if (!getCXXABI().classifyReturnType(FI)) {
+ if (!::classifyReturnType(getCXXABI(), FI, *this)) {
FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), State);
} else if (FI.getReturnInfo().isIndirect()) {
// The C++ ABI is not aware of register usage, so we have to check if the
@@ -2114,8 +2135,8 @@
/// classify it as INTEGER (for compatibility with older clang compilers).
bool classifyIntegerMMXAsSSE() const {
// Clang <= 3.8 did not do this.
- if (getCodeGenOpts().getClangABICompat() <=
- CodeGenOptions::ClangABI::Ver3_8)
+ if (getContext().getLangOpts().getClangABICompat() <=
+ LangOptions::ClangABI::Ver3_8)
return false;
const llvm::Triple &Triple = getTarget().getTriple();
@@ -3545,7 +3566,7 @@
unsigned FreeSSERegs = IsRegCall ? 16 : 8;
unsigned NeededInt, NeededSSE;
- if (!getCXXABI().classifyReturnType(FI)) {
+ if (!::classifyReturnType(getCXXABI(), FI, *this)) {
if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() &&
!FI.getReturnType()->getTypePtr()->isUnionType()) {
FI.getReturnInfo() =
@@ -4895,7 +4916,7 @@
bool isIllegalVectorType(QualType Ty) const;
void computeInfo(CGFunctionInfo &FI) const override {
- if (!getCXXABI().classifyReturnType(FI))
+ if (!::classifyReturnType(getCXXABI(), FI, *this))
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (auto &it : FI.arguments())
@@ -5626,7 +5647,7 @@
}
void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
- if (!getCXXABI().classifyReturnType(FI))
+ if (!::classifyReturnType(getCXXABI(), FI, *this))
FI.getReturnInfo() =
classifyReturnType(FI.getReturnType(), FI.isVariadic());
@@ -5673,18 +5694,6 @@
llvm::CallingConv::ID abiCC = getABIDefaultCC();
if (abiCC != getLLVMDefaultCC())
RuntimeCC = abiCC;
-
- // AAPCS apparently requires runtime support functions to be soft-float, but
- // that's almost certainly for historic reasons (Thumb1 not supporting VFP
- // most likely). It's more convenient for AAPCS16_VFP to be hard-float.
-
- // The Run-time ABI for the ARM Architecture section 4.1.2 requires
- // AEABI-complying FP helper functions to use the base AAPCS.
- // These AEABI functions are expanded in the ARM llvm backend, all the builtin
- // support functions emitted by clang such as the _Complex helpers follow the
- // abiCC.
- if (abiCC != getLLVMDefaultCC())
- BuiltinCC = abiCC;
}
ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
@@ -6149,6 +6158,7 @@
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const override;
+ bool shouldEmitStaticExternCAliases() const override;
private:
// Adds a NamedMDNode with F, Name, and Operand as operands, and adds the
@@ -6270,6 +6280,10 @@
// Append metadata to nvvm.annotations
MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
}
+
+bool NVPTXTargetCodeGenInfo::shouldEmitStaticExternCAliases() const {
+ return false;
+}
}
//===----------------------------------------------------------------------===//
@@ -7625,6 +7639,7 @@
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const override;
unsigned getOpenCLKernelCallingConv() const override;
+ unsigned getCUDAKernelCallingConv() const override;
llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM,
llvm::PointerType *T, QualType QT) const override;
@@ -7641,6 +7656,7 @@
createEnqueuedBlockKernel(CodeGenFunction &CGF,
llvm::Function *BlockInvokeFunc,
llvm::Value *BlockLiteral) const override;
+ bool shouldEmitStaticExternCAliases() const override;
};
}
@@ -7656,6 +7672,11 @@
const auto *ReqdWGS = M.getLangOpts().OpenCL ?
FD->getAttr<ReqdWorkGroupSizeAttr>() : nullptr;
+
+ if (M.getLangOpts().OpenCL && FD->hasAttr<OpenCLKernelAttr>() &&
+ (M.getTriple().getOS() == llvm::Triple::AMDHSA))
+ F->addFnAttr("amdgpu-implicitarg-num-bytes", "48");
+
const auto *FlatWGS = FD->getAttr<AMDGPUFlatWorkGroupSizeAttr>();
if (ReqdWGS || FlatWGS) {
unsigned Min = FlatWGS ? FlatWGS->getMin() : 0;
@@ -7706,6 +7727,10 @@
return llvm::CallingConv::AMDGPU_KERNEL;
}
+unsigned AMDGPUTargetCodeGenInfo::getCUDAKernelCallingConv() const {
+ return llvm::CallingConv::AMDGPU_KERNEL;
+}
+
// Currently LLVM assumes null pointers always have value 0,
// which results in incorrectly transformed IR. Therefore, instead of
// emitting null pointers in private and local address spaces, a null
@@ -7767,6 +7792,10 @@
return C.getOrInsertSyncScopeID(Name);
}
+bool AMDGPUTargetCodeGenInfo::shouldEmitStaticExternCAliases() const {
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// SPARC v8 ABI Implementation.
// Based on the SPARC Compliance Definition version 2.4.1.
@@ -8503,7 +8532,7 @@
// The ABI requires unions to be sorted but not structures.
// See FieldEncoding::operator< for sort algorithm.
if (RT->isUnionType())
- std::sort(FE.begin(), FE.end());
+ llvm::sort(FE.begin(), FE.end());
// We can now complete the TypeString.
unsigned E = FE.size();
for (unsigned I = 0; I != E; ++I) {
@@ -8547,7 +8576,7 @@
EnumEnc += '}';
FE.push_back(FieldEncoding(!I->getName().empty(), EnumEnc));
}
- std::sort(FE.begin(), FE.end());
+ llvm::sort(FE.begin(), FE.end());
unsigned E = FE.size();
for (unsigned I = 0; I != E; ++I) {
if (I)
diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h
index f7a813e..ab463c5 100644
--- a/lib/CodeGen/TargetInfo.h
+++ b/lib/CodeGen/TargetInfo.h
@@ -223,6 +223,9 @@
/// Get LLVM calling convention for OpenCL kernel.
virtual unsigned getOpenCLKernelCallingConv() const;
+ /// Get LLVM calling convention for CUDA kernel.
+ virtual unsigned getCUDAKernelCallingConv() const;
+
/// Get target specific null pointer.
/// \param T is the LLVM type of the null pointer.
/// \param QT is the clang QualType of the null pointer.
@@ -296,6 +299,11 @@
createEnqueuedBlockKernel(CodeGenFunction &CGF,
llvm::Function *BlockInvokeFunc,
llvm::Value *BlockLiteral) const;
+
+ /// \return true if the target supports alias from the unmangled name to the
+ /// mangled name of functions declared within an extern "C" region and marked
+ /// as 'used', and having internal linkage.
+ virtual bool shouldEmitStaticExternCAliases() const { return true; }
};
} // namespace CodeGen
diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp
index 85e466a..3e65f9e 100644
--- a/lib/Driver/Action.cpp
+++ b/lib/Driver/Action.cpp
@@ -1,4 +1,4 @@
-//===--- Action.cpp - Abstract compilation steps --------------------------===//
+//===- Action.cpp - Abstract compilation steps ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,16 +8,15 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Action.h"
-#include "clang/Driver/ToolChain.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Regex.h"
#include <cassert>
-using namespace clang::driver;
+#include <string>
+
+using namespace clang;
+using namespace driver;
using namespace llvm::opt;
-Action::~Action() {}
+Action::~Action() = default;
const char *Action::getClassName(ActionClass AC) {
switch (AC) {
@@ -102,7 +101,7 @@
}
if (!ActiveOffloadKindMask)
- return "";
+ return {};
std::string Res("host");
if (ActiveOffloadKindMask & OFK_Cuda)
@@ -119,11 +118,11 @@
/// for each offloading kind.
std::string
Action::GetOffloadingFileNamePrefix(OffloadKind Kind,
- llvm::StringRef NormalizedTriple,
+ StringRef NormalizedTriple,
bool CreatePrefixForHost) {
// Don't generate prefix for host actions unless required.
if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))
- return "";
+ return {};
std::string Res("-");
Res += GetOffloadKindName(Kind);
@@ -134,7 +133,7 @@
/// Return a string with the offload kind name. If that is not defined, we
/// assume 'host'.
-llvm::StringRef Action::GetOffloadKindName(OffloadKind Kind) {
+StringRef Action::GetOffloadKindName(OffloadKind Kind) {
switch (Kind) {
case OFK_None:
case OFK_Host:
@@ -153,12 +152,11 @@
void InputAction::anchor() {}
InputAction::InputAction(const Arg &_Input, types::ID _Type)
- : Action(InputClass, _Type), Input(_Input) {
-}
+ : Action(InputClass, _Type), Input(_Input) {}
void BindArchAction::anchor() {}
-BindArchAction::BindArchAction(Action *Input, llvm::StringRef ArchName)
+BindArchAction::BindArchAction(Action *Input, StringRef ArchName)
: Action(BindArchClass, Input), ArchName(ArchName) {}
void OffloadAction::anchor() {}
@@ -300,8 +298,7 @@
: Action(Kind, Input, Type) {}
JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
- : Action(Kind, Inputs, Type) {
-}
+ : Action(Kind, Inputs, Type) {}
void PreprocessJobAction::anchor() {}
@@ -341,20 +338,17 @@
void LinkJobAction::anchor() {}
LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
- : JobAction(LinkJobClass, Inputs, Type) {
-}
+ : JobAction(LinkJobClass, Inputs, Type) {}
void LipoJobAction::anchor() {}
LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
- : JobAction(LipoJobClass, Inputs, Type) {
-}
+ : JobAction(LipoJobClass, Inputs, Type) {}
void DsymutilJobAction::anchor() {}
DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
- : JobAction(DsymutilJobClass, Inputs, Type) {
-}
+ : JobAction(DsymutilJobClass, Inputs, Type) {}
void VerifyJobAction::anchor() {}
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index 645da50..5944936 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -1,4 +1,4 @@
-//===--- Compilation.cpp - Compilation Task Implementation ----------------===//
+//===- Compilation.cpp - Compilation Task Implementation ------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,26 +8,37 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Compilation.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"
+#include "clang/Driver/Util.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptSpecifier.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <string>
+#include <system_error>
+#include <utility>
-using namespace clang::driver;
using namespace clang;
+using namespace driver;
using namespace llvm::opt;
Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
InputArgList *_Args, DerivedArgList *_TranslatedArgs,
bool ContainsError)
- : TheDriver(D), DefaultToolChain(_DefaultToolChain), ActiveOffloadMask(0u),
- Args(_Args), TranslatedArgs(_TranslatedArgs), ForDiagnostics(false),
- ContainsError(ContainsError) {
+ : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
+ TranslatedArgs(_TranslatedArgs), ContainsError(ContainsError) {
// The offloading host toolchain is the default toolchain.
OrderedOffloadingToolchains.insert(
std::make_pair(Action::OFK_Host, &DefaultToolChain));
@@ -74,9 +85,8 @@
}
// Add allocated arguments to the final DAL.
- for (auto ArgPtr : AllocatedArgs) {
+ for (auto ArgPtr : AllocatedArgs)
Entry->AddSynthesizedArg(ArgPtr);
- }
}
return *Entry;
@@ -105,7 +115,7 @@
// so we don't need to check again.
if (IssueErrors)
- getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
+ getDriver().Diag(diag::err_drv_unable_to_remove_file)
<< EC.message();
return false;
}
@@ -115,9 +125,8 @@
bool Compilation::CleanupFileList(const ArgStringList &Files,
bool IssueErrors) const {
bool Success = true;
- for (ArgStringList::const_iterator
- it = Files.begin(), ie = Files.end(); it != ie; ++it)
- Success &= CleanupFile(*it, IssueErrors);
+ for (const auto &File: Files)
+ Success &= CleanupFile(File, IssueErrors);
return Success;
}
@@ -125,14 +134,12 @@
const JobAction *JA,
bool IssueErrors) const {
bool Success = true;
- for (ArgStringMap::const_iterator
- it = Files.begin(), ie = Files.end(); it != ie; ++it) {
-
+ for (const auto &File : Files) {
// If specified, only delete the files associated with the JobAction.
// Otherwise, delete all files in the map.
- if (JA && it->first != JA)
+ if (JA && File.first != JA)
continue;
- Success &= CleanupFile(it->second, IssueErrors);
+ Success &= CleanupFile(File.second, IssueErrors);
}
return Success;
}
@@ -151,7 +158,7 @@
llvm::sys::fs::F_Append |
llvm::sys::fs::F_Text);
if (EC) {
- getDriver().Diag(clang::diag::err_drv_cc_print_options_failure)
+ getDriver().Diag(diag::err_drv_cc_print_options_failure)
<< EC.message();
FailingCommand = &C;
delete OS;
@@ -173,7 +180,7 @@
int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
if (!Error.empty()) {
assert(Res && "Error string set with 0 result code!");
- getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
+ getDriver().Diag(diag::err_drv_command_failure) << Error;
}
if (Res)
@@ -186,7 +193,6 @@
static bool ActionFailed(const Action *A,
const FailingCommandList &FailingCommands) {
-
if (FailingCommands.empty())
return false;
@@ -200,7 +206,7 @@
if (A == &(CI.second->getSource()))
return true;
- for (const Action *AI : A->inputs())
+ for (const auto *AI : A->inputs())
if (ActionFailed(AI, FailingCommands))
return true;
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 4712daf..92fb8f0 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -1474,11 +1474,11 @@
// deterministic order. We could sort in any way, but we chose
// case-insensitive sorting for consistency with the -help option
// which prints out options in the case-insensitive alphabetical order.
- std::sort(SuggestedCompletions.begin(), SuggestedCompletions.end(),
- [](StringRef A, StringRef B) {
- if (int X = A.compare_lower(B))
- return X < 0;
- return A.compare(B) > 0;
+ llvm::sort(SuggestedCompletions.begin(), SuggestedCompletions.end(),
+ [](StringRef A, StringRef B) {
+ if (int X = A.compare_lower(B))
+ return X < 0;
+ return A.compare(B) > 0;
});
llvm::outs() << llvm::join(SuggestedCompletions, "\n") << '\n';
@@ -2171,7 +2171,7 @@
break;
CudaDeviceActions[I] = C.getDriver().ConstructPhaseAction(
- C, Args, Ph, CudaDeviceActions[I]);
+ C, Args, Ph, CudaDeviceActions[I], Action::OFK_Cuda);
if (Ph == phases::Assemble)
break;
@@ -3011,8 +3011,9 @@
Args.ClaimAllArgs(options::OPT_cuda_compile_host_device);
}
-Action *Driver::ConstructPhaseAction(Compilation &C, const ArgList &Args,
- phases::ID Phase, Action *Input) const {
+Action *Driver::ConstructPhaseAction(
+ Compilation &C, const ArgList &Args, phases::ID Phase, Action *Input,
+ Action::OffloadKind TargetDeviceOffloadKind) const {
llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
// Some types skip the assembler phase (e.g., llvm-bc), but we can't
@@ -3074,7 +3075,7 @@
return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
}
case phases::Backend: {
- if (isUsingLTO()) {
+ if (isUsingLTO() && TargetDeviceOffloadKind == Action::OFK_None) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
return C.MakeAction<BackendJobAction>(Input, Output);
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index 765c057..df08ba3 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -1,4 +1,4 @@
-//===--- Job.cpp - Command to Execute -------------------------------------===//
+//===- Job.cpp - Command to Execute ---------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -9,14 +9,14 @@
#include "clang/Driver/Job.h"
#include "InputInfo.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
@@ -24,17 +24,21 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
#include <cassert>
-using namespace clang::driver;
-using llvm::raw_ostream;
-using llvm::StringRef;
-using llvm::ArrayRef;
+#include <cstddef>
+#include <string>
+#include <system_error>
+#include <utility>
+
+using namespace clang;
+using namespace driver;
Command::Command(const Action &Source, const Tool &Creator,
const char *Executable, const ArgStringList &Arguments,
ArrayRef<InputInfo> Inputs)
: Source(Source), Creator(Creator), Executable(Executable),
- Arguments(Arguments), ResponseFile(nullptr) {
+ Arguments(Arguments) {
for (const auto &II : Inputs)
if (II.isFilename())
InputFilenames.push_back(II.getFilename());
@@ -67,7 +71,7 @@
.Cases("-iframework", "-include-pch", true)
.Default(false);
if (IsInclude)
- return HaveCrashVFS ? false : true;
+ return !HaveCrashVFS;
// The remaining flags are treated as a single argument.
@@ -86,7 +90,7 @@
StringRef FlagRef(Flag);
IsInclude = FlagRef.startswith("-F") || FlagRef.startswith("-I");
if (IsInclude)
- return HaveCrashVFS ? false : true;
+ return !HaveCrashVFS;
if (FlagRef.startswith("-fmodules-cache-path="))
return true;
@@ -104,7 +108,7 @@
// Quote and escape. This isn't really complete, but good enough.
OS << '"';
- for (const char c : Arg) {
+ for (const auto c : Arg) {
if (c == '"' || c == '\\' || c == '$')
OS << '\\';
OS << c;
@@ -115,7 +119,7 @@
void Command::writeResponseFile(raw_ostream &OS) const {
// In a file list, we only write the set of inputs to the response file
if (Creator.getResponseFilesSupport() == Tool::RF_FileList) {
- for (const char *Arg : InputFileList) {
+ for (const auto *Arg : InputFileList) {
OS << Arg << '\n';
}
return;
@@ -124,7 +128,7 @@
// In regular response files, we send all arguments to the response file.
// Wrapping all arguments in double quotes ensures that both Unix tools and
// Windows tools understand the response file.
- for (const char *Arg : Arguments) {
+ for (const auto *Arg : Arguments) {
OS << '"';
for (; *Arg != '\0'; Arg++) {
@@ -150,13 +154,13 @@
}
llvm::StringSet<> Inputs;
- for (const char *InputName : InputFileList)
+ for (const auto *InputName : InputFileList)
Inputs.insert(InputName);
Out.push_back(Executable);
// In a file list, build args vector ignoring parameters that will go in the
// response file (elements of the InputFileList vector)
bool FirstInput = true;
- for (const char *Arg : Arguments) {
+ for (const auto *Arg : Arguments) {
if (Inputs.count(Arg) == 0) {
Out.push_back(Arg);
} else if (FirstInput) {
@@ -174,6 +178,7 @@
llvm::SmallVectorImpl<llvm::SmallString<128>> &IncFlags) {
using namespace llvm;
using namespace sys;
+
auto getAbsPath = [](StringRef InInc, SmallVectorImpl<char> &OutInc) -> bool {
if (path::is_absolute(InInc)) // Nothing to do here...
return false;
@@ -212,8 +217,8 @@
OS << ' ';
printArg(OS, Executable, /*Quote=*/true);
- llvm::ArrayRef<const char *> Args = Arguments;
- llvm::SmallVector<const char *, 128> ArgsRespFile;
+ ArrayRef<const char *> Args = Arguments;
+ SmallVector<const char *, 128> ArgsRespFile;
if (ResponseFile != nullptr) {
buildArgvForResponseFile(ArgsRespFile);
Args = ArrayRef<const char *>(ArgsRespFile).slice(1); // no executable name
diff --git a/lib/Driver/Multilib.cpp b/lib/Driver/Multilib.cpp
index 16a8160..178a60d 100644
--- a/lib/Driver/Multilib.cpp
+++ b/lib/Driver/Multilib.cpp
@@ -1,4 +1,4 @@
-//===--- Multilib.cpp - Multilib Implementation ---------------------------===//
+//===- Multilib.cpp - Multilib Implementation -----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,25 +8,22 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Multilib.h"
-#include "ToolChains/CommonArgs.h"
-#include "clang/Driver/Options.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Option/OptTable.h"
-#include "llvm/Option/Option.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
-#include "llvm/Support/YAMLParser.h"
-#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
+#include <string>
-using namespace clang::driver;
using namespace clang;
-using namespace llvm::opt;
+using namespace driver;
using namespace llvm::sys;
/// normalize Segment to "/foo/bar" or "".
@@ -34,7 +31,7 @@
StringRef seg = Segment;
// Prune trailing "/" or "./"
- while (1) {
+ while (true) {
StringRef last = path::filename(seg);
if (last != ".")
break;
@@ -42,7 +39,7 @@
}
if (seg.empty() || seg == "/") {
- Segment = "";
+ Segment.clear();
return;
}
@@ -198,8 +195,8 @@
Multilibs.insert(Multilibs.end(), MultilibSegments.begin(),
MultilibSegments.end());
else {
- for (const Multilib &New : MultilibSegments) {
- for (const Multilib &Base : *this) {
+ for (const auto &New : MultilibSegments) {
+ for (const auto &Base : *this) {
Multilib MO = compose(Base, New);
if (MO.isValid())
Composed.push_back(MO);
@@ -262,7 +259,7 @@
return false;
}, Multilibs);
- if (Filtered.size() == 0)
+ if (Filtered.empty())
return false;
if (Filtered.size() == 1) {
M = Filtered[0];
@@ -279,7 +276,7 @@
}
void MultilibSet::print(raw_ostream &OS) const {
- for (const Multilib &M : *this)
+ for (const auto &M : *this)
OS << M << "\n";
}
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index 06e04b1..23aa6b6 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -30,7 +30,7 @@
NeedsUbsanCxxRt = Vptr | CFI,
NotAllowedWithTrap = Vptr,
NotAllowedWithMinimalRuntime = Vptr,
- RequiresPIE = DataFlow | Scudo,
+ RequiresPIE = DataFlow | HWAddress | Scudo,
NeedsUnwindTables = Address | HWAddress | Thread | Memory | DataFlow,
SupportsCoverage = Address | HWAddress | KernelAddress | Memory | Leak |
Undefined | Integer | Nullability | DataFlow | Fuzzer |
@@ -332,8 +332,31 @@
}
}
+ std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
+ std::make_pair(Address, Thread | Memory),
+ std::make_pair(Thread, Memory),
+ std::make_pair(Leak, Thread | Memory),
+ std::make_pair(KernelAddress, Address | Leak | Thread | Memory),
+ std::make_pair(HWAddress, Address | Thread | Memory | KernelAddress),
+ std::make_pair(Efficiency, Address | HWAddress | Leak | Thread | Memory |
+ KernelAddress),
+ std::make_pair(Scudo, Address | HWAddress | Leak | Thread | Memory |
+ KernelAddress | Efficiency),
+ std::make_pair(SafeStack, Address | HWAddress | Leak | Thread | Memory |
+ KernelAddress | Efficiency)};
+
// Enable toolchain specific default sanitizers if not explicitly disabled.
- Kinds |= TC.getDefaultSanitizers() & ~AllRemove;
+ SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
+
+ // Disable default sanitizers that are incompatible with explicitly requested
+ // ones.
+ for (auto G : IncompatibleGroups) {
+ SanitizerMask Group = G.first;
+ if ((Default & Group) && (Kinds & G.second))
+ Default &= ~Group;
+ }
+
+ Kinds |= Default;
// We disable the vptr sanitizer if it was enabled by group expansion but RTTI
// is disabled.
@@ -369,18 +392,6 @@
}
// Warn about incompatible groups of sanitizers.
- std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
- std::make_pair(Address, Thread | Memory),
- std::make_pair(Thread, Memory),
- std::make_pair(Leak, Thread | Memory),
- std::make_pair(KernelAddress, Address | Leak | Thread | Memory),
- std::make_pair(HWAddress, Address | Thread | Memory | KernelAddress),
- std::make_pair(Efficiency, Address | HWAddress | Leak | Thread | Memory |
- KernelAddress),
- std::make_pair(Scudo, Address | HWAddress | Leak | Thread | Memory |
- KernelAddress | Efficiency),
- std::make_pair(SafeStack, Address | HWAddress | Leak | Thread | Memory |
- KernelAddress | Efficiency)};
for (auto G : IncompatibleGroups) {
SanitizerMask Group = G.first;
if (Kinds & Group) {
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index ea0554b..645f357 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -1,4 +1,4 @@
-//===--- ToolChain.cpp - Collections of tools for one platform ------------===//
+//===- ToolChain.cpp - Collections of tools for one platform --------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,33 +8,45 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/ToolChain.h"
-#include "ToolChains/CommonArgs.h"
+#include "InputInfo.h"
#include "ToolChains/Arch/ARM.h"
#include "ToolChains/Clang.h"
#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/VersionTuple.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/XRayArgs.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/TargetRegistry.h"
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <string>
-using namespace clang::driver;
-using namespace clang::driver::tools;
using namespace clang;
+using namespace driver;
+using namespace tools;
using namespace llvm;
using namespace llvm::opt;
@@ -74,8 +86,7 @@
ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
const ArgList &Args)
: D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
- CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)),
- EffectiveTriple() {
+ CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) {
std::string CandidateLibPath = getArchSpecificLibPath();
if (getVFS().exists(CandidateLibPath))
getFilePaths().push_back(CandidateLibPath);
@@ -87,8 +98,7 @@
EffectiveTriple.setEnvironment(Env);
}
-ToolChain::~ToolChain() {
-}
+ToolChain::~ToolChain() = default;
vfs::FileSystem &ToolChain::getVFS() const { return getDriver().getVFS(); }
@@ -115,12 +125,15 @@
}
namespace {
+
struct DriverSuffix {
const char *Suffix;
const char *ModeFlag;
};
-const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
+} // namespace
+
+static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
// A list of known driver suffixes. Suffixes are compared against the
// program name in order. If there is a match, the frontend type is updated as
// necessary by applying the ModeFlag.
@@ -151,7 +164,7 @@
/// Normalize the program name from argv[0] by stripping the file extension if
/// present and lower-casing the string on Windows.
-std::string normalizeProgramName(llvm::StringRef Argv0) {
+static std::string normalizeProgramName(llvm::StringRef Argv0) {
std::string ProgName = llvm::sys::path::stem(Argv0);
#ifdef LLVM_ON_WIN32
// Transform to lowercase for case insensitive file systems.
@@ -160,7 +173,7 @@
return ProgName;
}
-const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
+static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
// Try to infer frontend type and default target from the program name by
// comparing it against DriverSuffixes in order.
@@ -185,7 +198,6 @@
}
return DS;
}
-} // anonymous namespace
ParsedClangName
ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
@@ -193,7 +205,7 @@
size_t SuffixPos;
const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);
if (!DS)
- return ParsedClangName();
+ return {};
size_t SuffixEnd = SuffixPos + strlen(DS->Suffix);
size_t LastComponent = ProgName.rfind('-', SuffixPos);
@@ -589,7 +601,7 @@
// CollectArgsForIntegratedAssembler but we can't change the ArchName at
// that point. There is no assembler equivalent of -mno-thumb, -marm, or
// -mno-arm.
- for (const Arg *A :
+ for (const auto *A :
Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
for (StringRef Value : A->getValues()) {
if (Value == "-mthumb")
@@ -707,7 +719,7 @@
/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
ArgStringList &CC1Args,
ArrayRef<StringRef> Paths) {
- for (StringRef Path : Paths) {
+ for (const auto Path : Paths) {
CC1Args.push_back("-internal-isystem");
CC1Args.push_back(DriverArgs.MakeArgString(Path));
}
@@ -789,7 +801,9 @@
SanitizerMask ToolChain::getSupportedSanitizers() const {
// Return sanitizers which don't require runtime support and are not
// platform dependent.
+
using namespace SanitizerKind;
+
SanitizerMask Res = (Undefined & ~Vptr & ~Function) | (CFI & ~CFIICall) |
CFICastStrict | UnsignedIntegerOverflow | Nullability |
LocalBounds;
@@ -871,7 +885,7 @@
bool Modified = false;
// Handle -Xopenmp-target flags
- for (Arg *A : Args) {
+ for (auto *A : Args) {
// Exclude flags which may only apply to the host toolchain.
// Do not exclude flags when the host triple (AuxTriple)
// matches the current toolchain triple. If it is not present
diff --git a/lib/Driver/ToolChains/Arch/RISCV.cpp b/lib/Driver/ToolChains/Arch/RISCV.cpp
index 2b4ae88..9bcc262 100644
--- a/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -24,15 +24,66 @@
std::vector<StringRef> &Features) {
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
StringRef MArch = A->getValue();
- // TODO: handle rv64
- std::pair<StringRef, StringRef> MArchSplit = StringRef(MArch).split("rv32");
- if (!MArchSplit.second.size())
+ if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) ||
+ (MArch.size() < 5)) {
+ // ISA string must begin with rv32 or rv64.
+ // TODO: Improve diagnostic message.
+ D.Diag(diag::err_drv_invalid_arch_name) << MArch;
return;
+ }
- for (char c : MArchSplit.second) {
+ // The canonical order specified in ISA manual.
+ // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
+ StringRef StdExts = "mafdc";
+
+ bool HasF = false, HasD = false;
+ char Baseline = MArch[4];
+
+ // TODO: Add 'e' once backend supported.
+ switch (Baseline) {
+ default:
+ // First letter should be 'e', 'i' or 'g'.
+ // TODO: Improve diagnostic message.
+ D.Diag(diag::err_drv_invalid_arch_name) << MArch;
+ return;
+ case 'i':
+ break;
+ case 'g':
+ // g = imafd
+ StdExts = StdExts.drop_front(4);
+ Features.push_back("+m");
+ Features.push_back("+a");
+ Features.push_back("+f");
+ Features.push_back("+d");
+ HasF = true;
+ HasD = true;
+ break;
+ }
+
+ auto StdExtsItr = StdExts.begin();
+ // Skip rvxxx
+ StringRef Exts = MArch.substr(5);
+
+ for (char c : Exts) {
+ // Check ISA extensions are specified in the canonical order.
+ while (StdExtsItr != StdExts.end() && *StdExtsItr != c)
+ ++StdExtsItr;
+
+ if (StdExtsItr == StdExts.end()) {
+ // TODO: Improve diagnostic message.
+ D.Diag(diag::err_drv_invalid_arch_name) << MArch;
+ return;
+ }
+
+ // Move to next char to prevent repeated letter.
+ ++StdExtsItr;
+
+ // The order is OK, then push it into features.
switch (c) {
- case 'i':
- break;
+ default:
+ // TODO: Improve diagnostic message.
+ D.Diag(diag::err_drv_invalid_arch_name) << MArch;
+ return;
case 'm':
Features.push_back("+m");
break;
@@ -41,15 +92,25 @@
break;
case 'f':
Features.push_back("+f");
+ HasF = true;
break;
case 'd':
Features.push_back("+d");
+ HasD = true;
break;
case 'c':
Features.push_back("+c");
break;
}
}
+
+ // Dependency check
+ // It's illegal to specify the 'd' (double-precision floating point)
+ // extension without also specifying the 'f' (single precision
+ // floating-point) extension.
+ // TODO: Improve diagnostic message.
+ if (HasD && !HasF)
+ D.Diag(diag::err_drv_invalid_arch_name) << MArch;
}
}
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index 3c08e88..a86c537 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -3249,7 +3249,11 @@
if (JA.getType() == types::TY_LLVM_BC)
CmdArgs.push_back("-emit-llvm-uselists");
- if (D.isUsingLTO()) {
+ // Device-side jobs do not support LTO.
+ bool isDeviceOffloadAction = !(JA.isDeviceOffloading(Action::OFK_None) ||
+ JA.isDeviceOffloading(Action::OFK_Host));
+
+ if (D.isUsingLTO() && !isDeviceOffloadAction) {
Args.AddLastArg(CmdArgs, options::OPT_flto, options::OPT_flto_EQ);
// The Darwin and PS4 linkers currently use the legacy LTO API, which
@@ -3455,7 +3459,7 @@
options::OPT_fno_optimize_sibling_calls))
CmdArgs.push_back("-mdisable-tail-calls");
if (Args.hasFlag(options::OPT_fno_escaping_block_tail_calls,
- options::OPT_fescaping_block_tail_calls))
+ options::OPT_fescaping_block_tail_calls, false))
CmdArgs.push_back("-fno-escaping-block-tail-calls");
Args.AddLastArg(CmdArgs, options::OPT_ffine_grained_bitfield_accesses,
diff --git a/lib/Driver/ToolChains/Cuda.cpp b/lib/Driver/ToolChains/Cuda.cpp
index 86a1184..64e62cb 100644
--- a/lib/Driver/ToolChains/Cuda.cpp
+++ b/lib/Driver/ToolChains/Cuda.cpp
@@ -21,6 +21,7 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include <system_error>
@@ -580,6 +581,44 @@
CC1Args.push_back("-target-feature");
CC1Args.push_back("+ptx42");
}
+
+ if (DeviceOffloadingKind == Action::OFK_OpenMP) {
+ SmallVector<StringRef, 8> LibraryPaths;
+ // Add path to lib and/or lib64 folders.
+ SmallString<256> DefaultLibPath =
+ llvm::sys::path::parent_path(getDriver().Dir);
+ llvm::sys::path::append(DefaultLibPath,
+ Twine("lib") + CLANG_LIBDIR_SUFFIX);
+ LibraryPaths.emplace_back(DefaultLibPath.c_str());
+
+ // Add user defined library paths from LIBRARY_PATH.
+ llvm::Optional<std::string> LibPath =
+ llvm::sys::Process::GetEnv("LIBRARY_PATH");
+ if (LibPath) {
+ SmallVector<StringRef, 8> Frags;
+ const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
+ llvm::SplitString(*LibPath, Frags, EnvPathSeparatorStr);
+ for (StringRef Path : Frags)
+ LibraryPaths.emplace_back(Path.trim());
+ }
+
+ std::string LibOmpTargetName =
+ "libomptarget-nvptx-" + GpuArch.str() + ".bc";
+ bool FoundBCLibrary = false;
+ for (StringRef LibraryPath : LibraryPaths) {
+ SmallString<128> LibOmpTargetFile(LibraryPath);
+ llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName);
+ if (llvm::sys::fs::exists(LibOmpTargetFile)) {
+ CC1Args.push_back("-mlink-cuda-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile));
+ FoundBCLibrary = true;
+ break;
+ }
+ }
+ if (!FoundBCLibrary)
+ getDriver().Diag(diag::warn_drv_omp_offload_target_missingbcruntime)
+ << LibOmpTargetName;
+ }
}
void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
diff --git a/lib/Driver/ToolChains/Fuchsia.cpp b/lib/Driver/ToolChains/Fuchsia.cpp
index 5f4995c..1b22309 100644
--- a/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/lib/Driver/ToolChains/Fuchsia.cpp
@@ -280,7 +280,12 @@
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
Res |= SanitizerKind::Fuzzer;
+ Res |= SanitizerKind::FuzzerNoLink;
Res |= SanitizerKind::SafeStack;
Res |= SanitizerKind::Scudo;
return Res;
}
+
+SanitizerMask Fuchsia::getDefaultSanitizers() const {
+ return SanitizerKind::SafeStack;
+}
diff --git a/lib/Driver/ToolChains/Fuchsia.h b/lib/Driver/ToolChains/Fuchsia.h
index 6f438de..e61eddc 100644
--- a/lib/Driver/ToolChains/Fuchsia.h
+++ b/lib/Driver/ToolChains/Fuchsia.h
@@ -60,10 +60,15 @@
return llvm::DebuggerKind::GDB;
}
+ unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
+ return 2; // SSPStrong
+ }
+
std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const override;
SanitizerMask getSupportedSanitizers() const override;
+ SanitizerMask getDefaultSanitizers() const override;
RuntimeLibType
GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp
index 041bf78..56c0cdf 100644
--- a/lib/Driver/ToolChains/Gnu.cpp
+++ b/lib/Driver/ToolChains/Gnu.cpp
@@ -307,7 +307,8 @@
}
static bool getPIE(const ArgList &Args, const toolchains::Linux &ToolChain) {
- if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_static))
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_r))
return false;
Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie,
diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp
index 4e9d0f1..aa9fefc 100644
--- a/lib/Driver/ToolChains/Linux.cpp
+++ b/lib/Driver/ToolChains/Linux.cpp
@@ -879,7 +879,7 @@
Res |= SanitizerKind::Function;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsMIPS || IsArmArch)
Res |= SanitizerKind::Scudo;
- if (IsAArch64)
+ if (IsX86_64 || IsAArch64)
Res |= SanitizerKind::HWAddress;
return Res;
}
diff --git a/lib/Edit/Commit.cpp b/lib/Edit/Commit.cpp
index 0cc152b..afc1a13 100644
--- a/lib/Edit/Commit.cpp
+++ b/lib/Edit/Commit.cpp
@@ -1,4 +1,4 @@
-//===----- Commit.cpp - A unit of edits -----------------------------------===//
+//===- Commit.cpp - A unit of edits ---------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,10 +8,16 @@
//===----------------------------------------------------------------------===//
#include "clang/Edit/Commit.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/EditedSource.h"
+#include "clang/Edit/FileOffset.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PPConditionalDirectiveRecord.h"
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <utility>
using namespace clang;
using namespace edit;
@@ -36,9 +42,9 @@
}
Commit::Commit(EditedSource &Editor)
- : SourceMgr(Editor.getSourceManager()), LangOpts(Editor.getLangOpts()),
- PPRec(Editor.getPPCondDirectiveRecord()),
- Editor(&Editor), IsCommitable(true) { }
+ : SourceMgr(Editor.getSourceManager()), LangOpts(Editor.getLangOpts()),
+ PPRec(Editor.getPPCondDirectiveRecord()),
+ Editor(&Editor) {}
bool Commit::insert(SourceLocation loc, StringRef text,
bool afterToken, bool beforePreviousInsertions) {
@@ -276,14 +282,12 @@
}
bool Commit::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) {
- for (unsigned i = 0, e = CachedEdits.size(); i != e; ++i) {
- Edit &act = CachedEdits[i];
+ for (const auto &act : CachedEdits)
if (act.Kind == Act_Remove) {
if (act.Offset.getFID() == Offs.getFID() &&
Offs > act.Offset && Offs < act.Offset.getWithOffset(act.Length))
return false; // position has been removed.
}
- }
if (!Editor)
return true;
@@ -338,6 +342,7 @@
SourceLocation *MacroBegin) const {
return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, LangOpts, MacroBegin);
}
+
bool Commit::isAtEndOfMacroExpansion(SourceLocation loc,
SourceLocation *MacroEnd) const {
return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd);
diff --git a/lib/Edit/EditedSource.cpp b/lib/Edit/EditedSource.cpp
index 444d039..0ff2447f 100644
--- a/lib/Edit/EditedSource.cpp
+++ b/lib/Edit/EditedSource.cpp
@@ -1,4 +1,4 @@
-//===----- EditedSource.cpp - Collection of source edits ------------------===//
+//===- EditedSource.cpp - Collection of source edits ----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -9,12 +9,21 @@
#include "clang/Edit/EditedSource.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/EditsReceiver.h"
+#include "clang/Edit/FileOffset.h"
#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include <algorithm>
+#include <cassert>
+#include <tuple>
+#include <utility>
using namespace clang;
using namespace edit;
@@ -269,9 +278,11 @@
struct CommitRAII {
EditedSource &Editor;
+
CommitRAII(EditedSource &Editor) : Editor(Editor) {
Editor.startingCommit();
}
+
~CommitRAII() {
Editor.finishedCommit();
}
diff --git a/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp
index 72d2078..b603067 100644
--- a/lib/Format/BreakableToken.cpp
+++ b/lib/Format/BreakableToken.cpp
@@ -89,9 +89,9 @@
// Do not split before a number followed by a dot: this would be interpreted
// as a numbered list, which would prevent re-flowing in subsequent passes.
- static llvm::Regex kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\.");
+ static auto *const kNumberedListRegexp = new llvm::Regex("^[1-9][0-9]?\\.");
if (SpaceOffset != StringRef::npos &&
- kNumberedListRegexp.match(Text.substr(SpaceOffset).ltrim(Blanks)))
+ kNumberedListRegexp->match(Text.substr(SpaceOffset).ltrim(Blanks)))
SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
if (SpaceOffset == StringRef::npos ||
@@ -284,10 +284,9 @@
Content = Content.trim(Blanks);
// Lines starting with '@' commonly have special meaning.
// Lines starting with '-', '-#', '+' or '*' are bulleted/numbered lists.
- static const SmallVector<StringRef, 8> kSpecialMeaningPrefixes = {
- "@", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* "};
bool hasSpecialMeaningPrefix = false;
- for (StringRef Prefix : kSpecialMeaningPrefixes) {
+ for (StringRef Prefix :
+ {"@", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* "}) {
if (Content.startswith(Prefix)) {
hasSpecialMeaningPrefix = true;
break;
@@ -297,9 +296,9 @@
// Numbered lists may also start with a number followed by '.'
// To avoid issues if a line starts with a number which is actually the end
// of a previous line, we only consider numbers with up to 2 digits.
- static llvm::Regex kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\. ");
+ static auto *const kNumberedListRegexp = new llvm::Regex("^[1-9][0-9]?\\. ");
hasSpecialMeaningPrefix =
- hasSpecialMeaningPrefix || kNumberedListRegexp.match(Content);
+ hasSpecialMeaningPrefix || kNumberedListRegexp->match(Content);
// Simple heuristic for what to reflow: content should contain at least two
// characters and either the first or second character must be
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index d28254d..167b882 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -889,19 +889,27 @@
if ((PreviousNonComment &&
(PreviousNonComment->ClosesTemplateDeclaration ||
PreviousNonComment->isOneOf(
- TT_AttributeParen, TT_FunctionAnnotationRParen, TT_JavaAnnotation,
- TT_LeadingJavaAnnotation))) ||
+ TT_AttributeParen, TT_AttributeSquare, TT_FunctionAnnotationRParen,
+ TT_JavaAnnotation, TT_LeadingJavaAnnotation))) ||
(!Style.IndentWrappedFunctionNames &&
NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName)))
return std::max(State.Stack.back().LastSpace, State.Stack.back().Indent);
if (NextNonComment->is(TT_SelectorName)) {
if (!State.Stack.back().ObjCSelectorNameFound) {
- if (NextNonComment->LongestObjCSelectorName == 0)
- return State.Stack.back().Indent;
- return (Style.IndentWrappedFunctionNames
- ? std::max(State.Stack.back().Indent,
- State.FirstIndent + Style.ContinuationIndentWidth)
- : State.Stack.back().Indent) +
+ unsigned MinIndent = State.Stack.back().Indent;
+ if (Style.IndentWrappedFunctionNames)
+ MinIndent = std::max(MinIndent,
+ State.FirstIndent + Style.ContinuationIndentWidth);
+ // If LongestObjCSelectorName is 0, we are indenting the first
+ // part of an ObjC selector (or a selector component which is
+ // not colon-aligned due to block formatting).
+ //
+ // Otherwise, we are indenting a subsequent part of an ObjC
+ // selector which should be colon-aligned to the longest
+ // component of the ObjC selector.
+ //
+ // In either case, we want to respect Style.IndentWrappedFunctionNames.
+ return MinIndent +
std::max(NextNonComment->LongestObjCSelectorName,
NextNonComment->ColumnWidth) -
NextNonComment->ColumnWidth;
@@ -1385,9 +1393,10 @@
// violate the rectangle rule and visually flows within the surrounding
// source.
bool ContentStartsOnNewline = Current.TokenText[OldPrefixSize] == '\n';
- unsigned NextStartColumn = ContentStartsOnNewline
- ? State.Stack.back().Indent + Style.IndentWidth
- : FirstStartColumn;
+ unsigned NextStartColumn =
+ ContentStartsOnNewline
+ ? State.Stack.back().NestedBlockIndent + Style.IndentWidth
+ : FirstStartColumn;
// The last start column is the column the raw string suffix starts if it is
// put on a newline.
@@ -1399,7 +1408,7 @@
// indent.
unsigned LastStartColumn = Current.NewlinesBefore
? FirstStartColumn - NewPrefixSize
- : State.Stack.back().Indent;
+ : State.Stack.back().NestedBlockIndent;
std::pair<tooling::Replacements, unsigned> Fixes = internal::reformat(
RawStringStyle, RawText, {tooling::Range(0, RawText.size())},
@@ -1453,7 +1462,13 @@
unsigned RawLastLineEndColumn = getLastLineEndColumn(
*NewCode, FirstStartColumn, Style.TabWidth, Encoding);
State.Column = RawLastLineEndColumn + NewSuffixSize;
- return Fixes.second;
+ // Since we're updating the column to after the raw string literal here, we
+ // have to manually add the penalty for the prefix R"delim( over the column
+ // limit.
+ unsigned PrefixExcessCharacters =
+ StartColumn + NewPrefixSize > Style.ColumnLimit ?
+ StartColumn + NewPrefixSize - Style.ColumnLimit : 0;
+ return Fixes.second + PrefixExcessCharacters * Style.PenaltyExcessCharacter;
}
unsigned ContinuationIndenter::addMultilineToken(const FormatToken &Current,
@@ -1479,7 +1494,7 @@
// Compute the raw string style to use in case this is a raw string literal
// that can be reformatted.
auto RawStringStyle = getRawStringStyle(Current, State);
- if (RawStringStyle) {
+ if (RawStringStyle && !Current.Finalized) {
Penalty = reformatRawStringLiteral(Current, State, *RawStringStyle, DryRun);
} else if (Current.IsMultiline && Current.isNot(TT_BlockComment)) {
// Don't break multi-line tokens other than block comments and raw string
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 5807db9..f7e74ab 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -511,7 +511,7 @@
namespace format {
const std::error_category &getParseCategory() {
- static ParseErrorCategory C;
+ static const ParseErrorCategory C{};
return C;
}
std::error_code make_error_code(ParseError e) {
@@ -766,6 +766,7 @@
GoogleStyle.JavaScriptWrapImports = false;
} else if (Language == FormatStyle::LK_Proto) {
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+ GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
GoogleStyle.SpacesInContainerLiterals = false;
GoogleStyle.Cpp11BracedListStyle = false;
// This affects protocol buffer options specifications and text protos.
@@ -1448,6 +1449,19 @@
// Keep this array sorted, since we are binary searching over it.
static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
"CGFloat",
+ "CGPoint",
+ "CGPointMake",
+ "CGPointZero",
+ "CGRect",
+ "CGRectEdge",
+ "CGRectInfinite",
+ "CGRectMake",
+ "CGRectNull",
+ "CGRectZero",
+ "CGSize",
+ "CGSizeMake",
+ "CGVector",
+ "CGVectorMake",
"NSAffineTransform",
"NSArray",
"NSAttributedString",
@@ -1496,10 +1510,12 @@
"NSURLQueryItem",
"NSUUID",
"NSValue",
+ "UIImage",
+ "UIView",
};
- for (auto &Line : AnnotatedLines) {
- for (FormatToken *FormatTok = Line->First; FormatTok;
+ for (auto Line : AnnotatedLines) {
+ for (const FormatToken *FormatTok = Line->First; FormatTok;
FormatTok = FormatTok->Next) {
if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
(FormatTok->isObjCAtKeyword(tok::objc_interface) ||
@@ -1519,6 +1535,8 @@
TT_ObjCMethodSpecifier, TT_ObjCProperty)) {
return true;
}
+ if (guessIsObjC(Line->Children, Keywords))
+ return true;
}
}
return false;
diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index 550bdcc..a1e8ecb 100644
--- a/lib/Format/FormatToken.h
+++ b/lib/Format/FormatToken.h
@@ -29,7 +29,9 @@
#define LIST_TOKEN_TYPES \
TYPE(ArrayInitializerLSquare) \
TYPE(ArraySubscriptLSquare) \
+ TYPE(AttributeColon) \
TYPE(AttributeParen) \
+ TYPE(AttributeSquare) \
TYPE(BinaryOperator) \
TYPE(BitFieldColon) \
TYPE(BlockComment) \
diff --git a/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp
index 199d297..e06e26f 100644
--- a/lib/Format/FormatTokenLexer.cpp
+++ b/lib/Format/FormatTokenLexer.cpp
@@ -38,7 +38,7 @@
for (const std::string &ForEachMacro : Style.ForEachMacros)
ForEachMacros.push_back(&IdentTable.get(ForEachMacro));
- std::sort(ForEachMacros.begin(), ForEachMacros.end());
+ llvm::sort(ForEachMacros.begin(), ForEachMacros.end());
}
ArrayRef<FormatToken *> FormatTokenLexer::lex() {
@@ -691,7 +691,9 @@
}
}
- if (Style.Language == FormatStyle::LK_JavaScript &&
+ if ((Style.Language == FormatStyle::LK_JavaScript ||
+ Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto) &&
Tok.is(tok::char_constant)) {
Tok.Tok.setKind(tok::string_literal);
}
diff --git a/lib/Format/NamespaceEndCommentsFixer.cpp b/lib/Format/NamespaceEndCommentsFixer.cpp
index df99bb2..ee11959 100644
--- a/lib/Format/NamespaceEndCommentsFixer.cpp
+++ b/lib/Format/NamespaceEndCommentsFixer.cpp
@@ -27,13 +27,6 @@
// Short namespaces don't need an end comment.
static const int kShortNamespaceMaxLines = 1;
-// Matches a valid namespace end comment.
-// Valid namespace end comments don't need to be edited.
-static llvm::Regex kNamespaceCommentPattern =
- llvm::Regex("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
- "namespace( +([a-zA-Z0-9:_]+))?\\.? *(\\*/)?$",
- llvm::Regex::IgnoreCase);
-
// Computes the name of a namespace given the namespace token.
// Returns "" for anonymous namespace.
std::string computeName(const FormatToken *NamespaceTok) {
@@ -67,8 +60,15 @@
bool validEndComment(const FormatToken *RBraceTok, StringRef NamespaceName) {
assert(hasEndComment(RBraceTok));
const FormatToken *Comment = RBraceTok->Next;
+
+ // Matches a valid namespace end comment.
+ // Valid namespace end comments don't need to be edited.
+ static llvm::Regex *const NamespaceCommentPattern =
+ new llvm::Regex("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
+ "namespace( +([a-zA-Z0-9:_]+))?\\.? *(\\*/)?$",
+ llvm::Regex::IgnoreCase);
SmallVector<StringRef, 7> Groups;
- if (kNamespaceCommentPattern.match(Comment->TokenText, &Groups)) {
+ if (NamespaceCommentPattern->match(Comment->TokenText, &Groups)) {
StringRef NamespaceNameInComment = Groups.size() > 5 ? Groups[5] : "";
// Anonymous namespace comments must not mention a namespace name.
if (NamespaceName.empty() && !NamespaceNameInComment.empty())
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 013a77b..24494b6 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -141,10 +141,7 @@
Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr;
bool StartsObjCMethodExpr = false;
- if (CurrentToken->is(tok::caret)) {
- // (^ can start a block type.
- Left->Type = TT_ObjCBlockLParen;
- } else if (FormatToken *MaybeSel = Left->Previous) {
+ if (FormatToken *MaybeSel = Left->Previous) {
// @selector( starts a selector.
if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous &&
MaybeSel->Previous->is(tok::at)) {
@@ -210,8 +207,16 @@
Left->Type = TT_ObjCMethodExpr;
}
+ // MightBeFunctionType and ProbablyFunctionType are used for
+ // function pointer and reference types as well as Objective-C
+ // block types:
+ //
+ // void (*FunctionPointer)(void);
+ // void (&FunctionReference)(void);
+ // void (^ObjCBlock)(void);
bool MightBeFunctionType = !Contexts[Contexts.size() - 2].IsExpression;
- bool ProbablyFunctionType = CurrentToken->isOneOf(tok::star, tok::amp);
+ bool ProbablyFunctionType =
+ CurrentToken->isOneOf(tok::star, tok::amp, tok::caret);
bool HasMultipleLines = false;
bool HasMultipleParametersOnALine = false;
bool MightBeObjCForRangeLoop =
@@ -248,7 +253,8 @@
if (MightBeFunctionType && ProbablyFunctionType && CurrentToken->Next &&
(CurrentToken->Next->is(tok::l_paren) ||
(CurrentToken->Next->is(tok::l_square) && Line.MustBeDeclaration)))
- Left->Type = TT_FunctionTypeLParen;
+ Left->Type = Left->Next->is(tok::caret) ? TT_ObjCBlockLParen
+ : TT_FunctionTypeLParen;
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
@@ -328,13 +334,40 @@
return false;
}
+ bool isCpp11AttributeSpecifier(const FormatToken &Tok) {
+ if (!Style.isCpp() || !Tok.startsSequence(tok::l_square, tok::l_square))
+ return false;
+ const FormatToken *AttrTok = Tok.Next->Next;
+ if (!AttrTok)
+ return false;
+ // C++17 '[[using ns: foo, bar(baz, blech)]]'
+ // We assume nobody will name an ObjC variable 'using'.
+ if (AttrTok->startsSequence(tok::kw_using, tok::identifier, tok::colon))
+ return true;
+ if (AttrTok->isNot(tok::identifier))
+ return false;
+ while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) {
+ // ObjC message send. We assume nobody will use : in a C++11 attribute
+ // specifier parameter, although this is technically valid:
+ // [[foo(:)]]
+ if (AttrTok->is(tok::colon) ||
+ AttrTok->startsSequence(tok::identifier, tok::identifier))
+ return false;
+ if (AttrTok->is(tok::ellipsis))
+ return true;
+ AttrTok = AttrTok->Next;
+ }
+ return AttrTok && AttrTok->startsSequence(tok::r_square, tok::r_square);
+ }
+
bool parseSquare() {
if (!CurrentToken)
return false;
// A '[' could be an index subscript (after an identifier or after
// ')' or ']'), it could be the start of an Objective-C method
- // expression, or it could the start of an Objective-C array literal.
+ // expression, it could the start of an Objective-C array literal,
+ // or it could be a C++ attribute specifier [[foo::bar]].
FormatToken *Left = CurrentToken->Previous;
Left->ParentBracket = Contexts.back().ContextKind;
FormatToken *Parent = Left->getPreviousNonComment();
@@ -347,8 +380,11 @@
(Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
Contexts.back().InTemplateArgument);
+ bool IsCpp11AttributeSpecifier = isCpp11AttributeSpecifier(*Left) ||
+ Contexts.back().InCpp11AttributeSpecifier;
+
bool StartsObjCMethodExpr =
- !CppArrayTemplates && Style.isCpp() &&
+ !CppArrayTemplates && Style.isCpp() && !IsCpp11AttributeSpecifier &&
Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
CurrentToken->isNot(tok::l_brace) &&
(!Parent ||
@@ -365,6 +401,8 @@
} else if (Left->is(TT_Unknown)) {
if (StartsObjCMethodExpr) {
Left->Type = TT_ObjCMethodExpr;
+ } else if (IsCpp11AttributeSpecifier) {
+ Left->Type = TT_AttributeSquare;
} else if (Style.Language == FormatStyle::LK_JavaScript && Parent &&
Contexts.back().ContextKind == tok::l_brace &&
Parent->isOneOf(tok::l_brace, tok::comma)) {
@@ -432,11 +470,14 @@
Contexts.back().IsExpression = false;
Contexts.back().ColonIsObjCMethodExpr = StartsObjCMethodExpr;
+ Contexts.back().InCpp11AttributeSpecifier = IsCpp11AttributeSpecifier;
while (CurrentToken) {
if (CurrentToken->is(tok::r_square)) {
- if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) &&
- Left->is(TT_ObjCMethodExpr)) {
+ if (IsCpp11AttributeSpecifier)
+ CurrentToken->Type = TT_AttributeSquare;
+ else if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) &&
+ Left->is(TT_ObjCMethodExpr)) {
// An ObjC method call is rarely followed by an open parenthesis.
// FIXME: Do we incorrectly label ":" with this?
StartsObjCMethodExpr = false;
@@ -466,8 +507,14 @@
if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace))
return false;
if (CurrentToken->is(tok::colon)) {
- if (Left->isOneOf(TT_ArraySubscriptLSquare,
- TT_DesignatedInitializerLSquare)) {
+ if (IsCpp11AttributeSpecifier &&
+ CurrentToken->endsSequence(tok::colon, tok::identifier,
+ tok::kw_using)) {
+ // Remember that this is a [[using ns: foo]] C++ attribute, so we
+ // don't add a space before the colon (unlike other colons).
+ CurrentToken->Type = TT_AttributeColon;
+ } else if (Left->isOneOf(TT_ArraySubscriptLSquare,
+ TT_DesignatedInitializerLSquare)) {
Left->Type = TT_ObjCMethodExpr;
StartsObjCMethodExpr = true;
// ParameterCount might have been set to 1 before expression was
@@ -654,7 +701,8 @@
else
Tok->Type = TT_InheritanceColon;
} else if (Tok->Previous->is(tok::identifier) && Tok->Next &&
- Tok->Next->isOneOf(tok::r_paren, tok::comma)) {
+ (Tok->Next->isOneOf(tok::r_paren, tok::comma) ||
+ Tok->Next->startsSequence(tok::identifier, tok::colon))) {
// This handles a special macro in ObjC code where selectors including
// the colon are passed as macro arguments.
Tok->Type = TT_ObjCMethodExpr;
@@ -1088,6 +1136,7 @@
bool InInheritanceList = false;
bool CaretFound = false;
bool IsForEachMacro = false;
+ bool InCpp11AttributeSpecifier = false;
};
/// \brief Puts a new \c Context onto the stack \c Contexts for the lifetime
@@ -2124,7 +2173,7 @@
return 35;
if (!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
TT_ArrayInitializerLSquare,
- TT_DesignatedInitializerLSquare))
+ TT_DesignatedInitializerLSquare, TT_AttributeSquare))
return 500;
}
@@ -2375,11 +2424,12 @@
Style)) ||
(Style.SpacesInSquareBrackets &&
Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare,
- TT_StructuredBindingLSquare)));
+ TT_StructuredBindingLSquare)) ||
+ Right.MatchingParen->is(TT_AttributeParen));
if (Right.is(tok::l_square) &&
!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
TT_DesignatedInitializerLSquare,
- TT_StructuredBindingLSquare) &&
+ TT_StructuredBindingLSquare, TT_AttributeSquare) &&
!Left.isOneOf(tok::numeric_constant, TT_DictLiteral))
return false;
if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
@@ -2391,7 +2441,8 @@
if (Left.is(TT_BlockComment))
return !Left.TokenText.endswith("=*/");
if (Right.is(tok::l_paren)) {
- if (Left.is(tok::r_paren) && Left.is(TT_AttributeParen))
+ if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) ||
+ (Left.is(tok::r_square) && Left.is(TT_AttributeSquare)))
return true;
return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
(Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
@@ -2429,6 +2480,10 @@
return false;
if (Left.is(TT_TemplateCloser) && Right.is(tok::l_square))
return false;
+ if (Right.is(tok::r_brace) && Right.MatchingParen &&
+ Right.MatchingParen->endsSequence(TT_DictLiteral, tok::at))
+ // Objective-C dictionary literal -> no space before closing brace.
+ return false;
return true;
}
@@ -2564,8 +2619,10 @@
if (Line.Type == LT_ObjCMethodDecl) {
if (Left.is(TT_ObjCMethodSpecifier))
return true;
- if (Left.is(tok::r_paren) && Right.is(tok::identifier))
- // Don't space between ')' and <id>
+ if (Left.is(tok::r_paren) && Right.isOneOf(tok::identifier, tok::kw_new))
+ // Don't space between ')' and <id> or ')' and 'new'. 'new' is not a
+ // keyword in Objective-C, and '+ (instancetype)new;' is a standard class
+ // method declaration.
return false;
}
if (Line.Type == LT_ObjCProperty &&
@@ -2602,6 +2659,8 @@
return false;
if (Right.is(TT_DictLiteral))
return Style.SpacesInContainerLiterals;
+ if (Right.is(TT_AttributeColon))
+ return false;
return true;
}
if (Left.is(TT_UnaryOperator))
@@ -2637,7 +2696,8 @@
Style.Standard == FormatStyle::LS_Cpp03) ||
!(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
tok::kw___super, TT_TemplateCloser,
- TT_TemplateOpener));
+ TT_TemplateOpener)) ||
+ (Left.is(tok ::l_paren) && Style.SpacesInParentheses);
if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))
return Style.SpacesInAngles;
// Space before TT_StructuredBindingLSquare.
@@ -2717,7 +2777,8 @@
return true;
} else if (Style.Language == FormatStyle::LK_Cpp ||
Style.Language == FormatStyle::LK_ObjC ||
- Style.Language == FormatStyle::LK_Proto) {
+ Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto) {
if (Left.isStringLiteral() && Right.isStringLiteral())
return true;
}
@@ -2773,10 +2834,10 @@
if (Style.BreakBeforeInheritanceComma && Right.is(TT_InheritanceComma))
return true;
if (Right.is(tok::string_literal) && Right.TokenText.startswith("R\""))
- // Raw string literals are special wrt. line breaks. The author has made a
- // deliberate choice and might have aligned the contents of the string
- // literal accordingly. Thus, we try keep existing line breaks.
- return Right.NewlinesBefore > 0;
+ // Multiline raw string literals are special wrt. line breaks. The author
+ // has made a deliberate choice and might have aligned the contents of the
+ // string literal accordingly. Thus, we try keep existing line breaks.
+ return Right.IsMultiline && Right.NewlinesBefore > 0;
if ((Right.Previous->is(tok::l_brace) ||
(Right.Previous->is(tok::less) && Right.Previous->Previous &&
Right.Previous->Previous->is(tok::equal))) &&
@@ -2911,10 +2972,13 @@
if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
if ((Style.Language == FormatStyle::LK_Proto ||
Style.Language == FormatStyle::LK_TextProto) &&
- Right.isStringLiteral())
+ !Style.AlwaysBreakBeforeMultilineStrings && Right.isStringLiteral())
return false;
return true;
}
+ if (Right.is(tok::r_square) && Right.MatchingParen &&
+ Right.MatchingParen->is(TT_ProtoExtensionLSquare))
+ return false;
if (Right.is(TT_SelectorName) || (Right.is(tok::identifier) && Right.Next &&
Right.Next->is(TT_ObjCMethodExpr)))
return Left.isNot(tok::period); // FIXME: Properly parse ObjC calls.
@@ -2962,7 +3026,8 @@
return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal, tok::l_paren,
tok::less, tok::coloncolon);
- if (Right.is(tok::kw___attribute))
+ if (Right.is(tok::kw___attribute) ||
+ (Right.is(tok::l_square) && Right.is(TT_AttributeSquare)))
return true;
if (Left.is(tok::identifier) && Right.is(tok::string_literal))
@@ -3003,6 +3068,9 @@
(Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None ||
Left.getPrecedence() == prec::Assignment))
return true;
+ if ((Left.is(TT_AttributeSquare) && Right.is(tok::l_square)) ||
+ (Left.is(tok::r_square) && Right.is(TT_AttributeSquare)))
+ return false;
return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
tok::kw_class, tok::kw_struct, tok::comment) ||
Right.isMemberAccess() ||
diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp
index a5477a9..5c54080 100644
--- a/lib/Format/WhitespaceManager.cpp
+++ b/lib/Format/WhitespaceManager.cpp
@@ -90,7 +90,7 @@
if (Changes.empty())
return Replaces;
- std::sort(Changes.begin(), Changes.end(), Change::IsBeforeInFile(SourceMgr));
+ llvm::sort(Changes.begin(), Changes.end(), Change::IsBeforeInFile(SourceMgr));
calculateLineBreakInformation();
alignConsecutiveDeclarations();
alignConsecutiveAssignments();
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 473da22..1247e82 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -1,4 +1,4 @@
-//===--- ASTUnit.cpp - ASTUnit utility --------------------------*- C++ -*-===//
+//===- ASTUnit.cpp - ASTUnit utility --------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,45 +14,99 @@
#include "clang/Frontend/ASTUnit.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclVisitor.h"
-#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/CommentCommandTraits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/MemoryBufferCache.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Frontend/PrecompiledPreamble.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Lex/Token.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/CodeCompleteOptions.h"
#include "clang/Sema/Sema.h"
+#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h"
+#include "clang/Serialization/ContinuousRangeMap.h"
+#include "clang/Serialization/Module.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/DJB.h"
-#include "llvm/Support/Host.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
-#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
#include <atomic>
+#include <cassert>
+#include <cstdint>
#include <cstdio>
#include <cstdlib>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
using namespace clang;
using llvm::TimeRecord;
namespace {
+
class SimpleTimer {
bool WantTiming;
TimeRecord Start;
@@ -64,11 +118,6 @@
Start = TimeRecord::getCurrentTime();
}
- void setOutput(const Twine &Output) {
- if (WantTiming)
- this->Output = Output.str();
- }
-
~SimpleTimer() {
if (WantTiming) {
TimeRecord Elapsed = TimeRecord::getCurrentTime();
@@ -78,22 +127,29 @@
llvm::errs() << '\n';
}
}
+
+ void setOutput(const Twine &Output) {
+ if (WantTiming)
+ this->Output = Output.str();
+ }
};
- template <class T>
- std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) {
- if (!Val)
- return nullptr;
- return std::move(*Val);
- }
+} // namespace
- template <class T>
- bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
- if (!Val)
- return false;
- Output = std::move(*Val);
- return true;
- }
+template <class T>
+static std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) {
+ if (!Val)
+ return nullptr;
+ return std::move(*Val);
+}
+
+template <class T>
+static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
+ if (!Val)
+ return false;
+ Output = std::move(*Val);
+ return true;
+}
/// \brief Get a source buffer for \p MainFilePath, handling all file-to-file
/// and file-to-buffer remappings inside \p Invocation.
@@ -156,7 +212,6 @@
return nullptr;
return llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), FilePath);
}
-}
struct ASTUnit::ASTWriterData {
SmallString<128> Buffer;
@@ -183,20 +238,10 @@
static std::atomic<unsigned> ActiveASTUnitObjects;
ASTUnit::ASTUnit(bool _MainFileIsAST)
- : Reader(nullptr), HadModuleLoaderFatalFailure(false),
- OnlyLocalDecls(false), CaptureDiagnostics(false),
- MainFileIsAST(_MainFileIsAST),
- TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
- OwnsRemappedFileBuffers(true),
- NumStoredDiagnosticsFromDriver(0),
- PreambleRebuildCounter(0),
- NumWarningsInPreamble(0),
- ShouldCacheCodeCompletionResults(false),
- IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),
- CompletionCacheTopLevelHashValue(0),
- PreambleTopLevelHashValue(0),
- CurrentTopLevelHashValue(0),
- UnsafeToFree(false) {
+ : MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")),
+ ShouldCacheCodeCompletionResults(false),
+ IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),
+ UnsafeToFree(false) {
if (getenv("LIBCLANG_OBJTRACKING"))
fprintf(stderr, "+++ %u translation units\n", ++ActiveASTUnitObjects);
}
@@ -278,7 +323,7 @@
// Part of the nested-name-specifier in C++0x.
if (LangOpts.CPlusPlus11)
IsNestedNameSpecifier = true;
- } else if (const RecordDecl *Record = dyn_cast<RecordDecl>(ND)) {
+ } else if (const auto *Record = dyn_cast<RecordDecl>(ND)) {
if (Record->isUnion())
Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag);
else
@@ -319,7 +364,7 @@
ClearCachedCompletionResults();
// Gather the set of global code completions.
- typedef CodeCompletionResult Result;
+ using Result = CodeCompletionResult;
SmallVector<Result, 8> Results;
CachedCompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();
CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator);
@@ -330,7 +375,7 @@
llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel);
- for (Result &R : Results) {
+ for (auto &R : Results) {
switch (R.Kind) {
case Result::RK_Declaration: {
bool IsNestedNameSpecifier = false;
@@ -470,8 +515,8 @@
std::shared_ptr<TargetOptions> &TargetOpts;
IntrusiveRefCntPtr<TargetInfo> &Target;
unsigned &Counter;
+ bool InitializedLanguage = false;
- bool InitializedLanguage;
public:
ASTInfoCollector(Preprocessor &PP, ASTContext *Context,
HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts,
@@ -480,7 +525,7 @@
IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter)
: PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts),
LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target),
- Counter(Counter), InitializedLanguage(false) {}
+ Counter(Counter) {}
bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
bool AllowCompatibleDifferences) override {
@@ -494,16 +539,15 @@
return false;
}
- virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
- StringRef SpecificModuleCachePath,
- bool Complain) override {
+ 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 {
+ bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
+ std::string &SuggestedPredefines) override {
this->PPOpts = PPOpts;
return false;
}
@@ -557,19 +601,18 @@
}
};
- /// \brief Diagnostic consumer that saves each diagnostic it is given.
+/// \brief Diagnostic consumer that saves each diagnostic it is given.
class StoredDiagnosticConsumer : public DiagnosticConsumer {
SmallVectorImpl<StoredDiagnostic> *StoredDiags;
SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags;
- const LangOptions *LangOpts;
- SourceManager *SourceMgr;
+ const LangOptions *LangOpts = nullptr;
+ SourceManager *SourceMgr = nullptr;
public:
StoredDiagnosticConsumer(
SmallVectorImpl<StoredDiagnostic> *StoredDiags,
SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags)
- : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags),
- LangOpts(nullptr), SourceMgr(nullptr) {
+ : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags) {
assert((StoredDiags || StandaloneDiags) &&
"No output collections were passed to StoredDiagnosticConsumer.");
}
@@ -590,15 +633,15 @@
class CaptureDroppedDiagnostics {
DiagnosticsEngine &Diags;
StoredDiagnosticConsumer Client;
- DiagnosticConsumer *PreviousClient;
+ DiagnosticConsumer *PreviousClient = nullptr;
std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;
public:
- CaptureDroppedDiagnostics(bool RequestCapture, DiagnosticsEngine &Diags,
- SmallVectorImpl<StoredDiagnostic> *StoredDiags,
- SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags)
- : Diags(Diags), Client(StoredDiags, StandaloneDiags), PreviousClient(nullptr)
- {
+ CaptureDroppedDiagnostics(
+ bool RequestCapture, DiagnosticsEngine &Diags,
+ SmallVectorImpl<StoredDiagnostic> *StoredDiags,
+ SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags)
+ : Diags(Diags), Client(StoredDiags, StandaloneDiags) {
if (RequestCapture || Diags.getClient() == nullptr) {
OwningPreviousClient = Diags.takeClient();
PreviousClient = Diags.getClient();
@@ -612,7 +655,7 @@
}
};
-} // anonymous namespace
+} // namespace
static ASTUnit::StandaloneDiagnostic
makeStandaloneDiagnostic(const LangOptions &LangOpts,
@@ -634,7 +677,7 @@
}
if (StandaloneDiags) {
- llvm::Optional<StoredDiagnostic> StoredDiag = llvm::None;
+ llvm::Optional<StoredDiagnostic> StoredDiag = None;
if (!ResultDiag) {
StoredDiag.emplace(Level, Info);
ResultDiag = StoredDiag.getPointer();
@@ -693,7 +736,7 @@
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
ASTUnitCleanup(AST.get());
llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
- llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
+ llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
DiagCleanup(Diags.get());
ConfigureDiags(Diags, *AST, CaptureDiagnostics);
@@ -741,7 +784,7 @@
bool disableValid = false;
if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
disableValid = true;
- AST->Reader = new ASTReader(PP, AST->Ctx.get(), PCHContainerRdr, { },
+ AST->Reader = new ASTReader(PP, AST->Ctx.get(), PCHContainerRdr, {},
/*isysroot=*/"",
/*DisableValidation=*/disableValid,
AllowPCHWithCompilerErrors);
@@ -794,20 +837,20 @@
return AST;
}
-namespace {
-
/// \brief Add the given macro to the hash of all top-level entities.
-void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) {
+static void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) {
Hash = llvm::djbHash(MacroNameTok.getIdentifierInfo()->getName(), Hash);
}
+namespace {
+
/// \brief Preprocessor callback class that updates a hash value with the names
/// of all macros that have been defined by the translation unit.
class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {
unsigned &Hash;
public:
- explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) { }
+ explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) {}
void MacroDefined(const Token &MacroNameTok,
const MacroDirective *MD) override {
@@ -815,8 +858,10 @@
}
};
+} // namespace
+
/// \brief Add the given declaration to the hash of all top-level entities.
-void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
+static void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
if (!D)
return;
@@ -827,8 +872,8 @@
if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit()))
return;
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
- if (EnumDecl *EnumD = dyn_cast<EnumDecl>(D)) {
+ if (const auto *ND = dyn_cast<NamedDecl>(D)) {
+ if (const auto *EnumD = dyn_cast<EnumDecl>(D)) {
// For an unscoped enum include the enumerators in the hash since they
// enter the top-level namespace.
if (!EnumD->isScoped()) {
@@ -848,8 +893,8 @@
return;
}
- if (ImportDecl *ImportD = dyn_cast<ImportDecl>(D)) {
- if (Module *Mod = ImportD->getImportedModule()) {
+ if (const auto *ImportD = dyn_cast<ImportDecl>(D)) {
+ if (const Module *Mod = ImportD->getImportedModule()) {
std::string ModName = Mod->getFullModuleName();
Hash = llvm::djbHash(ModName, Hash);
}
@@ -857,13 +902,15 @@
}
}
+namespace {
+
class TopLevelDeclTrackerConsumer : public ASTConsumer {
ASTUnit &Unit;
unsigned &Hash;
public:
TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash)
- : Unit(_Unit), Hash(Hash) {
+ : Unit(_Unit), Hash(Hash) {
Hash = 0;
}
@@ -886,14 +933,14 @@
void handleFileLevelDecl(Decl *D) {
Unit.addFileLevelDecl(D);
- if (NamespaceDecl *NSD = dyn_cast<NamespaceDecl>(D)) {
+ if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {
for (auto *I : NSD->decls())
handleFileLevelDecl(I);
}
}
bool HandleTopLevelDecl(DeclGroupRef D) override {
- for (Decl *TopLevelDecl : D)
+ for (auto *TopLevelDecl : D)
handleTopLevelDecl(TopLevelDecl);
return true;
}
@@ -902,7 +949,7 @@
void HandleInterestingDecl(DeclGroupRef) override {}
void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {
- for (Decl *TopLevelDecl : D)
+ for (auto *TopLevelDecl : D)
handleTopLevelDecl(TopLevelDecl);
}
@@ -932,6 +979,7 @@
TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
bool hasCodeCompletionSupport() const override { return false; }
+
TranslationUnitKind getTranslationUnitKind() override {
return Unit.getTranslationUnitKind();
}
@@ -949,7 +997,7 @@
void AfterPCHEmitted(ASTWriter &Writer) override {
TopLevelDeclIDs.reserve(TopLevelDecls.size());
- for (Decl *D : TopLevelDecls) {
+ for (const auto *D : TopLevelDecls) {
// Invalid top-level decls may not have been serialized.
if (D->isInvalidDecl())
continue;
@@ -958,7 +1006,7 @@
}
void HandleTopLevelDecl(DeclGroupRef DG) override {
- for (Decl *D : DG) {
+ for (auto *D : DG) {
// FIXME: Currently ObjC method declarations are incorrectly being
// reported as top-level declarations, even though their DeclContext
// is the containing ObjC @interface/@implementation. This is a
@@ -981,7 +1029,7 @@
llvm::SmallVector<ASTUnit::StandaloneDiagnostic, 4> PreambleDiags;
};
-} // anonymous namespace
+} // namespace
static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) {
return StoredDiag.getLocation().isValid();
@@ -1004,7 +1052,7 @@
// been careful to make sure that the source manager's state
// before and after are identical, so that we can reuse the source
// location itself.
- for (StoredDiagnostic &SD : StoredDiagnostics) {
+ for (auto &SD : StoredDiagnostics) {
if (SD.getLocation().isValid()) {
FullSourceLoc Loc(SD.getLocation(), SM);
SD.setLocation(Loc);
@@ -1192,9 +1240,9 @@
if (OutDiag.Filename.empty())
return OutDiag;
OutDiag.LocOffset = SM.getFileOffset(FileLoc);
- for (const CharSourceRange &Range : InDiag.getRanges())
+ for (const auto &Range : InDiag.getRanges())
OutDiag.Ranges.push_back(makeStandaloneRange(Range, SM, LangOpts));
- for (const FixItHint &FixIt : InDiag.getFixIts())
+ for (const auto &FixIt : InDiag.getFixIts())
OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, FixIt));
return OutDiag;
@@ -1226,7 +1274,6 @@
const CompilerInvocation &PreambleInvocationIn,
IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild,
unsigned MaxLines) {
-
auto MainFilePath =
PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile();
std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer =
@@ -1259,6 +1306,7 @@
Preamble.reset();
PreambleDiagnostics.clear();
TopLevelDeclsInPreamble.clear();
+ PreambleSrcLocCache.clear();
PreambleRebuildCounter = 1;
}
}
@@ -1306,7 +1354,6 @@
case BuildPreambleError::CouldntCreateTargetInfo:
case BuildPreambleError::BeginSourceFileFailed:
case BuildPreambleError::CouldntEmitPCH:
- case BuildPreambleError::CouldntCreateVFSOverlay:
// These erros are more likely to repeat, retry after some period.
PreambleRebuildCounter = DefaultPreambleRebuildInterval;
return nullptr;
@@ -1344,7 +1391,7 @@
std::vector<Decl *> Resolved;
Resolved.reserve(TopLevelDeclsInPreamble.size());
ExternalASTSource &Source = *getASTContext().getExternalSource();
- for (serialization::DeclID TopLevelDecl : TopLevelDeclsInPreamble) {
+ for (const auto TopLevelDecl : TopLevelDeclsInPreamble) {
// Resolve the declaration ID to an actual declaration, possibly
// deserializing the declaration in the process.
if (Decl *D = Source.GetExternalDecl(TopLevelDecl))
@@ -1388,12 +1435,12 @@
return FE->getName();
}
- return StringRef();
+ return {};
}
StringRef ASTUnit::getASTFileName() const {
if (!isMainFileAST())
- return StringRef();
+ return {};
serialization::ModuleFile &
Mod = Reader->getModuleManager().getPrimaryModule();
@@ -1408,8 +1455,6 @@
ConfigureDiags(Diags, *AST, CaptureDiagnostics);
IntrusiveRefCntPtr<vfs::FileSystem> VFS =
createVFSFromCompilerInvocation(*CI, *Diags);
- if (!VFS)
- return nullptr;
AST->Diagnostics = Diags;
AST->FileSystemOpts = CI->getFileSystemOpts();
AST->Invocation = std::move(CI);
@@ -1460,7 +1505,7 @@
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
ASTUnitCleanup(OwnAST.get());
llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
- llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
+ llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
DiagCleanup(Diags.get());
// We'll manage file buffers ourselves.
@@ -1628,7 +1673,7 @@
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
ASTUnitCleanup(AST.get());
llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
- llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
+ llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
DiagCleanup(Diags.get());
if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
@@ -1657,11 +1702,10 @@
std::shared_ptr<CompilerInvocation> CI;
{
-
CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,
&StoredDiagnostics, nullptr);
- CI = clang::createInvocationFromCommandLine(
+ CI = createInvocationFromCommandLine(
llvm::makeArrayRef(ArgBegin, ArgEnd), Diags, VFS);
if (!CI)
return nullptr;
@@ -1688,14 +1732,14 @@
// Create the AST unit.
std::unique_ptr<ASTUnit> AST;
AST.reset(new ASTUnit(false));
+ AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
+ AST->StoredDiagnostics.swap(StoredDiagnostics);
ConfigureDiags(Diags, *AST, CaptureDiagnostics);
AST->Diagnostics = Diags;
AST->FileSystemOpts = CI->getFileSystemOpts();
if (!VFS)
VFS = vfs::getRealFileSystem();
VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
- if (!VFS)
- return nullptr;
AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
AST->PCMCache = new MemoryBufferCache;
AST->OnlyLocalDecls = OnlyLocalDecls;
@@ -1705,8 +1749,6 @@
AST->IncludeBriefCommentsInCodeCompletion
= IncludeBriefCommentsInCodeCompletion;
AST->UserFilesAreVolatile = UserFilesAreVolatile;
- AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
- AST->StoredDiagnostics.swap(StoredDiagnostics);
AST->Invocation = CI;
if (ForSerialization)
AST->WriterData.reset(new ASTWriterData(*AST->PCMCache));
@@ -1767,7 +1809,6 @@
OverrideMainBuffer =
getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);
-
// Clear out the diagnostics state.
FileMgr.reset();
getDiagnostics().Reset();
@@ -1810,6 +1851,7 @@
//----------------------------------------------------------------------------//
namespace {
+
/// \brief Code completion consumer that combines the cached code-completion
/// results from an ASTUnit with the code-completion results provided to it,
/// then passes the result on to
@@ -1821,9 +1863,8 @@
public:
AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
const CodeCompleteOptions &CodeCompleteOpts)
- : CodeCompleteConsumer(CodeCompleteOpts, Next.isOutputBinary()),
- AST(AST), Next(Next)
- {
+ : CodeCompleteConsumer(CodeCompleteOpts, Next.isOutputBinary()),
+ AST(AST), Next(Next) {
// Compute the set of contexts in which we will look when we don't have
// any information about the specific context.
NormalContexts
@@ -1865,7 +1906,8 @@
return Next.getCodeCompletionTUInfo();
}
};
-} // anonymous namespace
+
+} // namespace
/// \brief Helper function that computes which global names are hidden by the
/// local code-completion results.
@@ -1920,7 +1962,7 @@
return;
}
- typedef CodeCompletionResult Result;
+ using Result = CodeCompletionResult;
for (unsigned I = 0; I != NumResults; ++I) {
if (Results[I].Kind != Result::RK_Declaration)
continue;
@@ -1962,7 +2004,7 @@
? NormalContexts : (1LL << Context.getKind());
// Contains the set of names that are hidden by "local" completion results.
llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;
- typedef CodeCompletionResult Result;
+ using Result = CodeCompletionResult;
SmallVector<Result, 8> AllResults;
for (ASTUnit::cached_completion_iterator
C = AST.cached_completion_begin(),
@@ -2258,7 +2300,7 @@
return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS);
}
-typedef ContinuousRangeMap<unsigned, int, 2> SLocRemap;
+using SLocRemap = ContinuousRangeMap<unsigned, int, 2>;
void ASTUnit::TranslateStoredDiagnostics(
FileManager &FileMgr,
@@ -2272,7 +2314,7 @@
SmallVector<StoredDiagnostic, 4> Result;
Result.reserve(Diags.size());
- for (const StandaloneDiagnostic &SD : Diags) {
+ for (const auto &SD : Diags) {
// Rebuild the StoredDiagnostic.
if (SD.Filename.empty())
continue;
@@ -2304,7 +2346,7 @@
SmallVector<FixItHint, 2> FixIts;
FixIts.reserve(SD.FixIts.size());
- for (const StandaloneFixIt &FixIt : SD.FixIts) {
+ for (const auto &FixIt : SD.FixIts) {
FixIts.push_back(FixItHint());
FixItHint &FH = FixIts.back();
FH.CodeToInsert = FixIt.CodeToInsert;
@@ -2487,7 +2529,7 @@
FID = SourceMgr->getPreambleFileID();
if (FID.isInvalid())
- return SourceLocation();
+ return {};
return SourceMgr->getLocForEndOfFile(FID);
}
@@ -2498,7 +2540,7 @@
FID = SourceMgr->getMainFileID();
if (FID.isInvalid())
- return SourceLocation();
+ return {};
return SourceMgr->getLocForStartOfFile(FID);
}
@@ -2522,7 +2564,7 @@
if (isMainFileAST()) {
serialization::ModuleFile &
Mod = Reader->getModuleManager().getPrimaryModule();
- for (const Decl *D : Reader->getModuleFileLevelDecls(Mod)) {
+ for (const auto *D : Reader->getModuleFileLevelDecls(Mod)) {
if (!Fn(context, D))
return false;
}
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 306d7c0..a03e5df 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -302,11 +302,9 @@
FileManager *CompilerInstance::createFileManager() {
if (!hasVirtualFileSystem()) {
- if (IntrusiveRefCntPtr<vfs::FileSystem> VFS =
- createVFSFromCompilerInvocation(getInvocation(), getDiagnostics()))
- setVirtualFileSystem(VFS);
- else
- return nullptr;
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ createVFSFromCompilerInvocation(getInvocation(), getDiagnostics());
+ setVirtualFileSystem(VFS);
}
FileMgr = new FileManager(getFileSystemOpts(), VirtualFileSystem);
return FileMgr.get();
@@ -1090,6 +1088,10 @@
}),
PPOpts.Macros.end());
+ // If the original compiler invocation had -fmodule-name, pass it through.
+ Invocation->getLangOpts()->ModuleName =
+ ImportingInstance.getInvocation().getLangOpts()->ModuleName;
+
// Note the name of the module we're building.
Invocation->getLangOpts()->CurrentModule = ModuleName;
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 23f3c8f..84eee0e 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1,4 +1,4 @@
-//===--- CompilerInvocation.cpp -------------------------------------------===//
+//===- CompilerInvocation.cpp ---------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,54 +10,99 @@
#include "clang/Frontend/CompilerInvocation.h"
#include "TestModuleFileExtension.h"
#include "clang/Basic/Builtins.h"
-#include "clang/Basic/FileManager.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/CommentOptions.h"
+#include "clang/Basic/DebugInfoOptions.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h"
+#include "clang/Basic/VersionTuple.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Basic/Visibility.h"
#include "clang/Config/config.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
-#include "clang/Driver/Util.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Frontend/CommandLineSourceLoc.h"
+#include "clang/Frontend/DependencyOutputOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/LangStandard.h"
+#include "clang/Frontend/MigratorOptions.h"
+#include "clang/Frontend/PreprocessorOutputOptions.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/PreprocessorOptions.h"
-#include "clang/Serialization/ASTReader.h"
+#include "clang/Sema/CodeCompleteOptions.h"
#include "clang/Serialization/ModuleFileExtension.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Linker/Linker.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptSpecifier.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/ScopedPrinter.h"
+#include <algorithm>
#include <atomic>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
#include <memory>
-#include <sys/stat.h>
-#include <system_error>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
using namespace clang;
+using namespace driver;
+using namespace options;
+using namespace llvm::opt;
//===----------------------------------------------------------------------===//
// Initialization.
//===----------------------------------------------------------------------===//
CompilerInvocationBase::CompilerInvocationBase()
- : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()),
- DiagnosticOpts(new DiagnosticOptions()),
- HeaderSearchOpts(new HeaderSearchOptions()),
- PreprocessorOpts(new PreprocessorOptions()) {}
+ : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()),
+ DiagnosticOpts(new DiagnosticOptions()),
+ HeaderSearchOpts(new HeaderSearchOptions()),
+ PreprocessorOpts(new PreprocessorOptions()) {}
CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X)
: LangOpts(new LangOptions(*X.getLangOpts())),
@@ -66,18 +111,12 @@
HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())),
PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {}
-CompilerInvocationBase::~CompilerInvocationBase() {}
+CompilerInvocationBase::~CompilerInvocationBase() = default;
//===----------------------------------------------------------------------===//
// Deserialization (from args)
//===----------------------------------------------------------------------===//
-using namespace clang::driver;
-using namespace clang::driver::options;
-using namespace llvm::opt;
-
-//
-
static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags) {
unsigned DefaultOpt = 0;
@@ -91,7 +130,7 @@
if (A->getOption().matches(options::OPT_Ofast))
return 3;
- assert (A->getOption().matches(options::OPT_O));
+ assert(A->getOption().matches(options::OPT_O));
StringRef S(A->getValue());
if (S == "s" || S == "z" || S.empty())
@@ -125,7 +164,7 @@
static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
OptSpecifier GroupWithValue,
std::vector<std::string> &Diagnostics) {
- for (Arg *A : Args.filtered(Group)) {
+ for (auto *A : Args.filtered(Group)) {
if (A->getOption().getKind() == Option::FlagClass) {
// The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
// its name (minus the "W" or "R" at the beginning) to the warning list.
@@ -135,7 +174,7 @@
Diagnostics.push_back(A->getOption().getName().drop_front(1).rtrim("=-"));
} else {
// Otherwise, add its value (for OPT_W_Joined and similar).
- for (const char *Arg : A->getValues())
+ for (const auto *Arg : A->getValues())
Diagnostics.emplace_back(Arg);
}
}
@@ -157,7 +196,6 @@
static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
- using namespace options;
bool Success = true;
if (Arg *A = Args.getLastArg(OPT_analyzer_store)) {
StringRef Name = A->getValue();
@@ -273,31 +311,31 @@
StringRef checkerList = A->getValue();
SmallVector<StringRef, 4> checkers;
checkerList.split(checkers, ",");
- for (StringRef checker : checkers)
+ for (auto checker : checkers)
Opts.CheckersControlList.emplace_back(checker, enable);
}
// Go through the analyzer configuration options.
- for (const Arg *A : Args.filtered(OPT_analyzer_config)) {
+ for (const auto *A : Args.filtered(OPT_analyzer_config)) {
A->claim();
// We can have a list of comma separated config names, e.g:
// '-analyzer-config key1=val1,key2=val2'
StringRef configList = A->getValue();
SmallVector<StringRef, 4> configVals;
configList.split(configVals, ",");
- for (unsigned i = 0, e = configVals.size(); i != e; ++i) {
+ for (const auto &configVal : configVals) {
StringRef key, val;
- std::tie(key, val) = configVals[i].split("=");
+ std::tie(key, val) = configVal.split("=");
if (val.empty()) {
Diags.Report(SourceLocation(),
- diag::err_analyzer_config_no_value) << configVals[i];
+ diag::err_analyzer_config_no_value) << configVal;
Success = false;
break;
}
if (val.find('=') != StringRef::npos) {
Diags.Report(SourceLocation(),
diag::err_analyzer_config_multiple_values)
- << configVals[i];
+ << configVal;
Success = false;
break;
}
@@ -306,7 +344,7 @@
}
llvm::raw_string_ostream os(Opts.FullCompilerInvocation);
- for (unsigned i=0; i<Args.getNumInputArgStrings(); i++) {
+ for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {
if (i != 0)
os << " ";
os << Args.getArgString(i);
@@ -425,8 +463,7 @@
<< S;
return;
}
- CodeGenOptions::ProfileInstrKind Instrumentor =
- static_cast<CodeGenOptions::ProfileInstrKind>(I);
+ auto Instrumentor = static_cast<CodeGenOptions::ProfileInstrKind>(I);
Opts.setProfileInstr(Instrumentor);
}
@@ -451,7 +488,6 @@
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags,
const TargetOptions &TargetOpts) {
- using namespace options;
bool Success = true;
llvm::Triple Triple = llvm::Triple(TargetOpts.Triple);
@@ -597,33 +633,6 @@
if (!Opts.ProfileInstrumentUsePath.empty())
setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath);
- if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
- Opts.setClangABICompat(CodeGenOptions::ClangABI::Latest);
-
- StringRef Ver = A->getValue();
- std::pair<StringRef, StringRef> VerParts = Ver.split('.');
- unsigned Major, Minor = 0;
-
- // Check the version number is valid: either 3.x (0 <= x <= 9) or
- // y or y.0 (4 <= y <= current version).
- if (!VerParts.first.startswith("0") &&
- !VerParts.first.getAsInteger(10, Major) &&
- 3 <= Major && Major <= CLANG_VERSION_MAJOR &&
- (Major == 3 ? VerParts.second.size() == 1 &&
- !VerParts.second.getAsInteger(10, Minor)
- : VerParts.first.size() == Ver.size() ||
- VerParts.second == "0")) {
- // Got a valid version number.
- if (Major == 3 && Minor <= 8)
- Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver3_8);
- else if (Major <= 4)
- Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver4);
- } else if (Ver != "latest") {
- Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue();
- }
- }
-
Opts.CoverageMapping =
Args.hasFlag(OPT_fcoverage_mapping, OPT_fno_coverage_mapping, false);
Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping);
@@ -853,7 +862,8 @@
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)) {
+ for (auto *A :
+ Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) {
CodeGenOptions::BitcodeFileToLink F;
F.Filename = A->getValue();
if (A->getOption().matches(OPT_mlink_cuda_bitcode)) {
@@ -1065,7 +1075,6 @@
static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
ArgList &Args) {
- using namespace options;
Opts.OutputFile = Args.getLastArgValue(OPT_dependency_file);
Opts.Targets = Args.getAllArgValues(OPT_MT);
Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps);
@@ -1085,7 +1094,7 @@
// we let make / ninja to know about this implicit dependency.
Opts.ExtraDeps = Args.getAllArgValues(OPT_fdepfile_entry);
// Only the -fmodule-file=<file> form.
- for (const Arg *A : Args.filtered(OPT_fmodule_file)) {
+ for (const auto *A : Args.filtered(OPT_fmodule_file)) {
StringRef Val = A->getValue();
if (Val.find('=') == StringRef::npos)
Opts.ExtraDeps.push_back(Val);
@@ -1102,7 +1111,7 @@
Colors_Off,
Colors_Auto
} ShowColors = DefaultColor ? Colors_Auto : Colors_Off;
- for (Arg *A : Args) {
+ for (auto *A : Args) {
const Option &O = A->getOption();
if (O.matches(options::OPT_fcolor_diagnostics) ||
O.matches(options::OPT_fdiagnostics_color)) {
@@ -1148,7 +1157,6 @@
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
DiagnosticsEngine *Diags,
bool DefaultDiagColor, bool DefaultShowOpt) {
- using namespace options;
bool Success = true;
Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file);
@@ -1243,7 +1251,7 @@
Success = false;
}
else
- std::sort(Opts.VerifyPrefixes.begin(), Opts.VerifyPrefixes.end());
+ llvm::sort(Opts.VerifyPrefixes.begin(), Opts.VerifyPrefixes.end());
DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=",
Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ),
@@ -1315,7 +1323,6 @@
static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags,
bool &IsHeaderFile) {
- using namespace options;
Opts.ProgramAction = frontend::ParseSyntaxOnly;
if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
switch (A->getOption().getID()) {
@@ -1399,7 +1406,7 @@
Opts.ActionName = A->getValue();
}
Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin);
- for (const Arg *AA : Args.filtered(OPT_plugin_arg))
+ for (const auto *AA : Args.filtered(OPT_plugin_arg))
Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));
for (const std::string &Arg :
@@ -1452,7 +1459,7 @@
Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex;
Opts.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file);
// Only the -fmodule-file=<file> form.
- for (const Arg *A : Args.filtered(OPT_fmodule_file)) {
+ for (const auto *A : Args.filtered(OPT_fmodule_file)) {
StringRef Val = A->getValue();
if (Val.find('=') == StringRef::npos)
Opts.ModuleFiles.push_back(Val);
@@ -1640,7 +1647,6 @@
static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
const std::string &WorkingDir) {
- using namespace options;
Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/");
Opts.Verbose = Args.hasArg(OPT_v);
Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc);
@@ -1663,12 +1669,12 @@
Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path);
// Only the -fmodule-file=<name>=<file> form.
- for (const Arg *A : Args.filtered(OPT_fmodule_file)) {
+ for (const auto *A : Args.filtered(OPT_fmodule_file)) {
StringRef Val = A->getValue();
if (Val.find('=') != StringRef::npos)
Opts.PrebuiltModuleFiles.insert(Val.split('='));
}
- for (const Arg *A : Args.filtered(OPT_fprebuilt_module_path))
+ for (const auto *A : Args.filtered(OPT_fprebuilt_module_path))
Opts.AddPrebuiltModulePath(A->getValue());
Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
Opts.ModulesHashContent = Args.hasArg(OPT_fmodules_hash_content);
@@ -1689,7 +1695,7 @@
if (const Arg *A = Args.getLastArg(OPT_fmodule_format_EQ))
Opts.ModuleFormat = A->getValue();
- for (const Arg *A : Args.filtered(OPT_fmodules_ignore_macro)) {
+ for (const auto *A : Args.filtered(OPT_fmodules_ignore_macro)) {
StringRef MacroDef = A->getValue();
Opts.ModulesIgnoreMacros.insert(
llvm::CachedHashString(MacroDef.split('=').first));
@@ -1699,7 +1705,7 @@
bool IsIndexHeaderMap = false;
bool IsSysrootSpecified =
Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
- for (const Arg *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) {
+ for (const auto *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) {
if (A->getOption().matches(OPT_index_header_map)) {
// -index-header-map applies to the next -I or -F.
IsIndexHeaderMap = true;
@@ -1726,7 +1732,7 @@
// Add -iprefix/-iwithprefix/-iwithprefixbefore options.
StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
- for (const Arg *A :
+ for (const auto *A :
Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) {
if (A->getOption().matches(OPT_iprefix))
Prefix = A->getValue();
@@ -1736,31 +1742,31 @@
Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true);
}
- for (const Arg *A : Args.filtered(OPT_idirafter))
+ for (const auto *A : Args.filtered(OPT_idirafter))
Opts.AddPath(A->getValue(), frontend::After, false, true);
- for (const Arg *A : Args.filtered(OPT_iquote))
+ for (const auto *A : Args.filtered(OPT_iquote))
Opts.AddPath(A->getValue(), frontend::Quoted, false, true);
- for (const Arg *A : Args.filtered(OPT_isystem, OPT_iwithsysroot))
+ for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot))
Opts.AddPath(A->getValue(), frontend::System, false,
!A->getOption().matches(OPT_iwithsysroot));
- for (const Arg *A : Args.filtered(OPT_iframework))
+ for (const auto *A : Args.filtered(OPT_iframework))
Opts.AddPath(A->getValue(), frontend::System, true, true);
- for (const Arg *A : Args.filtered(OPT_iframeworkwithsysroot))
+ for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot))
Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true,
/*IgnoreSysRoot=*/false);
// Add the paths for the various language specific isystem flags.
- for (const Arg *A : Args.filtered(OPT_c_isystem))
+ for (const auto *A : Args.filtered(OPT_c_isystem))
Opts.AddPath(A->getValue(), frontend::CSystem, false, true);
- for (const Arg *A : Args.filtered(OPT_cxx_isystem))
+ for (const auto *A : Args.filtered(OPT_cxx_isystem))
Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true);
- for (const Arg *A : Args.filtered(OPT_objc_isystem))
+ for (const auto *A : Args.filtered(OPT_objc_isystem))
Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true);
- for (const Arg *A : Args.filtered(OPT_objcxx_isystem))
+ for (const auto *A : Args.filtered(OPT_objcxx_isystem))
Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true);
// Add the internal paths from a driver that detects standard include paths.
- for (const Arg *A :
+ for (const auto *A :
Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) {
frontend::IncludeDirGroup Group = frontend::System;
if (A->getOption().matches(OPT_internal_externc_isystem))
@@ -1769,12 +1775,12 @@
}
// Add the path prefixes which are implicitly treated as being system headers.
- for (const Arg *A :
+ for (const auto *A :
Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix))
Opts.AddSystemHeaderPrefix(
A->getValue(), A->getOption().matches(OPT_system_header_prefix));
- for (const Arg *A : Args.filtered(OPT_ivfsoverlay))
+ for (const auto *A : Args.filtered(OPT_ivfsoverlay))
Opts.AddVFSOverlayFile(A->getValue());
}
@@ -1809,18 +1815,30 @@
break;
case InputKind::Asm:
case InputKind::C:
+#if defined(CLANG_DEFAULT_STD_C)
+ LangStd = CLANG_DEFAULT_STD_C;
+#else
// The PS4 uses C99 as the default C standard.
if (T.isPS4())
LangStd = LangStandard::lang_gnu99;
else
LangStd = LangStandard::lang_gnu11;
+#endif
break;
case InputKind::ObjC:
+#if defined(CLANG_DEFAULT_STD_C)
+ LangStd = CLANG_DEFAULT_STD_C;
+#else
LangStd = LangStandard::lang_gnu11;
+#endif
break;
case InputKind::CXX:
case InputKind::ObjCXX:
+#if defined(CLANG_DEFAULT_STD_CXX)
+ LangStd = CLANG_DEFAULT_STD_CXX;
+#else
LangStd = LangStandard::lang_gnucxx14;
+#endif
break;
case InputKind::RenderScript:
LangStd = LangStandard::lang_c99;
@@ -2030,6 +2048,12 @@
}
}
+ if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
+ StringRef Name = A->getValue();
+ if (Name == "full" || Name == "branch") {
+ Opts.CFProtectionBranch = 1;
+ }
+ }
// -cl-std only applies for OpenCL language standards.
// Override the -std option in this case.
if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
@@ -2354,10 +2378,11 @@
Opts.DebuggerCastResultToId = Args.hasArg(OPT_fdebugger_cast_result_to_id);
Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal);
Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack);
- Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name_EQ);
+ Opts.ModuleName = Args.getLastArgValue(OPT_fmodule_name_EQ);
+ Opts.CurrentModule = Opts.ModuleName;
Opts.AppExt = Args.hasArg(OPT_fapplication_extension);
Opts.ModuleFeatures = Args.getAllArgValues(OPT_fmodule_feature);
- std::sort(Opts.ModuleFeatures.begin(), Opts.ModuleFeatures.end());
+ llvm::sort(Opts.ModuleFeatures.begin(), Opts.ModuleFeatures.end());
Opts.NativeHalfType |= Args.hasArg(OPT_fnative_half_type);
Opts.NativeHalfArgsAndReturns |= Args.hasArg(OPT_fnative_half_arguments_and_returns);
// Enable HalfArgsAndReturns if present in Args or if NativeHalfArgsAndReturns
@@ -2489,7 +2514,7 @@
// Add unsupported host targets here:
case llvm::Triple::nvptx:
case llvm::Triple::nvptx64:
- Diags.Report(clang::diag::err_drv_omp_host_target_not_supported)
+ Diags.Report(diag::err_drv_omp_host_target_not_supported)
<< TargetOpts.Triple;
break;
}
@@ -2517,7 +2542,7 @@
TT.getArch() == llvm::Triple::nvptx64 ||
TT.getArch() == llvm::Triple::x86 ||
TT.getArch() == llvm::Triple::x86_64))
- Diags.Report(clang::diag::err_drv_invalid_omp_target) << A->getValue(i);
+ Diags.Report(diag::err_drv_invalid_omp_target) << A->getValue(i);
else
Opts.OMPTargetTriples.push_back(TT);
}
@@ -2528,7 +2553,7 @@
if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) {
Opts.OMPHostIRFile = A->getValue();
if (!llvm::sys::fs::exists(Opts.OMPHostIRFile))
- Diags.Report(clang::diag::err_drv_omp_host_ir_file_not_found)
+ Diags.Report(diag::err_drv_omp_host_ir_file_not_found)
<< Opts.OMPHostIRFile;
}
@@ -2618,6 +2643,33 @@
// -fallow-editor-placeholders
Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders);
+
+ if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
+ Opts.setClangABICompat(LangOptions::ClangABI::Latest);
+
+ StringRef Ver = A->getValue();
+ std::pair<StringRef, StringRef> VerParts = Ver.split('.');
+ unsigned Major, Minor = 0;
+
+ // Check the version number is valid: either 3.x (0 <= x <= 9) or
+ // y or y.0 (4 <= y <= current version).
+ if (!VerParts.first.startswith("0") &&
+ !VerParts.first.getAsInteger(10, Major) &&
+ 3 <= Major && Major <= CLANG_VERSION_MAJOR &&
+ (Major == 3 ? VerParts.second.size() == 1 &&
+ !VerParts.second.getAsInteger(10, Minor)
+ : VerParts.first.size() == Ver.size() ||
+ VerParts.second == "0")) {
+ // Got a valid version number.
+ if (Major == 3 && Minor <= 8)
+ Opts.setClangABICompat(LangOptions::ClangABI::Ver3_8);
+ else if (Major <= 4)
+ Opts.setClangABICompat(LangOptions::ClangABI::Ver4);
+ } else if (Ver != "latest") {
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue();
+ }
+ }
}
static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
@@ -2665,7 +2717,6 @@
static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags,
frontend::ActionKind Action) {
- using namespace options;
Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch);
Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth);
if (const Arg *A = Args.getLastArg(OPT_token_cache))
@@ -2678,7 +2729,7 @@
Opts.AllowPCHWithCompilerErrors = Args.hasArg(OPT_fallow_pch_with_errors);
Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls);
- for (const Arg *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
+ for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());
if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
@@ -2698,7 +2749,7 @@
}
// Add macros from the command line.
- for (const Arg *A : Args.filtered(OPT_D, OPT_U)) {
+ for (const auto *A : Args.filtered(OPT_D, OPT_U)) {
if (A->getOption().matches(OPT_D))
Opts.addMacroDef(A->getValue());
else
@@ -2708,13 +2759,13 @@
Opts.MacroIncludes = Args.getAllArgValues(OPT_imacros);
// Add the ordered list of -includes.
- for (const Arg *A : Args.filtered(OPT_include))
+ for (const auto *A : Args.filtered(OPT_include))
Opts.Includes.emplace_back(A->getValue());
- for (const Arg *A : Args.filtered(OPT_chain_include))
+ for (const auto *A : Args.filtered(OPT_chain_include))
Opts.ChainedIncludes.emplace_back(A->getValue());
- for (const Arg *A : Args.filtered(OPT_remap_file)) {
+ for (const auto *A : Args.filtered(OPT_remap_file)) {
std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');
if (Split.second.empty()) {
@@ -2748,8 +2799,6 @@
static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
ArgList &Args,
frontend::ActionKind Action) {
- using namespace options;
-
if (isStrictlyPreprocessorAction(Action))
Opts.ShowCPP = !Args.hasArg(OPT_dM);
else
@@ -2767,7 +2816,6 @@
static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
- using namespace options;
Opts.ABI = Args.getLastArgValue(OPT_target_abi);
if (Arg *A = Args.getLastArg(OPT_meabi)) {
StringRef Value = A->getValue();
@@ -2818,7 +2866,7 @@
}
// Issue errors on unknown arguments.
- for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
+ for (const auto *A : Args.filtered(OPT_UNKNOWN)) {
auto ArgString = A->getAsString(Args);
std::string Nearest;
if (Opts->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
@@ -2933,29 +2981,26 @@
// Extend the signature with the target options.
code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU,
TargetOpts->ABI);
- for (unsigned i = 0, n = TargetOpts->FeaturesAsWritten.size(); i != n; ++i)
- code = hash_combine(code, TargetOpts->FeaturesAsWritten[i]);
+ for (const auto &FeatureAsWritten : TargetOpts->FeaturesAsWritten)
+ code = hash_combine(code, FeatureAsWritten);
// Extend the signature with preprocessor options.
const PreprocessorOptions &ppOpts = getPreprocessorOpts();
const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
code = hash_combine(code, ppOpts.UsePredefines, ppOpts.DetailedRecord);
- for (std::vector<std::pair<std::string, bool/*isUndef*/>>::const_iterator
- I = getPreprocessorOpts().Macros.begin(),
- IEnd = getPreprocessorOpts().Macros.end();
- I != IEnd; ++I) {
+ for (const auto &I : getPreprocessorOpts().Macros) {
// If we're supposed to ignore this macro for the purposes of modules,
// don't put it into the hash.
if (!hsOpts.ModulesIgnoreMacros.empty()) {
// Check whether we're ignoring this macro.
- StringRef MacroDef = I->first;
+ StringRef MacroDef = I.first;
if (hsOpts.ModulesIgnoreMacros.count(
llvm::CachedHashString(MacroDef.split('=').first)))
continue;
}
- code = hash_combine(code, I->first, I->second);
+ code = hash_combine(code, I.first, I.second);
}
// Extend the signature with the sysroot and other header search options.
@@ -2988,8 +3033,6 @@
return llvm::APInt(64, code).toString(36, /*Signed=*/false);
}
-namespace clang {
-
template<typename IntTy>
static IntTy getLastArgIntValueImpl(const ArgList &Args, OptSpecifier Id,
IntTy Default,
@@ -3005,6 +3048,7 @@
return Res;
}
+namespace clang {
// Declared in clang/Frontend/Utils.h.
int getLastArgIntValue(const ArgList &Args, OptSpecifier Id, int Default,
@@ -3049,22 +3093,22 @@
IntrusiveRefCntPtr<vfs::OverlayFileSystem> Overlay(
new vfs::OverlayFileSystem(BaseFS));
// earlier vfs files are on the bottom
- for (const std::string &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
+ for (const auto &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
BaseFS->getBufferForFile(File);
if (!Buffer) {
Diags.Report(diag::err_missing_vfs_overlay_file) << File;
- return IntrusiveRefCntPtr<vfs::FileSystem>();
+ continue;
}
IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getVFSFromYAML(
std::move(Buffer.get()), /*DiagHandler*/ nullptr, File);
- if (!FS.get()) {
+ if (FS)
+ Overlay->pushOverlay(FS);
+ else
Diags.Report(diag::err_invalid_vfs_overlay) << File;
- return IntrusiveRefCntPtr<vfs::FileSystem>();
- }
- Overlay->pushOverlay(FS);
}
return Overlay;
}
-} // end namespace clang
+
+} // namespace clang
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp
index e326384..b6c9564 100644
--- a/lib/Frontend/DiagnosticRenderer.cpp
+++ b/lib/Frontend/DiagnosticRenderer.cpp
@@ -1,4 +1,4 @@
-//===--- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing --------------===//
+//===- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing ----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,24 +8,34 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/DiagnosticRenderer.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/EditedSource.h"
#include "clang/Edit/EditsReceiver.h"
#include "clang/Lex/Lexer.h"
-#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/ErrorHandling.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <utility>
+
using namespace clang;
DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts,
DiagnosticOptions *DiagOpts)
- : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
+ : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
-DiagnosticRenderer::~DiagnosticRenderer() {}
+DiagnosticRenderer::~DiagnosticRenderer() = default;
namespace {
@@ -34,24 +44,24 @@
public:
FixitReceiver(SmallVectorImpl<FixItHint> &MergedFixits)
- : MergedFixits(MergedFixits) { }
+ : MergedFixits(MergedFixits) {}
+
void insert(SourceLocation loc, StringRef text) override {
MergedFixits.push_back(FixItHint::CreateInsertion(loc, text));
}
+
void replace(CharSourceRange range, StringRef text) override {
MergedFixits.push_back(FixItHint::CreateReplacement(range, text));
}
};
-}
+} // namespace
static void mergeFixits(ArrayRef<FixItHint> FixItHints,
const SourceManager &SM, const LangOptions &LangOpts,
SmallVectorImpl<FixItHint> &MergedFixits) {
edit::Commit commit(SM, LangOpts);
- for (ArrayRef<FixItHint>::const_iterator
- I = FixItHints.begin(), E = FixItHints.end(); I != E; ++I) {
- const FixItHint &Hint = *I;
+ for (const auto &Hint : FixItHints)
if (Hint.CodeToInsert.empty()) {
if (Hint.InsertFromRange.isValid())
commit.insertFromRange(Hint.RemoveRange.getBegin(),
@@ -67,7 +77,6 @@
commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert,
/*afterToken=*/false, Hint.BeforePreviousInsertions);
}
- }
edit::EditedSource Editor(SM, LangOpts);
if (Editor.commit(commit)) {
@@ -100,11 +109,9 @@
FixItHints = MergedFixits;
}
- for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(),
- E = FixItHints.end();
- I != E; ++I)
- if (I->RemoveRange.isValid())
- MutableRanges.push_back(I->RemoveRange);
+ for (const auto &Hint : FixItHints)
+ if (Hint.RemoveRange.isValid())
+ MutableRanges.push_back(Hint.RemoveRange);
FullSourceLoc UnexpandedLoc = Loc;
@@ -134,7 +141,6 @@
endDiagnostic(D, Level);
}
-
void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
Diag.getRanges(), Diag.getFixIts(),
@@ -243,10 +249,10 @@
/// on demand.
void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) {
ModuleBuildStack Stack = SM.getModuleBuildStack();
- for (unsigned I = 0, N = Stack.size(); I != N; ++I) {
- emitBuildingModuleLocation(Stack[I].second, Stack[I].second.getPresumedLoc(
- DiagOpts->ShowPresumedLoc),
- Stack[I].first);
+ for (const auto &I : Stack) {
+ emitBuildingModuleLocation(I.second, I.second.getPresumedLoc(
+ DiagOpts->ShowPresumedLoc),
+ I.first);
}
}
@@ -261,7 +267,7 @@
if (MacroFileID == CaretFileID)
return Loc;
if (!Loc.isMacroID())
- return SourceLocation();
+ return {};
SourceLocation MacroLocation, MacroArgLocation;
@@ -318,8 +324,8 @@
SmallVector<FileID, 4> EndArgExpansions;
getMacroArgExpansionFileIDs(Begin, BeginArgExpansions, /*IsBegin=*/true, SM);
getMacroArgExpansionFileIDs(End, EndArgExpansions, /*IsBegin=*/false, SM);
- std::sort(BeginArgExpansions.begin(), BeginArgExpansions.end());
- std::sort(EndArgExpansions.begin(), EndArgExpansions.end());
+ llvm::sort(BeginArgExpansions.begin(), BeginArgExpansions.end());
+ llvm::sort(EndArgExpansions.begin(), EndArgExpansions.end());
std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(),
EndArgExpansions.begin(), EndArgExpansions.end(),
std::back_inserter(CommonArgExpansions));
@@ -342,11 +348,12 @@
const SourceManager *SM = &CaretLoc.getManager();
- for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
- if (I->isInvalid()) continue;
+ for (const auto &Range : Ranges) {
+ if (Range.isInvalid())
+ continue;
- SourceLocation Begin = I->getBegin(), End = I->getEnd();
- bool IsTokenRange = I->isTokenRange();
+ SourceLocation Begin = Range.getBegin(), End = Range.getEnd();
+ bool IsTokenRange = Range.isTokenRange();
FileID BeginFileID = SM->getFileID(Begin);
FileID EndFileID = SM->getFileID(End);
@@ -466,8 +473,9 @@
/// Count all valid ranges.
unsigned ValidCount = 0;
- for (auto I : Ranges)
- if (I.isValid()) ValidCount++;
+ for (const auto &Range : Ranges)
+ if (Range.isValid())
+ ValidCount++;
if (ValidCount > SpellingRanges.size())
return false;
@@ -480,10 +488,9 @@
if (!Loc.isMacroArgExpansion(&ArgumentLoc))
return false;
- for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) {
- if (!checkRangeForMacroArgExpansion(*I, Loc.getManager(), ArgumentLoc))
+ for (const auto &Range : SpellingRanges)
+ if (!checkRangeForMacroArgExpansion(Range, Loc.getManager(), ArgumentLoc))
return false;
- }
return true;
}
@@ -562,7 +569,7 @@
emitSingleMacroExpansion(*I, Level, Ranges);
}
-DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}
+DiagnosticNoteRenderer::~DiagnosticNoteRenderer() = default;
void DiagnosticNoteRenderer::emitIncludeLocation(FullSourceLoc Loc,
PresumedLoc PLoc) {
diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
index dca4345..0744d44 100644
--- a/lib/Frontend/FrontendOptions.cpp
+++ b/lib/Frontend/FrontendOptions.cpp
@@ -1,4 +1,4 @@
-//===--- FrontendOptions.cpp ----------------------------------------------===//
+//===- FrontendOptions.cpp ------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -9,6 +9,7 @@
#include "clang/Frontend/FrontendOptions.h"
#include "llvm/ADT/StringSwitch.h"
+
using namespace clang;
InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) {
diff --git a/lib/Frontend/PrecompiledPreamble.cpp b/lib/Frontend/PrecompiledPreamble.cpp
index d761f6e..ddd7bda 100644
--- a/lib/Frontend/PrecompiledPreamble.cpp
+++ b/lib/Frontend/PrecompiledPreamble.cpp
@@ -303,8 +303,6 @@
VFS =
createVFSFromCompilerInvocation(Clang->getInvocation(), Diagnostics, VFS);
- if (!VFS)
- return BuildPreambleError::CouldntCreateVFSOverlay;
// Create a file manager object to provide access to and cache the filesystem.
Clang->setFileManager(new FileManager(Clang->getFileSystemOpts(), VFS));
@@ -756,8 +754,6 @@
return "Could not create temporary file for PCH";
case BuildPreambleError::CouldntCreateTargetInfo:
return "CreateTargetInfo() return null";
- case BuildPreambleError::CouldntCreateVFSOverlay:
- return "Could not create VFS Overlay";
case BuildPreambleError::BeginSourceFileFailed:
return "BeginSourceFile() return an error";
case BuildPreambleError::CouldntEmitPCH:
diff --git a/lib/Frontend/Rewrite/FixItRewriter.cpp b/lib/Frontend/Rewrite/FixItRewriter.cpp
index dc787ac..17a35c3 100644
--- a/lib/Frontend/Rewrite/FixItRewriter.cpp
+++ b/lib/Frontend/Rewrite/FixItRewriter.cpp
@@ -1,4 +1,4 @@
-//===--- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --*- C++ -*-===//
+//===- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,28 +14,32 @@
//===----------------------------------------------------------------------===//
#include "clang/Rewrite/Frontend/FixItRewriter.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/EditsReceiver.h"
#include "clang/Frontend/FrontendDiagnostic.h"
-#include "llvm/Support/Path.h"
+#include "clang/Rewrite/Core/RewriteBuffer.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
#include <memory>
+#include <string>
+#include <system_error>
+#include <utility>
using namespace clang;
FixItRewriter::FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
const LangOptions &LangOpts,
FixItOptions *FixItOpts)
- : Diags(Diags),
- Editor(SourceMgr, LangOpts),
- Rewrite(SourceMgr, LangOpts),
- FixItOpts(FixItOpts),
- NumFailures(0),
- PrevDiagSilenced(false) {
+ : Diags(Diags), Editor(SourceMgr, LangOpts), Rewrite(SourceMgr, LangOpts),
+ FixItOpts(FixItOpts) {
Owner = Diags.takeClient();
Client = Diags.getClient();
Diags.setClient(this, false);
@@ -59,20 +63,21 @@
Rewriter &Rewrite;
public:
- RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }
+ RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) {}
void insert(SourceLocation loc, StringRef text) override {
Rewrite.InsertText(loc, text);
}
+
void replace(CharSourceRange range, StringRef text) override {
Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
}
};
-}
+} // namespace
bool FixItRewriter::WriteFixedFiles(
- std::vector<std::pair<std::string, std::string> > *RewrittenFiles) {
+ std::vector<std::pair<std::string, std::string>> *RewrittenFiles) {
if (NumFailures > 0 && !FixItOpts->FixWhatYouCan) {
Diag(FullSourceLoc(), diag::warn_fixit_no_changes);
return true;
@@ -200,4 +205,4 @@
Diags.setClient(this, false);
}
-FixItOptions::~FixItOptions() {}
+FixItOptions::~FixItOptions() = default;
diff --git a/lib/Frontend/SerializedDiagnosticReader.cpp b/lib/Frontend/SerializedDiagnosticReader.cpp
index 08b7087..4587178 100644
--- a/lib/Frontend/SerializedDiagnosticReader.cpp
+++ b/lib/Frontend/SerializedDiagnosticReader.cpp
@@ -1,4 +1,4 @@
-//===--- SerializedDiagnosticReader.cpp - Reads diagnostics ---------------===//
+//===- SerializedDiagnosticReader.cpp - Reads diagnostics -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -9,11 +9,22 @@
#include "clang/Frontend/SerializedDiagnosticReader.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
#include "clang/Frontend/SerializedDiagnostics.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Bitcode/BitCodes.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/ManagedStatic.h"
+#include <cstdint>
+#include <system_error>
using namespace clang;
-using namespace clang::serialized_diags;
+using namespace serialized_diags;
std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
// Open the diagnostics file.
@@ -44,13 +55,12 @@
std::error_code EC;
switch (Stream.ReadSubBlockID()) {
- case llvm::bitc::BLOCKINFO_BLOCK_ID: {
+ case llvm::bitc::BLOCKINFO_BLOCK_ID:
BlockInfo = Stream.ReadBlockInfoBlock();
if (!BlockInfo)
return SDError::MalformedBlockInfoBlock;
Stream.setBlockInfo(&*BlockInfo);
continue;
- }
case BLOCK_META:
if ((EC = readMetaBlock(Stream)))
return EC;
@@ -65,7 +75,7 @@
continue;
}
}
- return std::error_code();
+ return {};
}
enum class SerializedDiagnosticReader::Cursor {
@@ -132,7 +142,7 @@
case Cursor::BlockEnd:
if (!VersionChecked)
return SDError::MissingVersion;
- return std::error_code();
+ return {};
}
SmallVector<uint64_t, 1> Record;
@@ -176,7 +186,7 @@
case Cursor::BlockEnd:
if ((EC = visitEndOfDiagnostic()))
return EC;
- return std::error_code();
+ return {};
case Cursor::Record:
break;
}
@@ -253,12 +263,14 @@
}
namespace {
+
class SDErrorCategoryType final : public std::error_category {
const char *name() const noexcept override {
return "clang.serialized_diags";
}
+
std::string message(int IE) const override {
- SDError E = static_cast<SDError>(IE);
+ auto E = static_cast<SDError>(IE);
switch (E) {
case SDError::CouldNotLoad:
return "Failed to open diagnostics file";
@@ -290,7 +302,8 @@
llvm_unreachable("Unknown error type!");
}
};
-}
+
+} // namespace
static llvm::ManagedStatic<SDErrorCategoryType> ErrorCategory;
const std::error_category &clang::serialized_diags::SDErrorCategory() {
diff --git a/lib/Frontend/TextDiagnosticBuffer.cpp b/lib/Frontend/TextDiagnosticBuffer.cpp
index 2885073..44bb2bc 100644
--- a/lib/Frontend/TextDiagnosticBuffer.cpp
+++ b/lib/Frontend/TextDiagnosticBuffer.cpp
@@ -1,4 +1,4 @@
-//===--- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics ---------------===//
+//===- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,13 +12,15 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
+
using namespace clang;
/// HandleDiagnostic - Store the errors, warnings, and notes that are
/// reported.
-///
void TextDiagnosticBuffer::HandleDiagnostic(DiagnosticsEngine::Level Level,
const Diagnostic &Info) {
// Default implementation (Warnings/errors count).
@@ -50,25 +52,24 @@
}
void TextDiagnosticBuffer::FlushDiagnostics(DiagnosticsEngine &Diags) const {
- for (auto it = All.begin(), ie = All.end(); it != ie; ++it) {
- auto Diag = Diags.Report(Diags.getCustomDiagID(it->first, "%0"));
- switch (it->first) {
+ for (const auto &I : All) {
+ auto Diag = Diags.Report(Diags.getCustomDiagID(I.first, "%0"));
+ switch (I.first) {
default: llvm_unreachable(
"Diagnostic not handled during diagnostic flushing!");
case DiagnosticsEngine::Note:
- Diag << Notes[it->second].second;
+ Diag << Notes[I.second].second;
break;
case DiagnosticsEngine::Warning:
- Diag << Warnings[it->second].second;
+ Diag << Warnings[I.second].second;
break;
case DiagnosticsEngine::Remark:
- Diag << Remarks[it->second].second;
+ Diag << Remarks[I.second].second;
break;
case DiagnosticsEngine::Error:
case DiagnosticsEngine::Fatal:
- Diag << Errors[it->second].second;
+ Diag << Errors[I.second].second;
break;
}
}
}
-
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 0df5393..129a233 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -1,4 +1,4 @@
-//===---- VerifyDiagnosticConsumer.cpp - Verifying Diagnostic Client ------===//
+//===- VerifyDiagnosticConsumer.cpp - Verifying Diagnostic Client ---------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,27 +13,48 @@
#include "clang/Frontend/VerifyDiagnosticConsumer.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <iterator>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
using namespace clang;
-typedef VerifyDiagnosticConsumer::Directive Directive;
-typedef VerifyDiagnosticConsumer::DirectiveList DirectiveList;
-typedef VerifyDiagnosticConsumer::ExpectedData ExpectedData;
+
+using Directive = VerifyDiagnosticConsumer::Directive;
+using DirectiveList = VerifyDiagnosticConsumer::DirectiveList;
+using ExpectedData = VerifyDiagnosticConsumer::ExpectedData;
VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &Diags_)
- : Diags(Diags_),
- PrimaryClient(Diags.getClient()), PrimaryClientOwner(Diags.takeClient()),
- Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(nullptr),
- LangOpts(nullptr), SrcManager(nullptr), ActiveSourceFiles(0),
- Status(HasNoDirectives)
-{
+ : Diags(Diags_), PrimaryClient(Diags.getClient()),
+ PrimaryClientOwner(Diags.takeClient()),
+ Buffer(new TextDiagnosticBuffer()), Status(HasNoDirectives) {
if (Diags.hasSourceManager())
setSourceManager(Diags.getSourceManager());
}
@@ -48,14 +69,16 @@
}
#ifndef NDEBUG
+
namespace {
+
class VerifyFileTracker : public PPCallbacks {
VerifyDiagnosticConsumer &Verify;
SourceManager &SM;
public:
VerifyFileTracker(VerifyDiagnosticConsumer &Verify, SourceManager &SM)
- : Verify(Verify), SM(SM) { }
+ : Verify(Verify), SM(SM) {}
/// \brief Hook into the preprocessor and update the list of parsed
/// files when the preprocessor indicates a new file is entered.
@@ -66,7 +89,9 @@
VerifyDiagnosticConsumer::IsParsed);
}
};
-} // End anonymous namespace.
+
+} // namespace
+
#endif
// DiagnosticConsumer interface.
@@ -79,10 +104,10 @@
CurrentPreprocessor = PP;
this->LangOpts = &LangOpts;
setSourceManager(PP->getSourceManager());
- const_cast<Preprocessor*>(PP)->addCommentHandler(this);
+ const_cast<Preprocessor *>(PP)->addCommentHandler(this);
#ifndef NDEBUG
// Debug build tracks parsed files.
- const_cast<Preprocessor*>(PP)->addPPCallbacks(
+ const_cast<Preprocessor *>(PP)->addPPCallbacks(
llvm::make_unique<VerifyFileTracker>(*this, *SrcManager));
#endif
}
@@ -99,7 +124,8 @@
// Detach comment handler once last active source file completed.
if (--ActiveSourceFiles == 0) {
if (CurrentPreprocessor)
- const_cast<Preprocessor*>(CurrentPreprocessor)->removeCommentHandler(this);
+ const_cast<Preprocessor *>(CurrentPreprocessor)->
+ removeCommentHandler(this);
// Check diagnostics once last file completed.
CheckDiagnostics();
@@ -152,19 +178,18 @@
// Checking diagnostics implementation.
//===----------------------------------------------------------------------===//
-typedef TextDiagnosticBuffer::DiagList DiagList;
-typedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
+using DiagList = TextDiagnosticBuffer::DiagList;
+using const_diag_iterator = TextDiagnosticBuffer::const_iterator;
namespace {
/// StandardDirective - Directive with string matching.
-///
class StandardDirective : public Directive {
public:
StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
bool MatchAnyLine, StringRef Text, unsigned Min,
unsigned Max)
- : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max) { }
+ : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max) {}
bool isValid(std::string &Error) override {
// all strings are considered valid; even empty ones
@@ -177,14 +202,13 @@
};
/// RegexDirective - Directive with regular-expression matching.
-///
class RegexDirective : public Directive {
public:
RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max,
StringRef RegexStr)
- : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max),
- Regex(RegexStr) { }
+ : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max),
+ Regex(RegexStr) {}
bool isValid(std::string &Error) override {
return Regex.isValid(Error);
@@ -202,7 +226,7 @@
{
public:
ParseHelper(StringRef S)
- : Begin(S.begin()), End(S.end()), C(Begin), P(Begin), PEnd(nullptr) {}
+ : Begin(S.begin()), End(S.end()), C(Begin), P(Begin) {}
// Return true if string literal is next.
bool Next(StringRef S) {
@@ -210,7 +234,7 @@
PEnd = C + S.size();
if (PEnd > End)
return false;
- return !memcmp(P, S.data(), S.size());
+ return memcmp(P, S.data(), S.size()) == 0;
}
// Return true if number is next.
@@ -321,16 +345,23 @@
return !(C < End);
}
- const char * const Begin; // beginning of expected content
- const char * const End; // end of expected content (1-past)
- const char *C; // position of next char in content
+ // Beginning of expected content.
+ const char * const Begin;
+
+ // End of expected content (1-past).
+ const char * const End;
+
+ // Position of next char in content.
+ const char *C;
+
const char *P;
private:
- const char *PEnd; // previous next/search subject end (1-past)
+ // Previous next/search subject end (1-past).
+ const char *PEnd = nullptr;
};
-} // namespace anonymous
+} // anonymous
/// ParseDirective - Go through the comment and see if it indicates expected
/// diagnostics. If so, then put them in the appropriate directive list.
@@ -701,21 +732,20 @@
SmallString<256> Fmt;
llvm::raw_svector_ostream OS(Fmt);
- for (auto *DirPtr : DL) {
- Directive &D = *DirPtr;
- if (D.DiagnosticLoc.isInvalid())
+ for (const auto *D : DL) {
+ if (D->DiagnosticLoc.isInvalid())
OS << "\n File *";
else
- OS << "\n File " << SourceMgr.getFilename(D.DiagnosticLoc);
- if (D.MatchAnyLine)
+ OS << "\n File " << SourceMgr.getFilename(D->DiagnosticLoc);
+ if (D->MatchAnyLine)
OS << " Line *";
else
- OS << " Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
- if (D.DirectiveLoc != D.DiagnosticLoc)
+ OS << " Line " << SourceMgr.getPresumedLineNumber(D->DiagnosticLoc);
+ if (D->DirectiveLoc != D->DiagnosticLoc)
OS << " (directive at "
- << SourceMgr.getFilename(D.DirectiveLoc) << ':'
- << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ')';
- OS << ": " << D.Text;
+ << SourceMgr.getFilename(D->DirectiveLoc) << ':'
+ << SourceMgr.getPresumedLineNumber(D->DirectiveLoc) << ')';
+ OS << ": " << D->Text;
}
Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit()
@@ -741,7 +771,6 @@
/// CheckLists - Compare expected to seen diagnostic lists and return the
/// the difference between them.
-///
static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
const char *Label,
DirectiveList &Left,
@@ -792,7 +821,6 @@
/// CheckResults - This compares the expected results to those that
/// were actually reported. It emits any discrepencies. Return "true" if there
/// were problems. Return "false" otherwise.
-///
static unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
const TextDiagnosticBuffer &Buffer,
ExpectedData &ED) {
@@ -875,19 +903,16 @@
// this file is being parsed separately from the main file, in which
// case consider moving the directives to the correct place, if this
// is applicable.
- if (UnparsedFiles.size() > 0) {
+ if (!UnparsedFiles.empty()) {
// Generate a cache of parsed FileEntry pointers for alias lookups.
llvm::SmallPtrSet<const FileEntry *, 8> ParsedFileCache;
- for (ParsedFilesMap::iterator I = ParsedFiles.begin(),
- End = ParsedFiles.end(); I != End; ++I) {
- if (const FileEntry *FE = I->second)
+ for (const auto &I : ParsedFiles)
+ if (const FileEntry *FE = I.second)
ParsedFileCache.insert(FE);
- }
// Iterate through list of unparsed files.
- for (UnparsedFilesMap::iterator I = UnparsedFiles.begin(),
- End = UnparsedFiles.end(); I != End; ++I) {
- const UnparsedFileStatus &Status = I->second;
+ for (const auto &I : UnparsedFiles) {
+ const UnparsedFileStatus &Status = I.second;
const FileEntry *FE = Status.getFile();
// Skip files that have been parsed via an alias.
diff --git a/lib/Headers/mmintrin.h b/lib/Headers/mmintrin.h
index 4b38d51..102c08f 100644
--- a/lib/Headers/mmintrin.h
+++ b/lib/Headers/mmintrin.h
@@ -52,7 +52,7 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVD / MOVD </c> instruction.
+/// This intrinsic corresponds to the <c> MOVD </c> instruction.
///
/// \param __i
/// A 32-bit integer value.
@@ -69,7 +69,7 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVD / MOVD </c> instruction.
+/// This intrinsic corresponds to the <c> MOVD </c> instruction.
///
/// \param __m
/// A 64-bit integer vector.
@@ -85,7 +85,7 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVQ / MOVD </c> instruction.
+/// This intrinsic corresponds to the <c> MOVQ </c> instruction.
///
/// \param __i
/// A 64-bit signed integer.
@@ -101,7 +101,7 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VMOVQ / MOVD </c> instruction.
+/// This intrinsic corresponds to the <c> MOVQ </c> instruction.
///
/// \param __m
/// A 64-bit integer vector.
@@ -1289,7 +1289,7 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VXORPS / XORPS </c> instruction.
+/// This intrinsic corresponds to the <c> PXOR </c> instruction.
///
/// \returns An initialized 64-bit integer vector with all elements set to zero.
static __inline__ __m64 __DEFAULT_FN_ATTRS
@@ -1381,7 +1381,8 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VPSHUFD / PSHUFD </c> instruction.
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
///
/// \param __i
/// A 32-bit integer value used to initialize each vector element of the
@@ -1399,7 +1400,8 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VPSHUFLW / PSHUFLW </c> instruction.
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
///
/// \param __w
/// A 16-bit integer value used to initialize each vector element of the
@@ -1416,8 +1418,8 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the <c> VPUNPCKLBW + VPSHUFLW / PUNPCKLBW +
-/// PSHUFLW </c> instruction.
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
///
/// \param __b
/// An 8-bit integer value used to initialize each vector element of the
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index 2ff0a68..a711e1d 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -1630,14 +1630,15 @@
/// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
static void diagnosePrivateModules(const ModuleMap &Map,
DiagnosticsEngine &Diags,
- const Module *ActiveModule) {
+ const Module *ActiveModule,
+ SourceLocation InlineParent) {
auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
- const Module *M) {
+ const Module *M, SourceRange ReplLoc) {
auto D = Diags.Report(ActiveModule->DefinitionLoc,
diag::note_mmap_rename_top_level_private_module);
D << BadName << M->Name;
- D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, Canonical);
+ D << FixItHint::CreateReplacement(ReplLoc, Canonical);
};
for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
@@ -1657,7 +1658,8 @@
Diags.Report(ActiveModule->DefinitionLoc,
diag::warn_mmap_mismatched_private_submodule)
<< FullName;
- GenNoteAndFixIt(FullName, Canonical, M);
+ GenNoteAndFixIt(FullName, Canonical, M,
+ SourceRange(InlineParent, ActiveModule->DefinitionLoc));
continue;
}
@@ -1667,7 +1669,8 @@
Diags.Report(ActiveModule->DefinitionLoc,
diag::warn_mmap_mismatched_private_module_name)
<< ActiveModule->Name;
- GenNoteAndFixIt(ActiveModule->Name, Canonical, M);
+ GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
+ SourceRange(ActiveModule->DefinitionLoc));
}
}
}
@@ -1753,6 +1756,7 @@
}
Module *PreviousActiveModule = ActiveModule;
+ SourceLocation LastInlineParentLoc = SourceLocation();
if (Id.size() > 1) {
// This module map defines a submodule. Go find the module of which it
// is a submodule.
@@ -1763,6 +1767,7 @@
if (I == 0)
TopLevelModule = Next;
ActiveModule = Next;
+ LastInlineParentLoc = Id[I].second;
continue;
}
@@ -1882,7 +1887,7 @@
StartLoc) &&
(MapFileName.endswith("module.private.modulemap") ||
MapFileName.endswith("module_private.map")))
- diagnosePrivateModules(Map, Diags, ActiveModule);
+ diagnosePrivateModules(Map, Diags, ActiveModule, LastInlineParentLoc);
bool Done = false;
do {
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index a901a20..0bd1b8b 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -115,18 +115,19 @@
return false;
}
-// The -fmodule-name option (represented here by \p CurrentModule) tells the
-// compiler to textually include headers in the specified module, meaning clang
-// won't build the specified module. This is useful in a number of situations,
-// for instance, when building a library that vends a module map, one might want
-// to avoid hitting intermediate build products containig the the module map or
-// avoid finding the system installed modulemap for that library.
-static bool isForModuleBuilding(Module *M, StringRef CurrentModule) {
+// The -fmodule-name option tells the compiler to textually include headers in
+// the specified module, meaning clang won't build the specified module. This is
+// useful in a number of situations, for instance, when building a library that
+// vends a module map, one might want to avoid hitting intermediate build
+// products containig the the module map or avoid finding the system installed
+// modulemap for that library.
+static bool isForModuleBuilding(Module *M, StringRef CurrentModule,
+ StringRef ModuleName) {
StringRef TopLevelName = M->getTopLevelModuleName();
// When building framework Foo, we wanna make sure that Foo *and* Foo_Private
// are textually included and no modules are built for both.
- if (M->getTopLevelModule()->IsFramework &&
+ if (M->getTopLevelModule()->IsFramework && CurrentModule == ModuleName &&
!CurrentModule.endswith("_Private") && TopLevelName.endswith("_Private"))
TopLevelName = TopLevelName.drop_back(8);
@@ -1875,7 +1876,8 @@
// are processing this module textually (because we're building the module).
if (ShouldEnter && File && SuggestedModule && getLangOpts().Modules &&
!isForModuleBuilding(SuggestedModule.getModule(),
- getLangOpts().CurrentModule)) {
+ getLangOpts().CurrentModule,
+ getLangOpts().ModuleName)) {
// 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
@@ -2022,7 +2024,8 @@
// ShouldEnter is false because we are skipping the header. In that
// case, We are not importing the specified module.
if (SkipHeader && getLangOpts().CompilingPCH &&
- isForModuleBuilding(M, getLangOpts().CurrentModule))
+ isForModuleBuilding(M, getLangOpts().CurrentModule,
+ getLangOpts().ModuleName))
return;
makeModuleVisible(M, HashLoc);
@@ -2063,7 +2066,8 @@
// include headers in the specified module. We are not building the
// specified module.
if (getLangOpts().CompilingPCH &&
- isForModuleBuilding(M, getLangOpts().CurrentModule))
+ isForModuleBuilding(M, getLangOpts().CurrentModule,
+ getLangOpts().ModuleName))
return;
assert(!CurLexerSubmodule && "should not have marked this as a module yet");
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 7f524c5..8814b23 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -1344,7 +1344,7 @@
// These expressions are only allowed within a preprocessor directive.
if (!PP.isParsingIfOrElifDirective()) {
- PP.Diag(LParenLoc, diag::err_pp_directive_required) << II->getName();
+ PP.Diag(LParenLoc, diag::err_pp_directive_required) << II;
// Return a valid identifier token.
assert(Tok.is(tok::identifier));
Tok.setIdentifierInfo(II);
@@ -1801,12 +1801,21 @@
[this](Token &Tok, bool &HasLexedNextToken) -> int {
IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this,
diag::err_feature_check_malformed);
+ const LangOptions &LangOpts = getLangOpts();
if (!II)
return false;
- else if (II->getBuiltinID() != 0)
+ else if (II->getBuiltinID() != 0) {
+ switch (II->getBuiltinID()) {
+ case Builtin::BI__builtin_operator_new:
+ case Builtin::BI__builtin_operator_delete:
+ // denotes date of behavior change to support calling arbitrary
+ // usual allocation and deallocation functions. Required by libc++
+ return 201802;
+ default:
+ return true;
+ }
return true;
- else {
- const LangOptions &LangOpts = getLangOpts();
+ } else {
return llvm::StringSwitch<bool>(II->getName())
.Case("__make_integer_seq", LangOpts.CPlusPlus)
.Case("__type_pack_element", LangOpts.CPlusPlus)
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index deefcaf..0e02acd 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -15,6 +15,7 @@
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/CharInfo.h"
@@ -22,7 +23,6 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/Optional.h"
@@ -2027,8 +2027,13 @@
}
Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
- if (IsForRangeLoop)
+ if (IsForRangeLoop) {
Actions.ActOnCXXForRangeDecl(ThisDecl);
+ } else {
+ // Obj-C for loop
+ if (auto *VD = dyn_cast_or_null<VarDecl>(ThisDecl))
+ VD->setObjCForDecl(true);
+ }
Actions.FinalizeDeclaration(ThisDecl);
D.complete(ThisDecl);
return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, ThisDecl);
@@ -3908,7 +3913,7 @@
///
void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
unsigned TagType, Decl *TagDecl) {
- PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
+ PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,
"parsing struct/union body");
assert(!getLangOpts().CPlusPlus && "C++ declarations not supported");
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 172950f..0c789c9 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/Parse/Parser.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/OperatorKinds.h"
@@ -22,7 +23,6 @@
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallString.h"
@@ -188,8 +188,8 @@
IdentLoc, Ident, T.getOpenLocation(),
attrs.getList(), ImplicitUsingDirectiveDecl);
- PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc,
- "parsing namespace");
+ PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl,
+ NamespaceLoc, "parsing namespace");
// Parse the contents of the namespace. This includes parsing recovery on
// any improperly nested namespaces.
@@ -3110,7 +3110,7 @@
TagType == DeclSpec::TST_union ||
TagType == DeclSpec::TST_class) && "Invalid TagType!");
- PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
+ PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,
"parsing struct/union/class body");
// Determine whether this is a non-nested class. Note that local
@@ -4036,7 +4036,7 @@
if (TryConsumeToken(tok::ellipsis))
Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
- << AttrName->getName();
+ << AttrName;
}
if (ExpectAndConsume(tok::r_square))
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index ecb36fe..7ebd90e 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1744,17 +1744,34 @@
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
+ const auto WarnOnInit = [this, &CK] {
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
+ ? diag::warn_cxx14_compat_init_statement
+ : diag::ext_init_statement)
+ << (CK == Sema::ConditionKind::Switch);
+ };
+
// Determine what kind of thing we have.
switch (isCXXConditionDeclarationOrInitStatement(InitStmt)) {
case ConditionOrInitStatement::Expression: {
ProhibitAttributes(attrs);
+ // We can have an empty expression here.
+ // if (; true);
+ if (InitStmt && Tok.is(tok::semi)) {
+ WarnOnInit();
+ SourceLocation SemiLoc = ConsumeToken();
+ *InitStmt = Actions.ActOnNullStmt(SemiLoc);
+ return ParseCXXCondition(nullptr, Loc, CK);
+ }
+
// Parse the expression.
ExprResult Expr = ParseExpression(); // expression
if (Expr.isInvalid())
return Sema::ConditionError();
if (InitStmt && Tok.is(tok::semi)) {
+ WarnOnInit();
*InitStmt = Actions.ActOnExprStmt(Expr.get());
ConsumeToken();
return ParseCXXCondition(nullptr, Loc, CK);
@@ -1764,10 +1781,7 @@
}
case ConditionOrInitStatement::InitStmtDecl: {
- Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
- ? diag::warn_cxx14_compat_init_statement
- : diag::ext_init_statement)
- << (CK == Sema::ConditionKind::Switch);
+ WarnOnInit();
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy DG =
ParseSimpleDeclaration(DeclaratorContext::InitStmtContext, DeclEnd,
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 13f968f..0ac418a 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -13,11 +13,11 @@
#include "clang/Parse/Parser.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
@@ -2680,7 +2680,7 @@
Decl *Parser::ParseObjCMethodDefinition() {
Decl *MDecl = ParseObjCMethodPrototype();
- PrettyDeclStackTraceEntry CrashInfo(Actions, MDecl, Tok.getLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Actions.Context, MDecl, Tok.getLocation(),
"parsing Objective-C method");
// parse optional ';'
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index d34fad8..7528e43 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -719,7 +719,7 @@
SourceLocation DTLoc = ConsumeAnyToken();
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
// OpenMP 4.5 syntax with list of entities.
- llvm::SmallSetVector<const NamedDecl*, 16> SameDirectiveDecls;
+ Sema::NamedDeclSetType SameDirectiveDecls;
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OMPDeclareTargetDeclAttr::MapTypeTy MT =
OMPDeclareTargetDeclAttr::MT_To;
@@ -736,11 +736,12 @@
ConsumeToken();
}
auto Callback = [this, MT, &SameDirectiveDecls](
- CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
+ CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
SameDirectiveDecls);
};
- if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true))
+ if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
+ /*AllowScopeSpecifier=*/true))
break;
// Consume optional ','.
@@ -749,7 +750,13 @@
}
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
ConsumeAnyToken();
- return DeclGroupPtrTy();
+ SmallVector<Decl *, 4> Decls;
+ Decls.reserve(SameDirectiveDecls.size());
+ for (Decl *D : SameDirectiveDecls)
+ Decls.emplace_back(D);
+ if (Decls.empty())
+ return DeclGroupPtrTy();
+ return Actions.BuildDeclaratorGroup(Decls);
}
// Skip the last annot_pragma_openmp_end.
@@ -758,6 +765,7 @@
if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
return DeclGroupPtrTy();
+ llvm::SmallVector<Decl *, 4> Decls;
DKind = ParseOpenMPDirectiveKind(*this);
while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
@@ -772,6 +780,10 @@
Ptr =
ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
}
+ if (Ptr) {
+ DeclGroupRef Ref = Ptr.get();
+ Decls.append(Ref.begin(), Ref.end());
+ }
if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
TentativeParsingAction TPA(*this);
ConsumeAnnotationToken();
@@ -797,7 +809,7 @@
Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
}
Actions.ActOnFinishOpenMPDeclareTargetDirective();
- return DeclGroupPtrTy();
+ return Actions.BuildDeclaratorGroup(Decls);
}
case OMPD_unknown:
Diag(Tok, diag::err_omp_unknown_directive);
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index e815ea1..9e55634 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -220,6 +220,12 @@
Token &FirstToken) override;
};
+struct PragmaMSOptimizeHandler : public PragmaHandler {
+ PragmaMSOptimizeHandler() : PragmaHandler("optimize") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
PragmaForceCUDAHostDeviceHandler(Sema &Actions)
: PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
@@ -324,6 +330,8 @@
PP.AddPragmaHandler(MSRuntimeChecks.get());
MSIntrinsic.reset(new PragmaMSIntrinsicHandler());
PP.AddPragmaHandler(MSIntrinsic.get());
+ MSOptimize.reset(new PragmaMSOptimizeHandler());
+ PP.AddPragmaHandler(MSOptimize.get());
}
if (getLangOpts().CUDA) {
@@ -410,6 +418,8 @@
MSRuntimeChecks.reset();
PP.RemovePragmaHandler(MSIntrinsic.get());
MSIntrinsic.reset();
+ PP.RemovePragmaHandler(MSOptimize.get());
+ MSOptimize.reset();
}
if (getLangOpts().CUDA) {
@@ -2949,6 +2959,61 @@
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
<< "intrinsic";
}
+
+// #pragma optimize("gsty", on|off)
+void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ SourceLocation StartLoc = Tok.getLocation();
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize";
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::string_literal)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize";
+ return;
+ }
+ // We could syntax check the string but it's probably not worth the effort.
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::comma)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize";
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.is(tok::eod) || Tok.is(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument)
+ << "optimize" << /*Expected=*/true << "'on' or 'off'";
+ return;
+ }
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (!II || (!II->isStr("on") && !II->isStr("off"))) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
+ << PP.getSpelling(Tok) << "optimize" << /*Expected=*/true
+ << "'on' or 'off'";
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize";
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "optimize";
+ return;
+ }
+ PP.Diag(StartLoc, diag::warn_pragma_optimize);
+}
+
void PragmaForceCUDAHostDeviceHandler::HandlePragma(
Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) {
Token FirstTok = Tok;
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index b63c69d..f72fd32 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -12,13 +12,13 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/LoopHint.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/TypoCorrection.h"
using namespace clang;
@@ -1957,7 +1957,7 @@
assert(Tok.is(tok::l_brace));
SourceLocation LBraceLoc = Tok.getLocation();
- PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
+ PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, LBraceLoc,
"parsing function body");
// Save and reset current vtordisp stack if we have entered a C++ method body.
@@ -1990,7 +1990,7 @@
assert(Tok.is(tok::kw_try) && "Expected 'try'");
SourceLocation TryLoc = ConsumeToken();
- PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, TryLoc,
+ PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, TryLoc,
"parsing function try block");
// Constructor initializer list?
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 88c0e17..ebd6f0f 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -1894,7 +1894,8 @@
return TPResult::Error;
// cv-qualifier-seq
- while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict))
+ while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw___unaligned,
+ tok::kw_restrict))
ConsumeToken();
// ref-qualifier[opt]
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index f617d24..d8f9f7a 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -2250,7 +2250,7 @@
return true;
}
- if (getDepth() < MaxDepth)
+ if (getDepth() < P.getLangOpts().BracketDepth)
return false;
return diagnoseOverflow();
diff --git a/lib/Rewrite/DeltaTree.cpp b/lib/Rewrite/DeltaTree.cpp
index 352fab0..1dfc26c 100644
--- a/lib/Rewrite/DeltaTree.cpp
+++ b/lib/Rewrite/DeltaTree.cpp
@@ -1,4 +1,4 @@
-//===--- DeltaTree.cpp - B-Tree for Rewrite Delta tracking ----------------===//
+//===- DeltaTree.cpp - B-Tree for Rewrite Delta tracking ------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,8 +13,10 @@
#include "clang/Rewrite/Core/DeltaTree.h"
#include "clang/Basic/LLVM.h"
-#include <cstdio>
+#include "llvm/Support/Casting.h"
+#include <cassert>
#include <cstring>
+
using namespace clang;
/// The DeltaTree class is a multiway search tree (BTree) structure with some
@@ -33,6 +35,7 @@
/// full delta implied by a whole subtree in constant time.
namespace {
+
/// SourceDelta - As code in the original input buffer is added and deleted,
/// SourceDelta records are used to keep track of how the input SourceLocation
/// object is mapped into the output buffer.
@@ -67,12 +70,11 @@
enum { WidthFactor = 8 };
/// Values - This tracks the SourceDelta's currently in this node.
- ///
SourceDelta Values[2*WidthFactor-1];
/// NumValuesUsed - This tracks the number of values this node currently
/// holds.
- unsigned char NumValuesUsed;
+ unsigned char NumValuesUsed = 0;
/// IsLeaf - This is true if this is a leaf of the btree. If false, this is
/// an interior node, and is actually an instance of DeltaTreeInteriorNode.
@@ -80,20 +82,22 @@
/// FullDelta - This is the full delta of all the values in this node and
/// all children nodes.
- int FullDelta;
+ int FullDelta = 0;
+
public:
- DeltaTreeNode(bool isLeaf = true)
- : NumValuesUsed(0), IsLeaf(isLeaf), FullDelta(0) {}
+ DeltaTreeNode(bool isLeaf = true) : IsLeaf(isLeaf) {}
bool isLeaf() const { return IsLeaf; }
int getFullDelta() const { return FullDelta; }
bool isFull() const { return NumValuesUsed == 2*WidthFactor-1; }
unsigned getNumValuesUsed() const { return NumValuesUsed; }
+
const SourceDelta &getValue(unsigned i) const {
assert(i < NumValuesUsed && "Invalid value #");
return Values[i];
}
+
SourceDelta &getValue(unsigned i) {
assert(i < NumValuesUsed && "Invalid value #");
return Values[i];
@@ -114,23 +118,24 @@
void Destroy();
};
-} // end anonymous namespace
-namespace {
/// DeltaTreeInteriorNode - When isLeaf = false, a node has child pointers.
/// This class tracks them.
class DeltaTreeInteriorNode : public DeltaTreeNode {
+ friend class DeltaTreeNode;
+
DeltaTreeNode *Children[2*WidthFactor];
+
~DeltaTreeInteriorNode() {
for (unsigned i = 0, e = NumValuesUsed+1; i != e; ++i)
Children[i]->Destroy();
}
- friend class DeltaTreeNode;
+
public:
DeltaTreeInteriorNode() : DeltaTreeNode(false /*nonleaf*/) {}
DeltaTreeInteriorNode(const InsertResult &IR)
- : DeltaTreeNode(false /*nonleaf*/) {
+ : DeltaTreeNode(false /*nonleaf*/) {
Children[0] = IR.LHS;
Children[1] = IR.RHS;
Values[0] = IR.Split;
@@ -142,15 +147,16 @@
assert(i < getNumValuesUsed()+1 && "Invalid child");
return Children[i];
}
+
DeltaTreeNode *getChild(unsigned i) {
assert(i < getNumValuesUsed()+1 && "Invalid child");
return Children[i];
}
- static inline bool classof(const DeltaTreeNode *N) { return !N->isLeaf(); }
+ static bool classof(const DeltaTreeNode *N) { return !N->isLeaf(); }
};
-}
+} // namespace
/// Destroy - A 'virtual' destructor.
void DeltaTreeNode::Destroy() {
@@ -166,7 +172,7 @@
int NewFullDelta = 0;
for (unsigned i = 0, e = getNumValuesUsed(); i != e; ++i)
NewFullDelta += Values[i].Delta;
- if (DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(this))
+ if (auto *IN = dyn_cast<DeltaTreeInteriorNode>(this))
for (unsigned i = 0, e = getNumValuesUsed()+1; i != e; ++i)
NewFullDelta += IN->getChild(i)->getFullDelta();
FullDelta = NewFullDelta;
@@ -223,7 +229,7 @@
}
// Otherwise, this is an interior node. Send the request down the tree.
- DeltaTreeInteriorNode *IN = cast<DeltaTreeInteriorNode>(this);
+ auto *IN = cast<DeltaTreeInteriorNode>(this);
if (!IN->Children[i]->DoInsertion(FileIndex, Delta, InsertRes))
return false; // If there was space in the child, just return.
@@ -300,7 +306,7 @@
// Create the new child node.
DeltaTreeNode *NewNode;
- if (DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(this)) {
+ if (auto *IN = dyn_cast<DeltaTreeInteriorNode>(this)) {
// If this is an interior node, also move over 'WidthFactor' children
// into the new node.
DeltaTreeInteriorNode *New = new DeltaTreeInteriorNode();
@@ -328,8 +334,6 @@
InsertRes.Split = Values[WidthFactor-1];
}
-
-
//===----------------------------------------------------------------------===//
// DeltaTree Implementation
//===----------------------------------------------------------------------===//
@@ -340,7 +344,7 @@
/// VerifyTree - Walk the btree performing assertions on various properties to
/// verify consistency. This is useful for debugging new changes to the tree.
static void VerifyTree(const DeltaTreeNode *N) {
- const DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(N);
+ const auto *IN = dyn_cast<DeltaTreeInteriorNode>(N);
if (IN == 0) {
// Verify leaves, just ensure that FullDelta matches up and the elements
// are in proper order.
@@ -387,6 +391,7 @@
DeltaTree::DeltaTree() {
Root = new DeltaTreeNode();
}
+
DeltaTree::DeltaTree(const DeltaTree &RHS) {
// Currently we only support copying when the RHS is empty.
assert(getRoot(RHS.Root)->getNumValuesUsed() == 0 &&
@@ -407,7 +412,7 @@
int Result = 0;
// Walk down the tree.
- while (1) {
+ while (true) {
// For all nodes, include any local deltas before the specified file
// index by summing them up directly. Keep track of how many were
// included.
@@ -423,7 +428,7 @@
// If we have an interior node, include information about children and
// recurse. Otherwise, if we have a leaf, we're done.
- const DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(Node);
+ const auto *IN = dyn_cast<DeltaTreeInteriorNode>(Node);
if (!IN) return Result;
// Include any children to the left of the values we skipped, all of
@@ -461,4 +466,3 @@
VerifyTree(MyRoot);
#endif
}
-
diff --git a/lib/Rewrite/RewriteRope.cpp b/lib/Rewrite/RewriteRope.cpp
index 030ab77..5bc79f3 100644
--- a/lib/Rewrite/RewriteRope.cpp
+++ b/lib/Rewrite/RewriteRope.cpp
@@ -1,4 +1,4 @@
-//===--- RewriteRope.cpp - Rope specialized for rewriter --------*- C++ -*-===//
+//===- RewriteRope.cpp - Rope specialized for rewriter --------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,7 +13,11 @@
#include "clang/Rewrite/Core/RewriteRope.h"
#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Casting.h"
#include <algorithm>
+#include <cassert>
+#include <cstring>
+
using namespace clang;
/// RewriteRope is a "strong" string class, designed to make insertions and
@@ -59,12 +63,12 @@
/// RopePieceBTreeInterior - An interior node in the B+ Tree, which manages
/// up to '2*WidthFactor' other nodes in the tree.
+namespace {
//===----------------------------------------------------------------------===//
// RopePieceBTreeNode Class
//===----------------------------------------------------------------------===//
-namespace {
/// RopePieceBTreeNode - Common base class of RopePieceBTreeLeaf and
/// RopePieceBTreeInterior. This provides some 'virtual' dispatching methods
/// and a flag that determines which subclass the instance is. Also
@@ -82,13 +86,13 @@
/// Size - This is the number of bytes of file this node (including any
/// potential children) covers.
- unsigned Size;
+ unsigned Size = 0;
/// IsLeaf - True if this is an instance of RopePieceBTreeLeaf, false if it
/// is an instance of RopePieceBTreeInterior.
bool IsLeaf;
- RopePieceBTreeNode(bool isLeaf) : Size(0), IsLeaf(isLeaf) {}
+ RopePieceBTreeNode(bool isLeaf) : IsLeaf(isLeaf) {}
~RopePieceBTreeNode() = default;
public:
@@ -116,15 +120,12 @@
/// erase - Remove NumBytes from this node at the specified offset. We are
/// guaranteed that there is a split at Offset.
void erase(unsigned Offset, unsigned NumBytes);
-
};
-} // end anonymous namespace
//===----------------------------------------------------------------------===//
// RopePieceBTreeLeaf Class
//===----------------------------------------------------------------------===//
-namespace {
/// RopePieceBTreeLeaf - Directly manages up to '2*WidthFactor' RopePiece
/// nodes. This directly represents a chunk of the string with those
/// RopePieces contatenated. Since this is a B+Tree, all values (in this case
@@ -135,18 +136,19 @@
class RopePieceBTreeLeaf : public RopePieceBTreeNode {
/// NumPieces - This holds the number of rope pieces currently active in the
/// Pieces array.
- unsigned char NumPieces;
+ unsigned char NumPieces = 0;
/// Pieces - This tracks the file chunks currently in this leaf.
- ///
RopePiece Pieces[2*WidthFactor];
/// NextLeaf - This is a pointer to the next leaf in the tree, allowing
/// efficient in-order forward iteration of the tree without traversal.
- RopePieceBTreeLeaf **PrevLeaf, *NextLeaf;
+ RopePieceBTreeLeaf **PrevLeaf = nullptr;
+ RopePieceBTreeLeaf *NextLeaf = nullptr;
+
public:
- RopePieceBTreeLeaf() : RopePieceBTreeNode(true), NumPieces(0),
- PrevLeaf(nullptr), NextLeaf(nullptr) {}
+ RopePieceBTreeLeaf() : RopePieceBTreeNode(true) {}
+
~RopePieceBTreeLeaf() {
if (PrevLeaf || NextLeaf)
removeFromLeafInOrder();
@@ -170,6 +172,7 @@
}
const RopePieceBTreeLeaf *getNextLeafInOrder() const { return NextLeaf; }
+
void insertAfterLeafInOrder(RopePieceBTreeLeaf *Node) {
assert(!PrevLeaf && !NextLeaf && "Already in ordering");
@@ -214,16 +217,16 @@
/// node is returned and must be inserted into a parent.
RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
-
/// erase - Remove NumBytes from this node at the specified offset. We are
/// guaranteed that there is a split at Offset.
void erase(unsigned Offset, unsigned NumBytes);
- static inline bool classof(const RopePieceBTreeNode *N) {
+ static bool classof(const RopePieceBTreeNode *N) {
return N->isLeaf();
}
};
-} // end anonymous namespace
+
+} // namespace
/// split - Split the range containing the specified offset so that we are
/// guaranteed that there is a place to do an insertion at the specified
@@ -266,7 +269,6 @@
return insert(Offset, Tail);
}
-
/// insert - Insert the specified RopePiece into this tree node at the
/// specified offset. The offset is relative, so "0" is the start of the node.
///
@@ -388,18 +390,21 @@
//===----------------------------------------------------------------------===//
namespace {
+
/// RopePieceBTreeInterior - This represents an interior node in the B+Tree,
/// which holds up to 2*WidthFactor pointers to child nodes.
class RopePieceBTreeInterior : public RopePieceBTreeNode {
/// NumChildren - This holds the number of children currently active in the
/// Children array.
- unsigned char NumChildren;
+ unsigned char NumChildren = 0;
+
RopePieceBTreeNode *Children[2*WidthFactor];
+
public:
- RopePieceBTreeInterior() : RopePieceBTreeNode(false), NumChildren(0) {}
+ RopePieceBTreeInterior() : RopePieceBTreeNode(false) {}
RopePieceBTreeInterior(RopePieceBTreeNode *LHS, RopePieceBTreeNode *RHS)
- : RopePieceBTreeNode(false) {
+ : RopePieceBTreeNode(false) {
Children[0] = LHS;
Children[1] = RHS;
NumChildren = 2;
@@ -414,10 +419,12 @@
bool isFull() const { return NumChildren == 2*WidthFactor; }
unsigned getNumChildren() const { return NumChildren; }
+
const RopePieceBTreeNode *getChild(unsigned i) const {
assert(i < NumChildren && "invalid child #");
return Children[i];
}
+
RopePieceBTreeNode *getChild(unsigned i) {
assert(i < NumChildren && "invalid child #");
return Children[i];
@@ -431,7 +438,6 @@
Size += getChild(i)->size();
}
-
/// split - Split the range containing the specified offset so that we are
/// guaranteed that there is a place to do an insertion at the specified
/// offset. The offset is relative, so "0" is the start of the node.
@@ -440,7 +446,6 @@
/// node is returned and must be inserted into a parent.
RopePieceBTreeNode *split(unsigned Offset);
-
/// insert - Insert the specified ropepiece into this tree node at the
/// specified offset. The offset is relative, so "0" is the start of the
/// node.
@@ -457,11 +462,12 @@
/// guaranteed that there is a split at Offset.
void erase(unsigned Offset, unsigned NumBytes);
- static inline bool classof(const RopePieceBTreeNode *N) {
+ static bool classof(const RopePieceBTreeNode *N) {
return !N->isLeaf();
}
};
-} // end anonymous namespace
+
+} // namespace
/// split - Split the range containing the specified offset so that we are
/// guaranteed that there is a place to do an insertion at the specified
@@ -613,7 +619,7 @@
//===----------------------------------------------------------------------===//
void RopePieceBTreeNode::Destroy() {
- if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
+ if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
delete Leaf;
else
delete cast<RopePieceBTreeInterior>(this);
@@ -627,7 +633,7 @@
/// node is returned and must be inserted into a parent.
RopePieceBTreeNode *RopePieceBTreeNode::split(unsigned Offset) {
assert(Offset <= size() && "Invalid offset to split!");
- if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
+ if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
return Leaf->split(Offset);
return cast<RopePieceBTreeInterior>(this)->split(Offset);
}
@@ -641,7 +647,7 @@
RopePieceBTreeNode *RopePieceBTreeNode::insert(unsigned Offset,
const RopePiece &R) {
assert(Offset <= size() && "Invalid offset to insert!");
- if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
+ if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
return Leaf->insert(Offset, R);
return cast<RopePieceBTreeInterior>(this)->insert(Offset, R);
}
@@ -650,12 +656,11 @@
/// guaranteed that there is a split at Offset.
void RopePieceBTreeNode::erase(unsigned Offset, unsigned NumBytes) {
assert(Offset+NumBytes <= size() && "Invalid offset to erase!");
- if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
+ if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
return Leaf->erase(Offset, NumBytes);
return cast<RopePieceBTreeInterior>(this)->erase(Offset, NumBytes);
}
-
//===----------------------------------------------------------------------===//
// RopePieceBTreeIterator Implementation
//===----------------------------------------------------------------------===//
@@ -666,10 +671,10 @@
// begin iterator.
RopePieceBTreeIterator::RopePieceBTreeIterator(const void *n) {
- const RopePieceBTreeNode *N = static_cast<const RopePieceBTreeNode*>(n);
+ const auto *N = static_cast<const RopePieceBTreeNode *>(n);
// Walk down the left side of the tree until we get to a leaf.
- while (const RopePieceBTreeInterior *IN = dyn_cast<RopePieceBTreeInterior>(N))
+ while (const auto *IN = dyn_cast<RopePieceBTreeInterior>(N))
N = IN->getChild(0);
// We must have at least one leaf.
@@ -717,10 +722,12 @@
RopePieceBTree::RopePieceBTree() {
Root = new RopePieceBTreeLeaf();
}
+
RopePieceBTree::RopePieceBTree(const RopePieceBTree &RHS) {
assert(RHS.empty() && "Can't copy non-empty tree yet");
Root = new RopePieceBTreeLeaf();
}
+
RopePieceBTree::~RopePieceBTree() {
getRoot(Root)->Destroy();
}
@@ -730,7 +737,7 @@
}
void RopePieceBTree::clear() {
- if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(getRoot(Root)))
+ if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(getRoot(Root)))
Leaf->clear();
else {
getRoot(Root)->Destroy();
@@ -780,8 +787,7 @@
// just allocate a new rope piece for it alone.
if (Len > AllocChunkSize) {
unsigned Size = End-Start+sizeof(RopeRefCountString)-1;
- RopeRefCountString *Res =
- reinterpret_cast<RopeRefCountString *>(new char[Size]);
+ auto *Res = reinterpret_cast<RopeRefCountString *>(new char[Size]);
Res->RefCount = 0;
memcpy(Res->Data, Start, End-Start);
return RopePiece(Res, 0, End-Start);
@@ -791,8 +797,7 @@
// Make a new chunk and share it with later allocations.
unsigned AllocSize = offsetof(RopeRefCountString, Data) + AllocChunkSize;
- RopeRefCountString *Res =
- reinterpret_cast<RopeRefCountString *>(new char[AllocSize]);
+ auto *Res = reinterpret_cast<RopeRefCountString *>(new char[AllocSize]);
Res->RefCount = 0;
memcpy(Res->Data, Start, Len);
AllocBuffer = Res;
@@ -800,5 +805,3 @@
return RopePiece(AllocBuffer, 0, Len);
}
-
-
diff --git a/lib/Rewrite/Rewriter.cpp b/lib/Rewrite/Rewriter.cpp
index ae41dec..6041e0c 100644
--- a/lib/Rewrite/Rewriter.cpp
+++ b/lib/Rewrite/Rewriter.cpp
@@ -1,4 +1,4 @@
-//===--- Rewriter.cpp - Code rewriting interface --------------------------===//
+//===- Rewriter.cpp - Code rewriting interface ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,11 +15,24 @@
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Rewrite/Core/RewriteBuffer.h"
+#include "clang/Rewrite/Core/RewriteRope.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <iterator>
+#include <map>
+#include <memory>
+#include <system_error>
+#include <utility>
+
using namespace clang;
raw_ostream &RewriteBuffer::write(raw_ostream &os) const {
@@ -91,7 +104,6 @@
void RewriteBuffer::InsertText(unsigned OrigOffset, StringRef Str,
bool InsertAfter) {
-
// Nothing to insert, exit early.
if (Str.empty()) return;
@@ -114,7 +126,6 @@
AddReplaceDelta(OrigOffset, NewStr.size() - OrigLength);
}
-
//===----------------------------------------------------------------------===//
// Rewriter class
//===----------------------------------------------------------------------===//
@@ -127,10 +138,8 @@
!isRewritable(Range.getEnd())) return -1;
FileID StartFileID, EndFileID;
- unsigned StartOff, EndOff;
-
- StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
- EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
+ unsigned StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
+ unsigned EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
if (StartFileID != EndFileID)
return -1;
@@ -145,7 +154,6 @@
StartOff = RB.getMappedOffset(StartOff, !opts.IncludeInsertsAtBeginOfRange);
}
-
// Adjust the end offset to the end of the last token, instead of being the
// start of the last token if this is a token range.
if (Range.isTokenRange())
@@ -158,17 +166,15 @@
return getRangeSize(CharSourceRange::getTokenRange(Range), opts);
}
-
/// getRewrittenText - Return the rewritten form of the text in the specified
/// range. If the start or end of the range was unrewritable or if they are
/// in different buffers, this returns an empty string.
///
/// Note that this method is not particularly efficient.
-///
std::string Rewriter::getRewrittenText(SourceRange Range) const {
if (!isRewritable(Range.getBegin()) ||
!isRewritable(Range.getEnd()))
- return "";
+ return {};
FileID StartFileID, EndFileID;
unsigned StartOff, EndOff;
@@ -176,7 +182,7 @@
EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
if (StartFileID != EndFileID)
- return ""; // Start and end in different buffers.
+ return {}; // Start and end in different buffers.
// If edits have been made to this buffer, the delta between the range may
// have changed.
@@ -212,14 +218,12 @@
unsigned Rewriter::getLocationOffsetAndFileID(SourceLocation Loc,
FileID &FID) const {
assert(Loc.isValid() && "Invalid location");
- std::pair<FileID,unsigned> V = SourceMgr->getDecomposedLoc(Loc);
+ std::pair<FileID, unsigned> V = SourceMgr->getDecomposedLoc(Loc);
FID = V.first;
return V.second;
}
-
/// getEditBuffer - Get or create a RewriteBuffer for the specified FileID.
-///
RewriteBuffer &Rewriter::getEditBuffer(FileID FID) {
std::map<FileID, RewriteBuffer>::iterator I =
RewriteBuffers.lower_bound(FID);
@@ -393,6 +397,7 @@
}
namespace {
+
// A wrapper for a file stream that atomically overwrites the target.
//
// Creates a file output stream for a temporary file in the constructor,
@@ -403,7 +408,7 @@
public:
AtomicallyMovedFile(DiagnosticsEngine &Diagnostics, StringRef Filename,
bool &AllWritten)
- : Diagnostics(Diagnostics), Filename(Filename), AllWritten(AllWritten) {
+ : Diagnostics(Diagnostics), Filename(Filename), AllWritten(AllWritten) {
TempFilename = Filename;
TempFilename += "-%%%%%%%%";
int FD;
@@ -441,7 +446,8 @@
std::unique_ptr<llvm::raw_fd_ostream> FileStream;
bool &AllWritten;
};
-} // end anonymous namespace
+
+} // namespace
bool Rewriter::overwriteChangedFiles() {
bool AllWritten = true;
diff --git a/lib/Rewrite/TokenRewriter.cpp b/lib/Rewrite/TokenRewriter.cpp
index 494defd..1f5dec4 100644
--- a/lib/Rewrite/TokenRewriter.cpp
+++ b/lib/Rewrite/TokenRewriter.cpp
@@ -1,4 +1,4 @@
-//===--- TokenRewriter.cpp - Token-based code rewriting interface ---------===//
+//===- TokenRewriter.cpp - Token-based code rewriting interface -----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,6 +16,12 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/ScratchBuffer.h"
+#include "clang/Lex/Token.h"
+#include <cassert>
+#include <cstring>
+#include <map>
+#include <utility>
+
using namespace clang;
TokenRewriter::TokenRewriter(FileID FID, SourceManager &SM,
@@ -46,9 +52,7 @@
}
}
-TokenRewriter::~TokenRewriter() {
-}
-
+TokenRewriter::~TokenRewriter() = default;
/// RemapIterator - Convert from token_iterator (a const iterator) to
/// TokenRefTy (a non-const iterator).
@@ -63,7 +67,6 @@
return MapIt->second;
}
-
/// AddToken - Add the specified token into the Rewriter before the other
/// position.
TokenRewriter::TokenRefTy
@@ -77,7 +80,6 @@
return Where;
}
-
TokenRewriter::token_iterator
TokenRewriter::AddTokenBefore(token_iterator I, const char *Val) {
unsigned Len = strlen(Val);
@@ -96,4 +98,3 @@
return AddToken(Tok, RemapIterator(I));
}
-
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 9c9e1c3..2903f53 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -200,60 +200,41 @@
return false;
}
-// All blocks are in one of three states. States are ordered so that blocks
-// can only move to higher states.
-enum RecursiveState {
- FoundNoPath,
- FoundPath,
- FoundPathWithNoRecursiveCall
-};
-
-// Returns true if there exists a path to the exit block and every path
-// to the exit block passes through a call to FD.
+// Returns true if every path from the entry block passes through a call to FD.
static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) {
+ llvm::SmallPtrSet<CFGBlock *, 16> Visited;
+ llvm::SmallVector<CFGBlock *, 16> WorkList;
+ // Keep track of whether we found at least one recursive path.
+ bool foundRecursion = false;
const unsigned ExitID = cfg->getExit().getBlockID();
- // Mark all nodes as FoundNoPath, then set the status of the entry block.
- SmallVector<RecursiveState, 16> States(cfg->getNumBlockIDs(), FoundNoPath);
- States[cfg->getEntry().getBlockID()] = FoundPathWithNoRecursiveCall;
+ // Seed the work list with the entry block.
+ WorkList.push_back(&cfg->getEntry());
- // Make the processing stack and seed it with the entry block.
- SmallVector<CFGBlock *, 16> Stack;
- Stack.push_back(&cfg->getEntry());
+ while (!WorkList.empty()) {
+ CFGBlock *Block = WorkList.pop_back_val();
- while (!Stack.empty()) {
- CFGBlock *CurBlock = Stack.back();
- Stack.pop_back();
+ for (auto I = Block->succ_begin(), E = Block->succ_end(); I != E; ++I) {
+ if (CFGBlock *SuccBlock = *I) {
+ if (!Visited.insert(SuccBlock).second)
+ continue;
- unsigned ID = CurBlock->getBlockID();
- RecursiveState CurState = States[ID];
+ // Found a path to the exit node without a recursive call.
+ if (ExitID == SuccBlock->getBlockID())
+ return false;
- if (CurState == FoundPathWithNoRecursiveCall) {
- // Found a path to the exit node without a recursive call.
- if (ExitID == ID)
- return false;
-
- // Only change state if the block has a recursive call.
- if (hasRecursiveCallInPath(FD, *CurBlock))
- CurState = FoundPath;
- }
-
- // Loop over successor blocks and add them to the Stack if their state
- // changes.
- for (auto I = CurBlock->succ_begin(), E = CurBlock->succ_end(); I != E; ++I)
- if (*I) {
- unsigned next_ID = (*I)->getBlockID();
- if (States[next_ID] < CurState) {
- States[next_ID] = CurState;
- Stack.push_back(*I);
+ // If the successor block contains a recursive call, end analysis there.
+ if (hasRecursiveCallInPath(FD, *SuccBlock)) {
+ foundRecursion = true;
+ continue;
}
- }
- }
- // Return true if the exit node is reachable, and only reachable through
- // a recursive call.
- return States[ExitID] == FoundPath;
+ WorkList.push_back(SuccBlock);
+ }
+ }
+ }
+ return foundRecursion;
}
static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
@@ -269,10 +250,6 @@
CFG *cfg = AC.getCFG();
if (!cfg) return;
- // If the exit block is unreachable, skip processing the function.
- if (cfg->getExit().pred_empty())
- return;
-
// Emit diagnostic if a recursive function call is detected for all paths.
if (checkForRecursiveFunctionCall(FD, cfg))
S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function);
@@ -632,18 +609,19 @@
} // anonymous namespace
-/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
+/// CheckFallThroughForBody - Check that we don't fall off the end of a
/// function that should return a value. Check that we don't fall off the end
/// of a noreturn function. We assume that functions and blocks not marked
/// noreturn will return.
static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
const BlockExpr *blkExpr,
- const CheckFallThroughDiagnostics& CD,
- AnalysisDeclContext &AC) {
+ const CheckFallThroughDiagnostics &CD,
+ AnalysisDeclContext &AC,
+ sema::FunctionScopeInfo *FSI) {
bool ReturnsVoid = false;
bool HasNoReturn = false;
- bool IsCoroutine = S.getCurFunction() && S.getCurFunction()->isCoroutine();
+ bool IsCoroutine = FSI->isCoroutine();
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
@@ -675,7 +653,7 @@
SourceLocation LBrace = Body->getLocStart(), RBrace = Body->getLocEnd();
auto EmitDiag = [&](SourceLocation Loc, unsigned DiagID) {
if (IsCoroutine)
- S.Diag(Loc, DiagID) << S.getCurFunction()->CoroutinePromise->getType();
+ S.Diag(Loc, DiagID) << FSI->CoroutinePromise->getType();
else
S.Diag(Loc, DiagID);
};
@@ -1410,8 +1388,8 @@
// Sort by first use so that we emit the warnings in a deterministic order.
SourceManager &SM = S.getSourceManager();
- std::sort(UsesByStmt.begin(), UsesByStmt.end(),
- [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
+ llvm::sort(UsesByStmt.begin(), UsesByStmt.end(),
+ [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(),
RHS.first->getLocStart());
});
@@ -1549,8 +1527,8 @@
// Sort the uses by their SourceLocations. While not strictly
// guaranteed to produce them in line/column order, this will provide
// a stable ordering.
- std::sort(vec->begin(), vec->end(),
- [](const UninitUse &a, const UninitUse &b) {
+ llvm::sort(vec->begin(), vec->end(),
+ [](const UninitUse &a, const UninitUse &b) {
// Prefer a more confident report over a less confident one.
if (a.getKind() != b.getKind())
return a.getKind() > b.getKind();
@@ -1623,7 +1601,7 @@
if (Verbose && CurrentFunction) {
PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
S.PDiag(diag::note_thread_warning_in_fun)
- << CurrentFunction->getNameAsString());
+ << CurrentFunction);
return OptionalNotes(1, FNote);
}
return OptionalNotes();
@@ -1634,7 +1612,7 @@
if (Verbose && CurrentFunction) {
PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
S.PDiag(diag::note_thread_warning_in_fun)
- << CurrentFunction->getNameAsString());
+ << CurrentFunction);
ONS.push_back(std::move(FNote));
}
return ONS;
@@ -1648,7 +1626,7 @@
if (Verbose && CurrentFunction) {
PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
S.PDiag(diag::note_thread_warning_in_fun)
- << CurrentFunction->getNameAsString());
+ << CurrentFunction);
ONS.push_back(std::move(FNote));
}
return ONS;
@@ -1764,7 +1742,7 @@
diag::warn_variable_requires_any_lock:
diag::warn_var_deref_requires_any_lock;
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
- << D->getNameAsString() << getLockKindFromAccessKind(AK));
+ << D << getLockKindFromAccessKind(AK));
Warnings.emplace_back(std::move(Warning), getNotes());
}
@@ -1792,7 +1770,7 @@
break;
}
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
- << D->getNameAsString()
+ << D
<< LockName << LK);
PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match)
<< *PossibleMatch);
@@ -1822,12 +1800,11 @@
break;
}
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
- << D->getNameAsString()
+ << D
<< LockName << LK);
if (Verbose && POK == POK_VarAccess) {
PartialDiagnosticAt Note(D->getLocation(),
- S.PDiag(diag::note_guarded_by_declared_here)
- << D->getNameAsString());
+ S.PDiag(diag::note_guarded_by_declared_here));
Warnings.emplace_back(std::move(Warning), getNotes(Note));
} else
Warnings.emplace_back(std::move(Warning), getNotes());
@@ -2143,7 +2120,7 @@
: (fscope->isCoroutine()
? CheckFallThroughDiagnostics::MakeForCoroutine(D)
: CheckFallThroughDiagnostics::MakeForFunction(D)));
- CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC);
+ CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC, fscope);
}
// Warning: check for unreachable code
diff --git a/lib/Sema/DelayedDiagnostic.cpp b/lib/Sema/DelayedDiagnostic.cpp
index 2555206..122b477 100644
--- a/lib/Sema/DelayedDiagnostic.cpp
+++ b/lib/Sema/DelayedDiagnostic.cpp
@@ -23,17 +23,18 @@
DelayedDiagnostic
DelayedDiagnostic::makeAvailability(AvailabilityResult AR,
- SourceLocation Loc,
+ ArrayRef<SourceLocation> Locs,
const NamedDecl *ReferringDecl,
const NamedDecl *OffendingDecl,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
StringRef Msg,
bool ObjCPropertyAccess) {
+ assert(!Locs.empty());
DelayedDiagnostic DD;
DD.Kind = Availability;
DD.Triggered = false;
- DD.Loc = Loc;
+ DD.Loc = Locs.front();
DD.AvailabilityData.ReferringDecl = ReferringDecl;
DD.AvailabilityData.OffendingDecl = OffendingDecl;
DD.AvailabilityData.UnknownObjCClass = UnknownObjCClass;
@@ -43,9 +44,14 @@
MessageData = new char [Msg.size()];
memcpy(MessageData, Msg.data(), Msg.size());
}
-
DD.AvailabilityData.Message = MessageData;
DD.AvailabilityData.MessageLen = Msg.size();
+
+ DD.AvailabilityData.SelectorLocs = new SourceLocation[Locs.size()];
+ memcpy(DD.AvailabilityData.SelectorLocs, Locs.data(),
+ sizeof(SourceLocation) * Locs.size());
+ DD.AvailabilityData.NumSelectorLocs = Locs.size();
+
DD.AvailabilityData.AR = AR;
DD.AvailabilityData.ObjCPropertyAccess = ObjCPropertyAccess;
return DD;
@@ -59,6 +65,7 @@
case Availability:
delete[] AvailabilityData.Message;
+ delete[] AvailabilityData.SelectorLocs;
break;
case ForbiddenType:
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 1e9e53b..5c0026c 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
@@ -31,7 +32,6 @@
#include "clang/Sema/Initialization.h"
#include "clang/Sema/MultiplexExternalSemaSource.h"
#include "clang/Sema/ObjCMethodList.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaConsumer.h"
@@ -162,7 +162,7 @@
ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{},
nullptr, false);
- FunctionScopes.push_back(new FunctionScopeInfo(Diags));
+ PreallocatedFunctionScope.reset(new FunctionScopeInfo(Diags));
// Initilization of data sharing attributes stack for OpenMP
InitDataSharingAttributesStack();
@@ -332,11 +332,11 @@
Sema::~Sema() {
if (VisContext) FreeVisContext();
+
// Kill all the active scopes.
- for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
- delete FunctionScopes[I];
- if (FunctionScopes.size() == 1)
- delete FunctionScopes[0];
+ for (sema::FunctionScopeInfo *FSI : FunctionScopes)
+ if (FSI != PreallocatedFunctionScope.get())
+ delete FSI;
// Tell the SemaConsumer to forget about us; we're going out of scope.
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
@@ -850,6 +850,20 @@
if (PP.isCodeCompletionEnabled())
return;
+ // Transfer late parsed template instantiations over to the pending template
+ // instantiation list. During normal compliation, the late template parser
+ // will be installed and instantiating these templates will succeed.
+ //
+ // If we are building a TU prefix for serialization, it is also safe to
+ // transfer these over, even though they are not parsed. The end of the TU
+ // should be outside of any eager template instantiation scope, so when this
+ // AST is deserialized, these templates will not be parsed until the end of
+ // the combined TU.
+ PendingInstantiations.insert(PendingInstantiations.end(),
+ LateParsedInstantiations.begin(),
+ LateParsedInstantiations.end());
+ LateParsedInstantiations.clear();
+
// Complete translation units and modules define vtables and perform implicit
// instantiations. PCH files do not.
if (TUKind != TU_Prefix) {
@@ -879,8 +893,13 @@
PendingInstantiations.insert(PendingInstantiations.begin(),
Pending.begin(), Pending.end());
}
+
PerformPendingInstantiations();
+ assert(LateParsedInstantiations.empty() &&
+ "end of TU template instantiation should not create more "
+ "late-parsed templates");
+
if (LateTemplateParserCleanup)
LateTemplateParserCleanup(OpaqueParser);
@@ -1340,17 +1359,13 @@
/// \brief Enter a new function scope
void Sema::PushFunctionScope() {
- if (FunctionScopes.size() == 1) {
- // Use the "top" function scope rather than having to allocate
- // memory for a new scope.
- FunctionScopes.back()->Clear();
- FunctionScopes.push_back(FunctionScopes.back());
- if (LangOpts.OpenMP)
- pushOpenMPFunctionRegion();
- return;
+ if (FunctionScopes.empty()) {
+ // Use PreallocatedFunctionScope to avoid allocating memory when possible.
+ PreallocatedFunctionScope->Clear();
+ FunctionScopes.push_back(PreallocatedFunctionScope.get());
+ } else {
+ FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
}
-
- FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
if (LangOpts.OpenMP)
pushOpenMPFunctionRegion();
}
@@ -1370,15 +1385,15 @@
if (LambdaScopeInfo *const LSI = getCurLambda()) {
LSI->AutoTemplateParameterDepth = Depth;
return;
- }
- llvm_unreachable(
+ }
+ llvm_unreachable(
"Remove assertion if intentionally called in a non-lambda context.");
}
void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
const Decl *D, const BlockExpr *blkExpr) {
- FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
assert(!FunctionScopes.empty() && "mismatched push/pop!");
+ FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
if (LangOpts.OpenMP)
popOpenMPFunctionRegion(Scope);
@@ -1390,7 +1405,8 @@
for (const auto &PUD : Scope->PossiblyUnreachableDiags)
Diag(PUD.Loc, PUD.PD);
- if (FunctionScopes.back() != Scope)
+ // Delete the scope unless its our preallocated scope.
+ if (Scope != PreallocatedFunctionScope.get())
delete Scope;
}
@@ -1411,6 +1427,21 @@
return getCurFunction()->ErrorTrap.hasUnrecoverableErrorOccurred();
}
+void Sema::setFunctionHasBranchIntoScope() {
+ if (!FunctionScopes.empty())
+ FunctionScopes.back()->setHasBranchIntoScope();
+}
+
+void Sema::setFunctionHasBranchProtectedScope() {
+ if (!FunctionScopes.empty())
+ FunctionScopes.back()->setHasBranchProtectedScope();
+}
+
+void Sema::setFunctionHasIndirectGoto() {
+ if (!FunctionScopes.empty())
+ FunctionScopes.back()->setHasIndirectGoto();
+}
+
BlockScopeInfo *Sema::getCurBlock() {
if (FunctionScopes.empty())
return nullptr;
@@ -1426,6 +1457,18 @@
return CurBSI;
}
+FunctionScopeInfo *Sema::getEnclosingFunction() const {
+ if (FunctionScopes.empty())
+ return nullptr;
+
+ for (int e = FunctionScopes.size() - 1; e >= 0; --e) {
+ if (isa<sema::BlockScopeInfo>(FunctionScopes[e]))
+ continue;
+ return FunctionScopes[e];
+ }
+ return nullptr;
+}
+
LambdaScopeInfo *Sema::getCurLambda(bool IgnoreNonLambdaCapturingScope) {
if (FunctionScopes.empty())
return nullptr;
@@ -1501,24 +1544,6 @@
void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector<
FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {}
-void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
- SourceLocation Loc = this->Loc;
- if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
- if (Loc.isValid()) {
- Loc.print(OS, S.getSourceManager());
- OS << ": ";
- }
- OS << Message;
-
- if (auto *ND = dyn_cast_or_null<NamedDecl>(TheDecl)) {
- OS << " '";
- ND->getNameForDiagnostic(OS, ND->getASTContext().getPrintingPolicy(), true);
- OS << "'";
- }
-
- OS << '\n';
-}
-
/// \brief Figure out if an expression could be turned into a call.
///
/// Use this when trying to recover from an error where the programmer may have
diff --git a/lib/Sema/SemaCUDA.cpp b/lib/Sema/SemaCUDA.cpp
index cac5f68..8224bd8 100644
--- a/lib/Sema/SemaCUDA.cpp
+++ b/lib/Sema/SemaCUDA.cpp
@@ -521,7 +521,7 @@
if (!getSourceManager().isInSystemHeader(Match->getLocation())) {
Diag(NewD->getLocation(),
diag::err_cuda_unattributed_constexpr_cannot_overload_device)
- << NewD->getName();
+ << NewD;
Diag(Match->getLocation(),
diag::note_cuda_conflicting_device_function_declared_here);
}
@@ -790,9 +790,12 @@
// If the caller is known-emitted, mark the callee as known-emitted.
// Otherwise, mark the call in our call graph so we can traverse it later.
bool CallerKnownEmitted = IsKnownEmitted(*this, Caller);
- if (CallerKnownEmitted)
- MarkKnownEmitted(*this, Caller, Callee, Loc);
- else {
+ if (CallerKnownEmitted) {
+ // Host-side references to a __global__ function refer to the stub, so the
+ // function itself is never emitted and therefore should not be marked.
+ if (getLangOpts().CUDAIsDevice || IdentifyCUDATarget(Callee) != CFT_Global)
+ MarkKnownEmitted(*this, Caller, Callee, Loc);
+ } else {
// If we have
// host fn calls kernel fn calls host+device,
// the HD function does not get instantiated on the host. We model this by
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 9caabde..2efdcd3 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -1097,20 +1097,14 @@
return ExprError();
break;
case Builtin::BI__builtin_operator_new:
- case Builtin::BI__builtin_operator_delete:
- if (!getLangOpts().CPlusPlus) {
- Diag(TheCall->getExprLoc(), diag::err_builtin_requires_language)
- << (BuiltinID == Builtin::BI__builtin_operator_new
- ? "__builtin_operator_new"
- : "__builtin_operator_delete")
- << "C++";
- return ExprError();
- }
- // CodeGen assumes it can find the global new and delete to call,
- // so ensure that they are declared.
- DeclareGlobalNewDelete();
- break;
-
+ case Builtin::BI__builtin_operator_delete: {
+ bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete;
+ ExprResult Res =
+ SemaBuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete);
+ if (Res.isInvalid())
+ CorrectDelayedTyposInExpr(TheCallResult.get());
+ return Res;
+ }
// check secure string manipulation functions where overflows
// are detectable at compile time
case Builtin::BI__builtin___memcpy_chk:
@@ -1215,7 +1209,6 @@
if (SemaOpenCLBuiltinKernelWorkGroupSize(*this, TheCall))
return ExprError();
break;
- break;
case Builtin::BIget_kernel_max_sub_group_size_for_ndrange:
case Builtin::BIget_kernel_sub_group_count_for_ndrange:
if (SemaOpenCLBuiltinNDRangeAndBlock(*this, TheCall))
@@ -5003,7 +4996,7 @@
const CallExpr *CE = cast<CallExpr>(E);
if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
if (const FormatArgAttr *FA = ND->getAttr<FormatArgAttr>()) {
- const Expr *Arg = CE->getArg(FA->formatIdx().getASTIndex());
+ const Expr *Arg = CE->getArg(FA->getFormatIdx().getASTIndex());
return checkFormatStringExpr(S, Arg, Args,
HasVAListArg, format_idx, firstDataArg,
Type, CallType, InFunctionCall,
@@ -5028,7 +5021,7 @@
const auto *ME = cast<ObjCMessageExpr>(E);
if (const auto *ND = ME->getMethodDecl()) {
if (const auto *FA = ND->getAttr<FormatArgAttr>()) {
- const Expr *Arg = ME->getArg(FA->formatIdx().getASTIndex());
+ const Expr *Arg = ME->getArg(FA->getFormatIdx().getASTIndex());
return checkFormatStringExpr(
S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type,
CallType, InFunctionCall, CheckedVarArgs, UncoveredArg, Offset);
@@ -9183,6 +9176,32 @@
DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow);
}
+/// Analyze the given compound assignment for the possible losing of
+/// floating-point precision.
+static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) {
+ assert(isa<CompoundAssignOperator>(E) &&
+ "Must be compound assignment operation");
+ // Recurse on the LHS and RHS in here
+ AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
+ AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
+
+ // Now check the outermost expression
+ const auto *ResultBT = E->getLHS()->getType()->getAs<BuiltinType>();
+ const auto *RBT = cast<CompoundAssignOperator>(E)
+ ->getComputationResultType()
+ ->getAs<BuiltinType>();
+
+ // If both source and target are floating points.
+ if (ResultBT && ResultBT->isFloatingPoint() && RBT && RBT->isFloatingPoint())
+ // Builtin FP kinds are ordered by increasing FP rank.
+ if (ResultBT->getKind() < RBT->getKind())
+ // We don't want to warn for system macro.
+ if (!S.SourceMgr.isInSystemMacro(E->getOperatorLoc()))
+ // warn about dropping FP rank.
+ DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(),
+ E->getOperatorLoc(),
+ diag::warn_impcast_float_result_precision);
+}
/// Diagnose an implicit cast from a floating point value to an integer value.
static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
@@ -9550,7 +9569,7 @@
return;
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar);
}
-
+
// If the vector cast is cast between two vectors of the same size, it is
// a bitcast, not a conversion.
if (S.Context.getTypeSize(Source) == S.Context.getTypeSize(Target))
@@ -9827,7 +9846,7 @@
if (E->isTypeDependent() || E->isValueDependent())
return;
-
+
// For conditional operators, we analyze the arguments as if they
// were being fed directly into the output.
if (isa<ConditionalOperator>(E)) {
@@ -9871,6 +9890,9 @@
// And with simple assignments.
if (BO->getOpcode() == BO_Assign)
return AnalyzeAssignment(S, BO);
+ // And with compound assignments.
+ if (BO->isAssignmentOp())
+ return AnalyzeCompoundAssignment(S, BO);
}
// These break the otherwise-useful invariant below. Fortunately,
@@ -10203,18 +10225,22 @@
SmallVector<Expr *, 2> Exprs(1, E);
do {
- Expr *E = Exprs.pop_back_val();
+ Expr *OriginalE = Exprs.pop_back_val();
+ Expr *E = OriginalE->IgnoreParenCasts();
- if (isa<BinaryOperator>(E->IgnoreParenCasts())) {
- E->IgnoreParenCasts()->EvaluateForOverflow(Context);
+ if (isa<BinaryOperator>(E)) {
+ E->EvaluateForOverflow(Context);
continue;
}
- if (auto InitList = dyn_cast<InitListExpr>(E))
+ if (auto InitList = dyn_cast<InitListExpr>(OriginalE))
Exprs.append(InitList->inits().begin(), InitList->inits().end());
-
- if (isa<ObjCBoxedExpr>(E))
- E->IgnoreParenCasts()->EvaluateForOverflow(Context);
+ else if (isa<ObjCBoxedExpr>(OriginalE))
+ E->EvaluateForOverflow(Context);
+ else if (auto Call = dyn_cast<CallExpr>(E))
+ Exprs.append(Call->arg_begin(), Call->arg_end());
+ else if (auto Message = dyn_cast<ObjCMessageExpr>(E))
+ Exprs.append(Message->arg_begin(), Message->arg_end());
} while (!Exprs.empty());
}
@@ -11495,7 +11521,7 @@
if (ArgRE->isObjCSelfExpr()) {
Diag(Message->getSourceRange().getBegin(),
diag::warn_objc_circular_container)
- << ArgRE->getDecl()->getName() << StringRef("super");
+ << ArgRE->getDecl() << StringRef("'super'");
}
}
} else {
@@ -11511,11 +11537,11 @@
ValueDecl *Decl = ReceiverRE->getDecl();
Diag(Message->getSourceRange().getBegin(),
diag::warn_objc_circular_container)
- << Decl->getName() << Decl->getName();
+ << Decl << Decl;
if (!ArgRE->isObjCSelfExpr()) {
Diag(Decl->getLocation(),
diag::note_objc_circular_container_declared_here)
- << Decl->getName();
+ << Decl;
}
}
}
@@ -11525,10 +11551,10 @@
ObjCIvarDecl *Decl = IvarRE->getDecl();
Diag(Message->getSourceRange().getBegin(),
diag::warn_objc_circular_container)
- << Decl->getName() << Decl->getName();
+ << Decl << Decl;
Diag(Decl->getLocation(),
diag::note_objc_circular_container_declared_here)
- << Decl->getName();
+ << Decl;
}
}
}
@@ -12237,10 +12263,10 @@
bool IsPointerAttr = Attr->getIsPointer();
// Retrieve the argument representing the 'type_tag'.
- unsigned TypeTagIdxAST = Attr->typeTagIdx().getASTIndex();
+ unsigned TypeTagIdxAST = Attr->getTypeTagIdx().getASTIndex();
if (TypeTagIdxAST >= ExprArgs.size()) {
Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
- << 0 << Attr->typeTagIdx().getSourceIndex();
+ << 0 << Attr->getTypeTagIdx().getSourceIndex();
return;
}
const Expr *TypeTagExpr = ExprArgs[TypeTagIdxAST];
@@ -12257,10 +12283,10 @@
}
// Retrieve the argument representing the 'arg_idx'.
- unsigned ArgumentIdxAST = Attr->argumentIdx().getASTIndex();
+ unsigned ArgumentIdxAST = Attr->getArgumentIdx().getASTIndex();
if (ArgumentIdxAST >= ExprArgs.size()) {
Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
- << 1 << Attr->argumentIdx().getSourceIndex();
+ << 1 << Attr->getArgumentIdx().getSourceIndex();
return;
}
const Expr *ArgumentExpr = ExprArgs[ArgumentIdxAST];
diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp
index 54dcc97..139a210 100644
--- a/lib/Sema/SemaCoroutine.cpp
+++ b/lib/Sema/SemaCoroutine.cpp
@@ -19,6 +19,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Overload.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
using namespace clang;
@@ -361,6 +362,15 @@
if (Result.isInvalid())
return ExprError();
+ // We meant exactly what we asked for. No need for typo correction.
+ if (auto *TE = dyn_cast<TypoExpr>(Result.get())) {
+ S.clearDelayedTypo(TE);
+ S.Diag(Loc, diag::err_no_member)
+ << NameInfo.getName() << Base->getType()->getAsCXXRecordDecl()
+ << Base->getSourceRange();
+ return ExprError();
+ }
+
return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
}
@@ -707,9 +717,14 @@
if (E->getValueKind() == VK_RValue)
E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
+ // The location of the `co_await` token cannot be used when constructing
+ // the member call expressions since it's before the location of `Expr`, which
+ // is used as the start of the member call expression.
+ SourceLocation CallLoc = E->getExprLoc();
+
// Build the await_ready, await_suspend, await_resume calls.
ReadySuspendResumeResult RSS =
- buildCoawaitCalls(*this, Coroutine->CoroutinePromise, Loc, E);
+ buildCoawaitCalls(*this, Coroutine->CoroutinePromise, CallLoc, E);
if (RSS.IsInvalid)
return ExprError();
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 65b6d06..8100b95 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4057,7 +4057,8 @@
}
// Redefinition coming from different files or couldn't do better above.
- Diag(Old->getLocation(), diag::note_previous_definition);
+ if (Old->getLocation().isValid())
+ Diag(Old->getLocation(), diag::note_previous_definition);
}
/// We've just determined that \p Old and \p New both appear to be definitions
@@ -5231,10 +5232,13 @@
///
/// \param Loc The location of the name of the entity being declared.
///
+/// \param IsTemplateId Whether the name is a (simple-)template-id, and thus
+/// we're declaring an explicit / partial specialization / instantiation.
+///
/// \returns true if we cannot safely recover from this error, false otherwise.
bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
DeclarationName Name,
- SourceLocation Loc) {
+ SourceLocation Loc, bool IsTemplateId) {
DeclContext *Cur = CurContext;
while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
Cur = Cur->getParent();
@@ -5261,8 +5265,9 @@
}
// Check whether the qualifying scope encloses the scope of the original
- // declaration.
- if (!Cur->Encloses(DC)) {
+ // declaration. For a template-id, we perform the checks in
+ // CheckTemplateSpecializationScope.
+ if (!Cur->Encloses(DC) && !IsTemplateId) {
if (Cur->isRecord())
Diag(Loc, diag::err_member_qualification)
<< Name << SS.getRange();
@@ -5374,8 +5379,9 @@
return nullptr;
}
if (!D.getDeclSpec().isFriendSpecified()) {
- if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC,
- Name, D.getIdentifierLoc())) {
+ if (diagnoseQualifiedDeclaration(
+ D.getCXXScopeSpec(), DC, Name, D.getIdentifierLoc(),
+ D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId)) {
if (DC->isRecord())
return nullptr;
@@ -5747,7 +5753,7 @@
TypeSourceInfo *TInfo = NewTD->getTypeSourceInfo();
QualType T = TInfo->getType();
if (T->isVariablyModifiedType()) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if (S->getFnParent() == nullptr) {
bool SizeIsNegative;
@@ -6930,7 +6936,7 @@
/// variable \p VD, or an invalid source location otherwise.
static SourceLocation getCaptureLocation(const LambdaScopeInfo *LSI,
const VarDecl *VD) {
- for (const LambdaScopeInfo::Capture &Capture : LSI->Captures) {
+ for (const Capture &Capture : LSI->Captures) {
if (Capture.isVariableCapture() && Capture.getVariable() == VD)
return Capture.getLocation();
}
@@ -7407,7 +7413,7 @@
bool isVM = T->isVariablyModifiedType();
if (isVM || NewVD->hasAttr<CleanupAttr>() ||
NewVD->hasAttr<BlocksAttr>())
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if ((isVM && NewVD->hasLinkage()) ||
(T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
@@ -8828,10 +8834,6 @@
if (CurContext->isDependentContext() && CurContext->isRecord()
&& !isFriend) {
isDependentClassScopeExplicitSpecialization = true;
- Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ?
- diag::ext_function_specialization_in_class :
- diag::err_function_specialization_in_class)
- << NewFD->getDeclName();
} else if (!NewFD->isInvalidDecl() &&
CheckFunctionTemplateSpecialization(
NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr),
@@ -9117,12 +9119,12 @@
}
// Here we have an function template explicit specialization at class scope.
- // The actually specialization will be postponed to template instatiation
+ // The actual specialization will be postponed to template instatiation
// time via the ClassScopeFunctionSpecializationDecl node.
if (isDependentClassScopeExplicitSpecialization) {
ClassScopeFunctionSpecializationDecl *NewSpec =
ClassScopeFunctionSpecializationDecl::Create(
- Context, CurContext, SourceLocation(),
+ Context, CurContext, NewFD->getLocation(),
cast<CXXMethodDecl>(NewFD),
HasExplicitTemplateArgs, TemplateArgs);
CurContext->addDecl(NewSpec);
@@ -9374,7 +9376,7 @@
TargetAttr::ParsedTargetAttr NewParsed = NewTA->parse();
// Sort order doesn't matter, it just needs to be consistent.
- std::sort(NewParsed.Features.begin(), NewParsed.Features.end());
+ llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end());
const auto *OldTA = OldFD->getAttr<TargetAttr>();
if (!OldFD->isMultiVersion()) {
@@ -9633,16 +9635,16 @@
Previous.clear();
Previous.addDecl(OldDecl);
- if (FunctionTemplateDecl *OldTemplateDecl
- = dyn_cast<FunctionTemplateDecl>(OldDecl)) {
+ if (FunctionTemplateDecl *OldTemplateDecl =
+ dyn_cast<FunctionTemplateDecl>(OldDecl)) {
auto *OldFD = OldTemplateDecl->getTemplatedDecl();
NewFD->setPreviousDeclaration(OldFD);
adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
FunctionTemplateDecl *NewTemplateDecl
= NewFD->getDescribedFunctionTemplate();
assert(NewTemplateDecl && "Template/non-template mismatch");
- if (auto *Method = dyn_cast<CXXMethodDecl>(NewFD)) {
- Method->setAccess(OldTemplateDecl->getAccess());
+ if (NewFD->isCXXClassMember()) {
+ NewFD->setAccess(OldTemplateDecl->getAccess());
NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
}
@@ -9668,7 +9670,7 @@
// This needs to happen first so that 'inline' propagates.
NewFD->setPreviousDeclaration(OldFD);
adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
- if (isa<CXXMethodDecl>(NewFD))
+ if (NewFD->isCXXClassMember())
NewFD->setAccess(OldFD->getAccess());
}
}
@@ -10335,7 +10337,7 @@
S.DiagRuntimeBehavior(DRE->getLocStart(), DRE,
S.PDiag(diag)
- << DRE->getNameInfo().getName()
+ << DRE->getDecl()
<< OrigDecl->getLocation()
<< DRE->getSourceRange());
}
@@ -10395,12 +10397,22 @@
// C++11 [dcl.spec.auto]p3
if (!Init) {
assert(VDecl && "no init for init capture deduction?");
- Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
- << VDecl->getDeclName() << Type;
- return QualType();
+
+ // Except for class argument deduction, and then for an initializing
+ // declaration only, i.e. no static at class scope or extern.
+ if (!isa<DeducedTemplateSpecializationType>(Deduced) ||
+ VDecl->hasExternalStorage() ||
+ VDecl->isStaticDataMember()) {
+ Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
+ << VDecl->getDeclName() << Type;
+ return QualType();
+ }
}
- ArrayRef<Expr*> DeduceInits = Init;
+ ArrayRef<Expr*> DeduceInits;
+ if (Init)
+ DeduceInits = Init;
+
if (DirectInit) {
if (auto *PL = dyn_cast_or_null<ParenListExpr>(Init))
DeduceInits = PL->exprs();
@@ -10644,7 +10656,7 @@
}
if (VDecl->hasLocalStorage())
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) {
VDecl->setInvalidDecl();
@@ -11178,11 +11190,11 @@
if (const RecordType *Record
= Context.getBaseElementType(Type)->getAs<RecordType>()) {
CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record->getDecl());
- // Mark the function for further checking even if the looser rules of
- // C++11 do not require such checks, so that we can diagnose
- // incompatibilities with C++98.
+ // Mark the function (if we're in one) for further checking even if the
+ // looser rules of C++11 do not require such checks, so that we can
+ // diagnose incompatibilities with C++98.
if (!CXXRecord->isPOD())
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
}
}
@@ -11318,13 +11330,14 @@
case Qualifiers::OCL_Weak:
case Qualifiers::OCL_Strong:
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
break;
}
}
- if (var->getType().isDestructedType() == QualType::DK_nontrivial_c_struct)
- getCurFunction()->setHasBranchProtectedScope();
+ if (var->hasLocalStorage() &&
+ var->getType().isDestructedType() == QualType::DK_nontrivial_c_struct)
+ setFunctionHasBranchProtectedScope();
// Warn about externally-visible variables being defined without a
// prior declaration. We only want to do this for global
@@ -12406,8 +12419,13 @@
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
SkipBodyInfo *SkipBody) {
- if (!D)
+ if (!D) {
+ // Parsing the function declaration failed in some way. Push on a fake scope
+ // anyway so we can try to parse the function body.
+ PushFunctionScope();
return D;
+ }
+
FunctionDecl *FD = nullptr;
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
@@ -12695,8 +12713,8 @@
// Try to apply the named return value optimization. We have to check
// if we can do this here because lambdas keep return statements around
// to deduce an implicit return type.
- if (getLangOpts().CPlusPlus && FD->getReturnType()->isRecordType() &&
- !FD->isDependentContext())
+ if (FD->getReturnType()->isRecordType() &&
+ (!getLangOpts().CPlusPlus || !FD->isDependentContext()))
computeNRVO(Body, getCurFunction());
}
@@ -12816,6 +12834,9 @@
getCurFunction()->ObjCWarnForNoInitDelegation = false;
}
} else {
+ // Parsing the function declaration failed in some way. Pop the fake scope
+ // we pushed on.
+ PopFunctionScopeInfo(ActivePolicy, dcl);
return nullptr;
}
@@ -13096,11 +13117,11 @@
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID))
FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
- // We make "fma" on GNU or Windows const because we know it does not set
+ // We make "fma" on some platforms const because we know it does not set
// errno in those environments even though it could set errno based on the
// C standard.
const llvm::Triple &Trip = Context.getTargetInfo().getTriple();
- if ((Trip.isGNUEnvironment() || Trip.isOSMSVCRT()) &&
+ if ((Trip.isGNUEnvironment() || Trip.isAndroid() || Trip.isOSMSVCRT()) &&
!FD->hasAttr<ConstAttr>()) {
switch (BuiltinID) {
case Builtin::BI__builtin_fma:
@@ -14301,13 +14322,10 @@
if (SS.isNotEmpty()) {
if (SS.isSet()) {
// If this is either a declaration or a definition, check the
- // nested-name-specifier against the current context. We don't do this
- // for explicit specializations, because they have similar checking
- // (with more specific diagnostics) in the call to
- // CheckMemberSpecialization, below.
- if (!isMemberSpecialization &&
- (TUK == TUK_Definition || TUK == TUK_Declaration) &&
- diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc))
+ // nested-name-specifier against the current context.
+ if ((TUK == TUK_Definition || TUK == TUK_Declaration) &&
+ diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc,
+ isMemberSpecialization))
Invalid = true;
New->setQualifierInfo(SS.getWithLocInContext(Context));
@@ -14849,6 +14867,13 @@
InvalidDecl = true;
}
+ // Anonymous bit-fields cannot be cv-qualified (CWG 2229).
+ if (!InvalidDecl && getLangOpts().CPlusPlus && !II && BitWidth &&
+ T.hasQualifiers()) {
+ InvalidDecl = true;
+ Diag(Loc, diag::err_anon_bitfield_qualifiers);
+ }
+
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
if (!InvalidDecl && T->isVariablyModifiedType()) {
@@ -15252,7 +15277,6 @@
// Get the type for the field.
const Type *FDTy = FD->getType().getTypePtr();
- Qualifiers QS = FD->getType().getQualifiers();
if (!FD->isAnonymousStructOrUnion()) {
// Remember all fields written by the user.
@@ -15393,10 +15417,7 @@
QualType T = Context.getObjCObjectPointerType(FD->getType());
FD->setType(T);
} else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
- Record && !ObjCFieldLifetimeErrReported &&
- ((!getLangOpts().CPlusPlus &&
- QS.getObjCLifetime() == Qualifiers::OCL_Weak) ||
- Record->isUnion())) {
+ Record && !ObjCFieldLifetimeErrReported && Record->isUnion()) {
// It's an error in ARC or Weak if a field has lifetime.
// We don't want to report this in a system header, though,
// so we just make the field unavailable.
@@ -15433,15 +15454,19 @@
}
}
- if (Record && !getLangOpts().CPlusPlus) {
+ if (Record && !getLangOpts().CPlusPlus && !FD->hasAttr<UnavailableAttr>()) {
QualType FT = FD->getType();
if (FT.isNonTrivialToPrimitiveDefaultInitialize())
- Record->setNonTrivialToPrimitiveDefaultInitialize();
+ Record->setNonTrivialToPrimitiveDefaultInitialize(true);
QualType::PrimitiveCopyKind PCK = FT.isNonTrivialToPrimitiveCopy();
if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial)
- Record->setNonTrivialToPrimitiveCopy();
- if (FT.isDestructedType())
- Record->setNonTrivialToPrimitiveDestroy();
+ Record->setNonTrivialToPrimitiveCopy(true);
+ if (FT.isDestructedType()) {
+ Record->setNonTrivialToPrimitiveDestroy(true);
+ Record->setParamDestroyedInCallee(true);
+ }
+ if (!FT.canPassInRegisters())
+ Record->setCanPassInRegisters(false);
}
if (Record && FD->getType().isVolatileQualified())
@@ -16003,39 +16028,10 @@
return false;
}
-namespace {
-struct DupKey {
- int64_t val;
- bool isTombstoneOrEmptyKey;
- DupKey(int64_t val, bool isTombstoneOrEmptyKey)
- : val(val), isTombstoneOrEmptyKey(isTombstoneOrEmptyKey) {}
-};
-
-static DupKey GetDupKey(const llvm::APSInt& Val) {
- return DupKey(Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue(),
- false);
-}
-
-struct DenseMapInfoDupKey {
- static DupKey getEmptyKey() { return DupKey(0, true); }
- static DupKey getTombstoneKey() { return DupKey(1, true); }
- static unsigned getHashValue(const DupKey Key) {
- return (unsigned)(Key.val * 37);
- }
- static bool isEqual(const DupKey& LHS, const DupKey& RHS) {
- return LHS.isTombstoneOrEmptyKey == RHS.isTombstoneOrEmptyKey &&
- LHS.val == RHS.val;
- }
-};
-} // end anonymous namespace
-
// Emits a warning when an element is implicitly set a value that
// a previous element has already been set to.
static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
- EnumDecl *Enum,
- QualType EnumType) {
- if (S.Diags.isIgnored(diag::warn_duplicate_enum_values, Enum->getLocation()))
- return;
+ EnumDecl *Enum, QualType EnumType) {
// Avoid anonymous enums
if (!Enum->getIdentifier())
return;
@@ -16044,20 +16040,28 @@
if (Enum->getNumPositiveBits() > 63 || Enum->getNumNegativeBits() > 64)
return;
+ if (S.Diags.isIgnored(diag::warn_duplicate_enum_values, Enum->getLocation()))
+ return;
+
typedef SmallVector<EnumConstantDecl *, 3> ECDVector;
- typedef SmallVector<ECDVector *, 3> DuplicatesVector;
+ typedef SmallVector<std::unique_ptr<ECDVector>, 3> DuplicatesVector;
typedef llvm::PointerUnion<EnumConstantDecl*, ECDVector*> DeclOrVector;
- typedef llvm::DenseMap<DupKey, DeclOrVector, DenseMapInfoDupKey>
- ValueToVectorMap;
+ typedef llvm::DenseMap<int64_t, DeclOrVector> ValueToVectorMap;
+
+ // Use int64_t as a key to avoid needing special handling for DenseMap keys.
+ auto EnumConstantToKey = [](const EnumConstantDecl *D) {
+ llvm::APSInt Val = D->getInitVal();
+ return Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue();
+ };
DuplicatesVector DupVector;
ValueToVectorMap EnumMap;
// Populate the EnumMap with all values represented by enum constants without
- // an initialier.
- for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
- EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]);
+ // an initializer.
+ for (auto *Element : Elements) {
+ EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Element);
// Null EnumConstantDecl means a previous diagnostic has been emitted for
// this constant. Skip this enum since it may be ill-formed.
@@ -16065,45 +16069,45 @@
return;
}
+ // Constants with initalizers are handled in the next loop.
if (ECD->getInitExpr())
continue;
- DupKey Key = GetDupKey(ECD->getInitVal());
- DeclOrVector &Entry = EnumMap[Key];
-
- // First time encountering this value.
- if (Entry.isNull())
- Entry = ECD;
+ // Duplicate values are handled in the next loop.
+ EnumMap.insert({EnumConstantToKey(ECD), ECD});
}
+ if (EnumMap.size() == 0)
+ return;
+
// Create vectors for any values that has duplicates.
- for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
- EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]);
+ for (auto *Element : Elements) {
+ // The last loop returned if any constant was null.
+ EnumConstantDecl *ECD = cast<EnumConstantDecl>(Element);
if (!ValidDuplicateEnum(ECD, Enum))
continue;
- DupKey Key = GetDupKey(ECD->getInitVal());
-
- DeclOrVector& Entry = EnumMap[Key];
- if (Entry.isNull())
+ auto Iter = EnumMap.find(EnumConstantToKey(ECD));
+ if (Iter == EnumMap.end())
continue;
+ DeclOrVector& Entry = Iter->second;
if (EnumConstantDecl *D = Entry.dyn_cast<EnumConstantDecl*>()) {
// Ensure constants are different.
if (D == ECD)
continue;
// Create new vector and push values onto it.
- ECDVector *Vec = new ECDVector();
+ auto Vec = llvm::make_unique<ECDVector>();
Vec->push_back(D);
Vec->push_back(ECD);
// Update entry to point to the duplicates vector.
- Entry = Vec;
+ Entry = Vec.get();
// Store the vector somewhere we can consult later for quick emission of
// diagnostics.
- DupVector.push_back(Vec);
+ DupVector.emplace_back(std::move(Vec));
continue;
}
@@ -16116,26 +16120,21 @@
}
// Emit diagnostics.
- for (DuplicatesVector::iterator DupVectorIter = DupVector.begin(),
- DupVectorEnd = DupVector.end();
- DupVectorIter != DupVectorEnd; ++DupVectorIter) {
- ECDVector *Vec = *DupVectorIter;
+ for (const auto &Vec : DupVector) {
assert(Vec->size() > 1 && "ECDVector should have at least 2 elements.");
// Emit warning for one enum constant.
- ECDVector::iterator I = Vec->begin();
- S.Diag((*I)->getLocation(), diag::warn_duplicate_enum_values)
- << (*I)->getName() << (*I)->getInitVal().toString(10)
- << (*I)->getSourceRange();
- ++I;
+ auto *FirstECD = Vec->front();
+ S.Diag(FirstECD->getLocation(), diag::warn_duplicate_enum_values)
+ << FirstECD << FirstECD->getInitVal().toString(10)
+ << FirstECD->getSourceRange();
// Emit one note for each of the remaining enum constants with
// the same value.
- for (ECDVector::iterator E = Vec->end(); I != E; ++I)
- S.Diag((*I)->getLocation(), diag::note_duplicate_element)
- << (*I)->getName() << (*I)->getInitVal().toString(10)
- << (*I)->getSourceRange();
- delete Vec;
+ for (auto *ECD : llvm::make_range(Vec->begin() + 1, Vec->end()))
+ S.Diag(ECD->getLocation(), diag::note_duplicate_element)
+ << ECD << ECD->getInitVal().toString(10)
+ << ECD->getSourceRange();
}
}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index b35c311..1d2c3b5 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -31,6 +31,7 @@
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
@@ -331,8 +332,7 @@
return false;
}
- Idx = ParamIdx(IdxInt.getLimitedValue(UINT_MAX), D);
- unsigned IdxSource = Idx.getSourceIndex();
+ unsigned IdxSource = IdxInt.getLimitedValue(UINT_MAX);
if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
<< getAttrName(AI) << AttrArgNum << IdxExpr->getSourceRange();
@@ -347,6 +347,7 @@
}
}
+ Idx = ParamIdx(IdxSource, D);
return true;
}
@@ -806,10 +807,9 @@
// Parameter indices are 1-indexed, hence Index=1
if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Index=*/1))
return;
- ParamIdx SizeArgNo(SizeArgNoVal, D);
-
if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/0))
return;
+ ParamIdx SizeArgNo(SizeArgNoVal, D);
ParamIdx NumberArgNo;
if (AL.getNumArgs() == 2) {
@@ -818,10 +818,9 @@
// Parameter indices are 1-based, hence Index=2
if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Index=*/2))
return;
- NumberArgNo = ParamIdx(Val, D);
-
if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/1))
return;
+ NumberArgNo = ParamIdx(Val, D);
}
D->addAttr(::new (S.Context)
@@ -1909,9 +1908,6 @@
static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &Attrs) {
if (hasDeclarator(D)) return;
- if (S.CheckNoReturnAttr(Attrs))
- return;
-
if (!isa<ObjCMethodDecl>(D)) {
S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attrs.getName() << ExpectedFunctionOrMethod;
@@ -1922,16 +1918,14 @@
Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex()));
}
-static void handleNoCallerSavedRegsAttr(Sema &S, Decl *D,
- const AttributeList &AL) {
- if (S.CheckNoCallerSavedRegsAttr(AL))
- return;
-
- D->addAttr(::new (S.Context) AnyX86NoCallerSavedRegistersAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
+static void handleNoCfCheckAttr(Sema &S, Decl *D, const AttributeList &Attrs) {
+ if (!S.getLangOpts().CFProtectionBranch)
+ S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored);
+ else
+ handleSimpleAttribute<AnyX86NoCfCheckAttr>(S, D, Attrs);
}
-bool Sema::CheckNoReturnAttr(const AttributeList &Attrs) {
+bool Sema::CheckAttrNoArgs(const AttributeList &Attrs) {
if (!checkAttributeNumArgs(*this, Attrs, 0)) {
Attrs.setInvalid();
return true;
@@ -1940,7 +1934,7 @@
return false;
}
-bool Sema::CheckNoCallerSavedRegsAttr(const AttributeList &AL) {
+bool Sema::CheckAttrTarget(const AttributeList &AL) {
// Check whether the attribute is valid on the current target.
if (!AL.existsInTarget(Context.getTargetInfo())) {
Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName();
@@ -1948,11 +1942,6 @@
return true;
}
- if (!checkAttributeNumArgs(*this, AL, 0)) {
- AL.setInvalid();
- return true;
- }
-
return false;
}
@@ -5062,7 +5051,7 @@
return;
// Store tags sorted and without duplicates.
- std::sort(Tags.begin(), Tags.end());
+ llvm::sort(Tags.begin(), Tags.end());
Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end());
D->addAttr(::new (S.Context)
@@ -5757,6 +5746,9 @@
return true;
}
+ if (S.CheckAttrTarget(AL))
+ return true;
+
return false;
}
@@ -6053,6 +6045,9 @@
case AttributeList::AT_NoReturn:
handleNoReturnAttr(S, D, AL);
break;
+ case AttributeList::AT_AnyX86NoCfCheck:
+ handleNoCfCheckAttr(S, D, AL);
+ break;
case AttributeList::AT_NoThrow:
handleSimpleAttribute<NoThrowAttr>(S, D, AL);
break;
@@ -6428,7 +6423,7 @@
handleTypeTagForDatatypeAttr(S, D, AL);
break;
case AttributeList::AT_AnyX86NoCallerSavedRegisters:
- handleNoCallerSavedRegsAttr(S, D, AL);
+ handleSimpleAttribute<AnyX86NoCallerSavedRegistersAttr>(S, D, AL);
break;
case AttributeList::AT_RenderScriptKernel:
handleSimpleAttribute<RenderScriptKernelAttr>(S, D, AL);
@@ -6936,6 +6931,45 @@
} // end anonymous namespace
+/// Tries to parse a string as ObjC method name.
+///
+/// \param Name The string to parse. Expected to originate from availability
+/// attribute argument.
+/// \param SlotNames The vector that will be populated with slot names. In case
+/// of unsuccessful parsing can contain invalid data.
+/// \returns A number of method parameters if parsing was successful, None
+/// otherwise.
+static Optional<unsigned>
+tryParseObjCMethodName(StringRef Name, SmallVectorImpl<StringRef> &SlotNames,
+ const LangOptions &LangOpts) {
+ // Accept replacements starting with - or + as valid ObjC method names.
+ if (!Name.empty() && (Name.front() == '-' || Name.front() == '+'))
+ Name = Name.drop_front(1);
+ if (Name.empty())
+ return None;
+ Name.split(SlotNames, ':');
+ unsigned NumParams;
+ if (Name.back() == ':') {
+ // Remove an empty string at the end that doesn't represent any slot.
+ SlotNames.pop_back();
+ NumParams = SlotNames.size();
+ } else {
+ if (SlotNames.size() != 1)
+ // Not a valid method name, just a colon-separated string.
+ return None;
+ NumParams = 0;
+ }
+ // Verify all slot names are valid.
+ bool AllowDollar = LangOpts.DollarIdents;
+ for (StringRef S : SlotNames) {
+ if (S.empty())
+ continue;
+ if (!isValidIdentifier(S, AllowDollar))
+ return None;
+ }
+ return NumParams;
+}
+
/// Returns a source location in which it's appropriate to insert a new
/// attribute for the given declaration \D.
static Optional<AttributeInsertion>
@@ -6972,7 +7006,8 @@
static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
Decl *Ctx, const NamedDecl *ReferringDecl,
const NamedDecl *OffendingDecl,
- StringRef Message, SourceLocation Loc,
+ StringRef Message,
+ ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
bool ObjCPropertyAccess) {
@@ -6994,6 +7029,8 @@
if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx))
return;
+ SourceLocation Loc = Locs.front();
+
// The declaration can have multiple availability attributes, we are looking
// at one of them.
const AvailabilityAttr *A = getAttrForPlatform(S.Context, OffendingDecl);
@@ -7139,37 +7176,55 @@
llvm_unreachable("Warning for availability of available declaration?");
}
- CharSourceRange UseRange;
- StringRef Replacement;
+ SmallVector<FixItHint, 12> FixIts;
if (K == AR_Deprecated) {
+ StringRef Replacement;
if (auto AL = OffendingDecl->getAttr<DeprecatedAttr>())
Replacement = AL->getReplacement();
if (auto AL = getAttrForPlatform(S.Context, OffendingDecl))
Replacement = AL->getReplacement();
+ CharSourceRange UseRange;
if (!Replacement.empty())
UseRange =
CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
+ if (UseRange.isValid()) {
+ if (const auto *MethodDecl = dyn_cast<ObjCMethodDecl>(ReferringDecl)) {
+ Selector Sel = MethodDecl->getSelector();
+ SmallVector<StringRef, 12> SelectorSlotNames;
+ Optional<unsigned> NumParams = tryParseObjCMethodName(
+ Replacement, SelectorSlotNames, S.getLangOpts());
+ if (NumParams && NumParams.getValue() == Sel.getNumArgs()) {
+ assert(SelectorSlotNames.size() == Locs.size());
+ for (unsigned I = 0; I < Locs.size(); ++I) {
+ if (!Sel.getNameForSlot(I).empty()) {
+ CharSourceRange NameRange = CharSourceRange::getCharRange(
+ Locs[I], S.getLocForEndOfToken(Locs[I]));
+ FixIts.push_back(FixItHint::CreateReplacement(
+ NameRange, SelectorSlotNames[I]));
+ } else
+ FixIts.push_back(
+ FixItHint::CreateInsertion(Locs[I], SelectorSlotNames[I]));
+ }
+ } else
+ FixIts.push_back(FixItHint::CreateReplacement(UseRange, Replacement));
+ } else
+ FixIts.push_back(FixItHint::CreateReplacement(UseRange, Replacement));
+ }
}
if (!Message.empty()) {
- S.Diag(Loc, diag_message) << ReferringDecl << Message
- << (UseRange.isValid() ?
- FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
+ S.Diag(Loc, diag_message) << ReferringDecl << Message << FixIts;
if (ObjCProperty)
S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
<< ObjCProperty->getDeclName() << property_note_select;
} else if (!UnknownObjCClass) {
- S.Diag(Loc, diag) << ReferringDecl
- << (UseRange.isValid() ?
- FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
+ S.Diag(Loc, diag) << ReferringDecl << FixIts;
if (ObjCProperty)
S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
<< ObjCProperty->getDeclName() << property_note_select;
} else {
- S.Diag(Loc, diag_fwdclass_message) << ReferringDecl
- << (UseRange.isValid() ?
- FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
+ S.Diag(Loc, diag_fwdclass_message) << ReferringDecl << FixIts;
S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
}
@@ -7185,8 +7240,9 @@
DD.Triggered = true;
DoEmitAvailabilityWarning(
S, DD.getAvailabilityResult(), Ctx, DD.getAvailabilityReferringDecl(),
- DD.getAvailabilityOffendingDecl(), DD.getAvailabilityMessage(), DD.Loc,
- DD.getUnknownObjCClass(), DD.getObjCProperty(), false);
+ DD.getAvailabilityOffendingDecl(), DD.getAvailabilityMessage(),
+ DD.getAvailabilitySelectorLocs(), DD.getUnknownObjCClass(),
+ DD.getObjCProperty(), false);
}
void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
@@ -7247,7 +7303,8 @@
static void EmitAvailabilityWarning(Sema &S, AvailabilityResult AR,
const NamedDecl *ReferringDecl,
const NamedDecl *OffendingDecl,
- StringRef Message, SourceLocation Loc,
+ StringRef Message,
+ ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
bool ObjCPropertyAccess) {
@@ -7255,14 +7312,14 @@
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
S.DelayedDiagnostics.add(
DelayedDiagnostic::makeAvailability(
- AR, Loc, ReferringDecl, OffendingDecl, UnknownObjCClass,
+ AR, Locs, ReferringDecl, OffendingDecl, UnknownObjCClass,
ObjCProperty, Message, ObjCPropertyAccess));
return;
}
Decl *Ctx = cast<Decl>(S.getCurLexicalContext());
DoEmitAvailabilityWarning(S, AR, Ctx, ReferringDecl, OffendingDecl,
- Message, Loc, UnknownObjCClass, ObjCProperty,
+ Message, Locs, UnknownObjCClass, ObjCProperty,
ObjCPropertyAccess);
}
@@ -7600,7 +7657,8 @@
DiagnoseUnguardedAvailability(*this, D).IssueDiagnostics(Body);
}
-void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D, SourceLocation Loc,
+void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D,
+ ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
bool AvoidPartialAvailabilityChecks) {
@@ -7637,6 +7695,6 @@
}
}
- EmitAvailabilityWarning(*this, Result, D, OffendingDecl, Message, Loc,
+ EmitAvailabilityWarning(*this, Result, D, OffendingDecl, Message, Locs,
UnknownObjCClass, ObjCPDecl, ObjCPropertyAccess);
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 51ba96f..f8a3d94 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2404,7 +2404,7 @@
// The Microsoft extension __interface does not permit bases that
// are not themselves public interfaces.
Diag(KnownBase->getLocStart(), diag::err_invalid_base_in_interface)
- << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getName()
+ << getRecordDiagFromTagKind(RD->getTagKind()) << RD
<< RD->getSourceRange();
Invalid = true;
}
@@ -2862,7 +2862,7 @@
if (AS_none !=
CXXRecordDecl::MergeAccess(P.Access, BaseField->getAccess())) {
Diag(Loc, diag::warn_shadow_field)
- << FieldName.getAsString() << RD->getName() << Base->getName();
+ << FieldName << RD << Base;
Diag(BaseField->getLocation(), diag::note_shadow_field);
Bases.erase(It);
}
@@ -3051,7 +3051,9 @@
// int X::member;
// };
if (DeclContext *DC = computeDeclContext(SS, false))
- diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc());
+ diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc(),
+ D.getName().getKind() ==
+ UnqualifiedIdKind::IK_TemplateId);
else
Diag(D.getIdentifierLoc(), diag::err_member_qualification)
<< Name << SS.getRange();
@@ -5526,7 +5528,7 @@
S.MarkFunctionReferenced(Class->getLocation(), MD);
if (Trap.hasErrorOccurred()) {
S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
- << Class->getName() << !S.getLangOpts().CPlusPlus11;
+ << Class << !S.getLangOpts().CPlusPlus11;
break;
}
@@ -5685,6 +5687,21 @@
cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
NewAttr->setInherited(true);
Member->addAttr(NewAttr);
+
+ if (MD) {
+ // Propagate DLLAttr to friend re-declarations of MD that have already
+ // been constructed.
+ for (FunctionDecl *FD = MD->getMostRecentDecl(); FD;
+ FD = FD->getPreviousDecl()) {
+ if (FD->getFriendObjectKind() == Decl::FOK_None)
+ continue;
+ assert(!getDLLAttr(FD) &&
+ "friend re-decl should not already have a DLLAttr");
+ NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
+ NewAttr->setInherited(true);
+ FD->addAttr(NewAttr);
+ }
+ }
}
}
@@ -5774,12 +5791,21 @@
}
}
-/// Determine whether a type is permitted to be passed or returned in
-/// registers, per C++ [class.temporary]p3.
-static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
+/// Determine whether a type would be destructed in the callee if it had a
+/// non-trivial destructor. The rules here are based on C++ [class.temporary]p3,
+/// which determines whether a struct can be passed to or returned from
+/// functions in registers.
+static bool paramCanBeDestroyedInCallee(Sema &S, CXXRecordDecl *D,
+ TargetInfo::CallingConvKind CCK) {
if (D->isDependentType() || D->isInvalidDecl())
return false;
+ // Clang <= 4 used the pre-C++11 rule, which ignores move operations.
+ // The PS4 platform ABI follows the behavior of Clang 3.2.
+ if (CCK == TargetInfo::CCK_ClangABI4OrPS4)
+ return !D->hasNonTrivialDestructorForCall() &&
+ !D->hasNonTrivialCopyConstructorForCall();
+
// Per C++ [class.temporary]p3, the relevant condition is:
// each copy constructor, move constructor, and destructor of X is
// either trivial or deleted, and X has at least one non-deleted copy
@@ -5821,6 +5847,77 @@
return HasNonDeletedCopyOrMove;
}
+static bool computeCanPassInRegister(bool DestroyedInCallee,
+ const CXXRecordDecl *RD,
+ TargetInfo::CallingConvKind CCK,
+ Sema &S) {
+ if (RD->isDependentType() || RD->isInvalidDecl())
+ return true;
+
+ // The param cannot be passed in registers if CanPassInRegisters is already
+ // set to false.
+ if (!RD->canPassInRegisters())
+ return false;
+
+ if (CCK != TargetInfo::CCK_MicrosoftX86_64)
+ return DestroyedInCallee;
+
+ bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
+ bool DtorIsTrivialForCall = false;
+
+ // If a class has at least one non-deleted, trivial copy constructor, it
+ // is passed according to the C ABI. Otherwise, it is passed indirectly.
+ //
+ // Note: This permits classes with non-trivial copy or move ctors to be
+ // passed in registers, so long as they *also* have a trivial copy ctor,
+ // which is non-conforming.
+ if (RD->needsImplicitCopyConstructor()) {
+ if (!RD->defaultedCopyConstructorIsDeleted()) {
+ if (RD->hasTrivialCopyConstructor())
+ CopyCtorIsTrivial = true;
+ if (RD->hasTrivialCopyConstructorForCall())
+ CopyCtorIsTrivialForCall = true;
+ }
+ } else {
+ for (const CXXConstructorDecl *CD : RD->ctors()) {
+ if (CD->isCopyConstructor() && !CD->isDeleted()) {
+ if (CD->isTrivial())
+ CopyCtorIsTrivial = true;
+ if (CD->isTrivialForCall())
+ CopyCtorIsTrivialForCall = true;
+ }
+ }
+ }
+
+ if (RD->needsImplicitDestructor()) {
+ if (!RD->defaultedDestructorIsDeleted() &&
+ RD->hasTrivialDestructorForCall())
+ DtorIsTrivialForCall = true;
+ } else if (const auto *D = RD->getDestructor()) {
+ if (!D->isDeleted() && D->isTrivialForCall())
+ DtorIsTrivialForCall = true;
+ }
+
+ // If the copy ctor and dtor are both trivial-for-calls, pass direct.
+ if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)
+ return true;
+
+ // If a class has a destructor, we'd really like to pass it indirectly
+ // because it allows us to elide copies. Unfortunately, MSVC makes that
+ // impossible for small types, which it will pass in a single register or
+ // stack slot. Most objects with dtors are large-ish, so handle that early.
+ // We can't call out all large objects as being indirect because there are
+ // multiple x64 calling conventions and the C++ ABI code shouldn't dictate
+ // how we pass large POD types.
+
+ // Note: This permits small classes with nontrivial destructors to be
+ // passed in registers, which is non-conforming.
+ if (CopyCtorIsTrivial &&
+ S.getASTContext().getTypeSize(RD->getTypeForDecl()) <= 64)
+ return true;
+ return false;
+}
+
/// \brief Perform semantic checks on a class definition that has been
/// completing, introducing implicitly-declared members, checking for
/// abstract types, etc.
@@ -5984,7 +6081,17 @@
checkClassLevelDLLAttribute(Record);
- Record->setCanPassInRegisters(computeCanPassInRegisters(*this, Record));
+ bool ClangABICompat4 =
+ Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver4;
+ TargetInfo::CallingConvKind CCK =
+ Context.getTargetInfo().getCallingConvKind(ClangABICompat4);
+ bool DestroyedInCallee = paramCanBeDestroyedInCallee(*this, Record, CCK);
+
+ if (Record->hasNonTrivialDestructor())
+ Record->setParamDestroyedInCallee(DestroyedInCallee);
+
+ Record->setCanPassInRegisters(
+ computeCanPassInRegister(DestroyedInCallee, Record, CCK, *this));
}
/// Look up the special member function that would be called by a special
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 8c22c0e..c5f581f 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -25,6 +25,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
@@ -201,10 +202,11 @@
/// \returns true if there was an error (this declaration cannot be
/// referenced), false otherwise.
///
-bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
+bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
bool AvoidPartialAvailabilityChecks) {
+ SourceLocation Loc = Locs.front();
if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
// emit them now.
@@ -288,7 +290,7 @@
return true;
}
- DiagnoseAvailabilityOfDecl(D, Loc, UnknownObjCClass, ObjCPropertyAccess,
+ DiagnoseAvailabilityOfDecl(D, Locs, UnknownObjCClass, ObjCPropertyAccess,
AvoidPartialAvailabilityChecks);
DiagnoseUnusedOfDecl(*this, D, Loc);
@@ -1657,6 +1659,16 @@
isa<VarDecl>(D) &&
NeedToCaptureVariable(cast<VarDecl>(D), NameInfo.getLoc());
+ // Drop CUDA kernel calling convention since it is invisible to the user
+ // in DRE.
+ if (const auto *FT = Ty->getAs<FunctionType>()) {
+ if (FT->getCallConv() == CC_CUDAKernel) {
+ FT = Context.adjustFunctionType(FT,
+ FT->getExtInfo().withCallingConv(CC_C));
+ Ty = QualType(FT, Ty.getQualifiers().getAsOpaqueValue());
+ }
+ }
+
DeclRefExpr *E;
if (isa<VarTemplateSpecializationDecl>(D)) {
VarTemplateSpecializationDecl *VarSpec =
@@ -1679,9 +1691,9 @@
MarkDeclRefReferenced(E);
if (getLangOpts().ObjCWeak && isa<VarDecl>(D) &&
- Ty.getObjCLifetime() == Qualifiers::OCL_Weak &&
+ Ty.getObjCLifetime() == Qualifiers::OCL_Weak && !isUnevaluatedContext() &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
- recordUseOfEvaluatedWeak(E);
+ getCurFunction()->recordUseOfWeak(E);
FieldDecl *FD = dyn_cast<FieldDecl>(D);
if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(D))
@@ -2431,8 +2443,9 @@
IV->getLocation(), SelfExpr.get(), true, true);
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
- if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
- recordUseOfEvaluatedWeak(Result);
+ if (!isUnevaluatedContext() &&
+ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
+ getCurFunction()->recordUseOfWeak(Result);
}
if (getLangOpts().ObjCAutoRefCount) {
if (CurContext->isClosure())
@@ -5510,7 +5523,7 @@
// CUDA: Kernel calls must be to global functions
if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>())
return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function)
- << FDecl->getName() << Fn->getSourceRange());
+ << FDecl << Fn->getSourceRange());
// CUDA: Kernel function must have 'void' return type
if (!FuncT->getReturnType()->isVoidType())
@@ -5520,7 +5533,7 @@
// CUDA: Calls to global functions must be configured
if (FDecl && FDecl->hasAttr<CUDAGlobalAttr>())
return ExprError(Diag(LParenLoc, diag::err_global_call_not_config)
- << FDecl->getName() << Fn->getSourceRange());
+ << FDecl << Fn->getSourceRange());
}
}
@@ -8029,7 +8042,7 @@
if (Diagnose && isa<ObjCProtocolExpr>(PRE)) {
ObjCProtocolDecl *PDecl = cast<ObjCProtocolExpr>(PRE)->getProtocol();
if (PDecl && !PDecl->hasDefinition()) {
- Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl->getName();
+ Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl;
Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl;
}
}
@@ -13045,7 +13058,7 @@
// Set the captured variables on the block.
// FIXME: Share capture structure between BlockDecl and CapturingScopeInfo!
SmallVector<BlockDecl::Capture, 4> Captures;
- for (CapturingScopeInfo::Capture &Cap : BSI->Captures) {
+ for (Capture &Cap : BSI->Captures) {
if (Cap.isThisCapture())
continue;
BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(),
@@ -13125,7 +13138,7 @@
for (const auto &CI : Result->getBlockDecl()->captures()) {
const VarDecl *var = CI.getVariable();
if (var->getType().isDestructedType() != QualType::DK_none) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
break;
}
}
@@ -13515,7 +13528,7 @@
if (DiagKind == diag::warn_incompatible_qualified_id &&
PDecl && IFace && !IFace->hasDefinition())
Diag(IFace->getLocation(), diag::note_incomplete_class_and_qualified_id)
- << IFace->getName() << PDecl->getName();
+ << IFace << PDecl;
if (SecondType == Context.OverloadTy)
NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression,
@@ -14144,7 +14157,7 @@
// Similarly to mutable captures in lambda, all the OpenMP captures by copy
// are mutable in the sense that user can change their value - they are
// private instances of the captured declarations.
- const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var);
+ const Capture &Cap = CSI->getCapture(Var);
if (Cap.isCopyCapture() &&
!(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable) &&
!(isa<CapturedRegionScopeInfo>(CSI) &&
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index d3ab003..4ec76bd 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -728,7 +728,7 @@
// exception object
const VarDecl *NRVOVariable = nullptr;
if (IsThrownVarInScope)
- NRVOVariable = getCopyElisionCandidate(QualType(), Ex, false);
+ NRVOVariable = getCopyElisionCandidate(QualType(), Ex, CES_Strict);
InitializedEntity Entity = InitializedEntity::InitializeException(
OpLoc, ExceptionObjectTy,
@@ -1114,8 +1114,9 @@
assert((!ByCopy || Explicit) && "cannot implicitly capture *this by value");
- const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt ?
- *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;
+ const int MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
+ ? *FunctionScopeIndexToStopAt
+ : FunctionScopes.size() - 1;
// Check that we can capture the *enclosing object* (referred to by '*this')
// by the capturing-entity/closure (lambda/block/etc) at
@@ -1141,7 +1142,7 @@
unsigned NumCapturingClosures = 0;
- for (unsigned idx = MaxFunctionScopesIndex; idx != 0; idx--) {
+ for (int idx = MaxFunctionScopesIndex; idx >= 0; idx--) {
if (CapturingScopeInfo *CSI =
dyn_cast<CapturingScopeInfo>(FunctionScopes[idx])) {
if (CSI->CXXThisCaptureIndex != 0) {
@@ -1196,8 +1197,8 @@
// FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated
// contexts.
QualType ThisTy = getCurrentThisType();
- for (unsigned idx = MaxFunctionScopesIndex; NumCapturingClosures;
- --idx, --NumCapturingClosures) {
+ for (int idx = MaxFunctionScopesIndex; NumCapturingClosures;
+ --idx, --NumCapturingClosures) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]);
Expr *ThisExpr = nullptr;
@@ -1442,7 +1443,7 @@
CUDAPref = S.IdentifyCUDAPreference(Caller, FD);
}
- operator bool() const { return FD; }
+ explicit operator bool() const { return FD; }
bool isBetterThan(const UsualDeallocFnInfo &Other, bool WantSize,
bool WantAlign) const {
@@ -2270,7 +2271,6 @@
llvm_unreachable("Unreachable, bad result from BestViableFunction");
}
-
/// FindAllocationFunctions - Finds the overloads of operator new and delete
/// that are appropriate for the allocation.
bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
@@ -3342,6 +3342,128 @@
return Result;
}
+static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall,
+ bool IsDelete,
+ FunctionDecl *&Operator) {
+
+ DeclarationName NewName = S.Context.DeclarationNames.getCXXOperatorName(
+ IsDelete ? OO_Delete : OO_New);
+
+ LookupResult R(S, NewName, TheCall->getLocStart(), Sema::LookupOrdinaryName);
+ S.LookupQualifiedName(R, S.Context.getTranslationUnitDecl());
+ assert(!R.empty() && "implicitly declared allocation functions not found");
+ assert(!R.isAmbiguous() && "global allocation functions are ambiguous");
+
+ // We do our own custom access checks below.
+ R.suppressDiagnostics();
+
+ SmallVector<Expr *, 8> Args(TheCall->arg_begin(), TheCall->arg_end());
+ OverloadCandidateSet Candidates(R.getNameLoc(),
+ OverloadCandidateSet::CSK_Normal);
+ for (LookupResult::iterator FnOvl = R.begin(), FnOvlEnd = R.end();
+ FnOvl != FnOvlEnd; ++FnOvl) {
+ // Even member operator new/delete are implicitly treated as
+ // static, so don't use AddMemberCandidate.
+ NamedDecl *D = (*FnOvl)->getUnderlyingDecl();
+
+ if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) {
+ S.AddTemplateOverloadCandidate(FnTemplate, FnOvl.getPair(),
+ /*ExplicitTemplateArgs=*/nullptr, Args,
+ Candidates,
+ /*SuppressUserConversions=*/false);
+ continue;
+ }
+
+ FunctionDecl *Fn = cast<FunctionDecl>(D);
+ S.AddOverloadCandidate(Fn, FnOvl.getPair(), Args, Candidates,
+ /*SuppressUserConversions=*/false);
+ }
+
+ SourceRange Range = TheCall->getSourceRange();
+
+ // Do the resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (Candidates.BestViableFunction(S, R.getNameLoc(), Best)) {
+ case OR_Success: {
+ // Got one!
+ FunctionDecl *FnDecl = Best->Function;
+ assert(R.getNamingClass() == nullptr &&
+ "class members should not be considered");
+
+ if (!FnDecl->isReplaceableGlobalAllocationFunction()) {
+ S.Diag(R.getNameLoc(), diag::err_builtin_operator_new_delete_not_usual)
+ << (IsDelete ? 1 : 0) << Range;
+ S.Diag(FnDecl->getLocation(), diag::note_non_usual_function_declared_here)
+ << R.getLookupName() << FnDecl->getSourceRange();
+ return true;
+ }
+
+ Operator = FnDecl;
+ return false;
+ }
+
+ case OR_No_Viable_Function:
+ S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call)
+ << R.getLookupName() << Range;
+ Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ return true;
+
+ case OR_Ambiguous:
+ S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call)
+ << R.getLookupName() << Range;
+ Candidates.NoteCandidates(S, OCD_ViableCandidates, Args);
+ return true;
+
+ case OR_Deleted: {
+ S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call)
+ << Best->Function->isDeleted() << R.getLookupName()
+ << S.getDeletedOrUnavailableSuffix(Best->Function) << Range;
+ Candidates.NoteCandidates(S, OCD_AllCandidates, Args);
+ return true;
+ }
+ }
+ llvm_unreachable("Unreachable, bad result from BestViableFunction");
+}
+
+ExprResult
+Sema::SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult,
+ bool IsDelete) {
+ CallExpr *TheCall = cast<CallExpr>(TheCallResult.get());
+ if (!getLangOpts().CPlusPlus) {
+ Diag(TheCall->getExprLoc(), diag::err_builtin_requires_language)
+ << (IsDelete ? "__builtin_operator_delete" : "__builtin_operator_new")
+ << "C++";
+ return ExprError();
+ }
+ // CodeGen assumes it can find the global new and delete to call,
+ // so ensure that they are declared.
+ DeclareGlobalNewDelete();
+
+ FunctionDecl *OperatorNewOrDelete = nullptr;
+ if (resolveBuiltinNewDeleteOverload(*this, TheCall, IsDelete,
+ OperatorNewOrDelete))
+ return ExprError();
+ assert(OperatorNewOrDelete && "should be found");
+
+ TheCall->setType(OperatorNewOrDelete->getReturnType());
+ for (unsigned i = 0; i != TheCall->getNumArgs(); ++i) {
+ QualType ParamTy = OperatorNewOrDelete->getParamDecl(i)->getType();
+ InitializedEntity Entity =
+ InitializedEntity::InitializeParameter(Context, ParamTy, false);
+ ExprResult Arg = PerformCopyInitialization(
+ Entity, TheCall->getArg(i)->getLocStart(), TheCall->getArg(i));
+ if (Arg.isInvalid())
+ return ExprError();
+ TheCall->setArg(i, Arg.get());
+ }
+ auto Callee = dyn_cast<ImplicitCastExpr>(TheCall->getCallee());
+ assert(Callee && Callee->getCastKind() == CK_BuiltinFnToFnPtr &&
+ "Callee expected to be implicit cast to a builtin function pointer");
+ Callee->setType(OperatorNewOrDelete->getType());
+
+ return TheCallResult;
+}
+
void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc,
bool IsDelete, bool CallCanBeVirtual,
bool WarnOnNonAbstractTypes,
@@ -4391,6 +4513,8 @@
// does not correctly compute triviality in the presence of multiple special
// members of the same kind. Revisit this once the g++ bug is fixed.
case UTT_HasTrivialDefaultConstructor:
+ if (T.isNonTrivialToPrimitiveDefaultInitialize())
+ return false;
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
// If __is_pod (type) is true then the trait is true, else if type is
// a cv class or union type (or array thereof) with a trivial default
@@ -4402,6 +4526,8 @@
!RD->hasNonTrivialDefaultConstructor();
return false;
case UTT_HasTrivialMoveConstructor:
+ if (T.isNonTrivialToPrimitiveDestructiveMove())
+ return false;
// This trait is implemented by MSVC 2012 and needed to parse the
// standard library headers. Specifically this is used as the logic
// behind std::is_trivially_move_constructible (20.9.4.3).
@@ -4411,6 +4537,8 @@
return RD->hasTrivialMoveConstructor() && !RD->hasNonTrivialMoveConstructor();
return false;
case UTT_HasTrivialCopy:
+ if (T.isNonTrivialToPrimitiveCopy())
+ return false;
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
// If __is_pod (type) is true or type is a reference type then
// the trait is true, else if type is a cv class or union type
@@ -4423,6 +4551,8 @@
!RD->hasNonTrivialCopyConstructor();
return false;
case UTT_HasTrivialMoveAssign:
+ if (T.isNonTrivialToPrimitiveDestructiveMove())
+ return false;
// This trait is implemented by MSVC 2012 and needed to parse the
// standard library headers. Specifically it is used as the logic
// behind std::is_trivially_move_assignable (20.9.4.3)
@@ -4432,6 +4562,8 @@
return RD->hasTrivialMoveAssignment() && !RD->hasNonTrivialMoveAssignment();
return false;
case UTT_HasTrivialAssign:
+ if (T.isNonTrivialToPrimitiveCopy())
+ return false;
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
// If type is const qualified or is a reference type then the
// trait is false. Otherwise if __is_pod (type) is true then the
@@ -4502,6 +4634,8 @@
return true;
case UTT_HasTrivialDestructor:
+ if (T.isDestructedType() == QualType::DK_nontrivial_c_struct)
+ return false;
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
// If __is_pod (type) is true or type is a reference type
// then the trait is true, else if type is a cv class or union
@@ -7176,9 +7310,6 @@
const bool IsFullExprInstantiationDependent = FE->isInstantiationDependent();
- ArrayRef<const FunctionScopeInfo *> FunctionScopesArrayRef(
- S.FunctionScopes.data(), S.FunctionScopes.size());
-
// All the potentially captureable variables in the current nested
// lambda (within a generic outer lambda), must be captured by an
// outer lambda that is enclosed within a non-dependent context.
@@ -7207,7 +7338,7 @@
// capture the variable in that lambda (and all its enclosing lambdas).
if (const Optional<unsigned> Index =
getStackIndexOfNearestEnclosingCaptureCapableLambda(
- FunctionScopesArrayRef, Var, S)) {
+ S.FunctionScopes, Var, S)) {
const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(), S,
&FunctionScopeIndexOfCapturableLambda);
@@ -7243,7 +7374,7 @@
// 'this' in that lambda (and all its enclosing lambdas).
if (const Optional<unsigned> Index =
getStackIndexOfNearestEnclosingCaptureCapableLambda(
- FunctionScopesArrayRef, /*0 is 'this'*/ nullptr, S)) {
+ S.FunctionScopes, /*0 is 'this'*/ nullptr, S)) {
const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation,
/*Explicit*/ false, /*BuildAndDiagnose*/ true,
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index 5bb9653..522e4bb 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -1479,8 +1479,9 @@
IsArrow);
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
- if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc))
- S.recordUseOfEvaluatedWeak(Result);
+ if (!S.isUnevaluatedContext() &&
+ !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc))
+ S.getCurFunction()->recordUseOfWeak(Result);
}
return Result;
@@ -1567,6 +1568,9 @@
// Also must look for a getter name which uses property syntax.
Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);
ObjCInterfaceDecl *IFace = MD->getClassInterface();
+ if (!IFace)
+ goto fail;
+
ObjCMethodDecl *Getter;
if ((Getter = IFace->lookupClassMethod(Sel))) {
// Check the use of this method.
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 8d017af..14db414 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -2408,11 +2408,12 @@
<< FixItHint::CreateInsertion(Loc, "[");
LBracLoc = Loc;
}
- SourceLocation SelLoc;
+ ArrayRef<SourceLocation> SelectorSlotLocs;
if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
- SelLoc = SelectorLocs.front();
+ SelectorSlotLocs = SelectorLocs;
else
- SelLoc = Loc;
+ SelectorSlotLocs = Loc;
+ SourceLocation SelLoc = SelectorSlotLocs.front();
if (ReceiverType->isDependentType()) {
// If the receiver type is dependent, we can't type-check anything
@@ -2437,7 +2438,7 @@
assert(Class && "We don't know which class we're messaging?");
// objc++ diagnoses during typename annotation.
if (!getLangOpts().CPlusPlus)
- (void)DiagnoseUseOfDecl(Class, SelLoc);
+ (void)DiagnoseUseOfDecl(Class, SelectorSlotLocs);
// Find the method we are messaging.
if (!Method) {
SourceRange TypeRange
@@ -2462,7 +2463,7 @@
if (!Method)
Method = Class->lookupPrivateClassMethod(Sel);
- if (Method && DiagnoseUseOfDecl(Method, SelLoc))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
return ExprError();
}
@@ -2632,11 +2633,12 @@
SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
SourceRange RecRange =
SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange();
- SourceLocation SelLoc;
+ ArrayRef<SourceLocation> SelectorSlotLocs;
if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
- SelLoc = SelectorLocs.front();
+ SelectorSlotLocs = SelectorLocs;
else
- SelLoc = Loc;
+ SelectorSlotLocs = Loc;
+ SourceLocation SelLoc = SelectorSlotLocs.front();
if (LBracLoc.isInvalid()) {
Diag(Loc, diag::err_missing_open_square_message_send)
@@ -2748,7 +2750,7 @@
if (!AreMultipleMethodsInGlobalPool(Sel, Method,
SourceRange(LBracLoc, RBracLoc),
receiverIsIdLike, Methods))
- DiagnoseUseOfDecl(Method, SelLoc);
+ DiagnoseUseOfDecl(Method, SelectorSlotLocs);
}
} else if (ReceiverType->isObjCClassOrClassKindOfType() ||
ReceiverType->isObjCQualifiedClassType()) {
@@ -2780,7 +2782,7 @@
if (!Method)
Method = ClassDecl->lookupPrivateClassMethod(Sel);
}
- if (Method && DiagnoseUseOfDecl(Method, SelLoc))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
return ExprError();
}
if (!Method) {
@@ -2827,7 +2829,7 @@
Method = LookupMethodInQualifiedType(Sel, QIdTy, true);
if (!Method)
Method = LookupMethodInQualifiedType(Sel, QIdTy, false);
- if (Method && DiagnoseUseOfDecl(Method, SelLoc))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
return ExprError();
} else if (const ObjCObjectPointerType *OCIType
= ReceiverType->getAsObjCInterfacePointerType()) {
@@ -2902,7 +2904,7 @@
}
}
}
- if (Method && DiagnoseUseOfDecl(Method, SelLoc, forwardClass))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs, forwardClass))
return ExprError();
} else {
// Reject other random receiver types (e.g. structs).
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 19d2de7..1b9702f 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -904,6 +904,10 @@
ParamInfo.getDeclSpec().isConstexprSpecified());
if (ExplicitParams)
CheckCXXDefaultArguments(Method);
+
+ // This represents the function body for the lambda function, check if we
+ // have to apply optnone due to a pragma.
+ AddRangeBasedOptnone(Method);
// Attributes on the lambda apply to the method.
ProcessDeclAttributes(CurScope, Method, ParamInfo);
@@ -1388,8 +1392,9 @@
Class->addDecl(Conversion);
}
-static ExprResult performLambdaVarCaptureInitialization(
- Sema &S, const LambdaScopeInfo::Capture &Capture, FieldDecl *Field) {
+static ExprResult performLambdaVarCaptureInitialization(Sema &S,
+ const Capture &Capture,
+ FieldDecl *Field) {
assert(Capture.isVariableCapture() && "not a variable capture");
auto *Var = Capture.getVariable();
@@ -1443,7 +1448,7 @@
llvm_unreachable("Unknown implicit capture style");
}
-bool Sema::CaptureHasSideEffects(const LambdaScopeInfo::Capture &From) {
+bool Sema::CaptureHasSideEffects(const Capture &From) {
if (!From.isVLATypeCapture()) {
Expr *Init = From.getInitExpr();
if (Init && Init->HasSideEffects(Context))
@@ -1468,7 +1473,7 @@
return false;
}
-void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) {
+void Sema::DiagnoseUnusedLambdaCapture(const Capture &From) {
if (CaptureHasSideEffects(From))
return;
@@ -1523,7 +1528,7 @@
// Translate captures.
auto CurField = Class->field_begin();
for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) {
- const LambdaScopeInfo::Capture &From = LSI->Captures[I];
+ const Capture &From = LSI->Captures[I];
assert(!From.isBlockCapture() && "Cannot capture __block variables");
bool IsImplicit = I >= LSI->NumExplicitCaptures;
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index dd54fb4..05bf303 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -187,7 +187,7 @@
}
void done() {
- std::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
+ llvm::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
}
typedef ListTy::const_iterator const_iterator;
@@ -4529,7 +4529,8 @@
if (S && S->getContinueParent())
Consumer.addKeywordResult("continue");
- if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
+ if (SemaRef.getCurFunction() &&
+ !SemaRef.getCurFunction()->SwitchStack.empty()) {
Consumer.addKeywordResult("case");
Consumer.addKeywordResult("default");
}
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index be51787..ca9dc32 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -803,7 +803,8 @@
/// \brief Build a variable declaration for OpenMP loop iteration variable.
static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
- StringRef Name, const AttrVec *Attrs = nullptr) {
+ StringRef Name, const AttrVec *Attrs = nullptr,
+ DeclRefExpr *OrigRef = nullptr) {
DeclContext *DC = SemaRef.CurContext;
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
@@ -815,6 +816,10 @@
Decl->addAttr(*I);
}
Decl->setImplicit();
+ if (OrigRef) {
+ Decl->addAttr(
+ OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
+ }
return Decl;
}
@@ -1210,6 +1215,17 @@
DSAStack->popFunction(OldFSI);
}
+static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
+isDeclareTargetDeclaration(const ValueDecl *VD) {
+ for (const auto *D : VD->redecls()) {
+ if (!D->hasAttrs())
+ continue;
+ if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
+ return Attr->getMapType();
+ }
+ return llvm::None;
+}
+
bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
@@ -1382,13 +1398,15 @@
// If we are attempting to capture a global variable in a directive with
// 'target' we return true so that this global is also mapped to the device.
//
- // FIXME: If the declaration is enclosed in a 'declare target' directive,
- // then it should not be captured. Therefore, an extra check has to be
- // inserted here once support for 'declare target' is added.
- //
auto *VD = dyn_cast<VarDecl>(D);
- if (VD && !VD->hasLocalStorage() && isInOpenMPTargetExecutionDirective())
+ if (VD && !VD->hasLocalStorage() && isInOpenMPTargetExecutionDirective()) {
+ // If the declaration is enclosed in a 'declare target' directive,
+ // then it should not be captured.
+ //
+ if (isDeclareTargetDeclaration(VD))
+ return nullptr;
return VD;
+ }
if (DSAStack->getCurrentDirective() != OMPD_unknown &&
(!DSAStack->isClauseParsingMode() ||
@@ -1458,7 +1476,11 @@
}
if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
NewLevel)) {
- OMPC = OMPC_firstprivate;
+ OMPC = OMPC_map;
+ if (D->getType()->isScalarType() &&
+ DSAStack->getDefaultDMAAtLevel(NewLevel) !=
+ DefaultMapAttributes::DMA_tofrom_scalar)
+ OMPC = OMPC_firstprivate;
break;
}
}
@@ -1521,7 +1543,7 @@
// region uses original variable for proper diagnostics.
auto *VDPrivate = buildVarDecl(
*this, DE->getExprLoc(), Type.getUnqualifiedType(),
- VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+ VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
ActOnUninitializedDecl(VDPrivate);
if (VDPrivate->isInvalidDecl())
continue;
@@ -1916,7 +1938,10 @@
return;
// Skip internally declared static variables.
- if (VD->hasGlobalStorage() && !CS->capturesVariable(VD))
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ isDeclareTargetDeclaration(VD);
+ if (VD->hasGlobalStorage() && !CS->capturesVariable(VD) &&
+ (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link))
return;
auto ELoc = E->getExprLoc();
@@ -1963,7 +1988,7 @@
IsFirstprivate =
IsFirstprivate ||
(VD->getType().getNonReferenceType()->isScalarType() &&
- Stack->getDefaultDMA() != DMA_tofrom_scalar);
+ Stack->getDefaultDMA() != DMA_tofrom_scalar && !Res);
if (IsFirstprivate)
ImplicitFirstprivate.emplace_back(E);
else
@@ -3572,7 +3597,7 @@
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
DSAStack->isCancelRegion());
@@ -4202,9 +4227,12 @@
Expr *OpenMPIterationSpaceChecker::BuildPrivateCounterVar() const {
if (LCDecl && !LCDecl->isInvalidDecl()) {
auto Type = LCDecl->getType().getNonReferenceType();
- auto *PrivateVar =
- buildVarDecl(SemaRef, DefaultLoc, Type, LCDecl->getName(),
- LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr);
+ auto *PrivateVar = buildVarDecl(
+ SemaRef, DefaultLoc, Type, LCDecl->getName(),
+ LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
+ isa<VarDecl>(LCDecl)
+ ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
+ : nullptr);
if (PrivateVar->isInvalidDecl())
return nullptr;
return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
@@ -5281,7 +5309,7 @@
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B);
}
@@ -5317,7 +5345,7 @@
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B, DSAStack->isCancelRegion());
}
@@ -5357,7 +5385,7 @@
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B);
}
@@ -5394,7 +5422,7 @@
return StmtError();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
DSAStack->isCancelRegion());
@@ -5408,7 +5436,7 @@
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt,
@@ -5424,7 +5452,7 @@
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
// OpenMP [2.7.3, single Construct, Restrictions]
// The copyprivate clause must not be used with the nowait clause.
@@ -5454,7 +5482,7 @@
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
}
@@ -5508,7 +5536,7 @@
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
Clauses, AStmt);
@@ -5556,7 +5584,7 @@
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelForDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B,
DSAStack->isCancelRegion());
@@ -5601,7 +5629,7 @@
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -5639,7 +5667,7 @@
return StmtError();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPParallelSectionsDirective::Create(
Context, StartLoc, EndLoc, Clauses, AStmt, DSAStack->isCancelRegion());
@@ -5659,7 +5687,7 @@
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
DSAStack->isCancelRegion());
@@ -5689,7 +5717,7 @@
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt,
@@ -5772,7 +5800,7 @@
if (AStmt) {
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
}
return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
@@ -6442,7 +6470,7 @@
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
X, V, E, UE, IsXLHSInRHSPart,
@@ -6507,7 +6535,7 @@
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
@@ -6537,7 +6565,7 @@
CS->getCapturedDecl()->setNothrow();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetParallelDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt);
@@ -6592,7 +6620,7 @@
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetParallelForDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt,
B, DSAStack->isCancelRegion());
@@ -6629,7 +6657,7 @@
return StmtError();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt);
@@ -6756,7 +6784,7 @@
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -6879,7 +6907,7 @@
if (checkReductionClauseWithNogroup(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
@@ -6929,7 +6957,7 @@
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
@@ -6955,7 +6983,7 @@
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPDistributeDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
@@ -6999,7 +7027,7 @@
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPDistributeParallelForDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
DSAStack->isCancelRegion());
@@ -7058,7 +7086,7 @@
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPDistributeParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -7115,7 +7143,7 @@
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPDistributeSimdDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
@@ -7171,7 +7199,7 @@
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -7228,7 +7256,7 @@
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetSimdDirective::Create(Context, StartLoc, EndLoc,
NestedLoopCount, Clauses, AStmt, B);
}
@@ -7271,7 +7299,7 @@
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp teams distribute loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7334,7 +7362,7 @@
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7397,7 +7425,7 @@
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7446,7 +7474,7 @@
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DSAStack->setParentTeamsRegionLoc(StartLoc);
@@ -7480,7 +7508,7 @@
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
AStmt);
@@ -7525,7 +7553,7 @@
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp target teams distribute loop exprs were not built");
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDistributeDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -7580,7 +7608,7 @@
}
}
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDistributeParallelForDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
DSAStack->isCancelRegion());
@@ -7641,7 +7669,7 @@
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -7699,7 +7727,7 @@
if (checkSimdlenSafelenSpecified(*this, Clauses))
return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return OMPTargetTeamsDistributeSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
@@ -9318,8 +9346,10 @@
// IdResolver, so the code in the OpenMP region uses original variable for
// proper diagnostics.
Type = Type.getUnqualifiedType();
- auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ auto VDPrivate =
+ buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
ActOnUninitializedDecl(VDPrivate);
if (VDPrivate->isInvalidDecl())
continue;
@@ -9557,8 +9587,10 @@
}
Type = Type.getUnqualifiedType();
- auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ auto VDPrivate =
+ buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
// Generate helper private variable and initialize it with the value of the
// original variable. The address of the original variable is replaced by
// the address of the new private variable in the CodeGen. This new variable
@@ -10450,8 +10482,10 @@
Context.getAsArrayType(D->getType().getNonReferenceType()))
PrivateTy = D->getType().getNonReferenceType();
// Private copy.
- auto *PrivateVD = buildVarDecl(S, ELoc, PrivateTy, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ auto *PrivateVD =
+ buildVarDecl(S, ELoc, PrivateTy, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
// Add initializer for private variable.
Expr *Init = nullptr;
auto *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
@@ -10907,8 +10941,10 @@
Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
// Build private copy of original var.
- auto *Private = buildVarDecl(*this, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ auto *Private =
+ buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
auto *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
// Build var to save initial value.
VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
@@ -12450,7 +12486,7 @@
// Enter new function scope.
PushFunctionScope();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
getCurFunction()->setHasOMPDeclareReductionCombiner();
if (S != nullptr)
@@ -12506,7 +12542,7 @@
// Enter new function scope.
PushFunctionScope();
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
if (S != nullptr)
PushDeclContext(S, DRD);
@@ -13068,8 +13104,10 @@
}
// Build the private variable and the expression that refers to it.
- auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(),
- D->hasAttrs() ? &D->getAttrs() : nullptr);
+ auto VDPrivate =
+ buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr,
+ VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
if (VDPrivate->isInvalidDecl())
continue;
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 2c03f69..e917bcc 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1481,7 +1481,6 @@
.getTypePtr());
Changed = true;
}
-
// Convert FromFPT's ExtParameterInfo if necessary. The conversion is valid
// only if the ExtParameterInfo lists of the two function prototypes can be
// merged and the merged list is identical to ToFPT's ExtParameterInfo list.
@@ -6245,12 +6244,17 @@
if (!Function->isVariadic() && Args.size() < Function->getNumParams()) {
for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) {
ParmVarDecl *P = Function->getParamDecl(i);
- ExprResult R = S.PerformCopyInitialization(
- InitializedEntity::InitializeParameter(S.Context,
- Function->getParamDecl(i)),
- SourceLocation(),
- P->hasUninstantiatedDefaultArg() ? P->getUninstantiatedDefaultArg()
- : P->getDefaultArg());
+ Expr *DefArg = P->hasUninstantiatedDefaultArg()
+ ? P->getUninstantiatedDefaultArg()
+ : P->getDefaultArg();
+ // This can only happen in code completion, i.e. when PartialOverloading
+ // is true.
+ if (!DefArg)
+ return false;
+ ExprResult R =
+ S.PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ S.Context, Function->getParamDecl(i)),
+ SourceLocation(), DefArg);
if (R.isInvalid())
return false;
ConvertedArgs.push_back(R.get());
@@ -10683,8 +10687,8 @@
// in general, want to list every possible builtin candidate.
}
- std::sort(Cands.begin(), Cands.end(),
- CompareTemplateSpecCandidatesForDisplay(S));
+ llvm::sort(Cands.begin(), Cands.end(),
+ CompareTemplateSpecCandidatesForDisplay(S));
// FIXME: Perhaps rename OverloadsShown and getShowOverloads()
// for generalization purposes (?).
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index f09a6f7..a267670 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -190,11 +190,12 @@
Sema &S;
unsigned ResultIndex;
SourceLocation GenericLoc;
+ bool IsUnique;
SmallVector<Expr *, 4> Semantics;
- PseudoOpBuilder(Sema &S, SourceLocation genericLoc)
+ PseudoOpBuilder(Sema &S, SourceLocation genericLoc, bool IsUnique)
: S(S), ResultIndex(PseudoObjectExpr::NoResult),
- GenericLoc(genericLoc) {}
+ GenericLoc(genericLoc), IsUnique(IsUnique) {}
virtual ~PseudoOpBuilder() {}
@@ -208,6 +209,9 @@
assert(ResultIndex == PseudoObjectExpr::NoResult);
ResultIndex = Semantics.size();
Semantics.push_back(resultExpr);
+ // An OVE is not unique if it is used as the result expression.
+ if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))
+ OVE->setIsUnique(false);
}
ExprResult buildRValueOperation(Expr *op);
@@ -227,6 +231,9 @@
void setResultToLastSemantic() {
assert(ResultIndex == PseudoObjectExpr::NoResult);
ResultIndex = Semantics.size() - 1;
+ // An OVE is not unique if it is used as the result expression.
+ if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))
+ OVE->setIsUnique(false);
}
/// Return true if assignments have a non-void result.
@@ -274,10 +281,10 @@
Selector GetterSelector;
public:
- ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
- PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
- SyntacticRefExpr(nullptr), InstanceReceiver(nullptr), Getter(nullptr),
- Setter(nullptr) {
+ ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr, bool IsUnique)
+ : PseudoOpBuilder(S, refExpr->getLocation(), IsUnique),
+ RefExpr(refExpr), SyntacticRefExpr(nullptr),
+ InstanceReceiver(nullptr), Getter(nullptr), Setter(nullptr) {
}
ExprResult buildRValueOperation(Expr *op);
@@ -314,11 +321,10 @@
Selector AtIndexSetterSelector;
public:
- ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) :
- PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
- RefExpr(refExpr),
- InstanceBase(nullptr), InstanceKey(nullptr),
- AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
+ ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr, bool IsUnique)
+ : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
+ RefExpr(refExpr), InstanceBase(nullptr), InstanceKey(nullptr),
+ AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
ExprResult buildRValueOperation(Expr *op);
ExprResult buildAssignmentOperation(Scope *Sc,
@@ -342,11 +348,11 @@
MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E);
public:
- MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) :
- PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
- RefExpr(refExpr), InstanceBase(nullptr) {}
- MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr)
- : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
+ MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr, bool IsUnique)
+ : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
+ RefExpr(refExpr), InstanceBase(nullptr) {}
+ MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr, bool IsUnique)
+ : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
InstanceBase(nullptr) {
RefExpr = getBaseMSProperty(refExpr);
}
@@ -365,7 +371,9 @@
new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
e->getValueKind(), e->getObjectKind(),
e);
-
+ if (IsUnique)
+ captured->setIsUnique(true);
+
// Make sure we bind that in the semantics.
addSemanticExpr(captured);
return captured;
@@ -397,6 +405,8 @@
if (e == Semantics[index]) break;
}
ResultIndex = index;
+ // An OVE is not unique if it is used as the result expression.
+ cast<OpaqueValueExpr>(e)->setIsUnique(false);
return cast<OpaqueValueExpr>(e);
}
@@ -965,11 +975,11 @@
}
ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
- if (isWeakProperty() &&
+ if (isWeakProperty() && !S.isUnevaluatedContext() &&
!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
SyntacticForm->getLocStart()))
- S.recordUseOfEvaluatedWeak(SyntacticRefExpr,
- SyntacticRefExpr->isMessagingGetter());
+ S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,
+ SyntacticRefExpr->isMessagingGetter());
return PseudoOpBuilder::complete(SyntacticForm);
}
@@ -1528,20 +1538,20 @@
Expr *opaqueRef = E->IgnoreParens();
if (ObjCPropertyRefExpr *refExpr
= dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
- ObjCPropertyOpBuilder builder(*this, refExpr);
+ ObjCPropertyOpBuilder builder(*this, refExpr, true);
return builder.buildRValueOperation(E);
}
else if (ObjCSubscriptRefExpr *refExpr
= dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
- ObjCSubscriptOpBuilder builder(*this, refExpr);
+ ObjCSubscriptOpBuilder builder(*this, refExpr, true);
return builder.buildRValueOperation(E);
} else if (MSPropertyRefExpr *refExpr
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- MSPropertyOpBuilder builder(*this, refExpr);
+ MSPropertyOpBuilder builder(*this, refExpr, true);
return builder.buildRValueOperation(E);
} else if (MSPropertySubscriptExpr *RefExpr =
dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
- MSPropertyOpBuilder Builder(*this, RefExpr);
+ MSPropertyOpBuilder Builder(*this, RefExpr, true);
return Builder.buildRValueOperation(E);
} else {
llvm_unreachable("unknown pseudo-object kind!");
@@ -1560,18 +1570,18 @@
Expr *opaqueRef = op->IgnoreParens();
if (ObjCPropertyRefExpr *refExpr
= dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
- ObjCPropertyOpBuilder builder(*this, refExpr);
+ ObjCPropertyOpBuilder builder(*this, refExpr, false);
return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
} else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
Diag(opcLoc, diag::err_illegal_container_subscripting_op);
return ExprError();
} else if (MSPropertyRefExpr *refExpr
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- MSPropertyOpBuilder builder(*this, refExpr);
+ MSPropertyOpBuilder builder(*this, refExpr, false);
return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
} else if (MSPropertySubscriptExpr *RefExpr
= dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
- MSPropertyOpBuilder Builder(*this, RefExpr);
+ MSPropertyOpBuilder Builder(*this, RefExpr, false);
return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
} else {
llvm_unreachable("unknown pseudo-object kind!");
@@ -1594,22 +1604,23 @@
RHS = result.get();
}
+ bool IsSimpleAssign = opcode == BO_Assign;
Expr *opaqueRef = LHS->IgnoreParens();
if (ObjCPropertyRefExpr *refExpr
= dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
- ObjCPropertyOpBuilder builder(*this, refExpr);
+ ObjCPropertyOpBuilder builder(*this, refExpr, IsSimpleAssign);
return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else if (ObjCSubscriptRefExpr *refExpr
= dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
- ObjCSubscriptOpBuilder builder(*this, refExpr);
+ ObjCSubscriptOpBuilder builder(*this, refExpr, IsSimpleAssign);
return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else if (MSPropertyRefExpr *refExpr
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- MSPropertyOpBuilder builder(*this, refExpr);
+ MSPropertyOpBuilder builder(*this, refExpr, IsSimpleAssign);
return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else if (MSPropertySubscriptExpr *RefExpr
= dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
- MSPropertyOpBuilder Builder(*this, RefExpr);
+ MSPropertyOpBuilder Builder(*this, RefExpr, IsSimpleAssign);
return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else {
llvm_unreachable("unknown pseudo-object kind!");
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index b770185..fb2e0ba 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -557,7 +557,7 @@
return StmtError();
if (IsConstexpr || isa<ObjCAvailabilityCheckExpr>(Cond.get().second))
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
DiagnoseUnusedExprResult(thenStmt);
DiagnoseUnusedExprResult(elseStmt);
@@ -688,7 +688,7 @@
if (Cond.isInvalid())
return StmtError();
- getCurFunction()->setHasBranchIntoScope();
+ setFunctionHasBranchIntoScope();
SwitchStmt *SS = new (Context)
SwitchStmt(Context, InitStmt, Cond.get().first, Cond.get().second);
@@ -1873,7 +1873,7 @@
Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
Stmt *First, Expr *collection,
SourceLocation RParenLoc) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
ExprResult CollectionExprResult =
CheckObjCForCollectionOperand(ForLoc, collection);
@@ -2784,7 +2784,7 @@
StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
LabelDecl *TheDecl) {
- getCurFunction()->setHasBranchIntoScope();
+ setFunctionHasBranchIntoScope();
TheDecl->markUsed(Context);
return new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc);
}
@@ -2811,7 +2811,7 @@
return StmtError();
E = ExprRes.get();
- getCurFunction()->setHasIndirectGoto();
+ setFunctionHasIndirectGoto();
return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E);
}
@@ -2862,7 +2862,7 @@
/// \param E The expression being returned from the function or block, or
/// being thrown.
///
-/// \param AllowParamOrMoveConstructible Whether we allow function parameters or
+/// \param CESK Whether we allow function parameters or
/// id-expressions that could be moved out of the function to be considered NRVO
/// candidates. C++ prohibits these for NRVO itself, but we re-use this logic to
/// determine whether we should try to move as part of a return or throw (which
@@ -2871,10 +2871,7 @@
/// \returns The NRVO candidate variable, if the return statement may use the
/// NRVO, or NULL if there is no such candidate.
VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, Expr *E,
- bool AllowParamOrMoveConstructible) {
- if (!getLangOpts().CPlusPlus)
- return nullptr;
-
+ CopyElisionSemanticsKind CESK) {
// - in a return statement in a function [where] ...
// ... the expression is the name of a non-volatile automatic object ...
DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
@@ -2884,13 +2881,13 @@
if (!VD)
return nullptr;
- if (isCopyElisionCandidate(ReturnType, VD, AllowParamOrMoveConstructible))
+ if (isCopyElisionCandidate(ReturnType, VD, CESK))
return VD;
return nullptr;
}
bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
- bool AllowParamOrMoveConstructible) {
+ CopyElisionSemanticsKind CESK) {
QualType VDType = VD->getType();
// - in a return statement in a function with ...
// ... a class return type ...
@@ -2899,14 +2896,14 @@
return false;
// ... the same cv-unqualified type as the function return type ...
// When considering moving this expression out, allow dissimilar types.
- if (!AllowParamOrMoveConstructible && !VDType->isDependentType() &&
+ if (!(CESK & CES_AllowDifferentTypes) && !VDType->isDependentType() &&
!Context.hasSameUnqualifiedType(ReturnType, VDType))
return false;
}
// ...object (other than a function or catch-clause parameter)...
if (VD->getKind() != Decl::Var &&
- !(AllowParamOrMoveConstructible && VD->getKind() == Decl::ParmVar))
+ !((CESK & CES_AllowParameters) && VD->getKind() == Decl::ParmVar))
return false;
if (VD->isExceptionVariable()) return false;
@@ -2918,7 +2915,7 @@
// variable will no longer be used.
if (VD->hasAttr<BlocksAttr>()) return false;
- if (AllowParamOrMoveConstructible)
+ if (CESK & CES_AllowDifferentTypes)
return true;
// ...non-volatile...
@@ -2933,6 +2930,71 @@
return true;
}
+/// \brief Try to perform the initialization of a potentially-movable value,
+/// which is the operand to a return or throw statement.
+///
+/// This routine implements C++14 [class.copy]p32, which attempts to treat
+/// returned lvalues as rvalues in certain cases (to prefer move construction),
+/// then falls back to treating them as lvalues if that failed.
+///
+/// \param Res We will fill this in if move-initialization was possible.
+/// If move-initialization is not possible, such that we must fall back to
+/// treating the operand as an lvalue, we will leave Res in its original
+/// invalid state.
+static void TryMoveInitialization(Sema& S,
+ const InitializedEntity &Entity,
+ const VarDecl *NRVOCandidate,
+ QualType ResultType,
+ Expr *&Value,
+ ExprResult &Res) {
+ ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
+ CK_NoOp, Value, VK_XValue);
+
+ Expr *InitExpr = &AsRvalue;
+
+ InitializationKind Kind = InitializationKind::CreateCopy(
+ Value->getLocStart(), Value->getLocStart());
+
+ InitializationSequence Seq(S, Entity, Kind, InitExpr);
+
+ if (!Seq)
+ return;
+
+ for (const InitializationSequence::Step &Step : Seq.steps()) {
+ if (Step.Kind != InitializationSequence::SK_ConstructorInitialization &&
+ Step.Kind != InitializationSequence::SK_UserConversion)
+ continue;
+
+ FunctionDecl *FD = Step.Function.Function;
+ if (isa<CXXConstructorDecl>(FD)) {
+ // C++14 [class.copy]p32:
+ // [...] If the first overload resolution fails or was not performed,
+ // or if the type of the first parameter of the selected constructor
+ // is not an rvalue reference to the object's type (possibly
+ // cv-qualified), overload resolution is performed again, considering
+ // the object as an lvalue.
+ const RValueReferenceType *RRefType =
+ FD->getParamDecl(0)->getType()->getAs<RValueReferenceType>();
+ if (!RRefType)
+ break;
+ if (!S.Context.hasSameUnqualifiedType(RRefType->getPointeeType(),
+ NRVOCandidate->getType()))
+ break;
+ } else {
+ continue;
+ }
+
+ // Promote "AsRvalue" to the heap, since we now need this
+ // expression node to persist.
+ Value = ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp,
+ Value, nullptr, VK_XValue);
+
+ // Complete type-checking the initialization of the return type
+ // using the constructor we found.
+ Res = Seq.Perform(S, Entity, Kind, Value);
+ }
+}
+
/// \brief Perform the initialization of a potentially-movable value, which
/// is the result of return value.
///
@@ -2956,53 +3018,14 @@
// were designated by an rvalue.
ExprResult Res = ExprError();
- if (AllowNRVO && !NRVOCandidate)
- NRVOCandidate = getCopyElisionCandidate(ResultType, Value, true);
+ if (AllowNRVO) {
+ if (!NRVOCandidate) {
+ NRVOCandidate = getCopyElisionCandidate(ResultType, Value, CES_Default);
+ }
- if (AllowNRVO && NRVOCandidate) {
- ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
- CK_NoOp, Value, VK_XValue);
-
- Expr *InitExpr = &AsRvalue;
-
- InitializationKind Kind = InitializationKind::CreateCopy(
- Value->getLocStart(), Value->getLocStart());
-
- InitializationSequence Seq(*this, Entity, Kind, InitExpr);
- if (Seq) {
- for (const InitializationSequence::Step &Step : Seq.steps()) {
- if (!(Step.Kind ==
- InitializationSequence::SK_ConstructorInitialization ||
- (Step.Kind == InitializationSequence::SK_UserConversion &&
- isa<CXXConstructorDecl>(Step.Function.Function))))
- continue;
-
- CXXConstructorDecl *Constructor =
- cast<CXXConstructorDecl>(Step.Function.Function);
-
- const RValueReferenceType *RRefType
- = Constructor->getParamDecl(0)->getType()
- ->getAs<RValueReferenceType>();
-
- // [...] If the first overload resolution fails or was not performed, or
- // if the type of the first parameter of the selected constructor is not
- // an rvalue reference to the object's type (possibly cv-qualified),
- // overload resolution is performed again, considering the object as an
- // lvalue.
- if (!RRefType ||
- !Context.hasSameUnqualifiedType(RRefType->getPointeeType(),
- NRVOCandidate->getType()))
- break;
-
- // Promote "AsRvalue" to the heap, since we now need this
- // expression node to persist.
- Value = ImplicitCastExpr::Create(Context, Value->getType(), CK_NoOp,
- Value, nullptr, VK_XValue);
-
- // Complete type-checking the initialization of the return type
- // using the constructor we found.
- Res = Seq.Perform(*this, Entity, Kind, Value);
- }
+ if (NRVOCandidate) {
+ TryMoveInitialization(*this, Entity, NRVOCandidate, ResultType, Value,
+ Res);
}
}
@@ -3149,7 +3172,7 @@
// In C++ the return statement is handled via a copy initialization.
// the C version of which boils down to CheckSingleAssignmentConstraints.
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, CES_Strict);
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
FnRetType,
NRVOCandidate != nullptr);
@@ -3162,7 +3185,7 @@
RetValExp = Res.get();
CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc);
} else {
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, CES_Strict);
}
if (RetValExp) {
@@ -3532,7 +3555,7 @@
// In C++ the return statement is handled via a copy initialization,
// the C version of which boils down to CheckSingleAssignmentConstraints.
if (RetValExp)
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, CES_Strict);
if (!HasDependentReturnType && !RetValExp->isTypeDependent()) {
// we have a non-void function with an expression, continue checking
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
@@ -3607,7 +3630,7 @@
if (!getLangOpts().ObjCExceptions)
Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try";
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
unsigned NumCatchStmts = CatchStmts.size();
return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(),
NumCatchStmts, Finally);
@@ -3698,7 +3721,7 @@
Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr,
Stmt *SyncBody) {
// We can't jump into or indirect-jump out of a @synchronized block.
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody);
}
@@ -3714,7 +3737,7 @@
StmtResult
Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) {
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body);
}
@@ -4040,32 +4063,29 @@
return RD;
}
-static void buildCapturedStmtCaptureList(
- SmallVectorImpl<CapturedStmt::Capture> &Captures,
- SmallVectorImpl<Expr *> &CaptureInits,
- ArrayRef<CapturingScopeInfo::Capture> Candidates) {
-
- typedef ArrayRef<CapturingScopeInfo::Capture>::const_iterator CaptureIter;
- for (CaptureIter Cap = Candidates.begin(); Cap != Candidates.end(); ++Cap) {
-
- if (Cap->isThisCapture()) {
- Captures.push_back(CapturedStmt::Capture(Cap->getLocation(),
+static void
+buildCapturedStmtCaptureList(SmallVectorImpl<CapturedStmt::Capture> &Captures,
+ SmallVectorImpl<Expr *> &CaptureInits,
+ ArrayRef<sema::Capture> Candidates) {
+ for (const sema::Capture &Cap : Candidates) {
+ if (Cap.isThisCapture()) {
+ Captures.push_back(CapturedStmt::Capture(Cap.getLocation(),
CapturedStmt::VCK_This));
- CaptureInits.push_back(Cap->getInitExpr());
+ CaptureInits.push_back(Cap.getInitExpr());
continue;
- } else if (Cap->isVLATypeCapture()) {
+ } else if (Cap.isVLATypeCapture()) {
Captures.push_back(
- CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_VLAType));
+ CapturedStmt::Capture(Cap.getLocation(), CapturedStmt::VCK_VLAType));
CaptureInits.push_back(nullptr);
continue;
}
- Captures.push_back(CapturedStmt::Capture(Cap->getLocation(),
- Cap->isReferenceCapture()
+ Captures.push_back(CapturedStmt::Capture(Cap.getLocation(),
+ Cap.isReferenceCapture()
? CapturedStmt::VCK_ByRef
: CapturedStmt::VCK_ByCopy,
- Cap->getVariable()));
- CaptureInits.push_back(Cap->getInitExpr());
+ Cap.getVariable()));
+ CaptureInits.push_back(Cap.getInitExpr());
}
}
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index fc1cc7b..cad398a 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/lib/Sema/SemaStmtAsm.cpp
@@ -793,7 +793,7 @@
ArrayRef<Expr*> Exprs,
SourceLocation EndLoc) {
bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
- getCurFunction()->setHasBranchProtectedScope();
+ setFunctionHasBranchProtectedScope();
MSAsmStmt *NS =
new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
/*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 2e8a706..b5583d1 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1262,7 +1262,7 @@
if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
Invalid = true;
} else if (TUK != TUK_Friend && TUK != TUK_Reference)
- diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc);
+ diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc, false);
LookupQualifiedName(Previous, SemanticContext);
} else {
@@ -4617,6 +4617,8 @@
if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack())
NTTPType = NTTP->getExpansionType(ArgumentPackIndex);
+ // FIXME: Do we need to substitute into parameters here if they're
+ // instantiation-dependent but not dependent?
if (NTTPType->isDependentType() &&
!isa<TemplateTemplateParmDecl>(Template) &&
!Template->getDeclContext()->isDependentContext()) {
@@ -4756,9 +4758,15 @@
// Check template template parameters.
TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param);
+ TemplateParameterList *Params = TempParm->getTemplateParameters();
+ if (TempParm->isExpandedParameterPack())
+ Params = TempParm->getExpansionTemplateParameters(ArgumentPackIndex);
+
// Substitute into the template parameter list of the template
// template parameter, since previously-supplied template arguments
// may appear within the template template parameter.
+ //
+ // FIXME: Skip this if the parameters aren't instantiation-dependent.
{
// Set up a template instantiation context.
LocalInstantiationScope Scope(*this);
@@ -4769,10 +4777,9 @@
return true;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
- TempParm = cast_or_null<TemplateTemplateParmDecl>(
- SubstDecl(TempParm, CurContext,
- MultiLevelTemplateArgumentList(TemplateArgs)));
- if (!TempParm)
+ Params = SubstTemplateParams(Params, CurContext,
+ MultiLevelTemplateArgumentList(TemplateArgs));
+ if (!Params)
return true;
}
@@ -4793,7 +4800,7 @@
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
- if (CheckTemplateArgument(TempParm, Arg, ArgumentPackIndex))
+ if (CheckTemplateTemplateArgument(Params, Arg))
return true;
Converted.push_back(Arg.getArgument());
@@ -6536,9 +6543,8 @@
///
/// This routine implements the semantics of C++ [temp.arg.template].
/// It returns true if an error occurred, and false otherwise.
-bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
- TemplateArgumentLoc &Arg,
- unsigned ArgumentPackIndex) {
+bool Sema::CheckTemplateTemplateArgument(TemplateParameterList *Params,
+ TemplateArgumentLoc &Arg) {
TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern();
TemplateDecl *Template = Name.getAsTemplateDecl();
if (!Template) {
@@ -6573,10 +6579,6 @@
<< Template;
}
- TemplateParameterList *Params = Param->getTemplateParameters();
- if (Param->isExpandedParameterPack())
- Params = Param->getExpansionTemplateParameters(ArgumentPackIndex);
-
// C++1z [temp.arg.template]p3: (DR 150)
// A template-argument matches a template template-parameter P when P
// is at least as specialized as the template-argument A.
@@ -7122,120 +7124,43 @@
}
// C++ [temp.expl.spec]p2:
- // An explicit specialization shall be declared in the namespace
- // of which the template is a member, or, for member templates, in
- // the namespace of which the enclosing class or enclosing class
- // template is a member. An explicit specialization of a member
- // function, member class or static data member of a class
- // template shall be declared in the namespace of which the class
- // template is a member. Such a declaration may also be a
- // definition. If the declaration is not a definition, the
- // specialization may be defined later in the name- space in which
- // the explicit specialization was declared, or in a namespace
- // that encloses the one in which the explicit specialization was
- // declared.
+ // An explicit specialization may be declared in any scope in which
+ // the corresponding primary template may be defined.
if (S.CurContext->getRedeclContext()->isFunctionOrMethod()) {
S.Diag(Loc, diag::err_template_spec_decl_function_scope)
<< Specialized;
return true;
}
- if (S.CurContext->isRecord() && !IsPartialSpecialization) {
- if (S.getLangOpts().MicrosoftExt) {
- // Do not warn for class scope explicit specialization during
- // instantiation, warning was already emitted during pattern
- // semantic analysis.
- if (!S.inTemplateInstantiation())
- S.Diag(Loc, diag::ext_function_specialization_in_class)
- << Specialized;
- } else {
- S.Diag(Loc, diag::err_template_spec_decl_class_scope)
- << Specialized;
- return true;
- }
- }
-
- if (S.CurContext->isRecord() &&
- !S.CurContext->Equals(Specialized->getDeclContext())) {
- // Make sure that we're specializing in the right record context.
- // Otherwise, things can go horribly wrong.
- S.Diag(Loc, diag::err_template_spec_decl_class_scope)
- << Specialized;
- return true;
- }
-
// C++ [temp.class.spec]p6:
- // A class template partial specialization may be declared or redeclared
- // in any namespace scope in which its definition may be defined (14.5.1
- // and 14.5.2).
- DeclContext *SpecializedContext
- = Specialized->getDeclContext()->getEnclosingNamespaceContext();
- DeclContext *DC = S.CurContext->getEnclosingNamespaceContext();
+ // A class template partial specialization may be declared in any
+ // scope in which the primary template may be defined.
+ DeclContext *SpecializedContext =
+ Specialized->getDeclContext()->getRedeclContext();
+ DeclContext *DC = S.CurContext->getRedeclContext();
- // Make sure that this redeclaration (or definition) occurs in an enclosing
- // namespace.
- // Note that HandleDeclarator() performs this check for explicit
- // specializations of function templates, static data members, and member
- // functions, so we skip the check here for those kinds of entities.
- // FIXME: HandleDeclarator's diagnostics aren't quite as good, though.
- // Should we refactor that check, so that it occurs later?
- if (!DC->Encloses(SpecializedContext) &&
- !(isa<FunctionTemplateDecl>(Specialized) ||
- isa<FunctionDecl>(Specialized) ||
- isa<VarTemplateDecl>(Specialized) ||
- isa<VarDecl>(Specialized))) {
+ // Make sure that this redeclaration (or definition) occurs in the same
+ // scope or an enclosing namespace.
+ if (!(DC->isFileContext() ? DC->Encloses(SpecializedContext)
+ : DC->Equals(SpecializedContext))) {
if (isa<TranslationUnitDecl>(SpecializedContext))
S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
<< EntityKind << Specialized;
- else if (isa<NamespaceDecl>(SpecializedContext)) {
+ else {
+ auto *ND = cast<NamedDecl>(SpecializedContext);
int Diag = diag::err_template_spec_redecl_out_of_scope;
- if (S.getLangOpts().MicrosoftExt)
+ if (S.getLangOpts().MicrosoftExt && !DC->isRecord())
Diag = diag::ext_ms_template_spec_redecl_out_of_scope;
S.Diag(Loc, Diag) << EntityKind << Specialized
- << cast<NamedDecl>(SpecializedContext);
- } else
- llvm_unreachable("unexpected namespace context for specialization");
+ << ND << isa<CXXRecordDecl>(ND);
+ }
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
- } else if ((!PrevDecl ||
- getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared ||
- getTemplateSpecializationKind(PrevDecl) ==
- TSK_ImplicitInstantiation)) {
- // C++ [temp.exp.spec]p2:
- // An explicit specialization shall be declared in the namespace of which
- // the template is a member, or, for member templates, in the namespace
- // of which the enclosing class or enclosing class template is a member.
- // An explicit specialization of a member function, member class or
- // static data member of a class template shall be declared in the
- // namespace of which the class template is a member.
- //
- // C++11 [temp.expl.spec]p2:
- // An explicit specialization shall be declared in a namespace enclosing
- // the specialized template.
- // C++11 [temp.explicit]p3:
- // An explicit instantiation shall appear in an enclosing namespace of its
- // template.
- if (!DC->InEnclosingNamespaceSetOf(SpecializedContext)) {
- bool IsCPlusPlus11Extension = DC->Encloses(SpecializedContext);
- if (isa<TranslationUnitDecl>(SpecializedContext)) {
- assert(!IsCPlusPlus11Extension &&
- "DC encloses TU but isn't in enclosing namespace set");
- S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global)
- << EntityKind << Specialized;
- } else if (isa<NamespaceDecl>(SpecializedContext)) {
- int Diag;
- if (!IsCPlusPlus11Extension)
- Diag = diag::err_template_spec_decl_out_of_scope;
- else if (!S.getLangOpts().CPlusPlus11)
- Diag = diag::ext_template_spec_decl_out_of_scope;
- else
- Diag = diag::warn_cxx98_compat_template_spec_decl_out_of_scope;
- S.Diag(Loc, Diag)
- << EntityKind << Specialized << cast<NamedDecl>(SpecializedContext);
- }
- S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
- }
+ // Don't allow specializing in the wrong class during error recovery.
+ // Otherwise, things can go horribly wrong.
+ if (DC->isRecord())
+ return true;
}
return false;
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index bcc1e66..5b6eb39 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -18,11 +18,11 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/TemplateInstCallback.h"
@@ -2026,7 +2026,7 @@
if (Inst.isInvalid())
return true;
assert(!Inst.isAlreadyInstantiating() && "should have been caught by caller");
- PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
"instantiating class definition");
// Enter the scope of this instantiation. We don't use
@@ -2253,7 +2253,7 @@
return true;
if (Inst.isAlreadyInstantiating())
return false;
- PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
"instantiating enum definition");
// The instantiation is visible here, even if it was first declared in an
@@ -2329,7 +2329,7 @@
<< Instantiation;
return true;
}
- PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
"instantiating default member init");
// Enter the scope of this instantiation. We don't use PushDeclContext because
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 108724f..a7883c6 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -18,10 +18,10 @@
#include "clang/AST/DependentDiagnostic.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateInstCallback.h"
@@ -176,7 +176,8 @@
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const AllocAlignAttr *Align, Decl *New) {
Expr *Param = IntegerLiteral::Create(
- S.getASTContext(), llvm::APInt(64, Align->paramIndex().getSourceIndex()),
+ S.getASTContext(),
+ llvm::APInt(64, Align->getParamIndex().getSourceIndex()),
S.getASTContext().UnsignedLongLongTy, Align->getLocation());
S.AddAllocAlignAttr(Align->getLocation(), New, Param,
Align->getSpellingListIndex());
@@ -741,7 +742,7 @@
if (D->isNRVOVariable()) {
QualType ReturnType = cast<FunctionDecl>(DC)->getReturnType();
- if (SemaRef.isCopyElisionCandidate(ReturnType, Var, false))
+ if (SemaRef.isCopyElisionCandidate(ReturnType, Var, Sema::CES_Strict))
Var->setNRVOVariable(true);
}
@@ -1652,6 +1653,7 @@
NameInfo, T, TInfo, D->getSourceRange().getEnd());
if (DGuide->isCopyDeductionCandidate())
cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate();
+ Function->setAccess(D->getAccess());
} else {
Function = FunctionDecl::Create(
SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo,
@@ -2710,6 +2712,8 @@
assert(Specialization && "Class scope Specialization is null");
SemaRef.Context.setClassScopeSpecializationPattern(Specialization, OldFD);
+ // FIXME: If this is a definition, check for redefinition errors!
+
return NewFD;
}
@@ -3118,6 +3122,13 @@
return InstL;
}
+TemplateParameterList *
+Sema::SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
+ return Instantiator.SubstTemplateParams(Params);
+}
+
/// \brief Instantiate the declaration of a class template partial
/// specialization.
///
@@ -3826,8 +3837,8 @@
if (PatternDecl->isLateTemplateParsed() &&
!LateTemplateParser) {
Function->setInstantiationIsPending(true);
- PendingInstantiations.push_back(
- std::make_pair(Function, PointOfInstantiation));
+ LateParsedInstantiations.push_back(
+ std::make_pair(Function, PointOfInstantiation));
return;
}
@@ -3884,7 +3895,7 @@
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
- PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Function, SourceLocation(),
"instantiating function definition");
// The instantiation is visible here, even if it was first declared in an
@@ -3929,8 +3940,10 @@
TemplateArgs))
return;
+ StmtResult Body;
if (PatternDecl->hasSkippedBody()) {
ActOnSkippedFunctionBody(Function);
+ Body = nullptr;
} else {
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Function)) {
// If this is a constructor, instantiate the member initializers.
@@ -3946,16 +3959,14 @@
}
// Instantiate the function body.
- StmtResult Body = SubstStmt(Pattern, TemplateArgs);
+ Body = SubstStmt(Pattern, TemplateArgs);
if (Body.isInvalid())
Function->setInvalidDecl();
-
- // FIXME: finishing the function body while in an expression evaluation
- // context seems wrong. Investigate more.
- ActOnFinishFunctionBody(Function, Body.get(),
- /*IsInstantiation=*/true);
}
+ // FIXME: finishing the function body while in an expression evaluation
+ // context seems wrong. Investigate more.
+ ActOnFinishFunctionBody(Function, Body.get(), /*IsInstantiation=*/true);
PerformDependentDiagnostics(PatternDecl, TemplateArgs);
@@ -4072,6 +4083,7 @@
NewVar->setTSCSpec(OldVar->getTSCSpec());
NewVar->setInitStyle(OldVar->getInitStyle());
NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl());
+ NewVar->setObjCForDecl(OldVar->isObjCForDecl());
NewVar->setConstexpr(OldVar->isConstexpr());
NewVar->setInitCapture(OldVar->isInitCapture());
NewVar->setPreviousDeclInSameBlockScope(
@@ -4191,7 +4203,9 @@
Var->setInvalidDecl();
}
} else {
- if (Var->isStaticDataMember()) {
+ // `inline` variables are a definition and declaration all in one; we won't
+ // pick up an initializer from anywhere else.
+ if (Var->isStaticDataMember() && !Var->isInline()) {
if (!Var->isOutOfLine())
return;
@@ -4202,7 +4216,7 @@
}
// We'll add an initializer to a for-range declaration later.
- if (Var->isCXXForRangeDecl())
+ if (Var->isCXXForRangeDecl() || Var->isObjCForDecl())
return;
ActOnUninitializedDecl(Var);
@@ -4293,7 +4307,7 @@
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
- PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(),
"instantiating variable initializer");
// The instantiation is visible here, even if it was first declared in an
@@ -4406,7 +4420,7 @@
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
- PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(),
"instantiating variable definition");
// If we're performing recursive template instantiation, create our own
@@ -5210,7 +5224,7 @@
break;
}
- PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
+ PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(),
"instantiating variable definition");
bool DefinitionRequired = Var->getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDefinition;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 9791003..7bcc5b6 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -125,6 +125,7 @@
case AttributeList::AT_NoReturn: \
case AttributeList::AT_Regparm: \
case AttributeList::AT_AnyX86NoCallerSavedRegisters: \
+ case AttributeList::AT_AnyX86NoCfCheck: \
CALLING_CONV_ATTRS_CASELIST
// Microsoft-specific type qualifiers.
@@ -3315,6 +3316,18 @@
CallingConv CC = S.Context.getDefaultCallingConvention(FTI.isVariadic,
IsCXXInstanceMethod);
+ // Attribute AT_CUDAGlobal affects the calling convention for AMDGPU targets.
+ // This is the simplest place to infer calling convention for CUDA kernels.
+ if (S.getLangOpts().CUDA && S.getLangOpts().CUDAIsDevice) {
+ for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
+ Attr; Attr = Attr->getNext()) {
+ if (Attr->getKind() == AttributeList::AT_CUDAGlobal) {
+ CC = CC_CUDAKernel;
+ break;
+ }
+ }
+ }
+
// Attribute AT_OpenCLKernel affects the calling convention for SPIR
// and AMDGPU targets, hence it cannot be treated as a calling
// convention attribute. This is the simplest place to infer
@@ -4860,8 +4873,8 @@
if (Chunk.Fun.TypeQuals & Qualifiers::Restrict)
RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc());
if (!RemovalLocs.empty()) {
- std::sort(RemovalLocs.begin(), RemovalLocs.end(),
- BeforeThanCompare<SourceLocation>(S.getSourceManager()));
+ llvm::sort(RemovalLocs.begin(), RemovalLocs.end(),
+ BeforeThanCompare<SourceLocation>(S.getSourceManager()));
RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back());
Loc = RemovalLocs.front();
}
@@ -5144,6 +5157,8 @@
return AttributeList::AT_ObjCOwnership;
case AttributedType::attr_noreturn:
return AttributeList::AT_NoReturn;
+ case AttributedType::attr_nocf_check:
+ return AttributeList::AT_AnyX86NoCfCheck;
case AttributedType::attr_cdecl:
return AttributeList::AT_CDecl;
case AttributedType::attr_fastcall:
@@ -6609,7 +6624,7 @@
FunctionTypeUnwrapper unwrapped(S, type);
if (attr.getKind() == AttributeList::AT_NoReturn) {
- if (S.CheckNoReturnAttr(attr))
+ if (S.CheckAttrNoArgs(attr))
return true;
// Delay if this is not a function type.
@@ -6649,7 +6664,7 @@
}
if (attr.getKind() == AttributeList::AT_AnyX86NoCallerSavedRegisters) {
- if (S.CheckNoCallerSavedRegsAttr(attr))
+ if (S.CheckAttrTarget(attr) || S.CheckAttrNoArgs(attr))
return true;
// Delay if this is not a function type.
@@ -6662,6 +6677,27 @@
return true;
}
+ if (attr.getKind() == AttributeList::AT_AnyX86NoCfCheck) {
+ if (!S.getLangOpts().CFProtectionBranch) {
+ S.Diag(attr.getLoc(), diag::warn_nocf_check_attribute_ignored);
+ attr.setInvalid();
+ return true;
+ }
+
+ if (S.CheckAttrTarget(attr) || S.CheckAttrNoArgs(attr))
+ return true;
+
+ // If this is not a function type, warning will be asserted by subject
+ // check.
+ if (!unwrapped.isFunctionType())
+ return true;
+
+ FunctionType::ExtInfo EI =
+ unwrapped.get()->getExtInfo().withNoCfCheck(true);
+ type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ return true;
+ }
+
if (attr.getKind() == AttributeList::AT_Regparm) {
unsigned value;
if (S.CheckRegparmAttr(attr, value))
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 7d52394..4119e7a 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -10388,7 +10388,7 @@
// the corresponding pack is empty
if (AllEmptyPacks && !RequiresADL) {
getSema().Diag(Old->getNameLoc(), diag::err_using_pack_expansion_empty)
- << isa<UnresolvedMemberExpr>(Old) << Old->getNameInfo().getName();
+ << isa<UnresolvedMemberExpr>(Old) << Old->getName();
return true;
}
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index b6fc4b2..d77760d 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -396,8 +396,8 @@
ExistingTargetOpts.FeaturesAsWritten.end());
SmallVector<StringRef, 4> ReadFeatures(TargetOpts.FeaturesAsWritten.begin(),
TargetOpts.FeaturesAsWritten.end());
- std::sort(ExistingFeatures.begin(), ExistingFeatures.end());
- std::sort(ReadFeatures.begin(), ReadFeatures.end());
+ llvm::sort(ExistingFeatures.begin(), ExistingFeatures.end());
+ llvm::sort(ReadFeatures.begin(), ReadFeatures.end());
// We compute the set difference in both directions explicitly so that we can
// diagnose the differences differently.
@@ -6005,13 +6005,14 @@
}
case TYPE_FUNCTION_NO_PROTO: {
- if (Record.size() != 7) {
+ if (Record.size() != 8) {
Error("incorrect encoding of no-proto function type");
return QualType();
}
QualType ResultType = readType(*Loc.F, Record, Idx);
FunctionType::ExtInfo Info(Record[1], Record[2], Record[3],
- (CallingConv)Record[4], Record[5], Record[6]);
+ (CallingConv)Record[4], Record[5], Record[6],
+ Record[7]);
return Context.getFunctionNoProtoType(ResultType, Info);
}
@@ -6024,9 +6025,10 @@
/*regparm*/ Record[3],
static_cast<CallingConv>(Record[4]),
/*produces*/ Record[5],
- /*nocallersavedregs*/ Record[6]);
+ /*nocallersavedregs*/ Record[6],
+ /*nocfcheck*/ Record[7]);
- unsigned Idx = 7;
+ unsigned Idx = 8;
EPI.Variadic = Record[Idx++];
EPI.HasTrailingReturn = Record[Idx++];
@@ -9076,8 +9078,8 @@
NextCursor:
// De-serialized SourceLocations get negative FileIDs for other modules,
// potentially invalidating the original order. Sort it again.
- std::sort(Comments.begin(), Comments.end(),
- BeforeThanCompare<RawComment>(SourceMgr));
+ llvm::sort(Comments.begin(), Comments.end(),
+ BeforeThanCompare<RawComment>(SourceMgr));
Context.Comments.addDeserializedComments(Comments);
}
}
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 10439d3..fa0db51 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -232,7 +232,7 @@
if (auto &Old = LazySpecializations) {
IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
- std::sort(IDs.begin(), IDs.end());
+ llvm::sort(IDs.begin(), IDs.end());
IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
}
@@ -739,6 +739,11 @@
RD->setAnonymousStructOrUnion(Record.readInt());
RD->setHasObjectMember(Record.readInt());
RD->setHasVolatileMember(Record.readInt());
+ RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt());
+ RD->setNonTrivialToPrimitiveCopy(Record.readInt());
+ RD->setNonTrivialToPrimitiveDestroy(Record.readInt());
+ RD->setCanPassInRegisters(Record.readInt());
+ RD->setParamDestroyedInCallee(Record.readInt());
return Redecl;
}
@@ -1274,6 +1279,7 @@
VD->NonParmVarDeclBits.ExceptionVar = Record.readInt();
VD->NonParmVarDeclBits.NRVOVariable = Record.readInt();
VD->NonParmVarDeclBits.CXXForRangeDecl = Record.readInt();
+ VD->NonParmVarDeclBits.ObjCForDecl = Record.readInt();
VD->NonParmVarDeclBits.ARCPseudoStrong = Record.readInt();
VD->NonParmVarDeclBits.IsInline = Record.readInt();
VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt();
@@ -1584,7 +1590,6 @@
Data.HasIrrelevantDestructor = Record.readInt();
Data.HasConstexprNonCopyMoveConstructor = Record.readInt();
Data.HasDefaultedDefaultConstructor = Record.readInt();
- Data.CanPassInRegisters = Record.readInt();
Data.DefaultedDefaultConstructorIsConstexpr = Record.readInt();
Data.HasConstexprDefaultConstructor = Record.readInt();
Data.HasNonLiteralTypeFieldsOrBases = Record.readInt();
@@ -1724,7 +1729,6 @@
MATCH_FIELD(HasIrrelevantDestructor)
OR_FIELD(HasConstexprNonCopyMoveConstructor)
OR_FIELD(HasDefaultedDefaultConstructor)
- MATCH_FIELD(CanPassInRegisters)
MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)
OR_FIELD(HasConstexprDefaultConstructor)
MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)
@@ -1782,29 +1786,31 @@
else
DD = new (C) struct CXXRecordDecl::DefinitionData(D);
+ CXXRecordDecl *Canon = D->getCanonicalDecl();
+ // Set decl definition data before reading it, so that during deserialization
+ // when we read CXXRecordDecl, it already has definition data and we don't
+ // set fake one.
+ if (!Canon->DefinitionData)
+ Canon->DefinitionData = DD;
+ D->DefinitionData = Canon->DefinitionData;
ReadCXXDefinitionData(*DD, D);
- // We might already have a definition for this record. This can happen either
- // because we're reading an update record, or because we've already done some
- // merging. Either way, just merge into it.
- CXXRecordDecl *Canon = D->getCanonicalDecl();
- if (Canon->DefinitionData) {
+ // We might already have a different definition for this record. This can
+ // happen either because we're reading an update record, or because we've
+ // already done some merging. Either way, just merge into it.
+ if (Canon->DefinitionData != DD) {
MergeDefinitionData(Canon, std::move(*DD));
- D->DefinitionData = Canon->DefinitionData;
return;
}
// Mark this declaration as being a definition.
D->IsCompleteDefinition = true;
- D->DefinitionData = DD;
// If this is not the first declaration or is an update record, we can have
// other redeclarations already. Make a note that we need to propagate the
// DefinitionData pointer onto them.
- if (Update || Canon != D) {
- Canon->DefinitionData = D->DefinitionData;
+ if (Update || Canon != D)
Reader.PendingDefinitions.insert(D);
- }
}
ASTDeclReader::RedeclarableResult
@@ -4104,6 +4110,8 @@
bool HadRealDefinition =
OldDD && (OldDD->Definition != RD ||
!Reader.PendingFakeDefinitionData.count(OldDD));
+ RD->setCanPassInRegisters(Record.readInt());
+ RD->setParamDestroyedInCallee(Record.readInt());
ReadCXXRecordDefinition(RD, /*Update*/true);
// Visible update is handled separately.
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 4938b0e..a1ae6a4 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -1667,6 +1667,7 @@
VisitExpr(E);
E->SourceExpr = Record.readSubExpr();
E->Loc = ReadSourceLocation();
+ E->setIsUnique(Record.readInt());
}
void ASTStmtReader::VisitTypoExpr(TypoExpr *E) {
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 53e09b3..c2aabf5 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -276,6 +276,7 @@
Record.push_back(C.getCC());
Record.push_back(C.getProducesResult());
Record.push_back(C.getNoCallerSavedRegs());
+ Record.push_back(C.getNoCfCheck());
if (C.getHasRegParm() || C.getRegParm() || C.getProducesResult())
AbbrevToUse = 0;
@@ -884,6 +885,7 @@
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // CC
Abv->Add(BitCodeAbbrevOp(0)); // ProducesResult
Abv->Add(BitCodeAbbrevOp(0)); // NoCallerSavedRegs
+ Abv->Add(BitCodeAbbrevOp(0)); // NoCfCheck
// FunctionProtoType
Abv->Add(BitCodeAbbrevOp(0)); // IsVariadic
Abv->Add(BitCodeAbbrevOp(0)); // HasTrailingReturn
@@ -2481,8 +2483,8 @@
MacroIdentifiers.push_back(Id.second);
// Sort the set of macro definitions that need to be serialized by the
// name of the macro, to provide a stable ordering.
- std::sort(MacroIdentifiers.begin(), MacroIdentifiers.end(),
- llvm::less_ptr<IdentifierInfo>());
+ llvm::sort(MacroIdentifiers.begin(), MacroIdentifiers.end(),
+ llvm::less_ptr<IdentifierInfo>());
// Emit the macro directives as a list and associate the offset with the
// identifier they belong to.
@@ -3214,8 +3216,8 @@
SmallVector<std::pair<FileID, DeclIDInFileInfo *>, 64> SortedFileDeclIDs(
FileDeclIDs.begin(), FileDeclIDs.end());
- std::sort(SortedFileDeclIDs.begin(), SortedFileDeclIDs.end(),
- llvm::less_first());
+ llvm::sort(SortedFileDeclIDs.begin(), SortedFileDeclIDs.end(),
+ llvm::less_first());
// Join the vectors of DeclIDs from all files.
SmallVector<DeclID, 256> FileGroupedDeclIDs;
@@ -3719,7 +3721,7 @@
IIs.push_back(ID.second);
// Sort the identifiers lexicographically before getting them references so
// that their order is stable.
- std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
+ llvm::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
for (const IdentifierInfo *II : IIs)
if (Trait.isInterestingNonMacroIdentifier(II))
getIdentifierRef(II);
@@ -4017,7 +4019,7 @@
}
// Sort the names into a stable order.
- std::sort(Names.begin(), Names.end());
+ llvm::sort(Names.begin(), Names.end());
if (auto *D = dyn_cast<CXXRecordDecl>(DC)) {
// We need to establish an ordering of constructor and conversion function
@@ -4154,7 +4156,7 @@
std::make_pair(Entry.first, Entry.second.getLookupResult()));
}
- std::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first());
+ llvm::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first());
for (auto &NameAndResult : LookupResults) {
DeclarationName Name = NameAndResult.first;
DeclContext::lookup_result Result = NameAndResult.second;
@@ -4850,7 +4852,7 @@
IIs.push_back(II);
}
// Sort the identifiers to visit based on their name.
- std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
+ llvm::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
for (const IdentifierInfo *II : IIs) {
for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II),
DEnd = SemaRef.IdResolver.end();
@@ -5087,7 +5089,7 @@
};
// Sort and deduplicate module IDs.
- std::sort(Imports.begin(), Imports.end(), Cmp);
+ llvm::sort(Imports.begin(), Imports.end(), Cmp);
Imports.erase(std::unique(Imports.begin(), Imports.end(), Eq),
Imports.end());
@@ -5191,6 +5193,8 @@
case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
auto *RD = cast<CXXRecordDecl>(D);
UpdatedDeclContexts.insert(RD->getPrimaryContext());
+ Record.push_back(RD->canPassInRegisters());
+ Record.push_back(RD->isParamDestroyedInCallee());
Record.AddCXXDefinitionData(RD);
Record.AddOffset(WriteDeclContextLexicalBlock(
*Context, const_cast<CXXRecordDecl *>(RD)));
@@ -6018,7 +6022,6 @@
Record->push_back(Data.HasIrrelevantDestructor);
Record->push_back(Data.HasConstexprNonCopyMoveConstructor);
Record->push_back(Data.HasDefaultedDefaultConstructor);
- Record->push_back(Data.CanPassInRegisters);
Record->push_back(Data.DefaultedDefaultConstructorIsConstexpr);
Record->push_back(Data.HasConstexprDefaultConstructor);
Record->push_back(Data.HasNonLiteralTypeFieldsOrBases);
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index dd57029..06ea8e7 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h"
@@ -465,6 +466,11 @@
Record.push_back(D->isAnonymousStructOrUnion());
Record.push_back(D->hasObjectMember());
Record.push_back(D->hasVolatileMember());
+ Record.push_back(D->isNonTrivialToPrimitiveDefaultInitialize());
+ Record.push_back(D->isNonTrivialToPrimitiveCopy());
+ Record.push_back(D->isNonTrivialToPrimitiveDestroy());
+ Record.push_back(D->canPassInRegisters());
+ Record.push_back(D->isParamDestroyedInCallee());
if (D->getDeclContext() == D->getLexicalDeclContext() &&
!D->hasAttrs() &&
@@ -914,6 +920,7 @@
Record.push_back(D->isExceptionVariable());
Record.push_back(D->isNRVOVariable());
Record.push_back(D->isCXXForRangeDecl());
+ Record.push_back(D->isObjCForDecl());
Record.push_back(D->isARCPseudoStrong());
Record.push_back(D->isInline());
Record.push_back(D->isInlineSpecified());
@@ -1899,6 +1906,17 @@
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // AnonymousStructUnion
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasObjectMember
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasVolatileMember
+
+ // isNonTrivialToPrimitiveDefaultInitialize
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
+ // isNonTrivialToPrimitiveCopy
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
+ // isNonTrivialToPrimitiveDestroy
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // canPassInRegisters
+ // isParamDestroyedInCallee
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
+
// DC
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // VisibleOffset
@@ -2014,6 +2032,7 @@
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isObjCForDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong
Abv->Add(BitCodeAbbrevOp(0)); // isInline
Abv->Add(BitCodeAbbrevOp(0)); // isInlineSpecified
@@ -2214,6 +2233,9 @@
}
void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
+ PrettyDeclStackTraceEntry CrashInfo(Context, D, SourceLocation(),
+ "serializing");
+
// Determine the ID for this declaration.
serialization::DeclID ID;
assert(!D->isFromASTFile() && "should not be emitting imported decl");
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 6fd0372..0a02d1d 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -1699,6 +1699,7 @@
VisitExpr(E);
Record.AddStmt(E->getSourceExpr());
Record.AddSourceLocation(E->getLocation());
+ Record.push_back(E->isUnique());
Code = serialization::EXPR_OPAQUE_VALUE;
}
diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 9b42a55..c1c1b99 100644
--- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -37,7 +37,7 @@
DynamicTypeChecker.cpp
ExprInspectionChecker.cpp
FixedAddressChecker.cpp
- GCDAsyncSemaphoreChecker.cpp
+ GCDAntipatternChecker.cpp
GenericTaintChecker.cpp
GTestChecker.cpp
IdenticalExprChecker.cpp
@@ -63,6 +63,7 @@
NullabilityChecker.cpp
NumberObjectConversionChecker.cpp
ObjCAtSyncChecker.cpp
+ ObjCAutoreleaseWriteChecker.cpp
ObjCContainersASTChecker.cpp
ObjCContainersChecker.cpp
ObjCMissingSuperCallChecker.cpp
@@ -84,6 +85,7 @@
TaintTesterChecker.cpp
TestAfterDivZeroChecker.cpp
TraversalChecker.cpp
+ TrustNonnullChecker.cpp
UndefBranchChecker.cpp
UndefCapturedBlockVarChecker.cpp
UndefResultChecker.cpp
diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 4eb189e..bd40337 100644
--- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -1033,6 +1033,21 @@
if (stateNonZeroSize) {
state = stateNonZeroSize;
+ // Ensure the destination is not null. If it is NULL there will be a
+ // NULL pointer dereference.
+ state = checkNonNull(C, state, Dest, destVal);
+ if (!state)
+ return;
+
+ // Get the value of the Src.
+ SVal srcVal = state->getSVal(Source, LCtx);
+
+ // Ensure the source is not null. If it is NULL there will be a
+ // NULL pointer dereference.
+ state = checkNonNull(C, state, Source, srcVal);
+ if (!state)
+ return;
+
// Ensure the accesses are valid and that the buffers do not overlap.
const char * const writeWarning =
"Memory copy function overflows destination buffer";
@@ -2018,6 +2033,12 @@
return;
}
+ // Ensure the memory area is not null.
+ // If it is NULL there will be a NULL pointer dereference.
+ State = checkNonNull(C, StateNonZeroSize, Mem, MemVal);
+ if (!State)
+ return;
+
State = CheckBufferAccess(C, State, Size, Mem);
if (!State)
return;
diff --git a/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp b/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
new file mode 100644
index 0000000..4ee5159
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
@@ -0,0 +1,227 @@
+//===- GCDAntipatternChecker.cpp ---------------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines GCDAntipatternChecker which checks against a common
+// antipattern when synchronous API is emulated from asynchronous callbacks
+// using a semaphore:
+//
+// dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+//
+// AnyCFunctionCall(^{
+// // code…
+// dispatch_semaphore_signal(sema);
+// })
+// dispatch_semaphore_wait(sema, *)
+//
+// Such code is a common performance problem, due to inability of GCD to
+// properly handle QoS when a combination of queues and semaphores is used.
+// Good code would either use asynchronous API (when available), or perform
+// the necessary action in asynchronous callback.
+//
+// Currently, the check is performed using a simple heuristical AST pattern
+// matching.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "llvm/Support/Debug.h"
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;
+
+namespace {
+
+// ID of a node at which the diagnostic would be emitted.
+const char *WarnAtNode = "waitcall";
+
+class GCDAntipatternChecker : public Checker<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const;
+};
+
+auto callsName(const char *FunctionName)
+ -> decltype(callee(functionDecl())) {
+ return callee(functionDecl(hasName(FunctionName)));
+}
+
+auto equalsBoundArgDecl(int ArgIdx, const char *DeclName)
+ -> decltype(hasArgument(0, expr())) {
+ return hasArgument(ArgIdx, ignoringParenCasts(declRefExpr(
+ to(varDecl(equalsBoundNode(DeclName))))));
+}
+
+auto bindAssignmentToDecl(const char *DeclName) -> decltype(hasLHS(expr())) {
+ return hasLHS(ignoringParenImpCasts(
+ declRefExpr(to(varDecl().bind(DeclName)))));
+}
+
+/// The pattern is very common in tests, and it is OK to use it there.
+/// We have to heuristics for detecting tests: method name starts with "test"
+/// (used in XCTest), and a class name contains "mock" or "test" (used in
+/// helpers which are not tests themselves, but used exclusively in tests).
+static bool isTest(const Decl *D) {
+ if (const auto* ND = dyn_cast<NamedDecl>(D)) {
+ std::string DeclName = ND->getNameAsString();
+ if (StringRef(DeclName).startswith("test"))
+ return true;
+ }
+ if (const auto *OD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (const auto *CD = dyn_cast<ObjCContainerDecl>(OD->getParent())) {
+ std::string ContainerName = CD->getNameAsString();
+ StringRef CN(ContainerName);
+ if (CN.contains_lower("test") || CN.contains_lower("mock"))
+ return true;
+ }
+ }
+ return false;
+}
+
+static auto findGCDAntiPatternWithSemaphore() -> decltype(compoundStmt()) {
+
+ const char *SemaphoreBinding = "semaphore_name";
+ auto SemaphoreCreateM = callExpr(callsName("dispatch_semaphore_create"));
+
+ auto SemaphoreBindingM = anyOf(
+ forEachDescendant(
+ varDecl(hasDescendant(SemaphoreCreateM)).bind(SemaphoreBinding)),
+ forEachDescendant(binaryOperator(bindAssignmentToDecl(SemaphoreBinding),
+ hasRHS(SemaphoreCreateM))));
+
+ auto HasBlockArgumentM = hasAnyArgument(hasType(
+ hasCanonicalType(blockPointerType())
+ ));
+
+ auto ArgCallsSignalM = hasAnyArgument(stmt(hasDescendant(callExpr(
+ allOf(
+ callsName("dispatch_semaphore_signal"),
+ equalsBoundArgDecl(0, SemaphoreBinding)
+ )))));
+
+ auto HasBlockAndCallsSignalM = allOf(HasBlockArgumentM, ArgCallsSignalM);
+
+ auto HasBlockCallingSignalM =
+ forEachDescendant(
+ stmt(anyOf(
+ callExpr(HasBlockAndCallsSignalM),
+ objcMessageExpr(HasBlockAndCallsSignalM)
+ )));
+
+ auto SemaphoreWaitM = forEachDescendant(
+ callExpr(
+ allOf(
+ callsName("dispatch_semaphore_wait"),
+ equalsBoundArgDecl(0, SemaphoreBinding)
+ )
+ ).bind(WarnAtNode));
+
+ return compoundStmt(
+ SemaphoreBindingM, HasBlockCallingSignalM, SemaphoreWaitM);
+}
+
+static auto findGCDAntiPatternWithGroup() -> decltype(compoundStmt()) {
+
+ const char *GroupBinding = "group_name";
+ auto DispatchGroupCreateM = callExpr(callsName("dispatch_group_create"));
+
+ auto GroupBindingM = anyOf(
+ forEachDescendant(
+ varDecl(hasDescendant(DispatchGroupCreateM)).bind(GroupBinding)),
+ forEachDescendant(binaryOperator(bindAssignmentToDecl(GroupBinding),
+ hasRHS(DispatchGroupCreateM))));
+
+ auto GroupEnterM = forEachDescendant(
+ stmt(callExpr(allOf(callsName("dispatch_group_enter"),
+ equalsBoundArgDecl(0, GroupBinding)))));
+
+ auto HasBlockArgumentM = hasAnyArgument(hasType(
+ hasCanonicalType(blockPointerType())
+ ));
+
+ auto ArgCallsSignalM = hasAnyArgument(stmt(hasDescendant(callExpr(
+ allOf(
+ callsName("dispatch_group_leave"),
+ equalsBoundArgDecl(0, GroupBinding)
+ )))));
+
+ auto HasBlockAndCallsLeaveM = allOf(HasBlockArgumentM, ArgCallsSignalM);
+
+ auto AcceptsBlockM =
+ forEachDescendant(
+ stmt(anyOf(
+ callExpr(HasBlockAndCallsLeaveM),
+ objcMessageExpr(HasBlockAndCallsLeaveM)
+ )));
+
+ auto GroupWaitM = forEachDescendant(
+ callExpr(
+ allOf(
+ callsName("dispatch_group_wait"),
+ equalsBoundArgDecl(0, GroupBinding)
+ )
+ ).bind(WarnAtNode));
+
+ return compoundStmt(GroupBindingM, GroupEnterM, AcceptsBlockM, GroupWaitM);
+}
+
+static void emitDiagnostics(const BoundNodes &Nodes,
+ const char* Type,
+ BugReporter &BR,
+ AnalysisDeclContext *ADC,
+ const GCDAntipatternChecker *Checker) {
+ const auto *SW = Nodes.getNodeAs<CallExpr>(WarnAtNode);
+ assert(SW);
+
+ std::string Diagnostics;
+ llvm::raw_string_ostream OS(Diagnostics);
+ OS << "Waiting on a " << Type << " with Grand Central Dispatch creates "
+ << "useless threads and is subject to priority inversion; consider "
+ << "using a synchronous API or changing the caller to be asynchronous";
+
+ BR.EmitBasicReport(
+ ADC->getDecl(),
+ Checker,
+ /*Name=*/"GCD performance anti-pattern",
+ /*Category=*/"Performance",
+ OS.str(),
+ PathDiagnosticLocation::createBegin(SW, BR.getSourceManager(), ADC),
+ SW->getSourceRange());
+}
+
+void GCDAntipatternChecker::checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const {
+ if (isTest(D))
+ return;
+
+ AnalysisDeclContext *ADC = AM.getAnalysisDeclContext(D);
+
+ auto SemaphoreMatcherM = findGCDAntiPatternWithSemaphore();
+ auto Matches = match(SemaphoreMatcherM, *D->getBody(), AM.getASTContext());
+ for (BoundNodes Match : Matches)
+ emitDiagnostics(Match, "semaphore", BR, ADC, this);
+
+ auto GroupMatcherM = findGCDAntiPatternWithGroup();
+ Matches = match(GroupMatcherM, *D->getBody(), AM.getASTContext());
+ for (BoundNodes Match : Matches)
+ emitDiagnostics(Match, "group", BR, ADC, this);
+}
+
+}
+
+void ento::registerGCDAntipattern(CheckerManager &Mgr) {
+ Mgr.registerChecker<GCDAntipatternChecker>();
+}
diff --git a/lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp b/lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp
deleted file mode 100644
index 23ef032..0000000
--- a/lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-//===- GCDAsyncSemaphoreChecker.cpp -----------------------------*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines GCDAsyncSemaphoreChecker which checks against a common
-// antipattern when synchronous API is emulated from asynchronous callbacks
-// using a semaphor:
-//
-// dispatch_semapshore_t sema = dispatch_semaphore_create(0);
-
-// AnyCFunctionCall(^{
-// // code…
-// dispatch_semapshore_signal(sema);
-// })
-// dispatch_semapshore_wait(sema, *)
-//
-// Such code is a common performance problem, due to inability of GCD to
-// properly handle QoS when a combination of queues and semaphors is used.
-// Good code would either use asynchronous API (when available), or perform
-// the necessary action in asynchronous callback.
-//
-// Currently, the check is performed using a simple heuristical AST pattern
-// matching.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangSACheckers.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
-#include "llvm/Support/Debug.h"
-
-#define DEBUG_TYPE "gcdasyncsemaphorechecker"
-
-using namespace clang;
-using namespace ento;
-using namespace ast_matchers;
-
-namespace {
-
-const char *WarningBinding = "semaphore_wait";
-
-class GCDAsyncSemaphoreChecker : public Checker<check::ASTCodeBody> {
-public:
- void checkASTCodeBody(const Decl *D,
- AnalysisManager &AM,
- BugReporter &BR) const;
-};
-
-class Callback : public MatchFinder::MatchCallback {
- BugReporter &BR;
- const GCDAsyncSemaphoreChecker *C;
- AnalysisDeclContext *ADC;
-
-public:
- Callback(BugReporter &BR,
- AnalysisDeclContext *ADC,
- const GCDAsyncSemaphoreChecker *C) : BR(BR), C(C), ADC(ADC) {}
-
- virtual void run(const MatchFinder::MatchResult &Result) override;
-};
-
-auto callsName(const char *FunctionName)
- -> decltype(callee(functionDecl())) {
- return callee(functionDecl(hasName(FunctionName)));
-}
-
-auto equalsBoundArgDecl(int ArgIdx, const char *DeclName)
- -> decltype(hasArgument(0, expr())) {
- return hasArgument(ArgIdx, ignoringParenCasts(declRefExpr(
- to(varDecl(equalsBoundNode(DeclName))))));
-}
-
-auto bindAssignmentToDecl(const char *DeclName) -> decltype(hasLHS(expr())) {
- return hasLHS(ignoringParenImpCasts(
- declRefExpr(to(varDecl().bind(DeclName)))));
-}
-
-void GCDAsyncSemaphoreChecker::checkASTCodeBody(const Decl *D,
- AnalysisManager &AM,
- BugReporter &BR) const {
-
- // The pattern is very common in tests, and it is OK to use it there.
- if (const auto* ND = dyn_cast<NamedDecl>(D)) {
- std::string DeclName = ND->getNameAsString();
- if (StringRef(DeclName).startswith("test"))
- return;
- }
-
- const char *SemaphoreBinding = "semaphore_name";
- auto SemaphoreCreateM = callExpr(callsName("dispatch_semaphore_create"));
-
- auto SemaphoreBindingM = anyOf(
- forEachDescendant(
- varDecl(hasDescendant(SemaphoreCreateM)).bind(SemaphoreBinding)),
- forEachDescendant(binaryOperator(bindAssignmentToDecl(SemaphoreBinding),
- hasRHS(SemaphoreCreateM))));
-
- auto SemaphoreWaitM = forEachDescendant(
- callExpr(
- allOf(
- callsName("dispatch_semaphore_wait"),
- equalsBoundArgDecl(0, SemaphoreBinding)
- )
- ).bind(WarningBinding));
-
- auto AcceptsBlockM =
- forEachDescendant(callExpr(hasAnyArgument(hasType(
- hasCanonicalType(blockPointerType())
- ))));
-
- auto BlockSignallingM =
- forEachDescendant(callExpr(hasAnyArgument(hasDescendant(callExpr(
- allOf(
- callsName("dispatch_semaphore_signal"),
- equalsBoundArgDecl(0, SemaphoreBinding)
- ))))));
-
- auto FinalM = compoundStmt(
- SemaphoreBindingM,
- SemaphoreWaitM,
- AcceptsBlockM,
- BlockSignallingM);
-
- MatchFinder F;
- Callback CB(BR, AM.getAnalysisDeclContext(D), this);
-
- F.addMatcher(FinalM, &CB);
- F.match(*D->getBody(), AM.getASTContext());
-}
-
-void Callback::run(const MatchFinder::MatchResult &Result) {
- const auto *SW = Result.Nodes.getNodeAs<CallExpr>(WarningBinding);
- assert(SW);
- BR.EmitBasicReport(
- ADC->getDecl(), C,
- /*Name=*/"Semaphore performance anti-pattern",
- /*Category=*/"Performance",
- "Possible semaphore performance anti-pattern: wait on a semaphore "
- "signalled to in a callback",
- PathDiagnosticLocation::createBegin(SW, BR.getSourceManager(), ADC),
- SW->getSourceRange());
-}
-
-}
-
-void ento::registerGCDAsyncSemaphoreChecker(CheckerManager &Mgr) {
- Mgr.registerChecker<GCDAsyncSemaphoreChecker>();
-}
diff --git a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
index 11f4222..29d48ef 100644
--- a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
@@ -604,7 +604,7 @@
if (const auto *BSE = dyn_cast<BinarySymExpr>(SE)) {
return BSE->getOpcode();
} else if (const auto *SC = dyn_cast<SymbolConjured>(SE)) {
- const auto *COE = dyn_cast<CXXOperatorCallExpr>(SC->getStmt());
+ const auto *COE = dyn_cast_or_null<CXXOperatorCallExpr>(SC->getStmt());
if (!COE)
return BO_Comma; // Extremal value, neither EQ nor NE
if (COE->getOperator() == OO_EqualEqual) {
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index a3da79e..1d51339 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -2829,6 +2829,19 @@
return nullptr;
}
+static bool isReferenceCountingPointerDestructor(const CXXDestructorDecl *DD) {
+ if (const IdentifierInfo *II = DD->getParent()->getIdentifier()) {
+ StringRef N = II->getName();
+ if (N.contains_lower("ptr") || N.contains_lower("pointer")) {
+ if (N.contains_lower("ref") || N.contains_lower("cnt") ||
+ N.contains_lower("intrusive") || N.contains_lower("shared")) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
std::shared_ptr<PathDiagnosticPiece> MallocChecker::MallocBugVisitor::VisitNode(
const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
BugReport &BR) {
@@ -2882,21 +2895,33 @@
StackHint = new StackHintGeneratorForSymbol(Sym,
"Returning; memory was released");
- // See if we're releasing memory while inlining a destructor (or one of
- // its callees). If so, enable the atomic-related suppression within that
- // destructor (and all of its callees), which would kick in while visiting
- // other nodes (the visit order is from the bug to the graph root).
+ // See if we're releasing memory while inlining a destructor
+ // (or one of its callees). This turns on various common
+ // false positive suppressions.
+ bool FoundAnyDestructor = false;
for (const LocationContext *LC = CurrentLC; LC; LC = LC->getParent()) {
- if (isa<CXXDestructorDecl>(LC->getDecl())) {
- assert(!ReleaseDestructorLC &&
- "There can be only one release point!");
- ReleaseDestructorLC = LC->getCurrentStackFrame();
- // It is unlikely that releasing memory is delegated to a destructor
- // inside a destructor of a shared pointer, because it's fairly hard
- // to pass the information that the pointer indeed needs to be
- // released into it. So we're only interested in the innermost
- // destructor.
- break;
+ if (const auto *DD = dyn_cast<CXXDestructorDecl>(LC->getDecl())) {
+ if (isReferenceCountingPointerDestructor(DD)) {
+ // This immediately looks like a reference-counting destructor.
+ // We're bad at guessing the original reference count of the object,
+ // so suppress the report for now.
+ BR.markInvalid(getTag(), DD);
+ } else if (!FoundAnyDestructor) {
+ assert(!ReleaseDestructorLC &&
+ "There can be only one release point!");
+ // Suspect that it's a reference counting pointer destructor.
+ // On one of the next nodes might find out that it has atomic
+ // reference counting operations within it (see the code above),
+ // and if so, we'd conclude that it likely is a reference counting
+ // pointer destructor.
+ ReleaseDestructorLC = LC->getCurrentStackFrame();
+ // It is unlikely that releasing memory is delegated to a destructor
+ // inside a destructor of a shared pointer, because it's fairly hard
+ // to pass the information that the pointer indeed needs to be
+ // released into it. So we're only interested in the innermost
+ // destructor.
+ FoundAnyDestructor = true;
+ }
}
}
} else if (isRelinquished(RS, RSPrev, S)) {
diff --git a/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp b/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
index e62fa0f..5060b0e 100644
--- a/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
@@ -28,12 +28,13 @@
namespace {
class MmapWriteExecChecker : public Checker<check::PreCall> {
CallDescription MmapFn;
+ CallDescription MprotectFn;
static int ProtWrite;
static int ProtExec;
static int ProtRead;
mutable std::unique_ptr<BugType> BT;
public:
- MmapWriteExecChecker() : MmapFn("mmap", 6) {}
+ MmapWriteExecChecker() : MmapFn("mmap", 6), MprotectFn("mprotect", 3) {}
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
int ProtExecOv;
int ProtReadOv;
@@ -46,8 +47,8 @@
void MmapWriteExecChecker::checkPreCall(const CallEvent &Call,
CheckerContext &C) const {
- if (Call.isCalled(MmapFn)) {
- SVal ProtVal = Call.getArgSVal(2);
+ if (Call.isCalled(MmapFn) || Call.isCalled(MprotectFn)) {
+ SVal ProtVal = Call.getArgSVal(2);
Optional<nonloc::ConcreteInt> ProtLoc = ProtVal.getAs<nonloc::ConcreteInt>();
int64_t Prot = ProtLoc->getValue().getSExtValue();
if (ProtExecOv != ProtExec)
diff --git a/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
index 6f27995..01d2c04 100644
--- a/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
@@ -44,13 +44,9 @@
};
} // end anonymous namespace
-void NonNullParamChecker::checkPreCall(const CallEvent &Call,
- CheckerContext &C) const {
+/// \return Bitvector marking non-null attributes.
+static llvm::SmallBitVector getNonNullAttrs(const CallEvent &Call) {
const Decl *FD = Call.getDecl();
- if (!FD)
- return;
-
- // Merge all non-null attributes
unsigned NumArgs = Call.getNumArgs();
llvm::SmallBitVector AttrNonNull(NumArgs);
for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) {
@@ -65,43 +61,47 @@
AttrNonNull.set(IdxAST);
}
}
+ return AttrNonNull;
+}
+
+void NonNullParamChecker::checkPreCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ if (!Call.getDecl())
+ return;
+
+ llvm::SmallBitVector AttrNonNull = getNonNullAttrs(Call);
+ unsigned NumArgs = Call.getNumArgs();
ProgramStateRef state = C.getState();
-
- CallEvent::param_type_iterator TyI = Call.param_type_begin(),
- TyE = Call.param_type_end();
+ ArrayRef<ParmVarDecl*> parms = Call.parameters();
for (unsigned idx = 0; idx < NumArgs; ++idx) {
+ // For vararg functions, a corresponding parameter decl may not exist.
+ bool HasParam = idx < parms.size();
// Check if the parameter is a reference. We want to report when reference
// to a null pointer is passed as a parameter.
- bool haveRefTypeParam = false;
- if (TyI != TyE) {
- haveRefTypeParam = (*TyI)->isReferenceType();
- TyI++;
- }
-
+ bool haveRefTypeParam =
+ HasParam ? parms[idx]->getType()->isReferenceType() : false;
bool haveAttrNonNull = AttrNonNull[idx];
- if (!haveAttrNonNull) {
- // Check if the parameter is also marked 'nonnull'.
- ArrayRef<ParmVarDecl*> parms = Call.parameters();
- if (idx < parms.size())
- haveAttrNonNull = parms[idx]->hasAttr<NonNullAttr>();
- }
- if (!haveRefTypeParam && !haveAttrNonNull)
+ // Check if the parameter is also marked 'nonnull'.
+ if (!haveAttrNonNull && HasParam)
+ haveAttrNonNull = parms[idx]->hasAttr<NonNullAttr>();
+
+ if (!haveAttrNonNull && !haveRefTypeParam)
continue;
// If the value is unknown or undefined, we can't perform this check.
const Expr *ArgE = Call.getArgExpr(idx);
SVal V = Call.getArgSVal(idx);
- Optional<DefinedSVal> DV = V.getAs<DefinedSVal>();
+ auto DV = V.getAs<DefinedSVal>();
if (!DV)
continue;
- // Process the case when the argument is not a location.
assert(!haveRefTypeParam || DV->getAs<Loc>());
+ // Process the case when the argument is not a location.
if (haveAttrNonNull && !DV->getAs<Loc>()) {
// If the argument is a union type, we want to handle a potential
// transparent_union GCC extension.
@@ -113,66 +113,63 @@
if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
continue;
- if (Optional<nonloc::CompoundVal> CSV =
- DV->getAs<nonloc::CompoundVal>()) {
- nonloc::CompoundVal::iterator CSV_I = CSV->begin();
- assert(CSV_I != CSV->end());
- V = *CSV_I;
- DV = V.getAs<DefinedSVal>();
- assert(++CSV_I == CSV->end());
- // FIXME: Handle (some_union){ some_other_union_val }, which turns into
- // a LazyCompoundVal inside a CompoundVal.
- if (!V.getAs<Loc>())
- continue;
- // Retrieve the corresponding expression.
- if (const CompoundLiteralExpr *CE = dyn_cast<CompoundLiteralExpr>(ArgE))
- if (const InitListExpr *IE =
- dyn_cast<InitListExpr>(CE->getInitializer()))
- ArgE = dyn_cast<Expr>(*(IE->begin()));
+ auto CSV = DV->getAs<nonloc::CompoundVal>();
- } else {
- // FIXME: Handle LazyCompoundVals?
+ // FIXME: Handle LazyCompoundVals?
+ if (!CSV)
continue;
- }
+
+ V = *(CSV->begin());
+ DV = V.getAs<DefinedSVal>();
+ assert(++CSV->begin() == CSV->end());
+ // FIXME: Handle (some_union){ some_other_union_val }, which turns into
+ // a LazyCompoundVal inside a CompoundVal.
+ if (!V.getAs<Loc>())
+ continue;
+
+ // Retrieve the corresponding expression.
+ if (const auto *CE = dyn_cast<CompoundLiteralExpr>(ArgE))
+ if (const auto *IE = dyn_cast<InitListExpr>(CE->getInitializer()))
+ ArgE = dyn_cast<Expr>(*(IE->begin()));
}
ConstraintManager &CM = C.getConstraintManager();
ProgramStateRef stateNotNull, stateNull;
std::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
- if (stateNull) {
- if (!stateNotNull) {
- // Generate an error node. Check for a null node in case
- // we cache out.
- if (ExplodedNode *errorNode = C.generateErrorNode(stateNull)) {
+ // Generate an error node. Check for a null node in case
+ // we cache out.
+ if (stateNull && !stateNotNull) {
+ if (ExplodedNode *errorNode = C.generateErrorNode(stateNull)) {
- std::unique_ptr<BugReport> R;
- if (haveAttrNonNull)
- R = genReportNullAttrNonNull(errorNode, ArgE);
- else if (haveRefTypeParam)
- R = genReportReferenceToNullPointer(errorNode, ArgE);
+ std::unique_ptr<BugReport> R;
+ if (haveAttrNonNull)
+ R = genReportNullAttrNonNull(errorNode, ArgE);
+ else if (haveRefTypeParam)
+ R = genReportReferenceToNullPointer(errorNode, ArgE);
- // Highlight the range of the argument that was null.
- R->addRange(Call.getArgSourceRange(idx));
+ // Highlight the range of the argument that was null.
+ R->addRange(Call.getArgSourceRange(idx));
- // Emit the bug report.
- C.emitReport(std::move(R));
- }
-
- // Always return. Either we cached out or we just emitted an error.
- return;
+ // Emit the bug report.
+ C.emitReport(std::move(R));
}
+
+ // Always return. Either we cached out or we just emitted an error.
+ return;
+ }
+
+ if (stateNull) {
if (ExplodedNode *N = C.generateSink(stateNull, C.getPredecessor())) {
ImplicitNullDerefEvent event = {
- V, false, N, &C.getBugReporter(),
- /*IsDirectDereference=*/haveRefTypeParam};
+ V, false, N, &C.getBugReporter(),
+ /*IsDirectDereference=*/haveRefTypeParam};
dispatchEvent(event);
}
}
// If a pointer value passed the check we should assume that it is
// indeed not null from this point forward.
- assert(stateNotNull);
state = stateNotNull;
}
diff --git a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
index b348453..6230d53 100644
--- a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -30,6 +30,7 @@
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
@@ -40,21 +41,6 @@
using namespace ento;
namespace {
-// Do not reorder! The getMostNullable method relies on the order.
-// Optimization: Most pointers expected to be unspecified. When a symbol has an
-// unspecified or nonnull type non of the rules would indicate any problem for
-// that symbol. For this reason only nullable and contradicted nullability are
-// stored for a symbol. When a symbol is already contradicted, it can not be
-// casted back to nullable.
-enum class Nullability : char {
- Contradicted, // Tracked nullability is contradicted by an explicit cast. Do
- // not report any nullability related issue for this symbol.
- // This nullability is propagated aggressively to avoid false
- // positive results. See the comment on getMostNullable method.
- Nullable,
- Unspecified,
- Nonnull
-};
/// Returns the most nullable nullability. This is used for message expressions
/// like [receiver method], where the nullability of this expression is either
@@ -345,17 +331,6 @@
nullptr);
}
-static Nullability getNullabilityAnnotation(QualType Type) {
- const auto *AttrType = Type->getAs<AttributedType>();
- if (!AttrType)
- return Nullability::Unspecified;
- if (AttrType->getAttrKind() == AttributedType::attr_nullable)
- return Nullability::Nullable;
- else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)
- return Nullability::Nonnull;
- return Nullability::Unspecified;
-}
-
/// Returns true when the value stored at the given location is null
/// and the passed in type is nonnnull.
static bool checkValueAtLValForInvariantViolation(ProgramStateRef State,
@@ -872,7 +847,7 @@
// are either item retrieval related or not interesting nullability wise.
// Using this fact, to keep the code easier to read just ignore the return
// value of every instance method of dictionaries.
- if (M.isInstanceMessage() && Name.find("Dictionary") != StringRef::npos) {
+ if (M.isInstanceMessage() && Name.contains("Dictionary")) {
State =
State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
C.addTransition(State);
@@ -880,7 +855,7 @@
}
// For similar reasons ignore some methods of Cocoa arrays.
StringRef FirstSelectorSlot = M.getSelector().getNameForSlot(0);
- if (Name.find("Array") != StringRef::npos &&
+ if (Name.contains("Array") &&
(FirstSelectorSlot == "firstObject" ||
FirstSelectorSlot == "lastObject")) {
State =
@@ -893,7 +868,7 @@
// encodings are used. Using lossless encodings is so frequent that ignoring
// this class of methods reduced the emitted diagnostics by about 30% on
// some projects (and all of that was false positives).
- if (Name.find("String") != StringRef::npos) {
+ if (Name.contains("String")) {
for (auto Param : M.parameters()) {
if (Param->getName() == "encoding") {
State = State->set<NullabilityMap>(ReturnRegion,
diff --git a/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
new file mode 100644
index 0000000..0433a8a
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
@@ -0,0 +1,157 @@
+//===- ObjCAutoreleaseWriteChecker.cpp ----------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ObjCAutoreleaseWriteChecker which warns against writes
+// into autoreleased out parameters which are likely to cause crashes.
+// An example of a problematic write is a write to {@code error} in the example
+// below:
+//
+// - (BOOL) mymethod:(NSError *__autoreleasing *)error list:(NSArray*) list {
+// [list enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+// NSString *myString = obj;
+// if ([myString isEqualToString:@"error"] && error)
+// *error = [NSError errorWithDomain:@"MyDomain" code:-1];
+// }];
+// return false;
+// }
+//
+// Such code is very likely to crash due to the other queue autorelease pool
+// begin able to free the error object.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "llvm/ADT/Twine.h"
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;
+
+namespace {
+
+const char *ProblematicWriteBind = "problematicwrite";
+const char *ParamBind = "parambind";
+const char *MethodBind = "methodbind";
+
+class ObjCAutoreleaseWriteChecker : public Checker<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const;
+private:
+ std::vector<std::string> SelectorsWithAutoreleasingPool = {
+ "enumerateObjectsUsingBlock:",
+ "enumerateKeysAndObjectsUsingBlock:",
+ "enumerateKeysAndObjectsWithOptions:usingBlock:",
+ "enumerateObjectsWithOptions:usingBlock:",
+ "enumerateObjectsAtIndexes:options:usingBlock:",
+ "enumerateIndexesWithOptions:usingBlock:",
+ "enumerateIndexesUsingBlock:",
+ "enumerateIndexesInRange:options:usingBlock:",
+ "enumerateRangesUsingBlock:",
+ "enumerateRangesWithOptions:usingBlock:",
+ "enumerateRangesInRange:options:usingBlock:"
+ "objectWithOptions:passingTest:",
+ };
+
+ std::vector<std::string> FunctionsWithAutoreleasingPool = {
+ "dispatch_async", "dispatch_group_async", "dispatch_barrier_async"};
+};
+}
+
+static inline std::vector<llvm::StringRef> toRefs(std::vector<std::string> V) {
+ return std::vector<llvm::StringRef>(V.begin(), V.end());
+}
+
+static auto callsNames(std::vector<std::string> FunctionNames)
+ -> decltype(callee(functionDecl())) {
+ return callee(functionDecl(hasAnyName(toRefs(FunctionNames))));
+}
+
+static void emitDiagnostics(BoundNodes &Match, const Decl *D, BugReporter &BR,
+ AnalysisManager &AM,
+ const ObjCAutoreleaseWriteChecker *Checker) {
+ AnalysisDeclContext *ADC = AM.getAnalysisDeclContext(D);
+
+ const auto *PVD = Match.getNodeAs<ParmVarDecl>(ParamBind);
+ assert(PVD);
+ QualType Ty = PVD->getType();
+ if (Ty->getPointeeType().getObjCLifetime() != Qualifiers::OCL_Autoreleasing)
+ return;
+ const auto *SW = Match.getNodeAs<Expr>(ProblematicWriteBind);
+ bool IsMethod = Match.getNodeAs<ObjCMethodDecl>(MethodBind) != nullptr;
+ const char *Name = IsMethod ? "method" : "function";
+ assert(SW);
+ BR.EmitBasicReport(
+ ADC->getDecl(), Checker,
+ /*Name=*/"Writing into auto-releasing variable from a different queue",
+ /*Category=*/"Memory",
+ (llvm::Twine("Writing into an auto-releasing out parameter inside ") +
+ "autorelease pool that may exit before " + Name + " returns; consider "
+ "writing first to a strong local variable declared outside of the block")
+ .str(),
+ PathDiagnosticLocation::createBegin(SW, BR.getSourceManager(), ADC),
+ SW->getSourceRange());
+}
+
+void ObjCAutoreleaseWriteChecker::checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const {
+
+ // Write into a binded object, e.g. *ParamBind = X.
+ auto WritesIntoM = binaryOperator(
+ hasLHS(unaryOperator(
+ hasOperatorName("*"),
+ hasUnaryOperand(
+ ignoringParenImpCasts(
+ declRefExpr(to(parmVarDecl(equalsBoundNode(ParamBind))))))
+ )),
+ hasOperatorName("=")
+ ).bind(ProblematicWriteBind);
+
+ // WritesIntoM happens inside a block passed as an argument.
+ auto WritesInBlockM = hasAnyArgument(allOf(
+ hasType(hasCanonicalType(blockPointerType())),
+ forEachDescendant(WritesIntoM)
+ ));
+
+ auto CallsAsyncM = stmt(anyOf(
+ callExpr(allOf(
+ callsNames(FunctionsWithAutoreleasingPool), WritesInBlockM)),
+ objcMessageExpr(allOf(
+ hasAnySelector(toRefs(SelectorsWithAutoreleasingPool)),
+ WritesInBlockM))
+ ));
+
+ auto DoublePointerParamM =
+ parmVarDecl(hasType(pointerType(
+ pointee(hasCanonicalType(objcObjectPointerType())))))
+ .bind(ParamBind);
+
+ auto HasParamAndWritesAsyncM = allOf(
+ hasAnyParameter(DoublePointerParamM),
+ forEachDescendant(CallsAsyncM));
+
+ auto MatcherM = decl(anyOf(
+ objcMethodDecl(HasParamAndWritesAsyncM).bind(MethodBind),
+ functionDecl(HasParamAndWritesAsyncM)));
+
+ auto Matches = match(MatcherM, *D, AM.getASTContext());
+ for (BoundNodes Match : Matches)
+ emitDiagnostics(Match, D, BR, AM, this);
+}
+
+void ento::registerAutoreleaseWriteChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<ObjCAutoreleaseWriteChecker>();
+}
diff --git a/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
index b17cd8d..2957630 100644
--- a/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -237,7 +237,7 @@
};
std::transform(RD->field_begin(), RD->field_end(),
std::back_inserter(Fields), GatherSizesAndAlignments);
- std::sort(Fields.begin(), Fields.end());
+ llvm::sort(Fields.begin(), Fields.end());
// This lets us skip over vptrs and non-virtual bases,
// so that we can just worry about the fields in our object.
// Note that this does cause us to miss some cases where we
diff --git a/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
index 4c4a8e3..63f82b2 100644
--- a/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
@@ -308,6 +308,10 @@
// Indexing with 0 is OK.
if (Idx.isZeroConstant())
return;
+
+ // Indexing vector-type expressions is also OK.
+ if (SubsExpr->getBase()->getType()->isVectorType())
+ return;
reportPointerArithMisuse(SubsExpr->getBase(), C);
}
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index bf5945c..98d5fcf 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -1929,10 +1929,12 @@
isa<CXXBoolLiteralExpr>(E);
}
-static std::string describeRegion(const MemRegion *MR) {
+static Optional<std::string> describeRegion(const MemRegion *MR) {
+ if (const auto *VR = dyn_cast_or_null<VarRegion>(MR))
+ return std::string(VR->getDecl()->getName());
// Once we support more storage locations for bindings,
// this would need to be improved.
- return cast<VarRegion>(MR)->getDecl()->getName();
+ return None;
}
/// Returns true if this stack frame is for an Objective-C method that is a
@@ -2399,9 +2401,9 @@
os << "Object leaked: ";
- if (FirstBinding) {
- os << "object allocated and stored into '"
- << describeRegion(FirstBinding) << '\'';
+ Optional<std::string> RegionDescription = describeRegion(FirstBinding);
+ if (RegionDescription) {
+ os << "object allocated and stored into '" << *RegionDescription << '\'';
}
else
os << "allocated object";
@@ -2519,7 +2521,8 @@
UniqueingDecl = AllocNode->getLocationContext()->getDecl();
}
-void CFRefLeakReport::createDescription(CheckerContext &Ctx, bool GCEnabled, bool IncludeAllocationLine) {
+void CFRefLeakReport::createDescription(CheckerContext &Ctx, bool GCEnabled,
+ bool IncludeAllocationLine) {
assert(Location.isValid() && UniqueingDecl && UniqueingLocation.isValid());
Description.clear();
llvm::raw_string_ostream os(Description);
@@ -2528,8 +2531,9 @@
os << "(when using garbage collection) ";
os << "of an object";
- if (AllocBinding) {
- os << " stored into '" << describeRegion(AllocBinding) << '\'';
+ Optional<std::string> RegionDescription = describeRegion(AllocBinding);
+ if (RegionDescription) {
+ os << " stored into '" << *RegionDescription << '\'';
if (IncludeAllocationLine) {
FullSourceLoc SL(AllocStmt->getLocStart(), Ctx.getSourceManager());
os << " (allocated on line " << SL.getSpellingLineNumber() << ")";
diff --git a/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp b/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp
new file mode 100644
index 0000000..3b29944
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp
@@ -0,0 +1,52 @@
+//== TrustNonnullChecker.cpp - Checker for trusting annotations -*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker adds an assumption that methods annotated with _Nonnull
+// which come from system headers actually return a non-null pointer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class TrustNonnullChecker : public Checker<check::PostCall> {
+public:
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
+ // Only trust annotations for system headers for non-protocols.
+ if (!Call.isInSystemHeader())
+ return;
+
+ QualType RetType = Call.getResultType();
+ if (!RetType->isAnyPointerType())
+ return;
+
+ ProgramStateRef State = C.getState();
+ if (getNullabilityAnnotation(RetType) == Nullability::Nonnull)
+ if (auto L = Call.getReturnValue().getAs<Loc>())
+ State = State->assume(*L, /*Assumption=*/true);
+
+ C.addTransition(State);
+ }
+};
+
+} // end empty namespace
+
+
+void ento::registerTrustNonnullChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<TrustNonnullChecker>();
+}
diff --git a/lib/StaticAnalyzer/Checkers/ValistChecker.cpp b/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
index 44147e5..039bc08 100644
--- a/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
@@ -56,7 +56,6 @@
private:
const MemRegion *getVAListAsRegion(SVal SV, const Expr *VAExpr,
bool &IsSymbolic, CheckerContext &C) const;
- StringRef getVariableNameFromRegion(const MemRegion *Reg) const;
const ExplodedNode *getStartCallSite(const ExplodedNode *N,
const MemRegion *Reg) const;
diff --git a/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/lib/StaticAnalyzer/Core/AnalysisManager.cpp
index 53199f7..af107ab 100644
--- a/lib/StaticAnalyzer/Core/AnalysisManager.cpp
+++ b/lib/StaticAnalyzer/Core/AnalysisManager.cpp
@@ -26,6 +26,7 @@
// Adding LoopExit elements to the CFG is a requirement for loop
// unrolling.
Options.includeLoopExitInCFG() || Options.shouldUnrollLoops(),
+ Options.includeScopesInCFG(),
Options.shouldSynthesizeBodies(),
Options.shouldConditionalizeStaticInitializers(),
/*addCXXNewAllocator=*/true,
diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index b831c69..65231ea 100644
--- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -1,4 +1,4 @@
-//===-- AnalyzerOptions.cpp - Analysis Engine Options -----------*- C++ -*-===//
+//===- AnalyzerOptions.cpp - Analysis Engine Options ----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,8 +16,15 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstddef>
+#include <utility>
+#include <vector>
using namespace clang;
using namespace ento;
@@ -81,7 +88,6 @@
IPAKind AnalyzerOptions::getIPAMode() {
if (IPAMode == IPAK_NotSet) {
-
// Use the User Mode to set the default IPA value.
// Note, we have to add the string to the Config map for the ConfigDumper
// checker to function properly.
@@ -218,6 +224,12 @@
/* Default = */ true);
}
+bool AnalyzerOptions::includeScopesInCFG() {
+ return getBooleanOption(IncludeScopesInCFG,
+ "cfg-scopes",
+ /* Default = */ false);
+}
+
bool AnalyzerOptions::mayInlineCXXStandardLibrary() {
return getBooleanOption(InlineCXXStandardLibrary,
"c++-stdlib-inlining",
@@ -251,7 +263,7 @@
bool AnalyzerOptions::mayInlineCXXTemporaryDtors() {
return getBooleanOption(InlineCXXTemporaryDtors,
"c++-temp-dtor-inlining",
- /*Default=*/false);
+ /*Default=*/true);
}
bool AnalyzerOptions::mayInlineObjCMethod() {
@@ -340,7 +352,6 @@
unsigned AnalyzerOptions::getMaxInlinableSize() {
if (!MaxInlinableSize.hasValue()) {
-
int DefaultValue = 0;
UserModeKind HighLevelMode = getUserMode();
switch (HighLevelMode) {
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 5d32ef3..376bca8 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1,4 +1,4 @@
-// BugReporter.cpp - Generate PathDiagnostics for Bugs ------------*- C++ -*--//
+//===- BugReporter.cpp - Generate PathDiagnostics for bugs ----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,28 +13,62 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
-#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ParentMap.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
#include <memory>
#include <queue>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
using namespace clang;
using namespace ento;
@@ -47,7 +81,7 @@
"The maximum number of bug reports in the same equivalence class "
"where at least one report is valid (not suppressed)");
-BugReporterVisitor::~BugReporterVisitor() {}
+BugReporterVisitor::~BugReporterVisitor() = default;
void BugReporterContext::anchor() {}
@@ -127,10 +161,9 @@
if (i == N-1)
break;
- if (PathDiagnosticEventPiece *nextEvent =
+ if (auto *nextEvent =
dyn_cast<PathDiagnosticEventPiece>(path.front().get())) {
- PathDiagnosticEventPiece *event =
- cast<PathDiagnosticEventPiece>(piece.get());
+ auto *event = cast<PathDiagnosticEventPiece>(piece.get());
// Check to see if we should keep one of the two pieces. If we
// come up with a preference, record which piece to keep, and consume
// another piece from the path.
@@ -152,8 +185,8 @@
/// A map from PathDiagnosticPiece to the LocationContext of the inlined
/// function call it represents.
-typedef llvm::DenseMap<const PathPieces *, const LocationContext *>
- LocationContextMap;
+using LocationContextMap =
+ llvm::DenseMap<const PathPieces *, const LocationContext *>;
/// Recursively scan through a path and prune out calls and macros pieces
/// that aren't needed. Return true if afterwards the path contains
@@ -225,12 +258,11 @@
static void
adjustCallLocations(PathPieces &Pieces,
PathDiagnosticLocation *LastCallLocation = nullptr) {
- for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) {
- PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(I->get());
+ for (const auto &I : Pieces) {
+ auto *Call = dyn_cast<PathDiagnosticCallPiece>(I.get());
- if (!Call) {
+ if (!Call)
continue;
- }
if (LastCallLocation) {
bool CallerIsImplicit = hasImplicitBody(Call->getCaller());
@@ -313,8 +345,10 @@
//===----------------------------------------------------------------------===//
namespace {
+
class NodeMapClosure : public BugReport::NodeResolver {
InterExplodedGraphMap &M;
+
public:
NodeMapClosure(InterExplodedGraphMap &m) : M(m) {}
@@ -327,15 +361,15 @@
BugReport *R;
PathDiagnosticConsumer *PDC;
NodeMapClosure NMC;
+
public:
const LocationContext *LC;
PathDiagnosticBuilder(GRBugReporter &br,
BugReport *r, InterExplodedGraphMap &Backmap,
PathDiagnosticConsumer *pdc)
- : BugReporterContext(br),
- R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext())
- {}
+ : BugReporterContext(br), R(r), PDC(pdc), NMC(Backmap),
+ LC(r->getErrorNode()->getLocationContext()) {}
PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N);
@@ -364,7 +398,8 @@
return PDC ? PDC->supportsLogicalOpControlFlow() : true;
}
};
-} // end anonymous namespace
+
+} // namespace
PathDiagnosticLocation
PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) {
@@ -378,7 +413,6 @@
PathDiagnosticLocation
PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os,
const ExplodedNode *N) {
-
// Slow, but probably doesn't matter.
if (os.str().empty())
os << ' ';
@@ -432,12 +466,12 @@
getEnclosingStmtLocation(const Stmt *S, SourceManager &SMgr, const ParentMap &P,
const LocationContext *LC, bool allowNestedContexts) {
if (!S)
- return PathDiagnosticLocation();
+ return {};
while (const Stmt *Parent = getEnclosingParent(S, P)) {
switch (Parent->getStmtClass()) {
case Stmt::BinaryOperatorClass: {
- const BinaryOperator *B = cast<BinaryOperator>(Parent);
+ const auto *B = cast<BinaryOperator>(Parent);
if (B->isLogicalOp())
return PathDiagnosticLocation(allowNestedContexts ? B : S, SMgr, LC);
break;
@@ -529,20 +563,19 @@
//===----------------------------------------------------------------------===//
// "Minimal" path diagnostic generation algorithm.
//===----------------------------------------------------------------------===//
-typedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair;
-typedef SmallVector<StackDiagPair, 6> StackDiagVector;
+using StackDiagPair =
+ std::pair<PathDiagnosticCallPiece *, const ExplodedNode *>;
+using StackDiagVector = SmallVector<StackDiagPair, 6>;
static void updateStackPiecesWithMessage(PathDiagnosticPiece &P,
StackDiagVector &CallStack) {
// If the piece contains a special message, add it to all the call
// pieces on the active stack.
- if (PathDiagnosticEventPiece *ep = dyn_cast<PathDiagnosticEventPiece>(&P)) {
-
+ if (auto *ep = dyn_cast<PathDiagnosticEventPiece>(&P)) {
if (ep->hasCallStackHint())
- for (StackDiagVector::iterator I = CallStack.begin(),
- E = CallStack.end(); I != E; ++I) {
- PathDiagnosticCallPiece *CP = I->first;
- const ExplodedNode *N = I->second;
+ for (const auto &I : CallStack) {
+ PathDiagnosticCallPiece *CP = I.first;
+ const ExplodedNode *N = I.second;
std::string stackMsg = ep->getCallStackMessage(N);
// The last message on the path to final bug is the most important
@@ -556,14 +589,12 @@
static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM);
-
/// Add path diagnostic for statement associated with node \p N
/// to diagnostics \p PD.
/// Precondition: location associated with \p N is a \c BlockEdge.
static void generateMinimalDiagnosticsForBlockEdge(const ExplodedNode *N,
PathDiagnosticBuilder &PDB,
PathDiagnostic &PD) {
-
const LocationContext *LC = N->getLocationContext();
SourceManager& SMgr = PDB.getSourceManager();
BlockEdge BE = N->getLocation().castAs<BlockEdge>();
@@ -616,16 +647,16 @@
case Stmt::CaseStmtClass: {
os << "Control jumps to 'case ";
- const CaseStmt *Case = cast<CaseStmt>(S);
+ const auto *Case = cast<CaseStmt>(S);
const Expr *LHS = Case->getLHS()->IgnoreParenCasts();
// Determine if it is an enum.
bool GetRawInt = true;
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
+ if (const auto *DR = dyn_cast<DeclRefExpr>(LHS)) {
// FIXME: Maybe this should be an assertion. Are there cases
// were it is not an EnumConstantDecl?
- const EnumConstantDecl *D = dyn_cast<EnumConstantDecl>(DR->getDecl());
+ const auto *D = dyn_cast<EnumConstantDecl>(DR->getDecl());
if (D) {
GetRawInt = false;
@@ -691,7 +722,7 @@
if (!PDB.supportsLogicalOpControlFlow())
break;
- const BinaryOperator *B = cast<BinaryOperator>(T);
+ const auto *B = cast<BinaryOperator>(T);
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
os << "Left side of '";
@@ -742,7 +773,7 @@
break;
}
- case Stmt::DoStmtClass: {
+ case Stmt::DoStmtClass:
if (*(Src->succ_begin()) == Dst) {
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
@@ -766,12 +797,10 @@
std::make_shared<PathDiagnosticControlFlowPiece>(
Start, End, "Loop condition is false. Exiting loop"));
}
-
break;
- }
case Stmt::WhileStmtClass:
- case Stmt::ForStmtClass: {
+ case Stmt::ForStmtClass:
if (*(Src->succ_begin() + 1) == Dst) {
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
@@ -795,7 +824,6 @@
}
break;
- }
case Stmt::IfStmtClass: {
PathDiagnosticLocation End = PDB.ExecutionContinues(N);
@@ -824,7 +852,6 @@
PathDiagnostic &PD,
LocationContextMap &LCM,
StackDiagVector &CallStack) {
-
SourceManager &SMgr = PDB.getSourceManager();
ProgramPoint P = N->getLocation();
@@ -911,7 +938,7 @@
//===----------------------------------------------------------------------===//
static bool IsControlFlowExpr(const Stmt *S) {
- const Expr *E = dyn_cast<Expr>(S);
+ const auto *E = dyn_cast<Expr>(S);
if (!E)
return false;
@@ -921,7 +948,7 @@
if (isa<AbstractConditionalOperator>(E))
return true;
- if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E))
+ if (const auto *B = dyn_cast<BinaryOperator>(E))
if (B->isLogicalOp())
return true;
@@ -929,22 +956,26 @@
}
namespace {
+
class ContextLocation : public PathDiagnosticLocation {
bool IsDead;
+
public:
ContextLocation(const PathDiagnosticLocation &L, bool isdead = false)
- : PathDiagnosticLocation(L), IsDead(isdead) {}
+ : PathDiagnosticLocation(L), IsDead(isdead) {}
void markDead() { IsDead = true; }
bool isDead() const { return IsDead; }
};
+} // namespace
+
static PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L,
const LocationContext *LC,
bool firstCharOnly = false) {
if (const Stmt *S = L.asStmt()) {
const Stmt *Original = S;
- while (1) {
+ while (true) {
// Adjust the location for some expressions that are best referenced
// by one of their subexpressions.
switch (S->getStmtClass()) {
@@ -969,7 +1000,6 @@
firstCharOnly = true;
continue;
}
-
break;
}
@@ -983,9 +1013,13 @@
return L;
}
+namespace {
+
class EdgeBuilder {
std::vector<ContextLocation> CLocs;
- typedef std::vector<ContextLocation>::iterator iterator;
+
+ using iterator = std::vector<ContextLocation>::iterator;
+
PathDiagnostic &PD;
PathDiagnosticBuilder &PDB;
PathDiagnosticLocation PrevLoc;
@@ -997,8 +1031,6 @@
PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L);
-
-
void popLocation() {
if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) {
// For contexts, we only one the first character as the range.
@@ -1009,16 +1041,15 @@
public:
EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb)
- : PD(pd), PDB(pdb) {
+ : PD(pd), PDB(pdb) {
+ // If the PathDiagnostic already has pieces, add the enclosing statement
+ // of the first piece as a context as well.
+ if (!PD.path.empty()) {
+ PrevLoc = (*PD.path.begin())->getLocation();
- // If the PathDiagnostic already has pieces, add the enclosing statement
- // of the first piece as a context as well.
- if (!PD.path.empty()) {
- PrevLoc = (*PD.path.begin())->getLocation();
-
- if (const Stmt *S = PrevLoc.asStmt())
- addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
- }
+ if (const Stmt *S = PrevLoc.asStmt())
+ addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
+ }
}
~EdgeBuilder() {
@@ -1048,8 +1079,8 @@
void addContext(const PathDiagnosticLocation &L);
void addExtendedContext(const Stmt *S);
};
-} // end anonymous namespace
+} // namespace
PathDiagnosticLocation
EdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) {
@@ -1065,7 +1096,6 @@
bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
const PathDiagnosticLocation &Containee) {
-
if (Container == Containee)
return true;
@@ -1140,7 +1170,6 @@
void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd,
bool IsPostJump) {
-
if (!alwaysAdd && NewLoc.asLocation().isMacroID())
return;
@@ -1186,7 +1215,7 @@
}
bool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) {
- if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt()))
+ if (const auto *X = dyn_cast_or_null<Expr>(L.asStmt()))
return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X);
return false;
@@ -1209,6 +1238,7 @@
case Stmt::DoStmtClass:
case Stmt::ObjCAtSynchronizedStmtClass:
addContext(Parent);
+ break;
default:
break;
}
@@ -1256,7 +1286,7 @@
// because the constraint solver sometimes simplifies certain symbolic values
// into constants when appropriate, and this complicates reasoning about
// interesting values.
-typedef llvm::DenseSet<const Expr *> InterestingExprs;
+using InterestingExprs = llvm::DenseSet<const Expr *>;
static void reversePropagateIntererstingSymbols(BugReport &R,
InterestingExprs &IE,
@@ -1275,7 +1305,7 @@
case Stmt::BinaryOperatorClass:
case Stmt::UnaryOperatorClass: {
for (const Stmt *SubStmt : Ex->children()) {
- if (const Expr *child = dyn_cast_or_null<Expr>(SubStmt)) {
+ if (const auto *child = dyn_cast_or_null<Expr>(SubStmt)) {
IE.insert(child);
SVal ChildV = State->getSVal(child, LCtx);
R.markInteresting(ChildV);
@@ -1297,8 +1327,8 @@
// FIXME: Handle non-CallExpr-based CallEvents.
const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame();
const Stmt *CallSite = Callee->getCallSite();
- if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) {
+ if (const auto *CE = dyn_cast_or_null<CallExpr>(CallSite)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) {
FunctionDecl::param_const_iterator PI = FD->param_begin(),
PE = FD->param_end();
CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
@@ -1315,8 +1345,6 @@
}
}
-
-
//===----------------------------------------------------------------------===//
// Functions for determining if a loop was executed 0 times.
//===----------------------------------------------------------------------===//
@@ -1377,7 +1405,7 @@
const Stmt *LoopBody = nullptr;
switch (Term->getStmtClass()) {
case Stmt::CXXForRangeStmtClass: {
- const CXXForRangeStmt *FR = cast<CXXForRangeStmt>(Term);
+ const auto *FR = cast<CXXForRangeStmt>(Term);
if (isContainedByStmt(PM, FR->getInc(), S))
return true;
if (isContainedByStmt(PM, FR->getLoopVarStmt(), S))
@@ -1386,14 +1414,14 @@
break;
}
case Stmt::ForStmtClass: {
- const ForStmt *FS = cast<ForStmt>(Term);
+ const auto *FS = cast<ForStmt>(Term);
if (isContainedByStmt(PM, FS->getInc(), S))
return true;
LoopBody = FS->getBody();
break;
}
case Stmt::ObjCForCollectionStmtClass: {
- const ObjCForCollectionStmt *FC = cast<ObjCForCollectionStmt>(Term);
+ const auto *FC = cast<ObjCForCollectionStmt>(Term);
LoopBody = FC->getBody();
break;
}
@@ -1416,7 +1444,6 @@
StackDiagVector &CallStack,
PathDiagnostic &PD,
InterestingExprs &IE) {
-
const ExplodedNode *NextNode = N->getFirstPred();
ProgramPoint P = N->getLocation();
const SourceManager& SM = PDB.getSourceManager();
@@ -1429,7 +1456,7 @@
return;
} else if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
const Stmt *S = CE->getCalleeContext()->getCallSite();
- if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
+ if (const auto *Ex = dyn_cast_or_null<Expr>(S)) {
reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
N->getState().get(), Ex,
N->getLocationContext());
@@ -1447,7 +1474,6 @@
CallStack.push_back(StackDiagPair(P, N));
return;
} else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
-
// Pop the call hierarchy if we are done walking the contents
// of a function call.
@@ -1511,9 +1537,9 @@
PathDiagnosticLocation L(Loop, SM, PDB.LC);
const CompoundStmt *CS = nullptr;
- if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
+ if (const auto *FS = dyn_cast<ForStmt>(Loop))
CS = dyn_cast<CompoundStmt>(FS->getBody());
- else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
+ else if (const auto *WS = dyn_cast<WhileStmt>(Loop))
CS = dyn_cast<CompoundStmt>(WS->getBody());
auto p = std::make_shared<PathDiagnosticEventPiece>(
@@ -1644,8 +1670,7 @@
/// which returns the element for ObjCForCollectionStmts.
static const Stmt *getTerminatorCondition(const CFGBlock *B) {
const Stmt *S = B->getTerminatorCondition();
- if (const ObjCForCollectionStmt *FS =
- dyn_cast_or_null<ObjCForCollectionStmt>(S))
+ if (const auto *FS = dyn_cast_or_null<ObjCForCollectionStmt>(S))
return FS->getElement();
return S;
}
@@ -1746,7 +1771,7 @@
if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
const Stmt *S = CE->getCalleeContext()->getCallSite();
// Propagate the interesting symbols accordingly.
- if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
+ if (const auto *Ex = dyn_cast_or_null<Expr>(S)) {
reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
N->getState().get(), Ex,
N->getLocationContext());
@@ -1802,15 +1827,13 @@
PathDiagnosticLocation L(Loop, SM, PDB.LC);
const Stmt *Body = nullptr;
- if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
+ if (const auto *FS = dyn_cast<ForStmt>(Loop))
Body = FS->getBody();
- else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
+ else if (const auto *WS = dyn_cast<WhileStmt>(Loop))
Body = WS->getBody();
- else if (const ObjCForCollectionStmt *OFS =
- dyn_cast<ObjCForCollectionStmt>(Loop)) {
+ else if (const auto *OFS = dyn_cast<ObjCForCollectionStmt>(Loop)) {
Body = OFS->getBody();
- } else if (const CXXForRangeStmt *FRS =
- dyn_cast<CXXForRangeStmt>(Loop)) {
+ } else if (const auto *FRS = dyn_cast<CXXForRangeStmt>(Loop)) {
Body = FRS->getBody();
}
// do-while statements are explicitly excluded here
@@ -1823,7 +1846,7 @@
addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);
PD.getActivePath().push_front(std::move(p));
- if (const CompoundStmt *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
+ if (const auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
addEdgeToPath(PD.getActivePath(), PrevLoc,
PathDiagnosticLocation::createEndBrace(CS, SM),
PDB.LC);
@@ -1878,7 +1901,6 @@
PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N,
LocationContextMap &LCM,
ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
-
BugReport *report = PDB.getBugReport();
const SourceManager& SM = PDB.getSourceManager();
StackDiagVector CallStack;
@@ -1952,7 +1974,7 @@
static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) {
switch (S->getStmtClass()) {
case Stmt::BinaryOperatorClass: {
- const BinaryOperator *BO = cast<BinaryOperator>(S);
+ const auto *BO = cast<BinaryOperator>(S);
if (!BO->isLogicalOp())
return false;
return BO->getLHS() == Cond || BO->getRHS() == Cond;
@@ -1974,7 +1996,7 @@
case Stmt::BinaryConditionalOperatorClass:
return cast<BinaryConditionalOperator>(S)->getCond() == Cond;
case Stmt::ConditionalOperatorClass: {
- const ConditionalOperator *CO = cast<ConditionalOperator>(S);
+ const auto *CO = cast<ConditionalOperator>(S);
return CO->getCond() == Cond ||
CO->getLHS() == Cond ||
CO->getRHS() == Cond;
@@ -1982,7 +2004,7 @@
case Stmt::ObjCForCollectionStmtClass:
return cast<ObjCForCollectionStmt>(S)->getElement() == Cond;
case Stmt::CXXForRangeStmtClass: {
- const CXXForRangeStmt *FRS = cast<CXXForRangeStmt>(S);
+ const auto *FRS = cast<CXXForRangeStmt>(S);
return FRS->getCond() == Cond || FRS->getRangeInit() == Cond;
}
default:
@@ -1991,16 +2013,15 @@
}
static bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL) {
- if (const ForStmt *FS = dyn_cast<ForStmt>(FL))
+ if (const auto *FS = dyn_cast<ForStmt>(FL))
return FS->getInc() == S || FS->getInit() == S;
- if (const CXXForRangeStmt *FRS = dyn_cast<CXXForRangeStmt>(FL))
+ if (const auto *FRS = dyn_cast<CXXForRangeStmt>(FL))
return FRS->getInc() == S || FRS->getRangeStmt() == S ||
FRS->getLoopVarStmt() || FRS->getRangeInit() == S;
return false;
}
-typedef llvm::DenseSet<const PathDiagnosticCallPiece *>
- OptimizedCallsSet;
+using OptimizedCallsSet = llvm::DenseSet<const PathDiagnosticCallPiece *>;
/// Adds synthetic edges from top-level statements to their subexpressions.
///
@@ -2012,8 +2033,7 @@
PathPieces::iterator Prev = pieces.end();
for (PathPieces::iterator I = pieces.begin(), E = Prev; I != E;
Prev = I, ++I) {
- PathDiagnosticControlFlowPiece *Piece =
- dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
+ auto *Piece = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
if (!Piece)
continue;
@@ -2088,11 +2108,9 @@
/// the branch to the branch condition, and (3) an edge from the branch
/// condition to the branch target. We keep (1), but may wish to remove (2)
/// and move the source of (3) to the branch if the branch condition is simple.
-///
static void simplifySimpleBranches(PathPieces &pieces) {
for (PathPieces::iterator I = pieces.begin(), E = pieces.end(); I != E; ++I) {
-
- auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
+ const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
if (!PieceI)
continue;
@@ -2113,7 +2131,7 @@
if (NextI == E)
break;
- auto *EV = dyn_cast<PathDiagnosticEventPiece>(NextI->get());
+ const auto *EV = dyn_cast<PathDiagnosticEventPiece>(NextI->get());
if (EV) {
StringRef S = EV->getString();
if (S == StrEnteringLoop || S == StrLoopBodyZero ||
@@ -2215,8 +2233,7 @@
ParentMap &PM) {
for (PathPieces::iterator I = Path.begin(), E = Path.end(); I != E; ) {
// Pattern match the current piece and its successor.
- PathDiagnosticControlFlowPiece *PieceI =
- dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
+ const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
if (!PieceI) {
++I;
@@ -2230,7 +2247,7 @@
if (NextI == E)
break;
- PathDiagnosticControlFlowPiece *PieceNextI =
+ const auto *PieceNextI =
dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());
if (!PieceNextI) {
@@ -2268,9 +2285,7 @@
}
/// \brief Return true if X is contained by Y.
-static bool lexicalContains(ParentMap &PM,
- const Stmt *X,
- const Stmt *Y) {
+static bool lexicalContains(ParentMap &PM, const Stmt *X, const Stmt *Y) {
while (X) {
if (X == Y)
return true;
@@ -2280,18 +2295,15 @@
}
// Remove short edges on the same line less than 3 columns in difference.
-static void removePunyEdges(PathPieces &path,
- SourceManager &SM,
+static void removePunyEdges(PathPieces &path, SourceManager &SM,
ParentMap &PM) {
-
bool erased = false;
for (PathPieces::iterator I = path.begin(), E = path.end(); I != E;
erased ? I : ++I) {
-
erased = false;
- auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
+ const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
if (!PieceI)
continue;
@@ -2338,7 +2350,7 @@
static void removeIdenticalEvents(PathPieces &path) {
for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ++I) {
- auto *PieceI = dyn_cast<PathDiagnosticEventPiece>(I->get());
+ const auto *PieceI = dyn_cast<PathDiagnosticEventPiece>(I->get());
if (!PieceI)
continue;
@@ -2347,7 +2359,7 @@
if (NextI == E)
return;
- auto *PieceNextI = dyn_cast<PathDiagnosticEventPiece>(NextI->get());
+ const auto *PieceNextI = dyn_cast<PathDiagnosticEventPiece>(NextI->get());
if (!PieceNextI)
continue;
@@ -2397,7 +2409,7 @@
if (NextI == E)
break;
- auto *PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());
+ const auto *PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());
if (!PieceNextI) {
++I;
@@ -2423,7 +2435,6 @@
//
// NOTE: this will be limited later in cases where we add barriers
// to prevent this optimization.
- //
if (level1 && level1 == level2 && level1 == level3 && level1 == level4) {
PieceI->setEndLocation(PieceNextI->getEndLocation());
path.erase(NextI);
@@ -2438,7 +2449,6 @@
//
// NOTE: this will be limited later in cases where we add barriers
// to prevent this optimization.
- //
if (s1End && s1End == s2Start && level2) {
bool removeEdge = false;
// Remove edges into the increment or initialization of a
@@ -2504,8 +2514,7 @@
//
// (X -> element)
if (s1End == s2Start) {
- const ObjCForCollectionStmt *FS =
- dyn_cast_or_null<ObjCForCollectionStmt>(level3);
+ const auto *FS = dyn_cast_or_null<ObjCForCollectionStmt>(level3);
if (FS && FS->getCollection()->IgnoreParens() == s2Start &&
s2End == FS->getElement()) {
PieceI->setEndLocation(PieceNextI->getEndLocation());
@@ -2543,8 +2552,7 @@
/// statement had an invalid source location), this function does nothing.
// FIXME: We should just generate invalid edges anyway and have the optimizer
// deal with them.
-static void dropFunctionEntryEdge(PathPieces &Path,
- LocationContextMap &LCM,
+static void dropFunctionEntryEdge(PathPieces &Path, LocationContextMap &LCM,
SourceManager &SM) {
const auto *FirstEdge =
dyn_cast<PathDiagnosticControlFlowPiece>(Path.front().get());
@@ -2559,11 +2567,11 @@
Path.pop_front();
}
-
//===----------------------------------------------------------------------===//
// Methods for BugType and subclasses.
//===----------------------------------------------------------------------===//
-void BugType::anchor() { }
+
+void BugType::anchor() {}
void BugType::FlushReports(BugReporter &BR) {}
@@ -2638,7 +2646,7 @@
if (getInterestingSymbols().insert(sym).second)
++ConfigurationChangeToken;
- if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym))
+ if (const auto *meta = dyn_cast<SymbolMetadata>(sym))
getInterestingRegions().insert(meta->getRegion());
}
@@ -2651,7 +2659,7 @@
if (getInterestingRegions().insert(R).second)
++ConfigurationChangeToken;
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
+ if (const auto *SR = dyn_cast<SymbolicRegion>(R))
getInterestingSymbols().insert(SR->getSymbol());
}
@@ -2685,7 +2693,7 @@
bool b = getInterestingRegions().count(R);
if (b)
return true;
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
+ if (const auto *SR = dyn_cast<SymbolicRegion>(R))
return getInterestingSymbols().count(SR->getSymbol());
return false;
}
@@ -2745,7 +2753,7 @@
// If no custom ranges, add the range of the statement corresponding to
// the error node.
if (Ranges.empty()) {
- if (const Expr *E = dyn_cast_or_null<Expr>(getStmt()))
+ if (const auto *E = dyn_cast_or_null<Expr>(getStmt()))
addRange(E->getSourceRange());
else
return llvm::make_range(ranges_iterator(), ranges_iterator());
@@ -2773,9 +2781,11 @@
// Methods for BugReporter and subclasses.
//===----------------------------------------------------------------------===//
-BugReportEquivClass::~BugReportEquivClass() { }
-GRBugReporter::~GRBugReporter() { }
-BugReporterData::~BugReporterData() {}
+BugReportEquivClass::~BugReportEquivClass() = default;
+
+GRBugReporter::~GRBugReporter() = default;
+
+BugReporterData::~BugReporterData() = default;
ExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
@@ -2786,11 +2796,8 @@
FlushReports();
// Free the bug reports we are tracking.
- typedef std::vector<BugReportEquivClass *> ContTy;
- for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end();
- I != E; ++I) {
- delete *I;
- }
+ for (const auto I : EQClassesVector)
+ delete I;
}
void BugReporter::FlushReports() {
@@ -2802,18 +2809,13 @@
// FIXME: Only NSErrorChecker needs BugType's FlushReports.
// Turn NSErrorChecker into a proper checker and remove this.
SmallVector<const BugType *, 16> bugTypes(BugTypes.begin(), BugTypes.end());
- for (SmallVectorImpl<const BugType *>::iterator
- I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I)
- const_cast<BugType*>(*I)->FlushReports(*this);
+ for (const auto I : bugTypes)
+ const_cast<BugType*>(I)->FlushReports(*this);
// We need to flush reports in deterministic order to ensure the order
// of the reports is consistent between runs.
- typedef std::vector<BugReportEquivClass *> ContVecTy;
- for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end();
- EI != EE; ++EI){
- BugReportEquivClass& EQ = **EI;
- FlushReport(EQ);
- }
+ for (const auto EQ : EQClassesVector)
+ FlushReport(*EQ);
// BugReporter owns and deletes only BugTypes created implicitly through
// EmitBasicReport.
@@ -2830,6 +2832,7 @@
//===----------------------------------------------------------------------===//
namespace {
+
/// A wrapper around a report graph, which contains only a single path, and its
/// node maps.
class ReportGraph {
@@ -2844,10 +2847,12 @@
class TrimmedGraph {
InterExplodedGraphMap InverseMap;
- typedef llvm::DenseMap<const ExplodedNode *, unsigned> PriorityMapTy;
+ using PriorityMapTy = llvm::DenseMap<const ExplodedNode *, unsigned>;
+
PriorityMapTy PriorityMap;
- typedef std::pair<const ExplodedNode *, size_t> NodeIndexPair;
+ using NodeIndexPair = std::pair<const ExplodedNode *, size_t>;
+
SmallVector<NodeIndexPair, 32> ReportNodes;
std::unique_ptr<ExplodedGraph> G;
@@ -2885,7 +2890,8 @@
bool popNextReportGraph(ReportGraph &GraphWrapper);
};
-}
+
+} // namespace
TrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph,
ArrayRef<const ExplodedNode *> Nodes) {
@@ -2941,8 +2947,8 @@
}
// Sort the error paths from longest to shortest.
- std::sort(ReportNodes.begin(), ReportNodes.end(),
- PriorityCompare<true>(PriorityMap));
+ llvm::sort(ReportNodes.begin(), ReportNodes.end(),
+ PriorityCompare<true>(PriorityMap));
}
bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) {
@@ -2998,23 +3004,21 @@
return true;
}
-
/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
/// and collapses PathDiagosticPieces that are expanded by macros.
static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {
- typedef std::vector<
- std::pair<std::shared_ptr<PathDiagnosticMacroPiece>, SourceLocation>>
- MacroStackTy;
+ using MacroStackTy =
+ std::vector<
+ std::pair<std::shared_ptr<PathDiagnosticMacroPiece>, SourceLocation>>;
- typedef std::vector<std::shared_ptr<PathDiagnosticPiece>> PiecesTy;
+ using PiecesTy = std::vector<std::shared_ptr<PathDiagnosticPiece>>;
MacroStackTy MacroStack;
PiecesTy Pieces;
for (PathPieces::const_iterator I = path.begin(), E = path.end();
- I!=E; ++I) {
-
- auto &piece = *I;
+ I != E; ++I) {
+ const auto &piece = *I;
// Recursively compact calls.
if (auto *call = dyn_cast<PathDiagnosticCallPiece>(&*piece)) {
@@ -3101,11 +3105,10 @@
bool HasValid = false;
bool HasInvalid = false;
SmallVector<const ExplodedNode *, 32> errorNodes;
- for (ArrayRef<BugReport*>::iterator I = bugReports.begin(),
- E = bugReports.end(); I != E; ++I) {
- if ((*I)->isValid()) {
+ for (const auto I : bugReports) {
+ if (I->isValid()) {
HasValid = true;
- errorNodes.push_back((*I)->getErrorNode());
+ errorNodes.push_back(I->getErrorNode());
} else {
// Keep the errorNodes list in sync with the bugReports list.
HasInvalid = true;
@@ -3118,7 +3121,8 @@
if (!HasValid)
return false;
- typedef PathDiagnosticConsumer::PathGenerationScheme PathGenerationScheme;
+ using PathGenerationScheme = PathDiagnosticConsumer::PathGenerationScheme;
+
PathGenerationScheme ActiveScheme = PC.getGenerationScheme();
if (ActiveScheme == PathDiagnosticConsumer::Extensive) {
@@ -3173,8 +3177,8 @@
I != E; ++I) {
if (std::unique_ptr<PathDiagnosticPiece> Piece =
(*I)->getEndPath(PDB, N, *R)) {
- assert (!LastPiece &&
- "There can only be one final piece in a diagnostic.");
+ assert(!LastPiece &&
+ "There can only be one final piece in a diagnostic.");
LastPiece = std::move(Piece);
}
}
@@ -3305,20 +3309,21 @@
EQ->AddReport(std::move(R));
}
-
//===----------------------------------------------------------------------===//
// Emitting reports in equivalence classes.
//===----------------------------------------------------------------------===//
namespace {
+
struct FRIEC_WLItem {
const ExplodedNode *N;
ExplodedNode::const_succ_iterator I, E;
FRIEC_WLItem(const ExplodedNode *n)
- : N(n), I(N->succ_begin()), E(N->succ_end()) {}
+ : N(n), I(N->succ_begin()), E(N->succ_end()) {}
};
-}
+
+} // namespace
static const CFGBlock *findBlockForNode(const ExplodedNode *N) {
ProgramPoint P = N->getLocation();
@@ -3408,7 +3413,6 @@
static BugReport *
FindReportInEquivalenceClass(BugReportEquivClass& EQ,
SmallVectorImpl<BugReport*> &bugReports) {
-
BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end();
assert(I != E);
BugType& BT = I->getBugType();
@@ -3418,10 +3422,10 @@
// to 'Nodes'. Any of the reports will serve as a "representative" report.
if (!BT.isSuppressOnSink()) {
BugReport *R = &*I;
- for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) {
- const ExplodedNode *N = I->getErrorNode();
+ for (auto &I : EQ) {
+ const ExplodedNode *N = I.getErrorNode();
if (N) {
- R = &*I;
+ R = &I;
bugReports.push_back(R);
}
}
@@ -3462,8 +3466,9 @@
// At this point we know that 'N' is not a sink and it has at least one
// successor. Use a DFS worklist to find a non-sink end-of-path node.
- typedef FRIEC_WLItem WLItem;
- typedef SmallVector<WLItem, 10> DFSWorkList;
+ using WLItem = FRIEC_WLItem;
+ using DFSWorkList = SmallVector<WLItem, 10>;
+
llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
DFSWorkList WL;
@@ -3526,12 +3531,11 @@
static void populateExecutedLinesWithFunctionSignature(
const Decl *Signature, SourceManager &SM,
std::unique_ptr<FilesToLineNumsMap> &ExecutedLines) {
-
SourceRange SignatureSourceRange;
const Stmt* Body = Signature->getBody();
- if (auto FD = dyn_cast<FunctionDecl>(Signature)) {
+ if (const auto FD = dyn_cast<FunctionDecl>(Signature)) {
SignatureSourceRange = FD->getSourceRange();
- } else if (auto OD = dyn_cast<ObjCMethodDecl>(Signature)) {
+ } else if (const auto OD = dyn_cast<ObjCMethodDecl>(Signature)) {
SignatureSourceRange = OD->getSourceRange();
} else {
return;
@@ -3565,17 +3569,13 @@
while (N) {
if (N->getFirstPred() == nullptr) {
-
// First node: show signature of the entrance point.
const Decl *D = N->getLocationContext()->getDecl();
populateExecutedLinesWithFunctionSignature(D, SM, ExecutedLines);
-
} else if (auto CE = N->getLocationAs<CallEnter>()) {
-
// Inlined function: show signature.
const Decl* D = CE->getCalleeContext()->getDecl();
populateExecutedLinesWithFunctionSignature(D, SM, ExecutedLines);
-
} else if (const Stmt *S = PathDiagnosticLocation::getStmt(N)) {
populateExecutedLinesWithStmt(S, SM, ExecutedLines);
@@ -3585,7 +3585,7 @@
// The path exploration can die before the node with the associated
// return statement is generated, but we do want to show the whole
// return.
- if (auto *RS = dyn_cast_or_null<ReturnStmt>(P)) {
+ if (const auto *RS = dyn_cast_or_null<ReturnStmt>(P)) {
populateExecutedLinesWithStmt(RS, SM, ExecutedLines);
P = N->getParentMap().getParent(RS);
}
@@ -3602,7 +3602,6 @@
void BugReporter::FlushReport(BugReport *exampleReport,
PathDiagnosticConsumer &PD,
ArrayRef<BugReport*> bugReports) {
-
// FIXME: Make sure we use the 'R' for the path that was actually used.
// Probably doesn't make a difference in practice.
BugType& BT = exampleReport->getBugType();
@@ -3669,10 +3668,8 @@
// Get the meta data.
const BugReport::ExtraTextList &Meta = exampleReport->getExtraText();
- for (BugReport::ExtraTextList::const_iterator i = Meta.begin(),
- e = Meta.end(); i != e; ++i) {
- D->addMeta(*i);
- }
+ for (const auto &i : Meta)
+ D->addMeta(i);
PD.HandlePathDiagnostic(std::move(D));
}
@@ -3685,12 +3682,12 @@
EmitBasicReport(DeclWithIssue, Checker->getCheckName(), Name, Category, Str,
Loc, Ranges);
}
+
void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
CheckName CheckName,
StringRef name, StringRef category,
StringRef str, PathDiagnosticLocation Loc,
ArrayRef<SourceRange> Ranges) {
-
// 'BT' is owned by BugReporter.
BugType *BT = getBugTypeForName(CheckName, name, category);
auto R = llvm::make_unique<BugReport>(*BT, str, Loc);
@@ -3726,7 +3723,7 @@
if (const Stmt *SLoc = getLocStmt(getLocation()))
SLoc->dump();
- else if (const NamedDecl *ND = dyn_cast<NamedDecl>(getCallee()))
+ else if (const auto *ND = dyn_cast<NamedDecl>(getCallee()))
llvm::errs() << *ND << "\n";
else
getLocation().dump();
@@ -3780,7 +3777,7 @@
llvm::errs() << "<NULL STMT>\n";
break;
case DeclK:
- if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
+ if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
llvm::errs() << *ND << "\n";
else if (isa<BlockDecl>(D))
// FIXME: Make this nicer.
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index f5b4e7c..277ae28 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -1,4 +1,4 @@
-// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--//
+//===- BugReporterVisitors.cpp - Helpers for reporting bugs ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,37 +11,81 @@
// enhance the diagnostics reported for a bug.
//
//===----------------------------------------------------------------------===//
+
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <deque>
+#include <memory>
+#include <string>
+#include <utility>
using namespace clang;
using namespace ento;
-using llvm::FoldingSetNodeID;
-
//===----------------------------------------------------------------------===//
// Utility functions.
//===----------------------------------------------------------------------===//
bool bugreporter::isDeclRefExprToReference(const Expr *E) {
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
return DRE->getDecl()->getType()->isReferenceType();
- }
return false;
}
+static const Expr *peelOffPointerArithmetic(const BinaryOperator *B) {
+ if (B->isAdditiveOp() && B->getType()->isPointerType()) {
+ if (B->getLHS()->getType()->isPointerType()) {
+ return B->getLHS();
+ } else if (B->getRHS()->getType()->isPointerType()) {
+ return B->getRHS();
+ }
+ }
+ return nullptr;
+}
+
/// Given that expression S represents a pointer that would be dereferenced,
/// try to find a sub-expression from which the pointer came from.
/// This is used for tracking down origins of a null or undefined value:
@@ -55,33 +99,27 @@
/// x->y.z ==> x (lvalue)
/// foo()->y.z ==> foo() (rvalue)
const Expr *bugreporter::getDerefExpr(const Stmt *S) {
- const Expr *E = dyn_cast<Expr>(S);
+ const auto *E = dyn_cast<Expr>(S);
if (!E)
return nullptr;
while (true) {
- if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
+ if (const auto *CE = dyn_cast<CastExpr>(E)) {
if (CE->getCastKind() == CK_LValueToRValue) {
// This cast represents the load we're looking for.
break;
}
E = CE->getSubExpr();
- } else if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) {
+ } else if (const auto *B = dyn_cast<BinaryOperator>(E)) {
// Pointer arithmetic: '*(x + 2)' -> 'x') etc.
- if (B->getType()->isPointerType()) {
- if (B->getLHS()->getType()->isPointerType()) {
- E = B->getLHS();
- } else if (B->getRHS()->getType()->isPointerType()) {
- E = B->getRHS();
- } else {
- break;
- }
+ if (const Expr *Inner = peelOffPointerArithmetic(B)) {
+ E = Inner;
} else {
// Probably more arithmetic can be pattern-matched here,
// but for now give up.
break;
}
- } else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) {
+ } else if (const auto *U = dyn_cast<UnaryOperator>(E)) {
if (U->getOpcode() == UO_Deref || U->getOpcode() == UO_AddrOf ||
(U->isIncrementDecrementOp() && U->getType()->isPointerType())) {
// Operators '*' and '&' don't actually mean anything.
@@ -94,13 +132,13 @@
}
}
// Pattern match for a few useful cases: a[0], p->f, *p etc.
- else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ else if (const auto *ME = dyn_cast<MemberExpr>(E)) {
E = ME->getBase();
- } else if (const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
+ } else if (const auto *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
E = IvarRef->getBase();
- } else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(E)) {
+ } else if (const auto *AE = dyn_cast<ArraySubscriptExpr>(E)) {
E = AE->getBase();
- } else if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
+ } else if (const auto *PE = dyn_cast<ParenExpr>(E)) {
E = PE->getSubExpr();
} else {
// Other arbitrary stuff.
@@ -111,7 +149,7 @@
// Special case: remove the final lvalue-to-rvalue cast, but do not recurse
// deeper into the sub-expression. This way we return the lvalue from which
// our pointer rvalue was loaded.
- if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))
+ if (const auto *CE = dyn_cast<ImplicitCastExpr>(E))
if (CE->getCastKind() == CK_LValueToRValue)
E = CE->getSubExpr();
@@ -120,14 +158,14 @@
const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
- if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
+ if (const auto *BE = dyn_cast<BinaryOperator>(S))
return BE->getRHS();
return nullptr;
}
const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
- if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
+ if (const auto *RS = dyn_cast<ReturnStmt>(S))
return RS->getRetValue();
return nullptr;
}
@@ -190,11 +228,9 @@
/// pointer dereference outside.
class NoStoreFuncVisitor final
: public BugReporterVisitorImpl<NoStoreFuncVisitor> {
-
const SubRegion *RegionOfInterest;
static constexpr const char *DiagnosticsMsg =
"Returning without writing to '";
- bool Initialized = false;
/// Frames writing into \c RegionOfInterest.
/// This visitor generates a note only if a function does not write into
@@ -202,10 +238,10 @@
/// by looking at the node associated with the exit from the function
/// (usually the return statement). To avoid recomputing the same information
/// many times (going up the path for each node and checking whether the
- /// region was written into) we instead pre-compute and store all
- /// stack frames along the path which write into the region of interest
- /// on the first \c VisitNode invocation.
+ /// region was written into) we instead lazily compute the
+ /// stack frames along the path which write into the region of interest.
llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingRegion;
+ llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated;
public:
NoStoreFuncVisitor(const SubRegion *R) : RegionOfInterest(R) {}
@@ -219,10 +255,6 @@
const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override {
- if (!Initialized) {
- findModifyingFrames(N);
- Initialized = true;
- }
const LocationContext *Ctx = N->getLocationContext();
const StackFrameContext *SCtx = Ctx->getCurrentStackFrame();
@@ -230,7 +262,7 @@
auto CallExitLoc = N->getLocationAs<CallExitBegin>();
// No diagnostic if region was modified inside the frame.
- if (!CallExitLoc || FramesModifyingRegion.count(SCtx))
+ if (!CallExitLoc)
return nullptr;
CallEventRef<> Call =
@@ -238,10 +270,11 @@
const PrintingPolicy &PP = BRC.getASTContext().getPrintingPolicy();
const SourceManager &SM = BRC.getSourceManager();
- if (auto *CCall = dyn_cast<CXXConstructorCall>(Call)) {
+ if (const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) {
const MemRegion *ThisRegion = CCall->getCXXThisVal().getAsRegion();
- if (RegionOfInterest->isSubRegionOf(ThisRegion) &&
- !CCall->getDecl()->isImplicit())
+ if (RegionOfInterest->isSubRegionOf(ThisRegion)
+ && !CCall->getDecl()->isImplicit()
+ && !isRegionOfInterestModifiedInFrame(N))
return notModifiedInConstructorDiagnostics(Ctx, SM, PP, *CallExitLoc,
CCall, ThisRegion);
}
@@ -253,10 +286,15 @@
unsigned IndirectionLevel = 1;
QualType T = PVD->getType();
while (const MemRegion *R = S.getAsRegion()) {
- if (RegionOfInterest->isSubRegionOf(R) &&
- !isPointerToConst(PVD->getType()))
+ if (RegionOfInterest->isSubRegionOf(R)
+ && !isPointerToConst(PVD->getType())) {
+
+ if (isRegionOfInterestModifiedInFrame(N))
+ return nullptr;
+
return notModifiedDiagnostics(
Ctx, SM, PP, *CallExitLoc, Call, PVD, R, IndirectionLevel);
+ }
QualType PT = T->getPointeeType();
if (PT.isNull() || PT->isVoidType()) break;
S = State->getSVal(R, PT);
@@ -269,18 +307,39 @@
}
private:
+ /// Check and lazily calculate whether the region of interest is
+ /// modified in the stack frame to which \p N belongs.
+ /// The calculation is cached in FramesModifyingRegion.
+ bool isRegionOfInterestModifiedInFrame(const ExplodedNode *N) {
+ const LocationContext *Ctx = N->getLocationContext();
+ const StackFrameContext *SCtx = Ctx->getCurrentStackFrame();
+ if (!FramesModifyingCalculated.count(SCtx))
+ findModifyingFrames(N);
+ return FramesModifyingRegion.count(SCtx);
+ }
+
+
/// Write to \c FramesModifyingRegion all stack frames along
- /// the path which modify \c RegionOfInterest.
+ /// the path in the current stack frame which modify \c RegionOfInterest.
void findModifyingFrames(const ExplodedNode *N) {
- ProgramStateRef LastReturnState;
+ assert(N->getLocationAs<CallExitBegin>());
+ ProgramStateRef LastReturnState = N->getState();
+ SVal ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
+ const LocationContext *Ctx = N->getLocationContext();
+ const StackFrameContext *OriginalSCtx = Ctx->getCurrentStackFrame();
+
do {
ProgramStateRef State = N->getState();
auto CallExitLoc = N->getLocationAs<CallExitBegin>();
if (CallExitLoc) {
LastReturnState = State;
+ ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
}
- if (LastReturnState &&
- wasRegionOfInterestModifiedAt(N, LastReturnState)) {
+
+ FramesModifyingCalculated.insert(
+ N->getLocationContext()->getCurrentStackFrame());
+
+ if (wasRegionOfInterestModifiedAt(N, LastReturnState, ValueAtReturn)) {
const StackFrameContext *SCtx =
N->getLocationContext()->getCurrentStackFrame();
while (!SCtx->inTopFrame()) {
@@ -291,6 +350,11 @@
}
}
+ // Stop calculation at the call to the current function.
+ if (auto CE = N->getLocationAs<CallEnter>())
+ if (CE->getCalleeContext() == OriginalSCtx)
+ break;
+
N = N->getFirstPred();
} while (N);
}
@@ -299,8 +363,12 @@
/// where \p ReturnState is a state associated with the return
/// from the current frame.
bool wasRegionOfInterestModifiedAt(const ExplodedNode *N,
- ProgramStateRef ReturnState) {
- SVal ValueAtReturn = ReturnState->getSVal(RegionOfInterest);
+ ProgramStateRef ReturnState,
+ SVal ValueAtReturn) {
+ if (!N->getLocationAs<PostStore>()
+ && !N->getLocationAs<PostInitializer>()
+ && !N->getLocationAs<PostStmt>())
+ return false;
// Writing into region of interest.
if (auto PS = N->getLocationAs<PostStmt>())
@@ -323,7 +391,7 @@
ArrayRef<ParmVarDecl *> getCallParameters(CallEventRef<> Call) {
// Use runtime definition, if available.
RuntimeDefinition RD = Call->getRuntimeDefinition();
- if (auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl()))
+ if (const auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl()))
return FD->parameters();
return Call->parameters();
@@ -342,7 +410,6 @@
CallExitBegin &CallExitLoc,
const CXXConstructorCall *Call,
const MemRegion *ArgRegion) {
-
SmallString<256> sbuf;
llvm::raw_svector_ostream os(sbuf);
os << DiagnosticsMsg;
@@ -371,7 +438,6 @@
const ParmVarDecl *PVD,
const MemRegion *ArgRegion,
unsigned IndirectionLevel) {
-
PathDiagnosticLocation L = getPathDiagnosticLocation(
CallExitLoc.getReturnStmt(), SM, Ctx, Call);
SmallString<256> sbuf;
@@ -431,14 +497,14 @@
if (ShouldSurround)
os << "(";
- for (int i=0; i<IndirectionLevel; i++)
+ for (int i = 0; i < IndirectionLevel; i++)
os << "*";
os << TopRegionName;
if (ShouldSurround)
os << ")";
for (auto I = Subregions.rbegin(), E = Subregions.rend(); I != E; ++I) {
- if (auto *FR = dyn_cast<FieldRegion>(*I)) {
+ if (const auto *FR = dyn_cast<FieldRegion>(*I)) {
os << Sep;
FR->getDecl()->getDeclName().print(os, PP);
Sep = ".";
@@ -452,13 +518,8 @@
}
};
-} // namespace
-
-namespace {
-
class MacroNullReturnSuppressionVisitor final
: public BugReporterVisitorImpl<MacroNullReturnSuppressionVisitor> {
-
const SubRegion *RegionOfInterest;
public:
@@ -516,13 +577,13 @@
if (!S)
return None;
- if (auto *DS = dyn_cast<DeclStmt>(S)) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
+ if (const auto *DS = dyn_cast<DeclStmt>(S)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
if (const Expr *RHS = VD->getInit())
if (RegionOfInterest->isSubRegionOf(
State->getLValue(VD, LCtx).getAsRegion()))
return RHS->getLocStart();
- } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
+ } else if (const auto *BO = dyn_cast<BinaryOperator>(S)) {
const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion();
const Expr *RHS = BO->getRHS();
if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(R)) {
@@ -546,13 +607,13 @@
Initial,
MaybeUnsuppress,
Satisfied
- } Mode;
+ } Mode = Initial;
bool EnableNullFPSuppression;
public:
ReturnVisitor(const StackFrameContext *Frame, bool Suppressed)
- : StackFrame(Frame), Mode(Initial), EnableNullFPSuppression(Suppressed) {}
+ : StackFrame(Frame), EnableNullFPSuppression(Suppressed) {}
static void *getTag() {
static int Tag = 0;
@@ -646,7 +707,7 @@
if (!SP)
return nullptr;
- const ReturnStmt *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
+ const auto *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
if (!Ret)
return nullptr;
@@ -724,8 +785,8 @@
}
} else {
// FIXME: We should have a more generalized location printing mechanism.
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetE))
- if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
+ if (const auto *DR = dyn_cast<DeclRefExpr>(RetE))
+ if (const auto *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
Out << " (loaded from '" << *DD << "')";
}
@@ -812,10 +873,10 @@
return nullptr;
}
};
-} // end anonymous namespace
+} // namespace
-void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const {
+void FindLastStoreBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
static int tag = 0;
ID.AddPointer(&tag);
ID.AddPointer(R);
@@ -838,7 +899,7 @@
return false;
const MemSpaceRegion *VarSpace = VR->getMemorySpace();
- const StackSpaceRegion *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
+ const auto *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
if (!FrameSpace) {
// If we ever directly evaluate global DeclStmts, this assertion will be
// invalid, but this still seems preferable to silently accepting an
@@ -866,7 +927,7 @@
if (V.getAs<loc::ConcreteInt>()) {
bool b = false;
if (R->isBoundable()) {
- if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
+ if (const auto *TR = dyn_cast<TypedValueRegion>(R)) {
if (TR->getValueType()->isObjCObjectPointerType()) {
os << action << "nil";
b = true;
@@ -881,7 +942,7 @@
} else if (DS) {
if (V.isUndef()) {
if (isa<VarRegion>(R)) {
- const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
+ const auto *VD = cast<VarDecl>(DS->getSingleDecl());
if (VD->getInit()) {
os << (R->canPrintPretty() ? "initialized" : "Initializing")
<< " to a garbage value";
@@ -934,7 +995,7 @@
if (V.getAs<loc::ConcreteInt>()) {
bool b = false;
if (R->isBoundable()) {
- if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
+ if (const auto *TR = dyn_cast<TypedValueRegion>(R)) {
if (TR->getValueType()->isObjCObjectPointerType()) {
os << "nil object reference stored";
b = true;
@@ -977,7 +1038,6 @@
FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
const ExplodedNode *Pred,
BugReporterContext &BRC, BugReport &BR) {
-
if (Satisfied)
return nullptr;
@@ -986,7 +1046,7 @@
bool IsParam = false;
// First see if we reached the declaration of the region.
- if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+ if (const auto *VR = dyn_cast<VarRegion>(R)) {
if (isInitializationOfVar(Pred, VR)) {
StoreSite = Pred;
InitE = VR->getDecl()->getInit();
@@ -1032,8 +1092,8 @@
// 'this' should never be NULL, but this visitor isn't just for NULL and
// UndefinedVal.)
if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) {
- if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
- const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl());
+ if (const auto *VR = dyn_cast<VarRegion>(R)) {
+ const auto *Param = cast<ParmVarDecl>(VR->getDecl());
ProgramStateManager &StateMgr = BRC.getStateManager();
CallEventManager &CallMgr = StateMgr.getCallEventManager();
@@ -1047,7 +1107,7 @@
// If this is a CXXTempObjectRegion, the Expr responsible for its creation
// is wrapped inside of it.
- if (const CXXTempObjectRegion *TmpR = dyn_cast<CXXTempObjectRegion>(R))
+ if (const auto *TmpR = dyn_cast<CXXTempObjectRegion>(R))
InitE = TmpR->getExpr();
}
@@ -1077,8 +1137,8 @@
if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) {
const Stmt *S = PS->getStmt();
const char *action = nullptr;
- const DeclStmt *DS = dyn_cast<DeclStmt>(S);
- const VarRegion *VR = dyn_cast<VarRegion>(R);
+ const auto *DS = dyn_cast<DeclStmt>(S);
+ const auto *VR = dyn_cast<VarRegion>(R);
if (DS) {
action = R->canPrintPretty() ? "initialized to " :
@@ -1090,7 +1150,7 @@
// See if we can get the BlockVarRegion.
ProgramStateRef State = StoreSite->getState();
SVal V = StoreSite->getSVal(S);
- if (const BlockDataRegion *BDR =
+ if (const auto *BDR =
dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
if (Optional<KnownSVal> KV =
@@ -1105,7 +1165,7 @@
showBRDiagnostics(action, os, R, V, DS);
} else if (StoreSite->getLocation().getAs<CallEnter>()) {
- if (const VarRegion *VR = dyn_cast<VarRegion>(R))
+ if (const auto *VR = dyn_cast<VarRegion>(R))
showBRParamDiagnostics(os, VR, V);
}
@@ -1165,7 +1225,6 @@
// Check if in the previous state it was feasible for this constraint
// to *not* be true.
if (isUnderconstrained(PrevN)) {
-
IsSatisfied = true;
// As a sanity check, make sure that the negation of the constraint
@@ -1203,20 +1262,20 @@
SuppressInlineDefensiveChecksVisitor::
SuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N)
- : V(Value), IsSatisfied(false), IsTrackingTurnedOn(false) {
+ : V(Value) {
+ // Check if the visitor is disabled.
+ SubEngine *Eng = N->getState()->getStateManager().getOwningEngine();
+ assert(Eng && "Cannot file a bug report without an owning engine");
+ AnalyzerOptions &Options = Eng->getAnalysisManager().options;
+ if (!Options.shouldSuppressInlinedDefensiveChecks())
+ IsSatisfied = true;
- // Check if the visitor is disabled.
- SubEngine *Eng = N->getState()->getStateManager().getOwningEngine();
- assert(Eng && "Cannot file a bug report without an owning engine");
- AnalyzerOptions &Options = Eng->getAnalysisManager().options;
- if (!Options.shouldSuppressInlinedDefensiveChecks())
- IsSatisfied = true;
-
- assert(N->getState()->isNull(V).isConstrainedTrue() &&
- "The visitor only tracks the cases where V is constrained to 0");
+ assert(N->getState()->isNull(V).isConstrainedTrue() &&
+ "The visitor only tracks the cases where V is constrained to 0");
}
-void SuppressInlineDefensiveChecksVisitor::Profile(FoldingSetNodeID &ID) const {
+void SuppressInlineDefensiveChecksVisitor::Profile(
+ llvm::FoldingSetNodeID &ID) const {
static int id = 0;
ID.AddPointer(&id);
ID.Add(V);
@@ -1265,7 +1324,6 @@
if (!BugPoint)
return nullptr;
-
ProgramPoint CurPoint = Succ->getLocation();
const Stmt *CurTerminatorStmt = nullptr;
if (auto BE = CurPoint.getAs<BlockEdge>()) {
@@ -1301,8 +1359,8 @@
static const MemRegion *getLocationRegionIfReference(const Expr *E,
const ExplodedNode *N) {
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ if (const auto *DR = dyn_cast<DeclRefExpr>(E)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
if (!VD->getType()->isReferenceType())
return nullptr;
ProgramStateManager &StateMgr = N->getState()->getStateManager();
@@ -1323,12 +1381,12 @@
static const Expr *peelOffOuterExpr(const Expr *Ex,
const ExplodedNode *N) {
Ex = Ex->IgnoreParenCasts();
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex))
+ if (const auto *EWC = dyn_cast<ExprWithCleanups>(Ex))
return peelOffOuterExpr(EWC->getSubExpr(), N);
- if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex))
+ if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
return peelOffOuterExpr(OVE->getSourceExpr(), N);
- if (auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
- auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
+ if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
+ const auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
if (PropRef && PropRef->isMessagingGetter()) {
const Expr *GetterMessageSend =
POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
@@ -1338,7 +1396,7 @@
}
// Peel off the ternary operator.
- if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) {
+ if (const auto *CO = dyn_cast<ConditionalOperator>(Ex)) {
// Find a node where the branching occurred and find out which branch
// we took (true/false) by looking at the ExplodedGraph.
const ExplodedNode *NI = N;
@@ -1359,6 +1417,11 @@
NI = NI->getFirstPred();
} while (NI);
}
+
+ if (auto *BO = dyn_cast<BinaryOperator>(Ex))
+ if (const Expr *SubEx = peelOffPointerArithmetic(BO))
+ return peelOffOuterExpr(SubEx, N);
+
return Ex;
}
@@ -1396,7 +1459,6 @@
}
assert(N && "Unable to find the lvalue node.");
return N;
-
}
/// Performing operator `&' on an lvalue expression is essentially a no-op.
@@ -1418,7 +1480,6 @@
if (const Expr *DerefEx = bugreporter::getDerefExpr(Op->getSubExpr()))
return DerefEx;
return Ex;
-
}
bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
@@ -1562,7 +1623,7 @@
const Expr *NilReceiverBRVisitor::getNilReceiver(const Stmt *S,
const ExplodedNode *N) {
- const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S);
+ const auto *ME = dyn_cast<ObjCMessageExpr>(S);
if (!ME)
return nullptr;
if (const Expr *Receiver = ME->getInstanceReceiver()) {
@@ -1590,7 +1651,7 @@
llvm::SmallString<256> Buf;
llvm::raw_svector_ostream OS(Buf);
- if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
+ if (const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
OS << "'";
ME->getSelector().print(OS);
OS << "' not called";
@@ -1625,8 +1686,8 @@
ProgramStateManager &StateMgr = N->getState()->getStateManager();
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ if (const auto *DR = dyn_cast<DeclRefExpr>(Head)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
const VarRegion *R =
StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
@@ -1672,7 +1733,6 @@
ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
const ExplodedNode *Prev,
BugReporterContext &BRC, BugReport &BR) {
-
ProgramPoint progPoint = N->getLocation();
ProgramStateRef CurrentState = N->getState();
ProgramStateRef PrevState = Prev->getState();
@@ -1794,7 +1854,7 @@
return P;
break;
case Stmt::UnaryOperatorClass: {
- const UnaryOperator *UO = cast<UnaryOperator>(CondTmp);
+ const auto *UO = cast<UnaryOperator>(CondTmp);
if (UO->getOpcode() == UO_LNot) {
tookTrueTmp = !tookTrueTmp;
CondTmp = UO->getSubExpr();
@@ -1837,7 +1897,6 @@
isa<CXXBoolLiteralExpr>(Ex) ||
isa<IntegerLiteral>(Ex) ||
isa<FloatingLiteral>(Ex))) {
-
StringRef StartName = Lexer::getImmediateMacroNameForDiagnostics(LocStart,
BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
StringRef EndName = Lexer::getImmediateMacroNameForDiagnostics(LocEnd,
@@ -1868,7 +1927,7 @@
}
}
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
+ if (const auto *DR = dyn_cast<DeclRefExpr>(Ex)) {
const bool quotes = isa<VarDecl>(DR->getDecl());
if (quotes) {
Out << '\'';
@@ -1892,7 +1951,7 @@
return quotes;
}
- if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
+ if (const auto *IL = dyn_cast<IntegerLiteral>(Ex)) {
QualType OriginalTy = OriginalExpr->getType();
if (OriginalTy->isPointerType()) {
if (IL->getValue() == 0) {
@@ -1918,7 +1977,6 @@
ConditionBRVisitor::VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr,
const bool tookTrue, BugReporterContext &BRC,
BugReport &R, const ExplodedNode *N) {
-
bool shouldInvert = false;
Optional<bool> shouldPrune;
@@ -2023,8 +2081,8 @@
PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ if (const auto *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
const ProgramState *state = N->getState().get();
if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
if (report.isInteresting(R))
@@ -2040,8 +2098,7 @@
ConditionBRVisitor::VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR,
const bool tookTrue, BugReporterContext &BRC,
BugReport &report, const ExplodedNode *N) {
-
- const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ const auto *VD = dyn_cast<VarDecl>(DR->getDecl());
if (!VD)
return nullptr;
@@ -2107,7 +2164,6 @@
if (Options.shouldSuppressFromCXXStandardLibrary()) {
BR.markInvalid(getTag(), nullptr);
return nullptr;
-
} else {
// If the complete 'std' suppression is not enabled, suppress reports
// from the 'std' namespace that are known to produce false positives.
@@ -2115,7 +2171,7 @@
// The analyzer issues a false use-after-free when std::list::pop_front
// or std::list::pop_back are called multiple times because we cannot
// reason about the internal invariants of the data structure.
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
const CXXRecordDecl *CD = MD->getParent();
if (CD->getName() == "list") {
BR.markInvalid(getTag(), nullptr);
@@ -2125,7 +2181,7 @@
// The analyzer issues a false positive when the constructor of
// std::__independent_bits_engine from algorithms is used.
- if (const CXXConstructorDecl *MD = dyn_cast<CXXConstructorDecl>(D)) {
+ if (const auto *MD = dyn_cast<CXXConstructorDecl>(D)) {
const CXXRecordDecl *CD = MD->getParent();
if (CD->getName() == "__independent_bits_engine") {
BR.markInvalid(getTag(), nullptr);
@@ -2135,7 +2191,7 @@
for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
LCtx = LCtx->getParent()) {
- const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
+ const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
if (!MD)
continue;
@@ -2181,7 +2237,6 @@
UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N,
const ExplodedNode *PrevN,
BugReporterContext &BRC, BugReport &BR) {
-
ProgramStateRef State = N->getState();
ProgramPoint ProgLoc = N->getLocation();
@@ -2194,18 +2249,17 @@
CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State);
unsigned Idx = 0;
- ArrayRef<ParmVarDecl*> parms = Call->parameters();
+ ArrayRef<ParmVarDecl *> parms = Call->parameters();
- for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
- I != E; ++I, ++Idx) {
+ for (const auto ParamDecl : parms) {
const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
+ ++Idx;
// Are we tracking the argument or its subregion?
if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts()))
continue;
// Check the function parameter type.
- const ParmVarDecl *ParamDecl = *I;
assert(ParamDecl && "Formal parameter has no decl?");
QualType T = ParamDecl->getType();
@@ -2237,7 +2291,7 @@
if (Satisfied)
return nullptr;
- auto Edge = Succ->getLocation().getAs<BlockEdge>();
+ const auto Edge = Succ->getLocation().getAs<BlockEdge>();
if (!Edge.hasValue())
return nullptr;
diff --git a/lib/StaticAnalyzer/Core/CMakeLists.txt b/lib/StaticAnalyzer/Core/CMakeLists.txt
index 436a8a2..49afefe 100644
--- a/lib/StaticAnalyzer/Core/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -51,6 +51,7 @@
Store.cpp
SubEngine.cpp
SymbolManager.cpp
+ WorkList.cpp
Z3ConstraintManager.cpp
LINK_LIBS
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp
index 3ff02f1..dab5335 100644
--- a/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -67,11 +67,13 @@
using namespace ento;
QualType CallEvent::getResultType() const {
- const Expr *E = getOriginExpr();
- assert(E && "Calls without origin expressions do not have results");
- QualType ResultTy = E->getType();
-
ASTContext &Ctx = getState()->getStateManager().getContext();
+ const Expr *E = getOriginExpr();
+ if (!E)
+ return Ctx.VoidTy;
+ assert(E);
+
+ QualType ResultTy = E->getType();
// A function that returns a reference to 'int' will have a result type
// of simply 'int'. Check the origin expr's value kind to recover the
diff --git a/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
index ed41914..b9facff 100644
--- a/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -15,8 +15,12 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
+namespace clang {
+
+namespace ento {
+
// Recursively find any substatements containing macros
-bool clang::ento::containsMacro(const Stmt *S) {
+bool containsMacro(const Stmt *S) {
if (S->getLocStart().isMacroID())
return true;
@@ -31,7 +35,7 @@
}
// Recursively find any substatements containing enum constants
-bool clang::ento::containsEnum(const Stmt *S) {
+bool containsEnum(const Stmt *S) {
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
if (DR && isa<EnumConstantDecl>(DR->getDecl()))
@@ -45,7 +49,7 @@
}
// Recursively find any substatements containing static vars
-bool clang::ento::containsStaticLocal(const Stmt *S) {
+bool containsStaticLocal(const Stmt *S) {
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
if (DR)
@@ -61,7 +65,7 @@
}
// Recursively find any substatements containing __builtin_offsetof
-bool clang::ento::containsBuiltinOffsetOf(const Stmt *S) {
+bool containsBuiltinOffsetOf(const Stmt *S) {
if (isa<OffsetOfExpr>(S))
return true;
@@ -74,7 +78,7 @@
// Extract lhs and rhs from assignment statement
std::pair<const clang::VarDecl *, const clang::Expr *>
-clang::ento::parseAssignment(const Stmt *S) {
+parseAssignment(const Stmt *S) {
const VarDecl *VD = nullptr;
const Expr *RHS = nullptr;
@@ -94,3 +98,18 @@
return std::make_pair(VD, RHS);
}
+
+Nullability getNullabilityAnnotation(QualType Type) {
+ const auto *AttrType = Type->getAs<AttributedType>();
+ if (!AttrType)
+ return Nullability::Unspecified;
+ if (AttrType->getAttrKind() == AttributedType::attr_nullable)
+ return Nullability::Nullable;
+ else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)
+ return Nullability::Nonnull;
+ return Nullability::Unspecified;
+}
+
+
+} // end namespace ento
+} // end namespace clang
diff --git a/lib/StaticAnalyzer/Core/CheckerRegistry.cpp b/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
index c9cb189..6437f9c 100644
--- a/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
@@ -97,7 +97,7 @@
void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
SmallVectorImpl<CheckerOptInfo> &opts) const {
// Sort checkers for efficient collection.
- std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
+ llvm::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
// Collect checkers enabled by the options.
CheckerInfoSet enabledCheckers;
@@ -141,7 +141,7 @@
// FIXME: Alphabetical sort puts 'experimental' in the middle.
// Would it be better to name it '~experimental' or something else
// that's ASCIIbetically last?
- std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
+ llvm::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
// FIXME: Print available packages.
@@ -178,7 +178,7 @@
void CheckerRegistry::printList(
raw_ostream &out, SmallVectorImpl<CheckerOptInfo> &opts) const {
- std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
+ llvm::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
// Collect checkers enabled by the options.
CheckerInfoSet enabledCheckers;
diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 592f0ba..416b8e6 100644
--- a/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -27,21 +27,15 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/PriorityQueue.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <cassert>
-#include <deque>
#include <memory>
#include <utility>
-#include <vector>
using namespace clang;
using namespace ento;
@@ -55,230 +49,6 @@
STATISTIC(NumPathsExplored,
"The # of paths explored by the analyzer.");
-STATISTIC(MaxQueueSize, "Maximum size of the worklist");
-STATISTIC(MaxReachableSize, "Maximum size of auxiliary worklist set");
-
-//===----------------------------------------------------------------------===//
-// Worklist classes for exploration of reachable states.
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class DFS : public WorkList {
- SmallVector<WorkListUnit, 20> Stack;
-
-public:
- bool hasWork() const override {
- return !Stack.empty();
- }
-
- void enqueue(const WorkListUnit& U) override {
- Stack.push_back(U);
- }
-
- WorkListUnit dequeue() override {
- assert(!Stack.empty());
- const WorkListUnit& U = Stack.back();
- Stack.pop_back(); // This technically "invalidates" U, but we are fine.
- return U;
- }
-};
-
-class BFS : public WorkList {
- std::deque<WorkListUnit> Queue;
-
-public:
- bool hasWork() const override {
- return !Queue.empty();
- }
-
- void enqueue(const WorkListUnit& U) override {
- Queue.push_back(U);
- }
-
- WorkListUnit dequeue() override {
- WorkListUnit U = Queue.front();
- Queue.pop_front();
- return U;
- }
-};
-
-} // namespace
-
-// Place the dstor for WorkList here because it contains virtual member
-// functions, and we the code for the dstor generated in one compilation unit.
-WorkList::~WorkList() = default;
-
-std::unique_ptr<WorkList> WorkList::makeDFS() {
- return llvm::make_unique<DFS>();
-}
-
-std::unique_ptr<WorkList> WorkList::makeBFS() {
- return llvm::make_unique<BFS>();
-}
-
-namespace {
-
- class BFSBlockDFSContents : public WorkList {
- std::deque<WorkListUnit> Queue;
- SmallVector<WorkListUnit, 20> Stack;
-
- public:
- bool hasWork() const override {
- return !Queue.empty() || !Stack.empty();
- }
-
- void enqueue(const WorkListUnit& U) override {
- if (U.getNode()->getLocation().getAs<BlockEntrance>())
- Queue.push_front(U);
- else
- Stack.push_back(U);
- }
-
- WorkListUnit dequeue() override {
- // Process all basic blocks to completion.
- if (!Stack.empty()) {
- const WorkListUnit& U = Stack.back();
- Stack.pop_back(); // This technically "invalidates" U, but we are fine.
- return U;
- }
-
- assert(!Queue.empty());
- // Don't use const reference. The subsequent pop_back() might make it
- // unsafe.
- WorkListUnit U = Queue.front();
- Queue.pop_front();
- return U;
- }
- };
-
-} // namespace
-
-std::unique_ptr<WorkList> WorkList::makeBFSBlockDFSContents() {
- return llvm::make_unique<BFSBlockDFSContents>();
-}
-
-namespace {
-
-class UnexploredFirstStack : public WorkList {
- /// Stack of nodes known to have statements we have not traversed yet.
- SmallVector<WorkListUnit, 20> StackUnexplored;
-
- /// Stack of all other nodes.
- SmallVector<WorkListUnit, 20> StackOthers;
-
- using BlockID = unsigned;
- using LocIdentifier = std::pair<BlockID, const StackFrameContext *>;
-
- llvm::DenseSet<LocIdentifier> Reachable;
-
-public:
- bool hasWork() const override {
- return !(StackUnexplored.empty() && StackOthers.empty());
- }
-
- void enqueue(const WorkListUnit &U) override {
- const ExplodedNode *N = U.getNode();
- auto BE = N->getLocation().getAs<BlockEntrance>();
-
- if (!BE) {
- // Assume the choice of the order of the preceeding block entrance was
- // correct.
- StackUnexplored.push_back(U);
- } else {
- LocIdentifier LocId = std::make_pair(
- BE->getBlock()->getBlockID(), N->getStackFrame());
- auto InsertInfo = Reachable.insert(LocId);
-
- if (InsertInfo.second) {
- StackUnexplored.push_back(U);
- } else {
- StackOthers.push_back(U);
- }
- }
- MaxReachableSize.updateMax(Reachable.size());
- MaxQueueSize.updateMax(StackUnexplored.size() + StackOthers.size());
- }
-
- WorkListUnit dequeue() override {
- if (!StackUnexplored.empty()) {
- WorkListUnit &U = StackUnexplored.back();
- StackUnexplored.pop_back();
- return U;
- } else {
- WorkListUnit &U = StackOthers.back();
- StackOthers.pop_back();
- return U;
- }
- }
-};
-
-} // namespace
-
-std::unique_ptr<WorkList> WorkList::makeUnexploredFirst() {
- return llvm::make_unique<UnexploredFirstStack>();
-}
-
-class UnexploredFirstPriorityQueue : public WorkList {
- using BlockID = unsigned;
- using LocIdentifier = std::pair<BlockID, const StackFrameContext *>;
-
- // How many times each location was visited.
- // Is signed because we negate it later in order to have a reversed
- // comparison.
- using VisitedTimesMap = llvm::DenseMap<LocIdentifier, int>;
-
- // Compare by number of times the location was visited first (negated
- // to prefer less often visited locations), then by insertion time (prefer
- // expanding nodes inserted sooner first).
- using QueuePriority = std::pair<int, unsigned long>;
- using QueueItem = std::pair<WorkListUnit, QueuePriority>;
-
- struct ExplorationComparator {
- bool operator() (const QueueItem &LHS, const QueueItem &RHS) {
- return LHS.second < RHS.second;
- }
- };
-
- // Number of inserted nodes, used to emulate DFS ordering in the priority
- // queue when insertions are equal.
- unsigned long Counter = 0;
-
- // Number of times a current location was reached.
- VisitedTimesMap NumReached;
-
- // The top item is the largest one.
- llvm::PriorityQueue<QueueItem, std::vector<QueueItem>, ExplorationComparator>
- queue;
-
-public:
- bool hasWork() const override {
- return !queue.empty();
- }
-
- void enqueue(const WorkListUnit &U) override {
- const ExplodedNode *N = U.getNode();
- unsigned NumVisited = 0;
- if (auto BE = N->getLocation().getAs<BlockEntrance>()) {
- LocIdentifier LocId = std::make_pair(
- BE->getBlock()->getBlockID(), N->getStackFrame());
- NumVisited = NumReached[LocId]++;
- }
-
- queue.push(std::make_pair(U, std::make_pair(-NumVisited, ++Counter)));
- }
-
- WorkListUnit dequeue() override {
- QueueItem U = queue.top();
- queue.pop();
- return U.first;
- }
-};
-
-std::unique_ptr<WorkList> WorkList::makeUnexploredFirstPriorityQueue() {
- return llvm::make_unique<UnexploredFirstPriorityQueue>();
-}
-
//===----------------------------------------------------------------------===//
// Core analysis engine.
//===----------------------------------------------------------------------===//
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 1569e86..51c6f25 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -31,6 +31,7 @@
#include "clang/AST/Type.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/ConstructionContext.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
@@ -449,6 +450,87 @@
return true;
}
+ProgramStateRef ExprEngine::addAllNecessaryTemporaryInfo(
+ ProgramStateRef State, const ConstructionContext *CC,
+ const LocationContext *LC, const MemRegion *R) {
+ const CXXBindTemporaryExpr *BTE = nullptr;
+ const MaterializeTemporaryExpr *MTE = nullptr;
+
+ if (CC) {
+ // If the temporary is being returned from the function, it will be
+ // destroyed or lifetime-extended in the caller stack frame.
+ if (isa<ReturnedValueConstructionContext>(CC)) {
+ const StackFrameContext *SFC = LC->getCurrentStackFrame();
+ assert(SFC);
+ LC = SFC->getParent();
+ if (!LC) {
+ // We are on the top frame. We won't ever need any info
+ // for this temporary, so don't set anything.
+ return State;
+ }
+ const CFGElement &CallElem =
+ (*SFC->getCallSiteBlock())[SFC->getIndex()];
+ auto RTCElem = CallElem.getAs<CFGCXXRecordTypedCall>();
+ if (!RTCElem) {
+ // We have a parent stack frame, but no construction context for the
+ // return value. Give up until we provide the construction context
+ // at the call site.
+ return State;
+ }
+ // We use the ReturnedValueConstructionContext as an indication that we
+ // need to look for the actual construction context on the parent stack
+ // frame. This purpose has been fulfilled, so now we replace CC with the
+ // actual construction context.
+ CC = RTCElem->getConstructionContext();
+ if (!isa<TemporaryObjectConstructionContext>(CC)) {
+ // TODO: We are not returning an object into a temporary. There must
+ // be copy elision happening at the call site. We still need to
+ // explicitly support the situation when the return value is put
+ // into another return statement, i.e.
+ // ReturnedValueConstructionContexts are chained through multiple
+ // stack frames before finally settling in a temporary.
+ // We don't seem to need to explicitly support construction into
+ // a variable after a return.
+ return State;
+ }
+ // Proceed to deal with the temporary we've found on the parent
+ // stack frame.
+ }
+
+ // In case of temporary object construction, extract data necessary for
+ // destruction and lifetime extension.
+ if (const auto *TCC = dyn_cast<TemporaryObjectConstructionContext>(CC)) {
+ if (AMgr.getAnalyzerOptions().includeTemporaryDtorsInCFG()) {
+ BTE = TCC->getCXXBindTemporaryExpr();
+ MTE = TCC->getMaterializedTemporaryExpr();
+ if (!BTE) {
+ // FIXME: Lifetime extension for temporaries without destructors
+ // is not implemented yet.
+ MTE = nullptr;
+ }
+ if (MTE && MTE->getStorageDuration() != SD_FullExpression) {
+ // If the temporary is lifetime-extended, don't save the BTE,
+ // because we don't need a temporary destructor, but an automatic
+ // destructor.
+ BTE = nullptr;
+ }
+ }
+ }
+
+ if (BTE) {
+ State = addInitializedTemporary(State, BTE, LC,
+ cast<CXXTempObjectRegion>(R));
+ }
+
+ if (MTE) {
+ State = addTemporaryMaterialization(State, MTE, LC,
+ cast<CXXTempObjectRegion>(R));
+ }
+ }
+
+ return State;
+}
+
ProgramStateRef
ExprEngine::setCXXNewAllocatorValue(ProgramStateRef State,
const CXXNewExpr *CNE,
@@ -612,6 +694,7 @@
switch (E.getKind()) {
case CFGElement::Statement:
case CFGElement::Constructor:
+ case CFGElement::CXXRecordTypedCall:
ProcessStmt(E.castAs<CFGStmt>().getStmt(), Pred);
return;
case CFGElement::Initializer:
@@ -632,6 +715,8 @@
ProcessLoopExit(E.castAs<CFGLoopExit>().getLoopStmt(), Pred);
return;
case CFGElement::LifetimeEnds:
+ case CFGElement::ScopeBegin:
+ case CFGElement::ScopeEnd:
return;
}
}
@@ -2397,10 +2482,10 @@
assert(Ex->isGLValue() || VD->getType()->isVoidType());
const LocationContext *LocCtxt = Pred->getLocationContext();
const Decl *D = LocCtxt->getDecl();
- const auto *MD = D ? dyn_cast<CXXMethodDecl>(D) : nullptr;
+ const auto *MD = dyn_cast_or_null<CXXMethodDecl>(D);
const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
- SVal V;
- bool IsReference;
+ Optional<std::pair<SVal, QualType>> VInfo;
+
if (AMgr.options.shouldInlineLambdas() && DeclRefEx &&
DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
MD->getParent()->isLambda()) {
@@ -2409,25 +2494,23 @@
llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
FieldDecl *LambdaThisCaptureField;
CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
- const FieldDecl *FD = LambdaCaptureFields[VD];
- if (!FD) {
- // When a constant is captured, sometimes no corresponding field is
- // created in the lambda object.
- assert(VD->getType().isConstQualified());
- V = state->getLValue(VD, LocCtxt);
- IsReference = false;
- } else {
+
+ // Sema follows a sequence of complex rules to determine whether the
+ // variable should be captured.
+ if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
Loc CXXThis =
svalBuilder.getCXXThis(MD, LocCtxt->getCurrentStackFrame());
SVal CXXThisVal = state->getSVal(CXXThis);
- V = state->getLValue(FD, CXXThisVal);
- IsReference = FD->getType()->isReferenceType();
+ VInfo = std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
}
- } else {
- V = state->getLValue(VD, LocCtxt);
- IsReference = VD->getType()->isReferenceType();
}
+ if (!VInfo)
+ VInfo = std::make_pair(state->getLValue(VD, LocCtxt), VD->getType());
+
+ SVal V = VInfo->first;
+ bool IsReference = VInfo->second->isReferenceType();
+
// For references, the 'lvalue' is the pointer address stored in the
// reference region.
if (IsReference) {
@@ -2463,7 +2546,12 @@
currBldrCtx->blockCount());
state = state->assume(V.castAs<DefinedOrUnknownSVal>(), true);
Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
- ProgramPoint::PostLValueKind);
+ ProgramPoint::PostLValueKind);
+ return;
+ }
+ if (isa<BindingDecl>(D)) {
+ // FIXME: proper support for bound declarations.
+ // For now, let's just prevent crashing.
return;
}
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index f4aa56f..18cd414 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -134,7 +134,7 @@
makeZeroElementRegion(State, LValue, Ty, CallOpts.IsArrayCtorOrDtor);
return LValue.getAsRegion();
}
- case ConstructionContext::ConstructorInitializerKind: {
+ case ConstructionContext::SimpleConstructorInitializerKind: {
const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC);
const auto *Init = ICC->getCXXCtorInitializer();
assert(Init->isAnyMemberInitializer());
@@ -196,18 +196,41 @@
CallOpts.IsTemporaryCtorOrDtor = true;
return MRMgr.getCXXTempObjectRegion(CE, LCtx);
}
- case ConstructionContext::ReturnedValueKind: {
- // TODO: We should construct into a CXXBindTemporaryExpr or a
- // MaterializeTemporaryExpr around the call-expression on the previous
- // stack frame. Currently we re-bind the temporary to the correct region
- // later, but that's not semantically correct. This of course does not
- // apply when we're in the top frame. But if we are in an inlined
- // function, we should be able to take the call-site CFG element,
- // and it should contain (but right now it wouldn't) some sort of
- // construction context that'd give us the right temporary expression.
+ case ConstructionContext::SimpleReturnedValueKind: {
+ // The temporary is to be managed by the parent stack frame.
+ // So build it in the parent stack frame if we're not in the
+ // top frame of the analysis.
+ // TODO: What exactly happens when we are? Does the temporary object live
+ // long enough in the region store in this case? Would checkers think
+ // that this object immediately goes out of scope?
+ const LocationContext *TempLCtx = LCtx;
+ const StackFrameContext *SFC = LCtx->getCurrentStackFrame();
+ if (const LocationContext *CallerLCtx = SFC->getParent()) {
+ auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()]
+ .getAs<CFGCXXRecordTypedCall>();
+ if (!RTC) {
+ // We were unable to find the correct construction context for the
+ // call in the parent stack frame. This is equivalent to not being
+ // able to find construction context at all.
+ CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
+ } else if (!isa<TemporaryObjectConstructionContext>(
+ RTC->getConstructionContext())) {
+ // FXIME: The return value is constructed directly into a
+ // non-temporary due to C++17 mandatory copy elision. This is not
+ // implemented yet.
+ assert(getContext().getLangOpts().CPlusPlus17);
+ CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
+ }
+ TempLCtx = CallerLCtx;
+ }
CallOpts.IsTemporaryCtorOrDtor = true;
- return MRMgr.getCXXTempObjectRegion(CE, LCtx);
+ return MRMgr.getCXXTempObjectRegion(CE, TempLCtx);
}
+ case ConstructionContext::CXX17ElidedCopyVariableKind:
+ case ConstructionContext::CXX17ElidedCopyReturnedValueKind:
+ case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind:
+ // Not implemented yet.
+ break;
}
}
// If we couldn't find an existing region to construct into, assume we're
@@ -262,35 +285,9 @@
assert(C || getCurrentCFGElement().getAs<CFGStmt>());
const ConstructionContext *CC = C ? C->getConstructionContext() : nullptr;
- const CXXBindTemporaryExpr *BTE = nullptr;
- const MaterializeTemporaryExpr *MTE = nullptr;
-
switch (CE->getConstructionKind()) {
case CXXConstructExpr::CK_Complete: {
Target = getRegionForConstructedObject(CE, Pred, CC, CallOpts);
-
- // In case of temporary object construction, extract data necessary for
- // destruction and lifetime extension.
- if (const auto *TCC =
- dyn_cast_or_null<TemporaryObjectConstructionContext>(CC)) {
- assert(CallOpts.IsTemporaryCtorOrDtor);
- assert(!CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion);
- if (AMgr.getAnalyzerOptions().includeTemporaryDtorsInCFG()) {
- BTE = TCC->getCXXBindTemporaryExpr();
- MTE = TCC->getMaterializedTemporaryExpr();
- if (!BTE) {
- // FIXME: lifetime extension for temporaries without destructors
- // is not implemented yet.
- MTE = nullptr;
- }
- if (MTE && MTE->getStorageDuration() != SD_FullExpression) {
- // If the temporary is lifetime-extended, don't save the BTE,
- // because we don't need a temporary destructor, but an automatic
- // destructor.
- BTE = nullptr;
- }
- }
- }
break;
}
case CXXConstructExpr::CK_VirtualBase:
@@ -385,15 +382,7 @@
State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal, LCtx);
}
- if (BTE) {
- State = addInitializedTemporary(State, BTE, LCtx,
- cast<CXXTempObjectRegion>(Target));
- }
-
- if (MTE) {
- State = addTemporaryMaterialization(State, MTE, LCtx,
- cast<CXXTempObjectRegion>(Target));
- }
+ State = addAllNecessaryTemporaryInfo(State, CC, LCtx, Target);
Bldr.generateNode(CE, *I, State, /*tag=*/nullptr,
ProgramPoint::PreStmtKind);
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index ede4816..5aace88 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -581,23 +581,39 @@
return State->BindExpr(E, LCtx, ThisV);
}
- // Conjure a symbol if the return value is unknown.
+ SVal R;
QualType ResultTy = Call.getResultType();
- SValBuilder &SVB = getSValBuilder();
unsigned Count = currBldrCtx->blockCount();
+ if (auto RTC = getCurrentCFGElement().getAs<CFGCXXRecordTypedCall>()) {
+ // Conjure a temporary if the function returns an object by value.
+ MemRegionManager &MRMgr = svalBuilder.getRegionManager();
+ const CXXTempObjectRegion *TR = MRMgr.getCXXTempObjectRegion(E, LCtx);
+ State = addAllNecessaryTemporaryInfo(State, RTC->getConstructionContext(),
+ LCtx, TR);
- // See if we need to conjure a heap pointer instead of
- // a regular unknown pointer.
- bool IsHeapPointer = false;
- if (const auto *CNE = dyn_cast<CXXNewExpr>(E))
- if (CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
- // FIXME: Delegate this to evalCall in MallocChecker?
- IsHeapPointer = true;
- }
+ // Invalidate the region so that it didn't look uninitialized. Don't notify
+ // the checkers.
+ State = State->invalidateRegions(TR, E, Count, LCtx,
+ /* CausedByPointerEscape=*/false, nullptr,
+ &Call, nullptr);
- SVal R = IsHeapPointer
- ? SVB.getConjuredHeapSymbolVal(E, LCtx, Count)
- : SVB.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count);
+ R = State->getSVal(TR, E->getType());
+ } else {
+ // Conjure a symbol if the return value is unknown.
+
+ // See if we need to conjure a heap pointer instead of
+ // a regular unknown pointer.
+ bool IsHeapPointer = false;
+ if (const auto *CNE = dyn_cast<CXXNewExpr>(E))
+ if (CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
+ // FIXME: Delegate this to evalCall in MallocChecker?
+ IsHeapPointer = true;
+ }
+
+ R = IsHeapPointer ? svalBuilder.getConjuredHeapSymbolVal(E, LCtx, Count)
+ : svalBuilder.conjureSymbolVal(nullptr, E, LCtx, ResultTy,
+ Count);
+ }
return State->BindExpr(E, LCtx, R);
}
diff --git a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index f5e64f4..d76b9cb 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
@@ -42,6 +42,47 @@
getCheckerManager().runCheckersForPreStmt(Dst, Pred, S, *this);
}
+/// Generate a node in \p Bldr for an iteration statement using ObjC
+/// for-loop iterator.
+static void populateObjCForDestinationSet(
+ ExplodedNodeSet &dstLocation, SValBuilder &svalBuilder,
+ const ObjCForCollectionStmt *S, const Stmt *elem, SVal elementV,
+ SymbolManager &SymMgr, const NodeBuilderContext *currBldrCtx,
+ StmtNodeBuilder &Bldr, bool hasElements) {
+
+ for (ExplodedNode *Pred : dstLocation) {
+ ProgramStateRef state = Pred->getState();
+ const LocationContext *LCtx = Pred->getLocationContext();
+
+ SVal hasElementsV = svalBuilder.makeTruthVal(hasElements);
+
+ // FIXME: S is not an expression. We should not be binding values to it.
+ ProgramStateRef nextState = state->BindExpr(S, LCtx, hasElementsV);
+
+ if (auto MV = elementV.getAs<loc::MemRegionVal>())
+ if (const auto *R = dyn_cast<TypedValueRegion>(MV->getRegion())) {
+ // FIXME: The proper thing to do is to really iterate over the
+ // container. We will do this with dispatch logic to the store.
+ // For now, just 'conjure' up a symbolic value.
+ QualType T = R->getValueType();
+ assert(Loc::isLocType(T));
+
+ SVal V;
+ if (hasElements) {
+ SymbolRef Sym = SymMgr.conjureSymbol(elem, LCtx, T,
+ currBldrCtx->blockCount());
+ V = svalBuilder.makeLoc(Sym);
+ } else {
+ V = svalBuilder.makeIntVal(0, T);
+ }
+
+ nextState = nextState->bindLoc(elementV, V, LCtx);
+ }
+
+ Bldr.generateNode(S, Pred, nextState);
+ }
+}
+
void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
@@ -72,60 +113,35 @@
// result in state splitting.
const Stmt *elem = S->getElement();
+ const Stmt *collection = S->getCollection();
ProgramStateRef state = Pred->getState();
- SVal elementV;
+ SVal collectionV = state->getSVal(collection, Pred->getLocationContext());
- if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
+ SVal elementV;
+ if (const auto *DS = dyn_cast<DeclStmt>(elem)) {
const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl());
assert(elemD->getInit() == nullptr);
elementV = state->getLValue(elemD, Pred->getLocationContext());
- }
- else {
+ } else {
elementV = state->getSVal(elem, Pred->getLocationContext());
}
+ bool isContainerNull = state->isNull(collectionV).isConstrainedTrue();
+
ExplodedNodeSet dstLocation;
evalLocation(dstLocation, S, elem, Pred, state, elementV, nullptr, false);
ExplodedNodeSet Tmp;
StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
- for (ExplodedNodeSet::iterator NI = dstLocation.begin(),
- NE = dstLocation.end(); NI!=NE; ++NI) {
- Pred = *NI;
- ProgramStateRef state = Pred->getState();
- const LocationContext *LCtx = Pred->getLocationContext();
+ if (!isContainerNull)
+ populateObjCForDestinationSet(dstLocation, svalBuilder, S, elem, elementV,
+ SymMgr, currBldrCtx, Bldr,
+ /*hasElements=*/true);
- // Handle the case where the container still has elements.
- SVal TrueV = svalBuilder.makeTruthVal(1);
- ProgramStateRef hasElems = state->BindExpr(S, LCtx, TrueV);
-
- // Handle the case where the container has no elements.
- SVal FalseV = svalBuilder.makeTruthVal(0);
- ProgramStateRef noElems = state->BindExpr(S, LCtx, FalseV);
-
- if (Optional<loc::MemRegionVal> MV = elementV.getAs<loc::MemRegionVal>())
- if (const TypedValueRegion *R =
- dyn_cast<TypedValueRegion>(MV->getRegion())) {
- // FIXME: The proper thing to do is to really iterate over the
- // container. We will do this with dispatch logic to the store.
- // For now, just 'conjure' up a symbolic value.
- QualType T = R->getValueType();
- assert(Loc::isLocType(T));
- SymbolRef Sym = SymMgr.conjureSymbol(elem, LCtx, T,
- currBldrCtx->blockCount());
- SVal V = svalBuilder.makeLoc(Sym);
- hasElems = hasElems->bindLoc(elementV, V, LCtx);
-
- // Bind the location to 'nil' on the false branch.
- SVal nilV = svalBuilder.makeIntVal(0, T);
- noElems = noElems->bindLoc(elementV, nilV, LCtx);
- }
-
- // Create the new nodes.
- Bldr.generateNode(S, Pred, hasElems);
- Bldr.generateNode(S, Pred, noElems);
- }
+ populateObjCForDestinationSet(dstLocation, svalBuilder, S, elem, elementV,
+ SymMgr, currBldrCtx, Bldr,
+ /*hasElements=*/false);
// Finally, run any custom checkers.
// FIXME: Eventually all pre- and post-checks should live in VisitStmt.
diff --git a/lib/StaticAnalyzer/Core/LoopUnrolling.cpp b/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
index a8c4b05..b32e934 100644
--- a/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
+++ b/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
@@ -97,9 +97,7 @@
unaryOperator(anyOf(hasOperatorName("--"), hasOperatorName("++")),
hasUnaryOperand(ignoringParenImpCasts(
declRefExpr(to(varDecl(VarNodeMatcher)))))),
- binaryOperator(anyOf(hasOperatorName("="), hasOperatorName("+="),
- hasOperatorName("/="), hasOperatorName("*="),
- hasOperatorName("-=")),
+ binaryOperator(isAssignmentOperator(),
hasLHS(ignoringParenImpCasts(
declRefExpr(to(varDecl(VarNodeMatcher)))))));
}
diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp
index 1562ff1..b735f5a 100644
--- a/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -430,7 +430,7 @@
for (BlockDataRegion::referenced_vars_iterator
I = referenced_vars_begin(),
E = referenced_vars_end(); I != E; ++I)
- os << "(" << I.getCapturedRegion() << "," <<
+ os << "(" << I.getCapturedRegion() << "<-" <<
I.getOriginalRegion() << ") ";
os << '}';
}
@@ -483,7 +483,12 @@
}
void VarRegion::dumpToStream(raw_ostream &os) const {
- os << *cast<VarDecl>(D);
+ const auto *VD = cast<VarDecl>(D);
+ if (const auto *ID = VD->getIdentifier()) {
+ os << ID->getName();
+ } else {
+ os << "VarRegion{" << static_cast<const void*>(this) << '}';
+ }
}
LLVM_DUMP_METHOD void RegionRawOffset::dump() const {
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 8119e3a..fafedbb 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -1,4 +1,4 @@
-//===--- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -*- C++ -*-===//
+//===- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,26 +13,50 @@
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/OperationKinds.h"
#include "clang/AST/ParentMap.h"
-#include "clang/AST/StmtCXX.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstring>
+#include <memory>
+#include <utility>
+#include <vector>
using namespace clang;
using namespace ento;
bool PathDiagnosticMacroPiece::containsEvent() const {
- for (auto &P : subPieces) {
+ for (const auto &P : subPieces) {
if (isa<PathDiagnosticEventPiece>(*P))
return true;
- if (auto *MP = dyn_cast<PathDiagnosticMacroPiece>(P.get()))
+ if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(P.get()))
if (MP->containsEvent())
return true;
}
@@ -43,23 +67,27 @@
for (StringRef::size_type i = s.size(); i != 0; --i)
if (s[i - 1] != '.')
return s.substr(0, i);
- return "";
+ return {};
}
PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
Kind k, DisplayHint hint)
- : str(StripTrailingDots(s)), kind(k), Hint(hint),
- LastInMainSourceFile(false) {}
+ : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
- : kind(k), Hint(hint), LastInMainSourceFile(false) {}
+ : kind(k), Hint(hint) {}
-PathDiagnosticPiece::~PathDiagnosticPiece() {}
-PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {}
-PathDiagnosticCallPiece::~PathDiagnosticCallPiece() {}
-PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
-PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {}
-PathDiagnosticNotePiece::~PathDiagnosticNotePiece() {}
+PathDiagnosticPiece::~PathDiagnosticPiece() = default;
+
+PathDiagnosticEventPiece::~PathDiagnosticEventPiece() = default;
+
+PathDiagnosticCallPiece::~PathDiagnosticCallPiece() = default;
+
+PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() = default;
+
+PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() = default;
+
+PathDiagnosticNotePiece::~PathDiagnosticNotePiece() = default;
void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
bool ShouldFlattenMacros) const {
@@ -96,7 +124,7 @@
}
}
-PathDiagnostic::~PathDiagnostic() {}
+PathDiagnostic::~PathDiagnostic() = default;
PathDiagnostic::PathDiagnostic(
StringRef CheckName, const Decl *declWithIssue, StringRef bugtype,
@@ -133,10 +161,8 @@
// Check if the last piece in the callee path is a call to a function outside
// of the main file.
- if (PathDiagnosticCallPiece *CPInner =
- dyn_cast<PathDiagnosticCallPiece>(Path.back().get())) {
+ if (auto *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back().get()))
return getFirstStackedCallToHeaderFile(CPInner, SMgr);
- }
// Otherwise, the last piece is in the main file.
return nullptr;
@@ -152,14 +178,14 @@
// We only need to check if the report ends inside headers, if the last piece
// is a call piece.
- if (PathDiagnosticCallPiece *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
+ if (auto *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
CP = getFirstStackedCallToHeaderFile(CP, SMgr);
if (CP) {
// Mark the piece.
CP->setAsLastInMainSourceFile();
// Update the path diagnostic message.
- const NamedDecl *ND = dyn_cast<NamedDecl>(CP->getCallee());
+ const auto *ND = dyn_cast<NamedDecl>(CP->getCallee());
if (ND) {
SmallString<200> buf;
llvm::raw_svector_ostream os(buf);
@@ -176,14 +202,12 @@
}
}
-void PathDiagnosticConsumer::anchor() { }
+void PathDiagnosticConsumer::anchor() {}
PathDiagnosticConsumer::~PathDiagnosticConsumer() {
// Delete the contents of the FoldingSet if it isn't empty already.
- for (llvm::FoldingSet<PathDiagnostic>::iterator it =
- Diags.begin(), et = Diags.end() ; it != et ; ++it) {
- delete &*it;
- }
+ for (auto &Diag : Diags)
+ delete &Diag;
}
void PathDiagnosticConsumer::HandlePathDiagnostic(
@@ -214,9 +238,8 @@
while (!WorkList.empty()) {
const PathPieces &path = *WorkList.pop_back_val();
- for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E;
- ++I) {
- const PathDiagnosticPiece *piece = I->get();
+ for (const auto &I : path) {
+ const PathDiagnosticPiece *piece = I.get();
FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
if (FID.isInvalid()) {
@@ -228,28 +251,23 @@
// Check the source ranges.
ArrayRef<SourceRange> Ranges = piece->getRanges();
- for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
- E = Ranges.end(); I != E; ++I) {
- SourceLocation L = SMgr.getExpansionLoc(I->getBegin());
+ for (const auto &I : Ranges) {
+ SourceLocation L = SMgr.getExpansionLoc(I.getBegin());
if (!L.isFileID() || SMgr.getFileID(L) != FID) {
llvm::errs() << warning.str();
return;
}
- L = SMgr.getExpansionLoc(I->getEnd());
+ L = SMgr.getExpansionLoc(I.getEnd());
if (!L.isFileID() || SMgr.getFileID(L) != FID) {
llvm::errs() << warning.str();
return;
}
}
- if (const PathDiagnosticCallPiece *call =
- dyn_cast<PathDiagnosticCallPiece>(piece)) {
+ if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
WorkList.push_back(&call->path);
- }
- else if (const PathDiagnosticMacroPiece *macro =
- dyn_cast<PathDiagnosticMacroPiece>(piece)) {
+ else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
WorkList.push_back(¯o->subPieces);
- }
}
}
@@ -442,11 +460,8 @@
flushed = true;
std::vector<const PathDiagnostic *> BatchDiags;
- for (llvm::FoldingSet<PathDiagnostic>::iterator it = Diags.begin(),
- et = Diags.end(); it != et; ++it) {
- const PathDiagnostic *D = &*it;
- BatchDiags.push_back(D);
- }
+ for (const auto &D : Diags)
+ BatchDiags.push_back(&D);
// Sort the diagnostics so that they are always emitted in a deterministic
// order.
@@ -463,11 +478,8 @@
FlushDiagnosticsImpl(BatchDiags, Files);
// Delete the flushed diagnostics.
- for (std::vector<const PathDiagnostic *>::iterator it = BatchDiags.begin(),
- et = BatchDiags.end(); it != et; ++it) {
- const PathDiagnostic *D = *it;
+ for (const auto D : BatchDiags)
delete D;
- }
// Clear out the FoldingSet.
Diags.clear();
@@ -567,6 +579,7 @@
switch (Source.getKind()) {
case CFGElement::Statement:
case CFGElement::Constructor:
+ case CFGElement::CXXRecordTypedCall:
return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
SM, CallerCtx);
case CFGElement::Initializer: {
@@ -602,6 +615,9 @@
return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
CallerCtx);
}
+ case CFGElement::ScopeBegin:
+ case CFGElement::ScopeEnd:
+ llvm_unreachable("not yet implemented!");
case CFGElement::LifetimeEnds:
case CFGElement::LoopExit:
llvm_unreachable("CFGElement kind should not be on callsite!");
@@ -628,7 +644,7 @@
PathDiagnosticLocation::createEnd(const Stmt *S,
const SourceManager &SM,
LocationOrAnalysisDeclContext LAC) {
- if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(S))
+ if (const auto *CS = dyn_cast<CompoundStmt>(S))
return createEndBrace(CS, SM);
return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
SM, SingleLocK);
@@ -647,7 +663,6 @@
return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
}
-
PathDiagnosticLocation
PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
const SourceManager &SM) {
@@ -672,8 +687,7 @@
PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
const SourceManager &SM) {
// FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
- if (const CompoundStmt *CS =
- dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
+ if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
if (!CS->body_empty()) {
SourceLocation Loc = (*CS->body_begin())->getLocStart();
return PathDiagnosticLocation(Loc, SM, SingleLocK);
@@ -815,11 +829,11 @@
const LocationContext *LC = N->getLocationContext();
// For member expressions, return the location of the '.' or '->'.
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
+ if (const auto *ME = dyn_cast<MemberExpr>(S))
return PathDiagnosticLocation::createMemberLoc(ME, SM);
// For binary operators, return the location of the operator.
- if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
+ if (const auto *B = dyn_cast<BinaryOperator>(S))
return PathDiagnosticLocation::createOperatorLoc(B, SM);
if (P.getAs<PostStmtPurgeDeadSymbols>())
@@ -881,7 +895,7 @@
default:
break;
case Stmt::DeclStmtClass: {
- const DeclStmt *DS = cast<DeclStmt>(S);
+ const auto *DS = cast<DeclStmt>(S);
if (DS->isSingleDecl()) {
// Should always be the case, but we'll be defensive.
return SourceRange(DS->getLocStart(),
@@ -911,9 +925,9 @@
break;
}
case DeclK:
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->getSourceRange();
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (Stmt *Body = FD->getBody())
return Body->getSourceRange();
}
@@ -923,7 +937,7 @@
}
}
- return SourceRange(Loc,Loc);
+ return SourceRange(Loc, Loc);
}
void PathDiagnosticLocation::flatten() {
@@ -979,14 +993,14 @@
// non-autosynthesized callbacks.
// Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
// defaults to false.
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Callee))
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
IsCalleeAnAutosynthesizedPropertyAccessor = (
MD->isPropertyAccessor() &&
CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized());
}
-static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
- StringRef Prefix = StringRef()) {
+static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
+ StringRef Prefix = StringRef()) {
if (!D->getIdentifier())
return;
Out << Prefix << '\'' << *D << '\'';
@@ -1004,7 +1018,7 @@
return ExtendedDescription;
}
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
Out << Prefix;
if (ExtendedDescription && !MD->isUserProvided()) {
if (MD->isExplicitlyDefaulted())
@@ -1013,7 +1027,7 @@
Out << "implicit ";
}
- if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) {
+ if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
if (CD->isDefaultConstructor())
Out << "default ";
else if (CD->isCopyConstructor())
@@ -1023,7 +1037,6 @@
Out << "constructor";
describeClass(Out, MD->getParent(), " for ");
-
} else if (isa<CXXDestructorDecl>(MD)) {
if (!MD->isUserProvided()) {
Out << "destructor";
@@ -1032,15 +1045,12 @@
// Use ~Foo for explicitly-written destructors.
Out << "'" << *MD << "'";
}
-
} else if (MD->isCopyAssignmentOperator()) {
Out << "copy assignment operator";
describeClass(Out, MD->getParent(), " for ");
-
} else if (MD->isMoveAssignmentOperator()) {
Out << "move assignment operator";
describeClass(Out, MD->getParent(), " for ");
-
} else {
if (MD->getParent()->getIdentifier())
Out << "'" << *MD->getParent() << "::" << *MD << "'";
@@ -1080,7 +1090,7 @@
return nullptr;
if (Callee->isImplicit() || !Callee->hasBody())
return nullptr;
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee))
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
if (MD->isDefaulted())
return nullptr;
@@ -1120,13 +1130,10 @@
}
static void compute_path_size(const PathPieces &pieces, unsigned &size) {
- for (PathPieces::const_iterator it = pieces.begin(),
- et = pieces.end(); it != et; ++it) {
- const PathDiagnosticPiece *piece = it->get();
- if (const PathDiagnosticCallPiece *cp =
- dyn_cast<PathDiagnosticCallPiece>(piece)) {
+ for (const auto &I : pieces) {
+ const PathDiagnosticPiece *piece = I.get();
+ if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
compute_path_size(cp->path, size);
- }
else
++size;
}
@@ -1154,19 +1161,16 @@
// FIXME: Add profiling support for code hints.
ID.AddInteger((unsigned) getDisplayHint());
ArrayRef<SourceRange> Ranges = getRanges();
- for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
- I != E; ++I) {
- ID.AddInteger(I->getBegin().getRawEncoding());
- ID.AddInteger(I->getEnd().getRawEncoding());
+ for (const auto &I : Ranges) {
+ ID.AddInteger(I.getBegin().getRawEncoding());
+ ID.AddInteger(I.getEnd().getRawEncoding());
}
}
void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
PathDiagnosticPiece::Profile(ID);
- for (PathPieces::const_iterator it = path.begin(),
- et = path.end(); it != et; ++it) {
- ID.Add(**it);
- }
+ for (const auto &I : path)
+ ID.Add(*I);
}
void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
@@ -1176,15 +1180,14 @@
void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
PathDiagnosticPiece::Profile(ID);
- for (const_iterator I = begin(), E = end(); I != E; ++I)
- ID.Add(*I);
+ for (const auto &I : *this)
+ ID.Add(I);
}
void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
PathDiagnosticSpotPiece::Profile(ID);
- for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
- I != E; ++I)
- ID.Add(**I);
+ for (const auto &I : subPieces)
+ ID.Add(*I);
}
void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
@@ -1200,13 +1203,13 @@
void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
Profile(ID);
- for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I)
- ID.Add(**I);
+ for (const auto &I : path)
+ ID.Add(*I);
for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
ID.AddString(*I);
}
-StackHintGenerator::~StackHintGenerator() {}
+StackHintGenerator::~StackHintGenerator() = default;
std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
if (!N)
@@ -1217,9 +1220,9 @@
// FIXME: Use CallEvent to abstract this over all calls.
const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
- const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite);
+ const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
if (!CE)
- return "";
+ return {};
// Check if one of the parameters are set to the interesting symbol.
unsigned ArgIndex = 0;
diff --git a/lib/StaticAnalyzer/Core/WorkList.cpp b/lib/StaticAnalyzer/Core/WorkList.cpp
new file mode 100644
index 0000000..95ffc44
--- /dev/null
+++ b/lib/StaticAnalyzer/Core/WorkList.cpp
@@ -0,0 +1,252 @@
+//===- WorkList.cpp - Analyzer work-list implementation--------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines different worklist implementations for the static analyzer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
+#include "llvm/ADT/PriorityQueue.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Statistic.h"
+#include <deque>
+#include <vector>
+
+using namespace clang;
+using namespace ento;
+
+#define DEBUG_TYPE "WorkList"
+
+STATISTIC(MaxQueueSize, "Maximum size of the worklist");
+STATISTIC(MaxReachableSize, "Maximum size of auxiliary worklist set");
+
+//===----------------------------------------------------------------------===//
+// Worklist classes for exploration of reachable states.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class DFS : public WorkList {
+ SmallVector<WorkListUnit, 20> Stack;
+
+public:
+ bool hasWork() const override {
+ return !Stack.empty();
+ }
+
+ void enqueue(const WorkListUnit& U) override {
+ Stack.push_back(U);
+ }
+
+ WorkListUnit dequeue() override {
+ assert(!Stack.empty());
+ const WorkListUnit& U = Stack.back();
+ Stack.pop_back(); // This technically "invalidates" U, but we are fine.
+ return U;
+ }
+};
+
+class BFS : public WorkList {
+ std::deque<WorkListUnit> Queue;
+
+public:
+ bool hasWork() const override {
+ return !Queue.empty();
+ }
+
+ void enqueue(const WorkListUnit& U) override {
+ Queue.push_back(U);
+ }
+
+ WorkListUnit dequeue() override {
+ WorkListUnit U = Queue.front();
+ Queue.pop_front();
+ return U;
+ }
+};
+
+} // namespace
+
+// Place the dstor for WorkList here because it contains virtual member
+// functions, and we the code for the dstor generated in one compilation unit.
+WorkList::~WorkList() = default;
+
+std::unique_ptr<WorkList> WorkList::makeDFS() {
+ return llvm::make_unique<DFS>();
+}
+
+std::unique_ptr<WorkList> WorkList::makeBFS() {
+ return llvm::make_unique<BFS>();
+}
+
+namespace {
+
+ class BFSBlockDFSContents : public WorkList {
+ std::deque<WorkListUnit> Queue;
+ SmallVector<WorkListUnit, 20> Stack;
+
+ public:
+ bool hasWork() const override {
+ return !Queue.empty() || !Stack.empty();
+ }
+
+ void enqueue(const WorkListUnit& U) override {
+ if (U.getNode()->getLocation().getAs<BlockEntrance>())
+ Queue.push_front(U);
+ else
+ Stack.push_back(U);
+ }
+
+ WorkListUnit dequeue() override {
+ // Process all basic blocks to completion.
+ if (!Stack.empty()) {
+ const WorkListUnit& U = Stack.back();
+ Stack.pop_back(); // This technically "invalidates" U, but we are fine.
+ return U;
+ }
+
+ assert(!Queue.empty());
+ // Don't use const reference. The subsequent pop_back() might make it
+ // unsafe.
+ WorkListUnit U = Queue.front();
+ Queue.pop_front();
+ return U;
+ }
+ };
+
+} // namespace
+
+std::unique_ptr<WorkList> WorkList::makeBFSBlockDFSContents() {
+ return llvm::make_unique<BFSBlockDFSContents>();
+}
+
+namespace {
+
+class UnexploredFirstStack : public WorkList {
+ /// Stack of nodes known to have statements we have not traversed yet.
+ SmallVector<WorkListUnit, 20> StackUnexplored;
+
+ /// Stack of all other nodes.
+ SmallVector<WorkListUnit, 20> StackOthers;
+
+ using BlockID = unsigned;
+ using LocIdentifier = std::pair<BlockID, const StackFrameContext *>;
+
+ llvm::DenseSet<LocIdentifier> Reachable;
+
+public:
+ bool hasWork() const override {
+ return !(StackUnexplored.empty() && StackOthers.empty());
+ }
+
+ void enqueue(const WorkListUnit &U) override {
+ const ExplodedNode *N = U.getNode();
+ auto BE = N->getLocation().getAs<BlockEntrance>();
+
+ if (!BE) {
+ // Assume the choice of the order of the preceeding block entrance was
+ // correct.
+ StackUnexplored.push_back(U);
+ } else {
+ LocIdentifier LocId = std::make_pair(
+ BE->getBlock()->getBlockID(),
+ N->getLocationContext()->getCurrentStackFrame());
+ auto InsertInfo = Reachable.insert(LocId);
+
+ if (InsertInfo.second) {
+ StackUnexplored.push_back(U);
+ } else {
+ StackOthers.push_back(U);
+ }
+ }
+ MaxReachableSize.updateMax(Reachable.size());
+ MaxQueueSize.updateMax(StackUnexplored.size() + StackOthers.size());
+ }
+
+ WorkListUnit dequeue() override {
+ if (!StackUnexplored.empty()) {
+ WorkListUnit &U = StackUnexplored.back();
+ StackUnexplored.pop_back();
+ return U;
+ } else {
+ WorkListUnit &U = StackOthers.back();
+ StackOthers.pop_back();
+ return U;
+ }
+ }
+};
+
+} // namespace
+
+std::unique_ptr<WorkList> WorkList::makeUnexploredFirst() {
+ return llvm::make_unique<UnexploredFirstStack>();
+}
+
+class UnexploredFirstPriorityQueue : public WorkList {
+ using BlockID = unsigned;
+ using LocIdentifier = std::pair<BlockID, const StackFrameContext *>;
+
+ // How many times each location was visited.
+ // Is signed because we negate it later in order to have a reversed
+ // comparison.
+ using VisitedTimesMap = llvm::DenseMap<LocIdentifier, int>;
+
+ // Compare by number of times the location was visited first (negated
+ // to prefer less often visited locations), then by insertion time (prefer
+ // expanding nodes inserted sooner first).
+ using QueuePriority = std::pair<int, unsigned long>;
+ using QueueItem = std::pair<WorkListUnit, QueuePriority>;
+
+ struct ExplorationComparator {
+ bool operator() (const QueueItem &LHS, const QueueItem &RHS) {
+ return LHS.second < RHS.second;
+ }
+ };
+
+ // Number of inserted nodes, used to emulate DFS ordering in the priority
+ // queue when insertions are equal.
+ unsigned long Counter = 0;
+
+ // Number of times a current location was reached.
+ VisitedTimesMap NumReached;
+
+ // The top item is the largest one.
+ llvm::PriorityQueue<QueueItem, std::vector<QueueItem>, ExplorationComparator>
+ queue;
+
+public:
+ bool hasWork() const override {
+ return !queue.empty();
+ }
+
+ void enqueue(const WorkListUnit &U) override {
+ const ExplodedNode *N = U.getNode();
+ unsigned NumVisited = 0;
+ if (auto BE = N->getLocation().getAs<BlockEntrance>()) {
+ LocIdentifier LocId = std::make_pair(
+ BE->getBlock()->getBlockID(),
+ N->getLocationContext()->getCurrentStackFrame());
+ NumVisited = NumReached[LocId]++;
+ }
+
+ queue.push(std::make_pair(U, std::make_pair(-NumVisited, ++Counter)));
+ }
+
+ WorkListUnit dequeue() override {
+ QueueItem U = queue.top();
+ queue.pop();
+ return U.first;
+ }
+};
+
+std::unique_ptr<WorkList> WorkList::makeUnexploredFirstPriorityQueue() {
+ return llvm::make_unique<UnexploredFirstPriorityQueue>();
+}
diff --git a/lib/Tooling/ASTDiff/ASTDiff.cpp b/lib/Tooling/ASTDiff/ASTDiff.cpp
index 6da0de7..a58ac55 100644
--- a/lib/Tooling/ASTDiff/ASTDiff.cpp
+++ b/lib/Tooling/ASTDiff/ASTDiff.cpp
@@ -741,7 +741,7 @@
List.pop();
}
// TODO this is here to get a stable output, not a good heuristic
- std::sort(Result.begin(), Result.end());
+ llvm::sort(Result.begin(), Result.end());
return Result;
}
int peekMax() const {
diff --git a/lib/Tooling/ArgumentsAdjusters.cpp b/lib/Tooling/ArgumentsAdjusters.cpp
index 7068ec2..c8e9c16 100644
--- a/lib/Tooling/ArgumentsAdjusters.cpp
+++ b/lib/Tooling/ArgumentsAdjusters.cpp
@@ -1,4 +1,4 @@
-//===--- ArgumentsAdjusters.cpp - Command line arguments adjuster ---------===//
+//===- ArgumentsAdjusters.cpp - Command line arguments adjuster -----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,6 +13,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/ArgumentsAdjusters.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include <cstddef>
namespace clang {
namespace tooling {
@@ -21,7 +24,7 @@
ArgumentsAdjuster getClangSyntaxOnlyAdjuster() {
return [](const CommandLineArguments &Args, StringRef /*unused*/) {
CommandLineArguments AdjustedArgs;
- for (size_t i = 0, e = Args.size(); i != e; ++i) {
+ for (size_t i = 0, e = Args.size(); i < e; ++i) {
StringRef Arg = Args[i];
// FIXME: Remove options that generate output.
if (!Arg.startswith("-fcolor-diagnostics") &&
diff --git a/lib/Tooling/CompilationDatabase.cpp b/lib/Tooling/CompilationDatabase.cpp
index 92b76b1..3464a26 100644
--- a/lib/Tooling/CompilationDatabase.cpp
+++ b/lib/Tooling/CompilationDatabase.cpp
@@ -1,4 +1,4 @@
-//===--- CompilationDatabase.cpp - ----------------------------------------===//
+//===- CompilationDatabase.cpp --------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,7 +17,9 @@
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -26,20 +28,38 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Option/Arg.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <iterator>
+#include <memory>
#include <sstream>
+#include <string>
#include <system_error>
+#include <utility>
+#include <vector>
+
using namespace clang;
using namespace tooling;
LLVM_INSTANTIATE_REGISTRY(CompilationDatabasePluginRegistry)
-CompilationDatabase::~CompilationDatabase() {}
+CompilationDatabase::~CompilationDatabase() = default;
std::unique_ptr<CompilationDatabase>
CompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
@@ -121,20 +141,20 @@
return Result;
}
-CompilationDatabasePlugin::~CompilationDatabasePlugin() {}
+CompilationDatabasePlugin::~CompilationDatabasePlugin() = default;
namespace {
+
// Helper for recursively searching through a chain of actions and collecting
// all inputs, direct and indirect, of compile jobs.
struct CompileJobAnalyzer {
+ SmallVector<std::string, 2> Inputs;
+
void run(const driver::Action *A) {
runImpl(A, false);
}
- SmallVector<std::string, 2> Inputs;
-
private:
-
void runImpl(const driver::Action *A, bool Collect) {
bool CollectChildren = Collect;
switch (A->getKind()) {
@@ -142,16 +162,16 @@
CollectChildren = true;
break;
- case driver::Action::InputClass: {
+ case driver::Action::InputClass:
if (Collect) {
- const driver::InputAction *IA = cast<driver::InputAction>(A);
+ const auto *IA = cast<driver::InputAction>(A);
Inputs.push_back(IA->getInputArg().getSpelling());
}
- } break;
+ break;
default:
// Don't care about others
- ;
+ break;
}
for (const driver::Action *AI : A->inputs())
@@ -168,7 +188,7 @@
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) override {
- if (Info.getID() == clang::diag::warn_drv_input_file_unused) {
+ if (Info.getID() == diag::warn_drv_input_file_unused) {
// Arg 1 for this diagnostic is the option that didn't get used.
UnusedInputs.push_back(Info.getArgStdStr(0));
} else if (DiagLevel >= DiagnosticsEngine::Error) {
@@ -186,15 +206,18 @@
// S2 in Arr where S1 == S2?"
struct MatchesAny {
MatchesAny(ArrayRef<std::string> Arr) : Arr(Arr) {}
+
bool operator() (StringRef S) {
for (const std::string *I = Arr.begin(), *E = Arr.end(); I != E; ++I)
if (*I == S)
return true;
return false;
}
+
private:
ArrayRef<std::string> Arr;
};
+
} // namespace
/// \brief Strips any positional args and possible argv[0] from a command-line
@@ -224,7 +247,7 @@
TextDiagnosticPrinter DiagnosticPrinter(Output, &*DiagOpts);
UnusedInputDiagConsumer DiagClient(DiagnosticPrinter);
DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()),
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
&*DiagOpts, &DiagClient, false);
// The clang executable path isn't required since the jobs the driver builds
@@ -362,11 +385,11 @@
}
};
+} // namespace
+
static CompilationDatabasePluginRegistry::Add<FixedCompilationDatabasePlugin>
X("fixed-compilation-database", "Reads plain-text flags file");
-} // namespace
-
namespace clang {
namespace tooling {
@@ -375,5 +398,5 @@
extern volatile int JSONAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED JSONAnchorDest = JSONAnchorSource;
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+} // namespace clang
diff --git a/lib/Tooling/Core/Replacement.cpp b/lib/Tooling/Core/Replacement.cpp
index 6d4f3a3..d13a276 100644
--- a/lib/Tooling/Core/Replacement.cpp
+++ b/lib/Tooling/Core/Replacement.cpp
@@ -1,4 +1,4 @@
-//===--- Replacement.cpp - Framework for clang refactoring tools ----------===//
+//===- Replacement.cpp - Framework for clang refactoring tools ------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,21 +12,34 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/Core/Replacement.h"
-
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Rewrite/Core/RewriteBuffer.h"
#include "clang/Rewrite/Core/Rewriter.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_os_ostream.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <limits>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
-namespace clang {
-namespace tooling {
+using namespace clang;
+using namespace tooling;
static const char * const InvalidLocation = "";
@@ -80,6 +93,9 @@
return Stream.str();
}
+namespace clang {
+namespace tooling {
+
bool operator<(const Replacement &LHS, const Replacement &RHS) {
if (LHS.getOffset() != RHS.getOffset())
return LHS.getOffset() < RHS.getOffset();
@@ -99,6 +115,9 @@
LHS.getReplacementText() == RHS.getReplacementText();
}
+} // namespace tooling
+} // namespace clang
+
void Replacement::setFromSourceLocation(const SourceManager &Sources,
SourceLocation Start, unsigned Length,
StringRef ReplacementText) {
@@ -231,7 +250,7 @@
replacement_error::wrong_file_path, R, *Replaces.begin());
// Special-case header insertions.
- if (R.getOffset() == UINT_MAX) {
+ if (R.getOffset() == std::numeric_limits<unsigned>::max()) {
Replaces.insert(R);
return llvm::Error::success();
}
@@ -396,6 +415,7 @@
// Returns 'true' if an element from the second set should be merged next.
bool mergeSecond() const { return MergeSecond; }
+
int deltaFirst() const { return DeltaFirst; }
Replacement asReplacement() const { return {FilePath, Offset, Length, Text}; }
@@ -463,11 +483,11 @@
// Returns a set of non-overlapping and sorted ranges that is equivalent to
// \p Ranges.
static std::vector<Range> combineAndSortRanges(std::vector<Range> Ranges) {
- std::sort(Ranges.begin(), Ranges.end(),
- [](const Range &LHS, const Range &RHS) {
- if (LHS.getOffset() != RHS.getOffset())
- return LHS.getOffset() < RHS.getOffset();
- return LHS.getLength() < RHS.getLength();
+ llvm::sort(Ranges.begin(), Ranges.end(),
+ [](const Range &LHS, const Range &RHS) {
+ if (LHS.getOffset() != RHS.getOffset())
+ return LHS.getOffset() < RHS.getOffset();
+ return LHS.getLength() < RHS.getLength();
});
std::vector<Range> Result;
for (const auto &R : Ranges) {
@@ -485,6 +505,9 @@
return Result;
}
+namespace clang {
+namespace tooling {
+
std::vector<Range>
calculateRangesAfterReplacements(const Replacements &Replaces,
const std::vector<Range> &Ranges) {
@@ -508,10 +531,13 @@
return FakeReplaces.merge(Replaces).getAffectedRanges();
}
+} // namespace tooling
+} // namespace clang
+
std::vector<Range> Replacements::getAffectedRanges() const {
std::vector<Range> ChangedRanges;
int Shift = 0;
- for (const Replacement &R : Replaces) {
+ for (const auto &R : Replaces) {
unsigned Offset = R.getOffset() + Shift;
unsigned Length = R.getReplacementText().size();
Shift += Length - R.getLength();
@@ -522,7 +548,7 @@
unsigned Replacements::getShiftedCodePosition(unsigned Position) const {
unsigned Offset = 0;
- for (const auto& R : Replaces) {
+ for (const auto &R : Replaces) {
if (R.getOffset() + R.getLength() <= Position) {
Offset += R.getReplacementText().size() - R.getLength();
continue;
@@ -530,7 +556,7 @@
if (R.getOffset() < Position &&
R.getOffset() + R.getReplacementText().size() <= Position) {
Position = R.getOffset() + R.getReplacementText().size();
- if (R.getReplacementText().size() > 0)
+ if (!R.getReplacementText().empty())
Position--;
}
break;
@@ -538,6 +564,9 @@
return Position + Offset;
}
+namespace clang {
+namespace tooling {
+
bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite) {
bool Result = true;
for (auto I = Replaces.rbegin(), E = Replaces.rend(); I != E; ++I) {
@@ -596,5 +625,5 @@
return Result;
}
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+} // namespace clang
diff --git a/lib/Tooling/FileMatchTrie.cpp b/lib/Tooling/FileMatchTrie.cpp
index 86ed036..248d4e2 100644
--- a/lib/Tooling/FileMatchTrie.cpp
+++ b/lib/Tooling/FileMatchTrie.cpp
@@ -1,4 +1,4 @@
-//===--- FileMatchTrie.cpp - ----------------------------------------------===//
+//===- FileMatchTrie.cpp --------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,24 +13,30 @@
#include "clang/Tooling/FileMatchTrie.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-#include <sstream>
+#include <string>
+#include <vector>
+
using namespace clang;
using namespace tooling;
namespace {
+
/// \brief Default \c PathComparator using \c llvm::sys::fs::equivalent().
struct DefaultPathComparator : public PathComparator {
bool equivalent(StringRef FileA, StringRef FileB) const override {
return FileA == FileB || llvm::sys::fs::equivalent(FileA, FileB);
}
};
-}
+
+} // namespace
namespace clang {
namespace tooling {
+
/// \brief A node of the \c FileMatchTrie.
///
/// Each node has storage for up to one path and a map mapping a path segment to
@@ -103,7 +109,7 @@
if (Children.empty()) {
if (Comparator.equivalent(StringRef(Path), FileName))
return StringRef(Path);
- return StringRef();
+ return {};
}
StringRef Element(llvm::sys::path::filename(FileName.drop_back(
ConsumedLength)));
@@ -119,13 +125,13 @@
std::vector<StringRef> AllChildren;
getAll(AllChildren, MatchingChild);
StringRef Result;
- for (unsigned i = 0; i < AllChildren.size(); i++) {
- if (Comparator.equivalent(AllChildren[i], FileName)) {
+ for (const auto &Child : AllChildren) {
+ if (Comparator.equivalent(Child, FileName)) {
if (Result.empty()) {
- Result = AllChildren[i];
+ Result = Child;
} else {
IsAmbiguous = true;
- return StringRef();
+ return {};
}
}
}
@@ -158,14 +164,15 @@
// The children of this node stored in a map based on the next path segment.
llvm::StringMap<FileMatchTrieNode> Children;
};
-} // end namespace tooling
-} // end namespace clang
+
+} // namespace tooling
+} // namespace clang
FileMatchTrie::FileMatchTrie()
- : Root(new FileMatchTrieNode), Comparator(new DefaultPathComparator()) {}
+ : Root(new FileMatchTrieNode), Comparator(new DefaultPathComparator()) {}
FileMatchTrie::FileMatchTrie(PathComparator *Comparator)
- : Root(new FileMatchTrieNode), Comparator(Comparator) {}
+ : Root(new FileMatchTrieNode), Comparator(Comparator) {}
FileMatchTrie::~FileMatchTrie() {
delete Root;
@@ -179,7 +186,7 @@
raw_ostream &Error) const {
if (llvm::sys::path::is_relative(FileName)) {
Error << "Cannot resolve relative paths";
- return StringRef();
+ return {};
}
bool IsAmbiguous = false;
StringRef Result = Root->findEquivalent(*Comparator, FileName, IsAmbiguous);
diff --git a/lib/Tooling/JSONCompilationDatabase.cpp b/lib/Tooling/JSONCompilationDatabase.cpp
index f9a230e..67c1f5b 100644
--- a/lib/Tooling/JSONCompilationDatabase.cpp
+++ b/lib/Tooling/JSONCompilationDatabase.cpp
@@ -1,4 +1,4 @@
-//===--- JSONCompilationDatabase.cpp - ------------------------------------===//
+//===- JSONCompilationDatabase.cpp ----------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,18 +12,34 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/JSONCompilationDatabase.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
-#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/YAMLParser.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <memory>
+#include <string>
#include <system_error>
+#include <tuple>
+#include <utility>
+#include <vector>
-namespace clang {
-namespace tooling {
+using namespace clang;
+using namespace tooling;
namespace {
@@ -151,17 +167,23 @@
}
};
-} // end namespace
+} // namespace
// Register the JSONCompilationDatabasePlugin with the
// CompilationDatabasePluginRegistry using this statically initialized variable.
static CompilationDatabasePluginRegistry::Add<JSONCompilationDatabasePlugin>
X("json-compilation-database", "Reads JSON formatted compilation databases");
+namespace clang {
+namespace tooling {
+
// This anchor is used to force the linker to link in the generated object file
// and thus register the JSONCompilationDatabasePlugin.
volatile int JSONAnchorSource = 0;
+} // namespace tooling
+} // namespace clang
+
std::unique_ptr<JSONCompilationDatabase>
JSONCompilationDatabase::loadFromFile(StringRef FilePath,
std::string &ErrorMessage,
@@ -201,11 +223,10 @@
llvm::raw_string_ostream ES(Error);
StringRef Match = MatchTrie.findEquivalent(NativeFilePath, ES);
if (Match.empty())
- return std::vector<CompileCommand>();
- llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
- CommandsRefI = IndexByFile.find(Match);
+ return {};
+ const auto CommandsRefI = IndexByFile.find(Match);
if (CommandsRefI == IndexByFile.end())
- return std::vector<CompileCommand>();
+ return {};
std::vector<CompileCommand> Commands;
getCommands(CommandsRefI->getValue(), Commands);
return Commands;
@@ -214,15 +235,8 @@
std::vector<std::string>
JSONCompilationDatabase::getAllFiles() const {
std::vector<std::string> Result;
-
- llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
- CommandsRefI = IndexByFile.begin();
- const llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
- CommandsRefEnd = IndexByFile.end();
- for (; CommandsRefI != CommandsRefEnd; ++CommandsRefI) {
- Result.push_back(CommandsRefI->first().str());
- }
-
+ for (const auto &CommandRef : IndexByFile)
+ Result.push_back(CommandRef.first().str());
return Result;
}
@@ -237,28 +251,26 @@
nodeToCommandLine(JSONCommandLineSyntax Syntax,
const std::vector<llvm::yaml::ScalarNode *> &Nodes) {
SmallString<1024> Storage;
- if (Nodes.size() == 1) {
+ if (Nodes.size() == 1)
return unescapeCommandLine(Syntax, Nodes[0]->getValue(Storage));
- }
std::vector<std::string> Arguments;
- for (auto *Node : Nodes) {
+ for (const auto *Node : Nodes)
Arguments.push_back(Node->getValue(Storage));
- }
return Arguments;
}
void JSONCompilationDatabase::getCommands(
ArrayRef<CompileCommandRef> CommandsRef,
std::vector<CompileCommand> &Commands) const {
- for (int I = 0, E = CommandsRef.size(); I != E; ++I) {
+ for (const auto &CommandRef : CommandsRef) {
SmallString<8> DirectoryStorage;
SmallString<32> FilenameStorage;
SmallString<32> OutputStorage;
- auto Output = std::get<3>(CommandsRef[I]);
+ auto Output = std::get<3>(CommandRef);
Commands.emplace_back(
- std::get<0>(CommandsRef[I])->getValue(DirectoryStorage),
- std::get<1>(CommandsRef[I])->getValue(FilenameStorage),
- nodeToCommandLine(Syntax, std::get<2>(CommandsRef[I])),
+ std::get<0>(CommandRef)->getValue(DirectoryStorage),
+ std::get<1>(CommandRef)->getValue(FilenameStorage),
+ nodeToCommandLine(Syntax, std::get<2>(CommandRef)),
Output ? Output->getValue(OutputStorage) : "");
}
}
@@ -274,13 +286,13 @@
ErrorMessage = "Error while parsing YAML.";
return false;
}
- llvm::yaml::SequenceNode *Array = dyn_cast<llvm::yaml::SequenceNode>(Root);
+ auto *Array = dyn_cast<llvm::yaml::SequenceNode>(Root);
if (!Array) {
ErrorMessage = "Expected array.";
return false;
}
- for (auto& NextObject : *Array) {
- llvm::yaml::MappingNode *Object = dyn_cast<llvm::yaml::MappingNode>(&NextObject);
+ for (auto &NextObject : *Array) {
+ auto *Object = dyn_cast<llvm::yaml::MappingNode>(&NextObject);
if (!Object) {
ErrorMessage = "Expected object.";
return false;
@@ -290,8 +302,7 @@
llvm::yaml::ScalarNode *File = nullptr;
llvm::yaml::ScalarNode *Output = nullptr;
for (auto& NextKeyValue : *Object) {
- llvm::yaml::ScalarNode *KeyString =
- dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
if (!KeyString) {
ErrorMessage = "Expected strings as key.";
return false;
@@ -303,10 +314,8 @@
ErrorMessage = "Expected value.";
return false;
}
- llvm::yaml::ScalarNode *ValueString =
- dyn_cast<llvm::yaml::ScalarNode>(Value);
- llvm::yaml::SequenceNode *SequenceString =
- dyn_cast<llvm::yaml::SequenceNode>(Value);
+ auto *ValueString = dyn_cast<llvm::yaml::ScalarNode>(Value);
+ auto *SequenceString = dyn_cast<llvm::yaml::SequenceNode>(Value);
if (KeyValue == "arguments" && !SequenceString) {
ErrorMessage = "Expected sequence as value.";
return false;
@@ -319,7 +328,7 @@
} else if (KeyValue == "arguments") {
Command = std::vector<llvm::yaml::ScalarNode *>();
for (auto &Argument : *SequenceString) {
- auto Scalar = dyn_cast<llvm::yaml::ScalarNode>(&Argument);
+ auto *Scalar = dyn_cast<llvm::yaml::ScalarNode>(&Argument);
if (!Scalar) {
ErrorMessage = "Only strings are allowed in 'arguments'.";
return false;
@@ -370,6 +379,3 @@
}
return true;
}
-
-} // end namespace tooling
-} // end namespace clang
diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp
index 7ae2950..0644066 100644
--- a/lib/Tooling/Tooling.cpp
+++ b/lib/Tooling/Tooling.cpp
@@ -1,4 +1,4 @@
-//===--- Tooling.cpp - Running clang standalone tools ---------------------===//
+//===- Tooling.cpp - Running clang standalone tools -----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,90 +13,114 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/Tooling.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CompilationDatabase.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
-#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstring>
+#include <memory>
+#include <string>
+#include <system_error>
#include <utility>
+#include <vector>
#define DEBUG_TYPE "clang-tooling"
-namespace clang {
-namespace tooling {
+using namespace clang;
+using namespace tooling;
-ToolAction::~ToolAction() {}
+ToolAction::~ToolAction() = default;
-FrontendActionFactory::~FrontendActionFactory() {}
+FrontendActionFactory::~FrontendActionFactory() = default;
// FIXME: This file contains structural duplication with other parts of the
// code that sets up a compiler to run tools on it, and we should refactor
// it to be based on the same framework.
/// \brief Builds a clang driver initialized for running clang tools.
-static clang::driver::Driver *newDriver(
- clang::DiagnosticsEngine *Diagnostics, const char *BinaryName,
+static driver::Driver *newDriver(
+ DiagnosticsEngine *Diagnostics, const char *BinaryName,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
- clang::driver::Driver *CompilerDriver =
- new clang::driver::Driver(BinaryName, llvm::sys::getDefaultTargetTriple(),
- *Diagnostics, std::move(VFS));
+ driver::Driver *CompilerDriver =
+ new driver::Driver(BinaryName, llvm::sys::getDefaultTargetTriple(),
+ *Diagnostics, std::move(VFS));
CompilerDriver->setTitle("clang_based_tool");
return CompilerDriver;
}
/// \brief Retrieves the clang CC1 specific flags out of the compilation's jobs.
///
-/// Returns NULL on error.
+/// Returns nullptr on error.
static const llvm::opt::ArgStringList *getCC1Arguments(
- clang::DiagnosticsEngine *Diagnostics,
- clang::driver::Compilation *Compilation) {
+ DiagnosticsEngine *Diagnostics, driver::Compilation *Compilation) {
// We expect to get back exactly one Command job, if we didn't something
// failed. Extract that job from the Compilation.
- const clang::driver::JobList &Jobs = Compilation->getJobs();
- if (Jobs.size() != 1 || !isa<clang::driver::Command>(*Jobs.begin())) {
+ const driver::JobList &Jobs = Compilation->getJobs();
+ if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
SmallString<256> error_msg;
llvm::raw_svector_ostream error_stream(error_msg);
Jobs.Print(error_stream, "; ", true);
- Diagnostics->Report(clang::diag::err_fe_expected_compiler_job)
+ Diagnostics->Report(diag::err_fe_expected_compiler_job)
<< error_stream.str();
return nullptr;
}
// The one job we find should be to invoke clang again.
- const clang::driver::Command &Cmd =
- cast<clang::driver::Command>(*Jobs.begin());
+ const auto &Cmd = cast<driver::Command>(*Jobs.begin());
if (StringRef(Cmd.getCreator().getName()) != "clang") {
- Diagnostics->Report(clang::diag::err_fe_expected_clang_command);
+ Diagnostics->Report(diag::err_fe_expected_clang_command);
return nullptr;
}
return &Cmd.getArguments();
}
+namespace clang {
+namespace tooling {
+
/// \brief Returns a clang build invocation initialized from the CC1 flags.
-clang::CompilerInvocation *newInvocation(
- clang::DiagnosticsEngine *Diagnostics,
- const llvm::opt::ArgStringList &CC1Args) {
+CompilerInvocation *newInvocation(
+ DiagnosticsEngine *Diagnostics, const llvm::opt::ArgStringList &CC1Args) {
assert(!CC1Args.empty() && "Must at least contain the program name!");
- clang::CompilerInvocation *Invocation = new clang::CompilerInvocation;
- clang::CompilerInvocation::CreateFromArgs(
+ CompilerInvocation *Invocation = new CompilerInvocation;
+ CompilerInvocation::CreateFromArgs(
*Invocation, CC1Args.data() + 1, CC1Args.data() + CC1Args.size(),
*Diagnostics);
Invocation->getFrontendOpts().DisableFree = false;
@@ -104,7 +128,7 @@
return Invocation;
}
-bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
+bool runToolOnCode(FrontendAction *ToolAction, const Twine &Code,
const Twine &FileName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
return runToolOnCodeWithArgs(ToolAction, Code, std::vector<std::string>(),
@@ -112,6 +136,9 @@
std::move(PCHContainerOps));
}
+} // namespace tooling
+} // namespace clang
+
static std::vector<std::string>
getSyntaxOnlyToolArgs(const Twine &ToolName,
const std::vector<std::string> &ExtraArgs,
@@ -124,13 +151,15 @@
return Args;
}
+namespace clang {
+namespace tooling {
+
bool runToolOnCodeWithArgs(
- clang::FrontendAction *ToolAction, const Twine &Code,
+ FrontendAction *ToolAction, const Twine &Code,
const std::vector<std::string> &Args, const Twine &FileName,
const Twine &ToolName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
const FileContentMappings &VirtualMappedFiles) {
-
SmallString<16> FileNameStorage;
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
@@ -190,7 +219,7 @@
TokenRef.startswith("--driver-mode="));
}
auto TargetMode =
- clang::driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs);
+ driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs);
if (!AlreadyHasMode && TargetMode.DriverMode) {
CommandLine.insert(++CommandLine.begin(), TargetMode.DriverMode);
}
@@ -201,6 +230,9 @@
}
}
+} // namespace tooling
+} // namespace clang
+
namespace {
class SingleFrontendActionFactory : public FrontendActionFactory {
@@ -212,22 +244,20 @@
FrontendAction *create() override { return Action; }
};
-}
+} // namespace
ToolInvocation::ToolInvocation(
std::vector<std::string> CommandLine, ToolAction *Action,
FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: CommandLine(std::move(CommandLine)), Action(Action), OwnsAction(false),
- Files(Files), PCHContainerOps(std::move(PCHContainerOps)),
- DiagConsumer(nullptr) {}
+ Files(Files), PCHContainerOps(std::move(PCHContainerOps)) {}
ToolInvocation::ToolInvocation(
std::vector<std::string> CommandLine, FrontendAction *FAction,
FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: CommandLine(std::move(CommandLine)),
Action(new SingleFrontendActionFactory(FAction)), OwnsAction(true),
- Files(Files), PCHContainerOps(std::move(PCHContainerOps)),
- DiagConsumer(nullptr) {}
+ Files(Files), PCHContainerOps(std::move(PCHContainerOps)) {}
ToolInvocation::~ToolInvocation() {
if (OwnsAction)
@@ -254,23 +284,22 @@
TextDiagnosticPrinter DiagnosticPrinter(
llvm::errs(), &*DiagOpts);
DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false);
- const std::unique_ptr<clang::driver::Driver> Driver(
+ const std::unique_ptr<driver::Driver> Driver(
newDriver(&Diagnostics, BinaryName, Files->getVirtualFileSystem()));
// Since the input might only be virtual, don't check whether it exists.
Driver->setCheckInputsExist(false);
- const std::unique_ptr<clang::driver::Compilation> Compilation(
+ const std::unique_ptr<driver::Compilation> Compilation(
Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
if (!Compilation)
return false;
const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
&Diagnostics, Compilation.get());
- if (!CC1Args) {
+ if (!CC1Args)
return false;
- }
- std::unique_ptr<clang::CompilerInvocation> Invocation(
+ std::unique_ptr<CompilerInvocation> Invocation(
newInvocation(&Diagnostics, *CC1Args));
// FIXME: remove this when all users have migrated!
for (const auto &It : MappedFileContents) {
@@ -285,8 +314,8 @@
}
bool ToolInvocation::runInvocation(
- const char *BinaryName, clang::driver::Compilation *Compilation,
- std::shared_ptr<clang::CompilerInvocation> Invocation,
+ const char *BinaryName, driver::Compilation *Compilation,
+ std::shared_ptr<CompilerInvocation> Invocation,
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
// Show the invocation, with -v.
if (Invocation->getHeaderSearchOpts().Verbose) {
@@ -304,7 +333,7 @@
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) {
// Create a compiler instance to handle the actual work.
- clang::CompilerInstance Compiler(std::move(PCHContainerOps));
+ CompilerInstance Compiler(std::move(PCHContainerOps));
Compiler.setInvocation(std::move(Invocation));
Compiler.setFileManager(Files);
@@ -332,17 +361,16 @@
IntrusiveRefCntPtr<vfs::FileSystem> BaseFS)
: Compilations(Compilations), SourcePaths(SourcePaths),
PCHContainerOps(std::move(PCHContainerOps)),
- OverlayFileSystem(new vfs::OverlayFileSystem(BaseFS)),
+ OverlayFileSystem(new vfs::OverlayFileSystem(std::move(BaseFS))),
InMemoryFileSystem(new vfs::InMemoryFileSystem),
- Files(new FileManager(FileSystemOptions(), OverlayFileSystem)),
- DiagConsumer(nullptr) {
+ Files(new FileManager(FileSystemOptions(), OverlayFileSystem)) {
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
appendArgumentsAdjuster(getClangStripOutputAdjuster());
appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster());
appendArgumentsAdjuster(getClangStripDependencyFileAdjuster());
}
-ClangTool::~ClangTool() {}
+ClangTool::~ClangTool() = default;
void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
MappedFileContents.push_back(std::make_pair(FilePath, Content));
@@ -491,13 +519,17 @@
return true;
}
};
-}
+
+} // namespace
int ClangTool::buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs) {
ASTBuilderAction Action(ASTs);
return run(&Action);
}
+namespace clang {
+namespace tooling {
+
std::unique_ptr<ASTUnit>
buildASTFromCode(const Twine &Code, const Twine &FileName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
@@ -538,5 +570,5 @@
return std::move(ASTs[0]);
}
-} // end namespace tooling
-} // end namespace clang
+} // namespace tooling
+} // namespace clang
diff --git a/test/Analysis/Inputs/system-header-simulator-for-nullability-cxx.h b/test/Analysis/Inputs/system-header-simulator-for-nullability-cxx.h
new file mode 100644
index 0000000..fe620c9
--- /dev/null
+++ b/test/Analysis/Inputs/system-header-simulator-for-nullability-cxx.h
@@ -0,0 +1,9 @@
+#pragma clang system_header
+
+struct S {
+ ~S(){}
+};
+
+void foo() {
+ S s;
+}
diff --git a/test/Analysis/Inputs/system-header-simulator-for-nullability.h b/test/Analysis/Inputs/system-header-simulator-for-nullability.h
index 8d49f32..5c28269 100644
--- a/test/Analysis/Inputs/system-header-simulator-for-nullability.h
+++ b/test/Analysis/Inputs/system-header-simulator-for-nullability.h
@@ -32,6 +32,8 @@
@interface NSString : NSObject<NSCopying>
- (BOOL)isEqualToString : (NSString *)aString;
- (NSString *)stringByAppendingString:(NSString *)aString;
++ (_Nonnull NSString *) generateString;
++ (_Nullable NSString *) generatePossiblyNullString;
@end
void NSSystemFunctionTakingNonnull(NSString *s);
@@ -40,4 +42,11 @@
- (void) takesNonnull:(NSString *)s;
@end
+NSString* _Nullable getPossiblyNullString();
+NSString* _Nonnull getString();
+
+@protocol MyProtocol
+- (_Nonnull NSString *) getString;
+@end
+
NS_ASSUME_NONNULL_END
diff --git a/test/Analysis/NewDelete-atomics.cpp b/test/Analysis/NewDelete-atomics.cpp
index 275cf14..54fce17 100644
--- a/test/Analysis/NewDelete-atomics.cpp
+++ b/test/Analysis/NewDelete-atomics.cpp
@@ -2,6 +2,10 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
// expected-no-diagnostics
@@ -51,7 +55,7 @@
delete Ptr;
}
- Obj *getPtr() const { return Ptr; }
+ Obj *getPtr() const { return Ptr; } // no-warning
};
void testDestroyLocalRefPtr() {
diff --git a/test/Analysis/analyzer-config.c b/test/Analysis/analyzer-config.c
index 4acbad4..40f86e1 100644
--- a/test/Analysis/analyzer-config.c
+++ b/test/Analysis/analyzer-config.c
@@ -16,6 +16,7 @@
// CHECK-NEXT: cfg-lifetime = false
// CHECK-NEXT: cfg-loopexit = false
// CHECK-NEXT: cfg-rich-constructors = true
+// CHECK-NEXT: cfg-scopes = false
// CHECK-NEXT: cfg-temporary-dtors = true
// CHECK-NEXT: exploration_strategy = unexplored_first_queue
// CHECK-NEXT: faux-bodies = true
@@ -34,4 +35,4 @@
// CHECK-NEXT: unroll-loops = false
// CHECK-NEXT: widen-loops = false
// CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 22
+// CHECK-NEXT: num-entries = 23
diff --git a/test/Analysis/analyzer-config.cpp b/test/Analysis/analyzer-config.cpp
index 0ab1077..888cd77 100644
--- a/test/Analysis/analyzer-config.cpp
+++ b/test/Analysis/analyzer-config.cpp
@@ -23,13 +23,14 @@
// CHECK-NEXT: c++-inlining = destructors
// CHECK-NEXT: c++-shared_ptr-inlining = false
// CHECK-NEXT: c++-stdlib-inlining = true
-// CHECK-NEXT: c++-temp-dtor-inlining = false
+// CHECK-NEXT: c++-temp-dtor-inlining = true
// CHECK-NEXT: c++-template-inlining = true
// CHECK-NEXT: cfg-conditional-static-initializers = true
// CHECK-NEXT: cfg-implicit-dtors = true
// CHECK-NEXT: cfg-lifetime = false
// CHECK-NEXT: cfg-loopexit = false
// CHECK-NEXT: cfg-rich-constructors = true
+// CHECK-NEXT: cfg-scopes = false
// CHECK-NEXT: cfg-temporary-dtors = true
// CHECK-NEXT: experimental-enable-naive-ctu-analysis = false
// CHECK-NEXT: exploration_strategy = unexplored_first_queue
@@ -49,4 +50,4 @@
// CHECK-NEXT: unroll-loops = false
// CHECK-NEXT: widen-loops = false
// CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 29
+// CHECK-NEXT: num-entries = 30
diff --git a/test/Analysis/autoreleasewritechecker_test.m b/test/Analysis/autoreleasewritechecker_test.m
new file mode 100644
index 0000000..6b01ad8
--- /dev/null
+++ b/test/Analysis/autoreleasewritechecker_test.m
@@ -0,0 +1,173 @@
+// UNSUPPORTED: system-windows
+// RUN: %clang_analyze_cc1 -DARC -fobjc-arc -analyzer-checker=core,osx.cocoa.AutoreleaseWrite %s -triple x86_64-darwin -fblocks -verify
+// RUN: %clang_analyze_cc1 -DNOARC -analyzer-checker=core,osx.cocoa.AutoreleaseWrite %s -fblocks -triple x86_64-darwin -verify
+
+
+typedef signed char BOOL;
+@protocol NSObject - (BOOL)isEqual:(id)object; @end
+@interface NSObject <NSObject> {}
++(id)alloc;
+-(id)init;
+-(id)autorelease;
+-(id)copy;
+-(id)retain;
+@end
+typedef int NSZone;
+typedef int NSCoder;
+@protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end
+@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end
+@interface NSError : NSObject <NSCopying, NSCoding> {}
++ (id)errorWithDomain:(int)domain;
+@end
+
+typedef int dispatch_semaphore_t;
+typedef void (^block_t)();
+
+@interface NSArray
+- (void) enumerateObjectsUsingBlock:(block_t)block;
+@end
+
+typedef int group_t;
+typedef struct dispatch_queue_s *dispatch_queue_t;
+typedef void (^dispatch_block_t)(void);
+extern dispatch_queue_t queue;
+
+void dispatch_group_async(dispatch_queue_t queue,
+ group_t group,
+ dispatch_block_t block);
+void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
+dispatch_semaphore_t dispatch_semaphore_create(int);
+
+void dispatch_semaphore_wait(dispatch_semaphore_t, int);
+void dispatch_semaphore_signal(dispatch_semaphore_t);
+
+// No warnings without ARC.
+#ifdef NOARC
+
+// expected-no-diagnostics
+BOOL writeToErrorWithIterator(NSError ** error, NSArray *a) {
+ [a enumerateObjectsUsingBlock:^{
+ *error = [NSError errorWithDomain:1]; // no-warning
+ }];
+ return 0;
+}
+#endif
+
+#ifdef ARC
+@interface I : NSObject
+- (BOOL) writeToStrongErrorInBlock:(NSError *__strong *)error;
+- (BOOL) writeToErrorInBlock:(NSError *__autoreleasing *)error;
+- (BOOL) writeToLocalErrorInBlock:(NSError **)error;
+- (BOOL) writeToErrorInBlockMultipleTimes:(NSError *__autoreleasing *)error;
+- (BOOL) writeToError:(NSError *__autoreleasing *)error;
+- (BOOL) writeToErrorWithDispatchGroup:(NSError *__autoreleasing *)error;
+@end
+
+@implementation I
+
+- (BOOL) writeToErrorInBlock:(NSError *__autoreleasing *)error {
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
+ dispatch_async(queue, ^{
+ if (error) {
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out parameter inside autorelease pool that may exit before method returns}}
+ }
+ dispatch_semaphore_signal(sem);
+ });
+
+ dispatch_semaphore_wait(sem, 100);
+ return 0;
+}
+
+- (BOOL) writeToErrorWithDispatchGroup:(NSError *__autoreleasing *)error {
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
+ dispatch_group_async(queue, 0, ^{
+ if (error) {
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out}}
+ }
+ dispatch_semaphore_signal(sem);
+ });
+
+ dispatch_semaphore_wait(sem, 100);
+ return 0;
+}
+
+- (BOOL) writeToLocalErrorInBlock:(NSError *__autoreleasing *)error {
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
+ dispatch_async(queue, ^{
+ NSError* error2;
+ NSError*__strong* error3 = &error2;
+ if (error) {
+ *error3 = [NSError errorWithDomain:1]; // no-warning
+ }
+ dispatch_semaphore_signal(sem);
+ });
+
+ dispatch_semaphore_wait(sem, 100);
+ return 0;
+}
+
+- (BOOL) writeToStrongErrorInBlock:(NSError *__strong *)error {
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
+ dispatch_async(queue, ^{
+ if (error) {
+ *error = [NSError errorWithDomain:2]; // no-warning
+ }
+ dispatch_semaphore_signal(sem);
+ });
+
+ dispatch_semaphore_wait(sem, 100);
+ return 0;
+}
+
+- (BOOL) writeToErrorInBlockMultipleTimes:(NSError *__autoreleasing *)error {
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
+ dispatch_async(queue, ^{
+ if (error) {
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out}}
+ }
+ dispatch_semaphore_signal(sem);
+ });
+ dispatch_async(queue, ^{
+ if (error) {
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out}}
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out}}
+ }
+ dispatch_semaphore_signal(sem);
+ });
+ *error = [NSError errorWithDomain:1]; // no-warning
+
+ dispatch_semaphore_wait(sem, 100);
+ return 0;
+}
+
+- (BOOL) writeToError:(NSError *__autoreleasing *)error {
+ *error = [NSError errorWithDomain:1]; // no-warning
+ return 0;
+}
+@end
+
+BOOL writeToErrorInBlockFromCFunc(NSError *__autoreleasing* error) {
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
+ dispatch_async(queue, ^{
+ if (error) {
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out}}
+ }
+ dispatch_semaphore_signal(sem);
+ });
+
+ dispatch_semaphore_wait(sem, 100);
+ return 0;
+}
+
+BOOL writeToErrorNoWarning(NSError *__autoreleasing* error) {
+ *error = [NSError errorWithDomain:1]; // no-warning
+ return 0;
+}
+
+BOOL writeToErrorWithIterator(NSError *__autoreleasing* error, NSArray *a) {
+ [a enumerateObjectsUsingBlock:^{
+ *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}}
+ }];
+ return 0;
+}
+#endif
diff --git a/test/Analysis/cfg-rich-constructors.cpp b/test/Analysis/cfg-rich-constructors.cpp
index 2ae33d3..51eca12 100644
--- a/test/Analysis/cfg-rich-constructors.cpp
+++ b/test/Analysis/cfg-rich-constructors.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -analyzer-config cfg-temporary-dtors=true -std=c++11 -w %s > %t 2>&1
-// RUN: FileCheck --input-file=%t %s
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11 %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -analyzer-config cfg-temporary-dtors=true -std=c++17 -w %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX17 %s
class C {
public:
@@ -97,33 +99,42 @@
// CHECK: void simpleVariableInitializedByValue()
// CHECK: 1: C::get
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
-// CHECK-NEXT: 3: [B1.2]()
-// CHECK-NEXT: 4: [B1.3]
-// CHECK-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], class C)
-// CHECK-NEXT: 6: C c = C::get();
+// CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4])
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], class C)
+// CXX11-NEXT: 6: C c = C::get();
+// CXX17-NEXT: 4: C c = C::get();
void simpleVariableInitializedByValue() {
C c = C::get();
}
+// FIXME: Find construction contexts for both branches in C++17.
+// Note that once it gets detected, the test for the get() branch would not
+// fail, because FileCheck allows partial matches.
// CHECK: void simpleVariableWithTernaryOperator(bool coin)
// CHECK: [B1]
-// CHECK-NEXT: 1: [B4.2] ? [B2.5] : [B3.6]
-// CHECK-NEXT: 2: [B1.1]
-// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.4], class C)
-// CHECK-NEXT: 4: C c = coin ? C::get() : C(0);
+// CXX11-NEXT: 1: [B4.2] ? [B2.5] : [B3.6]
+// CXX11-NEXT: 2: [B1.1]
+// CXX11-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.4], class C)
+// CXX11-NEXT: 4: C c = coin ? C::get() : C(0);
+// CXX17-NEXT: 1: [B4.2] ? [B2.3] : [B3.4]
+// CXX17-NEXT: 2: C c = coin ? C::get() : C(0);
// CHECK: [B2]
// CHECK-NEXT: 1: C::get
// CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
-// CHECK-NEXT: 3: [B2.2]()
-// CHECK-NEXT: 4: [B2.3]
-// CHECK-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.2], class C)
+// CXX11-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4])
+// CXX11-NEXT: 4: [B2.3]
+// CXX11-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.2], class C)
+// CXX17-NEXT: 3: [B2.2]()
// CHECK: [B3]
// CHECK-NEXT: 1: 0
// CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *)
-// CHECK-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C)
-// CHECK-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
-// CHECK-NEXT: 5: [B3.4]
-// CHECK-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.2], class C)
+// CXX11-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C)
+// CXX11-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
+// CXX11-NEXT: 5: [B3.4]
+// CXX11-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.2], class C)
+// CXX17-NEXT: 3: [B3.2] (CXXConstructExpr, class C)
+// CXX17-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
// CHECK: [B4]
// CHECK-NEXT: 1: coin
// CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool)
@@ -137,9 +148,10 @@
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *)
// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C)
// CHECK-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
-// CHECK-NEXT: 5: [B1.4]
-// CHECK-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C)
-// CHECK-NEXT: 7: C c = C(0);
+// CXX11-NEXT: 5: [B1.4]
+// CXX11-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C)
+// CXX11-NEXT: 7: C c = C(0);
+// CXX17-NEXT: 5: C c = C(0);
void simpleVariableWithElidableCopy() {
C c = C(0);
}
@@ -165,23 +177,27 @@
// CHECK: void referenceVariableWithTernaryOperator(bool coin)
// CHECK: [B1]
-// CHECK-NEXT: 1: [B4.2] ? [B2.5] : [B3.6]
+// CXX11-NEXT: 1: [B4.2] ? [B2.5] : [B3.6]
+// CXX17-NEXT: 1: [B4.2] ? [B2.3] : [B3.4]
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class C)
// CHECK-NEXT: 3: [B1.2]
// CHECK-NEXT: 4: const C &c = coin ? C::get() : C(0);
// CHECK: [B2]
// CHECK-NEXT: 1: C::get
// CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
-// CHECK-NEXT: 3: [B2.2]()
-// CHECK-NEXT: 4: [B2.3]
-// CHECK-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.3], class C)
+// CXX11-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4])
+// CXX11-NEXT: 4: [B2.3]
+// CXX11-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.3], class C)
+// CXX17-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B1.3])
// CHECK: [B3]
// CHECK-NEXT: 1: 0
// CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *)
-// CHECK-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C)
-// CHECK-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
-// CHECK-NEXT: 5: [B3.4]
-// CHECK-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.3], class C)
+// CXX11-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C)
+// CXX11-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
+// CXX11-NEXT: 5: [B3.4]
+// CXX11-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.3], class C)
+// CXX17-NEXT: 3: [B3.2] (CXXConstructExpr, [B1.3], class C)
+// CXX17-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
// CHECK: [B4]
// CHECK-NEXT: 1: coin
// CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool)
@@ -214,25 +230,59 @@
// CHECK-NEXT: 2: D([B1.1]) (Delegating initializer)
D(int): D() {}
+// FIXME: Why is CXXRecordTypedCall not present in C++17? Note that once it gets
+// detected the test would not fail, because FileCheck allows partial matches.
// CHECK: D(double)
// CHECK: 1: C::get
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
-// CHECK-NEXT: 3: [B1.2]()
+// CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4])
// CHECK-NEXT: 4: [B1.3]
// CHECK-NEXT: 5: [B1.4] (CXXConstructExpr, C([B1.4]) (Base initializer), class C)
// CHECK-NEXT: 6: C([B1.5]) (Base initializer)
// CHECK-NEXT: 7: CFGNewAllocator(C *)
// CHECK-NEXT: 8: C::get
// CHECK-NEXT: 9: [B1.8] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
-// CHECK-NEXT: 10: [B1.9]()
-// CHECK-NEXT: 11: [B1.10]
-// CHECK-NEXT: 12: [B1.11] (CXXConstructExpr, [B1.13], class C)
-// CHECK-NEXT: 13: new C([B1.12])
-// CHECK-NEXT: 14: [B1.13] (CXXConstructExpr, c1([B1.13]) (Member initializer), class C)
-// CHECK-NEXT: 15: c1([B1.14]) (Member initializer)
+// CXX11-NEXT: 10: [B1.9]() (CXXRecordTypedCall, [B1.11])
+// CXX11-NEXT: 11: [B1.10]
+// CXX11-NEXT: 12: [B1.11] (CXXConstructExpr, [B1.13], class C)
+// CXX11-NEXT: 13: new C([B1.12])
+// CXX11-NEXT: 14: [B1.13] (CXXConstructExpr, c1([B1.13]) (Member initializer), class C)
+// CXX11-NEXT: 15: c1([B1.14]) (Member initializer)
+// CXX17-NEXT: 10: [B1.9]()
+// CXX17-NEXT: 11: new C([B1.10])
+// CXX17-NEXT: 12: [B1.11] (CXXConstructExpr, c1([B1.11]) (Member initializer), class C)
+// CXX17-NEXT: 13: c1([B1.12]) (Member initializer)
D(double): C(C::get()), c1(new C(C::get())) {}
};
+// Let's see if initializers work well for fields with destructors.
+class E {
+public:
+ static E get();
+ ~E();
+};
+
+class F {
+ E e;
+
+public:
+// FIXME: There should be no temporary destructor in C++17.
+// CHECK: F()
+// CHECK: 1: E::get
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class ctor_initializers::E (*)(
+// CXX11-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6])
+// CXX11-NEXT: 4: [B1.3] (BindTemporary)
+// CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class ctor_initializers::E)
+// CXX11-NEXT: 6: [B1.5]
+// CXX11-NEXT: 7: [B1.6] (CXXConstructExpr, e([B1.6]) (Member initializer), class ctor_initializers
+// CXX11-NEXT: 8: e([B1.7]) (Member initializer)
+// CXX11-NEXT: 9: ~ctor_initializers::E() (Temporary object destructor)
+// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, e([B1.4]) (Member initializer), [B1.4])
+// CXX17-NEXT: 4: [B1.3] (BindTemporary)
+// CXX17-NEXT: 5: e([B1.4]) (Member initializer)
+// CXX17-NEXT: 6: ~ctor_initializers::E() (Temporary object destructor)
+ F(): e(E::get()) {}
+};
} // end namespace ctor_initializers
namespace return_stmt_without_dtor {
@@ -277,9 +327,10 @@
// CHECK: C returnTemporary()
// CHECK: 1: C() (CXXConstructExpr, [B1.2], class C)
-// CHECK-NEXT: 2: [B1.1]
-// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.4], class C)
-// CHECK-NEXT: 4: return [B1.3];
+// CXX11-NEXT: 2: [B1.1]
+// CXX11-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.4], class C)
+// CXX11-NEXT: 4: return [B1.3];
+// CXX17-NEXT: 2: return [B1.1];
C returnTemporary() {
return C();
}
@@ -289,9 +340,11 @@
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *)
// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C)
// CHECK-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
-// CHECK-NEXT: 5: [B1.4]
-// CHECK-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C)
-// CHECK-NEXT: 7: return [B1.6];
+// CXX11-NEXT: 5: [B1.4]
+// CXX11-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C)
+// CXX11-NEXT: 7: return [B1.6];
+// CXX17-NEXT: 5: return [B1.4];
+
C returnTemporaryWithArgument() {
return C(nullptr);
}
@@ -299,10 +352,11 @@
// CHECK: C returnTemporaryConstructedByFunction()
// CHECK: 1: C::get
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
-// CHECK-NEXT: 3: [B1.2]()
-// CHECK-NEXT: 4: [B1.3]
-// CHECK-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], class C)
-// CHECK-NEXT: 6: return [B1.5];
+// CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4])
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], class C)
+// CXX11-NEXT: 6: return [B1.5];
+// CXX17-NEXT: 4: return [B1.3];
C returnTemporaryConstructedByFunction() {
return C::get();
}
@@ -310,13 +364,16 @@
// CHECK: C returnChainOfCopies()
// CHECK: 1: C::get
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
-// CHECK-NEXT: 3: [B1.2]()
-// CHECK-NEXT: 4: [B1.3]
-// CHECK-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], class C)
-// CHECK-NEXT: 6: C([B1.5]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
-// CHECK-NEXT: 7: [B1.6]
-// CHECK-NEXT: 8: [B1.7] (CXXConstructExpr, [B1.9], class C)
-// CHECK-NEXT: 9: return [B1.8];
+// CXX11-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4])
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], class C)
+// CXX11-NEXT: 6: C([B1.5]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
+// CXX11-NEXT: 7: [B1.6]
+// CXX11-NEXT: 8: [B1.7] (CXXConstructExpr, [B1.9], class C)
+// CXX11-NEXT: 9: return [B1.8];
+// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.5])
+// CXX17-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, NoOp, class C)
+// CXX17-NEXT: 5: return [B1.4];
C returnChainOfCopies() {
return C(C::get());
}
@@ -331,18 +388,44 @@
~D();
};
+// FIXME: There should be no temporary destructor in C++17.
// CHECK: return_stmt_with_dtor::D returnTemporary()
-// CHECK: 1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.2], [B1.4], class return_stmt_with_dtor::D)
-// CHECK-NEXT: 2: [B1.1] (BindTemporary)
-// CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class return_stmt_with_dtor::D)
-// CHECK-NEXT: 4: [B1.3]
-// CHECK-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], class return_stmt_with_dtor::D)
-// CHECK-NEXT: 6: ~return_stmt_with_dtor::D() (Temporary object destructor)
-// CHECK-NEXT: 7: return [B1.5];
+// CXX11: 1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.2], [B1.4], class return_stmt_with_dtor::D)
+// CXX11-NEXT: 2: [B1.1] (BindTemporary)
+// CXX11-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class return_stmt_with_dtor::D)
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], class return_stmt_with_dtor::D)
+// CXX11-NEXT: 6: ~return_stmt_with_dtor::D() (Temporary object destructor)
+// CXX11-NEXT: 7: return [B1.5];
+// CXX17: 1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.4], [B1.2], class return_stmt_w
+// CXX17-NEXT: 2: [B1.1] (BindTemporary)
+// CXX17-NEXT: 3: ~return_stmt_with_dtor::D() (Temporary object destructor)
+// CXX17-NEXT: 4: return [B1.2];
D returnTemporary() {
return D();
}
+// FIXME: There should be no temporary destructor in C++17.
+// CHECK: void returnByValueIntoVariable()
+// CHECK: 1: returnTemporary
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class return_stmt_with_dtor::D (*)(void))
+// CXX11-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6])
+// CXX11-NEXT: 4: [B1.3] (BindTemporary)
+// CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class return_stmt_with_dtor::D)
+// CXX11-NEXT: 6: [B1.5]
+// CXX11-NEXT: 7: [B1.6] (CXXConstructExpr, [B1.8], class return_stmt_with_dtor::D)
+// CXX11-NEXT: 8: return_stmt_with_dtor::D d = returnTemporary();
+// CXX11-NEXT: 9: ~return_stmt_with_dtor::D() (Temporary object destructor)
+// CXX11-NEXT: 10: [B1.8].~D() (Implicit destructor)
+// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.5], [B1.4])
+// CXX17-NEXT: 4: [B1.3] (BindTemporary)
+// CXX17-NEXT: 5: return_stmt_with_dtor::D d = returnTemporary();
+// CXX17-NEXT: 6: ~return_stmt_with_dtor::D() (Temporary object destructor)
+// CXX17-NEXT: 7: [B1.5].~D() (Implicit destructor)
+void returnByValueIntoVariable() {
+ D d = returnTemporary();
+}
+
} // end namespace return_stmt_with_dtor
namespace temporary_object_expr_without_dtors {
@@ -426,34 +509,60 @@
}
// CHECK: void referenceVariableWithTernaryOperator(bool coin)
-// CHECK: [B4]
-// CHECK-NEXT: 1: [B7.2] ? [B5.8] : [B6.8]
-// CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
-// CHECK-NEXT: 3: [B4.2]
-// CHECK-NEXT: 4: const temporary_object_expr_with_dtors::D &d = coin ? D::get() : temporary_object_expr_with_dtors::D(0);
-// CHECK-NEXT: T: (Temp Dtor) [B6.3]
-// CHECK: [B5]
-// CHECK-NEXT: 1: D::get
-// CHECK-NEXT: 2: [B5.1] (ImplicitCastExpr, FunctionToPointerDecay, class temporary_object_expr_with_dtors::D (*)(void))
-// CHECK-NEXT: 3: [B5.2]()
-// CHECK-NEXT: 4: [B5.3] (BindTemporary)
-// CHECK-NEXT: 5: [B5.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
-// CHECK-NEXT: 6: [B5.5]
-// CHECK-NEXT: 7: [B5.6] (CXXConstructExpr, [B5.8], [B4.3], class temporary_object_expr_with_dtors::D)
-// CHECK-NEXT: 8: [B5.7] (BindTemporary)
-// CHECK: [B6]
-// CHECK-NEXT: 1: 0
-// CHECK-NEXT: 2: [B6.1] (CXXConstructExpr, [B6.3], [B6.6], class temporary_object_expr_with_dtors::D)
-// CHECK-NEXT: 3: [B6.2] (BindTemporary)
-// CHECK-NEXT: 4: temporary_object_expr_with_dtors::D([B6.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D)
-// CHECK-NEXT: 5: [B6.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
-// CHECK-NEXT: 6: [B6.5]
-// CHECK-NEXT: 7: [B6.6] (CXXConstructExpr, [B6.8], [B4.3], class temporary_object_expr_with_dtors::D)
-// CHECK-NEXT: 8: [B6.7] (BindTemporary)
-// CHECK: [B7]
-// CHECK-NEXT: 1: coin
-// CHECK-NEXT: 2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
-// CHECK-NEXT: T: [B7.2] ? ... : ...
+// CXX11: [B1]
+// CXX11-NEXT: 1: [B4.4].~D() (Implicit destructor)
+// CXX11: [B2]
+// CXX11-NEXT: 1: ~temporary_object_expr_with_dtors::D() (Temporary object destructor)
+// CXX11: [B3]
+// CXX11-NEXT: 1: ~temporary_object_expr_with_dtors::D() (Temporary object destructor)
+// CXX11: [B4]
+// CXX11-NEXT: 1: [B7.2] ? [B5.8] : [B6.8]
+// CXX11-NEXT: 2: [B4.1] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 3: [B4.2]
+// CXX11-NEXT: 4: const temporary_object_expr_with_dtors::D &d = coin ? D::get() : temporary_object_expr_with_dtors::D(0);
+// CXX11-NEXT: T: (Temp Dtor) [B6.3]
+// CXX11: [B5]
+// CXX11-NEXT: 1: D::get
+// CXX11-NEXT: 2: [B5.1] (ImplicitCastExpr, FunctionToPointerDecay, class temporary_object_expr_with_dtors::D (*)(void))
+// CXX11-NEXT: 3: [B5.2]() (CXXRecordTypedCall, [B5.4], [B5.6])
+// CXX11-NEXT: 4: [B5.3] (BindTemporary)
+// CXX11-NEXT: 5: [B5.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 6: [B5.5]
+// CXX11-NEXT: 7: [B5.6] (CXXConstructExpr, [B5.8], [B4.3], class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 8: [B5.7] (BindTemporary)
+// CXX11: [B6]
+// CXX11-NEXT: 1: 0
+// CXX11-NEXT: 2: [B6.1] (CXXConstructExpr, [B6.3], [B6.6], class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 3: [B6.2] (BindTemporary)
+// CXX11-NEXT: 4: temporary_object_expr_with_dtors::D([B6.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 5: [B6.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 6: [B6.5]
+// CXX11-NEXT: 7: [B6.6] (CXXConstructExpr, [B6.8], [B4.3], class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 8: [B6.7] (BindTemporary)
+// CXX11: [B7]
+// CXX11-NEXT: 1: coin
+// CXX11-NEXT: 2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CXX11-NEXT: T: [B7.2] ? ... : ...
+// CXX17: [B1]
+// CXX17-NEXT: 1: [B4.2] ? [B2.4] : [B3.4]
+// CXX17-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CXX17-NEXT: 3: [B1.2]
+// CXX17-NEXT: 4: const temporary_object_expr_with_dtors::D &d = coin ? D::get() : temporary_object_expr_with_dtors::D(0);
+// CXX17-NEXT: 5: [B1.4].~D() (Implicit destructor)
+// CXX17: [B2]
+// CXX17-NEXT: 1: D::get
+// CXX17-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class temporary_object_expr_with_dtors::D (*)(void))
+// CXX17-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4], [B1.3])
+// CXX17-NEXT: 4: [B2.3] (BindTemporary)
+// CXX17: [B3]
+// CXX17-NEXT: 1: 0
+// CXX17-NEXT: 2: [B3.1] (CXXConstructExpr, [B3.3], [B1.3], class temporary_object_expr_with_dtors::D)
+// CXX17-NEXT: 3: [B3.2] (BindTemporary)
+// CXX17-NEXT: 4: temporary_object_expr_with_dtors::D([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D)
+// CXX17: [B4]
+// CXX17-NEXT: 1: coin
+// CXX17-NEXT: 2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CXX17-NEXT: T: [B4.2] ? ... : ...
void referenceVariableWithTernaryOperator(bool coin) {
const D &d = coin ? D::get() : D(0);
}
@@ -472,15 +581,24 @@
// Test the condition constructor, we don't care about branch constructors here.
// CHECK: void constructorInTernaryCondition()
-// CHECK: 1: 1
-// CHECK-NEXT: 2: [B7.1] (CXXConstructExpr, [B7.3], class temporary_object_expr_with_dtors::D)
-// CHECK-NEXT: 3: [B7.2] (BindTemporary)
-// CHECK-NEXT: 4: temporary_object_expr_with_dtors::D([B7.3]) (CXXFunctionalCastExpr, ConstructorConv
-// CHECK-NEXT: 5: [B7.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
-// CHECK-NEXT: 6: [B7.5].operator bool
-// CHECK-NEXT: 7: [B7.5]
-// CHECK-NEXT: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK-NEXT: T: [B7.8] ? ... : ...
+// CXX11: 1: 1
+// CXX11-NEXT: 2: [B7.1] (CXXConstructExpr, [B7.3], class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 3: [B7.2] (BindTemporary)
+// CXX11-NEXT: 4: temporary_object_expr_with_dtors::D([B7.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 5: [B7.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT: 6: [B7.5].operator bool
+// CXX11-NEXT: 7: [B7.5]
+// CXX11-NEXT: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX11-NEXT: T: [B7.8] ? ... : ...
+// CXX17: 1: 1
+// CXX17-NEXT: 2: [B4.1] (CXXConstructExpr, [B4.3], class temporary_object_expr_with_dtors::D)
+// CXX17-NEXT: 3: [B4.2] (BindTemporary)
+// CXX17-NEXT: 4: temporary_object_expr_with_dtors::D([B4.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D)
+// CXX17-NEXT: 5: [B4.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CXX17-NEXT: 6: [B4.5].operator bool
+// CXX17-NEXT: 7: [B4.5]
+// CXX17-NEXT: 8: [B4.7] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX17-NEXT: T: [B4.8] ? ... : ...
void constructorInTernaryCondition() {
const D &d = D(1) ? D(2) : D(3);
}
@@ -498,20 +616,79 @@
~B() {}
};
-// FIXME: Find construction context for the implicit constructor conversion.
+// CHECK: void implicitConstructionConversionFromTemporary()
+// CHECK: 1: implicit_constructor_conversion::A() (CXXConstructExpr, [B1.3], class implicit_constructor_conversion::A)
+// CXX11-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A)
+// CXX11-NEXT: 3: [B1.2]
+// CXX11-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.6], [B1.8], class implicit_constructor_conversion::B)
+// CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B)
+// CXX11-NEXT: 6: [B1.5] (BindTemporary)
+// CXX11-NEXT: 7: [B1.6] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B)
+// CXX11-NEXT: 8: [B1.7]
+// CXX11-NEXT: 9: [B1.8] (CXXConstructExpr, [B1.10], class implicit_constructor_conversion::B)
+// CXX11-NEXT: 10: implicit_constructor_conversion::B b = implicit_constructor_conversion::A();
+// CXX11-NEXT: 11: ~implicit_constructor_conversion::B() (Temporary object destructor)
+// CXX11-NEXT: 12: [B1.10].~B() (Implicit destructor)
+// CXX17-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A)
+// CXX17-NEXT: 3: [B1.2]
+// CXX17-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.6], class implicit_constructor_conversion::B)
+// CXX17-NEXT: 5: [B1.4] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B)
+// CXX17-NEXT: 6: implicit_constructor_conversion::B b = implicit_constructor_conversion::A();
+// CXX17-NEXT: 7: [B1.6].~B() (Implicit destructor)
+void implicitConstructionConversionFromTemporary() {
+ B b = A();
+}
+
// CHECK: void implicitConstructionConversionFromFunctionValue()
// CHECK: 1: get
-// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class implicit_constructor_conver
-// CHECK-NEXT: 3: [B1.2]()
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class implicit_constructor_conversion::A (*)(void))
+// CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.5])
// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A)
// CHECK-NEXT: 5: [B1.4]
-// CHECK-NEXT: 6: [B1.5] (CXXConstructExpr, class implicit_constructor_conversion::B)
+// CXX11-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.8], [B1.10], class implicit_constructor_conversion::B)
+// CXX11-NEXT: 7: [B1.6] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B)
+// CXX11-NEXT: 8: [B1.7] (BindTemporary)
+// CXX11-NEXT: 9: [B1.8] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B)
+// CXX11-NEXT: 10: [B1.9]
+// CXX11-NEXT: 11: [B1.10] (CXXConstructExpr, [B1.12], class implicit_constructor_conversion::B)
+// CXX11-NEXT: 12: implicit_constructor_conversion::B b = get();
+// CXX11-NEXT: 13: ~implicit_constructor_conversion::B() (Temporary object destructor)
+// CXX11-NEXT: 14: [B1.12].~B() (Implicit destructor)
+// CXX17-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.8], class implicit_constructor_conversion::B)
+// CXX17-NEXT: 7: [B1.6] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B)
+// CXX17-NEXT: 8: implicit_constructor_conversion::B b = get();
+// CXX17-NEXT: 9: [B1.8].~B() (Implicit destructor)
+void implicitConstructionConversionFromFunctionValue() {
+ B b = get();
+}
+
+// CHECK: void implicitConstructionConversionFromTemporaryWithLifetimeExtension()
+// CHECK: 1: implicit_constructor_conversion::A() (CXXConstructExpr, [B1.3], class implicit_constructor_conversion::A)
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A)
+// CHECK-NEXT: 3: [B1.2]
+// CHECK-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.7], class implicit_constructor_conversion::B)
+// CHECK-NEXT: 5: [B1.4] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B)
+// CHECK-NEXT: 6: [B1.5] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B)
+// CHECK-NEXT: 7: [B1.6]
+// CHECK-NEXT: 8: const implicit_constructor_conversion::B &b = implicit_constructor_conversion::A();
+// CHECK-NEXT: 9: [B1.8].~B() (Implicit destructor)
+void implicitConstructionConversionFromTemporaryWithLifetimeExtension() {
+ const B &b = A();
+}
+
+// CHECK: void implicitConstructionConversionFromFunctionValueWithLifetimeExtension()
+// CHECK: 1: get
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class implicit_constructor_conver
+// CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.5])
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A)
+// CHECK-NEXT: 5: [B1.4]
+// CHECK-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.9], class implicit_constructor_conversion::B)
// CHECK-NEXT: 7: [B1.6] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_convers
// CHECK-NEXT: 8: [B1.7] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B)
// CHECK-NEXT: 9: [B1.8]
// CHECK-NEXT: 10: const implicit_constructor_conversion::B &b = get();
// CHECK-NEXT: 11: [B1.10].~B() (Implicit destructor)
-void implicitConstructionConversionFromFunctionValue() {
+void implicitConstructionConversionFromFunctionValueWithLifetimeExtension() {
const B &b = get(); // no-crash
}
diff --git a/test/Analysis/cxx17-mandatory-elision.cpp b/test/Analysis/cxx17-mandatory-elision.cpp
new file mode 100644
index 0000000..700888e
--- /dev/null
+++ b/test/Analysis/cxx17-mandatory-elision.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s
+
+void clang_analyzer_eval(bool);
+
+template <typename T> struct AddressVector {
+ T *buf[10];
+ int len;
+
+ AddressVector() : len(0) {}
+
+ void push(T *t) {
+ buf[len] = t;
+ ++len;
+ }
+};
+
+class ClassWithoutDestructor {
+ AddressVector<ClassWithoutDestructor> &v;
+
+public:
+ ClassWithoutDestructor(AddressVector<ClassWithoutDestructor> &v) : v(v) {
+ v.push(this);
+ }
+
+ ClassWithoutDestructor(ClassWithoutDestructor &&c) : v(c.v) { v.push(this); }
+ ClassWithoutDestructor(const ClassWithoutDestructor &c) : v(c.v) {
+ v.push(this);
+ }
+};
+
+ClassWithoutDestructor make1(AddressVector<ClassWithoutDestructor> &v) {
+ return ClassWithoutDestructor(v);
+}
+ClassWithoutDestructor make2(AddressVector<ClassWithoutDestructor> &v) {
+ return make1(v);
+}
+ClassWithoutDestructor make3(AddressVector<ClassWithoutDestructor> &v) {
+ return make2(v);
+}
+
+void testMultipleReturns() {
+ AddressVector<ClassWithoutDestructor> v;
+ ClassWithoutDestructor c = make3(v);
+
+#if __cplusplus >= 201703L
+ // FIXME: Both should be TRUE.
+ clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == &c); // expected-warning{{FALSE}}
+#else
+ clang_analyzer_eval(v.len == 5); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] != v.buf[1]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[1] != v.buf[2]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[2] != v.buf[3]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[3] != v.buf[4]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[4] == &c); // expected-warning{{TRUE}}
+#endif
+}
diff --git a/test/Analysis/explain-svals.cpp b/test/Analysis/explain-svals.cpp
index d4b56a3..ecb5af1 100644
--- a/test/Analysis/explain-svals.cpp
+++ b/test/Analysis/explain-svals.cpp
@@ -94,5 +94,5 @@
void test_6() {
clang_analyzer_explain(conjure_S()); // expected-warning-re{{{{^lazily frozen compound value of temporary object constructed at statement 'conjure_S\(\)'$}}}}
- clang_analyzer_explain(conjure_S().z); // expected-warning-re{{{{^value derived from \(symbol of type 'struct S' conjured at statement 'conjure_S\(\)'\) for field 'z' of temporary object constructed at statement 'conjure_S\(\)'$}}}}
+ clang_analyzer_explain(conjure_S().z); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at statement 'conjure_S\(\)'\) for field 'z' of temporary object constructed at statement 'conjure_S\(\)'$}}}}
}
diff --git a/test/Analysis/gcdantipatternchecker_test.m b/test/Analysis/gcdantipatternchecker_test.m
new file mode 100644
index 0000000..d79a6ba
--- /dev/null
+++ b/test/Analysis/gcdantipatternchecker_test.m
@@ -0,0 +1,335 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.performance.GCDAntipattern %s -fblocks -verify
+typedef signed char BOOL;
+@protocol NSObject - (BOOL)isEqual:(id)object; @end
+@interface NSObject <NSObject> {}
++(id)alloc;
+-(id)init;
+-(id)autorelease;
+-(id)copy;
+-(id)retain;
+@end
+
+typedef int dispatch_semaphore_t;
+typedef int dispatch_group_t;
+typedef void (^block_t)();
+
+dispatch_semaphore_t dispatch_semaphore_create(int);
+dispatch_group_t dispatch_group_create();
+void dispatch_group_enter(dispatch_group_t);
+void dispatch_group_leave(dispatch_group_t);
+void dispatch_group_wait(dispatch_group_t, int);
+
+
+void dispatch_semaphore_wait(dispatch_semaphore_t, int);
+void dispatch_semaphore_signal(dispatch_semaphore_t);
+
+void func(void (^)(void));
+void func_w_typedef(block_t);
+
+int coin();
+
+void use_semaphor_antipattern() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
+
+// It's OK to use pattern in tests.
+// We simply match the containing function name against ^test.
+void test_no_warning() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100);
+}
+
+void use_semaphor_antipattern_multiple_times() {
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema1);
+ });
+ dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+
+ dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema2);
+ });
+ dispatch_semaphore_wait(sema2, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
+
+void use_semaphor_antipattern_multiple_wait() {
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema1);
+ });
+ // FIXME: multiple waits on same semaphor should not raise a warning.
+ dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+ dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
+
+void warn_incorrect_order() {
+ // FIXME: ASTMatchers do not allow ordered matching, so would match even
+ // if out of order.
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+}
+
+void warn_w_typedef() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func_w_typedef(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
+
+void warn_nested_ast() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ if (coin()) {
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ } else {
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ }
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
+
+void use_semaphore_assignment() {
+ dispatch_semaphore_t sema;
+ sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
+
+void use_semaphore_assignment_init() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+ sema = dispatch_semaphore_create(1);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
+
+void differentsemaphoreok() {
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
+ dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema1);
+ });
+ dispatch_semaphore_wait(sema2, 100); // no-warning
+}
+
+void nosignalok() {
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
+ dispatch_semaphore_wait(sema1, 100);
+}
+
+void nowaitok() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+}
+
+void noblockok() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+ dispatch_semaphore_signal(sema);
+ dispatch_semaphore_wait(sema, 100);
+}
+
+void storedblockok() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+ block_t b = ^{
+ dispatch_semaphore_signal(sema);
+ };
+ dispatch_semaphore_wait(sema, 100);
+}
+
+void passed_semaphore_ok(dispatch_semaphore_t sema) {
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100);
+}
+
+void warn_with_cast() {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal((int)sema);
+ });
+ dispatch_semaphore_wait((int)sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
+
+@interface MyInterface1 : NSObject
+-(void)use_method_warn;
+-(void) pass_block_as_second_param_warn;
+-(void)use_objc_callback_warn;
+-(void) use_dispatch_group;
+-(void)testNoWarn;
+-(void)acceptBlock:(block_t)callback;
+-(void)flag:(int)flag acceptBlock:(block_t)callback;
+@end
+
+@implementation MyInterface1
+
+-(void)use_method_warn {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
+
+-(void) pass_block_as_second_param_warn {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ [self flag:1 acceptBlock:^{
+ dispatch_semaphore_signal(sema);
+ }];
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
+
+-(void)testNoWarn {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100);
+}
+
+-(void)acceptBlock:(block_t) callback {
+ callback();
+}
+
+-(void)flag:(int)flag acceptBlock:(block_t)callback {
+ callback();
+}
+
+-(void)use_objc_callback_warn {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ [self acceptBlock:^{
+ dispatch_semaphore_signal(sema);
+ }];
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
+
+-(void)use_dispatch_group {
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_group_enter(group);
+ [self acceptBlock:^{
+ dispatch_group_leave(group);
+ }];
+ dispatch_group_wait(group, 100); // expected-warning{{Waiting on a group with Grand Central Dispatch}}
+
+}
+
+void use_objc_and_c_callback(MyInterface1 *t) {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
+
+ [t acceptBlock:^{
+ dispatch_semaphore_signal(sema1);
+ }];
+ dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
+@end
+
+// No warnings: class name contains "test"
+@interface Test1 : NSObject
+-(void)use_method_warn;
+@end
+
+@implementation Test1
+-(void)use_method_warn {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100);
+}
+@end
+
+
+// No warnings: class name contains "mock"
+@interface Mock1 : NSObject
+-(void)use_method_warn;
+@end
+
+@implementation Mock1
+-(void)use_method_warn {
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+ func(^{
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, 100);
+}
+@end
+
+void dispatch_group_wait_func(MyInterface1 *M) {
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_group_enter(group);
+
+ func(^{
+ dispatch_group_leave(group);
+ });
+ dispatch_group_wait(group, 100); // expected-warning{{Waiting on a group with Grand Central Dispatch}}
+}
+
+
+void dispatch_group_wait_cfunc(MyInterface1 *M) {
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_group_enter(group);
+ [M acceptBlock:^{
+ dispatch_group_leave(group);
+ }];
+ dispatch_group_wait(group, 100); // expected-warning{{Waiting on a group with Grand Central Dispatch}}
+}
+
+void dispatch_group_and_semaphore_use(MyInterface1 *M) {
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_group_enter(group);
+ [M acceptBlock:^{
+ dispatch_group_leave(group);
+ }];
+ dispatch_group_wait(group, 100); // expected-warning{{Waiting on a group with Grand Central Dispatch}}
+
+ dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
+
+ [M acceptBlock:^{
+ dispatch_semaphore_signal(sema1);
+ }];
+ dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}}
+}
diff --git a/test/Analysis/gcdasyncsemaphorechecker_test.m b/test/Analysis/gcdasyncsemaphorechecker_test.m
deleted file mode 100644
index a82545a..0000000
--- a/test/Analysis/gcdasyncsemaphorechecker_test.m
+++ /dev/null
@@ -1,203 +0,0 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.osx.GCDAsyncSemaphore %s -fblocks -verify
-typedef signed char BOOL;
-@protocol NSObject - (BOOL)isEqual:(id)object; @end
-@interface NSObject <NSObject> {}
-+(id)alloc;
--(id)init;
--(id)autorelease;
--(id)copy;
--(id)retain;
-@end
-
-typedef int dispatch_semaphore_t;
-typedef void (^block_t)();
-
-dispatch_semaphore_t dispatch_semaphore_create(int);
-void dispatch_semaphore_wait(dispatch_semaphore_t, int);
-void dispatch_semaphore_signal(dispatch_semaphore_t);
-
-void func(void (^)(void));
-void func_w_typedef(block_t);
-
-int coin();
-
-void use_semaphor_antipattern() {
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
-
- func(^{
- dispatch_semaphore_signal(sema);
- });
- dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
-}
-
-// It's OK to use pattern in tests.
-// We simply match the containing function name against ^test.
-void test_no_warning() {
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
-
- func(^{
- dispatch_semaphore_signal(sema);
- });
- dispatch_semaphore_wait(sema, 100);
-}
-
-void use_semaphor_antipattern_multiple_times() {
- dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
-
- func(^{
- dispatch_semaphore_signal(sema1);
- });
- dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
-
- dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
-
- func(^{
- dispatch_semaphore_signal(sema2);
- });
- dispatch_semaphore_wait(sema2, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
-}
-
-void use_semaphor_antipattern_multiple_wait() {
- dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
-
- func(^{
- dispatch_semaphore_signal(sema1);
- });
- // FIXME: multiple waits on same semaphor should not raise a warning.
- dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
- dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
-}
-
-void warn_incorrect_order() {
- // FIXME: ASTMatchers do not allow ordered matching, so would match even
- // if out of order.
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
-
- dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
- func(^{
- dispatch_semaphore_signal(sema);
- });
-}
-
-void warn_w_typedef() {
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
-
- func_w_typedef(^{
- dispatch_semaphore_signal(sema);
- });
- dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
-}
-
-void warn_nested_ast() {
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
-
- if (coin()) {
- func(^{
- dispatch_semaphore_signal(sema);
- });
- } else {
- func(^{
- dispatch_semaphore_signal(sema);
- });
- }
- dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
-}
-
-void use_semaphore_assignment() {
- dispatch_semaphore_t sema;
- sema = dispatch_semaphore_create(0);
-
- func(^{
- dispatch_semaphore_signal(sema);
- });
- dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
-}
-
-void use_semaphore_assignment_init() {
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
- sema = dispatch_semaphore_create(1);
-
- func(^{
- dispatch_semaphore_signal(sema);
- });
- dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
-}
-
-void differentsemaphoreok() {
- dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
- dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
-
- func(^{
- dispatch_semaphore_signal(sema1);
- });
- dispatch_semaphore_wait(sema2, 100); // no-warning
-}
-
-void nosignalok() {
- dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
- dispatch_semaphore_wait(sema1, 100);
-}
-
-void nowaitok() {
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
- func(^{
- dispatch_semaphore_signal(sema);
- });
-}
-
-void noblockok() {
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
- dispatch_semaphore_signal(sema);
- dispatch_semaphore_wait(sema, 100);
-}
-
-void storedblockok() {
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
- block_t b = ^{
- dispatch_semaphore_signal(sema);
- };
- dispatch_semaphore_wait(sema, 100);
-}
-
-void passed_semaphore_ok(dispatch_semaphore_t sema) {
- func(^{
- dispatch_semaphore_signal(sema);
- });
- dispatch_semaphore_wait(sema, 100);
-}
-
-void warn_with_cast() {
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
-
- func(^{
- dispatch_semaphore_signal((int)sema);
- });
- dispatch_semaphore_wait((int)sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
-}
-
-@interface Test1 : NSObject
--(void)use_method_warn;
--(void)testNoWarn;
-@end
-
-@implementation Test1
-
--(void)use_method_warn {
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
-
- func(^{
- dispatch_semaphore_signal(sema);
- });
- dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}}
-}
-
--(void)testNoWarn {
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
-
- func(^{
- dispatch_semaphore_signal(sema);
- });
- dispatch_semaphore_wait(sema, 100);
-}
-
-@end
diff --git a/test/Analysis/inlining/inline-defensive-checks.c b/test/Analysis/inlining/inline-defensive-checks.c
index ca61395..d290cf2 100644
--- a/test/Analysis/inlining/inline-defensive-checks.c
+++ b/test/Analysis/inlining/inline-defensive-checks.c
@@ -159,8 +159,7 @@
void idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset2(struct S *s) {
idc(s);
int *x = &(s->f2) - 1;
- // FIXME: Should not warn.
- *x = 7; // expected-warning{{Dereference of null pointer}}
+ *x = 7; // no-warning
}
void idcTrackZeroValueThroughUnaryPointerOperatorsWithAssignment(struct S *s) {
diff --git a/test/Analysis/lambdas.cpp b/test/Analysis/lambdas.cpp
index 38a2e3a..320ba2a 100644
--- a/test/Analysis/lambdas.cpp
+++ b/test/Analysis/lambdas.cpp
@@ -348,6 +348,23 @@
lambda();
}
+
+static int b = 0;
+
+int f() {
+ b = 0;
+ auto &bm = b;
+ [&] {
+ bm++;
+ bm++;
+ }();
+ if (bm != 2) {
+ int *y = 0;
+ return *y; // no-warning
+ }
+ return 0;
+}
+
// CHECK: [B2 (ENTRY)]
// CHECK: Succs (1): B1
// CHECK: [B1]
diff --git a/test/Analysis/lifetime-extension.cpp b/test/Analysis/lifetime-extension.cpp
index 53c8edb..c9038a2 100644
--- a/test/Analysis/lifetime-extension.cpp
+++ b/test/Analysis/lifetime-extension.cpp
@@ -1,7 +1,14 @@
// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify %s
// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -verify %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++17 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -DMOVES -verify %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -DMOVES -verify %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++17 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -DMOVES %s
+
+// Note: The C++17 run-lines don't -verify yet - it is a no-crash test.
void clang_analyzer_eval(bool);
+void clang_analyzer_checkInlined(bool);
namespace pr17001_call_wrong_destructor {
bool x;
@@ -63,6 +70,8 @@
~C() { if (after) *after = this; }
operator bool() const { return x; }
+
+ static C make(C **after, C **before) { return C(false, after, before); }
};
void f1() {
@@ -180,3 +189,154 @@
1 / x; // no-warning
}
} // end namespace maintain_original_object_address_on_move
+
+namespace maintain_address_of_copies {
+class C;
+
+struct AddressVector {
+ C *buf[10];
+ int len;
+
+ AddressVector() : len(0) {}
+
+ void push(C *c) {
+ buf[len] = c;
+ ++len;
+ }
+};
+
+class C {
+ AddressVector &v;
+
+public:
+ C(AddressVector &v) : v(v) { v.push(this); }
+ ~C() { v.push(this); }
+
+#ifdef MOVES
+ C(C &&c) : v(c.v) { v.push(this); }
+#endif
+
+ // Note how return-statements prefer move-constructors when available.
+ C(const C &c) : v(c.v) {
+#ifdef MOVES
+ clang_analyzer_checkInlined(false); // no-warning
+#else
+ v.push(this);
+#endif
+ } // no-warning
+
+ static C make(AddressVector &v) { return C(v); }
+};
+
+void f1() {
+ AddressVector v;
+ {
+ C c = C(v);
+ }
+ // 0. Create the original temporary and lifetime-extend it into variable 'c'
+ // construction argument.
+ // 1. Construct variable 'c' (elidable copy/move).
+ // 2. Destroy the temporary.
+ // 3. Destroy variable 'c'.
+ clang_analyzer_eval(v.len == 4);
+ clang_analyzer_eval(v.buf[0] == v.buf[2]);
+ clang_analyzer_eval(v.buf[1] == v.buf[3]);
+#ifdef TEMPORARIES
+ // expected-warning@-4{{TRUE}}
+ // expected-warning@-4{{TRUE}}
+ // expected-warning@-4{{TRUE}}
+#else
+ // expected-warning@-8{{UNKNOWN}}
+ // expected-warning@-8{{UNKNOWN}}
+ // expected-warning@-8{{UNKNOWN}}
+#endif
+}
+
+void f2() {
+ AddressVector v;
+ {
+ const C &c = C::make(v);
+ }
+ // 0. Construct the original temporary within make(),
+ // 1. Construct the return value of make() (elidable copy/move) and
+ // lifetime-extend it via reference 'c',
+ // 2. Destroy the temporary within make(),
+ // 3. Destroy the temporary lifetime-extended by 'c'.
+ clang_analyzer_eval(v.len == 4);
+ clang_analyzer_eval(v.buf[0] == v.buf[2]);
+ clang_analyzer_eval(v.buf[1] == v.buf[3]);
+#ifdef TEMPORARIES
+ // expected-warning@-4{{TRUE}}
+ // expected-warning@-4{{TRUE}}
+ // expected-warning@-4{{TRUE}}
+#else
+ // expected-warning@-8{{UNKNOWN}}
+ // expected-warning@-8{{UNKNOWN}}
+ // expected-warning@-8{{UNKNOWN}}
+#endif
+}
+
+void f3() {
+ AddressVector v;
+ {
+ C &&c = C::make(v);
+ }
+ // 0. Construct the original temporary within make(),
+ // 1. Construct the return value of make() (elidable copy/move) and
+ // lifetime-extend it via reference 'c',
+ // 2. Destroy the temporary within make(),
+ // 3. Destroy the temporary lifetime-extended by 'c'.
+ clang_analyzer_eval(v.len == 4);
+ clang_analyzer_eval(v.buf[0] == v.buf[2]);
+ clang_analyzer_eval(v.buf[1] == v.buf[3]);
+#ifdef TEMPORARIES
+ // expected-warning@-4{{TRUE}}
+ // expected-warning@-4{{TRUE}}
+ // expected-warning@-4{{TRUE}}
+#else
+ // expected-warning@-8{{UNKNOWN}}
+ // expected-warning@-8{{UNKNOWN}}
+ // expected-warning@-8{{UNKNOWN}}
+#endif
+}
+
+C doubleMake(AddressVector &v) {
+ return C::make(v);
+}
+
+void f4() {
+ AddressVector v;
+ {
+ C c = doubleMake(v);
+ }
+ // 0. Construct the original temporary within make(),
+ // 1. Construct the return value of make() (elidable copy/move) and
+ // lifetime-extend it into the return value constructor argument within
+ // doubleMake(),
+ // 2. Destroy the temporary within make(),
+ // 3. Construct the return value of doubleMake() (elidable copy/move) and
+ // lifetime-extend it into the variable 'c' constructor argument,
+ // 4. Destroy the return value of make(),
+ // 5. Construct variable 'c' (elidable copy/move),
+ // 6. Destroy the return value of doubleMake(),
+ // 7. Destroy variable 'c'.
+ clang_analyzer_eval(v.len == 8);
+ clang_analyzer_eval(v.buf[0] == v.buf[2]);
+ clang_analyzer_eval(v.buf[1] == v.buf[4]);
+ clang_analyzer_eval(v.buf[3] == v.buf[6]);
+ clang_analyzer_eval(v.buf[5] == v.buf[7]);
+#ifdef TEMPORARIES
+ // expected-warning@-6{{TRUE}}
+ // expected-warning@-6{{TRUE}}
+ // expected-warning@-6{{TRUE}}
+ // expected-warning@-6{{TRUE}}
+ // expected-warning@-6{{TRUE}}
+#else
+ // expected-warning@-12{{UNKNOWN}}
+ // expected-warning@-12{{UNKNOWN}}
+ // expected-warning@-12{{UNKNOWN}}
+ // expected-warning@-12{{UNKNOWN}}
+ // expected-warning@-12{{UNKNOWN}}
+#endif
+}
+} // end namespace maintain_address_of_copies
diff --git a/test/Analysis/loop-unrolling.cpp b/test/Analysis/loop-unrolling.cpp
index 1507acc..aa145ac 100644
--- a/test/Analysis/loop-unrolling.cpp
+++ b/test/Analysis/loop-unrolling.cpp
@@ -99,13 +99,101 @@
return 0;
}
+int no_unroll_assignment() {
+ for (int i = 0; i < 9; i++) {
+ i = i + 1;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment2() {
+ for (int i = 0; i < 9; i++) {
+ i *= 2;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment3() {
+ for (int i = 128; i > 0; i--) {
+ i /= 2;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment4() {
+ for (int i = 0; i < 9; i++) {
+ i -= 2;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment5() {
+ for (int i = 0; i < 9; i++) {
+ i += 1;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment6() {
+ for (int i = 128; i > 0; i--) {
+ i >>= 1;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment7() {
+ for (int i = 0; i < 512; i++) {
+ i <<= 1;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment8() {
+ for (int i = 0; i < 9; i++) {
+ i %= 8;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment9() {
+ for (int i = 0; i < 9; i++) {
+ i &= 31;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment10() {
+ for (int i = 0; i < 9; i++) {
+ i |= 2;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
+int no_unroll_assignment11() {
+ for (int i = 0; i < 9; i++) {
+ i ^= 2;
+ clang_analyzer_numTimesReached(); // expected-warning {{4}}
+ }
+ return 0;
+}
+
int make_new_branches_loop_cached() {
for (int i = 0; i < 8; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
- if(getNum()){
- (void) i; // Since this Stmt does not change the State the analyzer
- // won't make a new execution path but reuse the earlier nodes.
- }
+ if (getNum()) {
+ (void)i; // Since this Stmt does not change the State the analyzer
+ // won't make a new execution path but reuse the earlier nodes.
+ }
}
clang_analyzer_warnIfReached(); // no-warning
return 0;
@@ -115,7 +203,7 @@
int l = 2;
for (int i = 0; i < 8; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{10}}
- if(getNum()){
+ if (getNum()) {
++l;
}
}
@@ -127,7 +215,7 @@
int l = 2;
for (int i = 0; i < 8; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{10}}
- if(getNum()){
+ if (getNum()) {
++l;
}
(void)&i; // This ensures that the loop won't be unrolled.
@@ -185,7 +273,7 @@
for (j = 0; j < 9; ++j) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
a[j] = 22;
- (void) &j; // ensures that the inner loop won't be unrolled
+ (void)&j; // ensures that the inner loop won't be unrolled
}
a[i] = 42;
}
@@ -268,8 +356,8 @@
int k = 2;
for (int i = 0; i < 5; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{13}}
- if(i == 0 && b) // Splits the state in the first iteration but the recursion
- // call will be unrolled anyway since the condition is known there.
+ if (i == 0 && b) // Splits the state in the first iteration but the recursion
+ // call will be unrolled anyway since the condition is known there.
recursion_unroll1(false);
clang_analyzer_numTimesReached(); // expected-warning {{14}}
}
@@ -281,7 +369,7 @@
int k = 0;
for (int i = 0; i < 5; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{9}}
- if(i == 0 && b)
+ if (i == 0 && b)
recursion_unroll2(false);
clang_analyzer_numTimesReached(); // expected-warning {{9}}
}
@@ -307,7 +395,7 @@
int k = 2;
for (int i = 0; i < 5; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{13}}
- if(i == 0 && b) {
+ if (i == 0 && b) {
recursion_unroll4(false);
continue;
}
diff --git a/test/Analysis/loop-widening.c b/test/Analysis/loop-widening.c
index de17951..3378893 100644
--- a/test/Analysis/loop-widening.c
+++ b/test/Analysis/loop-widening.c
@@ -1,4 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify %s
+// RUN: %clang_analyze_cc1 -DTEST_NULL_TERM -analyzer-checker=core,unix.Malloc,debug.ExprInspection,alpha.cplusplus.IteratorRange -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify %s
void clang_analyzer_eval(int);
void clang_analyzer_warnIfReached();
@@ -188,3 +189,16 @@
}
clang_analyzer_eval(i >= 2); // expected-warning {{TRUE}}
}
+
+#ifdef TEST_NULL_TERM
+void null_terminator_loop_widen(int *a) {
+ int c;
+ // Loop widening will call 'invalidateRegions()' and 'invalidateRegions()'
+ // will construct the SymbolConjured with null Stmt because of the null
+ // terminator statement. Accessing the null Stmt will cause a crash.
+ for (;;) {
+ c = *a; // no-crash
+ a++;
+ }
+}
+#endif
diff --git a/test/Analysis/missing-bind-temporary.cpp b/test/Analysis/missing-bind-temporary.cpp
new file mode 100644
index 0000000..010c42e
--- /dev/null
+++ b/test/Analysis/missing-bind-temporary.cpp
@@ -0,0 +1,130 @@
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=debug.DumpCFG %s > %t 2>&1
+// RUN: FileCheck --input-file=%t %s
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=core,debug.ExprInspection -std=c++14 -verify %s
+
+void clang_analyzer_eval(bool);
+
+int global;
+
+namespace variant_0 {
+// This variant of the code works correctly. Function foo() is not a template
+// function. Note that there are two destructors within foo().
+
+class A {
+public:
+ ~A() { ++global; }
+};
+
+class B {
+ A a;
+};
+
+// CHECK: void foo(int)
+// CHECK: [B1]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], class variant_0::B)
+// CHECK-NEXT: 2: variant_0::B i;
+// CHECK-NEXT: 3: operator=
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, class variant_0::B &(*)(class variant_0::B &&) noexcept)
+// CHECK-NEXT: 5: i
+// CHECK-NEXT: 6: {} (CXXConstructExpr, [B1.7], [B1.8], class variant_0::B)
+// CHECK-NEXT: 7: [B1.6] (BindTemporary)
+// CHECK-NEXT: 8: [B1.7]
+// CHECK-NEXT: 9: [B1.5] = [B1.8] (OperatorCall)
+// CHECK-NEXT: 10: ~variant_0::B() (Temporary object destructor)
+// CHECK-NEXT: 11: [B1.2].~B() (Implicit destructor)
+void foo(int) {
+ B i;
+ i = {};
+}
+
+void bar() {
+ global = 0;
+ foo(1);
+ clang_analyzer_eval(global == 2); // expected-warning{{TRUE}}
+}
+
+} // end namespace variant_0
+
+namespace variant_1 {
+// Suddenly, if we turn foo() into a template, we are missing a
+// CXXBindTemporaryExpr in the AST, and therefore we're missing a
+// temporary destructor in the CFG.
+
+class A {
+public:
+ ~A() { ++global; }
+};
+
+class B {
+ A a;
+};
+
+// FIXME: Find the construction context for {} and enforce the temporary
+// destructor.
+// CHECK: template<> void foo<int>(int)
+// CHECK: [B1]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], class variant_1::B)
+// CHECK-NEXT: 2: variant_1::B i;
+// CHECK-NEXT: 3: operator=
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, class variant_1::B &(*)(class variant_1::B &&) noexcept)
+// CHECK-NEXT: 5: i
+// CHECK-NEXT: 6: {} (CXXConstructExpr, class variant_1::B)
+// CHECK-NEXT: 7: [B1.6]
+// CHECK-NEXT: 8: [B1.5] = [B1.7] (OperatorCall)
+// CHECK-NEXT: 9: [B1.2].~B() (Implicit destructor)
+template <typename T> void foo(T) {
+ B i;
+ i = {};
+}
+
+void bar() {
+ global = 0;
+ foo(1);
+ // FIXME: Should be TRUE, i.e. we should call (and inline) two destructors.
+ clang_analyzer_eval(global == 2); // expected-warning{{UNKNOWN}}
+}
+
+} // end namespace variant_1
+
+namespace variant_2 {
+// Making field 'a' in class 'B' public turns the class into an aggregate.
+// In this case there is no constructor at {} - only an aggregate
+// initialization. Aggregate initialization is unsupported for now.
+
+class A {
+public:
+ ~A() { ++global; }
+};
+
+class B {
+public:
+ A a;
+};
+
+// CHECK: template<> void foo<int>(int)
+// CHECK: [B1]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], class variant_2::B)
+// CHECK-NEXT: 2: variant_2::B i;
+// CHECK-NEXT: 3: operator=
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, class variant_2::B &(*)(class variant_2::B &&) noexcept)
+// CHECK-NEXT: 5: i
+// CHECK-NEXT: 6: {}
+// CHECK-NEXT: 7: {}
+// CHECK-NEXT: 8: [B1.7] (BindTemporary)
+// CHECK-NEXT: 9: [B1.8]
+// CHECK-NEXT: 10: [B1.5] = [B1.9] (OperatorCall)
+// CHECK-NEXT: 11: ~variant_2::B() (Temporary object destructor)
+// CHECK-NEXT: 12: [B1.2].~B() (Implicit destructor)
+template <typename T> void foo(T) {
+ B i;
+ i = {};
+}
+
+void bar() {
+ global = 0;
+ foo(1);
+ // FIXME: Should be TRUE, i.e. we should call (and inline) two destructors.
+ clang_analyzer_eval(global == 2); // expected-warning{{UNKNOWN}}
+}
+
+} // end namespace variant_2
diff --git a/test/Analysis/mmap-writeexec.c b/test/Analysis/mmap-writeexec.c
index 2d8ea9b..2ebc961 100644
--- a/test/Analysis/mmap-writeexec.c
+++ b/test/Analysis/mmap-writeexec.c
@@ -16,6 +16,7 @@
typedef __typeof(sizeof(int)) size_t;
void *mmap(void *, size_t, int, int, int, long);
+int mprotect(void *, size_t, int);
void f1()
{
@@ -34,3 +35,10 @@
int prot = PROT_WRITE | PROT_EXEC;
(void)callm(NULL, 1024, prot, MAP_PRIVATE | MAP_ANON, -1, 0); // expected-warning{{Both PROT_WRITE and PROT_EXEC flags are set. This can lead to exploitable memory regions, which could be overwritten with malicious code}}
}
+
+void f3()
+{
+ void *p = mmap(NULL, 1024, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); // no-warning
+ int m = mprotect(p, 1024, PROT_WRITE | PROT_EXEC); // expected-warning{{Both PROT_WRITE and PROT_EXEC flags are set. This can lead to exploitable memory regions, which could be overwritten with malicious code}}
+ (void)m;
+}
diff --git a/test/Analysis/nonnullparamchecker-crash.cpp b/test/Analysis/nonnullparamchecker-crash.cpp
index 96e7f21..76480f4 100644
--- a/test/Analysis/nonnullparamchecker-crash.cpp
+++ b/test/Analysis/nonnullparamchecker-crash.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -std=c++11 -verify %s
class C {};
// expected-no-diagnostics
diff --git a/test/Analysis/null-deref-path-notes.c b/test/Analysis/null-deref-path-notes.c
index a1477a6..3fd559d 100644
--- a/test/Analysis/null-deref-path-notes.c
+++ b/test/Analysis/null-deref-path-notes.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -w -x c -analyzer-checker=core -analyzer-output=text -verify %s
+// RUN: %clang_analyze_cc1 -w -x c -analyzer-checker=core,unix -analyzer-output=text -verify %s
// Avoid the crash when finding the expression for tracking the origins
// of the null pointer for path notes.
@@ -7,3 +7,46 @@
(a + 0)[0]; // expected-warning{{Array access results in a null pointer dereference}}
// expected-note@-1{{Array access results in a null pointer dereference}}
}
+
+typedef __typeof(sizeof(int)) size_t;
+void *memcpy(void *dest, const void *src, unsigned long count);
+
+void f1(char *source) {
+ char *destination = 0; // expected-note{{'destination' initialized to a null pointer value}}
+ memcpy(destination + 0, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}}
+ // expected-note@-1{{Null pointer argument in call to memory copy function}}
+}
+
+void f2(char *source) {
+ char *destination = 0; // expected-note{{'destination' initialized to a null pointer value}}
+ memcpy(destination - 0, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}}
+ // expected-note@-1{{Null pointer argument in call to memory copy function}}
+}
+
+void f3(char *source) {
+ char *destination = 0; // FIXME: There should be a note here as well.
+ destination = destination + 0; // expected-note{{Null pointer value stored to 'destination'}}
+ memcpy(destination, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}}
+ // expected-note@-1{{Null pointer argument in call to memory copy function}}
+}
+
+void f4(char *source) {
+ char *destination = 0; // FIXME: There should be a note here as well.
+ destination = destination - 0; // expected-note{{Null pointer value stored to 'destination'}}
+ memcpy(destination, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}}
+ // expected-note@-1{{Null pointer argument in call to memory copy function}}
+}
+
+void f5(char *source) {
+ char *destination1 = 0; // expected-note{{'destination1' initialized to a null pointer value}}
+ char *destination2 = destination1 + 0; // expected-note{{'destination2' initialized to a null pointer value}}
+ memcpy(destination2, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}}
+ // expected-note@-1{{Null pointer argument in call to memory copy function}}
+}
+
+void f6(char *source) {
+ char *destination1 = 0; // expected-note{{'destination1' initialized to a null pointer value}}
+ char *destination2 = destination1 - 0; // expected-note{{'destination2' initialized to a null pointer value}}
+ memcpy(destination2, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}}
+ // expected-note@-1{{Null pointer argument in call to memory copy function}}
+}
diff --git a/test/Analysis/objc-for.m b/test/Analysis/objc-for.m
index f191e86..b59a5c2 100644
--- a/test/Analysis/objc-for.m
+++ b/test/Analysis/objc-for.m
@@ -32,6 +32,7 @@
@interface NSDictionary (SomeCategory)
- (void)categoryMethodOnNSDictionary;
+- (id) allKeys;
@end
@interface NSMutableDictionary : NSDictionary
@@ -343,3 +344,10 @@
for (id key in array)
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
+
+int not_reachable_on_iteration_through_nil() {
+ NSDictionary* d = nil;
+ for (NSString* s in [d allKeys])
+ clang_analyzer_warnIfReached(); // no-warning
+ return 0;
+}
diff --git a/test/Analysis/ptr-arith.c b/test/Analysis/ptr-arith.c
index 93cb4ee..804759a 100644
--- a/test/Analysis/ptr-arith.c
+++ b/test/Analysis/ptr-arith.c
@@ -347,3 +347,9 @@
a[0] = 0;
label:;
}
+
+typedef __attribute__((__ext_vector_type__(2))) float simd_float2;
+float test_nowarning_on_vector_deref() {
+ simd_float2 x = {0, 1};
+ return x[1]; // no-warning
+}
diff --git a/test/Analysis/retaincountchecker-compoundregion.m b/test/Analysis/retaincountchecker-compoundregion.m
new file mode 100644
index 0000000..d9967b7
--- /dev/null
+++ b/test/Analysis/retaincountchecker-compoundregion.m
@@ -0,0 +1,25 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -fblocks -verify -Wno-objc-root-class %s
+typedef const void *CFTypeRef;
+enum { kCFNumberSInt8Type = 1, kCFNumberSInt16Type = 2,
+ kCFNumberSInt32Type = 3, kCFNumberSInt64Type = 4,
+ kCFNumberFloat32Type = 5, kCFNumberFloat64Type = 6,
+ kCFNumberCharType = 7, kCFNumberShortType = 8,
+ kCFNumberIntType = 9, kCFNumberLongType = 10,
+ kCFNumberLongLongType = 11, kCFNumberFloatType = 12,
+ kCFNumberDoubleType = 13, kCFNumberCFIndexType = 14,
+ kCFNumberNSIntegerType = 15, kCFNumberCGFloatType = 16,
+ kCFNumberMaxType = 16 };
+typedef const struct __CFAllocator * CFAllocatorRef;
+typedef signed long CFIndex;
+typedef CFIndex CFNumberType;
+typedef const struct __CFNumber * CFNumberRef;
+extern CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr);
+
+void foo(CFAllocatorRef allocator) {
+ int width = 0;
+ int height = 0;
+ CFTypeRef* values = (CFTypeRef[]){
+ CFNumberCreate(allocator, kCFNumberSInt32Type, &width), //expected-warning-re{{Potential leak of an object{{$}}}}
+ CFNumberCreate(allocator, kCFNumberSInt32Type, &height), //expected-warning-re{{Potential leak of an object{{$}}}}
+ };
+}
diff --git a/test/Analysis/scopes-cfg-output.cpp b/test/Analysis/scopes-cfg-output.cpp
new file mode 100644
index 0000000..28dde45
--- /dev/null
+++ b/test/Analysis/scopes-cfg-output.cpp
@@ -0,0 +1,1171 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -analyze -analyzer-checker=debug.DumpCFG -analyzer-config cfg-scopes=true %s > %t 2>&1
+// RUN: FileCheck --input-file=%t %s
+
+class A {
+public:
+// CHECK: [B1 (ENTRY)]
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+ A() {}
+
+// CHECK: [B1 (ENTRY)]
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+ ~A() {}
+
+// CHECK: [B2 (ENTRY)]
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B1]
+// CHECK-NEXT: 1: 1
+// CHECK-NEXT: 2: return [B1.1];
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+ operator int() const { return 1; }
+};
+
+int getX();
+extern const bool UV;
+
+// CHECK: [B2 (ENTRY)]
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B1.3], class A [2])
+// CHECK-NEXT: 3: A a[2];
+// CHECK-NEXT: 4: (CXXConstructExpr, [B1.5], class A [0])
+// CHECK-NEXT: 5: A b[0];
+// CHECK-NEXT: 6: [B1.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_array() {
+ A a[2];
+ A b[0];
+}
+
+// CHECK: [B2 (ENTRY)]
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B1.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: 4: CFGScopeBegin(c)
+// CHECK-NEXT: 5: (CXXConstructExpr, [B1.6], class A)
+// CHECK-NEXT: 6: A c;
+// CHECK-NEXT: 7: (CXXConstructExpr, [B1.8], class A)
+// CHECK-NEXT: 8: A d;
+// CHECK-NEXT: 9: [B1.8].~A() (Implicit destructor)
+// CHECK-NEXT: 10: [B1.6].~A() (Implicit destructor)
+// CHECK-NEXT: 11: CFGScopeEnd(c)
+// CHECK-NEXT: 12: (CXXConstructExpr, [B1.13], class A)
+// CHECK-NEXT: 13: A b;
+// CHECK-NEXT: 14: [B1.13].~A() (Implicit destructor)
+// CHECK-NEXT: 15: [B1.3].~A() (Implicit destructor)
+// CHECK-NEXT: 16: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_scope() {
+ A a;
+ { A c;
+ A d;
+ }
+ A b;
+}
+
+// CHECK: [B4 (ENTRY)]
+// CHECK-NEXT: Succs (1): B3
+// CHECK: [B1]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], class A)
+// CHECK-NEXT: 2: A c;
+// CHECK-NEXT: 3: [B1.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B3.5].~A() (Implicit destructor)
+// CHECK-NEXT: 5: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT: 6: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B3
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: return;
+// CHECK-NEXT: 2: [B3.5].~A() (Implicit destructor)
+// CHECK-NEXT: 3: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B3
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B3]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B3.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: 4: (CXXConstructExpr, [B3.5], class A)
+// CHECK-NEXT: 5: A b;
+// CHECK-NEXT: 6: UV
+// CHECK-NEXT: 7: [B3.6] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B3.7]
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (2): B2 B1
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (2): B1 B2
+void test_return() {
+ A a;
+ A b;
+ if (UV) return;
+ A c;
+}
+
+// CHECK: [B5 (ENTRY)]
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B4.8].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: 3: [B4.3].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B2 B3
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B2.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: [B2.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B3]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B3.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B4.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: 4: CFGScopeBegin(b)
+// CHECK-NEXT: 5: a
+// CHECK-NEXT: 6: [B4.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 7: [B4.6] (CXXConstructExpr, [B4.8], class A)
+// CHECK-NEXT: 8: A b = a;
+// CHECK-NEXT: 9: b
+// CHECK-NEXT: 10: [B4.9] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 11: [B4.10].operator int
+// CHECK-NEXT: 12: [B4.10]
+// CHECK-NEXT: 13: [B4.12] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 14: [B4.13] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: if [B4.14]
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (2): B3 B2
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_if_implicit_scope() {
+ A a;
+ if (A b = a)
+ A c;
+ else A c;
+}
+
+// CHECK: [B9 (ENTRY)]
+// CHECK-NEXT: Succs (1): B8
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B8.8].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: 3: (CXXConstructExpr, [B1.4], class A)
+// CHECK-NEXT: 4: A e;
+// CHECK-NEXT: 5: [B1.4].~A() (Implicit destructor)
+// CHECK-NEXT: 6: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B2 B5
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B2.2], class A)
+// CHECK-NEXT: 2: A d;
+// CHECK-NEXT: 3: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B4.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B3]
+// CHECK-NEXT: 1: return;
+// CHECK-NEXT: 2: [B4.3].~A() (Implicit destructor)
+// CHECK-NEXT: 3: CFGScopeEnd(c)
+// CHECK-NEXT: 4: [B8.8].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(b)
+// CHECK-NEXT: 6: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B4.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: UV
+// CHECK-NEXT: 5: [B4.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B4.5]
+// CHECK-NEXT: Preds (1): B8
+// CHECK-NEXT: Succs (2): B3 B2
+// CHECK: [B5]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B5.2], class A)
+// CHECK-NEXT: 2: A d;
+// CHECK-NEXT: 3: [B5.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B7.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B6]
+// CHECK-NEXT: 1: return;
+// CHECK-NEXT: 2: [B7.3].~A() (Implicit destructor)
+// CHECK-NEXT: 3: CFGScopeEnd(c)
+// CHECK-NEXT: 4: [B8.8].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(b)
+// CHECK-NEXT: 6: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B7]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B7.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: UV
+// CHECK-NEXT: 5: [B7.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B7.5]
+// CHECK-NEXT: Preds (1): B8
+// CHECK-NEXT: Succs (2): B6 B5
+// CHECK: [B8]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B8.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: 4: CFGScopeBegin(b)
+// CHECK-NEXT: 5: a
+// CHECK-NEXT: 6: [B8.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 7: [B8.6] (CXXConstructExpr, [B8.8], class A)
+// CHECK-NEXT: 8: A b = a;
+// CHECK-NEXT: 9: b
+// CHECK-NEXT: 10: [B8.9] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 11: [B8.10].operator int
+// CHECK-NEXT: 12: [B8.10]
+// CHECK-NEXT: 13: [B8.12] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 14: [B8.13] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: if [B8.14]
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (2): B7 B4
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (3): B1 B3 B6
+void test_if_jumps() {
+ A a;
+ if (A b = a) {
+ A c;
+ if (UV) return;
+ A d;
+ } else {
+ A c;
+ if (UV) return;
+ A d;
+ }
+ A e;
+}
+
+// CHECK: [B6 (ENTRY)]
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B4.5].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: 3: [B5.3].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: Preds (1): B3
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B3]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B3.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: 6: [B4.5].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(b)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(b)
+// CHECK-NEXT: 2: a
+// CHECK-NEXT: 3: [B4.2] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 4: [B4.3] (CXXConstructExpr, class A)
+// CHECK-NEXT: 5: A b = a;
+// CHECK-NEXT: 6: b
+// CHECK-NEXT: 7: [B4.6] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 8: [B4.7].operator int
+// CHECK-NEXT: 9: [B4.7]
+// CHECK-NEXT: 10: [B4.9] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 11: [B4.10] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: while [B4.11]
+// CHECK-NEXT: Preds (2): B2 B5
+// CHECK-NEXT: Succs (2): B3 B1
+// CHECK: [B5]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B5.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_while_implicit_scope() {
+ A a;
+ while (A b = a)
+ A c;
+}
+
+// CHECK: [B12 (ENTRY)]
+// CHECK-NEXT: Succs (1): B11
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: 3: (CXXConstructExpr, [B1.4], class A)
+// CHECK-NEXT: 4: A e;
+// CHECK-NEXT: 5: [B1.4].~A() (Implicit destructor)
+// CHECK-NEXT: 6: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B8 B10
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: Preds (2): B3 B6
+// CHECK-NEXT: Succs (1): B10
+// CHECK: [B3]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
+// CHECK-NEXT: 2: A d;
+// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: 6: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(b)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: return;
+// CHECK-NEXT: 2: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 3: CFGScopeEnd(c)
+// CHECK-NEXT: 4: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(b)
+// CHECK-NEXT: 6: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B5]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B5.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B5.2]
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (2): B4 B3
+// CHECK: [B6]
+// CHECK-NEXT: 1: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(c)
+// CHECK-NEXT: 3: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(b)
+// CHECK-NEXT: T: continue;
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B7]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B7.2]
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (2): B6 B5
+// CHECK: [B8]
+// CHECK-NEXT: 1: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(c)
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B9]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B9.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: UV
+// CHECK-NEXT: 5: [B9.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B9.5]
+// CHECK-NEXT: Preds (1): B10
+// CHECK-NEXT: Succs (2): B8 B7
+// CHECK: [B10]
+// CHECK-NEXT: 1: CFGScopeBegin(b)
+// CHECK-NEXT: 2: a
+// CHECK-NEXT: 3: [B10.2] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 4: [B10.3] (CXXConstructExpr, class A)
+// CHECK-NEXT: 5: A b = a;
+// CHECK-NEXT: 6: b
+// CHECK-NEXT: 7: [B10.6] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 8: [B10.7].operator int
+// CHECK-NEXT: 9: [B10.7]
+// CHECK-NEXT: 10: [B10.9] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 11: [B10.10] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: while [B10.11]
+// CHECK-NEXT: Preds (2): B2 B11
+// CHECK-NEXT: Succs (2): B9 B1
+// CHECK: [B11]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B11.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: Preds (1): B12
+// CHECK-NEXT: Succs (1): B10
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (2): B1 B4
+void test_while_jumps() {
+ A a;
+ while (A b = a) {
+ A c;
+ if (UV) break;
+ if (UV) continue;
+ if (UV) return;
+ A d;
+ }
+ A e;
+}
+
+// CHECK: [B12 (ENTRY)]
+// CHECK-NEXT: Succs (1): B11
+// CHECK: [B1]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], class A)
+// CHECK-NEXT: 2: A d;
+// CHECK-NEXT: 3: [B1.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B8 B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: do ... while [B2.2]
+// CHECK-NEXT: Preds (2): B3 B6
+// CHECK-NEXT: Succs (2): B10 B1
+// CHECK: [B3]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
+// CHECK-NEXT: 2: A c;
+// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(b)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: return;
+// CHECK-NEXT: 2: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 3: CFGScopeEnd(b)
+// CHECK-NEXT: 4: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B5]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B5.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B5.2]
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (2): B4 B3
+// CHECK: [B6]
+// CHECK-NEXT: 1: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: T: continue;
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B7]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B7.2]
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (2): B6 B5
+// CHECK: [B8]
+// CHECK-NEXT: 1: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B9]
+// CHECK-NEXT: 1: CFGScopeBegin(b)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B9.3], class A)
+// CHECK-NEXT: 3: A b;
+// CHECK-NEXT: 4: UV
+// CHECK-NEXT: 5: [B9.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B9.5]
+// CHECK-NEXT: Preds (2): B10 B11
+// CHECK-NEXT: Succs (2): B8 B7
+// CHECK: [B10]
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B9
+// CHECK: [B11]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B11.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: Preds (1): B12
+// CHECK-NEXT: Succs (1): B9
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (2): B1 B4
+void test_do_jumps() {
+ A a;
+ do {
+ A b;
+ if (UV) break;
+ if (UV) continue;
+ if (UV) return;
+ A c;
+ } while (UV);
+ A d;
+}
+
+// CHECK: [B6 (ENTRY)]
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B4.5].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: 3: [B5.3].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: Preds (1): B3
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B3]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B3.3], class A)
+// CHECK-NEXT: 3: A c;
+// CHECK-NEXT: 4: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: 6: [B4.5].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(b)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(b)
+// CHECK-NEXT: 2: a
+// CHECK-NEXT: 3: [B4.2] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 4: [B4.3] (CXXConstructExpr, class A)
+// CHECK-NEXT: 5: A b = a;
+// CHECK-NEXT: 6: b
+// CHECK-NEXT: 7: [B4.6] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 8: [B4.7].operator int
+// CHECK-NEXT: 9: [B4.7]
+// CHECK-NEXT: 10: [B4.9] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 11: [B4.10] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: for (...; [B4.11]; )
+// CHECK-NEXT: Preds (2): B2 B5
+// CHECK-NEXT: Succs (2): B3 B1
+// CHECK: [B5]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B5.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_for_implicit_scope() {
+ for (A a; A b = a; )
+ A c;
+}
+
+// CHECK: [B12 (ENTRY)]
+// CHECK-NEXT: Succs (1): B11
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(c)
+// CHECK-NEXT: 3: [B11.6].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(b)
+// CHECK-NEXT: 5: (CXXConstructExpr, [B1.6], class A)
+// CHECK-NEXT: 6: A f;
+// CHECK-NEXT: 7: [B1.6].~A() (Implicit destructor)
+// CHECK-NEXT: 8: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 9: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B8 B10
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: Preds (2): B3 B6
+// CHECK-NEXT: Succs (1): B10
+// CHECK: [B3]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B3.2], class A)
+// CHECK-NEXT: 2: A e;
+// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(d)
+// CHECK-NEXT: 6: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: return;
+// CHECK-NEXT: 2: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 3: CFGScopeEnd(d)
+// CHECK-NEXT: 4: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(c)
+// CHECK-NEXT: 6: [B11.6].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(b)
+// CHECK-NEXT: 8: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 9: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B5]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B5.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B5.2]
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (2): B4 B3
+// CHECK: [B6]
+// CHECK-NEXT: 1: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(d)
+// CHECK-NEXT: T: continue;
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B7]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B7.2]
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (2): B6 B5
+// CHECK: [B8]
+// CHECK-NEXT: 1: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(d)
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B9]
+// CHECK-NEXT: 1: CFGScopeBegin(d)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B9.3], class A)
+// CHECK-NEXT: 3: A d;
+// CHECK-NEXT: 4: UV
+// CHECK-NEXT: 5: [B9.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B9.5]
+// CHECK-NEXT: Preds (1): B10
+// CHECK-NEXT: Succs (2): B8 B7
+// CHECK: [B10]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: b
+// CHECK-NEXT: 3: [B10.2] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 4: [B10.3] (CXXConstructExpr, class A)
+// CHECK-NEXT: 5: A c = b;
+// CHECK-NEXT: 6: c
+// CHECK-NEXT: 7: [B10.6] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 8: [B10.7].operator int
+// CHECK-NEXT: 9: [B10.7]
+// CHECK-NEXT: 10: [B10.9] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 11: [B10.10] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: for (...; [B10.11]; )
+// CHECK-NEXT: Preds (2): B2 B11
+// CHECK-NEXT: Succs (2): B9 B1
+// CHECK: [B11]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B11.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: 4: CFGScopeBegin(b)
+// CHECK-NEXT: 5: (CXXConstructExpr, [B11.6], class A)
+// CHECK-NEXT: 6: A b;
+// CHECK-NEXT: Preds (1): B12
+// CHECK-NEXT: Succs (1): B10
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (2): B1 B4
+void test_for_jumps() {
+ A a;
+ for (A b; A c = b; ) {
+ A d;
+ if (UV) break;
+ if (UV) continue;
+ if (UV) return;
+ A e;
+ }
+ A f;
+}
+
+// CHECK: [B8 (ENTRY)]
+// CHECK-NEXT: Succs (1): B7
+// CHECK: [B1]
+// CHECK-NEXT: l1:
+// CHECK-NEXT: 1: (CXXConstructExpr, [B1.2], class A)
+// CHECK-NEXT: 2: A c;
+// CHECK-NEXT: 3: [B1.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B6.5].~A() (Implicit destructor)
+// CHECK-NEXT: 5: [B6.3].~A() (Implicit destructor)
+// CHECK-NEXT: 6: [B7.3].~A() (Implicit destructor)
+// CHECK-NEXT: 7: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B2 B3
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: (CXXConstructExpr, [B2.2], class A)
+// CHECK-NEXT: 2: A b;
+// CHECK-NEXT: 3: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT: 4: [B6.8].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B3]
+// CHECK-NEXT: 1: [B6.8].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(a)
+// CHECK-NEXT: T: goto l1;
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B4]
+// CHECK-NEXT: 1: UV
+// CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B4.2]
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (2): B3 B2
+// CHECK: [B5]
+// CHECK-NEXT: 1: [B6.8].~A() (Implicit destructor)
+// CHECK-NEXT: 2: [B6.5].~A() (Implicit destructor)
+// CHECK-NEXT: 3: [B6.3].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(cb)
+// CHECK-NEXT: T: goto l0;
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (1): B6
+// CHECK: [B6]
+// CHECK-NEXT: l0:
+// CHECK-NEXT: 1: CFGScopeBegin(cb)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B6.3], class A)
+// CHECK-NEXT: 3: A cb;
+// CHECK-NEXT: 4: (CXXConstructExpr, [B6.5], class A)
+// CHECK-NEXT: 5: A b;
+// CHECK-NEXT: 6: CFGScopeBegin(a)
+// CHECK-NEXT: 7: (CXXConstructExpr, [B6.8], class A)
+// CHECK-NEXT: 8: A a;
+// CHECK-NEXT: 9: UV
+// CHECK-NEXT: 10: [B6.9] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT: T: if [B6.10]
+// CHECK-NEXT: Preds (2): B7 B5
+// CHECK-NEXT: Succs (2): B5 B4
+// CHECK: [B7]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B7.3], class A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: Preds (1): B8
+// CHECK-NEXT: Succs (1): B6
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_goto() {
+ A a;
+l0:
+ A cb;
+ A b;
+ { A a;
+ if (UV) goto l0;
+ if (UV) goto l1;
+ A b;
+ }
+l1:
+ A c;
+}
+
+// CHECK: [B7 (ENTRY)]
+// CHECK-NEXT: Succs (1): B6
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeEnd(i)
+// CHECK-NEXT: 2: CFGScopeBegin(unused2)
+// CHECK-NEXT: 3: int unused2;
+// CHECK-NEXT: 4: CFGScopeEnd(unused2)
+// CHECK-NEXT: Preds (2): B4 B5
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: i
+// CHECK-NEXT: 2: ++[B2.1]
+// CHECK-NEXT: Preds (1): B3
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B3]
+// CHECK-NEXT: 1: CFGScopeEnd(unused1)
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(unused1)
+// CHECK-NEXT: 2: int unused1;
+// CHECK-NEXT: 3: CFGScopeEnd(unused1)
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B5]
+// CHECK-NEXT: 1: i
+// CHECK-NEXT: 2: [B5.1] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: 3: 3
+// CHECK-NEXT: 4: [B5.2] < [B5.3]
+// CHECK-NEXT: T: for (...; [B5.4]; ...)
+// CHECK-NEXT: Preds (2): B2 B6
+// CHECK-NEXT: Succs (2): B4 B1
+// CHECK: [B6]
+// CHECK-NEXT: 1: CFGScopeBegin(i)
+// CHECK-NEXT: 2: 0
+// CHECK-NEXT: 3: int i = 0;
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_for_compound_and_break() {
+ for (int i = 0; i < 3; ++i) {
+ {
+ int unused1;
+ break;
+ }
+ }
+ {
+ int unused2;
+ }
+}
+
+// CHECK: [B6 (ENTRY)]
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeEnd(__end1)
+// CHECK-NEXT: 2: CFGScopeEnd(__begin1)
+// CHECK-NEXT: 3: CFGScopeEnd(__range1)
+// CHECK-NEXT: 4: [B5.3].~A() (Implicit destructor)
+// CHECK-NEXT: 5: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: __begin1
+// CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, LValueToRValue, class A *)
+// CHECK-NEXT: 3: __end1
+// CHECK-NEXT: 4: [B2.3] (ImplicitCastExpr, LValueToRValue, class A *)
+// CHECK-NEXT: 5: [B2.2] != [B2.4]
+// CHECK-NEXT: T: for (auto &i : [B5.4]) {
+// CHECK: [B4.11];
+// CHECK-NEXT:}
+// CHECK-NEXT: Preds (2): B3 B5
+// CHECK-NEXT: Succs (2): B4 B1
+// CHECK: [B3]
+// CHECK-NEXT: 1: __begin1
+// CHECK-NEXT: 2: ++[B3.1]
+// CHECK-NEXT: Preds (1): B4
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(i)
+// CHECK-NEXT: 2: __begin1
+// CHECK-NEXT: 3: [B4.2] (ImplicitCastExpr, LValueToRValue, class A *)
+// CHECK-NEXT: 4: *[B4.3]
+// CHECK-NEXT: 5: auto &i = *__begin1;
+// CHECK-NEXT: 6: operator=
+// CHECK-NEXT: 7: [B4.6] (ImplicitCastExpr, FunctionToPointerDecay, class A &(*)(const class A &)
+// CHECK-NEXT: 8: i
+// CHECK-NEXT: 9: b
+// CHECK-NEXT: 10: [B4.9] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 11: [B4.8] = [B4.10] (OperatorCall)
+// CHECK-NEXT: 12: CFGScopeEnd(i)
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B3
+// CHECK: [B5]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B5.3], class A [10])
+// CHECK-NEXT: 3: A a[10];
+// CHECK-NEXT: 4: a
+// CHECK-NEXT: 5: auto &&__range1 = a;
+// CHECK-NEXT: 6: CFGScopeBegin(__end1)
+// CHECK-NEXT: 7: __range1
+// CHECK-NEXT: 8: [B5.7] (ImplicitCastExpr, ArrayToPointerDecay, class A *)
+// CHECK-NEXT: 9: 10
+// CHECK-NEXT: 10: [B5.8] + [B5.9]
+// CHECK-NEXT: 11: auto __end1 = __range1 + 10
+// CHECK-NEXT: 12: __range1
+// CHECK-NEXT: 13: [B5.12] (ImplicitCastExpr, ArrayToPointerDecay, class A *)
+// CHECK-NEXT: 14: auto __begin1 = __range1;
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_range_for(A &b) {
+ A a[10];
+ for (auto &i : a)
+ i = b;
+}
+
+// CHECK: [B8 (ENTRY)]
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeEnd(i)
+// CHECK-NEXT: 2: 1
+// CHECK-NEXT: 3: int k = 1;
+// CHECK-NEXT: 4: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (3): B3 B5 B6
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: '1'
+// CHECK-NEXT: 3: char c = '1';
+// CHECK-NEXT: 4: CFGScopeBegin(i)
+// CHECK-NEXT: 5: getX
+// CHECK-NEXT: 6: [B2.5] (ImplicitCastExpr, FunctionToPointerDecay, int (*)(void))
+// CHECK-NEXT: 7: [B2.6]()
+// CHECK-NEXT: 8: int i = getX();
+// CHECK-NEXT: 9: i
+// CHECK-NEXT: 10: [B2.9] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: T: switch [B2.10]
+// CHECK-NEXT: Preds (1): B8
+// CHECK-NEXT: Succs (5): B4 B5 B6 B7 B3
+// CHECK: [B3]
+// CHECK-NEXT: default:
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: 0
+// CHECK-NEXT: 3: int a = 0;
+// CHECK-NEXT: 4: i
+// CHECK-NEXT: 5: ++[B3.4]
+// CHECK-NEXT: 6: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B4 B2
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B4]
+// CHECK-NEXT: case 3:
+// CHECK-NEXT: 1: '2'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B4.2] = [B4.1]
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B3
+// CHECK: [B5]
+// CHECK-NEXT: case 2:
+// CHECK-NEXT: 1: '2'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B5.2] = [B5.1]
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B6]
+// CHECK-NEXT: case 1:
+// CHECK-NEXT: 1: '3'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B6.2] = [B6.1]
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (2): B2 B7
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B7]
+// CHECK-NEXT: case 0:
+// CHECK-NEXT: 1: '2'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B7.2] = [B7.1]
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B6
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_switch_with_compound_with_default() {
+ char c = '1';
+ switch (int i = getX()) {
+ case 0:
+ c = '2';
+ case 1:
+ c = '3';
+ break;
+ case 2: {
+ c = '2';
+ break;
+ }
+ case 3:
+ c = '2';
+ default: {
+ int a = 0;
+ ++i;
+ }
+ }
+ int k = 1;
+}
+
+// CHECK: [B6 (ENTRY)]
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeEnd(i)
+// CHECK-NEXT: 2: 3
+// CHECK-NEXT: 3: int k = 3;
+// CHECK-NEXT: 4: CFGScopeEnd(c)
+// CHECK-NEXT: Preds (3): B3 B4 B2
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: CFGScopeBegin(c)
+// CHECK-NEXT: 2: '1'
+// CHECK-NEXT: 3: char c = '1';
+// CHECK-NEXT: 4: CFGScopeBegin(i)
+// CHECK-NEXT: 5: getX
+// CHECK-NEXT: 6: [B2.5] (ImplicitCastExpr, FunctionToPointerDecay, int (*)(void))
+// CHECK-NEXT: 7: [B2.6]()
+// CHECK-NEXT: 8: int i = getX();
+// CHECK-NEXT: 9: i
+// CHECK-NEXT: 10: [B2.9] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: T: switch [B2.10]
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (4): B3 B4 B5 B1
+// CHECK: [B3]
+// CHECK-NEXT: case 2:
+// CHECK-NEXT: 1: '3'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B3.2] = [B3.1]
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B4]
+// CHECK-NEXT: case 1:
+// CHECK-NEXT: 1: '1'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B4.2] = [B4.1]
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (2): B2 B5
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B5]
+// CHECK-NEXT: case 0:
+// CHECK-NEXT: 1: '2'
+// CHECK-NEXT: 2: c
+// CHECK-NEXT: 3: [B5.2] = [B5.1]
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+int test_switch_with_compound_without_default() {
+ char c = '1';
+ switch (int i = getX()) {
+ case 0:
+ c = '2';
+ case 1:
+ c = '1';
+ break;
+ case 2:
+ c = '3';
+ break;
+ }
+ int k = 3;
+}
+
+// CHECK: [B5 (ENTRY)]
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeEnd(i)
+// CHECK-NEXT: 2: 1
+// CHECK-NEXT: 3: int k = 1;
+// CHECK-NEXT: 4: CFGScopeEnd(s)
+// CHECK-NEXT: Preds (1): B3
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: CFGScopeBegin(s)
+// CHECK-NEXT: 2: '1'
+// CHECK-NEXT: 3: char s = '1';
+// CHECK-NEXT: 4: CFGScopeBegin(i)
+// CHECK-NEXT: 5: getX
+// CHECK-NEXT: 6: [B2.5] (ImplicitCastExpr, FunctionToPointerDecay, int (*)(void))
+// CHECK-NEXT: 7: [B2.6]()
+// CHECK-NEXT: 8: int i = getX();
+// CHECK-NEXT: 9: i
+// CHECK-NEXT: 10: [B2.9] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: T: switch [B2.10]
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (2): B4 B3
+// CHECK: [B3]
+// CHECK-NEXT: default:
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: 0
+// CHECK-NEXT: 3: int a = 0;
+// CHECK-NEXT: 4: i
+// CHECK-NEXT: 5: ++[B3.4]
+// CHECK-NEXT: 6: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (2): B4 B2
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B4]
+// CHECK-NEXT: case 0:
+// CHECK-NEXT: Preds (1): B2
+// CHECK-NEXT: Succs (1): B3
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_without_compound() {
+ char s = '1';
+ switch (int i = getX())
+ case 0:
+ default: {
+ int a = 0;
+ ++i;
+ }
+ int k = 1;
+}
+
+// CHECK: [B12 (ENTRY)]
+// CHECK-NEXT: Succs (1): B11
+// CHECK: [B1]
+// CHECK-NEXT: 1: CFGScopeEnd(i)
+// CHECK-NEXT: Preds (2): B4 B10
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: i
+// CHECK-NEXT: 2: ++[B2.1]
+// CHECK-NEXT: Preds (2): B3 B7
+// CHECK-NEXT: Succs (1): B10
+// CHECK: [B3]
+// CHECK-NEXT: 1: CFGScopeEnd(z)
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: CFGScopeBegin(z)
+// CHECK-NEXT: 2: 5
+// CHECK-NEXT: 3: int z = 5;
+// CHECK-NEXT: 4: CFGScopeEnd(z)
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (2): B6 B8
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B5]
+// CHECK-NEXT: 1: x
+// CHECK-NEXT: 2: [B5.1] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: T: switch [B5.2]
+// CHECK-NEXT: Preds (1): B10
+// CHECK-NEXT: Succs (4): B7 B8 B9 B6
+// CHECK: [B6]
+// CHECK-NEXT: default:
+// CHECK-NEXT: 1: 3
+// CHECK-NEXT: 2: y
+// CHECK-NEXT: 3: [B6.2] = [B6.1]
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B7]
+// CHECK-NEXT: case 2:
+// CHECK-NEXT: 1: 4
+// CHECK-NEXT: 2: y
+// CHECK-NEXT: 3: [B7.2] = [B7.1]
+// CHECK-NEXT: T: continue;
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B8]
+// CHECK-NEXT: case 1:
+// CHECK-NEXT: 1: 2
+// CHECK-NEXT: 2: y
+// CHECK-NEXT: 3: [B8.2] = [B8.1]
+// CHECK-NEXT: T: break;
+// CHECK-NEXT: Preds (2): B5 B9
+// CHECK-NEXT: Succs (1): B4
+// CHECK: [B9]
+// CHECK-NEXT: case 0:
+// CHECK-NEXT: 1: 1
+// CHECK-NEXT: 2: y
+// CHECK-NEXT: 3: [B9.2] = [B9.1]
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B8
+// CHECK: [B10]
+// CHECK-NEXT: 1: i
+// CHECK-NEXT: 2: [B10.1] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: 3: 1000
+// CHECK-NEXT: 4: [B10.2] < [B10.3]
+// CHECK-NEXT: T: for (...; [B10.4]; ...)
+// CHECK-NEXT: Preds (2): B2 B11
+// CHECK-NEXT: Succs (2): B5 B1
+// CHECK: [B11]
+// CHECK-NEXT: 1: CFGScopeBegin(i)
+// CHECK-NEXT: 2: int i;
+// CHECK-NEXT: 3: int x;
+// CHECK-NEXT: 4: int y;
+// CHECK-NEXT: 5: 0
+// CHECK-NEXT: 6: i
+// CHECK-NEXT: 7: [B11.6] = [B11.5]
+// CHECK-NEXT: Preds (1): B12
+// CHECK-NEXT: Succs (1): B10
+// CHECK: [B0 (EXIT)]
+// CHECK-NEXT: Preds (1): B1
+void test_for_switch_in_for() {
+ int i, x, y;
+ for (i = 0; i < 1000; ++i) {
+ switch (x) {
+ case 0:
+ y = 1;
+ case 1:
+ y = 2;
+ break; // break from switch
+ case 2:
+ y = 4;
+ continue; // continue in loop
+ default:
+ y = 3;
+ }
+ {
+ int z = 5;
+ break; // break from loop
+ }
+ }
+}
diff --git a/test/Analysis/structured_bindings.cc b/test/Analysis/structured_bindings.cc
new file mode 100644
index 0000000..1e23246
--- /dev/null
+++ b/test/Analysis/structured_bindings.cc
@@ -0,0 +1,10 @@
+// RUN: %clang_analyze_cc1 -std=c++17 -analyzer-checker=core -verify %s
+
+// expected-no-diagnostics
+struct s { int a; };
+int foo() {
+ auto[a] = s{1}; // FIXME: proper modelling
+ if (a) {
+ }
+}
+
diff --git a/test/Analysis/symbol-reaper.c b/test/Analysis/symbol-reaper.c
index 72fcc7e..a47161b 100644
--- a/test/Analysis/symbol-reaper.c
+++ b/test/Analysis/symbol-reaper.c
@@ -3,6 +3,9 @@
void clang_analyzer_eval(int);
void clang_analyzer_warnOnDeadSymbol(int);
void clang_analyzer_numTimesReached();
+void clang_analyzer_warnIfReached();
+
+void exit(int);
int conjure_index();
@@ -58,6 +61,12 @@
struct S2 {
struct S1 array[5];
} s2;
+struct S3 {
+ void *field;
+};
+
+struct S1 *conjure_S1();
+struct S3 *conjure_S3();
void test_element_index_lifetime_with_complicated_hierarchy_of_regions() {
do {
@@ -68,6 +77,18 @@
} while (0); // no-warning
}
+void test_loc_as_integer_element_index_lifetime() {
+ do {
+ int x;
+ struct S3 *s = conjure_S3();
+ clang_analyzer_warnOnDeadSymbol((int)s);
+ x = (int)&(s->field);
+ ptr = &arr[x];
+ if (s) {}
+ // FIXME: Should not warn. The symbol is still alive within the ptr's index.
+ } while (0); // expected-warning{{SYMBOL DEAD}}
+}
+
// Test below checks lifetime of SymbolRegionValue in certain conditions.
int **ptrptr;
@@ -78,3 +99,38 @@
(void)0; // No-op; make sure the environment forgets things and the GC runs.
clang_analyzer_eval(**ptrptr); // expected-warning{{TRUE}}
} // no-warning
+
+int *produce_region_referenced_only_through_field_in_environment_value() {
+ struct S1 *s = conjure_S1();
+ clang_analyzer_warnOnDeadSymbol((int) s);
+ int *x = &s->field;
+ return x;
+}
+
+void test_region_referenced_only_through_field_in_environment_value() {
+ produce_region_referenced_only_through_field_in_environment_value();
+} // expected-warning{{SYMBOL DEAD}}
+
+void test_region_referenced_only_through_field_in_store_value() {
+ struct S1 *s = conjure_S1();
+ clang_analyzer_warnOnDeadSymbol((int) s);
+ ptr = &s->field; // Write the symbol into a global. It should live forever.
+ if (!s) {
+ exit(0); // no-warning (symbol should not die here)
+ // exit() is noreturn.
+ clang_analyzer_warnIfReached(); // no-warning
+ }
+ if (!ptr) { // no-warning (symbol should not die here)
+ // We exit()ed under these constraints earlier.
+ clang_analyzer_warnIfReached(); // no-warning
+ }
+ // The exit() call invalidates globals. The symbol will die here because
+ // the exit() statement itself is already over and there's no better statement
+ // to put the diagnostic on.
+} // expected-warning{{SYMBOL DEAD}}
+
+void test_zombie_referenced_only_through_field_in_store_value() {
+ struct S1 *s = conjure_S1();
+ clang_analyzer_warnOnDeadSymbol((int) s);
+ int *x = &s->field;
+} // expected-warning{{SYMBOL DEAD}}
diff --git a/test/Analysis/temp-obj-dtors-cfg-output.cpp b/test/Analysis/temp-obj-dtors-cfg-output.cpp
index d17c5be..0b9397d 100644
--- a/test/Analysis/temp-obj-dtors-cfg-output.cpp
+++ b/test/Analysis/temp-obj-dtors-cfg-output.cpp
@@ -205,6 +205,24 @@
return 0;
}
+namespace pass_references_through {
+class C {
+public:
+ ~C() {}
+};
+
+const C &foo1();
+C &&foo2();
+
+// In these examples the foo() expression has record type, not reference type.
+// Don't try to figure out how to perform construction of the record here.
+const C &bar1() { return foo1(); } // no-crash
+C &&bar2() { return foo2(); } // no-crash
+const C &bar3(bool coin) {
+ return coin ? foo1() : foo1(); // no-crash
+}
+} // end namespace pass_references_through
+
// CHECK: [B1 (ENTRY)]
// CHECK: Succs (1): B0
// CHECK: [B0 (EXIT)]
@@ -1111,7 +1129,8 @@
// CHECK: [B1]
// CHECK: 1: A::make
// CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void))
-// CHECK: 3: [B1.2]()
+// WARNINGS: 3: [B1.2]()
+// ANALYZER: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6])
// CHECK: 4: [B1.3] (BindTemporary)
// CHECK: 5: [B1.4] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 6: [B1.5]
@@ -1130,7 +1149,8 @@
// CHECK: [B1]
// CHECK: 1: A::make
// CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void))
-// CHECK: 3: [B1.2]()
+// WARNINGS: 3: [B1.2]()
+// ANALYZER: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6])
// CHECK: 4: [B1.3] (BindTemporary)
// CHECK: 5: [B1.4] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 6: [B1.5]
@@ -1139,7 +1159,8 @@
// CHECK: 9: [B1.8] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &))
// CHECK: 10: A::make
// CHECK: 11: [B1.10] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void))
-// CHECK: 12: [B1.11]()
+// WARNINGS: 12: [B1.11]()
+// ANALYZER: 12: [B1.11]() (CXXRecordTypedCall, [B1.13], [B1.15])
// CHECK: 13: [B1.12] (BindTemporary)
// CHECK: 14: [B1.13] (ImplicitCastExpr, NoOp, const class A)
// CHECK: 15: [B1.14]
@@ -1399,3 +1420,29 @@
// CHECK: Succs (2): B8 B1
// CHECK: [B0 (EXIT)]
// CHECK: Preds (3): B1 B2 B4
+// CHECK: [B1 (ENTRY)]
+// CHECK: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK: Preds (1): B1
+// CHECK: [B2 (ENTRY)]
+// CHECK: Succs (1): B1
+// CHECK: [B1]
+// CHECK: 1: foo1
+// CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, const class pass_references_through::C &(*)(void))
+// CHECK: 3: [B1.2]()
+// CHECK: 4: return [B1.3];
+// CHECK: Preds (1): B2
+// CHECK: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK: Preds (1): B1
+// CHECK: [B2 (ENTRY)]
+// CHECK: Succs (1): B1
+// CHECK: [B1]
+// CHECK: 1: foo2
+// CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class pass_references_through::C &&(*)(void))
+// CHECK: 3: [B1.2]()
+// CHECK: 4: return [B1.3];
+// CHECK: Preds (1): B2
+// CHECK: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK: Preds (1): B1
diff --git a/test/Analysis/temporaries.cpp b/test/Analysis/temporaries.cpp
index dce4858..964e7f1 100644
--- a/test/Analysis/temporaries.cpp
+++ b/test/Analysis/temporaries.cpp
@@ -1,6 +1,9 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify -w -std=c++03 %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify -w -std=c++11 %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true %s -std=c++11
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -w -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true %s -std=c++17
+
+// Note: The C++17 run-line doesn't -verify yet - it is a no-crash test.
extern bool clang_analyzer_eval(bool);
extern bool clang_analyzer_warnIfReached();
@@ -895,6 +898,45 @@
}
} // namespace test_match_constructors_and_destructors
+namespace destructors_for_return_values {
+
+class C {
+public:
+ ~C() {
+ 1 / 0; // expected-warning{{Division by zero}}
+ }
+};
+
+C make();
+
+void testFloatingCall() {
+ make();
+ // Should have divided by zero in the destructor.
+ clang_analyzer_warnIfReached();
+#ifndef TEMPORARY_DTORS
+ // expected-warning@-2{{REACHABLE}}
+#endif
+}
+
+void testLifetimeExtendedCall() {
+ {
+ const C &c = make();
+ clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+ }
+ // Should have divided by zero in the destructor.
+ clang_analyzer_warnIfReached(); // no-warning
+}
+
+void testCopiedCall() {
+ C c = make();
+ // Should have divided by zero in the temporary destructor.
+ clang_analyzer_warnIfReached();
+#ifndef TEMPORARY_DTORS
+ // expected-warning@-2{{REACHABLE}}
+#endif
+}
+} // namespace destructors_for_return_values
+
namespace dont_forget_destructor_around_logical_op {
int glob;
@@ -922,8 +964,17 @@
// return value of get() was initialized. However, we didn't track
// temporaries returned from functions, so we took the wrong branch.
coin && is(get()); // no-crash
- // FIXME: Should be true once we inline all destructors.
- clang_analyzer_eval(glob); // expected-warning{{UNKNOWN}}
+ if (coin) {
+ clang_analyzer_eval(glob);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+ } else {
+ // The destructor is not called on this branch.
+ clang_analyzer_eval(glob); // expected-warning{{UNKNOWN}}
+ }
}
} // namespace dont_forget_destructor_around_logical_op
@@ -940,3 +991,61 @@
}
} // namespace temporary_list_crash
#endif // C++11
+
+namespace implicit_constructor_conversion {
+struct S {
+ int x;
+ S(int x) : x(x) {}
+ ~S() {}
+};
+
+class C {
+ int x;
+
+public:
+ C(const S &s) : x(s.x) {}
+ ~C() {}
+ int getX() const { return x; }
+};
+
+void test() {
+ const C &c1 = S(10);
+ clang_analyzer_eval(c1.getX() == 10);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+
+ S s = 20;
+ clang_analyzer_eval(s.x == 20);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+
+ C c2 = s;
+ clang_analyzer_eval(c2.getX() == 20);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+}
+} // end namespace implicit_constructor_conversion
+
+namespace pass_references_through {
+class C {
+public:
+ ~C() {}
+};
+
+const C &foo1();
+C &&foo2();
+
+// In these examples the foo() expression has record type, not reference type.
+// Don't try to figure out how to perform construction of the record here.
+const C &bar1() { return foo1(); } // no-crash
+C &&bar2() { return foo2(); } // no-crash
+} // end namespace pass_references_through
diff --git a/test/Analysis/trustnonnullchecker_test.m b/test/Analysis/trustnonnullchecker_test.m
new file mode 100644
index 0000000..83fc782
--- /dev/null
+++ b/test/Analysis/trustnonnullchecker_test.m
@@ -0,0 +1,43 @@
+// RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-checker=core,nullability,apiModeling -verify %s
+
+#include "Inputs/system-header-simulator-for-nullability.h"
+
+NSString* getUnknownString();
+
+NSString* _Nonnull trust_nonnull_framework_annotation() {
+ NSString* out = [NSString generateString];
+ if (out) {}
+ return out; // no-warning
+}
+
+NSString* _Nonnull distrust_without_annotation() {
+ NSString* out = [NSString generatePossiblyNullString];
+ if (out) {}
+ return out; // expected-warning{{}}
+}
+
+NSString* _Nonnull nonnull_please_trust_me();
+
+NSString* _Nonnull distrust_local_nonnull_annotation() {
+ NSString* out = nonnull_please_trust_me();
+ if (out) {}
+ return out; // expected-warning{{}}
+}
+
+NSString* _Nonnull trust_c_function() {
+ NSString* out = getString();
+ if (out) {};
+ return out; // no-warning
+}
+
+NSString* _Nonnull distrust_unannoted_function() {
+ NSString* out = getPossiblyNullString();
+ if (out) {};
+ return out; // expected-warning{{}}
+}
+
+NSString * _Nonnull distrustProtocol(id<MyProtocol> o) {
+ NSString* out = [o getString];
+ if (out) {};
+ return out; // expected-warning{{}}
+}
diff --git a/test/Analysis/trustnonnullchecker_test.mm b/test/Analysis/trustnonnullchecker_test.mm
new file mode 100644
index 0000000..fa84673
--- /dev/null
+++ b/test/Analysis/trustnonnullchecker_test.mm
@@ -0,0 +1,9 @@
+// RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-checker=core,nullability,apiModeling -verify %s
+
+#include "Inputs/system-header-simulator-for-nullability-cxx.h"
+
+// expected-no-diagnostics
+
+void blah() {
+ foo(); // no-crash
+}
diff --git a/test/CXX/class/class.bit/p2.cpp b/test/CXX/class/class.bit/p2.cpp
index 7962330..8b2436a 100644
--- a/test/CXX/class/class.bit/p2.cpp
+++ b/test/CXX/class/class.bit/p2.cpp
@@ -9,7 +9,7 @@
A a2 = { 1 }; // expected-error{{excess elements in struct initializer}}
struct B {
- const int : 0;
+ const int : 0; // expected-error{{anonymous bit-field cannot have qualifiers}}
};
B b;
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
index cfb9a61..96be58f 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
@@ -5,8 +5,7 @@
A(int) -> A<char>;
static constexpr inline const volatile A a = {}; // ok, specifiers are permitted
-// FIXME: There isn't really a good reason to reject this.
-A b; // expected-error {{requires an initializer}}
+A b;
A c [[]] {};
A d = {}, e = {};
@@ -16,3 +15,5 @@
static A a; // expected-error {{requires an initializer}}
};
extern A x; // expected-error {{requires an initializer}}
+static A y;
+
diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp
index fbca663..a311d8f 100644
--- a/test/CXX/drs/dr0xx.cpp
+++ b/test/CXX/drs/dr0xx.cpp
@@ -499,10 +499,10 @@
// dr43: na
-namespace dr44 { // dr44: yes
+namespace dr44 { // dr44: sup 727
struct A {
template<int> void f();
- template<> void f<0>(); // expected-error {{explicit specialization of 'f' in class scope}}
+ template<> void f<0>();
};
}
diff --git a/test/CXX/drs/dr10xx.cpp b/test/CXX/drs/dr10xx.cpp
index e1db9ef..7f5fd8c 100644
--- a/test/CXX/drs/dr10xx.cpp
+++ b/test/CXX/drs/dr10xx.cpp
@@ -31,9 +31,8 @@
// This example (from the standard) is actually ill-formed, because
// name lookup of "T::template A" names the constructor.
- // FIXME: Only issue one diagnostic for this case.
- template<class T, template<class> class U = T::template A> struct Third { }; // expected-error 2{{is a constructor name}}
- Third<A<int> > t; // expected-note {{in instantiation of}} expected-note {{while substituting}} expected-note {{while checking}}
+ template<class T, template<class> class U = T::template A> struct Third { }; // expected-error {{is a constructor name}}
+ Third<A<int> > t; // expected-note {{in instantiation of default argument}}
}
namespace dr1048 { // dr1048: 3.6
diff --git a/test/CXX/drs/dr22xx.cpp b/test/CXX/drs/dr22xx.cpp
new file mode 100644
index 0000000..55b3d78
--- /dev/null
+++ b/test/CXX/drs/dr22xx.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+
+namespace dr2229 { // dr2229: yes
+struct AnonBitfieldQualifiers {
+ const unsigned : 1; // expected-error {{anonymous bit-field cannot have qualifiers}}
+ volatile unsigned : 1; // expected-error {{anonymous bit-field cannot have qualifiers}}
+ const volatile unsigned : 1; // expected-error {{anonymous bit-field cannot have qualifiers}}
+
+ unsigned : 1;
+ const unsigned i1 : 1;
+ volatile unsigned i2 : 1;
+ const volatile unsigned i3 : 1;
+};
+}
diff --git a/test/CXX/drs/dr3xx.cpp b/test/CXX/drs/dr3xx.cpp
index 3342148..0de2d49 100644
--- a/test/CXX/drs/dr3xx.cpp
+++ b/test/CXX/drs/dr3xx.cpp
@@ -925,7 +925,7 @@
using namespace A::B; // expected-error {{expected namespace name}}
}
-namespace dr374 { // dr374: yes c++11
+namespace dr374 { // dr374: yes
namespace N {
template<typename T> void f();
template<typename T> struct A { void f(); };
@@ -933,11 +933,6 @@
template<> void N::f<char>() {}
template<> void N::A<char>::f() {}
template<> struct N::A<int> {};
-#if __cplusplus < 201103L
- // expected-error@-4 {{extension}} expected-note@-7 {{here}}
- // expected-error@-4 {{extension}} expected-note@-7 {{here}}
- // expected-error@-4 {{extension}} expected-note@-8 {{here}}
-#endif
}
// dr375: dup 345
diff --git a/test/CXX/drs/dr7xx.cpp b/test/CXX/drs/dr7xx.cpp
index fe4a2dc..982ffdd 100644
--- a/test/CXX/drs/dr7xx.cpp
+++ b/test/CXX/drs/dr7xx.cpp
@@ -3,6 +3,53 @@
// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+namespace dr727 { // dr727: 7
+ struct A {
+ template<typename T> struct C; // expected-note 6{{here}}
+ template<typename T> void f(); // expected-note {{here}}
+ template<typename T> static int N; // expected-error 0-1{{C++14}} expected-note 6{{here}}
+
+ template<> struct C<int>;
+ template<> void f<int>();
+ template<> static int N<int>;
+
+ template<typename T> struct C<T*>;
+ template<typename T> static int N<T*>;
+
+ struct B {
+ template<> struct C<float>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<> void f<float>(); // expected-error {{no function template matches}}
+ template<> static int N<float>; // expected-error {{not in class 'A' or an enclosing namespace}}
+
+ template<typename T> struct C<T**>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<typename T> static int N<T**>; // expected-error {{not in class 'A' or an enclosing namespace}}
+
+ template<> struct A::C<double>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<> void A::f<double>(); // expected-error {{no function template matches}} expected-error {{cannot have a qualified name}}
+ template<> static int A::N<double>; // expected-error {{not in class 'A' or an enclosing namespace}} expected-error {{cannot have a qualified name}}
+
+ template<typename T> struct A::C<T***>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<typename T> static int A::N<T***>; // expected-error {{not in class 'A' or an enclosing namespace}} expected-error {{cannot have a qualified name}}
+ };
+ };
+
+ template<> struct A::C<char>;
+ template<> void A::f<char>();
+ template<> int A::N<char>;
+
+ template<typename T> struct A::C<T****>;
+ template<typename T> int A::N<T****>;
+
+ namespace C {
+ template<> struct A::C<long>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<> void A::f<long>(); // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<> int A::N<long>; // expected-error {{not in class 'A' or an enclosing namespace}}
+
+ template<typename T> struct A::C<T*****>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ template<typename T> int A::N<T*****>; // expected-error {{not in class 'A' or an enclosing namespace}}
+ }
+}
+
namespace dr777 { // dr777: 3.7
#if __cplusplus >= 201103L
template <typename... T>
@@ -16,5 +63,3 @@
void h(int i = 0, T ...args, int j = 1) {}
#endif
}
-
-// expected-no-diagnostics
diff --git a/test/CXX/stmt.stmt/stmt.select/p3.cpp b/test/CXX/stmt.stmt/stmt.select/p3.cpp
index 35e5c91..7a6a408 100644
--- a/test/CXX/stmt.stmt/stmt.select/p3.cpp
+++ b/test/CXX/stmt.stmt/stmt.select/p3.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++14-compat -verify %s -DCPP17
int f();
@@ -10,10 +11,67 @@
}
}
-
void h() {
if (int x = f()) // expected-note 2{{previous definition}}
int x; // expected-error{{redefinition of 'x'}}
else
int x; // expected-error{{redefinition of 'x'}}
}
+
+void ifInitStatement() {
+ int Var = 0;
+
+ if (int I = 0; true) {}
+ if (Var + Var; true) {}
+ if (; true) {}
+#ifdef CPP17
+ // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+ // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+ // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+#else
+ // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+ // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+ // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+#endif
+}
+
+void switchInitStatement() {
+ int Var = 0;
+
+ switch (int I = 0; Var) {}
+ switch (Var + Var; Var) {}
+ switch (; Var) {}
+#ifdef CPP17
+ // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+ // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+ // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+#else
+ // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+ // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+ // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+#endif
+}
+
+// TODO: Better diagnostics for while init statements.
+void whileInitStatement() {
+ while (int I = 10; I--); // expected-error {{expected ')'}}
+ // expected-note@-1 {{to match this '('}}
+ // expected-error@-2 {{use of undeclared identifier 'I'}}
+
+ int Var = 10;
+ while (Var + Var; Var--) {} // expected-error {{expected ')'}}
+ // expected-note@-1 {{to match this '('}}
+ // expected-error@-2 {{expected ';' after expression}}
+ // expected-error@-3 {{expected expression}}
+ // expected-warning@-4 {{while loop has empty body}}
+ // expected-note@-5 {{put the semicolon on a separate line to silence this warning}}
+}
+
+// TODO: This is needed because clang can't seem to diagnose invalid syntax after the
+// last loop above. It would be nice to remove this.
+void whileInitStatement2() {
+ while (; false) {} // expected-error {{expected expression}}
+ // expected-warning@-1 {{expression result unused}}
+ // expected-error@-2 {{expected ';' after expression}}
+ // expected-error@-3 {{expected expression}}
+}
diff --git a/test/CXX/temp/temp.deduct.guide/p1.cpp b/test/CXX/temp/temp.deduct.guide/p1.cpp
index c0a2ba1..8bb9da8 100644
--- a/test/CXX/temp/temp.deduct.guide/p1.cpp
+++ b/test/CXX/temp/temp.deduct.guide/p1.cpp
@@ -101,7 +101,7 @@
struct X {
template<typename T> struct C {};
template<typename T> C(T) -> C<T>;
- template<> C(int) -> C<int>; // expected-error {{explicit specialization of '<deduction guide for C>' in class scope}}
+ template<> C(int) -> C<int>; // expected-error {{deduction guide cannot be explicitly specialized}}
extern template C(float) -> C<float>; // expected-error {{expected member name or ';'}}
template C(char) -> C<char>; // expected-error {{expected '<' after 'template'}}
};
diff --git a/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp b/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
index 425d527..741ebc5 100644
--- a/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
+++ b/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
@@ -28,10 +28,8 @@
// Should recover as if specialization
template float pi1<float> = 1.0; // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}}
-#ifndef FIXING
namespace expected_global {
- template<> double pi1<double> = 1.5; // expected-error {{variable template specialization of 'pi1' must originally be declared in the global scope}}
- template int pi1<int> = 10; // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}} \
- expected-error {{variable template specialization of 'pi1' must originally be declared in the global scope}}
-}
+#ifndef FIXING
+ template int pi1<int> = 10; // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}} expected-error {{must occur at global scope}}
#endif
+}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp
index d0e24f5..c29646d 100644
--- a/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp
@@ -10,9 +10,6 @@
NonDefaultConstructible(int);
};
-// FIXME: The "must originally be declared in namespace" diagnostics throughout
-// this file are wrong.
-
// C++ [temp.expl.spec]p1:
// An explicit specialization of any of the following:
@@ -43,7 +40,7 @@
struct X1 {
template<typename T> void f(T);
- template<> void f(int); // expected-error{{in class scope}}
+ template<> void f(int); // OK (DR727)
};
// -- class template
@@ -94,7 +91,7 @@
// -- variable template [C++1y]
namespace N0 {
-template<typename T> int v0; // expected-note +{{here}}
+template<typename T> int v0; // expected-note 4{{explicitly specialized declaration is here}}
template<> extern int v0<char[1]>;
template<> extern int v0<char[2]>;
template<> extern int v0<char[5]>;
@@ -102,32 +99,32 @@
}
using N0::v0;
-template<typename T> int v1; // expected-note +{{here}}
+template<typename T> int v1; // expected-note 4{{explicitly specialized declaration is here}}
template<> extern int v1<char[3]>;
template<> extern int v1<char[4]>;
template<> extern int v1<char[7]>;
template<> extern int v1<char[8]>;
template<> int N0::v0<int[1]>;
-template<> int v0<int[2]>; // FIXME: ill-formed
+template<> int v0<int[2]>;
template<> int ::v1<int[3]>; // expected-warning {{extra qualification}}
template<> int v1<int[4]>;
template<> int N0::v0<char[1]>;
-template<> int v0<char[2]>; // FIXME: ill-formed
+template<> int v0<char[2]>;
template<> int ::v1<char[3]>; // expected-warning {{extra qualification}}
template<> int v1<char[4]>;
namespace N1 {
-template<> int N0::v0<int[5]>; // expected-error {{must originally be declared in namespace 'N0'}} expected-error {{does not enclose namespace}}
-template<> int v0<int[6]>; // expected-error {{must originally be declared in namespace 'N0'}}
-template<> int ::v1<int[7]>; // expected-error {{must originally be declared in the global scope}} expected-error {{cannot name the global scope}}
-template<> int v1<int[8]>; // expected-error {{must originally be declared in the global scope}}
+template<> int N0::v0<int[5]>; // expected-error {{not in a namespace enclosing 'N0'}}
+template<> int v0<int[6]>; // expected-error {{not in a namespace enclosing 'N0'}}
+template<> int ::v1<int[7]>; // expected-error {{must occur at global scope}}
+template<> int v1<int[8]>; // expected-error {{must occur at global scope}}
-template<> int N0::v0<char[5]>; // expected-error {{does not enclose namespace 'N0'}}
-template<> int v0<char[6]>; // FIXME: ill-formed
-template<> int ::v1<char[7]>; // expected-error {{cannot name the global scope}}
-template<> int v1<char[8]>; // FIXME: ill-formed
+template<> int N0::v0<char[5]>; // expected-error {{not in a namespace enclosing 'N0'}}
+template<> int v0<char[6]>; // expected-error {{not in a namespace enclosing 'N0'}}
+template<> int ::v1<char[7]>; // expected-error {{must occur at global scope}}
+template<> int v1<char[8]>; // expected-error {{must occur at global scope}}
}
// -- member function of a class template
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
index 21399b6..904f950 100644
--- a/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
@@ -20,9 +20,6 @@
// -- function template
namespace N0 {
template<typename T> void f0(T) {
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
T t;
}
@@ -43,16 +40,13 @@
}
template<> void N0::f0(double);
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of function template specialization of 'f0' outside namespace 'N0' is a C++11 extension}}
-#endif
template<> void N0::f0(double) { }
struct X1 {
template<typename T> void f(T);
- template<> void f(int); // expected-error{{in class scope}}
+ template<> void f(int);
};
// -- class template
@@ -60,38 +54,20 @@
template<typename T>
struct X0 { // expected-note {{explicitly specialized declaration is here}}
-#if __cplusplus <= 199711L
-// expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
static T member;
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
void f1(T t) {
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
t = 17;
}
struct Inner : public T { }; // expected-note 2{{explicitly specialized declaration is here}}
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
template<typename U>
struct InnerTemplate : public T { }; // expected-note {{explicitly specialized declaration is here}}
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
- // expected-error@-4 {{base specifier must name a class}}
+ // expected-error@-1 {{base specifier must name a class}}
template<typename U>
void ft1(T t, U u);
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
};
}
@@ -105,9 +81,6 @@
template<typename T> T N0::X0<T>::member;
template<> struct N0::X0<void> { };
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of class template specialization of 'X0' outside namespace 'N0' is a C++11 extension}}
-#endif
N0::X0<void> test_X0;
namespace N1 {
@@ -124,9 +97,6 @@
// -- member function of a class template
template<> void N0::X0<void*>::f1(void *) { }
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of member function specialization of 'f1' outside namespace 'N0' is a C++11 extension}}
-#endif
void test_spec(N0::X0<void*> xvp, void *vp) {
xvp.f1(vp);
@@ -160,9 +130,6 @@
}
template<> int N0::X0<int>::member;
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of static data member specialization of 'member' outside namespace 'N0' is a C++11 extension}}
-#endif
template<> float N0::X0<float>::member = 3.14f;
@@ -191,9 +158,6 @@
template<>
struct N0::X0<long>::Inner { };
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of member class specialization of 'Inner' outside namespace 'N0' is a C++11 extension}}
-#endif
template<>
struct N0::X0<float>::Inner { };
@@ -233,9 +197,6 @@
template<> template<>
struct N0::X0<int>::InnerTemplate<float> { };
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of class template specialization of 'InnerTemplate' outside namespace 'N0' is a C++11 extension}}
-#endif
namespace N1 {
template<> template<>
@@ -268,9 +229,6 @@
template<> template<>
void N0::X0<void*>::ft1(void *, float) { }
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of function template specialization of 'ft1' outside namespace 'N0' is a C++11 extension}}
-#endif
namespace N1 {
template<> template<>
@@ -293,6 +251,6 @@
template<typename T, typename U> void f(Inner<T, U>&);
typedef Inner<OtherInner, OtherInner> MyInner;
- template<> void f(MyInner&); // expected-error{{cannot specialize a function 'f' within class scope}}
+ template<> void f(MyInner&);
};
}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
index d82691c..ca55c54 100644
--- a/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
@@ -4,17 +4,9 @@
namespace N {
template<class T> class X; // expected-note {{'N::X' declared here}}
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized declaration is here}}
-#endif
}
-// TODO: Don't add a namespace qualifier to the template if it would trigger
-// the warning about the specialization being outside of the namespace.
template<> class X<int> { /* ... */ }; // expected-error {{no template named 'X'; did you mean 'N::X'?}}
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of class template specialization of 'X' outside namespace 'N' is a C++11 extension}}
-#endif
namespace N {
diff --git a/test/CodeCompletion/enable-if-attr-crash.cpp b/test/CodeCompletion/enable-if-attr-crash.cpp
new file mode 100644
index 0000000..cca84b2
--- /dev/null
+++ b/test/CodeCompletion/enable-if-attr-crash.cpp
@@ -0,0 +1,8 @@
+int foo(bool x) __attribute__((enable_if(x, "")));
+
+int test() {
+ bool fffffff;
+ // RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:7:8 %s | FileCheck %s
+ // CHECK: COMPLETION: fffffff : [#bool#]fffffff
+ foo(ff
+}
diff --git a/test/CodeGen/64bit-swiftcall.c b/test/CodeGen/64bit-swiftcall.c
index c5944b9..7486e44 100644
--- a/test/CodeGen/64bit-swiftcall.c
+++ b/test/CodeGen/64bit-swiftcall.c
@@ -108,9 +108,7 @@
TEST(struct_1);
// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_1() {{.*}}{
// CHECK: [[RET:%.*]] = alloca [[STRUCT1:%.*]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[STRUCT1]], align 4
// CHECK: call void @llvm.memset
-// CHECK: call void @llvm.memcpy
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT1]]* %retval to { i64, i64 }*
// CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4
@@ -158,12 +156,8 @@
TEST(struct_2);
// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_2() {{.*}}{
// CHECK: [[RET:%.*]] = alloca [[STRUCT2_TYPE]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[STRUCT2_TYPE]], align 4
-// CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[VAR]]
+// CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[RET]]
// CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[CASTVAR]], {{.*}}[[STRUCT2_RESULT]]
-// CHECK: [[CASTRET:%.*]] = bitcast {{.*}} [[RET]]
-// CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[VAR]]
-// CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[CASTRET]], {{.*}}[[CASTVAR]]
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT2_TYPE]]* [[RET]] to { i64, i64 }*
// CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4
@@ -214,12 +208,8 @@
TEST(struct_misaligned_1)
// CHECK-LABEL: define swiftcc i64 @return_struct_misaligned_1()
// CHECK: [[RET:%.*]] = alloca [[STRUCT:%.*]], align 1
-// CHECK: [[RES:%.*]] = alloca [[STRUCT]], align 1
-// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RES]] to i8*
+// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RET]] to i8*
// CHECK: call void @llvm.memset{{.*}}(i8* align 1 [[CAST]], i8 0, i64 5
-// CHECK: [[CASTRET:%.*]] = bitcast [[STRUCT]]* [[RET]] to i8*
-// CHECK: [[CASTRES:%.*]] = bitcast [[STRUCT]]* [[RES]] to i8*
-// CHECK: call void @llvm.memcpy{{.*}}(i8* align 1 [[CASTRET]], i8* align 1 [[CASTRES]], i64 5
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RET]] to { i64 }*
// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 1
@@ -267,12 +257,8 @@
TEST(union_het_fp)
// CHECK-LABEL: define swiftcc i64 @return_union_het_fp()
// CHECK: [[RET:%.*]] = alloca [[UNION:%.*]], align 8
-// CHECK: [[RES:%.*]] = alloca [[UNION]], align 8
-// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RES]] to i8*
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to i8*
// CHECK: call void @llvm.memcpy{{.*}}(i8* align 8 [[CAST]]
-// CHECK: [[CASTRET:%.*]] = bitcast [[UNION]]* [[RET]] to i8*
-// CHECK: [[CASTRES:%.*]] = bitcast [[UNION]]* [[RES]] to i8*
-// CHECK: call void @llvm.memcpy{{.*}}(i8* align 8 [[CASTRET]], i8* align 8 [[CASTRES]]
// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to { i64 }*
// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 8
@@ -1032,3 +1018,12 @@
TEST(union_hom_fp_partial2)
// X86-64-LABEL: take_union_hom_fp_partial2(i64, float)
// ARM64-LABEL: take_union_hom_fp_partial2(i64, float)
+
+// At one point, we emitted lifetime.ends without a matching lifetime.start for
+// CoerceAndExpanded args. Since we're not performing optimizations, neither
+// intrinsic should be emitted.
+// CHECK-LABEL: define void @no_lifetime_markers
+void no_lifetime_markers() {
+ // CHECK-NOT: call void @llvm.lifetime.
+ take_int5(return_int5());
+}
diff --git a/test/CodeGen/aarch64-inline-asm.c b/test/CodeGen/aarch64-inline-asm.c
index a1078f1..264df9d 100644
--- a/test/CodeGen/aarch64-inline-asm.c
+++ b/test/CodeGen/aarch64-inline-asm.c
@@ -54,3 +54,23 @@
asm("ldxr %0, %1" : "=r"(val) : "Q"(var));
// CHECK: call i32 asm "ldxr $0, $1", "=r,*Q"(i64* @var)
}
+
+void test_gcc_registers(void) {
+ register unsigned long reg0 asm("r0") = 0;
+ register unsigned long reg1 asm("r1") = 1;
+ register unsigned int reg29 asm("r29") = 2;
+ register unsigned int reg30 asm("r30") = 3;
+
+ // Test remapping register names in register ... asm("rN") statments.
+ // rN register operands in these two inline assembly lines
+ // should get renamed to valid AArch64 registers.
+ asm volatile("hvc #0" : : "r" (reg0), "r" (reg1));
+ // CHECK: call void asm sideeffect "hvc #0", "{x0},{x1}"
+ asm volatile("hvc #0" : : "r" (reg29), "r" (reg30));
+ // CHECK: call void asm sideeffect "hvc #0", "{fp},{lr}"
+
+ // rN registers when used without register ... asm("rN") syntax
+ // should not be remapped.
+ asm volatile("mov r0, r1\n");
+ // CHECK: call void asm sideeffect "mov r0, r1\0A", ""()
+}
diff --git a/test/CodeGen/aarch64-neon-perm.c b/test/CodeGen/aarch64-neon-perm.c
index c24447b..c5d5ab1 100644
--- a/test/CodeGen/aarch64-neon-perm.c
+++ b/test/CodeGen/aarch64-neon-perm.c
@@ -888,18 +888,14 @@
// CHECK-LABEL: @test_vuzp_s8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.int8x8x2_t [[TMP5]], 0
@@ -912,9 +908,8 @@
// CHECK-LABEL: @test_vuzp_s16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -923,9 +918,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int16x4x2_t [[TMP7]], 0
@@ -938,9 +930,8 @@
// CHECK-LABEL: @test_vuzp_s32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -949,9 +940,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int32x2x2_t [[TMP7]], 0
@@ -964,18 +952,14 @@
// CHECK-LABEL: @test_vuzp_u8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.uint8x8x2_t [[TMP5]], 0
@@ -988,9 +972,8 @@
// CHECK-LABEL: @test_vuzp_u16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -999,9 +982,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint16x4x2_t [[TMP7]], 0
@@ -1014,9 +994,8 @@
// CHECK-LABEL: @test_vuzp_u32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -1025,9 +1004,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint32x2x2_t [[TMP7]], 0
@@ -1040,9 +1016,8 @@
// CHECK-LABEL: @test_vuzp_f32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
@@ -1051,9 +1026,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x float> [[VUZP1_I]], <2 x float>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.float32x2x2_t [[TMP7]], 0
@@ -1066,18 +1038,14 @@
// CHECK-LABEL: @test_vuzp_p8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.poly8x8x2_t [[TMP5]], 0
@@ -1090,9 +1058,8 @@
// CHECK-LABEL: @test_vuzp_p16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -1101,9 +1068,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.poly16x4x2_t [[TMP7]], 0
@@ -1116,18 +1080,14 @@
// CHECK-LABEL: @test_vuzpq_s8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL_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> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26, i32 28, i32 30>
// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 32, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.int8x16x2_t [[TMP5]], 0
@@ -1140,9 +1100,8 @@
// CHECK-LABEL: @test_vuzpq_s16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -1151,9 +1110,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int16x8x2_t [[TMP7]], 0
@@ -1166,9 +1122,8 @@
// CHECK-LABEL: @test_vuzpq_s32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -1177,9 +1132,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int32x4x2_t [[TMP7]], 0
@@ -1192,18 +1144,14 @@
// CHECK-LABEL: @test_vuzpq_u8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL_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> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26, i32 28, i32 30>
// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 32, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.uint8x16x2_t [[TMP5]], 0
@@ -1216,9 +1164,8 @@
// CHECK-LABEL: @test_vuzpq_u16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -1227,9 +1174,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint16x8x2_t [[TMP7]], 0
@@ -1242,9 +1186,8 @@
// CHECK-LABEL: @test_vuzpq_u32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -1253,9 +1196,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint32x4x2_t [[TMP7]], 0
@@ -1268,9 +1208,8 @@
// CHECK-LABEL: @test_vuzpq_f32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
@@ -1279,9 +1218,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x float> [[VUZP1_I]], <4 x float>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.float32x4x2_t [[TMP7]], 0
@@ -1294,18 +1230,14 @@
// CHECK-LABEL: @test_vuzpq_p8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL_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> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26, i32 28, i32 30>
// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 32, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.poly8x16x2_t [[TMP5]], 0
@@ -1318,9 +1250,8 @@
// CHECK-LABEL: @test_vuzpq_p16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -1329,9 +1260,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.poly16x8x2_t [[TMP7]], 0
@@ -1344,18 +1272,14 @@
// CHECK-LABEL: @test_vzip_s8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.int8x8x2_t [[TMP5]], 0
@@ -1368,9 +1292,8 @@
// CHECK-LABEL: @test_vzip_s16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -1379,9 +1302,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int16x4x2_t [[TMP7]], 0
@@ -1394,9 +1314,8 @@
// CHECK-LABEL: @test_vzip_s32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -1405,9 +1324,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int32x2x2_t [[TMP7]], 0
@@ -1420,18 +1336,14 @@
// CHECK-LABEL: @test_vzip_u8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.uint8x8x2_t [[TMP5]], 0
@@ -1444,9 +1356,8 @@
// CHECK-LABEL: @test_vzip_u16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -1455,9 +1366,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint16x4x2_t [[TMP7]], 0
@@ -1470,9 +1378,8 @@
// CHECK-LABEL: @test_vzip_u32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -1481,9 +1388,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint32x2x2_t [[TMP7]], 0
@@ -1496,9 +1400,8 @@
// CHECK-LABEL: @test_vzip_f32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
@@ -1507,9 +1410,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x float> [[VZIP1_I]], <2 x float>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.float32x2x2_t [[TMP7]], 0
@@ -1522,18 +1422,14 @@
// CHECK-LABEL: @test_vzip_p8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.poly8x8x2_t [[TMP5]], 0
@@ -1546,9 +1442,8 @@
// CHECK-LABEL: @test_vzip_p16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -1557,9 +1452,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.poly16x4x2_t [[TMP7]], 0
@@ -1572,18 +1464,14 @@
// CHECK-LABEL: @test_vzipq_s8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL_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> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 32, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.int8x16x2_t [[TMP5]], 0
@@ -1596,9 +1484,8 @@
// CHECK-LABEL: @test_vzipq_s16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -1607,9 +1494,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int16x8x2_t [[TMP7]], 0
@@ -1622,9 +1506,8 @@
// CHECK-LABEL: @test_vzipq_s32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -1633,9 +1516,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int32x4x2_t [[TMP7]], 0
@@ -1648,18 +1528,14 @@
// CHECK-LABEL: @test_vzipq_u8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL_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> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 32, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.uint8x16x2_t [[TMP5]], 0
@@ -1672,9 +1548,8 @@
// CHECK-LABEL: @test_vzipq_u16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -1683,9 +1558,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint16x8x2_t [[TMP7]], 0
@@ -1698,9 +1570,8 @@
// CHECK-LABEL: @test_vzipq_u32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -1709,9 +1580,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint32x4x2_t [[TMP7]], 0
@@ -1724,9 +1592,8 @@
// CHECK-LABEL: @test_vzipq_f32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
@@ -1735,9 +1602,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x float> [[VZIP1_I]], <4 x float>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.float32x4x2_t [[TMP7]], 0
@@ -1750,18 +1614,14 @@
// CHECK-LABEL: @test_vzipq_p8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL_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> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 32, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.poly8x16x2_t [[TMP5]], 0
@@ -1774,9 +1634,8 @@
// CHECK-LABEL: @test_vzipq_p16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -1785,9 +1644,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.poly16x8x2_t [[TMP7]], 0
@@ -1800,18 +1656,14 @@
// CHECK-LABEL: @test_vtrn_s8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.int8x8x2_t [[TMP5]], 0
@@ -1824,9 +1676,8 @@
// CHECK-LABEL: @test_vtrn_s16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -1835,9 +1686,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int16x4x2_t [[TMP7]], 0
@@ -1850,9 +1698,8 @@
// CHECK-LABEL: @test_vtrn_s32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -1861,9 +1708,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int32x2x2_t [[TMP7]], 0
@@ -1876,18 +1720,14 @@
// CHECK-LABEL: @test_vtrn_u8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.uint8x8x2_t [[TMP5]], 0
@@ -1900,9 +1740,8 @@
// CHECK-LABEL: @test_vtrn_u16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -1911,9 +1750,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint16x4x2_t [[TMP7]], 0
@@ -1926,9 +1762,8 @@
// CHECK-LABEL: @test_vtrn_u32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -1937,9 +1772,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint32x2x2_t [[TMP7]], 0
@@ -1952,9 +1784,8 @@
// CHECK-LABEL: @test_vtrn_f32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x2x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
@@ -1963,9 +1794,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
// CHECK: store <2 x float> [[VTRN1_I]], <2 x float>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.float32x2x2_t [[TMP7]], 0
@@ -1978,18 +1806,14 @@
// CHECK-LABEL: @test_vtrn_p8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i64 16, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.poly8x8x2_t [[TMP5]], 0
@@ -2002,9 +1826,8 @@
// CHECK-LABEL: @test_vtrn_p16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -2013,9 +1836,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL_I]], align 8
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.poly16x4x2_t [[TMP7]], 0
@@ -2028,18 +1848,14 @@
// CHECK-LABEL: @test_vtrnq_s8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL_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> <i32 0, i32 16, i32 2, i32 18, i32 4, i32 20, i32 6, i32 22, i32 8, i32 24, i32 10, i32 26, i32 12, i32 28, i32 14, i32 30>
// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 17, i32 3, i32 19, i32 5, i32 21, i32 7, i32 23, i32 9, i32 25, i32 11, i32 27, i32 13, i32 29, i32 15, i32 31>
// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 32, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.int8x16x2_t [[TMP5]], 0
@@ -2052,9 +1868,8 @@
// CHECK-LABEL: @test_vtrnq_s16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -2063,9 +1878,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int16x8x2_t [[TMP7]], 0
@@ -2078,9 +1890,8 @@
// CHECK-LABEL: @test_vtrnq_s32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -2089,9 +1900,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.int32x4x2_t [[TMP7]], 0
@@ -2104,18 +1912,14 @@
// CHECK-LABEL: @test_vtrnq_u8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL_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> <i32 0, i32 16, i32 2, i32 18, i32 4, i32 20, i32 6, i32 22, i32 8, i32 24, i32 10, i32 26, i32 12, i32 28, i32 14, i32 30>
// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 17, i32 3, i32 19, i32 5, i32 21, i32 7, i32 23, i32 9, i32 25, i32 11, i32 27, i32 13, i32 29, i32 15, i32 31>
// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 32, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.uint8x16x2_t [[TMP5]], 0
@@ -2128,9 +1932,8 @@
// CHECK-LABEL: @test_vtrnq_u16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -2139,9 +1942,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint16x8x2_t [[TMP7]], 0
@@ -2154,9 +1954,8 @@
// CHECK-LABEL: @test_vtrnq_u32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -2165,9 +1964,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.uint32x4x2_t [[TMP7]], 0
@@ -2180,9 +1976,8 @@
// CHECK-LABEL: @test_vtrnq_f32(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
@@ -2191,9 +1986,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x float> [[VTRN1_I]], <4 x float>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.float32x4x2_t [[TMP7]], 0
@@ -2206,18 +1998,14 @@
// CHECK-LABEL: @test_vtrnq_p8(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL_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> <i32 0, i32 16, i32 2, i32 18, i32 4, i32 20, i32 6, i32 22, i32 8, i32 24, i32 10, i32 26, i32 12, i32 28, i32 14, i32 30>
// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 17, i32 3, i32 19, i32 5, i32 21, i32 7, i32 23, i32 9, i32 25, i32 11, i32 27, i32 13, i32 29, i32 15, i32 31>
// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP3]], i8* align 16 [[TMP4]], i64 32, i1 false) #2
// CHECK: [[TMP5:%.*]] = load %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP6:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP7:%.*]] = extractvalue %struct.poly8x16x2_t [[TMP5]], 0
@@ -2230,9 +2018,8 @@
// CHECK-LABEL: @test_vtrnq_p16(
// CHECK: [[RETVAL_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 16
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_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>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -2241,9 +2028,6 @@
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false) #2
// CHECK: [[TMP7:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL_I]], align 16
// CHECK: [[TMP8:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], i32 0, i32 0
// CHECK: [[TMP9:%.*]] = extractvalue %struct.poly16x8x2_t [[TMP7]], 0
diff --git a/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c b/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c
index 1a5c3a2..814a959 100644
--- a/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c
+++ b/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c
@@ -1223,27 +1223,25 @@
return vmulxq_n_f16(a, b);
}
-/* TODO: Not implemented yet (needs scalar intrinsic from arm_fp16.h)
-// CCHECK-LABEL: test_vmulxh_lane_f16
-// CCHECK: [[CONV0:%.*]] = fpext half %a to float
-// CCHECK: [[CONV1:%.*]] = fpext half %{{.*}} to float
-// CCHECK: [[MUL:%.*]] = fmul float [[CONV0:%.*]], [[CONV0:%.*]]
-// CCHECK: [[CONV3:%.*]] = fptrunc float %mul to half
-// CCHECK: ret half [[CONV3:%.*]]
+// CHECK-LABEL: test_vmulxh_lane_f16
+// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %b to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK: [[EXTR:%.*]] = extractelement <4 x half> [[TMP1]], i32 3
+// CHECK: [[MULX:%.*]] = call half @llvm.aarch64.neon.fmulx.f16(half %a, half [[EXTR]]
+// CHECK: ret half [[MULX]]
float16_t test_vmulxh_lane_f16(float16_t a, float16x4_t b) {
return vmulxh_lane_f16(a, b, 3);
}
-// CCHECK-LABEL: test_vmulxh_laneq_f16
-// CCHECK: [[CONV0:%.*]] = fpext half %a to float
-// CCHECK: [[CONV1:%.*]] = fpext half %{{.*}} to float
-// CCHECK: [[MUL:%.*]] = fmul float [[CONV0:%.*]], [[CONV0:%.*]]
-// CCHECK: [[CONV3:%.*]] = fptrunc float %mul to half
-// CCHECK: ret half [[CONV3:%.*]]
+// CHECK-LABEL: test_vmulxh_laneq_f16
+// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %b to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK: [[EXTR:%.*]] = extractelement <8 x half> [[TMP1]], i32 7
+// CHECK: [[MULX:%.*]] = call half @llvm.aarch64.neon.fmulx.f16(half %a, half [[EXTR]])
+// CHECK: ret half [[MULX]]
float16_t test_vmulxh_laneq_f16(float16_t a, float16x8_t b) {
return vmulxh_laneq_f16(a, b, 7);
}
-*/
// CHECK-LABEL: test_vmaxv_f16
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
@@ -1350,16 +1348,13 @@
// CHECK-LABEL: test_vzip_f16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[__RET_I:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x half>*
// CHECK: [[VZIP0_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
// CHECK: store <4 x half> [[VZIP0_I]], <4 x half>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, <4 x half>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x half> [[VZIP1_I]], <4 x half>* [[TMP2]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false)
float16x4x2_t test_vzip_f16(float16x4_t a, float16x4_t b) {
return vzip_f16(a, b);
}
@@ -1367,16 +1362,13 @@
// CHECK-LABEL: test_vzipq_f16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[__RET_I:%.*]] = alloca %struct.float16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x half>*
// CHECK: [[VZIP0_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
// CHECK: store <8 x half> [[VZIP0_I]], <8 x half>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, <8 x half>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x half> [[VZIP1_I]], <8 x half>* [[TMP2]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false)
float16x8x2_t test_vzipq_f16(float16x8_t a, float16x8_t b) {
return vzipq_f16(a, b);
}
@@ -1384,16 +1376,13 @@
// CHECK-LABEL: test_vuzp_f16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[__RET_I:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x half>*
// CHECK: [[VZIP0_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
// CHECK: store <4 x half> [[VZIP0_I]], <4 x half>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, <4 x half>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x half> [[VZIP1_I]], <4 x half>* [[TMP2]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false)
float16x4x2_t test_vuzp_f16(float16x4_t a, float16x4_t b) {
return vuzp_f16(a, b);
}
@@ -1401,16 +1390,13 @@
// CHECK-LABEL: test_vuzpq_f16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[__RET_I:%.*]] = alloca %struct.float16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x half>*
// CHECK: [[VZIP0_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
// CHECK: store <8 x half> [[VZIP0_I]], <8 x half>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, <8 x half>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x half> [[VZIP1_I]], <8 x half>* [[TMP2]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false)
float16x8x2_t test_vuzpq_f16(float16x8_t a, float16x8_t b) {
return vuzpq_f16(a, b);
}
@@ -1418,16 +1404,13 @@
// CHECK-LABEL: test_vtrn_f16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[__RET_I:%.*]] = alloca %struct.float16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x half>*
// CHECK: [[VZIP0_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
// CHECK: store <4 x half> [[VZIP0_I]], <4 x half>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <4 x half>, <4 x half>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x half> [[VZIP1_I]], <4 x half>* [[TMP2]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i64 16, i1 false)
float16x4x2_t test_vtrn_f16(float16x4_t a, float16x4_t b) {
return vtrn_f16(a, b);
}
@@ -1435,16 +1418,13 @@
// CHECK-LABEL: test_vtrnq_f16
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[__RET_I:%.*]] = alloca %struct.float16x8x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET_I]] to i8*
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x half>*
// CHECK: [[VZIP0_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
// CHECK: store <8 x half> [[VZIP0_I]], <8 x half>* [[TMP1]]
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x half>, <8 x half>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x half> [[VZIP1_I]], <8 x half>* [[TMP2]]
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP5]], i8* align 16 [[TMP6]], i64 32, i1 false)
float16x8x2_t test_vtrnq_f16(float16x8_t a, float16x8_t b) {
return vtrnq_f16(a, b);
}
diff --git a/test/CodeGen/aggregate-assign-call.c b/test/CodeGen/aggregate-assign-call.c
new file mode 100644
index 0000000..8398372
--- /dev/null
+++ b/test/CodeGen/aggregate-assign-call.c
@@ -0,0 +1,93 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=O1
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O0 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=O0
+//
+// Ensure that we place appropriate lifetime markers around indirectly returned
+// temporaries, and that the lifetime.ends appear in a timely manner.
+//
+// -O1 is used so lifetime markers actually get emitted.
+
+struct S {
+ int ns[40];
+};
+
+struct S foo(void);
+
+// CHECK-LABEL: define dso_local void @bar
+struct S bar() {
+ // O0-NOT: @llvm.lifetime.start
+ // O0-NOT: @llvm.lifetime.end
+
+ struct S r;
+ // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* nonnull %[[TMP1:[^)]+]])
+ // O1: call void @foo
+ r = foo();
+ // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* nonnull %[[TMP1]])
+
+ // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* nonnull %[[TMP2:[^)]+]])
+ // O1: call void @foo
+ r = foo();
+ // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* nonnull %[[TMP2]])
+
+ // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* nonnull %[[TMP3:[^)]+]])
+ // O1: call void @foo
+ r = foo();
+ // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* nonnull %[[TMP3]])
+
+ return r;
+}
+
+struct S foo_int(int);
+
+// Be sure that we're placing the lifetime.end so that all paths go through it.
+// Since this function turns out to be large-ish, optnone to hopefully keep it
+// stable.
+// CHECK-LABEL: define dso_local void @baz
+__attribute__((optnone))
+struct S baz(int i, volatile int *j) {
+ // O0-NOT: @llvm.lifetime.start
+ // O0-NOT: @llvm.lifetime.end
+
+ struct S r;
+ // O1: %[[TMP1_ALLOCA:[^ ]+]] = alloca %struct.S
+ // O1: %[[TMP2_ALLOCA:[^ ]+]] = alloca %struct.S
+ // O1: br label %[[DO_BODY:.+]]
+
+ do {
+ // O1: [[DO_BODY]]:
+ // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
+ // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* %[[P]])
+ // O1: br i1 {{[^,]+}}, label %[[IF_THEN:[^,]+]], label %[[IF_END:[^,]+]]
+ //
+ // O1: [[IF_THEN]]:
+ // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
+ // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
+ // O1: br label %[[DO_END:.*]]
+ //
+ // O1: [[IF_END]]:
+ // O1: call void @foo_int(%struct.S* sret %[[TMP1_ALLOCA]],
+ // O1: call void @llvm.memcpy
+ // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
+ // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
+ // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
+ // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* %[[P]])
+ // O1: call void @foo_int(%struct.S* sret %[[TMP2_ALLOCA]],
+ // O1: call void @llvm.memcpy
+ // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
+ // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
+ // O1: br label %[[DO_COND:.*]]
+ //
+ // O1: [[DO_COND]]:
+ // O1: br label %[[DO_BODY]]
+ r = foo_int(({
+ if (*j)
+ break;
+ i++;
+ }));
+
+ r = foo_int(i++);
+ } while (1);
+
+ // O1: [[DO_END]]:
+ // O1-NEXT: ret void
+ return r;
+}
diff --git a/test/CodeGen/alias.c b/test/CodeGen/alias.c
index 6ec1270..78b0204 100644
--- a/test/CodeGen/alias.c
+++ b/test/CodeGen/alias.c
@@ -23,20 +23,20 @@
extern const int __mod_usb_device_table __attribute__ ((alias("wacom_usb_ids")));
// CHECKBASIC-DAG: @__mod_usb_device_table = alias i32, getelementptr inbounds ([8 x i32], [8 x i32]* @wacom_usb_ids, i32 0, i32 0)
// CHECKASM-DAG: .globl __mod_usb_device_table
-// CHECKASM-DAG: __mod_usb_device_table = wacom_usb_ids
+// CHECKASM-DAG: .set __mod_usb_device_table, wacom_usb_ids
// CHECKASM-NOT: .size __mod_usb_device_table
extern int g1;
extern int g1 __attribute((alias("g0")));
// CHECKBASIC-DAG: @g1 = alias i32, i32* @g0
// CHECKASM-DAG: .globl g1
-// CHECKASM-DAG: g1 = g0
+// CHECKASM-DAG: .set g1, g0
// CHECKASM-NOT: .size g1
extern __thread int __libc_errno __attribute__ ((alias ("TL_WITH_ALIAS")));
// CHECKBASIC-DAG: @__libc_errno = thread_local alias i32, i32* @TL_WITH_ALIAS
// CHECKASM-DAG: .globl __libc_errno
-// CHECKASM-DAG: __libc_errno = TL_WITH_ALIAS
+// CHECKASM-DAG: .set __libc_errno, TL_WITH_ALIAS
// CHECKASM-NOT: .size __libc_errno
void f0(void) { }
diff --git a/test/CodeGen/arm-swiftcall.c b/test/CodeGen/arm-swiftcall.c
index f5c3384..53109a3 100644
--- a/test/CodeGen/arm-swiftcall.c
+++ b/test/CodeGen/arm-swiftcall.c
@@ -103,9 +103,7 @@
TEST(struct_1);
// CHECK-LABEL: define {{.*}} @return_struct_1()
// CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align 4
// CHECK: @llvm.memset
-// CHECK: @llvm.memcpy
// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i16, \[2 x i8\], float, float }]]*
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
// CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4
@@ -170,8 +168,6 @@
TEST(struct_2);
// CHECK-LABEL: define {{.*}} @return_struct_2()
// CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align 4
-// CHECK: @llvm.memcpy
// CHECK: @llvm.memcpy
// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i32, float, float }]]*
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
@@ -240,9 +236,7 @@
TEST(struct_misaligned_1)
// CHECK-LABEL: define {{.*}} @return_struct_misaligned_1()
// CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align
// CHECK: @llvm.memset
-// CHECK: @llvm.memcpy
// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i8 }]]*
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
// CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align
@@ -282,8 +276,6 @@
TEST(union_het_fp)
// CHECK-LABEL: define {{.*}} @return_union_het_fp()
// CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align {{(4|8)}}
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align {{(4|8)}}
-// CHECK: @llvm.memcpy
// CHECK: @llvm.memcpy
// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i32 }]]*
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
@@ -414,7 +406,6 @@
TEST(int8)
// CHECK-LABEL: define {{.*}} @return_int8()
// CHECK: [[RET:%.*]] = alloca [[REC:<8 x i32>]], align 32
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align
// CHECK: store
// CHECK: load
// CHECK: store
@@ -458,7 +449,6 @@
TEST(int5)
// CHECK-LABEL: define {{.*}} @return_int5()
// CHECK: [[RET:%.*]] = alloca [[REC:<5 x i32>]], align 32
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align
// CHECK: store
// CHECK: load
// CHECK: store
diff --git a/test/CodeGen/arm-v8.2a-neon-intrinsics.c b/test/CodeGen/arm-v8.2a-neon-intrinsics.c
new file mode 100644
index 0000000..f9c48de
--- /dev/null
+++ b/test/CodeGen/arm-v8.2a-neon-intrinsics.c
@@ -0,0 +1,982 @@
+// RUN: %clang_cc1 -triple armv8.2a-linux-gnu -target-abi apcs-gnu -target-feature +neon -target-feature +fullfp16 \
+// RUN: -fallow-half-arguments-and-returns -S -disable-O0-optnone -emit-llvm -o - %s \
+// RUN: | opt -S -mem2reg \
+// RUN: | FileCheck %s
+
+// REQUIRES: arm-registered-target
+
+#include <arm_neon.h>
+
+// CHECK-LABEL: test_vabs_f16
+// CHECK: [[ABS:%.*]] = call <4 x half> @llvm.fabs.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[ABS]]
+float16x4_t test_vabs_f16(float16x4_t a) {
+ return vabs_f16(a);
+}
+
+// CHECK-LABEL: test_vabsq_f16
+// CHECK: [[ABS:%.*]] = call <8 x half> @llvm.fabs.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[ABS]]
+float16x8_t test_vabsq_f16(float16x8_t a) {
+ return vabsq_f16(a);
+}
+
+// CHECK-LABEL: test_vceqz_f16
+// CHECK: [[TMP1:%.*]] = fcmp oeq <4 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vceqz_f16(float16x4_t a) {
+ return vceqz_f16(a);
+}
+
+// CHECK-LABEL: test_vceqzq_f16
+// CHECK: [[TMP1:%.*]] = fcmp oeq <8 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vceqzq_f16(float16x8_t a) {
+ return vceqzq_f16(a);
+}
+
+// CHECK-LABEL: test_vcgez_f16
+// CHECK: [[TMP1:%.*]] = fcmp oge <4 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vcgez_f16(float16x4_t a) {
+ return vcgez_f16(a);
+}
+
+// CHECK-LABEL: test_vcgezq_f16
+// CHECK: [[TMP1:%.*]] = fcmp oge <8 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcgezq_f16(float16x8_t a) {
+ return vcgezq_f16(a);
+}
+
+// CHECK-LABEL: test_vcgtz_f16
+// CHECK: [[TMP1:%.*]] = fcmp ogt <4 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vcgtz_f16(float16x4_t a) {
+ return vcgtz_f16(a);
+}
+
+// CHECK-LABEL: test_vcgtzq_f16
+// CHECK: [[TMP1:%.*]] = fcmp ogt <8 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcgtzq_f16(float16x8_t a) {
+ return vcgtzq_f16(a);
+}
+
+// CHECK-LABEL: test_vclez_f16
+// CHECK: [[TMP1:%.*]] = fcmp ole <4 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vclez_f16(float16x4_t a) {
+ return vclez_f16(a);
+}
+
+// CHECK-LABEL: test_vclezq_f16
+// CHECK: [[TMP1:%.*]] = fcmp ole <8 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vclezq_f16(float16x8_t a) {
+ return vclezq_f16(a);
+}
+
+// CHECK-LABEL: test_vcltz_f16
+// CHECK: [[TMP1:%.*]] = fcmp olt <4 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vcltz_f16(float16x4_t a) {
+ return vcltz_f16(a);
+}
+
+// CHECK-LABEL: test_vcltzq_f16
+// CHECK: [[TMP1:%.*]] = fcmp olt <8 x half> %a, zeroinitializer
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcltzq_f16(float16x8_t a) {
+ return vcltzq_f16(a);
+}
+
+// CHECK-LABEL: test_vcvt_f16_s16
+// CHECK: [[VCVT:%.*]] = sitofp <4 x i16> %a to <4 x half>
+// CHECK: ret <4 x half> [[VCVT]]
+float16x4_t test_vcvt_f16_s16 (int16x4_t a) {
+ return vcvt_f16_s16(a);
+}
+
+// CHECK-LABEL: test_vcvtq_f16_s16
+// CHECK: [[VCVT:%.*]] = sitofp <8 x i16> %a to <8 x half>
+// CHECK: ret <8 x half> [[VCVT]]
+float16x8_t test_vcvtq_f16_s16 (int16x8_t a) {
+ return vcvtq_f16_s16(a);
+}
+
+// CHECK-LABEL: test_vcvt_f16_u16
+// CHECK: [[VCVT:%.*]] = uitofp <4 x i16> %a to <4 x half>
+// CHECK: ret <4 x half> [[VCVT]]
+float16x4_t test_vcvt_f16_u16 (uint16x4_t a) {
+ return vcvt_f16_u16(a);
+}
+
+// CHECK-LABEL: test_vcvtq_f16_u16
+// CHECK: [[VCVT:%.*]] = uitofp <8 x i16> %a to <8 x half>
+// CHECK: ret <8 x half> [[VCVT]]
+float16x8_t test_vcvtq_f16_u16 (uint16x8_t a) {
+ return vcvtq_f16_u16(a);
+}
+
+// CHECK-LABEL: test_vcvt_s16_f16
+// CHECK: [[VCVT:%.*]] = fptosi <4 x half> %a to <4 x i16>
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvt_s16_f16 (float16x4_t a) {
+ return vcvt_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtq_s16_f16
+// CHECK: [[VCVT:%.*]] = fptosi <8 x half> %a to <8 x i16>
+// CHECK: ret <8 x i16> [[VCVT]]
+int16x8_t test_vcvtq_s16_f16 (float16x8_t a) {
+ return vcvtq_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvt_u16_f16
+// CHECK: [[VCVT:%.*]] = fptoui <4 x half> %a to <4 x i16>
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvt_u16_f16 (float16x4_t a) {
+ return vcvt_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtq_u16_f16
+// CHECK: [[VCVT:%.*]] = fptoui <8 x half> %a to <8 x i16>
+// CHECK: ret <8 x i16> [[VCVT]]
+int16x8_t test_vcvtq_u16_f16 (float16x8_t a) {
+ return vcvtq_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvta_s16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtas.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvta_s16_f16 (float16x4_t a) {
+ return vcvta_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtaq_s16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtas.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+int16x8_t test_vcvtaq_s16_f16 (float16x8_t a) {
+ return vcvtaq_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtm_s16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtms.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvtm_s16_f16 (float16x4_t a) {
+ return vcvtm_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtmq_s16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtms.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+int16x8_t test_vcvtmq_s16_f16 (float16x8_t a) {
+ return vcvtmq_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtm_u16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtmu.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+uint16x4_t test_vcvtm_u16_f16 (float16x4_t a) {
+ return vcvtm_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtmq_u16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtmu.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+uint16x8_t test_vcvtmq_u16_f16 (float16x8_t a) {
+ return vcvtmq_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtn_s16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtns.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvtn_s16_f16 (float16x4_t a) {
+ return vcvtn_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtnq_s16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtns.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+int16x8_t test_vcvtnq_s16_f16 (float16x8_t a) {
+ return vcvtnq_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtn_u16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtnu.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+uint16x4_t test_vcvtn_u16_f16 (float16x4_t a) {
+ return vcvtn_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtnq_u16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtnu.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+uint16x8_t test_vcvtnq_u16_f16 (float16x8_t a) {
+ return vcvtnq_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtp_s16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtps.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+int16x4_t test_vcvtp_s16_f16 (float16x4_t a) {
+ return vcvtp_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtpq_s16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtps.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+int16x8_t test_vcvtpq_s16_f16 (float16x8_t a) {
+ return vcvtpq_s16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtp_u16_f16
+// CHECK: [[VCVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtpu.v4i16.v4f16(<4 x half> %a)
+// CHECK: ret <4 x i16> [[VCVT]]
+uint16x4_t test_vcvtp_u16_f16 (float16x4_t a) {
+ return vcvtp_u16_f16(a);
+}
+
+// CHECK-LABEL: test_vcvtpq_u16_f16
+// CHECK: [[VCVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtpu.v8i16.v8f16(<8 x half> %a)
+// CHECK: ret <8 x i16> [[VCVT]]
+uint16x8_t test_vcvtpq_u16_f16 (float16x8_t a) {
+ return vcvtpq_u16_f16(a);
+}
+
+// FIXME: Fix the zero constant when fp16 non-storage-only type becomes available.
+// CHECK-LABEL: test_vneg_f16
+// CHECK: [[NEG:%.*]] = fsub <4 x half> <half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000>, %a
+// CHECK: ret <4 x half> [[NEG]]
+float16x4_t test_vneg_f16(float16x4_t a) {
+ return vneg_f16(a);
+}
+
+// CHECK-LABEL: test_vnegq_f16
+// CHECK: [[NEG:%.*]] = fsub <8 x half> <half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000>, %a
+// CHECK: ret <8 x half> [[NEG]]
+float16x8_t test_vnegq_f16(float16x8_t a) {
+ return vnegq_f16(a);
+}
+
+// CHECK-LABEL: test_vrecpe_f16
+// CHECK: [[RCP:%.*]] = call <4 x half> @llvm.arm.neon.vrecpe.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RCP]]
+float16x4_t test_vrecpe_f16(float16x4_t a) {
+ return vrecpe_f16(a);
+}
+
+// CHECK-LABEL: test_vrecpeq_f16
+// CHECK: [[RCP:%.*]] = call <8 x half> @llvm.arm.neon.vrecpe.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RCP]]
+float16x8_t test_vrecpeq_f16(float16x8_t a) {
+ return vrecpeq_f16(a);
+}
+
+// CHECK-LABEL: test_vrnd_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrintz.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrnd_f16(float16x4_t a) {
+ return vrnd_f16(a);
+}
+
+// CHECK-LABEL: test_vrndq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrintz.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndq_f16(float16x8_t a) {
+ return vrndq_f16(a);
+}
+
+// CHECK-LABEL: test_vrnda_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrinta.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrnda_f16(float16x4_t a) {
+ return vrnda_f16(a);
+}
+
+// CHECK-LABEL: test_vrndaq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrinta.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndaq_f16(float16x8_t a) {
+ return vrndaq_f16(a);
+}
+
+// CHECK-LABEL: test_vrndm_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrintm.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrndm_f16(float16x4_t a) {
+ return vrndm_f16(a);
+}
+
+// CHECK-LABEL: test_vrndmq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrintm.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndmq_f16(float16x8_t a) {
+ return vrndmq_f16(a);
+}
+
+// CHECK-LABEL: test_vrndn_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrintn.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrndn_f16(float16x4_t a) {
+ return vrndn_f16(a);
+}
+
+// CHECK-LABEL: test_vrndnq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrintn.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndnq_f16(float16x8_t a) {
+ return vrndnq_f16(a);
+}
+
+// CHECK-LABEL: test_vrndp_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrintp.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrndp_f16(float16x4_t a) {
+ return vrndp_f16(a);
+}
+
+// CHECK-LABEL: test_vrndpq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrintp.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndpq_f16(float16x8_t a) {
+ return vrndpq_f16(a);
+}
+
+// CHECK-LABEL: test_vrndx_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrintx.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrndx_f16(float16x4_t a) {
+ return vrndx_f16(a);
+}
+
+// CHECK-LABEL: test_vrndxq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrintx.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndxq_f16(float16x8_t a) {
+ return vrndxq_f16(a);
+}
+
+// CHECK-LABEL: test_vrsqrte_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.arm.neon.vrsqrte.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrsqrte_f16(float16x4_t a) {
+ return vrsqrte_f16(a);
+}
+
+// CHECK-LABEL: test_vrsqrteq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.arm.neon.vrsqrte.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrsqrteq_f16(float16x8_t a) {
+ return vrsqrteq_f16(a);
+}
+
+// CHECK-LABEL: test_vadd_f16
+// CHECK: [[ADD:%.*]] = fadd <4 x half> %a, %b
+// CHECK: ret <4 x half> [[ADD]]
+float16x4_t test_vadd_f16(float16x4_t a, float16x4_t b) {
+ return vadd_f16(a, b);
+}
+
+// CHECK-LABEL: test_vaddq_f16
+// CHECK: [[ADD:%.*]] = fadd <8 x half> %a, %b
+// CHECK: ret <8 x half> [[ADD]]
+float16x8_t test_vaddq_f16(float16x8_t a, float16x8_t b) {
+ return vaddq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vabd_f16
+// CHECK: [[ABD:%.*]] = call <4 x half> @llvm.arm.neon.vabds.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[ABD]]
+float16x4_t test_vabd_f16(float16x4_t a, float16x4_t b) {
+ return vabd_f16(a, b);
+}
+
+// CHECK-LABEL: test_vabdq_f16
+// CHECK: [[ABD:%.*]] = call <8 x half> @llvm.arm.neon.vabds.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[ABD]]
+float16x8_t test_vabdq_f16(float16x8_t a, float16x8_t b) {
+ return vabdq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcage_f16
+// CHECK: [[ABS:%.*]] = call <4 x i16> @llvm.arm.neon.vacge.v4i16.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x i16> [[ABS]]
+uint16x4_t test_vcage_f16(float16x4_t a, float16x4_t b) {
+ return vcage_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcageq_f16
+// CHECK: [[ABS:%.*]] = call <8 x i16> @llvm.arm.neon.vacge.v8i16.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x i16> [[ABS]]
+uint16x8_t test_vcageq_f16(float16x8_t a, float16x8_t b) {
+ return vcageq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcagt_f16
+// CHECK: [[ABS:%.*]] = call <4 x i16> @llvm.arm.neon.vacgt.v4i16.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x i16> [[ABS]]
+uint16x4_t test_vcagt_f16(float16x4_t a, float16x4_t b) {
+ return vcagt_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcagtq_f16
+// CHECK: [[ABS:%.*]] = call <8 x i16> @llvm.arm.neon.vacgt.v8i16.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x i16> [[ABS]]
+uint16x8_t test_vcagtq_f16(float16x8_t a, float16x8_t b) {
+ return vcagtq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcale_f16
+// CHECK: [[ABS:%.*]] = call <4 x i16> @llvm.arm.neon.vacge.v4i16.v4f16(<4 x half> %b, <4 x half> %a)
+// CHECK: ret <4 x i16> [[ABS]]
+uint16x4_t test_vcale_f16(float16x4_t a, float16x4_t b) {
+ return vcale_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcaleq_f16
+// CHECK: [[ABS:%.*]] = call <8 x i16> @llvm.arm.neon.vacge.v8i16.v8f16(<8 x half> %b, <8 x half> %a)
+// CHECK: ret <8 x i16> [[ABS]]
+uint16x8_t test_vcaleq_f16(float16x8_t a, float16x8_t b) {
+ return vcaleq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcalt_f16
+// CHECK: [[ABS:%.*]] = call <4 x i16> @llvm.arm.neon.vacgt.v4i16.v4f16(<4 x half> %b, <4 x half> %a)
+// CHECK: ret <4 x i16> [[ABS]]
+uint16x4_t test_vcalt_f16(float16x4_t a, float16x4_t b) {
+ return vcalt_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcaltq_f16
+// CHECK: [[ABS:%.*]] = call <8 x i16> @llvm.arm.neon.vacgt.v8i16.v8f16(<8 x half> %b, <8 x half> %a)
+// CHECK: ret <8 x i16> [[ABS]]
+uint16x8_t test_vcaltq_f16(float16x8_t a, float16x8_t b) {
+ return vcaltq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vceq_f16
+// CHECK: [[TMP1:%.*]] = fcmp oeq <4 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vceq_f16(float16x4_t a, float16x4_t b) {
+ return vceq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vceqq_f16
+// CHECK: [[TMP1:%.*]] = fcmp oeq <8 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vceqq_f16(float16x8_t a, float16x8_t b) {
+ return vceqq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcge_f16
+// CHECK: [[TMP1:%.*]] = fcmp oge <4 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vcge_f16(float16x4_t a, float16x4_t b) {
+ return vcge_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcgeq_f16
+// CHECK: [[TMP1:%.*]] = fcmp oge <8 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcgeq_f16(float16x8_t a, float16x8_t b) {
+ return vcgeq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcgt_f16
+// CHECK: [[TMP1:%.*]] = fcmp ogt <4 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vcgt_f16(float16x4_t a, float16x4_t b) {
+ return vcgt_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcgtq_f16
+// CHECK: [[TMP1:%.*]] = fcmp ogt <8 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcgtq_f16(float16x8_t a, float16x8_t b) {
+ return vcgtq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcle_f16
+// CHECK: [[TMP1:%.*]] = fcmp ole <4 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vcle_f16(float16x4_t a, float16x4_t b) {
+ return vcle_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcleq_f16
+// CHECK: [[TMP1:%.*]] = fcmp ole <8 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcleq_f16(float16x8_t a, float16x8_t b) {
+ return vcleq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vclt_f16
+// CHECK: [[TMP1:%.*]] = fcmp olt <4 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
+// CHECK: ret <4 x i16> [[TMP2]]
+uint16x4_t test_vclt_f16(float16x4_t a, float16x4_t b) {
+ return vclt_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcltq_f16
+// CHECK: [[TMP1:%.*]] = fcmp olt <8 x half> %a, %b
+// CHECK: [[TMP2:%.*]] = sext <8 x i1> [[TMP1:%.*]] to <8 x i16>
+// CHECK: ret <8 x i16> [[TMP2]]
+uint16x8_t test_vcltq_f16(float16x8_t a, float16x8_t b) {
+ return vcltq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vcvt_n_f16_s16
+// CHECK: [[CVT:%.*]] = call <4 x half> @llvm.arm.neon.vcvtfxs2fp.v4f16.v4i16(<4 x i16> %vcvt_n, i32 2)
+// CHECK: ret <4 x half> [[CVT]]
+float16x4_t test_vcvt_n_f16_s16(int16x4_t a) {
+ return vcvt_n_f16_s16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvtq_n_f16_s16
+// CHECK: [[CVT:%.*]] = call <8 x half> @llvm.arm.neon.vcvtfxs2fp.v8f16.v8i16(<8 x i16> %vcvt_n, i32 2)
+// CHECK: ret <8 x half> [[CVT]]
+float16x8_t test_vcvtq_n_f16_s16(int16x8_t a) {
+ return vcvtq_n_f16_s16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvt_n_f16_u16
+// CHECK: [[CVT:%.*]] = call <4 x half> @llvm.arm.neon.vcvtfxu2fp.v4f16.v4i16(<4 x i16> %vcvt_n, i32 2)
+// CHECK: ret <4 x half> [[CVT]]
+float16x4_t test_vcvt_n_f16_u16(uint16x4_t a) {
+ return vcvt_n_f16_u16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvtq_n_f16_u16
+// CHECK: [[CVT:%.*]] = call <8 x half> @llvm.arm.neon.vcvtfxu2fp.v8f16.v8i16(<8 x i16> %vcvt_n, i32 2)
+// CHECK: ret <8 x half> [[CVT]]
+float16x8_t test_vcvtq_n_f16_u16(uint16x8_t a) {
+ return vcvtq_n_f16_u16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvt_n_s16_f16
+// CHECK: [[CVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtfp2fxs.v4i16.v4f16(<4 x half> %vcvt_n, i32 2)
+// CHECK: ret <4 x i16> [[CVT]]
+int16x4_t test_vcvt_n_s16_f16(float16x4_t a) {
+ return vcvt_n_s16_f16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvtq_n_s16_f16
+// CHECK: [[CVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtfp2fxs.v8i16.v8f16(<8 x half> %vcvt_n, i32 2)
+// CHECK: ret <8 x i16> [[CVT]]
+int16x8_t test_vcvtq_n_s16_f16(float16x8_t a) {
+ return vcvtq_n_s16_f16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvt_n_u16_f16
+// CHECK: [[CVT:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtfp2fxu.v4i16.v4f16(<4 x half> %vcvt_n, i32 2)
+// CHECK: ret <4 x i16> [[CVT]]
+uint16x4_t test_vcvt_n_u16_f16(float16x4_t a) {
+ return vcvt_n_u16_f16(a, 2);
+}
+
+// CHECK-LABEL: test_vcvtq_n_u16_f16
+// CHECK: [[CVT:%.*]] = call <8 x i16> @llvm.arm.neon.vcvtfp2fxu.v8i16.v8f16(<8 x half> %vcvt_n, i32 2)
+// CHECK: ret <8 x i16> [[CVT]]
+uint16x8_t test_vcvtq_n_u16_f16(float16x8_t a) {
+ return vcvtq_n_u16_f16(a, 2);
+}
+
+// CHECK-LABEL: test_vmax_f16
+// CHECK: [[MAX:%.*]] = call <4 x half> @llvm.arm.neon.vmaxs.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MAX]]
+float16x4_t test_vmax_f16(float16x4_t a, float16x4_t b) {
+ return vmax_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmaxq_f16
+// CHECK: [[MAX:%.*]] = call <8 x half> @llvm.arm.neon.vmaxs.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MAX]]
+float16x8_t test_vmaxq_f16(float16x8_t a, float16x8_t b) {
+ return vmaxq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmaxnm_f16
+// CHECK: [[MAX:%.*]] = call <4 x half> @llvm.arm.neon.vmaxnm.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MAX]]
+float16x4_t test_vmaxnm_f16(float16x4_t a, float16x4_t b) {
+ return vmaxnm_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmaxnmq_f16
+// CHECK: [[MAX:%.*]] = call <8 x half> @llvm.arm.neon.vmaxnm.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MAX]]
+float16x8_t test_vmaxnmq_f16(float16x8_t a, float16x8_t b) {
+ return vmaxnmq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmin_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.arm.neon.vmins.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MIN]]
+float16x4_t test_vmin_f16(float16x4_t a, float16x4_t b) {
+ return vmin_f16(a, b);
+}
+
+// CHECK-LABEL: test_vminq_f16
+// CHECK: [[MIN:%.*]] = call <8 x half> @llvm.arm.neon.vmins.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MIN]]
+float16x8_t test_vminq_f16(float16x8_t a, float16x8_t b) {
+ return vminq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vminnm_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.arm.neon.vminnm.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MIN]]
+float16x4_t test_vminnm_f16(float16x4_t a, float16x4_t b) {
+ return vminnm_f16(a, b);
+}
+
+// CHECK-LABEL: test_vminnmq_f16
+// CHECK: [[MIN:%.*]] = call <8 x half> @llvm.arm.neon.vminnm.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MIN]]
+float16x8_t test_vminnmq_f16(float16x8_t a, float16x8_t b) {
+ return vminnmq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmul_f16
+// CHECK: [[MUL:%.*]] = fmul <4 x half> %a, %b
+// CHECK: ret <4 x half> [[MUL]]
+float16x4_t test_vmul_f16(float16x4_t a, float16x4_t b) {
+ return vmul_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmulq_f16
+// CHECK: [[MUL:%.*]] = fmul <8 x half> %a, %b
+// CHECK: ret <8 x half> [[MUL]]
+float16x8_t test_vmulq_f16(float16x8_t a, float16x8_t b) {
+ return vmulq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpadd_f16
+// CHECK: [[ADD:%.*]] = call <4 x half> @llvm.arm.neon.vpadd.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[ADD]]
+float16x4_t test_vpadd_f16(float16x4_t a, float16x4_t b) {
+ return vpadd_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpmax_f16
+// CHECK: [[MAX:%.*]] = call <4 x half> @llvm.arm.neon.vpmaxs.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MAX]]
+float16x4_t test_vpmax_f16(float16x4_t a, float16x4_t b) {
+ return vpmax_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpmin_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.arm.neon.vpmins.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MIN]]
+float16x4_t test_vpmin_f16(float16x4_t a, float16x4_t b) {
+ return vpmin_f16(a, b);
+}
+
+// CHECK-LABEL: test_vrecps_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.arm.neon.vrecps.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MIN]]
+float16x4_t test_vrecps_f16(float16x4_t a, float16x4_t b) {
+ return vrecps_f16(a, b);
+}
+
+// CHECK-LABEL: test_vrecpsq_f16
+// CHECK: [[MIN:%.*]] = call <8 x half> @llvm.arm.neon.vrecps.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MIN]]
+float16x8_t test_vrecpsq_f16(float16x8_t a, float16x8_t b) {
+ return vrecpsq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vrsqrts_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.arm.neon.vrsqrts.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MIN]]
+float16x4_t test_vrsqrts_f16(float16x4_t a, float16x4_t b) {
+ return vrsqrts_f16(a, b);
+}
+
+// CHECK-LABEL: test_vrsqrtsq_f16
+// CHECK: [[MIN:%.*]] = call <8 x half> @llvm.arm.neon.vrsqrts.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MIN]]
+float16x8_t test_vrsqrtsq_f16(float16x8_t a, float16x8_t b) {
+ return vrsqrtsq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vsub_f16
+// CHECK: [[ADD:%.*]] = fsub <4 x half> %a, %b
+// CHECK: ret <4 x half> [[ADD]]
+float16x4_t test_vsub_f16(float16x4_t a, float16x4_t b) {
+ return vsub_f16(a, b);
+}
+
+// CHECK-LABEL: test_vsubq_f16
+// CHECK: [[ADD:%.*]] = fsub <8 x half> %a, %b
+// CHECK: ret <8 x half> [[ADD]]
+float16x8_t test_vsubq_f16(float16x8_t a, float16x8_t b) {
+ return vsubq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vfma_f16
+// CHECK: [[ADD:%.*]] = call <4 x half> @llvm.fma.v4f16(<4 x half> %b, <4 x half> %c, <4 x half> %a)
+// CHECK: ret <4 x half> [[ADD]]
+float16x4_t test_vfma_f16(float16x4_t a, float16x4_t b, float16x4_t c) {
+ return vfma_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vfmaq_f16
+// CHECK: [[ADD:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> %b, <8 x half> %c, <8 x half> %a)
+// CHECK: ret <8 x half> [[ADD]]
+float16x8_t test_vfmaq_f16(float16x8_t a, float16x8_t b, float16x8_t c) {
+ return vfmaq_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vfms_f16
+// CHECK: [[SUB:%.*]] = fsub <4 x half> <half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000>, %b
+// CHECK: [[ADD:%.*]] = call <4 x half> @llvm.fma.v4f16(<4 x half> [[SUB]], <4 x half> %c, <4 x half> %a)
+// CHECK: ret <4 x half> [[ADD]]
+float16x4_t test_vfms_f16(float16x4_t a, float16x4_t b, float16x4_t c) {
+ return vfms_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vfmsq_f16
+// CHECK: [[SUB:%.*]] = fsub <8 x half> <half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000>, %b
+// CHECK: [[ADD:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> [[SUB]], <8 x half> %c, <8 x half> %a)
+// CHECK: ret <8 x half> [[ADD]]
+float16x8_t test_vfmsq_f16(float16x8_t a, float16x8_t b, float16x8_t c) {
+ return vfmsq_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vmul_lane_f16
+// CHECK: [[TMP0:%.*]] = shufflevector <4 x half> %b, <4 x half> %b, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
+// CHECK: [[MUL:%.*]] = fmul <4 x half> %a, [[TMP0]]
+// CHECK: ret <4 x half> [[MUL]]
+float16x4_t test_vmul_lane_f16(float16x4_t a, float16x4_t b) {
+ return vmul_lane_f16(a, b, 3);
+}
+
+// CHECK-LABEL: test_vmulq_lane_f16
+// CHECK: [[TMP0:%.*]] = shufflevector <4 x half> %b, <4 x half> %b, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+// CHECK: [[MUL:%.*]] = fmul <8 x half> %a, [[TMP0]]
+// CHECK: ret <8 x half> [[MUL]]
+float16x8_t test_vmulq_lane_f16(float16x8_t a, float16x4_t b) {
+ return vmulq_lane_f16(a, b, 7);
+}
+
+// CHECK-LABEL: test_vmul_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <4 x half> undef, half [[b:%.*]], i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half [[b]], i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half [[b]], i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half [[b]], i32 3
+// CHECK: [[MUL:%.*]] = fmul <4 x half> %a, [[TMP3]]
+// CHECK: ret <4 x half> [[MUL]]
+float16x4_t test_vmul_n_f16(float16x4_t a, float16_t b) {
+ return vmul_n_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmulq_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <8 x half> undef, half [[b:%.*]], i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half [[b]], i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half [[b]], i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half [[b]], i32 3
+// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half [[b]], i32 4
+// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half [[b]], i32 5
+// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half [[b]], i32 6
+// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half [[b]], i32 7
+// CHECK: [[MUL:%.*]] = fmul <8 x half> %a, [[TMP7]]
+// CHECK: ret <8 x half> [[MUL]]
+float16x8_t test_vmulq_n_f16(float16x8_t a, float16_t b) {
+ return vmulq_n_f16(a, b);
+}
+
+// CHECK-LABEL: test_vbsl_f16
+// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <4 x half> %c to <8 x i8>
+// CHECK: [[VBSL:%.*]] = call <8 x i8> @llvm.arm.neon.vbsl.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i8> [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[VBSL]] to <4 x half>
+// CHECK: ret <4 x half> [[TMP3]]
+float16x4_t test_vbsl_f16(uint16x4_t a, float16x4_t b, float16x4_t c) {
+ return vbsl_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vbslq_f16
+// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <8 x half> %c to <16 x i8>
+// CHECK: [[VBSL:%.*]] = call <16 x i8> @llvm.arm.neon.vbsl.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]], <16 x i8> [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[VBSL]] to <8 x half>
+// CHECK: ret <8 x half> [[TMP3]]
+float16x8_t test_vbslq_f16(uint16x8_t a, float16x8_t b, float16x8_t c) {
+ return vbslq_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vzip_f16
+// CHECK: [[VZIP0:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// CHECK: store <4 x half> [[VZIP0]], <4 x half>* [[addr1:%.*]]
+// CHECK: [[VZIP1:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
+// CHECK: store <4 x half> [[VZIP1]], <4 x half>* [[addr2:%.*]]
+float16x4x2_t test_vzip_f16(float16x4_t a, float16x4_t b) {
+ return vzip_f16(a, b);
+}
+
+// CHECK-LABEL: test_vzipq_f16
+// CHECK: [[VZIP0:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+// CHECK: store <8 x half> [[VZIP0]], <8 x half>* [[addr1:%.*]]
+// CHECK: [[VZIP1:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+// CHECK: store <8 x half> [[VZIP1]], <8 x half>* [[addr2:%.*]]
+float16x8x2_t test_vzipq_f16(float16x8_t a, float16x8_t b) {
+ return vzipq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vuzp_f16
+// CHECK: [[VUZP0:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// CHECK: store <4 x half> [[VUZP0]], <4 x half>* [[addr1:%.*]]
+// CHECK: [[VUZP1:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+// CHECK: store <4 x half> [[VUZP1]], <4 x half>* [[addr1:%.*]]
+float16x4x2_t test_vuzp_f16(float16x4_t a, float16x4_t b) {
+ return vuzp_f16(a, b);
+}
+
+// CHECK-LABEL: test_vuzpq_f16
+// CHECK: [[VUZP0:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+// CHECK: store <8 x half> [[VUZP0]], <8 x half>* [[addr1:%.*]]
+// CHECK: [[VUZP1:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+// CHECK: store <8 x half> [[VUZP1]], <8 x half>* [[addr2:%.*]]
+float16x8x2_t test_vuzpq_f16(float16x8_t a, float16x8_t b) {
+ return vuzpq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vtrn_f16
+// CHECK: [[VTRN0:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// CHECK: store <4 x half> [[VTRN0]], <4 x half>* [[addr1:%.*]]
+// CHECK: [[VTRN1:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+// CHECK: store <4 x half> [[VTRN1]], <4 x half>* [[addr2:%.*]]
+float16x4x2_t test_vtrn_f16(float16x4_t a, float16x4_t b) {
+ return vtrn_f16(a, b);
+}
+
+// CHECK-LABEL: test_vtrnq_f16
+// CHECK: [[VTRN0:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
+// CHECK: store <8 x half> [[VTRN0]], <8 x half>* [[addr1:%.*]]
+// CHECK: [[VTRN1:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
+// CHECK: store <8 x half> [[VTRN1]], <8 x half>* [[addr2:%.*]]
+float16x8x2_t test_vtrnq_f16(float16x8_t a, float16x8_t b) {
+ return vtrnq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmov_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <4 x half> undef, half [[ARG:%.*]], i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half [[ARG]], i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half [[ARG]], i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half [[ARG]], i32 3
+// CHECK: ret <4 x half> [[TMP3]]
+float16x4_t test_vmov_n_f16(float16_t a) {
+ return vmov_n_f16(a);
+}
+
+// CHECK-LABEL: test_vmovq_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <8 x half> undef, half [[ARG:%.*]], i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half [[ARG]], i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half [[ARG]], i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half [[ARG]], i32 3
+// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half [[ARG]], i32 4
+// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half [[ARG]], i32 5
+// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half [[ARG]], i32 6
+// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half [[ARG]], i32 7
+// CHECK: ret <8 x half> [[TMP7]]
+float16x8_t test_vmovq_n_f16(float16_t a) {
+ return vmovq_n_f16(a);
+}
+
+// CHECK-LABEL: test_vdup_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <4 x half> undef, half [[ARG:%.*]], i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half [[ARG]], i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half [[ARG]], i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half [[ARG]], i32 3
+// CHECK: ret <4 x half> [[TMP3]]
+float16x4_t test_vdup_n_f16(float16_t a) {
+ return vdup_n_f16(a);
+}
+
+// CHECK-LABEL: test_vdupq_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <8 x half> undef, half [[ARG:%.*]], i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half [[ARG]], i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half [[ARG]], i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half [[ARG]], i32 3
+// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half [[ARG]], i32 4
+// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half [[ARG]], i32 5
+// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half [[ARG]], i32 6
+// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half [[ARG]], i32 7
+// CHECK: ret <8 x half> [[TMP7]]
+float16x8_t test_vdupq_n_f16(float16_t a) {
+ return vdupq_n_f16(a);
+}
+
+// CHECK-LABEL: test_vdup_lane_f16
+// CHECK: [[SHFL:%.*]] = shufflevector <4 x half> %a, <4 x half> %a, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
+// CHECK: ret <4 x half> [[SHFL]]
+float16x4_t test_vdup_lane_f16(float16x4_t a) {
+ return vdup_lane_f16(a, 3);
+}
+
+// CHECK-LABEL: test_vdupq_lane_f16
+// CHECK: [[SHFL:%.*]] = shufflevector <4 x half> %a, <4 x half> %a, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+// CHECK: ret <8 x half> [[SHFL]]
+float16x8_t test_vdupq_lane_f16(float16x4_t a) {
+ return vdupq_lane_f16(a, 7);
+}
+
+// CHECK-LABEL: @test_vext_f16(
+// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK: [[VEXT:%.*]] = shufflevector <4 x half> [[TMP2]], <4 x half> [[TMP3]], <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+// CHECK: ret <4 x half> [[VEXT]]
+float16x4_t test_vext_f16(float16x4_t a, float16x4_t b) {
+ return vext_f16(a, b, 2);
+}
+
+// CHECK-LABEL: @test_vextq_f16(
+// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK: [[VEXT:%.*]] = shufflevector <8 x half> [[TMP2]], <8 x half> [[TMP3]], <8 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12>
+// CHECK: ret <8 x half> [[VEXT]]
+float16x8_t test_vextq_f16(float16x8_t a, float16x8_t b) {
+ return vextq_f16(a, b, 5);
+}
+
+// CHECK-LABEL: @test_vrev64_f16(
+// CHECK: [[SHFL:%.*]] = shufflevector <4 x half> %a, <4 x half> %a, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+// CHECK: ret <4 x half> [[SHFL]]
+float16x4_t test_vrev64_f16(float16x4_t a) {
+ return vrev64_f16(a);
+}
+
+// CHECK-LABEL: @test_vrev64q_f16(
+// CHECK: [[SHFL:%.*]] = shufflevector <8 x half> %a, <8 x half> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
+// CHECK: ret <8 x half> [[SHFL]]
+float16x8_t test_vrev64q_f16(float16x8_t a) {
+ return vrev64q_f16(a);
+}
diff --git a/test/CodeGen/arm_neon_intrinsics.c b/test/CodeGen/arm_neon_intrinsics.c
index 28b4f11..95ac3dc 100644
--- a/test/CodeGen/arm_neon_intrinsics.c
+++ b/test/CodeGen/arm_neon_intrinsics.c
@@ -20463,331 +20463,259 @@
return vtbx4_p8(a, b, c);
}
-// CHECK-LABEL: @test_vtrn_s8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_s8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !noalias !3
+// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !alias.scope !3
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]], !noalias !3
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i32 16, i1 false)
+// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]], !alias.scope !3
// CHECK: ret void
int8x8x2_t test_vtrn_s8(int8x8_t a, int8x8_t b) {
return vtrn_s8(a, b);
}
-// CHECK-LABEL: @test_vtrn_s16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_s16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]], !noalias !6
+// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]], !alias.scope !6
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]], !noalias !6
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]], !alias.scope !6
// CHECK: ret void
int16x4x2_t test_vtrn_s16(int16x4_t a, int16x4_t b) {
return vtrn_s16(a, b);
}
-// CHECK-LABEL: @test_vtrn_s32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_s32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VTRN_I]], <2 x i32>* [[TMP3]], !noalias !9
+// CHECK: store <2 x i32> [[VTRN_I]], <2 x i32>* [[TMP3]], !alias.scope !9
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP4]], !noalias !9
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP4]], !alias.scope !9
// CHECK: ret void
int32x2x2_t test_vtrn_s32(int32x2_t a, int32x2_t b) {
return vtrn_s32(a, b);
}
-// CHECK-LABEL: @test_vtrn_u8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_u8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !noalias !12
+// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !alias.scope !12
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]], !noalias !12
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i32 16, i1 false)
+// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]], !alias.scope !12
// CHECK: ret void
uint8x8x2_t test_vtrn_u8(uint8x8_t a, uint8x8_t b) {
return vtrn_u8(a, b);
}
-// CHECK-LABEL: @test_vtrn_u16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_u16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]], !noalias !15
+// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]], !alias.scope !15
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]], !noalias !15
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]], !alias.scope !15
// CHECK: ret void
uint16x4x2_t test_vtrn_u16(uint16x4_t a, uint16x4_t b) {
return vtrn_u16(a, b);
}
-// CHECK-LABEL: @test_vtrn_u32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_u32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VTRN_I]], <2 x i32>* [[TMP3]], !noalias !18
+// CHECK: store <2 x i32> [[VTRN_I]], <2 x i32>* [[TMP3]], !alias.scope !18
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP4]], !noalias !18
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP4]], !alias.scope !18
// CHECK: ret void
uint32x2x2_t test_vtrn_u32(uint32x2_t a, uint32x2_t b) {
return vtrn_u32(a, b);
}
-// CHECK-LABEL: @test_vtrn_f32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_f32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x float> [[VTRN_I]], <2 x float>* [[TMP3]], !noalias !21
+// CHECK: store <2 x float> [[VTRN_I]], <2 x float>* [[TMP3]], !alias.scope !21
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x float> [[VTRN1_I]], <2 x float>* [[TMP4]], !noalias !21
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <2 x float> [[VTRN1_I]], <2 x float>* [[TMP4]], !alias.scope !21
// CHECK: ret void
float32x2x2_t test_vtrn_f32(float32x2_t a, float32x2_t b) {
return vtrn_f32(a, b);
}
-// CHECK-LABEL: @test_vtrn_p8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_p8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !noalias !24
+// CHECK: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !alias.scope !24
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]], !noalias !24
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i32 16, i1 false)
+// CHECK: store <8 x i8> [[VTRN1_I]], <8 x i8>* [[TMP2]], !alias.scope !24
// CHECK: ret void
poly8x8x2_t test_vtrn_p8(poly8x8_t a, poly8x8_t b) {
return vtrn_p8(a, b);
}
-// CHECK-LABEL: @test_vtrn_p16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrn_p16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]], !noalias !27
+// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]], !alias.scope !27
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]], !noalias !27
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP4]], !alias.scope !27
// CHECK: ret void
poly16x4x2_t test_vtrn_p16(poly16x4_t a, poly16x4_t b) {
return vtrn_p16(a, b);
}
-// CHECK-LABEL: @test_vtrnq_s8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_s8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[AGG_RESULT]] 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> <i32 0, i32 16, i32 2, i32 18, i32 4, i32 20, i32 6, i32 22, i32 8, i32 24, i32 10, i32 26, i32 12, i32 28, i32 14, i32 30>
-// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !noalias !30
+// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !alias.scope !30
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 17, i32 3, i32 19, i32 5, i32 21, i32 7, i32 23, i32 9, i32 25, i32 11, i32 27, i32 13, i32 29, i32 15, i32 31>
-// 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* align 16 [[TMP3]], i8* align 16 [[TMP4]], i32 32, i1 false)
+// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]], !alias.scope !30
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_s16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x i16> [[VTRN_I]], <8 x i16>* [[TMP3]], !noalias !33
+// CHECK: store <8 x i16> [[VTRN_I]], <8 x i16>* [[TMP3]], !alias.scope !33
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]], !alias.scope !33
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_s32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i32> [[VTRN_I]], <4 x i32>* [[TMP3]], !noalias !36
+// CHECK: store <4 x i32> [[VTRN_I]], <4 x i32>* [[TMP3]], !alias.scope !36
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP4]], !alias.scope !36
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_u8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[AGG_RESULT]] 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> <i32 0, i32 16, i32 2, i32 18, i32 4, i32 20, i32 6, i32 22, i32 8, i32 24, i32 10, i32 26, i32 12, i32 28, i32 14, i32 30>
-// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !noalias !39
+// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !alias.scope !39
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 17, i32 3, i32 19, i32 5, i32 21, i32 7, i32 23, i32 9, i32 25, i32 11, i32 27, i32 13, i32 29, i32 15, i32 31>
-// 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* align 16 [[TMP3]], i8* align 16 [[TMP4]], i32 32, i1 false)
+// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]], !alias.scope !39
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_u16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x i16> [[VTRN_I]], <8 x i16>* [[TMP3]], !noalias !42
+// CHECK: store <8 x i16> [[VTRN_I]], <8 x i16>* [[TMP3]], !alias.scope !42
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]], !alias.scope !42
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_u32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i32> [[VTRN_I]], <4 x i32>* [[TMP3]], !noalias !45
+// CHECK: store <4 x i32> [[VTRN_I]], <4 x i32>* [[TMP3]], !alias.scope !45
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP4]], !alias.scope !45
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_f32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x float> [[VTRN_I]], <4 x float>* [[TMP3]], !noalias !48
+// CHECK: store <4 x float> [[VTRN_I]], <4 x float>* [[TMP3]], !alias.scope !48
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <4 x float> [[VTRN1_I]], <4 x float>* [[TMP4]], !alias.scope !48
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_p8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[AGG_RESULT]] 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> <i32 0, i32 16, i32 2, i32 18, i32 4, i32 20, i32 6, i32 22, i32 8, i32 24, i32 10, i32 26, i32 12, i32 28, i32 14, i32 30>
-// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !noalias !51
+// CHECK: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !alias.scope !51
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 17, i32 3, i32 19, i32 5, i32 21, i32 7, i32 23, i32 9, i32 25, i32 11, i32 27, i32 13, i32 29, i32 15, i32 31>
-// 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* align 16 [[TMP3]], i8* align 16 [[TMP4]], i32 32, i1 false)
+// CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]], !alias.scope !51
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vtrnq_p16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
-// CHECK: store <8 x i16> [[VTRN_I]], <8 x i16>* [[TMP3]], !noalias !54
+// CHECK: store <8 x i16> [[VTRN_I]], <8 x i16>* [[TMP3]], !alias.scope !54
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]], !alias.scope !54
// CHECK: ret void
poly16x8x2_t test_vtrnq_p16(poly16x8_t a, poly16x8_t b) {
return vtrnq_p16(a, b);
@@ -20957,661 +20885,517 @@
return vtstq_p16(a, b);
}
-// CHECK-LABEL: @test_vuzp_s8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_s8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !noalias !57
+// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !alias.scope !57
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]], !noalias !57
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i32 16, i1 false)
+// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]], !alias.scope !57
// CHECK: ret void
int8x8x2_t test_vuzp_s8(int8x8_t a, int8x8_t b) {
return vuzp_s8(a, b);
}
-// CHECK-LABEL: @test_vuzp_s16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_s16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]], !noalias !60
+// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]], !alias.scope !60
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]], !noalias !60
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]], !alias.scope !60
// CHECK: ret void
int16x4x2_t test_vuzp_s16(int16x4_t a, int16x4_t b) {
return vuzp_s16(a, b);
}
-// CHECK-LABEL: @test_vuzp_s32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_s32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VUZP_I]], <2 x i32>* [[TMP3]], !noalias !63
+// CHECK: store <2 x i32> [[VUZP_I]], <2 x i32>* [[TMP3]], !alias.scope !63
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP4]], !noalias !63
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP4]], !alias.scope !63
// CHECK: ret void
int32x2x2_t test_vuzp_s32(int32x2_t a, int32x2_t b) {
return vuzp_s32(a, b);
}
-// CHECK-LABEL: @test_vuzp_u8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_u8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !noalias !66
+// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !alias.scope !66
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]], !noalias !66
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i32 16, i1 false)
+// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]], !alias.scope !66
// CHECK: ret void
uint8x8x2_t test_vuzp_u8(uint8x8_t a, uint8x8_t b) {
return vuzp_u8(a, b);
}
-// CHECK-LABEL: @test_vuzp_u16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_u16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]], !noalias !69
+// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]], !alias.scope !69
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]], !noalias !69
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]], !alias.scope !69
// CHECK: ret void
uint16x4x2_t test_vuzp_u16(uint16x4_t a, uint16x4_t b) {
return vuzp_u16(a, b);
}
-// CHECK-LABEL: @test_vuzp_u32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_u32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VUZP_I]], <2 x i32>* [[TMP3]], !noalias !72
+// CHECK: store <2 x i32> [[VUZP_I]], <2 x i32>* [[TMP3]], !alias.scope !72
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP4]], !noalias !72
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP4]], !alias.scope !72
// CHECK: ret void
uint32x2x2_t test_vuzp_u32(uint32x2_t a, uint32x2_t b) {
return vuzp_u32(a, b);
}
-// CHECK-LABEL: @test_vuzp_f32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_f32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x float> [[VUZP_I]], <2 x float>* [[TMP3]], !noalias !75
+// CHECK: store <2 x float> [[VUZP_I]], <2 x float>* [[TMP3]], !alias.scope !75
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x float> [[VUZP1_I]], <2 x float>* [[TMP4]], !noalias !75
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <2 x float> [[VUZP1_I]], <2 x float>* [[TMP4]], !alias.scope !75
// CHECK: ret void
float32x2x2_t test_vuzp_f32(float32x2_t a, float32x2_t b) {
return vuzp_f32(a, b);
}
-// CHECK-LABEL: @test_vuzp_p8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_p8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !noalias !78
+// CHECK: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !alias.scope !78
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]], !noalias !78
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i32 16, i1 false)
+// CHECK: store <8 x i8> [[VUZP1_I]], <8 x i8>* [[TMP2]], !alias.scope !78
// CHECK: ret void
poly8x8x2_t test_vuzp_p8(poly8x8_t a, poly8x8_t b) {
return vuzp_p8(a, b);
}
-// CHECK-LABEL: @test_vuzp_p16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzp_p16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]], !noalias !81
+// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]], !alias.scope !81
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]], !noalias !81
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP4]], !alias.scope !81
// CHECK: ret void
poly16x4x2_t test_vuzp_p16(poly16x4_t a, poly16x4_t b) {
return vuzp_p16(a, b);
}
-// CHECK-LABEL: @test_vuzpq_s8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_s8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[AGG_RESULT]] 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> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26, i32 28, i32 30>
-// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !noalias !84
+// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !alias.scope !84
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
-// 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* align 16 [[TMP3]], i8* align 16 [[TMP4]], i32 32, i1 false)
+// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]], !alias.scope !84
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_s16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x i16> [[VUZP_I]], <8 x i16>* [[TMP3]], !noalias !87
+// CHECK: store <8 x i16> [[VUZP_I]], <8 x i16>* [[TMP3]], !alias.scope !87
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]], !alias.scope !87
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_s32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i32> [[VUZP_I]], <4 x i32>* [[TMP3]], !noalias !90
+// CHECK: store <4 x i32> [[VUZP_I]], <4 x i32>* [[TMP3]], !alias.scope !90
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP4]], !alias.scope !90
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_u8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[AGG_RESULT]] 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> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26, i32 28, i32 30>
-// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !noalias !93
+// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !alias.scope !93
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
-// 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* align 16 [[TMP3]], i8* align 16 [[TMP4]], i32 32, i1 false)
+// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]], !alias.scope !93
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_u16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x i16> [[VUZP_I]], <8 x i16>* [[TMP3]], !noalias !96
+// CHECK: store <8 x i16> [[VUZP_I]], <8 x i16>* [[TMP3]], !alias.scope !96
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]], !alias.scope !96
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_u32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i32> [[VUZP_I]], <4 x i32>* [[TMP3]], !noalias !99
+// CHECK: store <4 x i32> [[VUZP_I]], <4 x i32>* [[TMP3]], !alias.scope !99
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP4]], !alias.scope !99
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_f32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x float> [[VUZP_I]], <4 x float>* [[TMP3]], !noalias !102
+// CHECK: store <4 x float> [[VUZP_I]], <4 x float>* [[TMP3]], !alias.scope !102
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <4 x float> [[VUZP1_I]], <4 x float>* [[TMP4]], !alias.scope !102
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_p8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[AGG_RESULT]] 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> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26, i32 28, i32 30>
-// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !noalias !105
+// CHECK: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !alias.scope !105
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
-// 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* align 16 [[TMP3]], i8* align 16 [[TMP4]], i32 32, i1 false)
+// CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]], !alias.scope !105
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vuzpq_p16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
-// CHECK: store <8 x i16> [[VUZP_I]], <8 x i16>* [[TMP3]], !noalias !108
+// CHECK: store <8 x i16> [[VUZP_I]], <8 x i16>* [[TMP3]], !alias.scope !108
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]], !alias.scope !108
// CHECK: ret void
poly16x8x2_t test_vuzpq_p16(poly16x8_t a, poly16x8_t b) {
return vuzpq_p16(a, b);
}
-// CHECK-LABEL: @test_vzip_s8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_s8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !noalias !111
+// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !alias.scope !111
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]], !noalias !111
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i32 16, i1 false)
+// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]], !alias.scope !111
// CHECK: ret void
int8x8x2_t test_vzip_s8(int8x8_t a, int8x8_t b) {
return vzip_s8(a, b);
}
-// CHECK-LABEL: @test_vzip_s16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_s16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]], !noalias !114
+// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]], !alias.scope !114
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]], !noalias !114
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]], !alias.scope !114
// CHECK: ret void
int16x4x2_t test_vzip_s16(int16x4_t a, int16x4_t b) {
return vzip_s16(a, b);
}
-// CHECK-LABEL: @test_vzip_s32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_s32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VZIP_I]], <2 x i32>* [[TMP3]], !noalias !117
+// CHECK: store <2 x i32> [[VZIP_I]], <2 x i32>* [[TMP3]], !alias.scope !117
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP4]], !noalias !117
-// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP4]], !alias.scope !117
// CHECK: ret void
int32x2x2_t test_vzip_s32(int32x2_t a, int32x2_t b) {
return vzip_s32(a, b);
}
-// CHECK-LABEL: @test_vzip_u8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_u8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !noalias !120
+// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !alias.scope !120
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]], !noalias !120
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i32 16, i1 false)
+// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]], !alias.scope !120
// CHECK: ret void
uint8x8x2_t test_vzip_u8(uint8x8_t a, uint8x8_t b) {
return vzip_u8(a, b);
}
-// CHECK-LABEL: @test_vzip_u16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_u16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]], !noalias !123
+// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]], !alias.scope !123
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]], !noalias !123
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]], !alias.scope !123
// CHECK: ret void
uint16x4x2_t test_vzip_u16(uint16x4_t a, uint16x4_t b) {
return vzip_u16(a, b);
}
-// CHECK-LABEL: @test_vzip_u32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_u32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VZIP_I]], <2 x i32>* [[TMP3]], !noalias !126
+// CHECK: store <2 x i32> [[VZIP_I]], <2 x i32>* [[TMP3]], !alias.scope !126
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP4]], !noalias !126
-// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP4]], !alias.scope !126
// CHECK: ret void
uint32x2x2_t test_vzip_u32(uint32x2_t a, uint32x2_t b) {
return vzip_u32(a, b);
}
-// CHECK-LABEL: @test_vzip_f32(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x2x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_f32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x float> [[VZIP_I]], <2 x float>* [[TMP3]], !noalias !129
+// CHECK: store <2 x float> [[VZIP_I]], <2 x float>* [[TMP3]], !alias.scope !129
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x float> [[VZIP1_I]], <2 x float>* [[TMP4]], !noalias !129
-// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <2 x float> [[VZIP1_I]], <2 x float>* [[TMP4]], !alias.scope !129
// CHECK: ret void
float32x2x2_t test_vzip_f32(float32x2_t a, float32x2_t b) {
return vzip_f32(a, b);
}
-// CHECK-LABEL: @test_vzip_p8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_p8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i8>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !noalias !132
+// CHECK: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !alias.scope !132
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <8 x i8>, <8 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]], !noalias !132
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP3]], i8* align 8 [[TMP4]], i32 16, i1 false)
+// CHECK: store <8 x i8> [[VZIP1_I]], <8 x i8>* [[TMP2]], !alias.scope !132
// CHECK: ret void
poly8x8x2_t test_vzip_p8(poly8x8_t a, poly8x8_t b) {
return vzip_p8(a, b);
}
-// CHECK-LABEL: @test_vzip_p16(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x4x2_t, align 8
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzip_p16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]], !noalias !135
+// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]], !alias.scope !135
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]], !noalias !135
-// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[TMP5]], i8* align 8 [[TMP6]], i32 16, i1 false)
+// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP4]], !alias.scope !135
// CHECK: ret void
poly16x4x2_t test_vzip_p16(poly16x4_t a, poly16x4_t b) {
return vzip_p16(a, b);
}
-// CHECK-LABEL: @test_vzipq_s8(
-// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_s8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[AGG_RESULT]] 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> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
-// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !noalias !138
+// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !alias.scope !138
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
-// 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* align 16 [[TMP3]], i8* align 16 [[TMP4]], i32 32, i1 false)
+// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]], !alias.scope !138
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_s16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x i16> [[VZIP_I]], <8 x i16>* [[TMP3]], !noalias !141
+// CHECK: store <8 x i16> [[VZIP_I]], <8 x i16>* [[TMP3]], !alias.scope !141
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]], !alias.scope !141
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_s32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i32> [[VZIP_I]], <4 x i32>* [[TMP3]], !noalias !144
+// CHECK: store <4 x i32> [[VZIP_I]], <4 x i32>* [[TMP3]], !alias.scope !144
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP4]], !alias.scope !144
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_u8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[AGG_RESULT]] 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> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
-// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !noalias !147
+// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !alias.scope !147
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
-// 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* align 16 [[TMP3]], i8* align 16 [[TMP4]], i32 32, i1 false)
+// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]], !alias.scope !147
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_u16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x i16> [[VZIP_I]], <8 x i16>* [[TMP3]], !noalias !150
+// CHECK: store <8 x i16> [[VZIP_I]], <8 x i16>* [[TMP3]], !alias.scope !150
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]], !alias.scope !150
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_u32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i32> [[VZIP_I]], <4 x i32>* [[TMP3]], !noalias !153
+// CHECK: store <4 x i32> [[VZIP_I]], <4 x i32>* [[TMP3]], !alias.scope !153
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP4]], !alias.scope !153
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_f32({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x float> [[VZIP_I]], <4 x float>* [[TMP3]], !noalias !156
+// CHECK: store <4 x float> [[VZIP_I]], <4 x float>* [[TMP3]], !alias.scope !156
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <4 x float> [[VZIP1_I]], <4 x float>* [[TMP4]], !alias.scope !156
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_p8({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[AGG_RESULT]] 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> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
-// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !noalias !159
+// CHECK: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !alias.scope !159
// CHECK: [[TMP2:%.*]] = getelementptr inbounds <16 x i8>, <16 x i8>* [[TMP1]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
-// 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* align 16 [[TMP3]], i8* align 16 [[TMP4]], i32 32, i1 false)
+// CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]], !alias.scope !159
// 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 16
-// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
+// CHECK: @test_vzipq_p16({{.*}} sret [[AGG_RESULT:%[0-9a-zA-Z.]+]],
+// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[AGG_RESULT]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
-// CHECK: store <8 x i16> [[VZIP_I]], <8 x i16>* [[TMP3]], !noalias !162
+// CHECK: store <8 x i16> [[VZIP_I]], <8 x i16>* [[TMP3]], !alias.scope !162
// CHECK: [[TMP4:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
-// 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* align 16 [[TMP5]], i8* align 16 [[TMP6]], i32 32, i1 false)
+// CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]], !alias.scope !162
// CHECK: ret void
poly16x8x2_t test_vzipq_p16(poly16x8_t a, poly16x8_t b) {
return vzipq_p16(a, b);
diff --git a/test/CodeGen/atomic-ops.c b/test/CodeGen/atomic-ops.c
index 1ebb2ba..db97706 100644
--- a/test/CodeGen/atomic-ops.c
+++ b/test/CodeGen/atomic-ops.c
@@ -186,8 +186,8 @@
struct S fd1(struct S *a) {
// CHECK-LABEL: @fd1
// CHECK: [[RETVAL:%.*]] = alloca %struct.S, align 4
- // CHECK: [[RET:%.*]] = alloca %struct.S, align 4
- // CHECK: [[CAST:%.*]] = bitcast %struct.S* [[RET]] to i64*
+ // CHECK: bitcast %struct.S* {{.*}} to i64*
+ // CHECK: [[CAST:%.*]] = bitcast %struct.S* [[RETVAL]] to i64*
// CHECK: [[CALL:%.*]] = call i64 @__atomic_load_8(
// CHECK: store i64 [[CALL]], i64* [[CAST]], align 4
struct S ret;
diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c
index 34833a2..e7fd076 100644
--- a/test/CodeGen/attributes.c
+++ b/test/CodeGen/attributes.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -triple i386-linux-gnu -o %t %s
+// RUN: %clang_cc1 -emit-llvm -fcf-protection=branch -target-feature +ibt -triple i386-linux-gnu -o %t %s
// RUN: FileCheck --input-file=%t %s
// CHECK: @t5 = weak global i32 2
@@ -97,8 +97,20 @@
// CHECK: define void @t22() [[NUW]] section ".bar"
+// CHECK: define void @t23() [[NOCF_CHECK_FUNC:#[0-9]+]]
+void __attribute__((nocf_check)) t23(void) {}
+
+// CHECK: call void %{{[a-z0-9]+}}() [[NOCF_CHECK_CALL:#[0-9]+]]
+typedef void (*f_t)(void);
+void t24(f_t f1) {
+ __attribute__((nocf_check)) f_t p = f1;
+ (*p)();
+}
+
// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
// CHECK: attributes [[NR]] = { noinline noreturn nounwind{{.*}} }
// CHECK: attributes [[COLDDEF]] = { cold {{.*}}}
// CHECK: attributes [[COLDDECL]] = { cold {{.*}}}
+// CHECK: attributes [[NOCF_CHECK_FUNC]] = { nocf_check {{.*}}}
// CHECK: attributes [[COLDSITE]] = { cold {{.*}}}
+// CHECK: attributes [[NOCF_CHECK_CALL]] = { nocf_check }
diff --git a/test/CodeGen/blocks-windows.c b/test/CodeGen/blocks-windows.c
index 546c0bf..2dd97ff 100644
--- a/test/CodeGen/blocks-windows.c
+++ b/test/CodeGen/blocks-windows.c
@@ -67,7 +67,7 @@
return _Block_copy(^{ ++i; return i; });
}
-// CHECK-BLOCKS-IN-BLOCKS-DECL: @_NSConcreteStackBlock = external dllexport global i8*
+// CHECK-BLOCKS-IN-BLOCKS-DECL: @_NSConcreteStackBlock = external dso_local dllexport global i8*
// CHECK-BLOCKS-IN-BLOCKS-DEFN: @_NSConcreteStackBlock = common dso_local dllexport global [5 x i32]
// CHECK-BLOCKS-NOT-IN-BLOCKS: @_NSConcreteStackBlock = external dllimport global i8*
// CHECK-BLOCKS-NOT-IN-BLOCKS-EXTERN: @_NSConcreteStackBlock = external dllimport global i8*
diff --git a/test/CodeGen/builtins-hexagon-circ.c b/test/CodeGen/builtins-hexagon-circ.c
new file mode 100644
index 0000000..dc8f5a6
--- /dev/null
+++ b/test/CodeGen/builtins-hexagon-circ.c
@@ -0,0 +1,156 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -triple hexagon-unknown-elf -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: test1
+// CHECK: @llvm.hexagon.L2.loadrub.pci
+unsigned char test1(int mod, void *start) {
+ unsigned char *base = start;
+ return __builtin_HEXAGON_L2_loadrub_pci(&base, 4, mod, start);
+}
+
+// CHECK-LABEL: test2
+// CHECK: @llvm.hexagon.L2.loadrb.pci
+unsigned char test2(int mod, void *start) {
+ char *base = start;
+ return __builtin_HEXAGON_L2_loadrb_pci(&base, 4, mod, start);
+}
+
+// CHECK-LABEL: test3
+// CHECK: @llvm.hexagon.L2.loadruh.pci
+unsigned short test3(int mod, void *start) {
+ unsigned short *base = start;
+ return __builtin_HEXAGON_L2_loadruh_pci(&base, 4, mod, start);
+}
+
+// CHECK-LABEL: test4
+// CHECK: @llvm.hexagon.L2.loadrh.pci
+short test4(int mod, void *start) {
+ short *base = start;
+ return __builtin_HEXAGON_L2_loadrh_pci(&base, 4, mod, start);
+}
+
+// CHECK-LABEL: test5
+// CHECK: @llvm.hexagon.L2.loadri.pci
+int test5(int mod, void *start) {
+ int *base = start;
+ return __builtin_HEXAGON_L2_loadri_pci(&base, 4, mod, start);
+}
+
+// CHECK-LABEL: test6
+// CHECK: @llvm.hexagon.L2.loadrd.pci
+long long test6(int mod, void *start) {
+ long long *base = start;
+ return __builtin_HEXAGON_L2_loadrd_pci(&base, 8, mod, start);
+}
+
+// CHECK-LABEL: test7
+// CHECK: @llvm.hexagon.L2.loadrub.pcr
+unsigned char test7(int mod, void *start) {
+ unsigned char *base = start;
+ return __builtin_HEXAGON_L2_loadrub_pcr(&base, mod, start);
+}
+
+// CHECK-LABEL: test8
+// CHECK: @llvm.hexagon.L2.loadrb.pcr
+unsigned char test8(int mod, void *start) {
+ char *base = start;
+ return __builtin_HEXAGON_L2_loadrb_pcr(&base, mod, start);
+}
+
+// CHECK-LABEL: test9
+// CHECK: @llvm.hexagon.L2.loadruh.pcr
+unsigned short test9(int mod, void *start) {
+ unsigned short *base = start;
+ return __builtin_HEXAGON_L2_loadruh_pcr(&base, mod, start);
+}
+
+// CHECK-LABEL: test10
+// CHECK: @llvm.hexagon.L2.loadrh.pcr
+short test10(int mod, void *start) {
+ short *base = start;
+ return __builtin_HEXAGON_L2_loadrh_pcr(&base, mod, start);
+}
+
+// CHECK-LABEL: test11
+// CHECK: @llvm.hexagon.L2.loadri.pcr
+int test11(int mod, void *start) {
+ int *base = start;
+ return __builtin_HEXAGON_L2_loadri_pcr(&base, mod, start);
+}
+
+// CHECK-LABEL: test12
+// CHECK: @llvm.hexagon.L2.loadrd.pcr
+long long test12(int mod, void *start) {
+ long long *base = start;
+ return __builtin_HEXAGON_L2_loadrd_pcr(&base, mod, start);
+}
+
+// CHECK-LABEL: test13
+// CHECK: @llvm.hexagon.S2.storerb.pci
+void test13(int mod, void *start, char v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerb_pci(&base, 4, mod, v, start);
+}
+
+// CHECK-LABEL: test14
+// CHECK: @llvm.hexagon.S2.storerh.pci
+void test14(int mod, void *start, short v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerh_pci(&base, 4, mod, v, start);
+}
+
+// CHECK-LABEL: test15
+// CHECK: @llvm.hexagon.S2.storerf.pci
+void test15(int mod, void *start, short v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerf_pci(&base, 4, mod, v, start);
+}
+
+// CHECK-LABEL: test16
+// CHECK: @llvm.hexagon.S2.storeri.pci
+void test16(int mod, void *start, int v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storeri_pci(&base, 4, mod, v, start);
+}
+
+// CHECK-LABEL: test17
+// CHECK: @llvm.hexagon.S2.storerd.pci
+void test17(int mod, void *start, long long v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerd_pci(&base, 8, mod, v, start);
+}
+
+// CHECK-LABEL: test18
+// CHECK: @llvm.hexagon.S2.storerb.pcr
+void test18(int mod, void *start, char v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerb_pcr(&base, mod, v, start);
+}
+
+// CHECK-LABEL: test19
+// CHECK: @llvm.hexagon.S2.storerh.pcr
+void test19(int mod, void *start, short v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerh_pcr(&base, mod, v, start);
+}
+
+// CHECK-LABEL: test20
+// CHECK: @llvm.hexagon.S2.storerf.pcr
+void test20(int mod, void *start, short v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerf_pcr(&base, mod, v, start);
+}
+
+// CHECK-LABEL: test21
+// CHECK: @llvm.hexagon.S2.storeri.pcr
+void test21(int mod, void *start, int v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storeri_pcr(&base, mod, v, start);
+}
+
+// CHECK-LABEL: test22
+// CHECK: @llvm.hexagon.S2.storerd.pcr
+void test22(int mod, void *start, long long v) {
+ void *base = start;
+ __builtin_HEXAGON_S2_storerd_pcr(&base, mod, v, start);
+}
diff --git a/test/CodeGen/builtins-hexagon.c b/test/CodeGen/builtins-hexagon.c
index 22835a2..3b4d8d0 100644
--- a/test/CodeGen/builtins-hexagon.c
+++ b/test/CodeGen/builtins-hexagon.c
@@ -3322,28 +3322,30 @@
__builtin_HEXAGON_Y4_l2fetch(0, 0);
// CHECK: @llvm.hexagon.Y5.l2fetch
__builtin_HEXAGON_Y5_l2fetch(0, 0);
- // CHECK: @llvm.hexagon.brev.ldb
+
+ // CHECK: @llvm.hexagon.L2.loadrb.pbr
__builtin_brev_ldb(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.ldd
+ // CHECK: @llvm.hexagon.L2.loadrd.pbr
__builtin_brev_ldd(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.ldh
+ // CHECK: @llvm.hexagon.L2.loadrh.pbr
__builtin_brev_ldh(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.ldub
+ // CHECK: @llvm.hexagon.L2.loadrub.pbr
__builtin_brev_ldub(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.lduh
+ // CHECK: @llvm.hexagon.L2.loadruh.pbr
__builtin_brev_lduh(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.ldw
+ // CHECK: @llvm.hexagon.L2.loadri.pbr
__builtin_brev_ldw(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.stb
+ // CHECK: @llvm.hexagon.S2.storerb.pbr
__builtin_brev_stb(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.std
- __builtin_brev_std(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.sth
+ // CHECK: @llvm.hexagon.S2.storerd.pbr
+ __builtin_brev_std(0, 0LL, 0);
+ // CHECK: @llvm.hexagon.S2.storerh.pbr
__builtin_brev_sth(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.sthhi
+ // CHECK: @llvm.hexagon.S2.storerf.pbr
__builtin_brev_sthhi(0, 0, 0);
- // CHECK: @llvm.hexagon.brev.stw
+ // CHECK: @llvm.hexagon.S2.storeri.pbr
__builtin_brev_stw(0, 0, 0);
+
// CHECK: @llvm.hexagon.circ.ldb
__builtin_circ_ldb(0, 0, 0, 0);
// CHECK: @llvm.hexagon.circ.ldd
diff --git a/test/CodeGen/builtins-nvptx-sm_70.cu b/test/CodeGen/builtins-nvptx-sm_70.cu
index 09e5b6b..1e9133b 100644
--- a/test/CodeGen/builtins-nvptx-sm_70.cu
+++ b/test/CodeGen/builtins-nvptx-sm_70.cu
@@ -22,145 +22,145 @@
__device__ void nvvm_wmma(int *src, int *dst,
float *fsrc, float *fdst,
int ldm) {
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.a.sync.row.m16n16k16.stride.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.a.row.stride.f16
// expected-error@+1 {{'__hmma_m16n16k16_ld_a' needs target feature ptx60}}
__hmma_m16n16k16_ld_a(dst, src, ldm, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.a.sync.col.m16n16k16.stride.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.a.col.stride.f16
// expected-error@+1 {{'__hmma_m16n16k16_ld_a' needs target feature ptx60}}
__hmma_m16n16k16_ld_a(dst, src+1, ldm, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.b.sync.row.m16n16k16.stride.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.b.row.stride.f16
// expected-error@+1 {{'__hmma_m16n16k16_ld_b' needs target feature ptx60}}
__hmma_m16n16k16_ld_b(dst, src, ldm, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.b.sync.col.m16n16k16.stride.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.b.col.stride.f16
// expected-error@+1 {{'__hmma_m16n16k16_ld_b' needs target feature ptx60}}
__hmma_m16n16k16_ld_b(dst, src+2, ldm, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.c.sync.row.m16n16k16.stride.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.c.row.stride.f16
// expected-error@+1 {{'__hmma_m16n16k16_ld_c_f16' needs target feature ptx60}}
__hmma_m16n16k16_ld_c_f16(dst, src, ldm, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.c.sync.col.m16n16k16.stride.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.c.col.stride.f16
// expected-error@+1 {{'__hmma_m16n16k16_ld_c_f16' needs target feature ptx60}}
__hmma_m16n16k16_ld_c_f16(dst, src, ldm, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.c.sync.row.m16n16k16.stride.f32
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.c.row.stride.f32
// expected-error@+1 {{'__hmma_m16n16k16_ld_c_f32' needs target feature ptx60}}
__hmma_m16n16k16_ld_c_f32(fdst, fsrc, ldm, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.load.c.sync.col.m16n16k16.stride.f32
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.c.col.stride.f32
// expected-error@+1 {{'__hmma_m16n16k16_ld_c_f32' needs target feature ptx60}}
__hmma_m16n16k16_ld_c_f32(fdst, fsrc, ldm, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.store.d.sync.row.m16n16k16.stride.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.store.d.row.stride.f16
// expected-error@+1 {{'__hmma_m16n16k16_st_c_f16' needs target feature ptx60}}
__hmma_m16n16k16_st_c_f16(dst, src, ldm, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.store.d.sync.col.m16n16k16.stride.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.store.d.col.stride.f16
// expected-error@+1 {{'__hmma_m16n16k16_st_c_f16' needs target feature ptx60}}
__hmma_m16n16k16_st_c_f16(dst, src, ldm, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.store.d.sync.row.m16n16k16.stride.f32
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.store.d.row.stride.f32
// expected-error@+1 {{'__hmma_m16n16k16_st_c_f32' needs target feature ptx60}}
__hmma_m16n16k16_st_c_f32(fdst, fsrc, ldm, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.store.d.sync.col.m16n16k16.stride.f32
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.store.d.col.stride.f32
// expected-error@+1 {{'__hmma_m16n16k16_st_c_f32' needs target feature ptx60}}
__hmma_m16n16k16_st_c_f32(fdst, fsrc, ldm, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f16.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f16.f16
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 0, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f16.f16.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f16.f16.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 0, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f16.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f16.f16
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 1, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f16.f16.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f16.f16.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 1, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f16.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f16.f16
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 2, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f16.f16.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f16.f16.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 2, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f16.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f16.f16
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 3, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f16.f16.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f16.f16.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f16(dst, src, src, src, 3, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f16.f32
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f16.f32
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 0, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f16.f32.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f16.f32.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 0, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f16.f32
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f16.f32
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 1, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f16.f32.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f16.f32.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 1, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f16.f32
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f16.f32
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 2, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f16.f32.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f16.f32.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 2, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f16.f32
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f16.f32
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 3, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f16.f32.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f16.f32.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f16f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f16f32(dst, src, src, fsrc, 3, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f32.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f32.f16
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 0, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f32.f16.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f32.f16.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 0, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f32.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f32.f16
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 1, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f32.f16.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f32.f16.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 1, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f32.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f32.f16
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 2, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f32.f16.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f32.f16.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 2, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f32.f16
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f32.f16
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 3, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f32.f16.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f32.f16.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f16' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f16(fdst, src, src, src, 3, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f32.f32
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f32.f32
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 0, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.row.m16n16k16.f32.f32.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.row.f32.f32.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 0, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f32.f32
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f32.f32
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 1, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.row.col.m16n16k16.f32.f32.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.row.col.f32.f32.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 1, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f32.f32
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f32.f32
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 2, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.row.m16n16k16.f32.f32.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.row.f32.f32.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 2, 1);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f32.f32
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f32.f32
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 3, 0);
- // CHECK: call {{.*}} @llvm.nvvm.wmma.mma.sync.col.col.m16n16k16.f32.f32.satfinite
+ // CHECK: call {{.*}} @llvm.nvvm.wmma.m16n16k16.mma.col.col.f32.f32.satfinite
// expected-error@+1 {{'__hmma_m16n16k16_mma_f32f32' needs target feature ptx60}}
__hmma_m16n16k16_mma_f32f32(fdst, src, src, fsrc, 3, 1);
}
diff --git a/test/CodeGen/c-strings.c b/test/CodeGen/c-strings.c
index aa428b8..a94cd89 100644
--- a/test/CodeGen/c-strings.c
+++ b/test/CodeGen/c-strings.c
@@ -6,13 +6,13 @@
// CHECK: @align = {{(dso_local )?}}global i8 [[ALIGN:[0-9]+]]
// ITANIUM: @.str = private unnamed_addr constant [6 x i8] c"hello\00"
-// MSABI: @"\01??_C@_05CJBACGMB@hello?$AA@" = linkonce_odr unnamed_addr constant [6 x i8] c"hello\00", comdat, align 1
+// MSABI: @"??_C@_05CJBACGMB@hello?$AA@" = linkonce_odr dso_local unnamed_addr constant [6 x i8] c"hello\00", comdat, align 1
// ITANIUM: @f1.x = internal global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0)
-// MSABI: @f1.x = internal global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @"\01??_C@_05CJBACGMB@hello?$AA@", i32 0, i32 0)
+// MSABI: @f1.x = internal global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @"??_C@_05CJBACGMB@hello?$AA@", i32 0, i32 0)
// CHECK: @f2.x = internal global [6 x i8] c"hello\00", align [[ALIGN]]
// CHECK: @f3.x = internal global [8 x i8] c"hello\00\00\00", align [[ALIGN]]
// ITANIUM: @f4.x = internal global %struct.s { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0) }
-// MSABI: @f4.x = internal global %struct.s { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @"\01??_C@_05CJBACGMB@hello?$AA@", i32 0, i32 0) }
+// MSABI: @f4.x = internal global %struct.s { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @"??_C@_05CJBACGMB@hello?$AA@", i32 0, i32 0) }
// CHECK: @x = {{(dso_local )?}}global [3 x i8] c"ola", align [[ALIGN]]
// XFAIL: hexagon
@@ -32,7 +32,7 @@
void f0() {
bar("hello");
// ITANIUM: call {{.*}}void @bar({{.*}} @.str
- // MSABI: call {{.*}}void @bar({{.*}} @"\01??_C@_05CJBACGMB@hello?$AA@"
+ // MSABI: call {{.*}}void @bar({{.*}} @"??_C@_05CJBACGMB@hello?$AA@"
}
// CHECK-LABEL: define {{.*}}void @f1()
diff --git a/test/CodeGen/cetintrin.c b/test/CodeGen/cetintrin.c
index 4d2f87a..f70d1c8 100644
--- a/test/CodeGen/cetintrin.c
+++ b/test/CodeGen/cetintrin.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -ffreestanding %s -triple=i386-apple-darwin -target-feature +shstk -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=I386 --check-prefix=CHECK
-// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +shstk -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=X86_64 --check-prefix=CHECK
+// RUN: %clang_cc1 -ffreestanding %s -triple=i386-unknown-unknown -target-feature +shstk -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=I386 --check-prefix=CHECK
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-unknown-unknown -target-feature +shstk -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=X86_64 --check-prefix=CHECK
#include <immintrin.h>
diff --git a/test/CodeGen/cfi-icall-cross-dso.c b/test/CodeGen/cfi-icall-cross-dso.c
index 0fdf4a2..1df20aa 100644
--- a/test/CodeGen/cfi-icall-cross-dso.c
+++ b/test/CodeGen/cfi-icall-cross-dso.c
@@ -39,6 +39,11 @@
// MS-DIAG: call void @__cfi_slowpath_diag(i64 4195979634929632483, i8* %{{.*}}, {{.*}}@[[DATA]]{{.*}}) {{.*}}, !nosanitize
// MS-TRAP: call void @__cfi_slowpath(i64 4195979634929632483, i8* %{{.*}}) {{.*}}, !nosanitize
+// ITANIUM-DIAG: declare void @__cfi_slowpath_diag(
+// ITANIUM-TRAP: declare void @__cfi_slowpath(
+// MS-DIAG: declare dso_local void @__cfi_slowpath_diag(
+// MS-TRAP: declare dso_local void @__cfi_slowpath(
+
void caller(void (*f)()) {
f();
}
@@ -66,6 +71,9 @@
inline void foo() {}
void bar() { foo(); }
+// ITANIUM: define weak void @__cfi_check
+// MS: define weak dso_local void @__cfi_check
+
// CHECK: !{i32 4, !"Cross-DSO CFI", i32 1}
// Check that the type entries are correct.
diff --git a/test/CodeGen/cfstring-windows.c b/test/CodeGen/cfstring-windows.c
index 554c4d9..fe7511e 100644
--- a/test/CodeGen/cfstring-windows.c
+++ b/test/CodeGen/cfstring-windows.c
@@ -31,7 +31,7 @@
typedef struct __CFString *CFStringRef;
const CFStringRef string = (CFStringRef)__builtin___CFStringMakeConstantString("string");
-// CHECK-CF-IN-CF-DECL: @__CFConstantStringClassReference = external dllexport global [0 x i32]
+// CHECK-CF-IN-CF-DECL: @__CFConstantStringClassReference = external dso_local dllexport global [0 x i32]
// CHECK-CF-IN-CF-DEFN: @__CFConstantStringClassReference = common dso_local dllexport global [32 x i32]
// CHECK-CF: @__CFConstantStringClassReference = external dllimport global [0 x i32]
// CHECK-CF-EXTERN: @__CFConstantStringClassReference = external dllimport global [0 x i32]
diff --git a/test/CodeGen/debug-info-cc.c b/test/CodeGen/debug-info-cc.c
new file mode 100644
index 0000000..fe15855
--- /dev/null
+++ b/test/CodeGen/debug-info-cc.c
@@ -0,0 +1,120 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=LINUX
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=WINDOWS
+// RUN: %clang_cc1 -triple i386-pc-linux-gnu -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=LINUX32
+// RUN: %clang_cc1 -triple armv7--linux-gnueabihf -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=ARM
+
+// enum CallingConv {
+// CC_C, // __attribute__((cdecl))
+// CC_X86StdCall, // __attribute__((stdcall))
+// CC_X86FastCall, // __attribute__((fastcall))
+// CC_X86ThisCall, // __attribute__((thiscall))
+// CC_X86VectorCall, // __attribute__((vectorcall))
+// CC_X86Pascal, // __attribute__((pascal))
+// CC_Win64, // __attribute__((ms_abi))
+// CC_X86_64SysV, // __attribute__((sysv_abi))
+// CC_X86RegCall, // __attribute__((regcall))
+// CC_AAPCS, // __attribute__((pcs("aapcs")))
+// CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
+// CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
+// CC_SpirFunction, // default for OpenCL functions on SPIR target
+// CC_OpenCLKernel, // inferred for OpenCL kernels
+// CC_Swift, // __attribute__((swiftcall))
+// CC_PreserveMost, // __attribute__((preserve_most))
+// CC_PreserveAll, // __attribute__((preserve_all))
+// };
+
+#ifdef __x86_64__
+
+#ifdef __linux__
+// LINUX: !DISubprogram({{.*}}"add_msabi", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_Win64,
+__attribute__((ms_abi)) int add_msabi(int a, int b) {
+ return a+b;
+}
+
+// LINUX: !DISubprogram({{.*}}"add_regcall", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_X86RegCall,
+__attribute__((regcall)) int add_regcall(int a, int b) {
+ return a+b;
+}
+
+// LINUX: !DISubprogram({{.*}}"add_preserve_most", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_PreserveMost,
+__attribute__((preserve_most)) int add_preserve_most(int a, int b) {
+ return a+b;
+}
+
+// LINUX: !DISubprogram({{.*}}"add_preserve_all", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_PreserveAll,
+__attribute__((preserve_all)) int add_preserve_all(int a, int b) {
+ return a+b;
+}
+
+// LINUX: !DISubprogram({{.*}}"add_swiftcall", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_Swift,
+__attribute__((swiftcall)) int add_swiftcall(int a, int b) {
+ return a+b;
+}
+
+// LINUX: !DISubprogram({{.*}}"add_inteloclbicc", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_IntelOclBicc,
+__attribute__((intel_ocl_bicc)) int add_inteloclbicc(int a, int b) {
+ return a+b;
+}
+#endif
+
+#ifdef _WIN64
+// WINDOWS: !DISubprogram({{.*}}"add_sysvabi", {{.*}}type: ![[FTY:[0-9]+]]
+// WINDOWS: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_X86_64SysV,
+__attribute__((sysv_abi)) int add_sysvabi(int a, int b) {
+ return a+b;
+}
+#endif
+
+#endif
+
+#ifdef __i386__
+// LINUX32: !DISubprogram({{.*}}"add_stdcall", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX32: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_BORLAND_stdcall,
+__attribute__((stdcall)) int add_stdcall(int a, int b) {
+ return a+b;
+}
+
+// LINUX32: !DISubprogram({{.*}}"add_fastcall", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX32: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_BORLAND_msfastcall,
+__attribute__((fastcall)) int add_fastcall(int a, int b) {
+ return a+b;
+}
+
+// LINUX32: !DISubprogram({{.*}}"add_thiscall", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX32: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_BORLAND_thiscall,
+__attribute__((thiscall)) int add_thiscall(int a, int b) {
+ return a+b;
+}
+
+// LINUX32: !DISubprogram({{.*}}"add_vectorcall", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX32: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_vectorcall,
+__attribute__((vectorcall)) int add_vectorcall(int a, int b) {
+ return a+b;
+}
+
+// LINUX32: !DISubprogram({{.*}}"add_pascal", {{.*}}type: ![[FTY:[0-9]+]]
+// LINUX32: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_BORLAND_pascal,
+__attribute__((pascal)) int add_pascal(int a, int b) {
+ return a+b;
+}
+#endif
+
+#ifdef __arm__
+// ARM: !DISubprogram({{.*}}"add_aapcs", {{.*}}type: ![[FTY:[0-9]+]]
+// ARM: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_AAPCS,
+__attribute__((pcs("aapcs"))) int add_aapcs(int a, int b) {
+ return a+b;
+}
+
+// ARM: !DISubprogram({{.*}}"add_aapcs_vfp", {{.*}}type: ![[FTY:[0-9]+]]
+// ARM: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_AAPCS_VFP,
+__attribute__((pcs("aapcs-vfp"))) int add_aapcs_vfp(int a, int b) {
+ return a+b;
+}
+#endif
diff --git a/test/CodeGen/exceptions-seh-finally.c b/test/CodeGen/exceptions-seh-finally.c
index ecb6f76..555e3ac 100644
--- a/test/CodeGen/exceptions-seh-finally.c
+++ b/test/CodeGen/exceptions-seh-finally.c
@@ -19,16 +19,16 @@
//
// CHECK: [[invoke_cont]]
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
// CHECK-NEXT: ret void
//
// CHECK: [[lpad]]
// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
-// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}})
+// CHECK: define internal void @"?fin$0@0@basic_finally@@"({{.*}})
// CHECK-SAME: [[finally_attrs:#[0-9]+]]
// CHECK: call void @cleanup()
@@ -59,10 +59,10 @@
//
// CHECK: [[invoke_cont]]
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@label_in_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@label_in_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
// CHECK: ret void
-// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"({{.*}})
+// CHECK: define internal void @"?fin$0@0@label_in_finally@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: br label %[[l:[^ ]*]]
//
@@ -87,16 +87,16 @@
//
// CHECK: [[invoke_cont]]
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
// CHECK: ret void
//
// CHECK: [[lpad]]
// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
-// CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer)
+// CHECK: define internal void @"?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer)
// CHECK-SAME: [[finally_attrs]]
// CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32
// CHECK: store i32 %[[abnormal_zext]], i32* @crashed
@@ -111,10 +111,10 @@
}
// CHECK-LABEL: define dso_local void @noreturn_noop_finally()
-// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
+// CHECK: call void @"?fin$0@0@noreturn_noop_finally@@"({{.*}})
// CHECK: ret void
-// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
+// CHECK: define internal void @"?fin$0@0@noreturn_noop_finally@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: call void @abort()
// CHECK: unreachable
@@ -132,15 +132,15 @@
// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[cont]]
-// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
+// CHECK: call void @"?fin$0@0@noreturn_finally@@"({{.*}})
// CHECK: ret void
//
// CHECK: [[lpad]]
// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
-// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
+// CHECK: call void @"?fin$0@0@noreturn_finally@@"({{.*}})
// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
-// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
+// CHECK: define internal void @"?fin$0@0@noreturn_finally@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: call void @abort()
// CHECK: unreachable
@@ -152,10 +152,10 @@
}
}
// CHECK-LABEL: define dso_local i32 @finally_with_return()
-// CHECK: call void @"\01?fin$0@0@finally_with_return@@"({{.*}})
+// CHECK: call void @"?fin$0@0@finally_with_return@@"({{.*}})
// CHECK-NEXT: ret i32 42
-// CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"({{.*}})
+// CHECK: define internal void @"?fin$0@0@finally_with_return@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK-NOT: br i1
// CHECK-NOT: br label
@@ -174,23 +174,23 @@
}
// CHECK-LABEL: define dso_local i32 @nested___finally___finally
-// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
+// CHECK: invoke void @"?fin$1@0@nested___finally___finally@@"({{.*}})
// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[outercont]]
-// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
+// CHECK: call void @"?fin$0@0@nested___finally___finally@@"({{.*}})
// CHECK-NEXT: ret i32 0
//
// CHECK: [[lpad]]
// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
-// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
+// CHECK: call void @"?fin$0@0@nested___finally___finally@@"({{.*}})
// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
-// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
+// CHECK-LABEL: define internal void @"?fin$0@0@nested___finally___finally@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: ret void
-// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
+// CHECK-LABEL: define internal void @"?fin$1@0@nested___finally___finally@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: unreachable
@@ -213,16 +213,16 @@
// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
//
// [[invokecont]]
-// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK: invoke void @"?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK-NEXT: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
//
// CHECK: [[outercont]]
-// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK: call void @"?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK-NEXT: ret i32 912
//
// CHECK: [[lpad1]]
// CHECK-NEXT: %[[innerpad:[^ ]*]] = cleanuppad
-// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK: invoke void @"?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK-NEXT: label %[[innercleanupretbb:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
//
// CHECK: [[innercleanupretbb]]
@@ -230,14 +230,14 @@
//
// CHECK: [[lpad2]]
// CHECK-NEXT: %[[outerpad:[^ ]*]] = cleanuppad
-// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK: call void @"?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK-NEXT: cleanupret from %[[outerpad]] unwind to caller
-// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK-LABEL: define internal void @"?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: ret void
-// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK-LABEL: define internal void @"?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: unreachable
@@ -255,17 +255,17 @@
// CHECK-LABEL: define dso_local void @finally_within_finally(
// CHECK: invoke void @might_crash(
-// CHECK: call void @"\01?fin$0@0@finally_within_finally@@"(
-// CHECK: call void @"\01?fin$0@0@finally_within_finally@@"({{.*}}) [ "funclet"(
+// CHECK: call void @"?fin$0@0@finally_within_finally@@"(
+// CHECK: call void @"?fin$0@0@finally_within_finally@@"({{.*}}) [ "funclet"(
-// CHECK-LABEL: define internal void @"\01?fin$0@0@finally_within_finally@@"({{[^)]*}})
+// CHECK-LABEL: define internal void @"?fin$0@0@finally_within_finally@@"({{[^)]*}})
// CHECK-SAME: [[finally_attrs]]
// CHECK: invoke void @might_crash(
-// CHECK: call void @"\01?fin$1@0@finally_within_finally@@"(
-// CHECK: call void @"\01?fin$1@0@finally_within_finally@@"({{.*}}) [ "funclet"(
+// CHECK: call void @"?fin$1@0@finally_within_finally@@"(
+// CHECK: call void @"?fin$1@0@finally_within_finally@@"({{.*}}) [ "funclet"(
-// CHECK-LABEL: define internal void @"\01?fin$1@0@finally_within_finally@@"({{[^)]*}})
+// CHECK-LABEL: define internal void @"?fin$1@0@finally_within_finally@@"({{[^)]*}})
// CHECK-SAME: [[finally_attrs]]
// Look for the absence of noinline. Enum attributes come first, so check that
diff --git a/test/CodeGen/exceptions-seh-leave.c b/test/CodeGen/exceptions-seh-leave.c
index e61c8b3..e977e32 100644
--- a/test/CodeGen/exceptions-seh-leave.c
+++ b/test/CodeGen/exceptions-seh-leave.c
@@ -75,7 +75,7 @@
// CHECK-NOT: store i32 23
// CHECK: [[tryleave]]
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_simple@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@__leave_with___finally_simple@@"(i8 0, i8* %[[fp]])
// __finally block doesn't return, __finally.cont doesn't exist.
int __leave_with___finally_noreturn() {
@@ -95,7 +95,7 @@
// CHECK-NOT: store i32 23
// CHECK: [[tryleave]]
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_noreturn@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@__leave_with___finally_noreturn@@"(i8 0, i8* %[[fp]])
// The "normal" case.
int __leave_with___finally() {
@@ -119,7 +119,7 @@
// CHECK-NOT: store i32 23
// CHECK: [[tryleave]]
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@__leave_with___finally@@"(i8 0, i8* %[[fp]])
//////////////////////////////////////////////////////////////////////////////
@@ -149,7 +149,7 @@
// CHECK: [[g1_cont1]]
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: invoke void @"?fin$0@0@nested___except___finally@@"(i8 0, i8* %[[fp]])
// CHECK-NEXT: to label %[[fin_cont:.*]] unwind label %[[g2_lpad:.*]]
// CHECK: [[fin_cont]]
@@ -159,7 +159,7 @@
// CHECK: [[g1_lpad]]
// CHECK-NEXT: cleanuppad
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i8 1, i8* %[[fp]])
+// CHECK-NEXT: invoke void @"?fin$0@0@nested___except___finally@@"(i8 1, i8* %[[fp]])
// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[g2_lpad]]
// CHECK: cleanupret {{.*}} unwind label %[[g2_lpad]]
@@ -171,7 +171,7 @@
// CHECK: [[trycont]]
// CHECK-NEXT: ret i32 1
-// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___except___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
+// CHECK-LABEL: define internal void @"?fin$0@0@nested___except___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
// CHECK: call void @g()
// CHECK: unreachable
@@ -271,16 +271,16 @@
// CHECK: [[tryleave]]
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@nested___finally___except@@"(i8 0, i8* %[[fp]])
// CHECK-NEXT: ret i32 1
// CHECK: [[g2_lpad]]
// CHECK: cleanuppad
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i8 1, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@nested___finally___except@@"(i8 1, i8* %[[fp]])
// CHECK: cleanupret {{.*}} unwind to caller
-// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___except@@"(i8 %abnormal_termination, i8* %frame_pointer)
+// CHECK-LABEL: define internal void @"?fin$0@0@nested___finally___except@@"(i8 %abnormal_termination, i8* %frame_pointer)
// CHECK: ret void
int nested___finally___finally() {
@@ -310,19 +310,19 @@
// CHECK: [[g1_cont]]
// CHECK: store i32 16, i32* %[[myres:[^ ]*]],
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: invoke void @"?fin$1@0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
// CHECK-NEXT: to label %[[finally_cont:.*]] unwind label %[[g2_lpad:.*]]
// CHECK: [[finally_cont]]
// CHECK: store i32 51, i32* %[[myres]]
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
// CHECK-NEXT: ret i32 1
// CHECK: [[g1_lpad]]
// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad within none []
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
+// CHECK-NEXT: invoke void @"?fin$1@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label %[[g2_lpad]]
// CHECK: [[finally_cont2]]
// CHECK: cleanupret from %[[padtoken]] unwind label %[[g2_lpad]]
@@ -330,12 +330,12 @@
// CHECK: [[g2_lpad]]
// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad within none []
// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
+// CHECK-NEXT: call void @"?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
// CHECK: cleanupret from %[[padtoken]] unwind to caller
-// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
+// CHECK-LABEL: define internal void @"?fin$0@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
// CHECK: ret void
-// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
+// CHECK-LABEL: define internal void @"?fin$1@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
// CHECK: call void @g()
// CHECK: unreachable
diff --git a/test/CodeGen/exceptions-seh.c b/test/CodeGen/exceptions-seh.c
index 085a9a1..b38c7a2 100644
--- a/test/CodeGen/exceptions-seh.c
+++ b/test/CodeGen/exceptions-seh.c
@@ -35,7 +35,7 @@
//
// CHECK: [[catchpad]]
// X64: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* null]
-// X86: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* bitcast (i32 ()* @"\01?filt$0@0@safe_div@@" to i8*)]
+// X86: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* bitcast (i32 ()* @"?filt$0@0@safe_div@@" to i8*)]
// CHECK-NEXT: catchret from %[[padtoken]] to label %[[except:[^ ]*]]
//
// CHECK: [[except]]
@@ -46,7 +46,7 @@
// 32-bit SEH needs this filter to save the exception code.
//
-// X86-LABEL: define internal i32 @"\01?filt$0@0@safe_div@@"()
+// X86-LABEL: define internal i32 @"?filt$0@0@safe_div@@"()
// X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[ebp]])
// X86: call i8* @llvm.localrecover(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[fp]], i32 0)
@@ -82,17 +82,17 @@
// CHECK: store i32 42, i32* %[[r]]
// CHECK: invoke void @j() #[[NOINLINE]]
//
-// CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@filter_expr_capture@@" to i8*)]
+// CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"?filt$0@0@filter_expr_capture@@" to i8*)]
// CHECK: store i32 13, i32* %[[r]]
//
// CHECK: %[[rv:[^ ]*]] = load i32, i32* %[[r]]
// CHECK: ret i32 %[[rv]]
-// X64-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer)
+// X64-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer)
// X64: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer)
// X64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0)
//
-// X86-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"()
+// X86-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"()
// X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[ebp]])
// X86: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0)
@@ -128,7 +128,7 @@
// CHECK: %[[cs_outer:[^ ]*]] = catchswitch within none [label %[[cpad_outer:[^ ]*]]] unwind to caller
//
// CHECK: [[cpad_outer]]
-// CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@nested_try@@" to i8*)]
+// CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"?filt$0@0@nested_try@@" to i8*)]
// CHECK-NEXT: catchret {{.*}} to label %[[except_outer:[^ ]*]]
//
// CHECK: [[except_outer]]
@@ -140,7 +140,7 @@
// CHECK: ret i32 %[[r_load]]
//
// CHECK: [[cpad_inner]]
-// CHECK: catchpad within %[[cs_inner]] [i8* bitcast (i32 ({{.*}})* @"\01?filt$1@0@nested_try@@" to i8*)]
+// CHECK: catchpad within %[[cs_inner]] [i8* bitcast (i32 ({{.*}})* @"?filt$1@0@nested_try@@" to i8*)]
// CHECK-NEXT: catchret {{.*}} to label %[[except_inner:[^ ]*]]
//
// CHECK: [[except_inner]]
@@ -154,13 +154,13 @@
// CHECK: store i32 0, i32* %[[r]]
// CHECK: br label %[[inner_try_cont]]
//
-// CHECK-LABEL: define internal i32 @"\01?filt$0@0@nested_try@@"({{.*}})
+// CHECK-LABEL: define internal i32 @"?filt$0@0@nested_try@@"({{.*}})
// X86: call i8* @llvm.x86.seh.recoverfp({{.*}})
// CHECK: load i32*, i32**
// CHECK: load i32, i32*
// CHECK: icmp eq i32 %{{.*}}, 456
//
-// CHECK-LABEL: define internal i32 @"\01?filt$1@0@nested_try@@"({{.*}})
+// CHECK-LABEL: define internal i32 @"?filt$1@0@nested_try@@"({{.*}})
// X86: call i8* @llvm.x86.seh.recoverfp({{.*}})
// CHECK: load i32*, i32**
// CHECK: load i32, i32*
@@ -186,17 +186,17 @@
//
// CHECK: [[cont]]
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
// CHECK: load i32, i32* %[[g_addr]], align 4
// CHECK: ret i32
//
// CHECK: [[cleanuppad]]
// CHECK: %[[padtoken:[^ ]*]] = cleanuppad within none []
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
// CHECK: cleanupret from %[[padtoken]] unwind to caller
-// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} %abnormal_termination, i8* %frame_pointer)
+// CHECK: define internal void @"?fin$0@0@basic_finally@@"({{i8( zeroext)?}} %abnormal_termination, i8* %frame_pointer)
// CHECK: call i8* @llvm.localrecover(i8* bitcast (i32 (i32)* @basic_finally to i8*), i8* %frame_pointer, i32 0)
// CHECK: load i32, i32* %{{.*}}, align 4
// CHECK: add nsw i32 %{{.*}}, 1
diff --git a/test/CodeGen/flip-dllimport.c b/test/CodeGen/flip-dllimport.c
new file mode 100644
index 0000000..d20479d
--- /dev/null
+++ b/test/CodeGen/flip-dllimport.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -emit-llvm -o - %s | FileCheck %s
+
+__declspec(dllimport) void f();
+void g() { f(); } // use it
+
+// CHECK: define dso_local dllexport void @f
+void f() { }
diff --git a/test/CodeGen/hexagon-brev-ld-ptr-incdec.c b/test/CodeGen/hexagon-brev-ld-ptr-incdec.c
new file mode 100644
index 0000000..67c6c34
--- /dev/null
+++ b/test/CodeGen/hexagon-brev-ld-ptr-incdec.c
@@ -0,0 +1,52 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -emit-llvm -O2 -o - -triple hexagon-unknown-elf %s | FileCheck %s
+
+// The return value should return the value in A[1].
+// Check that the HexagonBuiltinExpr doesn't evaluate &(*ptr++) twice. If so,
+// the return value will be the value in A[2]
+// CHECK: @brev_ptr_inc
+// CHECK-DAG: llvm.hexagon.L2.loadri.pbr
+// CHECK-DAG: getelementptr{{.*}}i32 1
+// CHECK-NOT: getelementptr{{.*}}i32 2
+// CHECK-NOT: getelementptr{{.*}}i32 1
+int brev_ptr_inc(int A[], int B[]) {
+ int *p0 = &B[0];
+ int *p1 = &A[0];
+ __builtin_brev_ldw(p0, &*p1++, 8);
+ return (*p1);
+}
+
+// The return value should return the value in A[0].
+// CHECK: @brev_ptr_dec
+// CHECK: llvm.hexagon.L2.loadri.pbr
+// CHECK: [[RET:%[0-9]+]] = load{{.*}}%A
+// CHECK: ret{{.*}}[[RET]]
+int brev_ptr_dec(int A[], int B[]) {
+ int *p0 = &B[0];
+ int *p1 = &A[1];
+ __builtin_brev_ldw(p0, &*p1--, 8);
+ return (*p1);
+}
+
+// The store in bitcode needs to be of width correspondng to 16-bit.
+// CHECK: @brev_ptr_half
+// CHECK: llvm.hexagon.L2.loadrh.pbr
+// CHECK: store{{.*}}i16{{.*}}i16*
+short int brev_ptr_half(short int A[], short int B[]) {
+ short int *p0 = &B[0];
+ short int *p1 = &A[0];
+ __builtin_brev_ldh(p0, &*p1++, 8);
+ return (*p1);
+}
+
+// The store in bitcode needs to be of width correspondng to 8-bit.
+// CHECK: @brev_ptr_byte
+// CHECK: llvm.hexagon.L2.loadrub.pbr
+// CHECK: store{{.*}}i8{{.*}}i8*
+unsigned char brev_ptr_byte(unsigned char A[], unsigned char B[]) {
+ unsigned char *p0 = &B[0];
+ unsigned char *p1 = &A[0];
+ __builtin_brev_ldub(p0, &*p1++, 8);
+ return (*p1);
+}
+
diff --git a/test/CodeGen/hexagon-brev-store-elm.c b/test/CodeGen/hexagon-brev-store-elm.c
new file mode 100644
index 0000000..f593419
--- /dev/null
+++ b/test/CodeGen/hexagon-brev-store-elm.c
@@ -0,0 +1,46 @@
+// REQUIRES: hexagon-registered-target
+// RUN: %clang_cc1 -emit-llvm -O2 -o - -triple hexagon-unknown-elf %s | FileCheck %s
+// This unit test validates that the store to "dst" variable needs to be eliminated.
+
+// CHECK: @brev_store_elimination_test1
+// CHECK: llvm.hexagon.L2.loadri.pbr
+// CHECK-NOT: store
+
+int *brev_store_elimination_test1(int *ptr, int mod) {
+ int dst = 100;
+ return __builtin_brev_ldw(ptr, &dst, mod);
+}
+
+// CHECK: @brev_store_elimination_test2
+// CHECK: llvm.hexagon.L2.loadri.pbr
+// CHECK-NOT: store
+extern int add(int a);
+int brev_store_elimination_test2(int *ptr, int mod) {
+ int dst = 100;
+ __builtin_brev_ldw(ptr, &dst, mod);
+ return add(dst);
+}
+
+// CHECK: @brev_store_elimination_test3
+// CHECK: llvm.hexagon.L2.loadri.pbr
+// CHECK-NOT: store
+int brev_store_elimination_test3(int *ptr, int mod, int inc) {
+ int dst = 100;
+ for (int i = 0; i < inc; ++i) {
+ __builtin_brev_ldw(ptr, &dst, mod);
+ dst = add(dst);
+ }
+ return dst;
+}
+
+// brev_store_elimination_test4 validates the fact that we are not deleting the
+// stores if the value is passed by reference later.
+// CHECK: @brev_store_elimination_test4
+// CHECK: llvm.hexagon.L2.loadri.pbr
+// CHECK: store
+extern int sub(int *a);
+int brev_store_elimination_test4(int *ptr, int mod) {
+ int dst = 100;
+ __builtin_brev_ldw(ptr, &dst, mod);
+ return sub(&dst);
+}
diff --git a/test/CodeGen/mangle-ms.c b/test/CodeGen/mangle-ms.c
index 0b05b7b..13d23c6 100644
--- a/test/CodeGen/mangle-ms.c
+++ b/test/CodeGen/mangle-ms.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s
-// CHECK: define dso_local void @"\01?f@@$$J0YAXP6AX@Z@Z"
+// CHECK: define dso_local void @"?f@@$$J0YAXP6AX@Z@Z"
__attribute__((overloadable)) void f(void (*x)()) {}
// CHECK: define dso_local void @f
@@ -9,5 +9,5 @@
// CHECK: define dso_local void @g
void g(void (*x)(int)) {}
-// CHECK: define dso_local void @"\01?g@@$$J0YAXP6AX@Z@Z"
+// CHECK: define dso_local void @"?g@@$$J0YAXP6AX@Z@Z"
__attribute__((overloadable)) void g(void (*x)()) {}
diff --git a/test/CodeGen/math-builtins.c b/test/CodeGen/math-builtins.c
index 89be56d..4be8981 100644
--- a/test/CodeGen/math-builtins.c
+++ b/test/CodeGen/math-builtins.c
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm %s | FileCheck %s -check-prefix=NO__ERRNO
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s -check-prefix=HAS_ERRNO
// RUN: %clang_cc1 -triple x86_64-unknown-unknown-gnu -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO_GNU
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown-android -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO_ANDROID
// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO_WIN
// Test attributes and codegen of math builtins.
@@ -296,6 +297,10 @@
// HAS_ERRNO_GNU: declare float @llvm.fma.f32(float, float, float) [[READNONE_INTRINSIC]]
// HAS_ERRNO_GNU: declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) [[READNONE_INTRINSIC]]
+// HAS_ERRNO_ANDROID: declare double @llvm.fma.f64(double, double, double) [[READNONE_INTRINSIC:#[0-9]+]]
+// HAS_ERRNO_ANDROID: declare float @llvm.fma.f32(float, float, float) [[READNONE_INTRINSIC]]
+// HAS_ERRNO_ANDROID: declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) [[READNONE_INTRINSIC]]
+
// HAS_ERRNO_WIN: declare double @llvm.fma.f64(double, double, double) [[READNONE_INTRINSIC:#[0-9]+]]
// HAS_ERRNO_WIN: declare float @llvm.fma.f32(float, float, float) [[READNONE_INTRINSIC]]
// Long double is just double on win, so no f80 use/declaration.
@@ -582,5 +587,6 @@
// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} }
// HAS_ERRNO_GNU: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} }
+// HAS_ERRNO_ANDROID: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} }
// HAS_ERRNO_WIN: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} }
diff --git a/test/CodeGen/mingw-long-double.c b/test/CodeGen/mingw-long-double.c
index d344d9f..6026c24 100644
--- a/test/CodeGen/mingw-long-double.c
+++ b/test/CodeGen/mingw-long-double.c
@@ -41,3 +41,7 @@
// GNU32: define dso_local void @TestLDC({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 4 %x)
// GNU64: define dso_local void @TestLDC({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* %x)
// MSC64: define dso_local void @TestLDC({ double, double }* noalias sret %agg.result, { double, double }* %x)
+
+// GNU32: declare dso_local void @__mulxc3
+// GNU64: declare dso_local void @__mulxc3
+// MSC64: declare dso_local void @__muldc3
diff --git a/test/CodeGen/ms-declspecs.cpp b/test/CodeGen/ms-declspecs.cpp
index 06f45a2..99e39f9 100644
--- a/test/CodeGen/ms-declspecs.cpp
+++ b/test/CodeGen/ms-declspecs.cpp
@@ -8,8 +8,8 @@
__declspec(selectany) int x4;
}
__declspec(selectany) int x5;
-// CHECK: @"\01?x1@@3HA" = weak_odr dso_local global i32 0, comdat, align 4
+// CHECK: @"?x1@@3HA" = weak_odr dso_local global i32 0, comdat, align 4
// CHECK: @x2 = weak_odr dso_local global i32 0, comdat, align 4
-// CHECK: @"\01?x3@@3HA" = weak_odr dso_local global i32 0, comdat, align 4
+// CHECK: @"?x3@@3HA" = weak_odr dso_local global i32 0, comdat, align 4
// CHECK: @x4 = weak_odr dso_local global i32 0, comdat, align 4
-// CHECK: @"\01?x5@@3HA" = weak_odr dso_local global i32 0, comdat, align 4
+// CHECK: @"?x5@@3HA" = weak_odr dso_local global i32 0, comdat, align 4
diff --git a/test/CodeGen/ms_this.cpp b/test/CodeGen/ms_this.cpp
index 3776a6e..f0da36f 100644
--- a/test/CodeGen/ms_this.cpp
+++ b/test/CodeGen/ms_this.cpp
@@ -13,7 +13,7 @@
void runc();
};
-// CHECK: define dso_local void @"\01?runc@t2@@
+// CHECK: define dso_local void @"?runc@t2@@
void t2::runc() {
double num = 0;
__asm {
@@ -26,7 +26,7 @@
};
}
-// CHECK: define dso_local void @"\01?runc@t1@@
+// CHECK: define dso_local void @"?runc@t1@@
void t1::runc() {
double num = 0;
__asm {
@@ -41,7 +41,7 @@
struct s {
int a;
- // CHECK: define linkonce_odr dso_local void @"\01?func@s@@
+ // CHECK: define linkonce_odr dso_local void @"?func@s@@
void func() {
__asm mov rax, [this]
// CHECK: [[THIS_ADDR_S:%.+]] = alloca %struct.s*
diff --git a/test/CodeGen/personality.c b/test/CodeGen/personality.c
new file mode 100644
index 0000000..283fccd
--- /dev/null
+++ b/test/CodeGen/personality.c
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-SJLJ
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fblocks -fseh-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH -check-prefix CHECK-WIN-SEH-X86
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fblocks -fseh-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH -check-prefix CHECK-WIN-SEH-X64
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fblocks -fsjlj-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SJLJ
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fblocks -fseh-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MINGW-SEH -check-prefix CHECK-WIN-SEH-X86
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-gnu -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fblocks -fseh-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MINGW-SEH -check-prefix CHECK-WIN-SEH-X64
+
+
+extern void g(void (^)(void));
+extern void i(void);
+
+// CHECK-GNU: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+// CHECK-DWARF: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+// CHECK-SEH: personality i8* bitcast (i32 (...)* @__gcc_personality_seh0 to i8*)
+// CHECK-SJLJ: personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*)
+
+// CHECK-WIN: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+// CHECK-WIN-DWARF: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+// CHECK-WIN-SEH: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+// CHECK-MINGW-SEH: personality i8* bitcast (i32 (...)* @__gcc_personality_seh0 to i8*)
+// CHECK-WIN-SJLJ: personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*)
+
+void f(void) {
+ __block int i;
+ g(^ { });
+}
+
+#if defined(__SEH_EXCEPTIONS__)
+// CHECK-WIN-SEH-X86: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
+// CHECK-WIN-SEH-X64: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+
+void h(void) {
+ __try {
+ i();
+ } __finally {
+ }
+}
+#endif
+
diff --git a/test/CodeGen/ppc64-align-struct.c b/test/CodeGen/ppc64-align-struct.c
index 3cf3e04..5e2dc8b 100644
--- a/test/CodeGen/ppc64-align-struct.c
+++ b/test/CodeGen/ppc64-align-struct.c
@@ -48,13 +48,12 @@
{
}
-// CHECK-LABEL: define void @test1va(%struct.test1* noalias sret %agg.result, i32 signext %x, ...)
-// CHECK: %y = alloca %struct.test1, align 4
+// CHECK: define void @test1va(%struct.test1* noalias sret %[[AGG_RESULT:.*]], i32 signext %x, ...)
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 8
// CHECK: store i8* %[[NEXT]], i8** %ap
// CHECK: [[T0:%.*]] = bitcast i8* %[[CUR]] to %struct.test1*
-// CHECK: [[DEST:%.*]] = bitcast %struct.test1* %y to i8*
+// CHECK: [[DEST:%.*]] = bitcast %struct.test1* %[[AGG_RESULT]] to i8*
// CHECK: [[SRC:%.*]] = bitcast %struct.test1* [[T0]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[DEST]], i8* align 8 [[SRC]], i64 8, i1 false)
struct test1 test1va (int x, ...)
@@ -67,8 +66,7 @@
return y;
}
-// CHECK-LABEL: define void @test2va(%struct.test2* noalias sret %agg.result, i32 signext %x, ...)
-// CHECK: %y = alloca %struct.test2, align 16
+// CHECK: define void @test2va(%struct.test2* noalias sret %[[AGG_RESULT:.*]], i32 signext %x, ...)
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK: %[[TMP0:[^ ]+]] = ptrtoint i8* %[[CUR]] to i64
// CHECK: %[[TMP1:[^ ]+]] = add i64 %[[TMP0]], 15
@@ -77,7 +75,7 @@
// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[ALIGN]], i64 16
// CHECK: store i8* %[[NEXT]], i8** %ap
// CHECK: [[T0:%.*]] = bitcast i8* %[[ALIGN]] to %struct.test2*
-// CHECK: [[DEST:%.*]] = bitcast %struct.test2* %y to i8*
+// CHECK: [[DEST:%.*]] = bitcast %struct.test2* %[[AGG_RESULT]] to i8*
// CHECK: [[SRC:%.*]] = bitcast %struct.test2* [[T0]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[DEST]], i8* align 16 [[SRC]], i64 16, i1 false)
struct test2 test2va (int x, ...)
@@ -90,8 +88,7 @@
return y;
}
-// CHECK-LABEL: define void @test3va(%struct.test3* noalias sret %agg.result, i32 signext %x, ...)
-// CHECK: %y = alloca %struct.test3, align 32
+// CHECK: define void @test3va(%struct.test3* noalias sret %[[AGG_RESULT:.*]], i32 signext %x, ...)
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK: %[[TMP0:[^ ]+]] = ptrtoint i8* %[[CUR]] to i64
// CHECK: %[[TMP1:[^ ]+]] = add i64 %[[TMP0]], 15
@@ -100,7 +97,7 @@
// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[ALIGN]], i64 32
// CHECK: store i8* %[[NEXT]], i8** %ap
// CHECK: [[T0:%.*]] = bitcast i8* %[[ALIGN]] to %struct.test3*
-// CHECK: [[DEST:%.*]] = bitcast %struct.test3* %y to i8*
+// CHECK: [[DEST:%.*]] = bitcast %struct.test3* %[[AGG_RESULT]] to i8*
// CHECK: [[SRC:%.*]] = bitcast %struct.test3* [[T0]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 32 [[DEST]], i8* align 16 [[SRC]], i64 32, i1 false)
struct test3 test3va (int x, ...)
@@ -113,13 +110,12 @@
return y;
}
-// CHECK-LABEL: define void @test4va(%struct.test4* noalias sret %agg.result, i32 signext %x, ...)
-// CHECK: %y = alloca %struct.test4, align 4
+// CHECK: define void @test4va(%struct.test4* noalias sret %[[AGG_RESULT:.*]], i32 signext %x, ...)
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 16
// CHECK: store i8* %[[NEXT]], i8** %ap
// CHECK: [[T0:%.*]] = bitcast i8* %[[CUR]] to %struct.test4*
-// CHECK: [[DEST:%.*]] = bitcast %struct.test4* %y to i8*
+// CHECK: [[DEST:%.*]] = bitcast %struct.test4* %[[AGG_RESULT]] to i8*
// CHECK: [[SRC:%.*]] = bitcast %struct.test4* [[T0]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[DEST]], i8* align 8 [[SRC]], i64 12, i1 false)
struct test4 test4va (int x, ...)
@@ -132,13 +128,12 @@
return y;
}
-// CHECK-LABEL: define void @testva_longdouble(%struct.test_longdouble* noalias sret %agg.result, i32 signext %x, ...)
-// CHECK: %y = alloca %struct.test_longdouble, align 16
+// CHECK: define void @testva_longdouble(%struct.test_longdouble* noalias sret %[[AGG_RESULT:.*]], i32 signext %x, ...)
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 16
// CHECK: store i8* %[[NEXT]], i8** %ap
// CHECK: [[T0:%.*]] = bitcast i8* %[[CUR]] to %struct.test_longdouble*
-// CHECK: [[DEST:%.*]] = bitcast %struct.test_longdouble* %y to i8*
+// CHECK: [[DEST:%.*]] = bitcast %struct.test_longdouble* %[[AGG_RESULT]] to i8*
// CHECK: [[SRC:%.*]] = bitcast %struct.test_longdouble* [[T0]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[DEST]], i8* align 8 [[SRC]], i64 16, i1 false)
struct test_longdouble { long double x; };
@@ -152,8 +147,7 @@
return y;
}
-// CHECK-LABEL: define void @testva_vector(%struct.test_vector* noalias sret %agg.result, i32 signext %x, ...)
-// CHECK: %y = alloca %struct.test_vector, align 16
+// CHECK: define void @testva_vector(%struct.test_vector* noalias sret %[[AGG_RESULT:.*]], i32 signext %x, ...)
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK: %[[TMP0:[^ ]+]] = ptrtoint i8* %[[CUR]] to i64
// CHECK: %[[TMP1:[^ ]+]] = add i64 %[[TMP0]], 15
@@ -162,7 +156,7 @@
// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[ALIGN]], i64 16
// CHECK: store i8* %[[NEXT]], i8** %ap
// CHECK: [[T0:%.*]] = bitcast i8* %[[ALIGN]] to %struct.test_vector*
-// CHECK: [[DEST:%.*]] = bitcast %struct.test_vector* %y to i8*
+// CHECK: [[DEST:%.*]] = bitcast %struct.test_vector* %[[AGG_RESULT]] to i8*
// CHECK: [[SRC:%.*]] = bitcast %struct.test_vector* [[T0]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[DEST]], i8* align 16 [[SRC]], i64 16, i1 false)
struct test_vector { vector int x; };
diff --git a/test/CodeGen/preserve-call-conv.c b/test/CodeGen/preserve-call-conv.c
index 2dff34e..7a84fa2 100644
--- a/test/CodeGen/preserve-call-conv.c
+++ b/test/CodeGen/preserve-call-conv.c
@@ -3,6 +3,7 @@
// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple thumbv7-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s
// Check that the preserve_most calling convention attribute at the source level
// is lowered to the corresponding calling convention attrribute at the LLVM IR
diff --git a/test/CodeGen/string-literal-short-wstring.c b/test/CodeGen/string-literal-short-wstring.c
index fb1fe0c..8894b88 100644
--- a/test/CodeGen/string-literal-short-wstring.c
+++ b/test/CodeGen/string-literal-short-wstring.c
@@ -12,12 +12,12 @@
char b[10] = "\u1120\u0220\U00102030";
// ITANIUM: private unnamed_addr constant [3 x i16] [i16 65, i16 66, i16 0]
- // MSABI: linkonce_odr unnamed_addr constant [3 x i16] [i16 65, i16 66, i16 0]
+ // MSABI: linkonce_odr dso_local unnamed_addr constant [3 x i16] [i16 65, i16 66, i16 0]
const wchar_t *foo = L"AB";
// This should convert to utf16.
// ITANIUM: private unnamed_addr constant [5 x i16] [i16 4384, i16 544, i16 -9272, i16 -9168, i16 0]
- // MSABI: linkonce_odr unnamed_addr constant [5 x i16] [i16 4384, i16 544, i16 -9272, i16 -9168, i16 0]
+ // MSABI: linkonce_odr dso_local unnamed_addr constant [5 x i16] [i16 4384, i16 544, i16 -9272, i16 -9168, i16 0]
const wchar_t *bar = L"\u1120\u0220\U00102030";
diff --git a/test/CodeGen/target-data.c b/test/CodeGen/target-data.c
index 9349cec..2b99091 100644
--- a/test/CodeGen/target-data.c
+++ b/test/CodeGen/target-data.c
@@ -124,20 +124,20 @@
// RUN: %clang_cc1 -triple r600-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=R600
-// R600: target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5"
+// R600: target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5"
// RUN: %clang_cc1 -triple r600-unknown -target-cpu cayman -o - -emit-llvm %s \
// RUN: | FileCheck %s -check-prefix=R600D
-// R600D: target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5"
+// R600D: target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5"
// RUN: %clang_cc1 -triple amdgcn-unknown -target-cpu hawaii -o - -emit-llvm %s \
// RUN: | FileCheck %s -check-prefix=R600SI
-// R600SI: target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5"
+// R600SI: target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5"
// Test default -target-cpu
// RUN: %clang_cc1 -triple amdgcn-unknown -o - -emit-llvm %s \
// RUN: | FileCheck %s -check-prefix=R600SIDefault
-// R600SIDefault: target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5"
+// R600SIDefault: target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5"
// RUN: %clang_cc1 -triple arm64-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=AARCH64
diff --git a/test/CodeGen/thinlto-distributed-cfi-devirt.ll b/test/CodeGen/thinlto-distributed-cfi-devirt.ll
index bd35524..aaec1ae 100644
--- a/test/CodeGen/thinlto-distributed-cfi-devirt.ll
+++ b/test/CodeGen/thinlto-distributed-cfi-devirt.ll
@@ -23,7 +23,7 @@
; Ensure that typeids are in the index.
; RUN: llvm-bcanalyzer -dump %t.o.thinlto.bc | FileCheck %s
; CHECK-LABEL: <GLOBALVAL_SUMMARY_BLOCK
-; CHECK: <TYPE_ID op0=0 op1=6 op2=4 op3=7 op4=0 op5=0 op6=0 op7=0 op8=0 op9=0 op10=6 op11=0 op12=0 op13=8 op14=1 op15=6 op16=9 op17=0/>
+; CHECK: <TYPE_ID op0=0 op1=6 op2=4 op3=7 op4=0 op5=0 op6=0 op7=0 op8=0 op9=2 op10=6 op11=0 op12=0 op13=8 op14=1 op15=6 op16=9 op17=0/>
; CHECK-LABEL: </GLOBALVAL_SUMMARY_BLOCK
; CHECK-LABEL: <STRTAB_BLOCK
; CHECK: blob data = '_ZTS1A_ZN1A1nEi'
diff --git a/test/CodeGen/wasm-varargs.c b/test/CodeGen/wasm-varargs.c
index 3883549..acbd590 100644
--- a/test/CodeGen/wasm-varargs.c
+++ b/test/CodeGen/wasm-varargs.c
@@ -80,10 +80,9 @@
return v;
}
-// CHECK: define void @test_struct([[STRUCT_S:%[^,=]+]]*{{.*}} noalias sret %agg.result, i8*{{.*}} %fmt, ...) {{.*}} {
+// CHECK: define void @test_struct([[STRUCT_S:%[^,=]+]]*{{.*}} noalias sret [[AGG_RESULT:%.*]], i8*{{.*}} %fmt, ...) {{.*}} {
// CHECK: [[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4
// CHECK: [[VA:%[^,=]+]] = alloca i8*, align 4
-// CHECK: [[V:%[^,=]+]] = alloca [[STRUCT_S]], align 4
// CHECK: store i8* %fmt, i8** [[FMT_ADDR]], align 4
// CHECK: [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
// CHECK: call void @llvm.va_start(i8* [[VA1]])
@@ -91,13 +90,10 @@
// CHECK: [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i32 12
// CHECK: store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
// CHECK: [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]*
-// CHECK: [[R4:%[^,=]+]] = bitcast [[STRUCT_S]]* [[V]] to i8*
+// CHECK: [[R4:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
// CHECK: [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R3]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R4]], i8* align 4 [[R5]], i32 12, i1 false)
// CHECK: [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
// CHECK: call void @llvm.va_end(i8* [[VA2]])
-// CHECK: [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* %agg.result to i8*
-// CHECK: [[R7:%[^,=]+]] = bitcast [[STRUCT_S]]* [[V]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R6]], i8* align 4 [[R7]], i32 12, i1 false)
// CHECK: ret void
// CHECK: }
diff --git a/test/CodeGen/wchar-const.c b/test/CodeGen/wchar-const.c
index b461d60..91b14ec 100644
--- a/test/CodeGen/wchar-const.c
+++ b/test/CodeGen/wchar-const.c
@@ -15,7 +15,7 @@
// CHECK-DAR: private unnamed_addr constant [18 x i32] [i32 84,
-// CHECK-WIN: linkonce_odr unnamed_addr constant [18 x i16] [i16 84,
+// CHECK-WIN: linkonce_odr dso_local unnamed_addr constant [18 x i16] [i16 84,
extern void foo(const wchar_t* p);
int main (int argc, const char * argv[])
{
diff --git a/test/CodeGen/windows-swiftcall.c b/test/CodeGen/windows-swiftcall.c
index a7cfb4d..d8fdec4 100644
--- a/test/CodeGen/windows-swiftcall.c
+++ b/test/CodeGen/windows-swiftcall.c
@@ -99,9 +99,7 @@
TEST(struct_1);
// CHECK-LABEL: define dso_local swiftcc { i64, i64 } @return_struct_1() {{.*}}{
// CHECK: [[RET:%.*]] = alloca [[STRUCT1:%.*]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[STRUCT1]], align 4
// CHECK: call void @llvm.memset
-// CHECK: call void @llvm.memcpy
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT1]]* %retval to { i64, i64 }*
// CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4
@@ -149,12 +147,8 @@
TEST(struct_2);
// CHECK-LABEL: define dso_local swiftcc { i64, i64 } @return_struct_2() {{.*}}{
// CHECK: [[RET:%.*]] = alloca [[STRUCT2_TYPE]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[STRUCT2_TYPE]], align 4
-// CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[VAR]]
+// CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[RET]]
// CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[CASTVAR]], {{.*}}[[STRUCT2_RESULT]]
-// CHECK: [[CASTRET:%.*]] = bitcast {{.*}} [[RET]]
-// CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[VAR]]
-// CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[CASTRET]], {{.*}}[[CASTVAR]]
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT2_TYPE]]* [[RET]] to { i64, i64 }*
// CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4
@@ -205,12 +199,8 @@
TEST(struct_misaligned_1)
// CHECK-LABEL: define dso_local swiftcc i64 @return_struct_misaligned_1()
// CHECK: [[RET:%.*]] = alloca [[STRUCT:%.*]], align 1
-// CHECK: [[RES:%.*]] = alloca [[STRUCT]], align 1
-// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RES]] to i8*
+// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RET]] to i8*
// CHECK: call void @llvm.memset{{.*}}(i8* align 1 [[CAST]], i8 0, i64 5
-// CHECK: [[CASTRET:%.*]] = bitcast [[STRUCT]]* [[RET]] to i8*
-// CHECK: [[CASTRES:%.*]] = bitcast [[STRUCT]]* [[RES]] to i8*
-// CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} [[CASTRET]], i8* align {{[0-9]+}} [[CASTRES]], i64 5
// CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RET]] to { i64 }*
// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 1
@@ -258,12 +248,8 @@
TEST(union_het_fp)
// CHECK-LABEL: define dso_local swiftcc i64 @return_union_het_fp()
// CHECK: [[RET:%.*]] = alloca [[UNION:%.*]], align 8
-// CHECK: [[RES:%.*]] = alloca [[UNION]], align 8
-// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RES]] to i8*
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to i8*
// CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} [[CAST]]
-// CHECK: [[CASTRET:%.*]] = bitcast [[UNION]]* [[RET]] to i8*
-// CHECK: [[CASTRES:%.*]] = bitcast [[UNION]]* [[RES]] to i8*
-// CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} [[CASTRET]], i8* align {{[0-9]+}} [[CASTRES]]
// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to { i64 }*
// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0
// CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 8
diff --git a/test/CodeGen/x86-cf-protection.c b/test/CodeGen/x86-cf-protection.c
index c853791..044f839 100644
--- a/test/CodeGen/x86-cf-protection.c
+++ b/test/CodeGen/x86-cf-protection.c
@@ -1,5 +1,5 @@
-// RUN: not %clang_cc1 -fsyntax-only -S -emit-llvm -o %t -triple i386-unknown-unknown -fcf-protection=return %s 2>&1 | FileCheck %s --check-prefix=RETURN
-// RUN: not %clang_cc1 -fsyntax-only -S -emit-llvm -o %t -triple i386-unknown-unknown -fcf-protection=branch %s 2>&1 | FileCheck %s --check-prefix=BRANCH
+// RUN: not %clang_cc1 -fsyntax-only -S -o %t -triple i386-unknown-unknown -fcf-protection=return %s 2>&1 | FileCheck %s --check-prefix=RETURN
+// RUN: not %clang_cc1 -fsyntax-only -S -o %t -triple i386-unknown-unknown -fcf-protection=branch %s 2>&1 | FileCheck %s --check-prefix=BRANCH
// RETURN: error: option 'cf-protection=return' cannot be specified without '-mshstk'
// BRANCH: error: option 'cf-protection=branch' cannot be specified without '-mibt'
diff --git a/test/CodeGenCUDA/alias.cu b/test/CodeGenCUDA/alias.cu
index 6efff6b..56e595e 100644
--- a/test/CodeGenCUDA/alias.cu
+++ b/test/CodeGenCUDA/alias.cu
@@ -1,8 +1,11 @@
// REQUIRES: x86-registered-target
// REQUIRES: nvptx-registered-target
+// REQUIRES: amdgpu-registered-target
// RUN: %clang_cc1 -fcuda-is-device -triple nvptx-nvidia-cuda -emit-llvm \
// RUN: -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fcuda-is-device -triple amdgcn -emit-llvm \
+// RUN: -o - %s | FileCheck %s
#include "Inputs/cuda.h"
diff --git a/test/CodeGenCUDA/kernel-amdgcn.cu b/test/CodeGenCUDA/kernel-amdgcn.cu
new file mode 100644
index 0000000..a7369f9
--- /dev/null
+++ b/test/CodeGenCUDA/kernel-amdgcn.cu
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -triple amdgcn -fcuda-is-device -emit-llvm %s -o - | FileCheck %s
+#include "Inputs/cuda.h"
+
+// CHECK: define amdgpu_kernel void @_ZN1A6kernelEv
+class A {
+public:
+ static __global__ void kernel(){}
+};
+
+// CHECK: define void @_Z10non_kernelv
+__device__ void non_kernel(){}
+
+// CHECK: define amdgpu_kernel void @_Z6kerneli
+__global__ void kernel(int x) {
+ non_kernel();
+}
+
+// CHECK: define amdgpu_kernel void @_Z15template_kernelI1AEvT_
+template<class T>
+__global__ void template_kernel(T x) {}
+
+void launch(void *f);
+
+int main() {
+ launch((void*)A::kernel);
+ launch((void*)kernel);
+ launch((void*)template_kernel<A>);
+ return 0;
+}
diff --git a/test/CodeGenCXX/PR19955.cpp b/test/CodeGenCXX/PR19955.cpp
index 601ccc6..5175b74 100644
--- a/test/CodeGenCXX/PR19955.cpp
+++ b/test/CodeGenCXX/PR19955.cpp
@@ -6,22 +6,22 @@
extern int *varp;
int *varp = &var;
-// CHECK-DAG: @"\01?varp@@3PAHA" = dso_local global i32* null
-// X64-DAG: @"\01?varp@@3PEAHEA" = dso_local global i32* null
+// CHECK-DAG: @"?varp@@3PAHA" = dso_local global i32* null
+// X64-DAG: @"?varp@@3PEAHEA" = dso_local global i32* null
extern void (*funp)();
void (*funp)() = &fun;
-// CHECK-DAG: @"\01?funp@@3P6AXXZA" = dso_local global void ()* null
-// X64-DAG: @"\01?funp@@3P6AXXZEA" = dso_local global void ()* null
+// CHECK-DAG: @"?funp@@3P6AXXZA" = dso_local global void ()* null
+// X64-DAG: @"?funp@@3P6AXXZEA" = dso_local global void ()* null
-// CHECK-LABEL: @"\01??__Evarp@@YAXXZ"
-// CHECK-DAG: store i32* @"\01?var@@3HA", i32** @"\01?varp@@3PAHA"
+// CHECK-LABEL: @"??__Evarp@@YAXXZ"
+// CHECK-DAG: store i32* @"?var@@3HA", i32** @"?varp@@3PAHA"
-// X64-LABEL: @"\01??__Evarp@@YAXXZ"
-// X64-DAG: store i32* @"\01?var@@3HA", i32** @"\01?varp@@3PEAHEA"
+// X64-LABEL: @"??__Evarp@@YAXXZ"
+// X64-DAG: store i32* @"?var@@3HA", i32** @"?varp@@3PEAHEA"
-// CHECK-LABEL: @"\01??__Efunp@@YAXXZ"()
-// CHECK-DAG: store void ()* @"\01?fun@@YAXXZ", void ()** @"\01?funp@@3P6AXXZA"
+// CHECK-LABEL: @"??__Efunp@@YAXXZ"()
+// CHECK-DAG: store void ()* @"?fun@@YAXXZ", void ()** @"?funp@@3P6AXXZA"
-// X64-LABEL: @"\01??__Efunp@@YAXXZ"()
-// X64-DAG: store void ()* @"\01?fun@@YAXXZ", void ()** @"\01?funp@@3P6AXXZEA"
+// X64-LABEL: @"??__Efunp@@YAXXZ"()
+// X64-DAG: store void ()* @"?fun@@YAXXZ", void ()** @"?funp@@3P6AXXZEA"
diff --git a/test/CodeGenCXX/PR26569.cpp b/test/CodeGenCXX/PR26569.cpp
index 859b6e2..379b50c 100644
--- a/test/CodeGenCXX/PR26569.cpp
+++ b/test/CodeGenCXX/PR26569.cpp
@@ -9,12 +9,12 @@
extern template class __declspec(dllimport) B<int>;
class __declspec(dllexport) C : B<int> {};
-// CHECK-DAG: @[[VTABLE_C:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4C@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] }
-// CHECK-DAG: @[[VTABLE_B:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$B@H@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"\01??_S?$B@H@@6B@")
-// CHECK-DAG: @[[VTABLE_A:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4A@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"\01??_SA@@6B@")
+// CHECK-DAG: @[[VTABLE_C:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4C@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"?m_fn1@A@@EAEXXZ" to i8*)] }
+// CHECK-DAG: @[[VTABLE_B:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4?$B@H@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"??_S?$B@H@@6B@")
+// CHECK-DAG: @[[VTABLE_A:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4A@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"??_SA@@6B@")
-// CHECK-DAG: @"\01??_7C@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_C]], i32 0, i32 0, i32 1)
-// CHECK-DAG: @"\01??_S?$B@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_B]], i32 0, i32 0, i32 1)
-// CHECK-DAG: @"\01??_SA@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_A]], i32 0, i32 0, i32 1)
+// CHECK-DAG: @"??_7C@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_C]], i32 0, i32 0, i32 1)
+// CHECK-DAG: @"??_S?$B@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_B]], i32 0, i32 0, i32 1)
+// CHECK-DAG: @"??_SA@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_A]], i32 0, i32 0, i32 1)
-// CHECK-DAG: @"\01??_8?$B@H@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4]
+// CHECK-DAG: @"??_8?$B@H@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4]
diff --git a/test/CodeGenCXX/PR28220.cpp b/test/CodeGenCXX/PR28220.cpp
index 6262c87..5863b6d 100644
--- a/test/CodeGenCXX/PR28220.cpp
+++ b/test/CodeGenCXX/PR28220.cpp
@@ -14,6 +14,6 @@
S<T> U<T>::u;
template S<int> U<int>::u;
-// CHECK-NOT: define internal void @"\01??__Eu@?$U@H@@2U?$S@H@@A@YAXXZ"(
+// CHECK-NOT: define internal void @"??__Eu@?$U@H@@2U?$S@H@@A@YAXXZ"(
S<int> &i = U<int>::u;
diff --git a/test/CodeGenCXX/alloc-size.cpp b/test/CodeGenCXX/alloc-size.cpp
index 275ffe6..e68e52c 100644
--- a/test/CodeGenCXX/alloc-size.cpp
+++ b/test/CodeGenCXX/alloc-size.cpp
@@ -71,6 +71,22 @@
}
} // namespace templated_alloc_size
+// Be sure that an ExprWithCleanups doesn't deter us.
+namespace alloc_size_with_cleanups {
+struct Foo {
+ ~Foo();
+};
+
+void *my_malloc(const Foo &, int N) __attribute__((alloc_size(2)));
+
+// CHECK-LABEL: define i32 @_ZN24alloc_size_with_cleanups6testItEv
+int testIt() {
+ int *const p = (int *)my_malloc(Foo{}, 3);
+ // CHECK: ret i32 3
+ return __builtin_object_size(p, 0);
+}
+} // namespace alloc_size_with_cleanups
+
class C {
public:
void *my_malloc(int N) __attribute__((alloc_size(2)));
@@ -88,15 +104,3 @@
// CHECK: ret i32 32
return __builtin_object_size(C().my_calloc(16, 2), 0);
}
-
-struct D {
- ~D();
- void *my_malloc(int N) __attribute__((alloc_size(2)));
-};
-
-// CHECK-LABEL: define i32 @_Z20callExprWithCleanupsv
-int callExprWithCleanups() {
- int *const p = (int *)D().my_malloc(3);
- // CHECK: ret i32 3
- return __builtin_object_size(p, 0);
-}
diff --git a/test/CodeGenCXX/amdgcn-func-arg.cpp b/test/CodeGenCXX/amdgcn-func-arg.cpp
new file mode 100644
index 0000000..9ac143a
--- /dev/null
+++ b/test/CodeGenCXX/amdgcn-func-arg.cpp
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 -O0 -triple amdgcn -emit-llvm %s -o - | FileCheck %s
+
+class A {
+public:
+ int x;
+ A():x(0) {}
+ ~A() {}
+};
+
+class B {
+int x[100];
+};
+
+A g_a;
+B g_b;
+
+void func_with_ref_arg(A &a);
+void func_with_ref_arg(B &b);
+
+// CHECK-LABEL: define void @_Z22func_with_indirect_arg1A(%class.A addrspace(5)* %a)
+// CHECK: %p = alloca %class.A*, align 8, addrspace(5)
+// CHECK: %[[r1:.+]] = addrspacecast %class.A* addrspace(5)* %p to %class.A**
+// CHECK: %[[r0:.+]] = addrspacecast %class.A addrspace(5)* %a to %class.A*
+// CHECK: store %class.A* %[[r0]], %class.A** %[[r1]], align 8
+void func_with_indirect_arg(A a) {
+ A *p = &a;
+}
+
+// CHECK-LABEL: define void @_Z22test_indirect_arg_autov()
+// CHECK: %a = alloca %class.A, align 4, addrspace(5)
+// CHECK: %[[r0:.+]] = addrspacecast %class.A addrspace(5)* %a to %class.A*
+// CHECK: %agg.tmp = alloca %class.A, align 4, addrspace(5)
+// CHECK: %[[r1:.+]] = addrspacecast %class.A addrspace(5)* %agg.tmp to %class.A*
+// CHECK: call void @_ZN1AC1Ev(%class.A* %[[r0]])
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
+// CHECK: %[[r4:.+]] = addrspacecast %class.A* %[[r1]] to %class.A addrspace(5)*
+// CHECK: call void @_Z22func_with_indirect_arg1A(%class.A addrspace(5)* %[[r4]])
+// CHECK: call void @_ZN1AD1Ev(%class.A* %[[r1]])
+// CHECK: call void @_Z17func_with_ref_argR1A(%class.A* dereferenceable(4) %[[r0]])
+// CHECK: call void @_ZN1AD1Ev(%class.A* %[[r0]])
+void test_indirect_arg_auto() {
+ A a;
+ func_with_indirect_arg(a);
+ func_with_ref_arg(a);
+}
+
+// CHECK: define void @_Z24test_indirect_arg_globalv()
+// CHECK: %agg.tmp = alloca %class.A, align 4, addrspace(5)
+// CHECK: %[[r0:.+]] = addrspacecast %class.A addrspace(5)* %agg.tmp to %class.A*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
+// CHECK: %[[r2:.+]] = addrspacecast %class.A* %[[r0]] to %class.A addrspace(5)*
+// CHECK: call void @_Z22func_with_indirect_arg1A(%class.A addrspace(5)* %[[r2]])
+// CHECK: call void @_ZN1AD1Ev(%class.A* %[[r0]])
+// CHECK: call void @_Z17func_with_ref_argR1A(%class.A* dereferenceable(4) addrspacecast (%class.A addrspace(1)* @g_a to %class.A*))
+void test_indirect_arg_global() {
+ func_with_indirect_arg(g_a);
+ func_with_ref_arg(g_a);
+}
+
+// CHECK-LABEL: define void @_Z19func_with_byval_arg1B(%class.B addrspace(5)* byval align 4 %b)
+// CHECK: %p = alloca %class.B*, align 8, addrspace(5)
+// CHECK: %[[r1:.+]] = addrspacecast %class.B* addrspace(5)* %p to %class.B**
+// CHECK: %[[r0:.+]] = addrspacecast %class.B addrspace(5)* %b to %class.B*
+// CHECK: store %class.B* %[[r0]], %class.B** %[[r1]], align 8
+void func_with_byval_arg(B b) {
+ B *p = &b;
+}
+
+// CHECK-LABEL: define void @_Z19test_byval_arg_autov()
+// CHECK: %b = alloca %class.B, align 4, addrspace(5)
+// CHECK: %[[r0:.+]] = addrspacecast %class.B addrspace(5)* %b to %class.B*
+// CHECK: %agg.tmp = alloca %class.B, align 4, addrspace(5)
+// CHECK: %[[r1:.+]] = addrspacecast %class.B addrspace(5)* %agg.tmp to %class.B*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
+// CHECK: %[[r4:.+]] = addrspacecast %class.B* %[[r1]] to %class.B addrspace(5)*
+// CHECK: call void @_Z19func_with_byval_arg1B(%class.B addrspace(5)* byval align 4 %[[r4]])
+// CHECK: call void @_Z17func_with_ref_argR1B(%class.B* dereferenceable(400) %[[r0]])
+void test_byval_arg_auto() {
+ B b;
+ func_with_byval_arg(b);
+ func_with_ref_arg(b);
+}
+
+// CHECK-LABEL: define void @_Z21test_byval_arg_globalv()
+// CHECK: %agg.tmp = alloca %class.B, align 4, addrspace(5)
+// CHECK: %[[r0:.+]] = addrspacecast %class.B addrspace(5)* %agg.tmp to %class.B*
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
+// CHECK: %[[r2:.+]] = addrspacecast %class.B* %[[r0]] to %class.B addrspace(5)*
+// CHECK: call void @_Z19func_with_byval_arg1B(%class.B addrspace(5)* byval align 4 %[[r2]])
+// CHECK: call void @_Z17func_with_ref_argR1B(%class.B* dereferenceable(400) addrspacecast (%class.B addrspace(1)* @g_b to %class.B*))
+void test_byval_arg_global() {
+ func_with_byval_arg(g_b);
+ func_with_ref_arg(g_b);
+}
diff --git a/test/CodeGenCXX/atomic-dllexport.cpp b/test/CodeGenCXX/atomic-dllexport.cpp
index 8ba7c3d..20c5005 100644
--- a/test/CodeGenCXX/atomic-dllexport.cpp
+++ b/test/CodeGenCXX/atomic-dllexport.cpp
@@ -3,7 +3,7 @@
struct __declspec(dllexport) SomeStruct {
// Copy assignment operator should be produced, and exported:
- // M32: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"\01??4SomeStruct@@QAEAAU0@ABU0@@Z"
- // M64: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"\01??4SomeStruct@@QEAAAEAU0@AEBU0@@Z"
+ // M32: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"??4SomeStruct@@QAEAAU0@ABU0@@Z"
+ // M64: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"??4SomeStruct@@QEAAAEAU0@AEBU0@@Z"
_Atomic(int) mData;
};
diff --git a/test/CodeGenCXX/builtin-operator-new-delete.cpp b/test/CodeGenCXX/builtin-operator-new-delete.cpp
new file mode 100644
index 0000000..712805a
--- /dev/null
+++ b/test/CodeGenCXX/builtin-operator-new-delete.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s \
+// RUN: -faligned-allocation -fsized-deallocation -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+typedef __SIZE_TYPE__ size_t;
+
+// Declare an 'operator new' template to tickle a bug in __builtin_operator_new.
+template<typename T> void *operator new(size_t, int (*)(T));
+
+// Ensure that this declaration doesn't cause operator new to lose its
+// 'noalias' attribute.
+void *operator new(size_t);
+
+namespace std {
+ struct nothrow_t {};
+ enum class align_val_t : size_t { __zero = 0,
+ __max = (size_t)-1 };
+}
+std::nothrow_t nothrow;
+
+// Declare the reserved placement operators.
+void *operator new(size_t, void*) throw();
+void operator delete(void*, void*) throw();
+void *operator new[](size_t, void*) throw();
+void operator delete[](void*, void*) throw();
+
+// Declare the replaceable global allocation operators.
+void *operator new(size_t, const std::nothrow_t &) throw();
+void *operator new[](size_t, const std::nothrow_t &) throw();
+void operator delete(void *, const std::nothrow_t &) throw();
+void operator delete[](void *, const std::nothrow_t &) throw();
+
+// Declare some other placement operators.
+void *operator new(size_t, void*, bool) throw();
+void *operator new[](size_t, void*, bool) throw();
+
+
+// CHECK-LABEL: define void @test_basic(
+extern "C" void test_basic() {
+ // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
+ // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
+ // CHECK: ret void
+ __builtin_operator_delete(__builtin_operator_new(4));
+}
+// CHECK: declare noalias i8* @_Znwm(i64) [[ATTR_NOBUILTIN:#[^ ]*]]
+// CHECK: declare void @_ZdlPv(i8*) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]]
+
+// CHECK-LABEL: define void @test_aligned_alloc(
+extern "C" void test_aligned_alloc() {
+ // CHECK: call i8* @_ZnwmSt11align_val_t(i64 4, i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
+ // CHECK: call void @_ZdlPvSt11align_val_t({{.*}}, i64 4) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
+ __builtin_operator_delete(__builtin_operator_new(4, std::align_val_t(4)), std::align_val_t(4));
+}
+// CHECK: declare noalias i8* @_ZnwmSt11align_val_t(i64, i64) [[ATTR_NOBUILTIN:#[^ ]*]]
+// CHECK: declare void @_ZdlPvSt11align_val_t(i8*, i64) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]]
+
+
+// CHECK-LABEL: define void @test_sized_delete(
+extern "C" void test_sized_delete() {
+ // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
+ // CHECK: call void @_ZdlPvm({{.*}}, i64 4) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
+ __builtin_operator_delete(__builtin_operator_new(4), 4);
+}
+// CHECK: declare void @_ZdlPvm(i8*, i64) [[ATTR_NOBUILTIN_UNWIND:#[^ ]*]]
+
+
+// CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin {{.*[}]}}
+// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}}
+
+// CHECK-DAG: attributes [[ATTR_BUILTIN_NEW]] = {{[{].*}} builtin {{.*[}]}}
+// CHECK-DAG: attributes [[ATTR_BUILTIN_DELETE]] = {{[{].*}} builtin {{.*[}]}}
diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp
index 786c6da..4513936 100644
--- a/test/CodeGenCXX/catch-undef-behavior.cpp
+++ b/test/CodeGenCXX/catch-undef-behavior.cpp
@@ -206,7 +206,7 @@
// CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null
// CHECK: br i1 %[[NONNULL]],
- // A null poiner access is guarded without -fsanitize=null.
+ // A null pointer access is guarded without -fsanitize=null.
// DOWNCAST-NULL: %[[NONNULL:.*]] = icmp ne {{.*}}, null
// DOWNCAST-NULL: br i1 %[[NONNULL]],
diff --git a/test/CodeGenCXX/cfi-cross-dso.cpp b/test/CodeGenCXX/cfi-cross-dso.cpp
index bfa0705..6d5e059 100644
--- a/test/CodeGenCXX/cfi-cross-dso.cpp
+++ b/test/CodeGenCXX/cfi-cross-dso.cpp
@@ -26,7 +26,7 @@
b.f();
}
-// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"\01??_R4B@?A@@6B@"{{.*}}@"\01?f@B@?A@@UEAAXXZ"
+// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"??_R4B@?A@@6B@"{{.*}}@"?f@B@?A@@UEAAXXZ"
// CHECK: %[[VT:.*]] = load void (%struct.A*)**, void (%struct.A*)***
// CHECK: %[[VT2:.*]] = bitcast {{.*}}%[[VT]] to i8*, !nosanitize
diff --git a/test/CodeGenCXX/cfi-icall.cpp b/test/CodeGenCXX/cfi-icall.cpp
index 5f5778f..e53aeef 100644
--- a/test/CodeGenCXX/cfi-icall.cpp
+++ b/test/CodeGenCXX/cfi-icall.cpp
@@ -21,7 +21,7 @@
}
// ITANIUM: define internal void @_ZN12_GLOBAL__N_11fENS_1SE({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]]
-// MS: define internal void @"\01?f@?A@@YAXUS@?A@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]]
+// MS: define internal void @"?f@?A@@YAXUS@?A@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]]
// CHECK: [[VOIDS1]] = distinct !{}
// CHECK: [[TS1]] = !{i64 0, [[VOIDS1]]}
diff --git a/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp b/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp
index 3276d8f..6142ca5 100644
--- a/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp
+++ b/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp
@@ -8,7 +8,7 @@
template <typename T>
struct bar : virtual public foo {
void f() {
- // CHECK: define{{.*}}@"\01?f@?$bar@Ubaz@@@@UEAAXXZ"
+ // CHECK: define{{.*}}@"?f@?$bar@Ubaz@@@@UEAAXXZ"
// Load "this", vbtable, vbase offset and vtable.
// CHECK: load
// CHECK: load
diff --git a/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp b/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp
index ab61062..d423255 100644
--- a/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp
+++ b/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp
@@ -16,7 +16,7 @@
};
void f(baz *z) {
- // CHECK: define{{.*}}@"\01?f@@YAXPEAUbaz@@@Z"
+ // CHECK: define{{.*}}@"?f@@YAXPEAUbaz@@@Z"
// Load z, vbtable, vbase offset and vtable.
// CHECK: load
// CHECK: load
diff --git a/test/CodeGenCXX/constructor-destructor-return-this.cpp b/test/CodeGenCXX/constructor-destructor-return-this.cpp
index ddb715d..f6450e2 100644
--- a/test/CodeGenCXX/constructor-destructor-return-this.cpp
+++ b/test/CodeGenCXX/constructor-destructor-return-this.cpp
@@ -45,8 +45,8 @@
// CHECKIOS5-LABEL: define %class.B* @_ZN1BD2Ev(%class.B* %this)
// CHECKIOS5-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* %this)
-// CHECKMS-LABEL: define dso_local x86_thiscallcc %class.B* @"\01??0B@@QAE@PAH@Z"(%class.B* returned %this, i32* %i)
-// CHECKMS-LABEL: define dso_local x86_thiscallcc void @"\01??1B@@UAE@XZ"(%class.B* %this)
+// CHECKMS-LABEL: define dso_local x86_thiscallcc %class.B* @"??0B@@QAE@PAH@Z"(%class.B* returned %this, i32* %i)
+// CHECKMS-LABEL: define dso_local x86_thiscallcc void @"??1B@@UAE@XZ"(%class.B* %this)
class C : public A, public B {
public:
@@ -83,8 +83,8 @@
// CHECKIOS5-LABEL: define void @_ZN1CD0Ev(%class.C* %this)
// CHECKIOS5-LABEL: define void @_ZThn8_N1CD0Ev(%class.C* %this)
-// CHECKMS-LABEL: define dso_local x86_thiscallcc %class.C* @"\01??0C@@QAE@PAHPAD@Z"(%class.C* returned %this, i32* %i, i8* %c)
-// CHECKMS-LABEL: define dso_local x86_thiscallcc void @"\01??1C@@UAE@XZ"(%class.C* %this)
+// CHECKMS-LABEL: define dso_local x86_thiscallcc %class.C* @"??0C@@QAE@PAHPAD@Z"(%class.C* returned %this, i32* %i, i8* %c)
+// CHECKMS-LABEL: define dso_local x86_thiscallcc void @"??1C@@UAE@XZ"(%class.C* %this)
class D : public virtual A {
public:
@@ -110,8 +110,8 @@
// CHECKIOS5-LABEL: define %class.D* @_ZN1DD2Ev(%class.D* %this, i8** %vtt)
// CHECKIOS5-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* %this)
-// CHECKMS-LABEL: define dso_local x86_thiscallcc %class.D* @"\01??0D@@QAE@XZ"(%class.D* returned %this, i32 %is_most_derived)
-// CHECKMS-LABEL: define dso_local x86_thiscallcc void @"\01??1D@@UAE@XZ"(%class.D* %this)
+// CHECKMS-LABEL: define dso_local x86_thiscallcc %class.D* @"??0D@@QAE@XZ"(%class.D* returned %this, i32 %is_most_derived)
+// CHECKMS-LABEL: define dso_local x86_thiscallcc void @"??1D@@UAE@XZ"(%class.D* %this)
class E {
public:
diff --git a/test/CodeGenCXX/cxx1z-aligned-allocation.cpp b/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
index 4c57997..2e2bfc5 100644
--- a/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
+++ b/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
@@ -29,10 +29,10 @@
// CHECK-LABEL: define {{.*}} @_Z2a0v()
// CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 32)
// CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 32)
-// CHECK-MS-LABEL: define {{.*}} @"\01?a0@@YAPEAXXZ"()
-// CHECK-MS: %[[ALLOC:.*]] = call i8* @"\01??2@YAPEAX_KW4align_val_t@std@@@Z"(i64 512, i64 32)
+// CHECK-MS-LABEL: define {{.*}} @"?a0@@YAPEAXXZ"()
+// CHECK-MS: %[[ALLOC:.*]] = call i8* @"??2@YAPEAX_KW4align_val_t@std@@@Z"(i64 512, i64 32)
// CHECK-MS: cleanuppad
-// CHECK-MS: call void @"\01??3@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32)
+// CHECK-MS: call void @"??3@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32)
void *a0() { return new A; }
// FIXME: Why don't we call the sized array deallocation overload in this case?
@@ -44,13 +44,13 @@
// CHECK-NOT: store
// CHECK: invoke void @_ZN1AC1Ev(
// CHECK: call void @_ZdaPvSt11align_val_t(i8* %[[ALLOC]], i64 32)
-// CHECK-MS-LABEL: define {{.*}} @"\01?a1@@YAPEAXJ@Z"(
-// CHECK-MS: %[[ALLOC:.*]] = call i8* @"\01??_U@YAPEAX_KW4align_val_t@std@@@Z"(i64 %{{.*}}, i64 32)
+// CHECK-MS-LABEL: define {{.*}} @"?a1@@YAPEAXJ@Z"(
+// CHECK-MS: %[[ALLOC:.*]] = call i8* @"??_U@YAPEAX_KW4align_val_t@std@@@Z"(i64 %{{.*}}, i64 32)
// No array cookie.
// CHECK-MS-NOT: store
-// CHECK-MS: invoke %struct.A* @"\01??0A@@QEAA@XZ"(
+// CHECK-MS: invoke %struct.A* @"??0A@@QEAA@XZ"(
// CHECK-MS: cleanuppad
-// CHECK-MS: call void @"\01??_V@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32)
+// CHECK-MS: call void @"??_V@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32)
void *a1(long n) { return new A[n]; }
// CHECK-LABEL: define {{.*}} @_Z2a2P1A(
diff --git a/test/CodeGenCXX/cxx1z-eval-order.cpp b/test/CodeGenCXX/cxx1z-eval-order.cpp
index 1106719..04c1b50 100644
--- a/test/CodeGenCXX/cxx1z-eval-order.cpp
+++ b/test/CodeGenCXX/cxx1z-eval-order.cpp
@@ -56,13 +56,13 @@
void postfix_before_args() {
// CHECK: call {{.*}}@{{.*}}get_f{{.*}}(
// CHECK-ITANIUM: call {{.*}}@_ZN1AC1Ev(
- // CHECK-WINDOWS: call {{.*}}@"\01??0A@@Q{{AE|EAA}}@XZ"(
+ // CHECK-WINDOWS: call {{.*}}@"??0A@@Q{{AE|EAA}}@XZ"(
// CHECK: call {{.*}}%{{.*}}(
get_f()(A{});
// CHECK: call {{.*}}@{{.*}}side_effect{{.*}}(
// CHECK-ITANIUM: call {{.*}}@_ZN1AC1Ev(
- // CHECK-WINDOWS: call {{.*}}@"\01??0A@@Q{{AE|EAA}}@XZ"(
+ // CHECK-WINDOWS: call {{.*}}@"??0A@@Q{{AE|EAA}}@XZ"(
// CHECK: call {{.*}}@{{.*}}callee{{.*}}(
(side_effect(), callee)(A{});
// CHECK: }
@@ -126,7 +126,7 @@
void alloc_before_init() {
struct Q { Q(A) {} };
// CHECK-ITANIUM: call {{.*}}@_Znw{{.*}}(
- // CHECK-WINDOWS: call {{.*}}@"\01??2@YAP{{EAX_K|AXI}}@Z"(
+ // CHECK-WINDOWS: call {{.*}}@"??2@YAP{{EAX_K|AXI}}@Z"(
// CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
delete new Q(make_a());
diff --git a/test/CodeGenCXX/cxx1z-inline-variables.cpp b/test/CodeGenCXX/cxx1z-inline-variables.cpp
index 50eab3b..938ebbb 100644
--- a/test/CodeGenCXX/cxx1z-inline-variables.cpp
+++ b/test/CodeGenCXX/cxx1z-inline-variables.cpp
@@ -111,3 +111,29 @@
// CHECK-NOT: __cxa_guard_acquire(i64* @_ZGV1b)
// CHECK: call i32 @_Z1fv
// CHECK-NOT: __cxa_guard_release(i64* @_ZGV1b)
+
+namespace PR35599 {
+struct Marker1 {};
+struct Marker2 {};
+
+template <typename>
+struct Foo {
+ struct Bar { Bar(); };
+ inline static Bar bar;
+};
+
+void run() {
+ // All we want here are ODR uses. Anything that requires that the type is
+ // complete is uninteresting.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-value"
+ Foo<Marker1>::bar;
+#pragma clang diagnostic pop
+ static_cast<void>(Foo<Marker2>::bar);
+}
+
+// CHECK-LABEL: define {{.*}}global_var_init{{.*}}comdat
+// CHECK: call void @_ZN7PR355993FooINS_7Marker1EE3BarC1Ev
+// CHECK-LABEL: define {{.*}}global_var_init{{.*}}comdat
+// CHECK: call void @_ZN7PR355993FooINS_7Marker2EE3BarC1Ev
+}
diff --git a/test/CodeGenCXX/cxx1z-lambda-star-this.cpp b/test/CodeGenCXX/cxx1z-lambda-star-this.cpp
index 379dbfd..114791c 100644
--- a/test/CodeGenCXX/cxx1z-lambda-star-this.cpp
+++ b/test/CodeGenCXX/cxx1z-lambda-star-this.cpp
@@ -10,7 +10,7 @@
int X = A{}.foo()();
} //end ns1
-//CHECK: @"\01?foo@A@@QAE?A?<auto>@@XZ"(%struct.A* %this, %class.anon* noalias sret %[[A_LAMBDA_RETVAL:.*]])
+//CHECK: @"?foo@A@@QAE?A?<auto>@@XZ"(%struct.A* %this, %class.anon* noalias sret %[[A_LAMBDA_RETVAL:.*]])
// get the first object with the closure type, which is of type 'struct.A'
//CHECK: %[[I0:.+]] = getelementptr inbounds %[[A_LAMBDA]], %[[A_LAMBDA]]* %[[A_LAMBDA_RETVAL]], i32 0, i32 0
//CHECK: %[[I1:.+]] = bitcast %struct.A* %[[I0]] to i8*
@@ -26,6 +26,6 @@
namespace ns2 {
int X = B{}.bar()();
}
-//CHECK: @"\01?bar@B@@QAE?A?<auto>@@XZ"(%struct.B* %this, %class.anon.0* noalias sret %agg.result)
+//CHECK: @"?bar@B@@QAE?A?<auto>@@XZ"(%struct.B* %this, %class.anon.0* noalias sret %agg.result)
//CHECK: %[[I20:.+]] = getelementptr inbounds %class.anon.0, %class.anon.0* %agg.result, i32 0, i32 0
//CHECK: store %struct.B* %this1, %struct.B** %[[I20]], align 4
diff --git a/test/CodeGenCXX/cxx2a-destroying-delete.cpp b/test/CodeGenCXX/cxx2a-destroying-delete.cpp
index 9c6db1b..60c5970 100644
--- a/test/CodeGenCXX/cxx2a-destroying-delete.cpp
+++ b/test/CodeGenCXX/cxx2a-destroying-delete.cpp
@@ -21,7 +21,7 @@
// Ensure that we call the destroying delete and not the destructor.
// CHECK-NOT: call
// CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]])
-// CHECK-MSABI: call void @"\01??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8
+// CHECK-MSABI: call void @"??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8
// CHECK-NOT: call
// CHECK: }
@@ -65,7 +65,7 @@
//
// CHECK-NOT: call
// CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]])
-// CHECK-MSABI: call void @"\01??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8
+// CHECK-MSABI: call void @"??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8
// CHECK-NOT: call
// CHECK: }
@@ -100,7 +100,7 @@
// CHECK-LABEL: define {{.*}}delete_G
// CHECK-NOT: call
// CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t(%{{.*}}* %[[a]], i64 32, i64 16)
-// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"(%{{.*}}* %[[a]], i8 {{[^,]*}}, i64 32, i64 16)
+// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"(%{{.*}}* %[[a]], i8 {{[^,]*}}, i64 32, i64 16)
// CHECK-NOT: call
// CHECK: }
@@ -116,7 +116,7 @@
// CHECK-ITANIUM-NOT: call
// CHECK-ITANIUM: }
-// CHECK-MSABI: define {{.*}} @"\01??_GH@@UEAAPEAXI@Z"(
+// CHECK-MSABI: define {{.*}} @"??_GH@@UEAAPEAXI@Z"(
// CHECK-MSABI-NOT: call{{ }}
// CHECK-MSABI: load i32
// CHECK-MSABI: icmp eq i32 {{.*}}, 0
@@ -125,10 +125,10 @@
// CHECK-MSABI-NOT: call{{ }}
// CHECK-MSABI: getelementptr {{.*}}, i64 24
// CHECK-MSABI-NOT: call{{ }}
-// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 48, i64 16)
+// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 48, i64 16)
// CHECK-MSABI: br label %[[RETURN:.*]]
//
-// CHECK-MSABI: call void @"\01??_DH@@QEAAXXZ"(
+// CHECK-MSABI: call void @"??1H@@UEAA@XZ"(
// CHECK-MSABI: br label %[[RETURN]]
//
// CHECK-MSABI: }
@@ -143,7 +143,7 @@
// CHECK-ITANIUM-NOT: call
// CHECK-ITANIUM: }
-// CHECK-MSABI: define {{.*}} @"\01??_GI@@UEAAPEAXI@Z"(
+// CHECK-MSABI: define {{.*}} @"??_GI@@UEAAPEAXI@Z"(
// CHECK-MSABI-NOT: call{{ }}
// CHECK-MSABI: load i32
// CHECK-MSABI: icmp eq i32 {{.*}}, 0
@@ -152,10 +152,10 @@
// CHECK-MSABI-NOT: call{{ }}
// CHECK-MSABI: getelementptr {{.*}}, i64 24
// CHECK-MSABI-NOT: call{{ }}
-// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 96, i64 32)
+// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 96, i64 32)
// CHECK-MSABI: br label %[[RETURN:.*]]
//
-// CHECK-MSABI: call void @"\01??_DI@@QEAAXXZ"(
+// CHECK-MSABI: call void @"??1I@@UEAA@XZ"(
// CHECK-MSABI: br label %[[RETURN]]
//
// CHECK-MSABI: }
diff --git a/test/CodeGenCXX/debug-info-composite-cc.cpp b/test/CodeGenCXX/debug-info-composite-cc.cpp
index 2f09116..d4d4046 100644
--- a/test/CodeGenCXX/debug-info-composite-cc.cpp
+++ b/test/CodeGenCXX/debug-info-composite-cc.cpp
@@ -38,3 +38,13 @@
Complex(Complex &Copy) : i(Copy.i) {};
int i;
} complex;
+
+// This type is manually marked as trivial_abi.
+// CHECK-DAG: !DICompositeType({{.*}}, name: "Marked",{{.*}}flags: DIFlagTypePassByValue
+struct __attribute__((trivial_abi)) Marked {
+ int *p;
+ Marked();
+ ~Marked();
+ Marked(const Marked &) noexcept;
+ Marked &operator=(const Marked &);
+} marked;
diff --git a/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp b/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp
index f876267..d6fdee6 100644
--- a/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp
+++ b/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp
@@ -4,11 +4,11 @@
struct __declspec(dllexport) T { virtual ~T(); };
struct __declspec(dllexport) U : S, T { virtual ~U(); };
-// CHECK-LABEL: define {{.*}} @"\01??_GS@@UAEPAXI@Z"
-// CHECK: call x86_thiscallcc void @"\01??_DS@@QAEXXZ"(%struct.S* %this1){{.*}}!dbg !{{[0-9]+}}
+// CHECK-LABEL: define {{.*}} @"??_GS@@UAEPAXI@Z"
+// CHECK: call x86_thiscallcc void @"??1S@@UAE@XZ"(%struct.S* %this1){{.*}}!dbg !{{[0-9]+}}
-// CHECK-LABEL: define {{.*}} @"\01??_GT@@UAEPAXI@Z"
-// CHECK: call x86_thiscallcc void @"\01??_DT@@QAEXXZ"(%struct.T* %this1){{.*}}!dbg !{{[0-9]+}}
+// CHECK-LABEL: define {{.*}} @"??_GT@@UAEPAXI@Z"
+// CHECK: call x86_thiscallcc void @"??1T@@UAE@XZ"(%struct.T* %this1){{.*}}!dbg !{{[0-9]+}}
-// CHECK-LABEL: define {{.*}} @"\01??_GU@@UAEPAXI@Z"
-// CHECK: call x86_thiscallcc void @"\01??_DU@@QAEXXZ"(%struct.U* %this1){{.*}}!dbg !{{[0-9]+}}
+// CHECK-LABEL: define {{.*}} @"??_GU@@UAEPAXI@Z"
+// CHECK: call x86_thiscallcc void @"??1U@@UAE@XZ"(%struct.U* %this1){{.*}}!dbg !{{[0-9]+}}
diff --git a/test/CodeGenCXX/debug-info-thunk-msabi.cpp b/test/CodeGenCXX/debug-info-thunk-msabi.cpp
index 5c705ac0..565992a 100644
--- a/test/CodeGenCXX/debug-info-thunk-msabi.cpp
+++ b/test/CodeGenCXX/debug-info-thunk-msabi.cpp
@@ -3,10 +3,10 @@
class __declspec(dllexport) A {
A(int * = new int) {}
};
-// CHECK: define {{.*}}void @"\01??_FA@@AAEXXZ"
+// CHECK: define {{.*}}void @"??_FA@@AAEXXZ"
// CHECK-SAME: !dbg ![[SP:[0-9]+]]
// CHECK-NOT: {{ret }}
-// CHECK: call x86_thiscallcc %class.A* @"\01??0A@@AAE@PAH@Z"
+// CHECK: call x86_thiscallcc %class.A* @"??0A@@AAE@PAH@Z"
// CHECK-SAME: !dbg ![[DBG:[0-9]+]]
// CHECK: ret void, !dbg
//
diff --git a/test/CodeGenCXX/debug-info-windows-dtor.cpp b/test/CodeGenCXX/debug-info-windows-dtor.cpp
index 8eb744a..0b3d7e1 100644
--- a/test/CodeGenCXX/debug-info-windows-dtor.cpp
+++ b/test/CodeGenCXX/debug-info-windows-dtor.cpp
@@ -14,8 +14,8 @@
template struct AB<int>;
-// CHECK: define {{.*}}@"\01??_E?$AB@H@@W3AEPAXI@Z"({{.*}} !dbg [[THUNK_VEC_DEL_DTOR:![0-9]*]]
-// CHECK: call {{.*}}@"\01??_G?$AB@H@@UAEPAXI@Z"({{.*}}) #{{[0-9]*}}, !dbg [[THUNK_LOC:![0-9]*]]
+// CHECK: define {{.*}}@"??_E?$AB@H@@W3AEPAXI@Z"({{.*}} !dbg [[THUNK_VEC_DEL_DTOR:![0-9]*]]
+// CHECK: call {{.*}}@"??_G?$AB@H@@UAEPAXI@Z"({{.*}}) #{{[0-9]*}}, !dbg [[THUNK_LOC:![0-9]*]]
// CHECK: define
// CHECK: [[THUNK_VEC_DEL_DTOR]] = distinct !DISubprogram
diff --git a/test/CodeGenCXX/delayed-template-parsing.cpp b/test/CodeGenCXX/delayed-template-parsing.cpp
index c5f4486..c0e9425 100644
--- a/test/CodeGenCXX/delayed-template-parsing.cpp
+++ b/test/CodeGenCXX/delayed-template-parsing.cpp
@@ -11,8 +11,8 @@
void call() {
Type T;
-// CHECK: call {{.*}} @"\01??$Foo@$0A@@Type@ClassScopeSpecialization@@QAEXXZ"
-// X64: call {{.*}} @"\01??$Foo@$0A@@Type@ClassScopeSpecialization@@QEAAXXZ"
+// CHECK: call {{.*}} @"??$Foo@$0A@@Type@ClassScopeSpecialization@@QAEXXZ"
+// X64: call {{.*}} @"??$Foo@$0A@@Type@ClassScopeSpecialization@@QEAAXXZ"
T.Foo<0>();
}
}
diff --git a/test/CodeGenCXX/devirtualize-ms-dtor.cpp b/test/CodeGenCXX/devirtualize-ms-dtor.cpp
new file mode 100644
index 0000000..d999b0c
--- /dev/null
+++ b/test/CodeGenCXX/devirtualize-ms-dtor.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s
+
+// If we de-virtualize ~Foo, we still need to call ??1Foo, not ??_DFoo.
+
+struct Base {
+ virtual ~Base();
+};
+struct Foo final : Base {
+};
+void f(Foo *p) {
+ p->~Foo();
+}
+
+// CHECK-LABEL: define{{.*}} void @"?f@@YAXPEAUFoo@@@Z"(%struct.Foo* %p)
+// CHECK: call void @"??1Foo@@UEAA@XZ"
+// CHECK: ret void
diff --git a/test/CodeGenCXX/dllexport-ctor-closure.cpp b/test/CodeGenCXX/dllexport-ctor-closure.cpp
index 3a48a47..72d674d 100644
--- a/test/CodeGenCXX/dllexport-ctor-closure.cpp
+++ b/test/CodeGenCXX/dllexport-ctor-closure.cpp
@@ -5,11 +5,11 @@
struct CtorWithClosure {
__declspec(dllexport) CtorWithClosure(...) {}
-// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FCtorWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FCtorWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
// CHECK: %[[this_addr:.*]] = alloca %struct.CtorWithClosure*, align 4
// CHECK: store %struct.CtorWithClosure* %this, %struct.CtorWithClosure** %[[this_addr]], align 4
// CHECK: %[[this:.*]] = load %struct.CtorWithClosure*, %struct.CtorWithClosure** %[[this_addr]]
-// CHECK: call %struct.CtorWithClosure* (%struct.CtorWithClosure*, ...) @"\01??0CtorWithClosure@@QAA@ZZ"(%struct.CtorWithClosure* %[[this]])
+// CHECK: call %struct.CtorWithClosure* (%struct.CtorWithClosure*, ...) @"??0CtorWithClosure@@QAA@ZZ"(%struct.CtorWithClosure* %[[this]])
// CHECK: ret void
};
@@ -17,7 +17,7 @@
__declspec(dllexport) CtorWithClosureOutOfLine(...);
};
CtorWithClosureOutOfLine::CtorWithClosureOutOfLine(...) {}
-// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FCtorWithClosureOutOfLine@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FCtorWithClosureOutOfLine@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
#define DELETE_IMPLICIT_MEMBERS(ClassName) \
ClassName(ClassName &&) = delete; \
@@ -28,11 +28,11 @@
struct __declspec(dllexport) ClassWithClosure {
DELETE_IMPLICIT_MEMBERS(ClassWithClosure);
ClassWithClosure(...) {}
-// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FClassWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FClassWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
// CHECK: %[[this_addr:.*]] = alloca %struct.ClassWithClosure*, align 4
// CHECK: store %struct.ClassWithClosure* %this, %struct.ClassWithClosure** %[[this_addr]], align 4
// CHECK: %[[this:.*]] = load %struct.ClassWithClosure*, %struct.ClassWithClosure** %[[this_addr]]
-// CHECK: call %struct.ClassWithClosure* (%struct.ClassWithClosure*, ...) @"\01??0ClassWithClosure@@QAA@ZZ"(%struct.ClassWithClosure* %[[this]])
+// CHECK: call %struct.ClassWithClosure* (%struct.ClassWithClosure*, ...) @"??0ClassWithClosure@@QAA@ZZ"(%struct.ClassWithClosure* %[[this]])
// CHECK: ret void
};
@@ -44,11 +44,11 @@
extern template struct TemplateWithClosure<int>;
template struct __declspec(dllexport) TemplateWithClosure<int>;
-// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_F?$TemplateWithClosure@D@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
-// CHECK: call {{.*}} @"\01??0?$TemplateWithClosure@D@@QAE@H@Z"({{.*}}, i32 1)
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_F?$TemplateWithClosure@D@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK: call {{.*}} @"??0?$TemplateWithClosure@D@@QAE@H@Z"({{.*}}, i32 1)
-// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_F?$TemplateWithClosure@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
-// CHECK: call {{.*}} @"\01??0?$TemplateWithClosure@H@@QAE@H@Z"({{.*}}, i32 4)
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_F?$TemplateWithClosure@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK: call {{.*}} @"??0?$TemplateWithClosure@H@@QAE@H@Z"({{.*}}, i32 4)
struct __declspec(dllexport) NestedOuter {
DELETE_IMPLICIT_MEMBERS(NestedOuter);
@@ -59,8 +59,8 @@
};
};
-// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FNestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
-// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FNestedInner@NestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FNestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FNestedInner@NestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
struct HasDtor {
~HasDtor();
@@ -76,7 +76,7 @@
};
CtorClosureOutOfLine::CtorClosureOutOfLine(const HasImplicitDtor2 &v) {}
-// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FCtorClosureInline@@QAEXXZ"
-// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"\01??1HasImplicitDtor1@@QAE@XZ"
-// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FCtorClosureOutOfLine@@QAEXXZ"
-// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"\01??1HasImplicitDtor2@@QAE@XZ"
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FCtorClosureInline@@QAEXXZ"
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"??1HasImplicitDtor1@@QAE@XZ"
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FCtorClosureOutOfLine@@QAEXXZ"
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"??1HasImplicitDtor2@@QAE@XZ"
diff --git a/test/CodeGenCXX/dllexport-dtor-thunks.cpp b/test/CodeGenCXX/dllexport-dtor-thunks.cpp
index 45cce8b..bda126e 100644
--- a/test/CodeGenCXX/dllexport-dtor-thunks.cpp
+++ b/test/CodeGenCXX/dllexport-dtor-thunks.cpp
@@ -5,6 +5,6 @@
struct __declspec(dllexport) C : A, B { virtual ~C(); };
C::~C() {}
+// CHECK: define dso_local dllexport void @"??1C@@UEAA@XZ"
// This thunk should *not* be dllexport.
-// CHECK: define linkonce_odr dso_local i8* @"\01??_EC@@W7EAAPEAXI@Z"
-// CHECK: define dso_local dllexport void @"\01??1C@@UEAA@XZ"
+// CHECK: define linkonce_odr dso_local i8* @"??_EC@@W7EAAPEAXI@Z"
diff --git a/test/CodeGenCXX/dllexport-members.cpp b/test/CodeGenCXX/dllexport-members.cpp
index 569ef25..b027538 100644
--- a/test/CodeGenCXX/dllexport-members.cpp
+++ b/test/CodeGenCXX/dllexport-members.cpp
@@ -26,14 +26,14 @@
struct ExportMembers {
struct Nested;
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?normalDef@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define dso_local dllexport void @"\01?normalDef@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?normalInclass@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01?normalInclass@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?normalInlineDef@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01?normalInlineDef@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?normalInlineDecl@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01?normalInlineDecl@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?normalDef@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dso_local dllexport void @"?normalDef@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?normalInclass@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?normalInclass@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?normalInlineDef@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?normalInlineDef@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?normalInlineDecl@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?normalInlineDecl@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers9normalDefEv(%struct.ExportMembers* %this)
// G64-DAG: define dso_local dllexport void @_ZN13ExportMembers9normalDefEv(%struct.ExportMembers* %this)
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers13normalInclassEv(%struct.ExportMembers* %this)
@@ -42,21 +42,21 @@
// G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers15normalInlineDefEv(%struct.ExportMembers* %this)
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers16normalInlineDeclEv(%struct.ExportMembers* %this)
// G64-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers16normalInlineDeclEv(%struct.ExportMembers* %this)
- // M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"\01?referencedNonExportedInClass@ExportMembers@@QAEXXZ"
+ // M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?referencedNonExportedInClass@ExportMembers@@QAEXXZ"
__declspec(dllexport) void normalDef();
__declspec(dllexport) void normalInclass() { referencedNonExportedInClass(); }
__declspec(dllexport) void normalInlineDef();
__declspec(dllexport) inline void normalInlineDecl();
void referencedNonExportedInClass() {}
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?virtualDef@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define dso_local dllexport void @"\01?virtualDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?virtualInclass@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01?virtualInclass@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?virtualInlineDef@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01?virtualInlineDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?virtualInlineDecl@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01?virtualInlineDecl@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?virtualDef@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dso_local dllexport void @"?virtualDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?virtualInclass@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?virtualInclass@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?virtualInlineDef@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?virtualInlineDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?virtualInlineDecl@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?virtualInlineDecl@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers10virtualDefEv(%struct.ExportMembers* %this)
// G64-DAG: define dso_local dllexport void @_ZN13ExportMembers10virtualDefEv(%struct.ExportMembers* %this)
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers14virtualInclassEv(%struct.ExportMembers* %this)
@@ -70,10 +70,10 @@
__declspec(dllexport) virtual void virtualInlineDef();
__declspec(dllexport) virtual inline void virtualInlineDecl();
- // MSC-DAG: define dso_local dllexport void @"\01?staticDef@ExportMembers@@SAXXZ"()
- // MSC-DAG: define weak_odr dso_local dllexport void @"\01?staticInclass@ExportMembers@@SAXXZ"()
- // MSC-DAG: define weak_odr dso_local dllexport void @"\01?staticInlineDef@ExportMembers@@SAXXZ"()
- // MSC-DAG: define weak_odr dso_local dllexport void @"\01?staticInlineDecl@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define dso_local dllexport void @"?staticDef@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"?staticInclass@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"?staticInlineDef@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"?staticInlineDecl@ExportMembers@@SAXXZ"()
// GNU-DAG: define dso_local dllexport void @_ZN13ExportMembers9staticDefEv()
// GNU-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers13staticInclassEv()
// GNU-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers15staticInlineDefEv()
@@ -83,39 +83,39 @@
__declspec(dllexport) static void staticInlineDef();
__declspec(dllexport) static inline void staticInlineDecl();
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?protectedDef@ExportMembers@@IAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define dso_local dllexport void @"\01?protectedDef@ExportMembers@@IEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?protectedDef@ExportMembers@@IAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dso_local dllexport void @"?protectedDef@ExportMembers@@IEAAXXZ"(%struct.ExportMembers* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers12protectedDefEv(%struct.ExportMembers* %this)
// G64-DAG: define dso_local dllexport void @_ZN13ExportMembers12protectedDefEv(%struct.ExportMembers* %this)
- // MSC-DAG: define dso_local dllexport void @"\01?protectedStaticDef@ExportMembers@@KAXXZ"()
+ // MSC-DAG: define dso_local dllexport void @"?protectedStaticDef@ExportMembers@@KAXXZ"()
// GNU-DAG: define dso_local dllexport void @_ZN13ExportMembers18protectedStaticDefEv()
protected:
__declspec(dllexport) void protectedDef();
__declspec(dllexport) static void protectedStaticDef();
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?privateDef@ExportMembers@@AAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define dso_local dllexport void @"\01?privateDef@ExportMembers@@AEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?privateDef@ExportMembers@@AAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dso_local dllexport void @"?privateDef@ExportMembers@@AEAAXXZ"(%struct.ExportMembers* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers10privateDefEv(%struct.ExportMembers* %this)
// G64-DAG: define dso_local dllexport void @_ZN13ExportMembers10privateDefEv(%struct.ExportMembers* %this)
- // MSC-DAG: define dso_local dllexport void @"\01?privateStaticDef@ExportMembers@@CAXXZ"()
+ // MSC-DAG: define dso_local dllexport void @"?privateStaticDef@ExportMembers@@CAXXZ"()
// GNU-DAG: define dso_local dllexport void @_ZN13ExportMembers16privateStaticDefEv()
private:
__declspec(dllexport) void privateDef();
__declspec(dllexport) static void privateStaticDef();
- // M32-DAG: define dso_local x86_thiscallcc void @"\01?ignored@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
- // M64-DAG: define dso_local void @"\01?ignored@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define dso_local x86_thiscallcc void @"?ignored@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dso_local void @"?ignored@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
// G32-DAG: define dso_local x86_thiscallcc void @_ZN13ExportMembers7ignoredEv(%struct.ExportMembers* %this)
// G64-DAG: define dso_local void @_ZN13ExportMembers7ignoredEv(%struct.ExportMembers* %this)
public:
void ignored();
- // MSC-DAG: @"\01?StaticField@ExportMembers@@2HA" = dso_local dllexport global i32 1, align 4
- // MSC-DAG: @"\01?StaticConstField@ExportMembers@@2HB" = dso_local dllexport constant i32 1, align 4
- // MSC-DAG: @"\01?StaticConstFieldEqualInit@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
- // MSC-DAG: @"\01?StaticConstFieldBraceInit@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
- // MSC-DAG: @"\01?StaticConstFieldRefNotDef@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
- // MSC-DAG: @"\01?ConstexprField@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?StaticField@ExportMembers@@2HA" = dso_local dllexport global i32 1, align 4
+ // MSC-DAG: @"?StaticConstField@ExportMembers@@2HB" = dso_local dllexport constant i32 1, align 4
+ // MSC-DAG: @"?StaticConstFieldEqualInit@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?StaticConstFieldBraceInit@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?StaticConstFieldRefNotDef@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?ConstexprField@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
// GNU-DAG: @_ZN13ExportMembers11StaticFieldE = dso_local dllexport global i32 1, align 4
// GNU-DAG: @_ZN13ExportMembers16StaticConstFieldE = dso_local dllexport constant i32 1, align 4
// GNU-DAG: @_ZN13ExportMembers25StaticConstFieldEqualInitE = dso_local dllexport constant i32 1, align 4
@@ -154,14 +154,14 @@
// Export individual members of a nested class.
struct ExportMembers::Nested {
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?normalDef@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define dso_local dllexport void @"\01?normalDef@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?normalInclass@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01?normalInclass@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?normalInlineDef@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01?normalInlineDef@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01?normalInlineDecl@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?normalDef@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dso_local dllexport void @"?normalDef@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?normalInclass@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?normalInclass@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?normalInlineDef@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?normalInlineDef@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?normalInlineDecl@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?normalInlineDecl@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested9normalDefEv(%"struct.ExportMembers::Nested"* %this)
// G64-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested9normalDefEv(%"struct.ExportMembers::Nested"* %this)
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested13normalInclassEv(%"struct.ExportMembers::Nested"* %this)
@@ -175,14 +175,14 @@
__declspec(dllexport) void normalInlineDef();
__declspec(dllexport) inline void normalInlineDecl();
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?virtualDef@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define dso_local dllexport void @"\01?virtualDef@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?virtualInclass@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01?virtualInclass@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01?virtualInlineDef@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01?virtualInlineDecl@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?virtualDef@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dso_local dllexport void @"?virtualDef@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?virtualInclass@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?virtualInclass@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?virtualInlineDef@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?virtualInlineDef@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?virtualInlineDecl@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"?virtualInlineDecl@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested10virtualDefEv(%"struct.ExportMembers::Nested"* %this)
// G64-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested10virtualDefEv(%"struct.ExportMembers::Nested"* %this)
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested14virtualInclassEv(%"struct.ExportMembers::Nested"* %this)
@@ -196,10 +196,10 @@
__declspec(dllexport) virtual void virtualInlineDef();
__declspec(dllexport) virtual inline void virtualInlineDecl();
- // MSC-DAG: define dso_local dllexport void @"\01?staticDef@Nested@ExportMembers@@SAXXZ"()
- // MSC-DAG: define weak_odr dso_local dllexport void @"\01?staticInclass@Nested@ExportMembers@@SAXXZ"()
- // MSC-DAG: define weak_odr dso_local dllexport void @"\01?staticInlineDef@Nested@ExportMembers@@SAXXZ"()
- // MSC-DAG: define weak_odr dso_local dllexport void @"\01?staticInlineDecl@Nested@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define dso_local dllexport void @"?staticDef@Nested@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"?staticInclass@Nested@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"?staticInlineDef@Nested@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"?staticInlineDecl@Nested@ExportMembers@@SAXXZ"()
// GNU-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested9staticDefEv()
// GNU-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers6Nested13staticInclassEv()
// GNU-DAG: define weak_odr dso_local dllexport void @_ZN13ExportMembers6Nested15staticInlineDefEv()
@@ -209,39 +209,39 @@
__declspec(dllexport) static void staticInlineDef();
__declspec(dllexport) static inline void staticInlineDecl();
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?protectedDef@Nested@ExportMembers@@IAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define dso_local dllexport void @"\01?protectedDef@Nested@ExportMembers@@IEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?protectedDef@Nested@ExportMembers@@IAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dso_local dllexport void @"?protectedDef@Nested@ExportMembers@@IEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested12protectedDefEv(%"struct.ExportMembers::Nested"* %this)
// G64-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested12protectedDefEv(%"struct.ExportMembers::Nested"* %this)
- // MSC-DAG: define dso_local dllexport void @"\01?protectedStaticDef@Nested@ExportMembers@@KAXXZ"()
+ // MSC-DAG: define dso_local dllexport void @"?protectedStaticDef@Nested@ExportMembers@@KAXXZ"()
// GNU-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested18protectedStaticDefEv()
protected:
__declspec(dllexport) void protectedDef();
__declspec(dllexport) static void protectedStaticDef();
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?privateDef@Nested@ExportMembers@@AAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define dso_local dllexport void @"\01?privateDef@Nested@ExportMembers@@AEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?privateDef@Nested@ExportMembers@@AAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dso_local dllexport void @"?privateDef@Nested@ExportMembers@@AEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested10privateDefEv(%"struct.ExportMembers::Nested"* %this)
// G64-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested10privateDefEv(%"struct.ExportMembers::Nested"* %this)
- // MSC-DAG: define dso_local dllexport void @"\01?privateStaticDef@Nested@ExportMembers@@CAXXZ"()
+ // MSC-DAG: define dso_local dllexport void @"?privateStaticDef@Nested@ExportMembers@@CAXXZ"()
// GNU-DAG: define dso_local dllexport void @_ZN13ExportMembers6Nested16privateStaticDefEv()
private:
__declspec(dllexport) void privateDef();
__declspec(dllexport) static void privateStaticDef();
- // M32-DAG: define dso_local x86_thiscallcc void @"\01?ignored@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
- // M64-DAG: define dso_local void @"\01?ignored@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define dso_local x86_thiscallcc void @"?ignored@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dso_local void @"?ignored@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
// G32-DAG: define dso_local x86_thiscallcc void @_ZN13ExportMembers6Nested7ignoredEv(%"struct.ExportMembers::Nested"* %this)
// G64-DAG: define dso_local void @_ZN13ExportMembers6Nested7ignoredEv(%"struct.ExportMembers::Nested"* %this)
public:
void ignored();
- // MSC-DAG: @"\01?StaticField@Nested@ExportMembers@@2HA" = dso_local dllexport global i32 1, align 4
- // MSC-DAG: @"\01?StaticConstField@Nested@ExportMembers@@2HB" = dso_local dllexport constant i32 1, align 4
- // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
- // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
- // MSC-DAG: @"\01?StaticConstFieldRefNotDef@Nested@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
- // MSC-DAG: @"\01?ConstexprField@Nested@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?StaticField@Nested@ExportMembers@@2HA" = dso_local dllexport global i32 1, align 4
+ // MSC-DAG: @"?StaticConstField@Nested@ExportMembers@@2HB" = dso_local dllexport constant i32 1, align 4
+ // MSC-DAG: @"?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?StaticConstFieldRefNotDef@Nested@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+ // MSC-DAG: @"?ConstexprField@Nested@ExportMembers@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
// GNU-DAG: @_ZN13ExportMembers6Nested11StaticFieldE = dso_local dllexport global i32 1, align 4
// GNU-DAG: @_ZN13ExportMembers6Nested16StaticConstFieldE = dso_local dllexport constant i32 1, align 4
// GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldEqualInitE = dso_local dllexport constant i32 1, align 4
@@ -280,46 +280,46 @@
// Export special member functions.
struct ExportSpecials {
- // M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportSpecials* @"\01??0ExportSpecials@@QAE@XZ"(%struct.ExportSpecials* returned %this)
- // M64-DAG: define dso_local dllexport %struct.ExportSpecials* @"\01??0ExportSpecials@@QEAA@XZ"(%struct.ExportSpecials* returned %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportSpecials* @"??0ExportSpecials@@QAE@XZ"(%struct.ExportSpecials* returned %this)
+ // M64-DAG: define dso_local dllexport %struct.ExportSpecials* @"??0ExportSpecials@@QEAA@XZ"(%struct.ExportSpecials* returned %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1Ev(%struct.ExportSpecials* %this)
// G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsC1Ev(%struct.ExportSpecials* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2Ev(%struct.ExportSpecials* %this)
// G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsC2Ev(%struct.ExportSpecials* %this)
__declspec(dllexport) ExportSpecials();
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01??1ExportSpecials@@QAE@XZ"(%struct.ExportSpecials* %this)
- // M64-DAG: define dso_local dllexport void @"\01??1ExportSpecials@@QEAA@XZ"(%struct.ExportSpecials* %this)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"??1ExportSpecials@@QAE@XZ"(%struct.ExportSpecials* %this)
+ // M64-DAG: define dso_local dllexport void @"??1ExportSpecials@@QEAA@XZ"(%struct.ExportSpecials* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsD1Ev(%struct.ExportSpecials* %this)
// G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsD1Ev(%struct.ExportSpecials* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsD2Ev(%struct.ExportSpecials* %this)
// G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsD2Ev(%struct.ExportSpecials* %this)
__declspec(dllexport) ~ExportSpecials();
- // M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportSpecials* @"\01??0ExportSpecials@@QAE@ABU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: define dso_local dllexport %struct.ExportSpecials* @"\01??0ExportSpecials@@QEAA@AEBU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportSpecials* @"??0ExportSpecials@@QAE@ABU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define dso_local dllexport %struct.ExportSpecials* @"??0ExportSpecials@@QEAA@AEBU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsC1ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsC2ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportSpecials(const ExportSpecials&);
- // M32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QAEAAU0@ABU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"??4ExportSpecials@@QAEAAU0@ABU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"??4ExportSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportSpecials& operator=(const ExportSpecials&);
- // M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportSpecials* @"\01??0ExportSpecials@@QAE@$$QAU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: define dso_local dllexport %struct.ExportSpecials* @"\01??0ExportSpecials@@QEAA@$$QEAU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportSpecials* @"??0ExportSpecials@@QAE@$$QAU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define dso_local dllexport %struct.ExportSpecials* @"??0ExportSpecials@@QEAA@$$QEAU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsC1EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: define dso_local dllexport void @_ZN14ExportSpecialsC2EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportSpecials(ExportSpecials&&);
- // M32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"??4ExportSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"??4ExportSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSEOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSEOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportSpecials& operator=(ExportSpecials&&);
@@ -334,38 +334,38 @@
// Export class with inline special member functions.
struct ExportInlineSpecials {
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QAE@XZ"(%struct.ExportInlineSpecials* returned %this)
- // M64-DAG: define weak_odr dso_local dllexport %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QEAA@XZ"(
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"??0ExportInlineSpecials@@QAE@XZ"(%struct.ExportInlineSpecials* returned %this)
+ // M64-DAG: define weak_odr dso_local dllexport %struct.ExportInlineSpecials* @"??0ExportInlineSpecials@@QEAA@XZ"(
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1Ev(
// G64-DAG: define weak_odr dso_local dllexport void @_ZN20ExportInlineSpecialsC1Ev(
__declspec(dllexport) ExportInlineSpecials() {}
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??1ExportInlineSpecials@@QAE@XZ"(
- // M64-DAG: define weak_odr dso_local dllexport void @"\01??1ExportInlineSpecials@@QEAA@XZ"(
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??1ExportInlineSpecials@@QAE@XZ"(
+ // M64-DAG: define weak_odr dso_local dllexport void @"??1ExportInlineSpecials@@QEAA@XZ"(
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsD1Ev(
// G64-DAG: define weak_odr dso_local dllexport void @_ZN20ExportInlineSpecialsD1Ev(
__declspec(dllexport) ~ExportInlineSpecials() {}
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QAE@ABU0@@Z"(
- // M64-DAG: define weak_odr dso_local dllexport %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QEAA@AEBU0@@Z"(
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"??0ExportInlineSpecials@@QAE@ABU0@@Z"(
+ // M64-DAG: define weak_odr dso_local dllexport %struct.ExportInlineSpecials* @"??0ExportInlineSpecials@@QEAA@AEBU0@@Z"(
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1ERKS_(
// G64-DAG: define weak_odr dso_local dllexport void @_ZN20ExportInlineSpecialsC1ERKS_(
__declspec(dllexport) inline ExportInlineSpecials(const ExportInlineSpecials&);
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QAEAAU0@ABU0@@Z"(
- // M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"??4ExportInlineSpecials@@QAEAAU0@ABU0@@Z"(
+ // M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"??4ExportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSERKS_(
// G64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSERKS_(
__declspec(dllexport) ExportInlineSpecials& operator=(const ExportInlineSpecials&);
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QAE@$$QAU0@@Z"(
- // M64-DAG: define weak_odr dso_local dllexport %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QEAA@$$QEAU0@@Z"(
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"??0ExportInlineSpecials@@QAE@$$QAU0@@Z"(
+ // M64-DAG: define weak_odr dso_local dllexport %struct.ExportInlineSpecials* @"??0ExportInlineSpecials@@QEAA@$$QEAU0@@Z"(
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1EOS_(
// G64-DAG: define weak_odr dso_local dllexport void @_ZN20ExportInlineSpecialsC1EOS_(
__declspec(dllexport) ExportInlineSpecials(ExportInlineSpecials&&) {}
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(
- // M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"??4ExportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(
+ // M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"??4ExportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSEOS_(
// G64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSEOS_(
__declspec(dllexport) ExportInlineSpecials& operator=(ExportInlineSpecials&&) { return *this; }
@@ -384,46 +384,46 @@
__declspec(dllexport) ExportDefaultedDefs& operator=(ExportDefaultedDefs&&);
};
-// M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QAE@XZ"(%struct.ExportDefaultedDefs* returned %this)
-// M64-DAG: define dso_local dllexport %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QEAA@XZ"(%struct.ExportDefaultedDefs* returned %this)
+// M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"??0ExportDefaultedDefs@@QAE@XZ"(%struct.ExportDefaultedDefs* returned %this)
+// M64-DAG: define dso_local dllexport %struct.ExportDefaultedDefs* @"??0ExportDefaultedDefs@@QEAA@XZ"(%struct.ExportDefaultedDefs* returned %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1Ev(%struct.ExportDefaultedDefs* %this)
// G64-DAG: define dso_local dllexport void @_ZN19ExportDefaultedDefsC1Ev(%struct.ExportDefaultedDefs* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2Ev(%struct.ExportDefaultedDefs* %this)
// G64-DAG: define dso_local dllexport void @_ZN19ExportDefaultedDefsC2Ev(%struct.ExportDefaultedDefs* %this)
__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs() = default;
-// M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01??1ExportDefaultedDefs@@QAE@XZ"(%struct.ExportDefaultedDefs* %this)
-// M64-DAG: define dso_local dllexport void @"\01??1ExportDefaultedDefs@@QEAA@XZ"(%struct.ExportDefaultedDefs* %this)
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"??1ExportDefaultedDefs@@QAE@XZ"(%struct.ExportDefaultedDefs* %this)
+// M64-DAG: define dso_local dllexport void @"??1ExportDefaultedDefs@@QEAA@XZ"(%struct.ExportDefaultedDefs* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsD1Ev(%struct.ExportDefaultedDefs* %this)
// G64-DAG: define dso_local dllexport void @_ZN19ExportDefaultedDefsD1Ev(%struct.ExportDefaultedDefs* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsD2Ev(%struct.ExportDefaultedDefs* %this)
// G64-DAG: define dso_local dllexport void @_ZN19ExportDefaultedDefsD2Ev(%struct.ExportDefaultedDefs* %this)
ExportDefaultedDefs::~ExportDefaultedDefs() = default;
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"??0ExportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedDefs* @"??0ExportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define weak_odr dso_local dllexport void @_ZN19ExportDefaultedDefsC1ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define weak_odr dso_local dllexport void @_ZN19ExportDefaultedDefsC2ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(const ExportDefaultedDefs&) = default;
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"??4ExportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"??4ExportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
inline ExportDefaultedDefs& ExportDefaultedDefs::operator=(const ExportDefaultedDefs&) = default;
-// M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: define dso_local dllexport %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"??0ExportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define dso_local dllexport %struct.ExportDefaultedDefs* @"??0ExportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define dso_local dllexport void @_ZN19ExportDefaultedDefsC1EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define dso_local dllexport void @_ZN19ExportDefaultedDefsC2EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(ExportDefaultedDefs&&) = default;
-// M32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"??4ExportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"??4ExportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSEOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSEOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
ExportDefaultedDefs& ExportDefaultedDefs::operator=(ExportDefaultedDefs&&) = default;
@@ -432,26 +432,26 @@
// Export defaulted member function definitions declared inside class.
struct ExportDefaultedInclassDefs {
__declspec(dllexport) ExportDefaultedInclassDefs() = default;
- // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
- // M64VS2013-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
- // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
- // M64VS2015-NOT: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M64VS2013-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M64VS2015-NOT: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
__declspec(dllexport) ~ExportDefaultedInclassDefs() = default;
- // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
- // M64VS2013-DAG: define weak_odr dso_local dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
- // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
- // M64VS2015-NOT: define weak_odr dso_local dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M64VS2013-DAG: define weak_odr dso_local dllexport void @"??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc void @"??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M64VS2015-NOT: define weak_odr dso_local dllexport void @"??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
__declspec(dllexport) ExportDefaultedInclassDefs(const ExportDefaultedInclassDefs&) = default;
- // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M64VS2013-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M64VS2015-NOT: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64VS2013-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64VS2015-NOT: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
__declspec(dllexport) ExportDefaultedInclassDefs& operator=(const ExportDefaultedInclassDefs&) = default;
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"??4ExportDefaultedInclassDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"??4ExportDefaultedInclassDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
};
@@ -463,26 +463,26 @@
__declspec(dllexport) void operator delete[](void*);
};
-// M32-DAG: define dso_local dllexport i8* @"\01??2ExportAlloc@@SAPAXI@Z"(i32 %n)
-// M64-DAG: define dso_local dllexport i8* @"\01??2ExportAlloc@@SAPEAX_K@Z"(i64 %n)
+// M32-DAG: define dso_local dllexport i8* @"??2ExportAlloc@@SAPAXI@Z"(i32 %n)
+// M64-DAG: define dso_local dllexport i8* @"??2ExportAlloc@@SAPEAX_K@Z"(i64 %n)
// G32-DAG: define dso_local dllexport i8* @_ZN11ExportAllocnwEj(i32 %n)
// G64-DAG: define dso_local dllexport i8* @_ZN11ExportAllocnwEy(i64 %n)
void* ExportAlloc::operator new(__SIZE_TYPE__ n) { return malloc(n); }
-// M32-DAG: define dso_local dllexport i8* @"\01??_UExportAlloc@@SAPAXI@Z"(i32 %n)
-// M64-DAG: define dso_local dllexport i8* @"\01??_UExportAlloc@@SAPEAX_K@Z"(i64 %n)
+// M32-DAG: define dso_local dllexport i8* @"??_UExportAlloc@@SAPAXI@Z"(i32 %n)
+// M64-DAG: define dso_local dllexport i8* @"??_UExportAlloc@@SAPEAX_K@Z"(i64 %n)
// G32-DAG: define dso_local dllexport i8* @_ZN11ExportAllocnaEj(i32 %n)
// G64-DAG: define dso_local dllexport i8* @_ZN11ExportAllocnaEy(i64 %n)
void* ExportAlloc::operator new[](__SIZE_TYPE__ n) { return malloc(n); }
-// M32-DAG: define dso_local dllexport void @"\01??3ExportAlloc@@SAXPAX@Z"(i8* %p)
-// M64-DAG: define dso_local dllexport void @"\01??3ExportAlloc@@SAXPEAX@Z"(i8* %p)
+// M32-DAG: define dso_local dllexport void @"??3ExportAlloc@@SAXPAX@Z"(i8* %p)
+// M64-DAG: define dso_local dllexport void @"??3ExportAlloc@@SAXPEAX@Z"(i8* %p)
// G32-DAG: define dso_local dllexport void @_ZN11ExportAllocdlEPv(i8* %p)
// G64-DAG: define dso_local dllexport void @_ZN11ExportAllocdlEPv(i8* %p)
void ExportAlloc::operator delete(void* p) { free(p); }
-// M32-DAG: define dso_local dllexport void @"\01??_VExportAlloc@@SAXPAX@Z"(i8* %p)
-// M64-DAG: define dso_local dllexport void @"\01??_VExportAlloc@@SAXPEAX@Z"(i8* %p)
+// M32-DAG: define dso_local dllexport void @"??_VExportAlloc@@SAXPAX@Z"(i8* %p)
+// M64-DAG: define dso_local dllexport void @"??_VExportAlloc@@SAXPEAX@Z"(i8* %p)
// G32-DAG: define dso_local dllexport void @_ZN11ExportAllocdaEPv(i8* %p)
// G64-DAG: define dso_local dllexport void @_ZN11ExportAllocdaEPv(i8* %p)
void ExportAlloc::operator delete[](void* p) { free(p); }
@@ -501,13 +501,13 @@
// Export implicit instantiation of an exported member function template.
void useMemFunTmpl() {
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??$exportedNormal@UImplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
- // M64-DAG: define weak_odr dso_local dllexport void @"\01??$exportedNormal@UImplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$exportedNormal@UImplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+ // M64-DAG: define weak_odr dso_local dllexport void @"??$exportedNormal@UImplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ImplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedNormalI21ImplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
MemFunTmpl().exportedNormal<ImplicitInst_Exported>();
- // MSC-DAG: define weak_odr dso_local dllexport void @"\01??$exportedStatic@UImplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
+ // MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedStatic@UImplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedStaticI21ImplicitInst_ExportedEEvv()
MemFunTmpl().exportedStatic<ImplicitInst_Exported>();
}
@@ -515,14 +515,14 @@
// Export explicit instantiation declaration of an exported member function
// template.
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitDecl_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define weak_odr dso_local dllexport void @"\01??$exportedNormal@UExplicitDecl_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$exportedNormal@UExplicitDecl_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dso_local dllexport void @"??$exportedNormal@UExplicitDecl_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedNormalI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
extern template void MemFunTmpl::exportedNormal<ExplicitDecl_Exported>();
template void MemFunTmpl::exportedNormal<ExplicitDecl_Exported>();
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$exportedStatic@UExplicitDecl_Exported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedStatic@UExplicitDecl_Exported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedStaticI21ExplicitDecl_ExportedEEvv()
extern template void MemFunTmpl::exportedStatic<ExplicitDecl_Exported>();
template void MemFunTmpl::exportedStatic<ExplicitDecl_Exported>();
@@ -530,62 +530,62 @@
// Export explicit instantiation definition of an exported member function
// template.
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define weak_odr dso_local dllexport void @"\01??$exportedNormal@UExplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$exportedNormal@UExplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dso_local dllexport void @"??$exportedNormal@UExplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedNormalI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
template void MemFunTmpl::exportedNormal<ExplicitInst_Exported>();
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$exportedStatic@UExplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedStatic@UExplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedStaticI21ExplicitInst_ExportedEEvv()
template void MemFunTmpl::exportedStatic<ExplicitInst_Exported>();
// Export specialization of an exported member function template.
-// M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define dso_local dllexport void @"\01??$exportedNormal@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"??$exportedNormal@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define dso_local dllexport void @"??$exportedNormal@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define dso_local dllexport void @_ZN10MemFunTmpl14exportedNormalI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
template<> __declspec(dllexport) void MemFunTmpl::exportedNormal<ExplicitSpec_Def_Exported>() {}
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define weak_odr dso_local dllexport void @"\01??$exportedNormal@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$exportedNormal@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dso_local dllexport void @"??$exportedNormal@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedNormalI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
template<> __declspec(dllexport) inline void MemFunTmpl::exportedNormal<ExplicitSpec_InlineDef_Exported>() {}
-// MSC-DAG: define dso_local dllexport void @"\01??$exportedStatic@UExplicitSpec_Def_Exported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: define dso_local dllexport void @"??$exportedStatic@UExplicitSpec_Def_Exported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define dso_local dllexport void @_ZN10MemFunTmpl14exportedStaticI25ExplicitSpec_Def_ExportedEEvv()
template<> __declspec(dllexport) void MemFunTmpl::exportedStatic<ExplicitSpec_Def_Exported>() {}
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$exportedStatic@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedStatic@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl14exportedStaticI31ExplicitSpec_InlineDef_ExportedEEvv()
template<> __declspec(dllexport) inline void MemFunTmpl::exportedStatic<ExplicitSpec_InlineDef_Exported>() {}
// Not exporting specialization of an exported member function template without
// explicit dso_local dllexport.
-// M32-DAG: define dso_local x86_thiscallcc void @"\01??$exportedNormal@UExplicitSpec_NotExported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define dso_local void @"\01??$exportedNormal@UExplicitSpec_NotExported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// M32-DAG: define dso_local x86_thiscallcc void @"??$exportedNormal@UExplicitSpec_NotExported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define dso_local void @"??$exportedNormal@UExplicitSpec_NotExported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
// G32-DAG: define dso_local x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI24ExplicitSpec_NotExportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define dso_local void @_ZN10MemFunTmpl14exportedNormalI24ExplicitSpec_NotExportedEEvv(%struct.MemFunTmpl* %this)
template<> void MemFunTmpl::exportedNormal<ExplicitSpec_NotExported>() {}
-// M32-DAG: define dso_local void @"\01??$exportedStatic@UExplicitSpec_NotExported@@@MemFunTmpl@@SAXXZ"()
+// M32-DAG: define dso_local void @"??$exportedStatic@UExplicitSpec_NotExported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define dso_local void @_ZN10MemFunTmpl14exportedStaticI24ExplicitSpec_NotExportedEEvv()
template<> void MemFunTmpl::exportedStatic<ExplicitSpec_NotExported>() {}
// Export explicit instantiation declaration of a non-exported member function
// template.
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitDecl_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define weak_odr dso_local dllexport void @"\01??$normalDef@UExplicitDecl_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$normalDef@UExplicitDecl_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dso_local dllexport void @"??$normalDef@UExplicitDecl_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
extern template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitDecl_Exported>();
template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitDecl_Exported>();
-// M32-DAG: define weak_odr dso_local dllexport void @"\01??$staticDef@UExplicitDecl_Exported@@@MemFunTmpl@@SAXXZ"()
+// M32-DAG: define weak_odr dso_local dllexport void @"??$staticDef@UExplicitDecl_Exported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl9staticDefI21ExplicitDecl_ExportedEEvv()
extern template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitDecl_Exported>();
template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitDecl_Exported>();
@@ -593,22 +593,22 @@
// Export explicit instantiation definition of a non-exported member function
// template.
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define weak_odr dso_local dllexport void @"\01??$normalDef@UExplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$normalDef@UExplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dso_local dllexport void @"??$normalDef@UExplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitInst_Exported>();
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$staticDef@UExplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$staticDef@UExplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl9staticDefI21ExplicitInst_ExportedEEvv()
template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitInst_Exported>();
// Export specialization of a non-exported member function template.
-// M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define dso_local dllexport void @"\01??$normalDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define weak_odr dso_local dllexport void @"\01??$normalDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"??$normalDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define dso_local dllexport void @"??$normalDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??$normalDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dso_local dllexport void @"??$normalDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define dso_local dllexport void @_ZN10MemFunTmpl9normalDefI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
@@ -616,8 +616,8 @@
template<> __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitSpec_Def_Exported>() {}
template<> __declspec(dllexport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Exported>() {}
-// MSC-DAG: define dso_local dllexport void @"\01??$staticDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@SAXXZ"()
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$staticDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: define dso_local dllexport void @"??$staticDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$staticDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define dso_local dllexport void @_ZN10MemFunTmpl9staticDefI25ExplicitSpec_Def_ExportedEEvv()
// GNU-DAG: define weak_odr dso_local dllexport void @_ZN10MemFunTmpl9staticDefI31ExplicitSpec_InlineDef_ExportedEEvv()
template<> __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitSpec_Def_Exported>() {}
@@ -633,49 +633,49 @@
template<typename T> const int MemVarTmpl::ExportedStaticVar;
// Export implicit instantiation of an exported member variable template.
-// MSC-DAG: @"\01??$ExportedStaticVar@UImplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedStaticVar@UImplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ImplicitInst_ExportedEE = weak_odr dso_local dllexport constant i32 1, comdat, align 4
int useMemVarTmpl() { return MemVarTmpl::ExportedStaticVar<ImplicitInst_Exported>; }
// Export explicit instantiation declaration of an exported member variable
// template.
-// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedStaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitDecl_ExportedEE = weak_odr dso_local dllexport constant i32 1, comdat, align 4
extern template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>;
template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>;
// Export explicit instantiation definition of an exported member variable
// template.
-// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedStaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitInst_ExportedEE = weak_odr dso_local dllexport constant i32 1, comdat, align 4
template const int MemVarTmpl::ExportedStaticVar<ExplicitInst_Exported>;
// Export specialization of an exported member variable template.
-// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedStaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI25ExplicitSpec_Def_ExportedEE = dso_local dllexport constant i32 1, align 4
template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_Def_Exported> = 1;
// Not exporting specialization of an exported member variable template without
// explicit dllexport.
-// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_NotExported@@@MemVarTmpl@@2HB" = weak_odr dso_local constant i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedStaticVar@UExplicitSpec_NotExported@@@MemVarTmpl@@2HB" = weak_odr dso_local constant i32 1, comdat, align 4
// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI24ExplicitSpec_NotExportedEE = dso_local constant i32 1, align 4
template<> const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_NotExported> = 1;
// Export explicit instantiation declaration of a non-exported member variable
// template.
-// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// MSC-DAG: @"??$StaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ExportedEE = weak_odr dso_local dllexport constant i32 1, comdat, align 4
extern template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>;
template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>;
// Export explicit instantiation definition of a non-exported member variable
// template.
-// MSC-DAG: @"\01??$StaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// MSC-DAG: @"??$StaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitInst_ExportedEE = weak_odr dso_local dllexport constant i32 1, comdat, align 4
template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitInst_Exported>;
// Export specialization of a non-exported member variable template.
-// MSC-DAG: @"\01??$StaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
+// MSC-DAG: @"??$StaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = weak_odr dso_local dllexport constant i32 1, comdat, align 4
// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI25ExplicitSpec_Def_ExportedEE = dso_local dllexport constant i32 1, align 4
template<> __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitSpec_Def_Exported> = 1;
diff --git a/test/CodeGenCXX/dllexport-ms-friend.cpp b/test/CodeGenCXX/dllexport-ms-friend.cpp
index 73379f3..6702647 100644
--- a/test/CodeGenCXX/dllexport-ms-friend.cpp
+++ b/test/CodeGenCXX/dllexport-ms-friend.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple %ms_abi_triple -fms-extensions -emit-llvm -O0 -o - %s | FileCheck %s
// Friend functions defined in classes are emitted.
-// CHECK: define weak_odr dso_local dllexport void @"\01?friend1@@YAXXZ"()
+// CHECK: define weak_odr dso_local dllexport void @"?friend1@@YAXXZ"()
struct FuncFriend1 {
friend __declspec(dllexport) void friend1() {}
};
diff --git a/test/CodeGenCXX/dllexport-pr26549.cpp b/test/CodeGenCXX/dllexport-pr26549.cpp
index e9a62e2..c5ac1c1 100644
--- a/test/CodeGenCXX/dllexport-pr26549.cpp
+++ b/test/CodeGenCXX/dllexport-pr26549.cpp
@@ -3,7 +3,7 @@
template <typename> struct MessageT { };
extern template struct MessageT<int>;
-// CHECK: define weak_odr dso_local dllexport {{.*}} %struct.MessageT* @"\01??4?$MessageT@H@@QEAAAEAU0@AEBU0@@Z"(
+// CHECK: define weak_odr dso_local dllexport {{.*}} %struct.MessageT* @"??4?$MessageT@H@@QEAAAEAU0@AEBU0@@Z"(
template struct __declspec(dllexport) MessageT<int>;
// Previously we crashed when this dllexport was the last thing in the file.
// DO NOT ADD MORE TESTS AFTER THIS LINE!
diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp
index 4155940..b867662 100644
--- a/test/CodeGenCXX/dllexport.cpp
+++ b/test/CodeGenCXX/dllexport.cpp
@@ -27,9 +27,9 @@
#define INST(func) template void func();
// The vftable for struct W is comdat largest because we have RTTI.
-// M32-DAG: $"\01??_7W@@6B@" = comdat largest
+// M32-DAG: $"??_7W@@6B@" = comdat largest
-// M32-DAG: $"\01?smember@?$Base@H@PR32992@@0HA" = comdat any
+// M32-DAG: $"?smember@?$Base@H@PR32992@@0HA" = comdat any
//===----------------------------------------------------------------------===//
@@ -37,59 +37,63 @@
//===----------------------------------------------------------------------===//
// Declarations are not exported.
-// MSC-NOT: @"\01?ExternGlobalDecl@@3HA"
+// MSC-NOT: @"?ExternGlobalDecl@@3HA"
// GNU-NOT: @ExternGlobalDecl
__declspec(dllexport) extern int ExternGlobalDecl;
+// M64-DAG: @__ImageBase = external dso_local constant i8
+
+// GNU-DAG: @_ZTVN10__cxxabiv117__class_type_infoE = external dso_local global
+
// dllexport implies a definition.
-// MSC-DAG: @"\01?GlobalDef@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?GlobalDef@@3HA" = dso_local dllexport global i32 0, align 4
// GNU-DAG: @GlobalDef = dso_local dllexport global i32 0, align 4
__declspec(dllexport) int GlobalDef;
// Export definition.
-// MSC-DAG: @"\01?GlobalInit1@@3HA" = dso_local dllexport global i32 1, align 4
+// MSC-DAG: @"?GlobalInit1@@3HA" = dso_local dllexport global i32 1, align 4
// GNU-DAG: @GlobalInit1 = dso_local dllexport global i32 1, align 4
__declspec(dllexport) int GlobalInit1 = 1;
-// MSC-DAG: @"\01?GlobalInit2@@3HA" = dso_local dllexport global i32 1, align 4
+// MSC-DAG: @"?GlobalInit2@@3HA" = dso_local dllexport global i32 1, align 4
// GNU-DAG: @GlobalInit2 = dso_local dllexport global i32 1, align 4
int __declspec(dllexport) GlobalInit2 = 1;
// Declare, then export definition.
-// MSC-DAG: @"\01?GlobalDeclInit@@3HA" = dso_local dllexport global i32 1, align 4
+// MSC-DAG: @"?GlobalDeclInit@@3HA" = dso_local dllexport global i32 1, align 4
// GNU-DAG: @GlobalDeclInit = dso_local dllexport global i32 1, align 4
__declspec(dllexport) extern int GlobalDeclInit;
int GlobalDeclInit = 1;
// Redeclarations
-// MSC-DAG: @"\01?GlobalRedecl1@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?GlobalRedecl1@@3HA" = dso_local dllexport global i32 0, align 4
// GNU-DAG: @GlobalRedecl1 = dso_local dllexport global i32 0, align 4
__declspec(dllexport) extern int GlobalRedecl1;
__declspec(dllexport) int GlobalRedecl1;
-// MSC-DAG: @"\01?GlobalRedecl2@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?GlobalRedecl2@@3HA" = dso_local dllexport global i32 0, align 4
// GNU-DAG: @GlobalRedecl2 = dso_local dllexport global i32 0, align 4
__declspec(dllexport) extern int GlobalRedecl2;
int GlobalRedecl2;
-// MSC-DAG: @"\01?ExternalGlobal@ns@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?ExternalGlobal@ns@@3HA" = dso_local dllexport global i32 0, align 4
// GNU-DAG: @_ZN2ns14ExternalGlobalE = dso_local dllexport global i32 0, align 4
namespace ns { __declspec(dllexport) int ExternalGlobal; }
-// MSC-DAG: @"\01?ExternalAutoTypeGlobal@@3UExternal@@A" = dso_local dllexport global %struct.External zeroinitializer, align 4
+// MSC-DAG: @"?ExternalAutoTypeGlobal@@3UExternal@@A" = dso_local dllexport global %struct.External zeroinitializer, align 4
// GNU-DAG: @ExternalAutoTypeGlobal = dso_local dllexport global %struct.External zeroinitializer, align 4
__declspec(dllexport) auto ExternalAutoTypeGlobal = External();
int f();
-// MSC-DAG: @"\01?x@?1??nonInlineStaticLocalsFunc@@YAHXZ@4HA" = internal {{(unnamed_addr )*}}global i32 0
-// MSC-DAG: @"\01?$S1@?1??nonInlineStaticLocalsFunc@@YAHXZ@4IA" = internal {{(unnamed_addr )*}}global i32 0
+// MSC-DAG: @"?x@?1??nonInlineStaticLocalsFunc@@YAHXZ@4HA" = internal {{(unnamed_addr )*}}global i32 0
+// MSC-DAG: @"?$S1@?1??nonInlineStaticLocalsFunc@@YAHXZ@4IA" = internal {{(unnamed_addr )*}}global i32 0
int __declspec(dllexport) nonInlineStaticLocalsFunc() {
static int x = f();
return x++;
};
-// MSC-DAG: @"\01?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat
-// MSC-DAG: @"\01??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = weak_odr dllexport global i32 0, comdat
+// MSC-DAG: @"?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat
+// MSC-DAG: @"??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = weak_odr dllexport global i32 0, comdat
// Note: MinGW doesn't seem to export the static local here.
inline int __declspec(dllexport) inlineStaticLocalsFunc() {
static int x = f();
@@ -103,7 +107,7 @@
virtual void myfunc() {}
static int smember;
};
-// MSC-DAG: @"\01?smember@?$Base@H@PR32992@@0HA" = weak_odr dso_local dllexport global i32 77, comdat, align 4
+// MSC-DAG: @"?smember@?$Base@H@PR32992@@0HA" = weak_odr dso_local dllexport global i32 77, comdat, align 4
template <class T> int Base<T>::smember = 77;
template <class T>
class __declspec(dllexport) Derived2 : Base<T> {
@@ -132,48 +136,48 @@
// Declarations are not exported.
-// MSC-DAG: @"\01??$VarTmplImplicitDef@UImplicitInst_Exported@@@@3HA" = external dso_local global
+// MSC-DAG: @"??$VarTmplImplicitDef@UImplicitInst_Exported@@@@3HA" = external dso_local global
// GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE = external dso_local global
template<typename T> __declspec(dllexport) extern int VarTmplImplicitDef;
USEVAR(VarTmplImplicitDef<ImplicitInst_Exported>)
// Export definition.
-// MSC-DAG: @"\01??$VarTmplInit1@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmplInit1@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
// GNU-DAG: @_Z12VarTmplInit1I21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template<typename T> __declspec(dllexport) int VarTmplInit1 = 1;
INSTVAR(VarTmplInit1<ExplicitInst_Exported>)
-// MSC-DAG: @"\01??$VarTmplInit2@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmplInit2@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
// GNU-DAG: @_Z12VarTmplInit2I21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template<typename T> int __declspec(dllexport) VarTmplInit2 = 1;
INSTVAR(VarTmplInit2<ExplicitInst_Exported>)
// Declare, then export definition.
-// MSC-DAG: @"\01??$VarTmplDeclInit@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmplDeclInit@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
// GNU-DAG: @_Z15VarTmplDeclInitI21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template<typename T> __declspec(dllexport) extern int VarTmplDeclInit;
template<typename T> int VarTmplDeclInit = 1;
INSTVAR(VarTmplDeclInit<ExplicitInst_Exported>)
// Redeclarations
-// MSC-DAG: @"\01??$VarTmplRedecl1@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmplRedecl1@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
// GNU-DAG: @_Z14VarTmplRedecl1I21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template<typename T> __declspec(dllexport) extern int VarTmplRedecl1;
template<typename T> __declspec(dllexport) int VarTmplRedecl1 = 1;
INSTVAR(VarTmplRedecl1<ExplicitInst_Exported>)
-// MSC-DAG: @"\01??$VarTmplRedecl2@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmplRedecl2@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
// GNU-DAG: @_Z14VarTmplRedecl2I21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template<typename T> __declspec(dllexport) extern int VarTmplRedecl2;
template<typename T> int VarTmplRedecl2 = 1;
INSTVAR(VarTmplRedecl2<ExplicitInst_Exported>)
-// MSC-DAG: @"\01??$ExternalVarTmpl@UExplicitInst_Exported@@@ns@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$ExternalVarTmpl@UExplicitInst_Exported@@@ns@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ExplicitInst_ExportedEE = weak_odr dso_local dllexport global i32 1, comdat, align 4
namespace ns { template<typename T> __declspec(dllexport) int ExternalVarTmpl = 1; }
INSTVAR(ns::ExternalVarTmpl<ExplicitInst_Exported>)
-// MSC-DAG: @"\01??$ExternalAutoTypeVarTmpl@UExplicitInst_Exported@@@@3UExternal@@A" = weak_odr dso_local dllexport global %struct.External zeroinitializer, comdat, align 4
+// MSC-DAG: @"??$ExternalAutoTypeVarTmpl@UExplicitInst_Exported@@@@3UExternal@@A" = weak_odr dso_local dllexport global %struct.External zeroinitializer, comdat, align 4
// GNU-DAG: @_Z23ExternalAutoTypeVarTmplI21ExplicitInst_ExportedE = weak_odr dso_local dllexport global %struct.External zeroinitializer, comdat, align 4
template<typename T> __declspec(dllexport) auto ExternalAutoTypeVarTmpl = External();
template External ExternalAutoTypeVarTmpl<ExplicitInst_Exported>;
@@ -183,54 +187,54 @@
template<typename T> __declspec(dllexport) int ExportedVarTmpl = 1;
// Export implicit instantiation of an exported variable template.
-// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
// GNU-DAG: @_Z15ExportedVarTmplI21ImplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
USEVAR(ExportedVarTmpl<ImplicitInst_Exported>)
// Export explicit instantiation declaration of an exported variable template.
-// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitDecl_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
extern template int ExportedVarTmpl<ExplicitDecl_Exported>;
template int ExportedVarTmpl<ExplicitDecl_Exported>;
// Export explicit instantiation definition of an exported variable template.
-// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template __declspec(dllexport) int ExportedVarTmpl<ExplicitInst_Exported>;
// Export specialization of an exported variable template.
-// MSC-DAG: @"\01??$ExportedVarTmpl@UExplicitSpec_Exported@@@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"??$ExportedVarTmpl@UExplicitSpec_Exported@@@@3HA" = dso_local dllexport global i32 0, align 4
// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitSpec_ExportedE = dso_local dllexport global i32 0, align 4
template<> __declspec(dllexport) int ExportedVarTmpl<ExplicitSpec_Exported>;
-// MSC-DAG: @"\01??$ExportedVarTmpl@UExplicitSpec_Def_Exported@@@@3HA" = dso_local dllexport global i32 1, align 4
+// MSC-DAG: @"??$ExportedVarTmpl@UExplicitSpec_Def_Exported@@@@3HA" = dso_local dllexport global i32 1, align 4
// GNU-DAG: @_Z15ExportedVarTmplI25ExplicitSpec_Def_ExportedE = dso_local dllexport global i32 1, align 4
template<> __declspec(dllexport) int ExportedVarTmpl<ExplicitSpec_Def_Exported> = 1;
// Not exporting specialization of an exported variable template without
// explicit dllexport.
-// MSC-DAG: @"\01??$ExportedVarTmpl@UExplicitSpec_NotExported@@@@3HA" = dso_local global i32 0, align 4
+// MSC-DAG: @"??$ExportedVarTmpl@UExplicitSpec_NotExported@@@@3HA" = dso_local global i32 0, align 4
// GNU-DAG: @_Z15ExportedVarTmplI24ExplicitSpec_NotExportedE = dso_local global i32 0, align 4
template<> int ExportedVarTmpl<ExplicitSpec_NotExported>;
// Export explicit instantiation declaration of a non-exported variable template.
-// MSC-DAG: @"\01??$VarTmpl@UExplicitDecl_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmpl@UExplicitDecl_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
extern template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>;
template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>;
// Export explicit instantiation definition of a non-exported variable template.
-// MSC-DAG: @"\01??$VarTmpl@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
+// MSC-DAG: @"??$VarTmpl@UExplicitInst_Exported@@@@3HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4
// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ExportedE = weak_odr dso_local dllexport global i32 1, comdat, align 4
template __declspec(dllexport) int VarTmpl<ExplicitInst_Exported>;
// Export specialization of a non-exported variable template.
-// MSC-DAG: @"\01??$VarTmpl@UExplicitSpec_Exported@@@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"??$VarTmpl@UExplicitSpec_Exported@@@@3HA" = dso_local dllexport global i32 0, align 4
// GNU-DAG: @_Z7VarTmplI21ExplicitSpec_ExportedE = dso_local dllexport global i32 0, align 4
template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Exported>;
-// MSC-DAG: @"\01??$VarTmpl@UExplicitSpec_Def_Exported@@@@3HA" = dso_local dllexport global i32 1, align 4
+// MSC-DAG: @"??$VarTmpl@UExplicitSpec_Def_Exported@@@@3HA" = dso_local dllexport global i32 1, align 4
// GNU-DAG: @_Z7VarTmplI25ExplicitSpec_Def_ExportedE = dso_local dllexport global i32 1, align 4
template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Def_Exported> = 1;
@@ -243,7 +247,7 @@
// Declarations are not exported.
// Export function definition.
-// MSC-DAG: define dso_local dllexport void @"\01?def@@YAXXZ"()
+// MSC-DAG: define dso_local dllexport void @"?def@@YAXXZ"()
// GNU-DAG: define dso_local dllexport void @_Z3defv()
__declspec(dllexport) void def() {}
@@ -253,35 +257,35 @@
extern "C" __declspec(dllexport) void externC() {}
// Export inline function.
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01?inlineFunc@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"?inlineFunc@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z10inlineFuncv()
__declspec(dllexport) inline void inlineFunc() {}
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01?inlineDecl@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"?inlineDecl@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z10inlineDeclv()
__declspec(dllexport) inline void inlineDecl();
void inlineDecl() {}
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01?inlineDef@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"?inlineDef@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z9inlineDefv()
__declspec(dllexport) void inlineDef();
inline void inlineDef() {}
// Redeclarations
-// MSC-DAG: define dso_local dllexport void @"\01?redecl1@@YAXXZ"()
+// MSC-DAG: define dso_local dllexport void @"?redecl1@@YAXXZ"()
// GNU-DAG: define dso_local dllexport void @_Z7redecl1v()
__declspec(dllexport) void redecl1();
__declspec(dllexport) void redecl1() {}
-// MSC-DAG: define dso_local dllexport void @"\01?redecl2@@YAXXZ"()
+// MSC-DAG: define dso_local dllexport void @"?redecl2@@YAXXZ"()
// GNU-DAG: define dso_local dllexport void @_Z7redecl2v()
__declspec(dllexport) void redecl2();
void redecl2() {}
// Friend functions
-// MSC-DAG: define dso_local dllexport void @"\01?friend1@@YAXXZ"()
+// MSC-DAG: define dso_local dllexport void @"?friend1@@YAXXZ"()
// GNU-DAG: define dso_local dllexport void @_Z7friend1v()
-// MSC-DAG: define dso_local dllexport void @"\01?friend2@@YAXXZ"()
+// MSC-DAG: define dso_local dllexport void @"?friend2@@YAXXZ"()
// GNU-DAG: define dso_local dllexport void @_Z7friend2v()
struct FuncFriend {
friend __declspec(dllexport) void friend1();
@@ -290,13 +294,23 @@
__declspec(dllexport) void friend1() {}
void friend2() {}
+// MSC-DAG: define dso_local dllexport void @"?func@Befriended@@SAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_ZN10Befriended4funcEv()
+struct __declspec(dllexport) Befriended {
+ static void func();
+ struct Befriending {
+ friend void Befriended::func();
+ };
+};
+void Befriended::func() {}
+
// Implicit declarations can be redeclared with dllexport.
-// MSC-DAG: define dso_local dllexport noalias i8* @"\01??2@{{YAPAXI|YAPEAX_K}}@Z"(
+// MSC-DAG: define dso_local dllexport noalias i8* @"??2@{{YAPAXI|YAPEAX_K}}@Z"(
// GNU-DAG: define dso_local dllexport noalias i8* @_Znw{{[yj]}}(
void* alloc(__SIZE_TYPE__ n);
__declspec(dllexport) void* operator new(__SIZE_TYPE__ n) { return alloc(n); }
-// MSC-DAG: define dso_local dllexport void @"\01?externalFunc@ns@@YAXXZ"()
+// MSC-DAG: define dso_local dllexport void @"?externalFunc@ns@@YAXXZ"()
// GNU-DAG: define dso_local dllexport void @_ZN2ns12externalFuncEv()
namespace ns { __declspec(dllexport) void externalFunc() {} }
@@ -307,29 +321,29 @@
//===----------------------------------------------------------------------===//
// Export function template definition.
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$funcTmplDef@UExplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmplDef@UExplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z11funcTmplDefI21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) void funcTmplDef() {}
INST(funcTmplDef<ExplicitInst_Exported>)
// Export inline function template.
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$inlineFuncTmpl1@UExplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$inlineFuncTmpl1@UExplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z15inlineFuncTmpl1I21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) inline void inlineFuncTmpl1() {}
INST(inlineFuncTmpl1<ExplicitInst_Exported>)
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$inlineFuncTmpl2@UExplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$inlineFuncTmpl2@UExplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z15inlineFuncTmpl2I21ExplicitInst_ExportedEvv()
template<typename T> inline void __attribute__((dllexport)) inlineFuncTmpl2() {}
INST(inlineFuncTmpl2<ExplicitInst_Exported>)
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$inlineFuncTmplDecl@UExplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$inlineFuncTmplDecl@UExplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z18inlineFuncTmplDeclI21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) inline void inlineFuncTmplDecl();
template<typename T> void inlineFuncTmplDecl() {}
INST(inlineFuncTmplDecl<ExplicitInst_Exported>)
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$inlineFuncTmplDef@UExplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$inlineFuncTmplDef@UExplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z17inlineFuncTmplDefI21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) void inlineFuncTmplDef();
template<typename T> inline void inlineFuncTmplDef() {}
@@ -337,19 +351,19 @@
// Redeclarations
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$funcTmplRedecl1@UExplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmplRedecl1@UExplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z15funcTmplRedecl1I21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) void funcTmplRedecl1();
template<typename T> __declspec(dllexport) void funcTmplRedecl1() {}
INST(funcTmplRedecl1<ExplicitInst_Exported>)
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$funcTmplRedecl2@UExplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmplRedecl2@UExplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z15funcTmplRedecl2I21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) void funcTmplRedecl2();
template<typename T> void funcTmplRedecl2() {}
INST(funcTmplRedecl2<ExplicitInst_Exported>)
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$funcTmplRedecl3@UExplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmplRedecl3@UExplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z15funcTmplRedecl3I21ExplicitInst_ExportedEvv()
template<typename T> __declspec(dllexport) void funcTmplRedecl3();
template<typename T> void funcTmplRedecl3() {}
@@ -357,9 +371,9 @@
// Function template friends
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$funcTmplFriend1@UExplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmplFriend1@UExplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z15funcTmplFriend1I21ExplicitInst_ExportedEvv()
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$funcTmplFriend2@UExplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmplFriend2@UExplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z15funcTmplFriend2I21ExplicitInst_ExportedEvv()
struct FuncTmplFriend {
template<typename T> friend __declspec(dllexport) void funcTmplFriend1();
@@ -370,7 +384,7 @@
INST(funcTmplFriend1<ExplicitInst_Exported>)
INST(funcTmplFriend2<ExplicitInst_Exported>)
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$externalFuncTmpl@UExplicitInst_Exported@@@ns@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$externalFuncTmpl@UExplicitInst_Exported@@@ns@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_ZN2ns16externalFuncTmplI21ExplicitInst_ExportedEEvv()
namespace ns { template<typename T> __declspec(dllexport) void externalFuncTmpl() {} }
INST(ns::externalFuncTmpl<ExplicitInst_Exported>)
@@ -380,54 +394,54 @@
template<typename T> __declspec(dllexport) void exportedFuncTmpl() {}
// Export implicit instantiation of an exported function template.
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$exportedFuncTmpl@UImplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedFuncTmpl@UImplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z16exportedFuncTmplI21ImplicitInst_ExportedEvv()
USE(exportedFuncTmpl<ImplicitInst_Exported>)
// Export explicit instantiation declaration of an exported function template.
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$exportedFuncTmpl@UExplicitDecl_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedFuncTmpl@UExplicitDecl_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z16exportedFuncTmplI21ExplicitDecl_ExportedEvv()
extern template void exportedFuncTmpl<ExplicitDecl_Exported>();
template void exportedFuncTmpl<ExplicitDecl_Exported>();
// Export explicit instantiation definition of an exported function template.
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$exportedFuncTmpl@UExplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedFuncTmpl@UExplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z16exportedFuncTmplI21ExplicitInst_ExportedEvv()
template void exportedFuncTmpl<ExplicitInst_Exported>();
// Export specialization of an exported function template.
-// MSC-DAG: define dso_local dllexport void @"\01??$exportedFuncTmpl@UExplicitSpec_Def_Exported@@@@YAXXZ"()
+// MSC-DAG: define dso_local dllexport void @"??$exportedFuncTmpl@UExplicitSpec_Def_Exported@@@@YAXXZ"()
// GNU-DAG: define dso_local dllexport void @_Z16exportedFuncTmplI25ExplicitSpec_Def_ExportedEvv()
template<> __declspec(dllexport) void exportedFuncTmpl<ExplicitSpec_Def_Exported>() {}
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$exportedFuncTmpl@UExplicitSpec_InlineDef_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$exportedFuncTmpl@UExplicitSpec_InlineDef_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z16exportedFuncTmplI31ExplicitSpec_InlineDef_ExportedEvv()
template<> __declspec(dllexport) inline void exportedFuncTmpl<ExplicitSpec_InlineDef_Exported>() {}
// Not exporting specialization of an exported function template without
// explicit dllexport.
-// MSC-DAG: define dso_local void @"\01??$exportedFuncTmpl@UExplicitSpec_NotExported@@@@YAXXZ"()
+// MSC-DAG: define dso_local void @"??$exportedFuncTmpl@UExplicitSpec_NotExported@@@@YAXXZ"()
// GNU-DAG: define dso_local void @_Z16exportedFuncTmplI24ExplicitSpec_NotExportedEvv()
template<> void exportedFuncTmpl<ExplicitSpec_NotExported>() {}
// Export explicit instantiation declaration of a non-exported function template.
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$funcTmpl@UExplicitDecl_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmpl@UExplicitDecl_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z8funcTmplI21ExplicitDecl_ExportedEvv()
extern template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>();
template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>();
// Export explicit instantiation definition of a non-exported function template.
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$funcTmpl@UExplicitInst_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmpl@UExplicitInst_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z8funcTmplI21ExplicitInst_ExportedEvv()
template __declspec(dllexport) void funcTmpl<ExplicitInst_Exported>();
// Export specialization of a non-exported function template.
-// MSC-DAG: define dso_local dllexport void @"\01??$funcTmpl@UExplicitSpec_Def_Exported@@@@YAXXZ"()
+// MSC-DAG: define dso_local dllexport void @"??$funcTmpl@UExplicitSpec_Def_Exported@@@@YAXXZ"()
// GNU-DAG: define dso_local dllexport void @_Z8funcTmplI25ExplicitSpec_Def_ExportedEvv()
template<> __declspec(dllexport) void funcTmpl<ExplicitSpec_Def_Exported>() {}
-// MSC-DAG: define weak_odr dso_local dllexport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Exported@@@@YAXXZ"()
+// MSC-DAG: define weak_odr dso_local dllexport void @"??$funcTmpl@UExplicitSpec_InlineDef_Exported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local dllexport void @_Z8funcTmplI31ExplicitSpec_InlineDef_ExportedEvv()
template<> __declspec(dllexport) inline void funcTmpl<ExplicitSpec_InlineDef_Exported>() {}
@@ -438,60 +452,60 @@
//===----------------------------------------------------------------------===//
// dllexport takes precedence over the dllimport if both are specified.
-// MSC-DAG: @"\01?PrecedenceGlobal1A@@3HA" = dso_local dllexport global i32 0, align 4
-// MSC-DAG: @"\01?PrecedenceGlobal1B@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobal1A@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobal1B@@3HA" = dso_local dllexport global i32 0, align 4
// GNU-DAG: @PrecedenceGlobal1A = dso_local dllexport global i32 0, align 4
// GNU-DAG: @PrecedenceGlobal1B = dso_local dllexport global i32 0, align 4
__attribute__((dllimport, dllexport)) int PrecedenceGlobal1A; // dllimport ignored
__declspec(dllimport) __declspec(dllexport) int PrecedenceGlobal1B; // dllimport ignored
-// MSC-DAG: @"\01?PrecedenceGlobal2A@@3HA" = dso_local dllexport global i32 0, align 4
-// MSC-DAG: @"\01?PrecedenceGlobal2B@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobal2A@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobal2B@@3HA" = dso_local dllexport global i32 0, align 4
// GNU-DAG: @PrecedenceGlobal2A = dso_local dllexport global i32 0, align 4
// GNU-DAG: @PrecedenceGlobal2B = dso_local dllexport global i32 0, align 4
__attribute__((dllexport, dllimport)) int PrecedenceGlobal2A; // dllimport ignored
__declspec(dllexport) __declspec(dllimport) int PrecedenceGlobal2B; // dllimport ignored
-// MSC-DAG: @"\01?PrecedenceGlobalRedecl1@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobalRedecl1@@3HA" = dso_local dllexport global i32 0, align 4
// GNU-DAG: @PrecedenceGlobalRedecl1 = dso_local dllexport global i32 0, align 4
__declspec(dllexport) extern int PrecedenceGlobalRedecl1;
__declspec(dllimport) int PrecedenceGlobalRedecl1 = 0;
-// MSC-DAG: @"\01?PrecedenceGlobalRedecl2@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobalRedecl2@@3HA" = dso_local dllexport global i32 0, align 4
// GNU-DAG: @PrecedenceGlobalRedecl2 = dso_local dllexport global i32 0, align 4
__declspec(dllimport) extern int PrecedenceGlobalRedecl2;
__declspec(dllexport) int PrecedenceGlobalRedecl2;
-// MSC-DAG: @"\01?PrecedenceGlobalMixed1@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobalMixed1@@3HA" = dso_local dllexport global i32 0, align 4
// GNU-DAG: @PrecedenceGlobalMixed1 = dso_local dllexport global i32 0, align 4
__attribute__((dllexport)) extern int PrecedenceGlobalMixed1;
__declspec(dllimport) int PrecedenceGlobalMixed1 = 0;
-// MSC-DAG: @"\01?PrecedenceGlobalMixed2@@3HA" = dso_local dllexport global i32 0, align 4
+// MSC-DAG: @"?PrecedenceGlobalMixed2@@3HA" = dso_local dllexport global i32 0, align 4
// GNU-DAG: @PrecedenceGlobalMixed2 = dso_local dllexport global i32 0, align 4
__attribute__((dllimport)) extern int PrecedenceGlobalMixed2;
__declspec(dllexport) int PrecedenceGlobalMixed2;
-// MSC-DAG: define dso_local dllexport void @"\01?precedence1A@@YAXXZ"
-// MSC-DAG: define dso_local dllexport void @"\01?precedence1B@@YAXXZ"
+// MSC-DAG: define dso_local dllexport void @"?precedence1A@@YAXXZ"
+// MSC-DAG: define dso_local dllexport void @"?precedence1B@@YAXXZ"
// GNU-DAG: define dso_local dllexport void @_Z12precedence1Av()
// GNU-DAG: define dso_local dllexport void @_Z12precedence1Bv()
void __attribute__((dllimport, dllexport)) precedence1A() {}
void __declspec(dllimport) __declspec(dllexport) precedence1B() {}
-// MSC-DAG: define dso_local dllexport void @"\01?precedence2A@@YAXXZ"
-// MSC-DAG: define dso_local dllexport void @"\01?precedence2B@@YAXXZ"
+// MSC-DAG: define dso_local dllexport void @"?precedence2A@@YAXXZ"
+// MSC-DAG: define dso_local dllexport void @"?precedence2B@@YAXXZ"
// GNU-DAG: define dso_local dllexport void @_Z12precedence2Av()
// GNU-DAG: define dso_local dllexport void @_Z12precedence2Bv()
void __attribute__((dllexport, dllimport)) precedence2A() {}
void __declspec(dllexport) __declspec(dllimport) precedence2B() {}
-// MSC-DAG: define dso_local dllexport void @"\01?precedenceRedecl1@@YAXXZ"
+// MSC-DAG: define dso_local dllexport void @"?precedenceRedecl1@@YAXXZ"
// GNU-DAG: define dso_local dllexport void @_Z17precedenceRedecl1v()
void __declspec(dllimport) precedenceRedecl1();
void __declspec(dllexport) precedenceRedecl1() {}
-// MSC-DAG: define dso_local dllexport void @"\01?precedenceRedecl2@@YAXXZ"
+// MSC-DAG: define dso_local dllexport void @"?precedenceRedecl2@@YAXXZ"
// GNU-DAG: define dso_local dllexport void @_Z17precedenceRedecl2v()
void __declspec(dllexport) precedenceRedecl2();
void __declspec(dllimport) precedenceRedecl2() {}
@@ -504,11 +518,11 @@
struct S {
void __declspec(dllexport) a() {}
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?a@S@@QAEXXZ"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?a@S@@QAEXXZ"
struct T {
void __declspec(dllexport) a() {}
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?a@T@S@@QAEXXZ"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?a@T@S@@QAEXXZ"
};
};
@@ -517,11 +531,11 @@
SomeTemplate(T o = T()) : o(o) {}
T o;
};
-// MSVC2015-DAG: define weak_odr dso_local dllexport {{.+}} @"\01??4?$SomeTemplate@H@@Q{{.+}}@$$Q{{.+}}@@Z"
-// MSVC2013-DAG: define weak_odr dso_local dllexport {{.+}} @"\01??4?$SomeTemplate@H@@Q{{.+}}0@A{{.+}}0@@Z"
+// MSVC2015-DAG: define weak_odr dso_local dllexport {{.+}} @"??4?$SomeTemplate@H@@Q{{.+}}@$$Q{{.+}}@@Z"
+// MSVC2013-DAG: define weak_odr dso_local dllexport {{.+}} @"??4?$SomeTemplate@H@@Q{{.+}}0@A{{.+}}0@@Z"
struct __declspec(dllexport) InheritFromTemplate : SomeTemplate<int> {};
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_F?$SomeTemplate@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??_F?$SomeTemplate@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
namespace PR23801 {
template <typename>
@@ -538,31 +552,31 @@
}
//
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FB@PR23801@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FB@PR23801@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
struct __declspec(dllexport) T {
// Copy assignment operator:
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@ABU0@@Z"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"??4T@@QAEAAU0@ABU0@@Z"
// Explicitly defaulted copy constructur:
T(const T&) = default;
- // M32MSVC2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.T* @"\01??0T@@QAE@ABU0@@Z"
+ // M32MSVC2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.T* @"??0T@@QAE@ABU0@@Z"
void a() {}
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?a@T@@QAEXXZ"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?a@T@@QAEXXZ"
static int b;
- // M32-DAG: @"\01?b@T@@2HA" = external dso_local global i32
+ // M32-DAG: @"?b@T@@2HA" = external dso_local global i32
static int c;
- // M32-DAG: @"\01?c@T@@2HA" = dso_local dllexport global i32 0, align 4
+ // M32-DAG: @"?c@T@@2HA" = dso_local dllexport global i32 0, align 4
};
USEVAR(T::b)
int T::c;
// Export template class with static member variable
-// MSC-DAG: @"\01?StaticClassVarExpTmplClass@?$TmplClass@H@@2HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4
+// MSC-DAG: @"?StaticClassVarExpTmplClass@?$TmplClass@H@@2HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4
// GNU-DAG: @_ZN9TmplClassIiE26StaticClassVarExpTmplClassE = weak_odr dso_local dllexport global i32 0, comdat, align 4
template<typename T>
struct __declspec(dllexport) TmplClass
@@ -574,7 +588,7 @@
T TmplClass<T>::StaticClassVarExpTmplClass;
// Export a definition of a template function.
-// MSC-DAG: define weak_odr dso_local dllexport i32 @"\01??$TypeFunTmpl@H@@YAHH@Z"
+// MSC-DAG: define weak_odr dso_local dllexport i32 @"??$TypeFunTmpl@H@@YAHH@Z"
// GNU-DAG: define weak_odr dso_local dllexport i32 @_Z11TypeFunTmplIiET_S0_
template<typename T>
T __declspec(dllexport) TypeFunTmpl(T t) { return t + t; }
@@ -588,38 +602,38 @@
template <typename T> struct __declspec(dllexport) U { void foo() {} };
struct __declspec(dllexport) V : public U<int> { };
// U<int>'s assignment operator is emitted.
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.U* @"\01??4?$U@H@@QAEAAU0@ABU0@@Z"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.U* @"??4?$U@H@@QAEAAU0@ABU0@@Z"
struct __declspec(dllexport) W { virtual void foo(); };
void W::foo() {}
// Default ctor:
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.W* @"??0W@@QAE@XZ"
// Copy ctor:
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@ABU0@@Z"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.W* @"??0W@@QAE@ABU0@@Z"
// vftable:
-// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i8*), i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] }, comdat($"\01??_7W@@6B@")
-// M32-DAG: @"\01??_7W@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[W_VTABLE]], i32 0, i32 0, i32 1)
+// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4W@@6B@" to i8*), i8* bitcast (void (%struct.W*)* @"?foo@W@@UAEXXZ" to i8*)] }, comdat($"??_7W@@6B@")
+// M32-DAG: @"??_7W@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[W_VTABLE]], i32 0, i32 0, i32 1)
// G32-DAG: @_ZTV1W = dso_local dllexport unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1W to i8*), i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] }
struct __declspec(dllexport) X : public virtual W {};
// vbtable:
-// M32-DAG: @"\01??_8X@@7B@" = weak_odr dllexport unnamed_addr constant [2 x i32] [i32 0, i32 4]
+// M32-DAG: @"??_8X@@7B@" = weak_odr dllexport unnamed_addr constant [2 x i32] [i32 0, i32 4]
struct __declspec(dllexport) Y {
// Move assignment operator:
- // MSVC2015-DAG: define weak_odr dso_local dllexport {{.+}} @"\01??4Y@@Q{{.+}}@$$Q{{.+}}@@Z"
- // MSVC2013-DAG: define weak_odr dso_local dllexport {{.+}} @"\01??4Y@@Q{{.+}}0@A{{.+}}0@@Z"
+ // MSVC2015-DAG: define weak_odr dso_local dllexport {{.+}} @"??4Y@@Q{{.+}}@$$Q{{.+}}@@Z"
+ // MSVC2013-DAG: define weak_odr dso_local dllexport {{.+}} @"??4Y@@Q{{.+}}0@A{{.+}}0@@Z"
int x;
};
struct __declspec(dllexport) Z { virtual ~Z() {} };
// The scalar deleting dtor does not get exported:
-// M32-DAG: define linkonce_odr dso_local x86_thiscallcc i8* @"\01??_GZ@@UAEPAXI@Z"
+// M32-DAG: define linkonce_odr dso_local x86_thiscallcc i8* @"??_GZ@@UAEPAXI@Z"
// The user-defined dtor does get exported:
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??1Z@@UAE@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??1Z@@UAE@XZ"
namespace UseDtorAlias {
struct __declspec(dllexport) A { ~A(); };
@@ -627,39 +641,39 @@
A::~A() { }
B::~B() { }
// Emit a alias definition of B's constructor.
- // M32-DAG: @"\01??1B@UseDtorAlias@@QAE@XZ" = dso_local dllexport alias {{.*}} @"\01??1A@UseDtorAlias@@QAE@XZ"
+ // M32-DAG: @"??1B@UseDtorAlias@@QAE@XZ" = dso_local dllexport alias {{.*}} @"??1A@UseDtorAlias@@QAE@XZ"
}
struct __declspec(dllexport) DefaultedCtorsDtors {
DefaultedCtorsDtors() = default;
- // M32MSVC2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.DefaultedCtorsDtors* @"\01??0DefaultedCtorsDtors@@QAE@XZ"
+ // M32MSVC2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.DefaultedCtorsDtors* @"??0DefaultedCtorsDtors@@QAE@XZ"
~DefaultedCtorsDtors() = default;
- // M32MSVC2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??1DefaultedCtorsDtors@@QAE@XZ"
+ // M32MSVC2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??1DefaultedCtorsDtors@@QAE@XZ"
};
// Export defaulted member function definitions declared inside class.
struct __declspec(dllexport) ExportDefaultedInclassDefs {
ExportDefaultedInclassDefs() = default;
- // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
- // M64VS2013-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
- // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
- // M64VS2015-NOT: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M64VS2013-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M64VS2015-NOT: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
~ExportDefaultedInclassDefs() = default;
- // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
- // M64VS2013-DAG: define weak_odr dso_local dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
- // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
- // M64VS2015-NOT: define weak_odr dso_local dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M64VS2013-DAG: define weak_odr dso_local dllexport void @"??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc void @"??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M64VS2015-NOT: define weak_odr dso_local dllexport void @"??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this)
ExportDefaultedInclassDefs(const ExportDefaultedInclassDefs&) = default;
- // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M64VS2013-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M64VS2015-NOT: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32VS2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64VS2013-DAG: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32VS2015-NOT: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64VS2015-NOT: define weak_odr dso_local dllexport %struct.ExportDefaultedInclassDefs* @"??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
ExportDefaultedInclassDefs& operator=(const ExportDefaultedInclassDefs&) = default;
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
- // M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"??4ExportDefaultedInclassDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"??4ExportDefaultedInclassDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
};
namespace ReferencedInlineMethodInNestedClass {
@@ -672,8 +686,8 @@
};
T *t;
};
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?foo@S@ReferencedInlineMethodInNestedClass@@QAEXXZ"
- // M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"\01?bar@T@S@ReferencedInlineMethodInNestedClass@@QAEXXZ"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?foo@S@ReferencedInlineMethodInNestedClass@@QAEXXZ"
+ // M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?bar@T@S@ReferencedInlineMethodInNestedClass@@QAEXXZ"
}
// MS ignores DLL attributes on partial specializations.
@@ -681,7 +695,7 @@
template <typename T> struct __declspec(dllexport) PartiallySpecializedClassTemplate<T*> { void f(); };
template <typename T> void PartiallySpecializedClassTemplate<T*>::f() {}
USEMEMFUNC(PartiallySpecializedClassTemplate<void*>, f);
-// M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"\01?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ"
+// M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ"
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN33PartiallySpecializedClassTemplateIPvE1fEv
// Attributes on explicit specializations are honored.
@@ -689,14 +703,14 @@
template <> struct __declspec(dllexport) ExplicitlySpecializedClassTemplate<void*> { void f(); };
void ExplicitlySpecializedClassTemplate<void*>::f() {}
USEMEMFUNC(ExplicitlySpecializedClassTemplate<void*>, f);
-// M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ"
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ"
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv
// MS inherits DLL attributes to partial specializations.
template <typename T> struct __declspec(dllexport) PartiallySpecializedExportedClassTemplate {};
template <typename T> struct PartiallySpecializedExportedClassTemplate<T*> { void f() {} };
USEMEMFUNC(PartiallySpecializedExportedClassTemplate<void*>, f);
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?f@?$PartiallySpecializedExportedClassTemplate@PAX@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$PartiallySpecializedExportedClassTemplate@PAX@@QAEXXZ"
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN41PartiallySpecializedExportedClassTemplateIPvE1fEv
// MS ignores DLL attributes on partial specializations; inheritance still works though.
@@ -704,14 +718,14 @@
template <typename T> struct __declspec(dllimport) PartiallySpecializedExportedClassTemplate2<T*> { void f(); };
template <typename T> void PartiallySpecializedExportedClassTemplate2<T*>::f() {}
USEMEMFUNC(PartiallySpecializedExportedClassTemplate2<void*>, f);
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?f@?$PartiallySpecializedExportedClassTemplate2@PAX@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$PartiallySpecializedExportedClassTemplate2@PAX@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN42PartiallySpecializedExportedClassTemplate2IPvE1fEv
// Attributes on the instantiation take precedence over attributes on the template.
template <typename T> struct __declspec(dllimport) ExplicitlyInstantiatedWithDifferentAttr { void f() {} };
template struct __declspec(dllexport) ExplicitlyInstantiatedWithDifferentAttr<int>;
USEMEMFUNC(ExplicitlyInstantiatedWithDifferentAttr<int>, f);
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ"
// Don't create weak dllexport aliases. (PR21373)
struct NonExportedBaseClass {
@@ -720,61 +734,61 @@
NonExportedBaseClass::~NonExportedBaseClass() {}
struct __declspec(dllexport) ExportedDerivedClass : NonExportedBaseClass {};
-// M32-DAG: weak_odr dso_local dllexport x86_thiscallcc void @"\01??1ExportedDerivedClass@@UAE@XZ"
+// M32-DAG: weak_odr dso_local dllexport x86_thiscallcc void @"??1ExportedDerivedClass@@UAE@XZ"
// Do not assert about generating code for constexpr functions twice during explicit instantiation (PR21718).
template <typename T> struct ExplicitInstConstexprMembers {
// Copy assignment operator
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable(1) %struct.ExplicitInstConstexprMembers* @"\01??4?$ExplicitInstConstexprMembers@X@@QAEAAU0@ABU0@@Z"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable(1) %struct.ExplicitInstConstexprMembers* @"??4?$ExplicitInstConstexprMembers@X@@QAEAAU0@ABU0@@Z"
constexpr ExplicitInstConstexprMembers() {}
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"\01??0?$ExplicitInstConstexprMembers@X@@QAE@XZ"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"??0?$ExplicitInstConstexprMembers@X@@QAE@XZ"
ExplicitInstConstexprMembers(const ExplicitInstConstexprMembers&) = default;
- // M32MSVC2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"\01??0?$ExplicitInstConstexprMembers@X@@QAE@ABU0@@Z"
+ // M32MSVC2013-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"??0?$ExplicitInstConstexprMembers@X@@QAE@ABU0@@Z"
constexpr int f() const { return 42; }
- // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc i32 @"\01?f@?$ExplicitInstConstexprMembers@X@@QBEHXZ"
+ // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc i32 @"?f@?$ExplicitInstConstexprMembers@X@@QBEHXZ"
};
template struct __declspec(dllexport) ExplicitInstConstexprMembers<void>;
template <typename T> struct ExplicitInstantiationDeclTemplate { void f() {} };
extern template struct __declspec(dllexport) ExplicitInstantiationDeclTemplate<int>;
USEMEMFUNC(ExplicitInstantiationDeclTemplate<int>, f);
-// M32-DAG: {{declare|define available_externally}} dso_local x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclTemplate@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dso_local x86_thiscallcc void @"?f@?$ExplicitInstantiationDeclTemplate@H@@QAEXXZ"
template <typename T> struct __declspec(dllexport) ExplicitInstantiationDeclExportedTemplate { void f() {} };
extern template struct ExplicitInstantiationDeclExportedTemplate<int>;
USEMEMFUNC(ExplicitInstantiationDeclExportedTemplate<int>, f);
-// M32-DAG: {{declare|define available_externally}} dso_local x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedTemplate@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dso_local x86_thiscallcc void @"?f@?$ExplicitInstantiationDeclExportedTemplate@H@@QAEXXZ"
template <typename T> struct ExplicitInstantiationDeclExportedDefTemplate { void f() {} ExplicitInstantiationDeclExportedDefTemplate() {} };
extern template struct ExplicitInstantiationDeclExportedDefTemplate<int>;
template struct __declspec(dllexport) ExplicitInstantiationDeclExportedDefTemplate<int>;
USEMEMFUNC(ExplicitInstantiationDeclExportedDefTemplate<int>, f);
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAEXXZ"
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefTemplate* @"\01??0?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAE@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefTemplate* @"??0?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAE@XZ"
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN44ExplicitInstantiationDeclExportedDefTemplateIiE1fEv
template <typename T> struct ImplicitInstantiationExportedExplicitInstantiationDefTemplate { virtual void f() {} };
ImplicitInstantiationExportedExplicitInstantiationDefTemplate<int> ImplicitInstantiationExportedExplicitInstantiationDefTemplateInstance;
template struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefTemplate<int>;
USEMEMFUNC(ImplicitInstantiationExportedExplicitInstantiationDefTemplate<int>, f);
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExportedExplicitInstantiationDefTemplate@H@@UAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$ImplicitInstantiationExportedExplicitInstantiationDefTemplate@H@@UAEXXZ"
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN61ImplicitInstantiationExportedExplicitInstantiationDefTemplateIiE1fEv
template <typename T> struct __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate { virtual void f() {} };
ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExplicitInstantiationDefExportedTemplateInstance;
template struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>;
USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>, f);
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefExportedTemplate@H@@UAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$ImplicitInstantiationExplicitInstantiationDefExportedTemplate@H@@UAEXXZ"
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN61ImplicitInstantiationExplicitInstantiationDefExportedTemplateIiE1fEv
template <typename T> struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate { virtual void f() {} };
ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplateInstance;
template struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate<int>;
USEMEMFUNC(ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate<int>, f);
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate@H@@UAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate@H@@UAEXXZ"
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN69ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplateIiE1fEv
namespace { struct InternalLinkageType {}; }
@@ -783,20 +797,20 @@
};
void PR23308::f(InternalLinkageType*) {}
long use(PR23308* p) { p->f(nullptr); }
-// M32-DAG: define internal x86_thiscallcc void @"\01?f@PR23308@@QAEXPAUInternalLinkageType@?A@@@Z"
+// M32-DAG: define internal x86_thiscallcc void @"?f@PR23308@@QAEXPAUInternalLinkageType@?A@@@Z"
template <typename T> struct PR23770BaseTemplate { void f() {} };
template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {};
extern template struct PR23770DerivedTemplate<int>;
template struct __declspec(dllexport) PR23770DerivedTemplate<int>;
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?f@?$PR23770BaseTemplate@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$PR23770BaseTemplate@H@@QAEXXZ"
namespace InClassInits {
struct __declspec(dllexport) S {
int x = 42;
};
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::S"* @"\01??0S@InClassInits@@QAE@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::S"* @"??0S@InClassInits@@QAE@XZ"
// dllexport an already instantiated class template.
template <typename T> struct Base {
@@ -804,7 +818,7 @@
};
Base<int> base;
struct __declspec(dllexport) T : Base<int> { };
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::Base"* @"\01??0?$Base@H@InClassInits@@QAE@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::Base"* @"??0?$Base@H@InClassInits@@QAE@XZ"
struct A { A(int); };
struct __declspec(dllexport) U {
@@ -812,7 +826,7 @@
U(A = 0) {}
int x = 0;
};
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::U"* @"\01??0U@InClassInits@@QAE@UA@1@@Z"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::U"* @"??0U@InClassInits@@QAE@UA@1@@Z"
struct Evil {
template <typename T> struct Base {
@@ -824,7 +838,7 @@
// the default ctor must still be delayed.
struct __declspec(dllexport) T : Base<int> {};
};
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::Evil::Base"* @"\01??0?$Base@H@Evil@InClassInits@@QAE@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::Evil::Base"* @"??0?$Base@H@Evil@InClassInits@@QAE@XZ"
template <typename T> struct Foo {};
template <typename T> struct Bar {
@@ -836,7 +850,7 @@
// After parsing Baz, in ActOnFinishCXXNonNestedClass we would synthesize
// Baz's operator=, causing instantiation of Foo<int> after which
// ActOnFinishCXXNonNestedClass is called, and we would bite our own tail.
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable(1) %"struct.InClassInits::Baz"* @"\01??4Baz@InClassInits@@QAEAAU01@ABU01@@Z"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable(1) %"struct.InClassInits::Baz"* @"??4Baz@InClassInits@@QAEAAU01@ABU01@@Z"
}
// We had an issue where instantiating A would force emission of B's delayed
@@ -847,28 +861,28 @@
B(int = 0) {}
A<int> m_fn1() {}
};
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FB@pr26490@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FB@pr26490@@QAEXXZ"
}
// dllexport trumps dllimport on an explicit instantiation.
template <typename T> struct ExplicitInstantiationTwoAttributes { void f() {} };
template struct __declspec(dllexport) __declspec(dllimport) ExplicitInstantiationTwoAttributes<int>;
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationTwoAttributes@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?f@?$ExplicitInstantiationTwoAttributes@H@@QAEXXZ"
namespace pr34849 {
// Specializations of exported class template member functions get exported.
template <typename> struct __declspec(dllexport) ExportedClassTemplate { void foo(); };
template<> void ExportedClassTemplate<int>::foo() {}
template struct ExportedClassTemplate<int>;
-// M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?foo@?$ExportedClassTemplate@H@pr34849@@QAEXXZ"
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"?foo@?$ExportedClassTemplate@H@pr34849@@QAEXXZ"
// Specializations of exported class member template functions do not get exported.
struct __declspec(dllexport) ExportedClass { template <typename> void bar() ; };
template<> void ExportedClass::bar<int>() {}
-// M32-DAG: define dso_local x86_thiscallcc void @"\01??$bar@H@ExportedClass@pr34849@@QAEXXZ"
+// M32-DAG: define dso_local x86_thiscallcc void @"??$bar@H@ExportedClass@pr34849@@QAEXXZ"
template <typename> struct __declspec(dllexport) ExportedClassTemplate2 { template <typename> void baz(); };
template<> template<> void ExportedClassTemplate2<int>::baz<int>() {}
-// M32-DAG: define dso_local x86_thiscallcc void @"\01??$baz@H@?$ExportedClassTemplate2@H@pr34849@@QAEXXZ"
+// M32-DAG: define dso_local x86_thiscallcc void @"??$baz@H@?$ExportedClassTemplate2@H@pr34849@@QAEXXZ"
}
//===----------------------------------------------------------------------===//
@@ -904,69 +918,69 @@
// MS: ClassTemplate<int> gets exported.
struct __declspec(dllexport) DerivedFromTemplate : public ClassTemplate<int> {};
USEMEMFUNC(DerivedFromTemplate, func)
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ClassTemplate@H@@QAEXXZ"
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv
// ExportedTemplate is explicitly exported.
struct __declspec(dllexport) DerivedFromExportedTemplate : public ExportedClassTemplate<int> {};
USEMEMFUNC(DerivedFromExportedTemplate, func)
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?func@?$ExportedClassTemplate@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ExportedClassTemplate@H@@QAEXXZ"
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv
// ImportedClassTemplate is explicitly imported.
struct __declspec(dllexport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {};
USEMEMFUNC(DerivedFromImportedTemplate, func)
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?func@?$ImportedClassTemplate@H@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN21ImportedClassTemplateIiE4funcEv
// Base class already implicitly instantiated without dll attribute.
struct DerivedFromTemplateD : public ClassTemplate<double> {};
struct __declspec(dllexport) DerivedFromTemplateD2 : public ClassTemplate<double> {};
USEMEMFUNC(DerivedFromTemplateD2, func)
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ClassTemplate@N@@QAEXXZ"
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv
// MS: Base class already instantiated with different dll attribute.
struct __declspec(dllimport) DerivedFromTemplateB : public ClassTemplate<bool> {};
struct __declspec(dllexport) DerivedFromTemplateB2 : public ClassTemplate<bool> {};
USEMEMFUNC(DerivedFromTemplateB2, func)
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@_N@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?func@?$ClassTemplate@_N@@QAEXXZ"
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv
// Base class already specialized without dll attribute.
struct __declspec(dllexport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate<int> {};
USEMEMFUNC(DerivedFromExplicitlySpecializedTemplate, func)
-// M32-DAG: define dso_local x86_thiscallcc void @"\01?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ"
+// M32-DAG: define dso_local x86_thiscallcc void @"?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ"
// G32-DAG: define dso_local x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv
// Base class alredy specialized with export attribute.
struct __declspec(dllexport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate<int> {};
USEMEMFUNC(DerivedFromExplicitlyExportSpecializedTemplate, func)
-// M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ"
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ"
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv
// Base class already specialized with import attribute.
struct __declspec(dllexport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {};
USEMEMFUNC(DerivedFromExplicitlyImportSpecializedTemplate, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv
// Base class already instantiated without dll attribute.
struct __declspec(dllexport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {};
USEMEMFUNC(DerivedFromExplicitlyInstantiatedTemplate, func)
-// M32-DAG: define weak_odr dso_local x86_thiscallcc void @"\01?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local x86_thiscallcc void @"?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ"
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv
// Base class already instantiated with export attribute.
struct __declspec(dllexport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate<int> {};
USEMEMFUNC(DerivedFromExplicitlyExportInstantiatedTemplate, func)
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ"
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv
// Base class already instantiated with import attribute.
struct __declspec(dllexport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {};
USEMEMFUNC(DerivedFromExplicitlyImportInstantiatedTemplate, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv
// MS: A dll attribute propagates through multiple levels of instantiation.
@@ -974,14 +988,14 @@
template <typename T> struct MiddleClass : public TopClass<T> { };
struct __declspec(dllexport) BottomClass : public MiddleClass<int> { };
USEMEMFUNC(BottomClass, func)
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?func@?$TopClass@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$TopClass@H@@QAEXXZ"
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN8TopClassIiE4funcEv
template <typename T> struct ExplicitInstantiationDeclTemplateBase { void func() {} };
extern template struct ExplicitInstantiationDeclTemplateBase<int>;
struct __declspec(dllexport) DerivedFromExplicitInstantiationDeclTemplateBase : public ExplicitInstantiationDeclTemplateBase<int> {};
template struct ExplicitInstantiationDeclTemplateBase<int>;
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ"
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN37ExplicitInstantiationDeclTemplateBaseIiE4funcEv
// PR26076
@@ -995,8 +1009,8 @@
};
LayerSelection foo;
};
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.LayerTreeImpl::ElementLayers"* @"\01??0ElementLayers@LayerTreeImpl@@QAE@XZ"
-// M64-DAG: define weak_odr dso_local dllexport %"struct.LayerTreeImpl::ElementLayers"* @"\01??0ElementLayers@LayerTreeImpl@@QEAA@XZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.LayerTreeImpl::ElementLayers"* @"??0ElementLayers@LayerTreeImpl@@QAE@XZ"
+// M64-DAG: define weak_odr dso_local dllexport %"struct.LayerTreeImpl::ElementLayers"* @"??0ElementLayers@LayerTreeImpl@@QEAA@XZ"
class __declspec(dllexport) ACE_Shared_Object {
public:
diff --git a/test/CodeGenCXX/dllimport-dtor-thunks.cpp b/test/CodeGenCXX/dllimport-dtor-thunks.cpp
index a1ff34c..da3227a 100644
--- a/test/CodeGenCXX/dllimport-dtor-thunks.cpp
+++ b/test/CodeGenCXX/dllimport-dtor-thunks.cpp
@@ -1,9 +1,5 @@
// RUN: %clang_cc1 -mconstructor-aliases %s -triple x86_64-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s
-// FIXME: We should really consider removing -mconstructor-aliases for MS C++
-// ABI. The risk of bugs introducing ABI incompatibility under
-// -mno-constructor-aliases is too high.
-
// PR32990
// Introduces the virtual destructor. We should use the base destructor
@@ -40,10 +36,10 @@
// The destructors are called in reverse order of construction. Only the third
// needs the complete destructor (_D).
// CHECK-LABEL: define dso_local void @testit()
-// CHECK: call void @"\01??_DImportVBaseOverrideVDtor@@QEAAXXZ"(%struct.ImportVBaseOverrideVDtor* %{{.*}})
-// CHECK: call void @"\01??1ImportOverrideVDtor@@UEAA@XZ"(%struct.ImportOverrideVDtor* %{{.*}})
-// CHECK: call void @"\01??1ImportIntroVDtor@@UEAA@XZ"(%struct.ImportIntroVDtor* %{{.*}})
+// CHECK: call void @"??_DImportVBaseOverrideVDtor@@QEAAXXZ"(%struct.ImportVBaseOverrideVDtor* %{{.*}})
+// CHECK: call void @"??1ImportOverrideVDtor@@UEAA@XZ"(%struct.ImportOverrideVDtor* %{{.*}})
+// CHECK: call void @"??1ImportIntroVDtor@@UEAA@XZ"(%struct.ImportIntroVDtor* %{{.*}})
-// CHECK-LABEL: define linkonce_odr dso_local void @"\01??_DImportVBaseOverrideVDtor@@QEAAXXZ"
-// CHECK-LABEL: declare dllimport void @"\01??1ImportOverrideVDtor@@UEAA@XZ"
-// CHECK-LABEL: declare dllimport void @"\01??1ImportIntroVDtor@@UEAA@XZ"
+// CHECK-LABEL: declare dllimport void @"??_DImportVBaseOverrideVDtor@@QEAAXXZ"
+// CHECK-LABEL: declare dllimport void @"??1ImportOverrideVDtor@@UEAA@XZ"
+// CHECK-LABEL: declare dllimport void @"??1ImportIntroVDtor@@UEAA@XZ"
diff --git a/test/CodeGenCXX/dllimport-members.cpp b/test/CodeGenCXX/dllimport-members.cpp
index c0986d5..7a7519f 100644
--- a/test/CodeGenCXX/dllimport-members.cpp
+++ b/test/CodeGenCXX/dllimport-members.cpp
@@ -63,16 +63,16 @@
struct ImportMembers {
struct Nested;
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?normalDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers* %this)
- // M64-DAG: define dso_local dllexport void @"\01?normalDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers* %this)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?normalDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?normalInclass@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?normalInlineDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?normalInlineDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?normalDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers* %this)
+ // M64-DAG: define dso_local dllexport void @"?normalDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?normalDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalInclass@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?normalInclass@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalInlineDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?normalInlineDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalInlineDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?normalInlineDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
// G32-DAG: define dso_local x86_thiscallcc void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this)
// G64-DAG: define dso_local void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*)
@@ -83,9 +83,9 @@
// G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers* %this)
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers* %this)
// G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDef@ImportMembers@@QAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDecl@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?normalInclass@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?normalInlineDef@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?normalInlineDecl@ImportMembers@@QAEXXZ"(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv(
@@ -95,16 +95,16 @@
__declspec(dllimport) void normalInlineDef();
__declspec(dllimport) inline void normalInlineDecl();
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?virtualDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers* %this)
- // M64-DAG: define dso_local dllexport void @"\01?virtualDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers* %this)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?virtualDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?virtualInclass@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?virtualInlineDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?virtualInlineDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?virtualDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers* %this)
+ // M64-DAG: define dso_local dllexport void @"?virtualDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?virtualDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualInclass@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?virtualInclass@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualInlineDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?virtualInlineDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualInlineDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?virtualInlineDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
// G32-DAG: define dso_local x86_thiscallcc void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this)
// G64-DAG: define dso_local void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers11virtualDeclEv(%struct.ImportMembers*)
@@ -115,9 +115,9 @@
// G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers* %this)
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers* %this)
// G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDef@ImportMembers@@UAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDecl@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?virtualInclass@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?virtualInlineDef@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?virtualInlineDecl@ImportMembers@@UAEXXZ"(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv(
@@ -127,19 +127,19 @@
__declspec(dllimport) virtual void virtualInlineDef();
__declspec(dllimport) virtual inline void virtualInlineDecl();
- // MSC-DAG: define dso_local dllexport void @"\01?staticDef@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticDecl@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticInclass@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticInlineDecl@ImportMembers@@SAXXZ"()
+ // MSC-DAG: define dso_local dllexport void @"?staticDef@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticDecl@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticInclass@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticInlineDef@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticInlineDecl@ImportMembers@@SAXXZ"()
// GNU-DAG: define dso_local void @_ZN13ImportMembers9staticDefEv()
// GNU-DAG: declare dllimport void @_ZN13ImportMembers10staticDeclEv()
// GNU-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers13staticInclassEv()
// GNU-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers15staticInlineDefEv()
// GNU-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers16staticInlineDeclEv()
- // MO1-DAG: define available_externally dllimport void @"\01?staticInclass@ImportMembers@@SAXXZ"()
- // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"()
- // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDecl@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"?staticInclass@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"?staticInlineDef@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"?staticInlineDecl@ImportMembers@@SAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers13staticInclassEv()
// GO1-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers15staticInlineDefEv()
// GO1-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers16staticInlineDeclEv()
@@ -149,38 +149,38 @@
__declspec(dllimport) static void staticInlineDef();
__declspec(dllimport) static inline void staticInlineDecl();
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?protectedNormalDecl@ImportMembers@@IAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?protectedNormalDecl@ImportMembers@@IEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?protectedNormalDecl@ImportMembers@@IAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?protectedNormalDecl@ImportMembers@@IEAAXXZ"(%struct.ImportMembers*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers19protectedNormalDeclEv(%struct.ImportMembers*)
// G64-DAG: declare dllimport void @_ZN13ImportMembers19protectedNormalDeclEv(%struct.ImportMembers*)
- // MSC-DAG: declare dllimport void @"\01?protectedStaticDecl@ImportMembers@@KAXXZ"()
+ // MSC-DAG: declare dllimport void @"?protectedStaticDecl@ImportMembers@@KAXXZ"()
// GNU-DAG: declare dllimport void @_ZN13ImportMembers19protectedStaticDeclEv()
protected:
__declspec(dllimport) void protectedNormalDecl();
__declspec(dllimport) static void protectedStaticDecl();
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?privateNormalDecl@ImportMembers@@AAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dllimport void @"\01?privateNormalDecl@ImportMembers@@AEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?privateNormalDecl@ImportMembers@@AAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"?privateNormalDecl@ImportMembers@@AEAAXXZ"(%struct.ImportMembers*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers17privateNormalDeclEv(%struct.ImportMembers*)
// G64-DAG: declare dllimport void @_ZN13ImportMembers17privateNormalDeclEv(%struct.ImportMembers*)
- // MSC-DAG: declare dllimport void @"\01?privateStaticDecl@ImportMembers@@CAXXZ"()
+ // MSC-DAG: declare dllimport void @"?privateStaticDecl@ImportMembers@@CAXXZ"()
// GNU-DAG: declare dllimport void @_ZN13ImportMembers17privateStaticDeclEv()
private:
__declspec(dllimport) void privateNormalDecl();
__declspec(dllimport) static void privateStaticDecl();
- // M32-DAG: declare dso_local x86_thiscallcc void @"\01?ignored@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
- // M64-DAG: declare dso_local void @"\01?ignored@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dso_local x86_thiscallcc void @"?ignored@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dso_local void @"?ignored@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
// G32-DAG: declare dso_local x86_thiscallcc void @_ZN13ImportMembers7ignoredEv(%struct.ImportMembers*)
// G64-DAG: declare dso_local void @_ZN13ImportMembers7ignoredEv(%struct.ImportMembers*)
public:
void ignored();
- // MSC-DAG: @"\01?StaticField@ImportMembers@@2HA" = external dllimport global i32
- // MSC-DAG: @"\01?StaticConstField@ImportMembers@@2HB" = external dllimport constant i32
- // MSC-DAG: @"\01?StaticConstFieldEqualInit@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
- // MSC-DAG: @"\01?StaticConstFieldBraceInit@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
- // MSC-DAG: @"\01?ConstexprField@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"?StaticField@ImportMembers@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?StaticConstField@ImportMembers@@2HB" = external dllimport constant i32
+ // MSC-DAG: @"?StaticConstFieldEqualInit@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"?StaticConstFieldBraceInit@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"?ConstexprField@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
// GNU-DAG: @_ZN13ImportMembers11StaticFieldE = external dllimport global i32
// GNU-DAG: @_ZN13ImportMembers16StaticConstFieldE = external dllimport constant i32
// GNU-DAG: @_ZN13ImportMembers25StaticConstFieldEqualInitE = external dllimport constant i32
@@ -235,16 +235,16 @@
// Import individual members of a nested class.
struct ImportMembers::Nested {
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?normalDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"* %this)
- // M64-DAG: define dso_local dllexport void @"\01?normalDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"* %this)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?normalDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?normalInclass@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?normalInlineDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?normalInlineDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?normalDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"* %this)
+ // M64-DAG: define dso_local dllexport void @"?normalDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?normalDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalInclass@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?normalInclass@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?normalInlineDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?normalInlineDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
// G32-DAG: define dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this)
// G64-DAG: define dso_local void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested10normalDeclEv(%"struct.ImportMembers::Nested"*)
@@ -255,9 +255,9 @@
// G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"* %this)
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"* %this)
// G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInclass@Nested@ImportMembers@@QAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?normalInclass@Nested@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv(
@@ -267,16 +267,16 @@
__declspec(dllimport) void normalInlineDef();
__declspec(dllimport) inline void normalInlineDecl();
- // M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?virtualDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"* %this)
- // M64-DAG: define dso_local dllexport void @"\01?virtualDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"* %this)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?virtualDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?virtualInclass@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?virtualInlineDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?virtualInlineDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: define dso_local dllexport x86_thiscallcc void @"?virtualDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"* %this)
+ // M64-DAG: define dso_local dllexport void @"?virtualDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?virtualDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualInclass@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?virtualInclass@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?virtualInlineDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?virtualInlineDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
// G32-DAG: define dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this)
// G64-DAG: define dso_local void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested11virtualDeclEv(%"struct.ImportMembers::Nested"*)
@@ -288,9 +288,9 @@
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"* %this)
// G64-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInclass@Nested@ImportMembers@@UAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?virtualInclass@Nested@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(
@@ -300,19 +300,19 @@
__declspec(dllimport) virtual void virtualInlineDef();
__declspec(dllimport) virtual inline void virtualInlineDecl();
- // MSC-DAG: define dso_local dllexport void @"\01?staticDef@Nested@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticDecl@Nested@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticInclass@Nested@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"()
- // MSC-DAG: declare dllimport void @"\01?staticInlineDecl@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: define dso_local dllexport void @"?staticDef@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticDecl@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticInclass@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticInlineDef@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?staticInlineDecl@Nested@ImportMembers@@SAXXZ"()
// GNU-DAG: define dso_local void @_ZN13ImportMembers6Nested9staticDefEv()
// GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested10staticDeclEv()
// GNU-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested13staticInclassEv()
// GNU-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested15staticInlineDefEv()
// GNU-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested16staticInlineDeclEv()
- // MO1-DAG: define available_externally dllimport void @"\01?staticInclass@Nested@ImportMembers@@SAXXZ"()
- // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"()
- // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDecl@Nested@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"?staticInclass@Nested@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"?staticInlineDef@Nested@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"?staticInlineDecl@Nested@ImportMembers@@SAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested13staticInclassEv()
// GO1-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested15staticInlineDefEv()
// GO1-DAG: define linkonce_odr dso_local void @_ZN13ImportMembers6Nested16staticInlineDeclEv()
@@ -322,38 +322,38 @@
__declspec(dllimport) static void staticInlineDef();
__declspec(dllimport) static inline void staticInlineDecl();
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?protectedNormalDecl@Nested@ImportMembers@@IAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?protectedNormalDecl@Nested@ImportMembers@@IEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?protectedNormalDecl@Nested@ImportMembers@@IAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?protectedNormalDecl@Nested@ImportMembers@@IEAAXXZ"(%"struct.ImportMembers::Nested"*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested19protectedNormalDeclEv(%"struct.ImportMembers::Nested"*)
// G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested19protectedNormalDeclEv(%"struct.ImportMembers::Nested"*)
- // MSC-DAG: declare dllimport void @"\01?protectedStaticDecl@Nested@ImportMembers@@KAXXZ"()
+ // MSC-DAG: declare dllimport void @"?protectedStaticDecl@Nested@ImportMembers@@KAXXZ"()
// GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested19protectedStaticDeclEv()
protected:
__declspec(dllimport) void protectedNormalDecl();
__declspec(dllimport) static void protectedStaticDecl();
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01?privateNormalDecl@Nested@ImportMembers@@AAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dllimport void @"\01?privateNormalDecl@Nested@ImportMembers@@AEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"?privateNormalDecl@Nested@ImportMembers@@AAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"?privateNormalDecl@Nested@ImportMembers@@AEAAXXZ"(%"struct.ImportMembers::Nested"*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested17privateNormalDeclEv(%"struct.ImportMembers::Nested"*)
// G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested17privateNormalDeclEv(%"struct.ImportMembers::Nested"*)
- // MSC-DAG: declare dllimport void @"\01?privateStaticDecl@Nested@ImportMembers@@CAXXZ"()
+ // MSC-DAG: declare dllimport void @"?privateStaticDecl@Nested@ImportMembers@@CAXXZ"()
// GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested17privateStaticDeclEv()
private:
__declspec(dllimport) void privateNormalDecl();
__declspec(dllimport) static void privateStaticDecl();
- // M32-DAG: declare dso_local x86_thiscallcc void @"\01?ignored@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
- // M64-DAG: declare dso_local void @"\01?ignored@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dso_local x86_thiscallcc void @"?ignored@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dso_local void @"?ignored@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
// G32-DAG: declare dso_local x86_thiscallcc void @_ZN13ImportMembers6Nested7ignoredEv(%"struct.ImportMembers::Nested"*)
// G64-DAG: declare dso_local void @_ZN13ImportMembers6Nested7ignoredEv(%"struct.ImportMembers::Nested"*)
public:
void ignored();
- // MSC-DAG: @"\01?StaticField@Nested@ImportMembers@@2HA" = external dllimport global i32
- // MSC-DAG: @"\01?StaticConstField@Nested@ImportMembers@@2HB" = external dllimport constant i32
- // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
- // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
- // MSC-DAG: @"\01?ConstexprField@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"?StaticField@Nested@ImportMembers@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?StaticConstField@Nested@ImportMembers@@2HB" = external dllimport constant i32
+ // MSC-DAG: @"?StaticConstFieldEqualInit@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"?StaticConstFieldBraceInit@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"?ConstexprField@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
// GNU-DAG: @_ZN13ImportMembers6Nested11StaticFieldE = external dllimport global i32
// GNU-DAG: @_ZN13ImportMembers6Nested16StaticConstFieldE = external dllimport constant i32
// GNU-DAG: @_ZN13ImportMembers6Nested25StaticConstFieldEqualInitE = external dllimport constant i32
@@ -408,38 +408,38 @@
// Import special member functions.
struct ImportSpecials {
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"\01??0ImportSpecials@@QAE@XZ"(%struct.ImportSpecials* returned)
- // M64-DAG: declare dllimport %struct.ImportSpecials* @"\01??0ImportSpecials@@QEAA@XZ"(%struct.ImportSpecials* returned)
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"??0ImportSpecials@@QAE@XZ"(%struct.ImportSpecials* returned)
+ // M64-DAG: declare dllimport %struct.ImportSpecials* @"??0ImportSpecials@@QEAA@XZ"(%struct.ImportSpecials* returned)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsC1Ev(%struct.ImportSpecials*)
// G64-DAG: declare dllimport void @_ZN14ImportSpecialsC1Ev(%struct.ImportSpecials*)
__declspec(dllimport) ImportSpecials();
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportSpecials@@QAE@XZ"(%struct.ImportSpecials*)
- // M64-DAG: declare dllimport void @"\01??1ImportSpecials@@QEAA@XZ"(%struct.ImportSpecials*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"??1ImportSpecials@@QAE@XZ"(%struct.ImportSpecials*)
+ // M64-DAG: declare dllimport void @"??1ImportSpecials@@QEAA@XZ"(%struct.ImportSpecials*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsD1Ev(%struct.ImportSpecials*)
// G64-DAG: declare dllimport void @_ZN14ImportSpecialsD1Ev(%struct.ImportSpecials*)
__declspec(dllimport) ~ImportSpecials();
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"\01??0ImportSpecials@@QAE@ABU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport %struct.ImportSpecials* @"\01??0ImportSpecials@@QEAA@AEBU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"??0ImportSpecials@@QAE@ABU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportSpecials* @"??0ImportSpecials@@QEAA@AEBU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsC1ERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: declare dllimport void @_ZN14ImportSpecialsC1ERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportSpecials(const ImportSpecials&);
- // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"??4ImportSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"??4ImportSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportSpecials& operator=(const ImportSpecials&);
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"\01??0ImportSpecials@@QAE@$$QAU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport %struct.ImportSpecials* @"\01??0ImportSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"??0ImportSpecials@@QAE@$$QAU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportSpecials* @"??0ImportSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsC1EOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: declare dllimport void @_ZN14ImportSpecialsC1EOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportSpecials(ImportSpecials&&);
- // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"??4ImportSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"??4ImportSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSEOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSEOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportSpecials& operator=(ImportSpecials&&);
@@ -449,51 +449,51 @@
// Export inline special member functions.
struct ImportInlineSpecials {
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials* returned)
- // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials* returned)
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials* returned)
+ // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials* returned)
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials* %this)
// G64-DAG: define linkonce_odr dso_local void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@XZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QAE@XZ"(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev(
__declspec(dllimport) ImportInlineSpecials() {}
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials*)
- // M64-DAG: declare dllimport void @"\01??1ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"??1ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials*)
+ // M64-DAG: declare dllimport void @"??1ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials*)
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials* %this)
// G64-DAG: define linkonce_odr dso_local void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1ImportInlineSpecials@@QAE@XZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"??1ImportInlineSpecials@@QAE@XZ"(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev(
__declspec(dllimport) ~ImportInlineSpecials() {}
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@ABU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@AEBU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QAE@ABU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QEAA@AEBU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: define linkonce_odr dso_local void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@ABU0@@Z"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QAE@ABU0@@Z"(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_(
__declspec(dllimport) inline ImportInlineSpecials(const ImportInlineSpecials&);
- // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"??4ImportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(
__declspec(dllimport) ImportInlineSpecials& operator=(const ImportInlineSpecials&);
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: define linkonce_odr dso_local void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_(
__declspec(dllimport) ImportInlineSpecials(ImportInlineSpecials&&) {}
- // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"??4ImportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
// G64-DAG: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(
__declspec(dllimport) ImportInlineSpecials& operator=(ImportInlineSpecials&&) { return *this; }
};
@@ -504,51 +504,51 @@
// Import defaulted member functions.
struct ImportDefaulted {
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned)
- // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted* returned)
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned)
+ // M64-DAG: declare dllimport %struct.ImportDefaulted* @"??0ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted* returned)
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this)
// G64-DAG: define linkonce_odr dso_local void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned %this)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned %this)
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this)
__declspec(dllimport) ImportDefaulted() = default;
- // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted*)
- // M64-DAG: declare dllimport void @"\01??1ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted*)
+ // M64-DAG: declare dllimport void @"??1ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted*)
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this)
// G64-DAG: define linkonce_odr dso_local void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this)
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* %this)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* %this)
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this)
__declspec(dllimport) ~ImportDefaulted() = default;
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@AEBU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportDefaulted* @"??0ImportDefaulted@@QEAA@AEBU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
// G64-DAG: define linkonce_odr dso_local void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportDefaulted(const ImportDefaulted&) = default;
- // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"??4ImportDefaulted@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
// G64-DAG: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportDefaulted& operator=(const ImportDefaulted&) = default;
- // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportDefaulted* @"??0ImportDefaulted@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
// G64-DAG: define linkonce_odr dso_local void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportDefaulted(ImportDefaulted&&) = default;
- // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"??4ImportDefaulted@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
// G64-DAG: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
- // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
// GO1-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
__declspec(dllimport) ImportDefaulted& operator=(ImportDefaulted&&) = default;
@@ -571,40 +571,40 @@
#ifdef MSABI
// For MinGW, the function will not be dllimport, and we cannot add the attribute now.
-// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs* returned)
-// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs* returned)
+// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"??0ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs* returned)
+// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"??0ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs* returned)
__declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs() = default;
#endif
#ifdef MSABI
// For MinGW, the function will not be dllimport, and we cannot add the attribute now.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs*)
-// M64-DAG: declare dllimport void @"\01??1ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??1ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs*)
+// M64-DAG: declare dllimport void @"??1ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs*)
__declspec(dllimport) ImportDefaultedDefs::~ImportDefaultedDefs() = default;
#endif
-// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"??0ImportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"??0ImportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define linkonce_odr dso_local void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
inline ImportDefaultedDefs::ImportDefaultedDefs(const ImportDefaultedDefs&) = default;
-// M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"??4ImportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"??4ImportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
inline ImportDefaultedDefs& ImportDefaultedDefs::operator=(const ImportDefaultedDefs&) = default;
-// M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: define dso_local dllexport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: define dso_local dllexport x86_thiscallcc %struct.ImportDefaultedDefs* @"??0ImportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define dso_local dllexport %struct.ImportDefaultedDefs* @"??0ImportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define dso_local x86_thiscallcc void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define dso_local void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define dso_local x86_thiscallcc void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define dso_local void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
ImportDefaultedDefs::ImportDefaultedDefs(ImportDefaultedDefs&&) = default; // dllimport ignored
-// M32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
-// M64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M32-DAG: define dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"??4ImportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define dso_local dllexport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"??4ImportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define dso_local dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
ImportDefaultedDefs& ImportDefaultedDefs::operator=(ImportDefaultedDefs&&) = default; // dllimport ignored
@@ -620,26 +620,26 @@
__declspec(dllimport) void operator delete[](void*);
};
-// M32-DAG: declare dllimport i8* @"\01??2ImportAlloc@@SAPAXI@Z"(i32)
-// M64-DAG: declare dllimport i8* @"\01??2ImportAlloc@@SAPEAX_K@Z"(i64)
+// M32-DAG: declare dllimport i8* @"??2ImportAlloc@@SAPAXI@Z"(i32)
+// M64-DAG: declare dllimport i8* @"??2ImportAlloc@@SAPEAX_K@Z"(i64)
// G32-DAG: declare dllimport i8* @_ZN11ImportAllocnwEj(i32)
// G64-DAG: declare dllimport i8* @_ZN11ImportAllocnwEy(i64)
void UNIQ(use)() { new ImportAlloc(); }
-// M32-DAG: declare dllimport i8* @"\01??_UImportAlloc@@SAPAXI@Z"(i32)
-// M64-DAG: declare dllimport i8* @"\01??_UImportAlloc@@SAPEAX_K@Z"(i64)
+// M32-DAG: declare dllimport i8* @"??_UImportAlloc@@SAPAXI@Z"(i32)
+// M64-DAG: declare dllimport i8* @"??_UImportAlloc@@SAPEAX_K@Z"(i64)
// G32-DAG: declare dllimport i8* @_ZN11ImportAllocnaEj(i32)
// G64-DAG: declare dllimport i8* @_ZN11ImportAllocnaEy(i64)
void UNIQ(use)() { new ImportAlloc[1]; }
-// M32-DAG: declare dllimport void @"\01??3ImportAlloc@@SAXPAX@Z"(i8*)
-// M64-DAG: declare dllimport void @"\01??3ImportAlloc@@SAXPEAX@Z"(i8*)
+// M32-DAG: declare dllimport void @"??3ImportAlloc@@SAXPAX@Z"(i8*)
+// M64-DAG: declare dllimport void @"??3ImportAlloc@@SAXPEAX@Z"(i8*)
// G32-DAG: declare dllimport void @_ZN11ImportAllocdlEPv(i8*)
// G64-DAG: declare dllimport void @_ZN11ImportAllocdlEPv(i8*)
void UNIQ(use)(ImportAlloc* ptr) { delete ptr; }
-// M32-DAG: declare dllimport void @"\01??_VImportAlloc@@SAXPAX@Z"(i8*)
-// M64-DAG: declare dllimport void @"\01??_VImportAlloc@@SAXPEAX@Z"(i8*)
+// M32-DAG: declare dllimport void @"??_VImportAlloc@@SAXPAX@Z"(i8*)
+// M64-DAG: declare dllimport void @"??_VImportAlloc@@SAXPEAX@Z"(i8*)
// G32-DAG: declare dllimport void @_ZN11ImportAllocdaEPv(i8*)
// G64-DAG: declare dllimport void @_ZN11ImportAllocdaEPv(i8*)
void UNIQ(use)(ImportAlloc* ptr) { delete[] ptr; }
@@ -657,27 +657,27 @@
};
// Import implicit instantiation of an imported member function template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define linkonce_odr dso_local void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
USEMF(MemFunTmpl, importedNormal<ImplicitInst_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$importedStatic@UImplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedStatic@UImplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_ZN10MemFunTmpl14importedStaticI21ImplicitInst_ImportedEEvv()
USE(MemFunTmpl::importedStatic<ImplicitInst_Imported>)
// Import explicit instantiation declaration of an imported member function
// template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
// G32-DAG: declare dso_local x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
// G64-DAG: declare dso_local void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
extern template void MemFunTmpl::importedNormal<ExplicitDecl_Imported>();
USEMF(MemFunTmpl, importedNormal<ExplicitDecl_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedStatic@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: declare dso_local void @_ZN10MemFunTmpl14importedStaticI21ExplicitDecl_ImportedEEvv()
extern template void MemFunTmpl::importedStatic<ExplicitDecl_Imported>();
USE(MemFunTmpl::importedStatic<ExplicitDecl_Imported>)
@@ -685,54 +685,54 @@
// Import explicit instantiation definition of an imported member function
// template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define weak_odr dso_local void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
template void MemFunTmpl::importedNormal<ExplicitInst_Imported>();
USEMF(MemFunTmpl, importedNormal<ExplicitInst_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedStatic@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define weak_odr dso_local void @_ZN10MemFunTmpl14importedStaticI21ExplicitInst_ImportedEEvv()
template void MemFunTmpl::importedStatic<ExplicitInst_Imported>();
USE(MemFunTmpl::importedStatic<ExplicitInst_Imported>)
// Import specialization of an imported member function template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitSpec_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$importedNormal@UExplicitSpec_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$importedNormal@UExplicitSpec_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*)
// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*)
template<> __declspec(dllimport) void MemFunTmpl::importedNormal<ExplicitSpec_Imported>();
USEMF(MemFunTmpl, importedNormal<ExplicitSpec_Imported>)
-// M32-DAG-FIXME: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG-FIXME: declare dllimport void @"\01??$importedNormal@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG-FIXME: declare dllimport x86_thiscallcc void @"??$importedNormal@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG-FIXME: declare dllimport void @"??$importedNormal@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
#ifdef MSABI
//template<> __declspec(dllimport) void MemFunTmpl::importedNormal<ExplicitSpec_Def_Imported>() {}
//USEMF(MemFunTmpl, importedNormal<ExplicitSpec_Def_Imported>)
#endif
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define linkonce_odr dso_local void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this)
template<> __declspec(dllimport) inline void MemFunTmpl::importedNormal<ExplicitSpec_InlineDef_Imported>() {}
USEMF(MemFunTmpl, importedNormal<ExplicitSpec_InlineDef_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitSpec_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedStatic@UExplicitSpec_Imported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ExplicitSpec_ImportedEEvv()
template<> __declspec(dllimport) void MemFunTmpl::importedStatic<ExplicitSpec_Imported>();
USE(MemFunTmpl::importedStatic<ExplicitSpec_Imported>)
-// MSC-DAG-FIXME: declare dllimport void @"\01??$importedStatic@UExplicitSpec_Def_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG-FIXME: declare dllimport void @"??$importedStatic@UExplicitSpec_Def_Imported@@@MemFunTmpl@@SAXXZ"()
#ifdef MSABI
//template<> __declspec(dllimport) void MemFunTmpl::importedStatic<ExplicitSpec_Def_Imported>() {}
//USE(MemFunTmpl::importedStatic<ExplicitSpec_Def_Imported>)
#endif
-// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedStatic@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_ZN10MemFunTmpl14importedStaticI31ExplicitSpec_InlineDef_ImportedEEvv()
template<> __declspec(dllimport) inline void MemFunTmpl::importedStatic<ExplicitSpec_InlineDef_Imported>() {}
USE(MemFunTmpl::importedStatic<ExplicitSpec_InlineDef_Imported>)
@@ -740,14 +740,14 @@
// Not importing specialization of an imported member function template without
// explicit dllimport.
-// M32-DAG: define dso_local x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_NotImported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
-// M64-DAG: define dso_local void @"\01??$importedNormal@UExplicitSpec_NotImported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// M32-DAG: define dso_local x86_thiscallcc void @"??$importedNormal@UExplicitSpec_NotImported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define dso_local void @"??$importedNormal@UExplicitSpec_NotImported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
// G32-DAG: define dso_local x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI24ExplicitSpec_NotImportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define dso_local void @_ZN10MemFunTmpl14importedNormalI24ExplicitSpec_NotImportedEEvv(%struct.MemFunTmpl* %this)
template<> void MemFunTmpl::importedNormal<ExplicitSpec_NotImported>() {}
USEMF(MemFunTmpl, importedNormal<ExplicitSpec_NotImported>)
-// MSC-DAG: define dso_local void @"\01??$importedStatic@UExplicitSpec_NotImported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: define dso_local void @"??$importedStatic@UExplicitSpec_NotImported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define dso_local void @_ZN10MemFunTmpl14importedStaticI24ExplicitSpec_NotImportedEEvv()
template<> void MemFunTmpl::importedStatic<ExplicitSpec_NotImported>() {}
USE(MemFunTmpl::importedStatic<ExplicitSpec_NotImported>)
@@ -755,14 +755,14 @@
// Import explicit instantiation declaration of a non-imported member function
// template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
// G32-DAG: declare dso_local x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
// G64-DAG: declare dso_local void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
extern template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitDecl_Imported>();
USEMF(MemFunTmpl, normalDef<ExplicitDecl_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: declare dllimport void @"??$staticDef@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: declare dso_local void @_ZN10MemFunTmpl9staticDefI21ExplicitDecl_ImportedEEvv()
extern template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitDecl_Imported>();
USE(MemFunTmpl::staticDef<ExplicitDecl_Imported>)
@@ -770,54 +770,54 @@
// Import explicit instantiation definition of a non-imported member function
// template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define weak_odr dso_local void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this)
template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitInst_Imported>();
USEMF(MemFunTmpl, normalDef<ExplicitInst_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: declare dllimport void @"??$staticDef@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define weak_odr dso_local void @_ZN10MemFunTmpl9staticDefI21ExplicitInst_ImportedEEvv()
template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitInst_Imported>();
USE(MemFunTmpl::staticDef<ExplicitInst_Imported>)
// Import specialization of a non-imported member function template.
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitSpec_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$normalDef@UExplicitSpec_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$normalDef@UExplicitSpec_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*)
// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*)
template<> __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitSpec_Imported>();
USEMF(MemFunTmpl, normalDef<ExplicitSpec_Imported>)
-// M32-DAG-FIXME: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG-FIXME: declare dllimport void @"\01??$normalDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG-FIXME: declare dllimport x86_thiscallcc void @"??$normalDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG-FIXME: declare dllimport void @"??$normalDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
#ifdef MSABI
//template<> __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitSpec_Def_Imported>() {}
//USEMF(MemFunTmpl, normalDef<ExplicitSpec_Def_Imported>)
#endif
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
-// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// M32-DAG: declare dllimport x86_thiscallcc void @"??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this)
// G64-DAG: define linkonce_odr dso_local void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this)
template<> __declspec(dllimport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Imported>() {}
USEMF(MemFunTmpl, normalDef<ExplicitSpec_InlineDef_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitSpec_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: declare dllimport void @"??$staticDef@UExplicitSpec_Imported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI21ExplicitSpec_ImportedEEvv()
template<> __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitSpec_Imported>();
USE(MemFunTmpl::staticDef<ExplicitSpec_Imported>)
-// MSC-DAG-FIXME: declare dllimport void @"\01??$staticDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG-FIXME: declare dllimport void @"??$staticDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@SAXXZ"()
#ifdef MSABI
//template<> __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitSpec_Def_Imported>() {}
//USE(MemFunTmpl::staticDef<ExplicitSpec_Def_Imported>)
#endif
-// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: declare dllimport void @"??$staticDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_ZN10MemFunTmpl9staticDefI31ExplicitSpec_InlineDef_ImportedEEvv()
template<> __declspec(dllimport) inline void MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Imported>() {}
USE(MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Imported>)
@@ -830,13 +830,13 @@
};
// Import implicit instantiation of an imported member variable template.
-// MSC-DAG: @"\01??$ImportedStaticVar@UImplicitInst_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1, align 4
+// MSC-DAG: @"??$ImportedStaticVar@UImplicitInst_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1, align 4
// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ImplicitInst_ImportedEE = external dllimport constant i32
USEMV(MemVarTmpl, ImportedStaticVar<ImplicitInst_Imported>)
// Import explicit instantiation declaration of an imported member variable
// template.
-// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1
+// MSC-DAG: @"??$ImportedStaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1
// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ExplicitDecl_ImportedEE = external dllimport constant i32
extern template const int MemVarTmpl::ImportedStaticVar<ExplicitDecl_Imported>;
USEMV(MemVarTmpl, ImportedStaticVar<ExplicitDecl_Imported>)
@@ -846,14 +846,14 @@
// in-class initializer does not count.
// Import specialization of an imported member variable template.
-// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitSpec_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32
+// MSC-DAG: @"??$ImportedStaticVar@UExplicitSpec_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32
// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ExplicitSpec_ImportedEE = external dllimport constant i32
template<> __declspec(dllimport) const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_Imported>;
USEMV(MemVarTmpl, ImportedStaticVar<ExplicitSpec_Imported>)
// Not importing specialization of a member variable template without explicit
// dllimport.
-// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitSpec_NotImported@@@MemVarTmpl@@2HB" = external dso_local constant i32
+// MSC-DAG: @"??$ImportedStaticVar@UExplicitSpec_NotImported@@@MemVarTmpl@@2HB" = external dso_local constant i32
// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI24ExplicitSpec_NotImportedEE = external dso_local constant i32
template<> const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_NotImported>;
USEMV(MemVarTmpl, ImportedStaticVar<ExplicitSpec_NotImported>)
@@ -861,7 +861,7 @@
// Import explicit instantiation declaration of a non-imported member variable
// template.
-// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1
+// MSC-DAG: @"??$StaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1
// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ImportedEE = external dllimport constant i32
extern template __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitDecl_Imported>;
USEMV(MemVarTmpl, StaticVar<ExplicitDecl_Imported>)
@@ -871,7 +871,7 @@
// in-class initializer does not count.
// Import specialization of a non-imported member variable template.
-// MSC-DAG: @"\01??$StaticVar@UExplicitSpec_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32
+// MSC-DAG: @"??$StaticVar@UExplicitSpec_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32
// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitSpec_ImportedEE = external dllimport constant i32
template<> __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitSpec_Imported>;
USEMV(MemVarTmpl, StaticVar<ExplicitSpec_Imported>)
diff --git a/test/CodeGenCXX/dllimport-memptr-global.cpp b/test/CodeGenCXX/dllimport-memptr-global.cpp
index 5c77d36..91abfeb 100644
--- a/test/CodeGenCXX/dllimport-memptr-global.cpp
+++ b/test/CodeGenCXX/dllimport-memptr-global.cpp
@@ -40,19 +40,19 @@
// All of the non-virtual globals need dynamic initializers.
-// CHECK: @"\01?mp_single_nv@@3P8Single@@AEXXZQ1@" = dso_local global i8* null, align 4
-// CHECK: @"\01?mp_multi_nv@@3P8Multi@@AEXXZQ1@" = dso_local global { i8*, i32 } zeroinitializer, align 4
-// CHECK: @"\01?mp_virtual_nv@@3P8Virtual@@AEXXZQ1@" = dso_local global { i8*, i32, i32 } zeroinitializer, align 4
-// CHECK: @"\01?mp_general_nv@@3P8General@@AEXXZQ1@" = dso_local global { i8*, i32, i32, i32 } zeroinitializer, align 4
+// CHECK: @"?mp_single_nv@@3P8Single@@AEXXZQ1@" = dso_local global i8* null, align 4
+// CHECK: @"?mp_multi_nv@@3P8Multi@@AEXXZQ1@" = dso_local global { i8*, i32 } zeroinitializer, align 4
+// CHECK: @"?mp_virtual_nv@@3P8Virtual@@AEXXZQ1@" = dso_local global { i8*, i32, i32 } zeroinitializer, align 4
+// CHECK: @"?mp_general_nv@@3P8General@@AEXXZQ1@" = dso_local global { i8*, i32, i32, i32 } zeroinitializer, align 4
-// CHECK: @"\01?mp_single_v@@3P8Single@@AEXXZQ1@" = dso_local global i8* bitcast (void (%struct.Single*, ...)* @"\01??_9Single@@$BA@AE" to i8*), align 4
-// CHECK: @"\01?mp_multi_v@@3P8Multi@@AEXXZQ1@" = dso_local global { i8*, i32 } { i8* bitcast (void (%struct.Multi*, ...)* @"\01??_9Multi@@$BA@AE" to i8*), i32 0 }, align 4
-// CHECK: @"\01?mp_virtual_v@@3P8Virtual@@AEXXZQ1@" = dso_local global { i8*, i32, i32 } { i8* bitcast (void (%struct.Virtual*, ...)* @"\01??_9Virtual@@$BA@AE" to i8*), i32 0, i32 0 }, align 4
-// CHECK: @"\01?mp_general_v@@3P8General@@AEXXZQ1@" = dso_local global { i8*, i32, i32, i32 } { i8* bitcast (void (%struct.General*, ...)* @"\01??_9General@@$BA@AE" to i8*), i32 0, i32 0, i32 0 }, align 4
+// CHECK: @"?mp_single_v@@3P8Single@@AEXXZQ1@" = dso_local global i8* bitcast (void (%struct.Single*, ...)* @"??_9Single@@$BA@AE" to i8*), align 4
+// CHECK: @"?mp_multi_v@@3P8Multi@@AEXXZQ1@" = dso_local global { i8*, i32 } { i8* bitcast (void (%struct.Multi*, ...)* @"??_9Multi@@$BA@AE" to i8*), i32 0 }, align 4
+// CHECK: @"?mp_virtual_v@@3P8Virtual@@AEXXZQ1@" = dso_local global { i8*, i32, i32 } { i8* bitcast (void (%struct.Virtual*, ...)* @"??_9Virtual@@$BA@AE" to i8*), i32 0, i32 0 }, align 4
+// CHECK: @"?mp_general_v@@3P8General@@AEXXZQ1@" = dso_local global { i8*, i32, i32, i32 } { i8* bitcast (void (%struct.General*, ...)* @"??_9General@@$BA@AE" to i8*), i32 0, i32 0, i32 0 }, align 4
// CHECK: define internal void @_GLOBAL__sub_I{{.*}}() {{.*}} {
-// CHECK: call void @"\01??__Emp_single_nv@@YAXXZ"()
-// CHECK: call void @"\01??__Emp_multi_nv@@YAXXZ"()
-// CHECK: call void @"\01??__Emp_virtual_nv@@YAXXZ"()
-// CHECK: call void @"\01??__Emp_general_nv@@YAXXZ"()
+// CHECK: call void @"??__Emp_single_nv@@YAXXZ"()
+// CHECK: call void @"??__Emp_multi_nv@@YAXXZ"()
+// CHECK: call void @"??__Emp_virtual_nv@@YAXXZ"()
+// CHECK: call void @"??__Emp_general_nv@@YAXXZ"()
// CHECK: }
diff --git a/test/CodeGenCXX/dllimport-rtti.cpp b/test/CodeGenCXX/dllimport-rtti.cpp
index 619d956..d8e6f8e 100644
--- a/test/CodeGenCXX/dllimport-rtti.cpp
+++ b/test/CodeGenCXX/dllimport-rtti.cpp
@@ -5,11 +5,11 @@
virtual void f() {}
} s;
// MSVC: [[VF_S:.*]] = private unnamed_addr constant { [2 x i8*] }
-// MSVC-DAG: @"\01??_SS@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VF_S]], i32 0, i32 0, i32 1)
-// MSVC-DAG: @"\01??_R0?AUS@@@8" = linkonce_odr
-// MSVC-DAG: @"\01??_R1A@?0A@EA@S@@8" = linkonce_odr
-// MSVC-DAG: @"\01??_R2S@@8" = linkonce_odr
-// MSVC-DAG: @"\01??_R3S@@8" = linkonce_odr
+// MSVC-DAG: @"??_SS@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VF_S]], i32 0, i32 0, i32 1)
+// MSVC-DAG: @"??_R0?AUS@@@8" = linkonce_odr
+// MSVC-DAG: @"??_R1A@?0A@EA@S@@8" = linkonce_odr
+// MSVC-DAG: @"??_R2S@@8" = linkonce_odr
+// MSVC-DAG: @"??_R3S@@8" = linkonce_odr
// GNU-DAG: @_ZTV1S = available_externally dllimport
// GNU-DAG: @_ZTI1S = linkonce_odr dso_local
diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp
index 4ac4f5c..74f58cc 100644
--- a/test/CodeGenCXX/dllimport.cpp
+++ b/test/CodeGenCXX/dllimport.cpp
@@ -38,38 +38,38 @@
//===----------------------------------------------------------------------===//
// Import declaration.
-// MSC-DAG: @"\01?ExternGlobalDecl@@3HA" = external dllimport global i32
+// MSC-DAG: @"?ExternGlobalDecl@@3HA" = external dllimport global i32
// GNU-DAG: @ExternGlobalDecl = external dllimport global i32
__declspec(dllimport) extern int ExternGlobalDecl;
USEVAR(ExternGlobalDecl)
// dllimport implies a declaration.
-// MSC-DAG: @"\01?GlobalDecl@@3HA" = external dllimport global i32
+// MSC-DAG: @"?GlobalDecl@@3HA" = external dllimport global i32
// GNU-DAG: @GlobalDecl = external dllimport global i32
__declspec(dllimport) int GlobalDecl;
USEVAR(GlobalDecl)
// Redeclarations
-// MSC-DAG: @"\01?GlobalRedecl1@@3HA" = external dllimport global i32
+// MSC-DAG: @"?GlobalRedecl1@@3HA" = external dllimport global i32
// GNU-DAG: @GlobalRedecl1 = external dllimport global i32
__declspec(dllimport) extern int GlobalRedecl1;
__declspec(dllimport) extern int GlobalRedecl1;
USEVAR(GlobalRedecl1)
-// MSC-DAG: @"\01?GlobalRedecl2a@@3HA" = external dllimport global i32
+// MSC-DAG: @"?GlobalRedecl2a@@3HA" = external dllimport global i32
// GNU-DAG: @GlobalRedecl2a = external dllimport global i32
__declspec(dllimport) int GlobalRedecl2a;
__declspec(dllimport) int GlobalRedecl2a;
USEVAR(GlobalRedecl2a)
-// M32-DAG: @"\01?GlobalRedecl2b@@3PAHA" = external dllimport global i32*
-// M64-DAG: @"\01?GlobalRedecl2b@@3PEAHEA" = external dllimport global i32*
+// M32-DAG: @"?GlobalRedecl2b@@3PAHA" = external dllimport global i32*
+// M64-DAG: @"?GlobalRedecl2b@@3PEAHEA" = external dllimport global i32*
// GNU-DAG: @GlobalRedecl2b = external dllimport global i32*
int *__attribute__((dllimport)) GlobalRedecl2b;
int *__attribute__((dllimport)) GlobalRedecl2b;
USEVARTYPE(int*, GlobalRedecl2b)
-// MSC-DAG: @"\01?GlobalRedecl2c@@3HA" = external dllimport global i32
+// MSC-DAG: @"?GlobalRedecl2c@@3HA" = external dllimport global i32
// GNU-DAG: @GlobalRedecl2c = external dllimport global i32
int GlobalRedecl2c __attribute__((dllimport));
int GlobalRedecl2c __attribute__((dllimport));
@@ -77,20 +77,20 @@
// NB: MSC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC
// and drop the dllimport with a warning.
-// MSC-DAG: @"\01?GlobalRedecl3@@3HA" = external dso_local global i32
+// MSC-DAG: @"?GlobalRedecl3@@3HA" = external dso_local global i32
// GNU-DAG: @GlobalRedecl3 = external dso_local global i32
__declspec(dllimport) extern int GlobalRedecl3;
extern int GlobalRedecl3; // dllimport ignored
USEVAR(GlobalRedecl3)
-// MSC-DAG: @"\01?ExternalGlobal@ns@@3HA" = external dllimport global i32
+// MSC-DAG: @"?ExternalGlobal@ns@@3HA" = external dllimport global i32
// GNU-DAG: @_ZN2ns14ExternalGlobalE = external dllimport global i32
namespace ns { __declspec(dllimport) int ExternalGlobal; }
USEVAR(ns::ExternalGlobal)
int __declspec(dllimport) f();
-// MO1-DAG: @"\01?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = available_externally dllimport global i32 0
-// MO1-DAG: @"\01??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = available_externally dllimport global i32 0
+// MO1-DAG: @"?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = available_externally dllimport global i32 0
+// MO1-DAG: @"??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = available_externally dllimport global i32 0
inline int __declspec(dllimport) inlineStaticLocalsFunc() {
static int x = f();
return x++;
@@ -98,7 +98,7 @@
USE(inlineStaticLocalsFunc);
// The address of a dllimport global cannot be used in constant initialization.
-// M32-DAG: @"\01?arr@?1??initializationFunc@@YAPAHXZ@4QBQAHB" = internal global [1 x i32*] zeroinitializer
+// M32-DAG: @"?arr@?1??initializationFunc@@YAPAHXZ@4QBQAHB" = internal global [1 x i32*] zeroinitializer
// GNU-DAG: @_ZZ18initializationFuncvE3arr = internal global [1 x i32*] zeroinitializer
int *initializationFunc() {
static int *const arr[] = {&ExternGlobalDecl};
@@ -112,38 +112,38 @@
//===----------------------------------------------------------------------===//
// Import declaration.
-// MSC-DAG: @"\01??$ExternVarTmplDecl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$ExternVarTmplDecl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z17ExternVarTmplDeclI21ImplicitInst_ImportedE = external dllimport global i32
template<typename T> __declspec(dllimport) extern int ExternVarTmplDecl;
USEVAR(ExternVarTmplDecl<ImplicitInst_Imported>)
// dllimport implies a declaration.
-// MSC-DAG: @"\01??$VarTmplDecl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$VarTmplDecl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z11VarTmplDeclI21ImplicitInst_ImportedE = external dllimport global i32
template<typename T> __declspec(dllimport) int VarTmplDecl;
USEVAR(VarTmplDecl<ImplicitInst_Imported>)
// Redeclarations
-// MSC-DAG: @"\01??$VarTmplRedecl1@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$VarTmplRedecl1@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z14VarTmplRedecl1I21ImplicitInst_ImportedE = external dllimport global i32
template<typename T> __declspec(dllimport) extern int VarTmplRedecl1;
template<typename T> __declspec(dllimport) extern int VarTmplRedecl1;
USEVAR(VarTmplRedecl1<ImplicitInst_Imported>)
-// MSC-DAG: @"\01??$VarTmplRedecl2@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$VarTmplRedecl2@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z14VarTmplRedecl2I21ImplicitInst_ImportedE = external dllimport global i32
template<typename T> __declspec(dllimport) int VarTmplRedecl2;
template<typename T> __declspec(dllimport) int VarTmplRedecl2;
USEVAR(VarTmplRedecl2<ImplicitInst_Imported>)
-// MSC-DAG: @"\01??$VarTmplRedecl3@UImplicitInst_Imported@@@@3HA" = external dso_local global i32
+// MSC-DAG: @"??$VarTmplRedecl3@UImplicitInst_Imported@@@@3HA" = external dso_local global i32
// GNU-DAG: @_Z14VarTmplRedecl3I21ImplicitInst_ImportedE = external dso_local global i32
template<typename T> __declspec(dllimport) extern int VarTmplRedecl3;
template<typename T> extern int VarTmplRedecl3; // dllimport ignored
USEVAR(VarTmplRedecl3<ImplicitInst_Imported>)
-// MSC-DAG: @"\01??$ExternalVarTmpl@UImplicitInst_Imported@@@ns@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$ExternalVarTmpl@UImplicitInst_Imported@@@ns@@3HA" = external dllimport global i32
// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ImplicitInst_ImportedEE = external dllimport global i32
namespace ns { template<typename T> __declspec(dllimport) int ExternalVarTmpl; }
USEVAR(ns::ExternalVarTmpl<ImplicitInst_Imported>)
@@ -153,12 +153,12 @@
template<typename T> __declspec(dllimport) int ImportedVarTmpl;
// Import implicit instantiation of an imported variable template.
-// MSC-DAG: @"\01??$ImportedVarTmpl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$ImportedVarTmpl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z15ImportedVarTmplI21ImplicitInst_ImportedE = external dllimport global i32
USEVAR(ImportedVarTmpl<ImplicitInst_Imported>)
// Import explicit instantiation declaration of an imported variable template.
-// MSC-DAG: @"\01??$ImportedVarTmpl@UExplicitDecl_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$ImportedVarTmpl@UExplicitDecl_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z15ImportedVarTmplI21ExplicitDecl_ImportedE = external dllimport global i32
extern template int ImportedVarTmpl<ExplicitDecl_Imported>;
USEVAR(ImportedVarTmpl<ExplicitDecl_Imported>)
@@ -167,32 +167,32 @@
// be imported because the template must be defined which is illegal.
// Import specialization of an imported variable template.
-// MSC-DAG: @"\01??$ImportedVarTmpl@UExplicitSpec_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$ImportedVarTmpl@UExplicitSpec_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z15ImportedVarTmplI21ExplicitSpec_ImportedE = external dllimport global i32
template<> __declspec(dllimport) int ImportedVarTmpl<ExplicitSpec_Imported>;
USEVAR(ImportedVarTmpl<ExplicitSpec_Imported>)
// Not importing specialization of an imported variable template without
// explicit dllimport.
-// MSC-DAG: @"\01??$ImportedVarTmpl@UExplicitSpec_NotImported@@@@3HA" = dso_local global i32 0, align 4
+// MSC-DAG: @"??$ImportedVarTmpl@UExplicitSpec_NotImported@@@@3HA" = dso_local global i32 0, align 4
// GNU-DAG: @_Z15ImportedVarTmplI24ExplicitSpec_NotImportedE = dso_local global i32 0, align 4
template<> int ImportedVarTmpl<ExplicitSpec_NotImported>;
USEVAR(ImportedVarTmpl<ExplicitSpec_NotImported>)
// Import explicit instantiation declaration of a non-imported variable template.
-// MSC-DAG: @"\01??$VarTmpl@UExplicitDecl_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$VarTmpl@UExplicitDecl_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ImportedE = external dllimport global i32
extern template __declspec(dllimport) int VarTmpl<ExplicitDecl_Imported>;
USEVAR(VarTmpl<ExplicitDecl_Imported>)
// Import explicit instantiation definition of a non-imported variable template.
-// MSC-DAG: @"\01??$VarTmpl@UExplicitInst_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$VarTmpl@UExplicitInst_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ImportedE = external dllimport global i32
template __declspec(dllimport) int VarTmpl<ExplicitInst_Imported>;
USEVAR(VarTmpl<ExplicitInst_Imported>)
// Import specialization of a non-imported variable template.
-// MSC-DAG: @"\01??$VarTmpl@UExplicitSpec_Imported@@@@3HA" = external dllimport global i32
+// MSC-DAG: @"??$VarTmpl@UExplicitSpec_Imported@@@@3HA" = external dllimport global i32
// GNU-DAG: @_Z7VarTmplI21ExplicitSpec_ImportedE = external dllimport global i32
template<> __declspec(dllimport) int VarTmpl<ExplicitSpec_Imported>;
USEVAR(VarTmpl<ExplicitSpec_Imported>)
@@ -203,8 +203,10 @@
// Functions
//===----------------------------------------------------------------------===//
+// GNU-DAG: declare dso_local void @_ZdlPv(i8*)
+
// Import function declaration.
-// MSC-DAG: declare dllimport void @"\01?decl@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"?decl@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z4declv()
__declspec(dllimport) void decl();
USE(decl)
@@ -216,42 +218,42 @@
USE(externC)
// Import inline function.
-// MSC-DAG: declare dllimport void @"\01?inlineFunc@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"?inlineFunc@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z10inlineFuncv()
-// MO1-DAG: define available_externally dllimport void @"\01?inlineFunc@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"?inlineFunc@@YAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_Z10inlineFuncv()
__declspec(dllimport) inline void inlineFunc() {}
USE(inlineFunc)
-// MSC-DAG: declare dllimport void @"\01?inlineDecl@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"?inlineDecl@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z10inlineDeclv()
-// MO1-DAG: define available_externally dllimport void @"\01?inlineDecl@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"?inlineDecl@@YAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_Z10inlineDeclv()
__declspec(dllimport) inline void inlineDecl();
void inlineDecl() {}
USE(inlineDecl)
-// MSC-DAG: declare dllimport void @"\01?inlineDef@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"?inlineDef@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z9inlineDefv()
-// MO1-DAG: define available_externally dllimport void @"\01?inlineDef@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"?inlineDef@@YAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_Z9inlineDefv()
__declspec(dllimport) void inlineDef();
inline void inlineDef() {}
USE(inlineDef)
// inline attributes
-// MSC-DAG: declare dllimport void @"\01?noinline@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"?noinline@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z8noinlinev()
__declspec(dllimport) __attribute__((noinline)) inline void noinline() {}
USE(noinline)
-// MSC2-NOT: @"\01?alwaysInline@@YAXXZ"()
+// MSC2-NOT: @"?alwaysInline@@YAXXZ"()
// GNU2-NOT: @_Z12alwaysInlinev()
__declspec(dllimport) __attribute__((always_inline)) inline void alwaysInline() {}
USE(alwaysInline)
// Redeclarations
-// MSC-DAG: declare dllimport void @"\01?redecl1@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"?redecl1@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z7redecl1v()
__declspec(dllimport) void redecl1();
__declspec(dllimport) void redecl1();
@@ -259,13 +261,13 @@
// NB: MSC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC
// and drop the dllimport with a warning.
-// MSC-DAG: declare dso_local void @"\01?redecl2@@YAXXZ"()
+// MSC-DAG: declare dso_local void @"?redecl2@@YAXXZ"()
// GNU-DAG: declare dso_local void @_Z7redecl2v()
__declspec(dllimport) void redecl2();
void redecl2();
USE(redecl2)
-// MSC-DAG: define dso_local dllexport void @"\01?redecl3@@YAXXZ"()
+// MSC-DAG: define dso_local dllexport void @"?redecl3@@YAXXZ"()
// GNU-DAG: define dso_local void @_Z7redecl3v()
__declspec(dllimport) void redecl3();
void redecl3() {} // dllimport ignored
@@ -273,15 +275,15 @@
// Friend functions
-// MSC-DAG: declare dllimport void @"\01?friend1@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"?friend1@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z7friend1v()
-// MSC-DAG: declare dso_local void @"\01?friend2@@YAXXZ"()
+// MSC-DAG: declare dso_local void @"?friend2@@YAXXZ"()
// GNU-DAG: declare dso_local void @_Z7friend2v()
-// MSC-DAG: define dso_local dllexport void @"\01?friend3@@YAXXZ"()
+// MSC-DAG: define dso_local dllexport void @"?friend3@@YAXXZ"()
// GNU-DAG: define dso_local void @_Z7friend3v()
-// MSC-DAG: declare dso_local void @"\01?friend4@@YAXXZ"()
+// MSC-DAG: declare dso_local void @"?friend4@@YAXXZ"()
// GNU-DAG: declare dso_local void @_Z7friend4v()
-// MSC-DAG: declare dllimport void @"\01?friend5@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"?friend5@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z7friend5v()
struct FuncFriend {
@@ -306,12 +308,12 @@
USE(friend5)
// Implicit declarations can be redeclared with dllimport.
-// MSC-DAG: declare dllimport noalias i8* @"\01??2@{{YAPAXI|YAPEAX_K}}@Z"(
+// MSC-DAG: declare dllimport noalias i8* @"??2@{{YAPAXI|YAPEAX_K}}@Z"(
// GNU-DAG: declare dllimport noalias i8* @_Znw{{[yj]}}(
__declspec(dllimport) void* operator new(__SIZE_TYPE__ n);
void UNIQ(use)() { ::operator new(42); }
-// MSC-DAG: declare dllimport void @"\01?externalFunc@ns@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"?externalFunc@ns@@YAXXZ"()
// GNU-DAG: declare dllimport void @_ZN2ns12externalFuncEv()
namespace ns { __declspec(dllimport) void externalFunc(); }
USE(ns::externalFunc)
@@ -325,17 +327,17 @@
struct ClassWithNonImportedMethod { int f(); };
__declspec(dllimport) inline int ReferencingImportedVar() { return ImportedVar; }
-// MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingImportedVar@@YAHXZ"
+// MO1-DAG: define available_externally dllimport i32 @"?ReferencingImportedVar@@YAHXZ"
__declspec(dllimport) inline int ReferencingNonImportedVar() { return NonImportedVar; }
-// MO1-DAG: declare dllimport i32 @"\01?ReferencingNonImportedVar@@YAHXZ"()
+// MO1-DAG: declare dllimport i32 @"?ReferencingNonImportedVar@@YAHXZ"()
__declspec(dllimport) inline int ReferencingImportedFunc() { return ImportedFunc(); }
-// MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingImportedFunc@@YAHXZ"
+// MO1-DAG: define available_externally dllimport i32 @"?ReferencingImportedFunc@@YAHXZ"
__declspec(dllimport) inline int ReferencingNonImportedFunc() { return NonImportedFunc(); }
-// MO1-DAG: declare dllimport i32 @"\01?ReferencingNonImportedFunc@@YAHXZ"()
+// MO1-DAG: declare dllimport i32 @"?ReferencingNonImportedFunc@@YAHXZ"()
__declspec(dllimport) inline int ReferencingNonImportedMethod(ClassWithNonImportedMethod *x) { return x->f(); }
-// MO1-DAG: declare dllimport i32 @"\01?ReferencingNonImportedMethod
+// MO1-DAG: declare dllimport i32 @"?ReferencingNonImportedMethod
__declspec(dllimport) inline int ReferencingClassMemberPtr(int (ClassWithNonImportedMethod::*p)(), ClassWithNonImportedMethod *x) { return (x->*p)(); }
-// MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingClassMemberPtr@@YAHP8ClassWithNonImportedMethod@@AEHXZPAU1@@Z"
+// MO1-DAG: define available_externally dllimport i32 @"?ReferencingClassMemberPtr@@YAHP8ClassWithNonImportedMethod@@AEHXZPAU1@@Z"
USE(ReferencingImportedVar)
USE(ReferencingNonImportedVar)
USE(ReferencingImportedFunc)
@@ -344,17 +346,17 @@
void UNIQ(use)() { ReferencingClassMemberPtr(&ClassWithNonImportedMethod::f, nullptr); }
// References to operator new and delete count too, despite not being DeclRefExprs.
__declspec(dllimport) inline int *ReferencingNonImportedNew() { return new int[2]; }
-// MO1-DAG: declare dllimport i32* @"\01?ReferencingNonImportedNew@@YAPAHXZ"
+// MO1-DAG: declare dllimport i32* @"?ReferencingNonImportedNew@@YAPAHXZ"
__declspec(dllimport) inline int *ReferencingNonImportedDelete() { delete (int*)nullptr; }
-// MO1-DAG: declare dllimport i32* @"\01?ReferencingNonImportedDelete@@YAPAHXZ"
+// MO1-DAG: declare dllimport i32* @"?ReferencingNonImportedDelete@@YAPAHXZ"
USE(ReferencingNonImportedNew)
USE(ReferencingNonImportedDelete)
__declspec(dllimport) void* operator new[](__SIZE_TYPE__);
__declspec(dllimport) void operator delete(void*);
__declspec(dllimport) inline int *ReferencingImportedNew() { return new int[2]; }
-// MO1-DAG: define available_externally dllimport i32* @"\01?ReferencingImportedNew@@YAPAHXZ"
+// MO1-DAG: define available_externally dllimport i32* @"?ReferencingImportedNew@@YAPAHXZ"
__declspec(dllimport) inline int *ReferencingImportedDelete() { delete (int*)nullptr; }
-// MO1-DAG: define available_externally dllimport i32* @"\01?ReferencingImportedDelete@@YAPAHXZ"
+// MO1-DAG: define available_externally dllimport i32* @"?ReferencingImportedDelete@@YAPAHXZ"
USE(ReferencingImportedNew)
USE(ReferencingImportedDelete)
struct ClassWithDtor { ~ClassWithDtor() {} };
@@ -362,25 +364,25 @@
struct __declspec(dllimport) ClassWithNonDllImportBase : public ClassWithDtor { };
USECLASS(ClassWithNonDllImportField);
USECLASS(ClassWithNonDllImportBase);
-// MO1-DAG: declare dllimport x86_thiscallcc void @"\01??1ClassWithNonDllImportBase@@QAE@XZ"(%struct.ClassWithNonDllImportBase*)
-// MO1-DAG: declare dllimport x86_thiscallcc void @"\01??1ClassWithNonDllImportField@@QAE@XZ"(%struct.ClassWithNonDllImportField*)
+// MO1-DAG: declare dllimport x86_thiscallcc void @"??1ClassWithNonDllImportBase@@QAE@XZ"(%struct.ClassWithNonDllImportBase*)
+// MO1-DAG: declare dllimport x86_thiscallcc void @"??1ClassWithNonDllImportField@@QAE@XZ"(%struct.ClassWithNonDllImportField*)
struct ClassWithCtor { ClassWithCtor() {} };
struct __declspec(dllimport) ClassWithNonDllImportFieldWithCtor { ClassWithCtor t; };
USECLASS(ClassWithNonDllImportFieldWithCtor);
-// MO1-DAG: declare dllimport x86_thiscallcc %struct.ClassWithNonDllImportFieldWithCtor* @"\01??0ClassWithNonDllImportFieldWithCtor@@QAE@XZ"(%struct.ClassWithNonDllImportFieldWithCtor* returned)
+// MO1-DAG: declare dllimport x86_thiscallcc %struct.ClassWithNonDllImportFieldWithCtor* @"??0ClassWithNonDllImportFieldWithCtor@@QAE@XZ"(%struct.ClassWithNonDllImportFieldWithCtor* returned)
struct ClassWithImplicitDtor { __declspec(dllimport) ClassWithImplicitDtor(); ClassWithDtor member; };
__declspec(dllimport) inline void ReferencingDtorThroughDefinition() { ClassWithImplicitDtor x; };
USE(ReferencingDtorThroughDefinition)
-// MO1-DAG: declare dllimport void @"\01?ReferencingDtorThroughDefinition@@YAXXZ"()
+// MO1-DAG: declare dllimport void @"?ReferencingDtorThroughDefinition@@YAXXZ"()
__declspec(dllimport) inline void ReferencingDtorThroughTemporary() { ClassWithImplicitDtor(); };
USE(ReferencingDtorThroughTemporary)
-// MO1-DAG: declare dllimport void @"\01?ReferencingDtorThroughTemporary@@YAXXZ"()
+// MO1-DAG: declare dllimport void @"?ReferencingDtorThroughTemporary@@YAXXZ"()
// A dllimport function with a TLS variable must not be available_externally.
__declspec(dllimport) inline void FunctionWithTLSVar() { static __thread int x = 42; }
-// MO1-DAG: declare dllimport void @"\01?FunctionWithTLSVar@@YAXXZ"
+// MO1-DAG: declare dllimport void @"?FunctionWithTLSVar@@YAXXZ"
__declspec(dllimport) inline void FunctionWithNormalVar() { static int x = 42; }
-// MO1-DAG: define available_externally dllimport void @"\01?FunctionWithNormalVar@@YAXXZ"
+// MO1-DAG: define available_externally dllimport void @"?FunctionWithNormalVar@@YAXXZ"
USE(FunctionWithTLSVar)
USE(FunctionWithNormalVar)
@@ -390,7 +392,7 @@
//===----------------------------------------------------------------------===//
// Import function template declaration.
-// MSC-DAG: declare dllimport void @"\01??$funcTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z12funcTmplDeclI21ImplicitInst_ImportedEvv()
template<typename T> __declspec(dllimport) void funcTmplDecl();
USE(funcTmplDecl<ImplicitInst_Imported>)
@@ -398,31 +400,31 @@
// Function template definitions cannot be imported.
// Import inline function template.
-// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv()
template<typename T> __declspec(dllimport) inline void inlineFuncTmpl1() {}
USE(inlineFuncTmpl1<ImplicitInst_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv()
template<typename T> inline void __attribute__((dllimport)) inlineFuncTmpl2() {}
USE(inlineFuncTmpl2<ImplicitInst_Imported>)
-// MSC-DAG: define linkonce_odr dso_local void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: define linkonce_odr dso_local void @"??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv()
-// MO1-DAG: define linkonce_odr dso_local void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
+// MO1-DAG: define linkonce_odr dso_local void @"??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv()
template<typename T> __declspec(dllimport) inline void inlineFuncTmplDecl();
template<typename T> void inlineFuncTmplDecl() {}
USE(inlineFuncTmplDecl<ImplicitInst_Imported>)
-// MSC-DAG: define linkonce_odr dso_local void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: define linkonce_odr dso_local void @"??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv()
-// MO1-DAG: define linkonce_odr dso_local void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"()
+// MO1-DAG: define linkonce_odr dso_local void @"??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv()
template<typename T> __declspec(dllimport) void inlineFuncTmplDef();
template<typename T> inline void inlineFuncTmplDef() {}
@@ -430,19 +432,19 @@
// Redeclarations
-// MSC-DAG: declare dllimport void @"\01??$funcTmplRedecl1@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmplRedecl1@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z15funcTmplRedecl1I21ImplicitInst_ImportedEvv()
template<typename T> __declspec(dllimport) void funcTmplRedecl1();
template<typename T> __declspec(dllimport) void funcTmplRedecl1();
USE(funcTmplRedecl1<ImplicitInst_Imported>)
-// MSC-DAG: declare dso_local void @"\01??$funcTmplRedecl2@UImplicitInst_NotImported@@@@YAXXZ"()
+// MSC-DAG: declare dso_local void @"??$funcTmplRedecl2@UImplicitInst_NotImported@@@@YAXXZ"()
// GNU-DAG: declare dso_local void @_Z15funcTmplRedecl2I24ImplicitInst_NotImportedEvv()
template<typename T> __declspec(dllimport) void funcTmplRedecl2();
template<typename T> void funcTmplRedecl2(); // dllimport ignored
USE(funcTmplRedecl2<ImplicitInst_NotImported>)
-// MSC-DAG: define linkonce_odr dso_local void @"\01??$funcTmplRedecl3@UImplicitInst_NotImported@@@@YAXXZ"()
+// MSC-DAG: define linkonce_odr dso_local void @"??$funcTmplRedecl3@UImplicitInst_NotImported@@@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z15funcTmplRedecl3I24ImplicitInst_NotImportedEvv()
template<typename T> __declspec(dllimport) void funcTmplRedecl3();
template<typename T> void funcTmplRedecl3() {} // dllimport ignored
@@ -450,13 +452,13 @@
// Function template friends
-// MSC-DAG: declare dllimport void @"\01??$funcTmplFriend1@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmplFriend1@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z15funcTmplFriend1I21ImplicitInst_ImportedEvv()
-// MSC-DAG: declare dso_local void @"\01??$funcTmplFriend2@UImplicitInst_NotImported@@@@YAXXZ"()
+// MSC-DAG: declare dso_local void @"??$funcTmplFriend2@UImplicitInst_NotImported@@@@YAXXZ"()
// GNU-DAG: declare dso_local void @_Z15funcTmplFriend2I24ImplicitInst_NotImportedEvv()
-// MSC-DAG: define linkonce_odr dso_local void @"\01??$funcTmplFriend3@UImplicitInst_NotImported@@@@YAXXZ"()
+// MSC-DAG: define linkonce_odr dso_local void @"??$funcTmplFriend3@UImplicitInst_NotImported@@@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z15funcTmplFriend3I24ImplicitInst_NotImportedEvv()
-// MSC-DAG: define linkonce_odr dso_local void @"\01??$funcTmplFriend4@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: define linkonce_odr dso_local void @"??$funcTmplFriend4@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z15funcTmplFriend4I21ImplicitInst_ImportedEvv()
struct FuncTmplFriend {
template<typename T> friend __declspec(dllimport) void funcTmplFriend1();
@@ -473,7 +475,7 @@
USE(funcTmplFriend3<ImplicitInst_NotImported>)
USE(funcTmplFriend4<ImplicitInst_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$externalFuncTmpl@UImplicitInst_Imported@@@ns@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$externalFuncTmpl@UImplicitInst_Imported@@@ns@@YAXXZ"()
// GNU-DAG: declare dllimport void @_ZN2ns16externalFuncTmplI21ImplicitInst_ImportedEEvv()
namespace ns { template<typename T> __declspec(dllimport) void externalFuncTmpl(); }
USE(ns::externalFuncTmpl<ImplicitInst_Imported>)
@@ -485,69 +487,69 @@
template<typename T> __declspec(dllimport) inline void importedFuncTmpl() {}
// Import implicit instantiation of an imported function template.
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z20importedFuncTmplDeclI21ImplicitInst_ImportedEvv()
USE(importedFuncTmplDecl<ImplicitInst_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv()
USE(importedFuncTmpl<ImplicitInst_Imported>)
// Import explicit instantiation declaration of an imported function template.
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
// GNU-DAG: declare dso_local void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
// GO1-DAG: define available_externally dso_local void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv()
extern template void importedFuncTmpl<ExplicitDecl_Imported>();
USE(importedFuncTmpl<ExplicitDecl_Imported>)
// Import explicit instantiation definition of an imported function template.
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: define weak_odr dso_local void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
// GO1-DAG: define weak_odr dso_local void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv()
template void importedFuncTmpl<ExplicitInst_Imported>();
USE(importedFuncTmpl<ExplicitInst_Imported>)
// Import specialization of an imported function template.
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmplDecl@UExplicitSpec_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z20importedFuncTmplDeclI21ExplicitSpec_ImportedEvv()
template<> __declspec(dllimport) void importedFuncTmplDecl<ExplicitSpec_Imported>();
USE(importedFuncTmplDecl<ExplicitSpec_Imported>)
-// MSC-DAG-FIXME: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
-// MO1-DAG-FIXME: define available_externally dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MSC-DAG-FIXME: declare dllimport void @"??$importedFuncTmplDecl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MO1-DAG-FIXME: define available_externally dllimport void @"??$importedFuncTmplDecl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
#ifdef MSABI
//template<> __declspec(dllimport) void importedFuncTmplDecl<ExplicitSpec_Def_Imported>() {}
//USE(importedFuncTmplDecl<ExplicitSpec_Def_Imported>)
#endif
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv()
template<> __declspec(dllimport) inline void importedFuncTmplDecl<ExplicitSpec_InlineDef_Imported>() {}
USE(importedFuncTmplDecl<ExplicitSpec_InlineDef_Imported>)
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmpl@UExplicitSpec_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ExplicitSpec_ImportedEvv()
template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Imported>();
USE(importedFuncTmpl<ExplicitSpec_Imported>)
-// MSC-DAG-FIXME: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
-// MO1-DAG-FIXME: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MSC-DAG-FIXME: declare dllimport void @"??$importedFuncTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MO1-DAG-FIXME: define available_externally dllimport void @"??$importedFuncTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
#ifdef MSABI
//template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Def_Imported>() {}
//USE(importedFuncTmpl<ExplicitSpec_Def_Imported>)
#endif
-// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv()
template<> __declspec(dllimport) inline void importedFuncTmpl<ExplicitSpec_InlineDef_Imported>() {}
USE(importedFuncTmpl<ExplicitSpec_InlineDef_Imported>)
@@ -555,18 +557,18 @@
// Not importing specialization of an imported function template without
// explicit dllimport.
-// MSC-DAG: define dso_local void @"\01??$importedFuncTmpl@UExplicitSpec_NotImported@@@@YAXXZ"()
+// MSC-DAG: define dso_local void @"??$importedFuncTmpl@UExplicitSpec_NotImported@@@@YAXXZ"()
// GNU-DAG: define dso_local void @_Z16importedFuncTmplI24ExplicitSpec_NotImportedEvv()
template<> void importedFuncTmpl<ExplicitSpec_NotImported>() {}
USE(importedFuncTmpl<ExplicitSpec_NotImported>)
// Import explicit instantiation declaration of a non-imported function template.
-// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
-// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitDecl_ImportedEvv()
// GNU-DAG: declare dso_local void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
// GO1-DAG: define available_externally dso_local void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv()
extern template __declspec(dllimport) void funcTmpl<ExplicitDecl_Imported>();
extern template __declspec(dllimport) void inlineFuncTmpl<ExplicitDecl_Imported>();
@@ -575,12 +577,12 @@
// Import explicit instantiation definition of a non-imported function template.
-// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"()
-// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitInst_ImportedEvv()
// GNU-DAG: define weak_odr dso_local void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv()
-// MO1-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"()
-// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// MO1-DAG: declare dllimport void @"??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
// GO1-DAG: define available_externally dllimport void @_Z8funcTmplI21ExplicitInst_ImportedEvv()
// GO1-DAG: define weak_odr dso_local void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv()
template __declspec(dllimport) void funcTmpl<ExplicitInst_Imported>();
@@ -590,21 +592,21 @@
// Import specialization of a non-imported function template.
-// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmpl@UExplicitSpec_Imported@@@@YAXXZ"()
// GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitSpec_ImportedEvv()
template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Imported>();
USE(funcTmpl<ExplicitSpec_Imported>)
-// MSC-DAG-FIXME: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
-// MO1-DAG-FIXME: define available_externally dllimport void @"\01??$funcTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MSC-DAG-FIXME: declare dllimport void @"??$funcTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MO1-DAG-FIXME: define available_externally dllimport void @"??$funcTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
#ifdef MSABI
//template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Def_Imported>() {}
//USE(funcTmpl<ExplicitSpec_Def_Imported>)
#endif
-// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
// GNU-DAG: define linkonce_odr dso_local void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv()
-// MO1-DAG: define available_externally dllimport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
// GO1-DAG: define linkonce_odr dso_local void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv()
template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {}
USE(funcTmpl<ExplicitSpec_InlineDef_Imported>)
@@ -626,22 +628,22 @@
struct __declspec(dllimport) T {
void a() {}
- // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?a@T@@QAEXXZ"
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?a@T@@QAEXXZ"
static void StaticMethod();
- // MSC-DAG: declare dllimport void @"\01?StaticMethod@T@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"?StaticMethod@T@@SAXXZ"()
// GNU-DAG: declare dllimport void @_ZN1T12StaticMethodEv()
static int b;
- // MO1-DAG: @"\01?b@T@@2HA" = external dllimport global i32
+ // MO1-DAG: @"?b@T@@2HA" = external dllimport global i32
T& operator=(T&) = default;
- // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@AAU0@@Z"
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"??4T@@QAEAAU0@AAU0@@Z"
T& operator=(T&&) = default;
// Note: Don't mark inline move operators dllimport because current MSVC versions don't export them.
- // M18-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@$$QAU0@@Z"
- // M19-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@$$QAU0@@Z"
+ // M18-DAG: define linkonce_odr dso_local x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"??4T@@QAEAAU0@$$QAU0@@Z"
+ // M19-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"??4T@@QAEAAU0@$$QAU0@@Z"
};
USEMEMFUNC(T, a)
USESTATICMEMFUNC(T, StaticMethod)
@@ -650,14 +652,14 @@
USEMOVEASSIGN(T)
template <typename T> struct __declspec(dllimport) U { void foo() {} };
-// MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?foo@?$U@H@@QAEXXZ"
+// MO1-DAG: define available_externally dllimport x86_thiscallcc void @"?foo@?$U@H@@QAEXXZ"
struct __declspec(dllimport) V : public U<int> { };
USEMEMFUNC(V, foo)
struct __declspec(dllimport) W { virtual void foo() {} };
USECLASS(W)
// vftable:
-// MO1-DAG: @"\01??_SW@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] }
+// MO1-DAG: @"??_SW@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void (%struct.W*)* @"?foo@W@@UAEXXZ" to i8*)] }
// GO1-DAG: @_ZTV1W = available_externally dllimport unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] }
struct __declspec(dllimport) KeyFuncClass {
@@ -670,7 +672,7 @@
struct __declspec(dllimport) X : public virtual W {};
USECLASS(X)
// vbtable:
-// MO1-DAG: @"\01??_8X@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4]
+// MO1-DAG: @"??_8X@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4]
struct __declspec(dllimport) Y {
int x;
@@ -679,7 +681,7 @@
struct __declspec(dllimport) Z { virtual ~Z() {} };
USECLASS(Z)
// User-defined dtor:
-// MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1Z@@UAE@XZ"
+// MO1-DAG: define available_externally dllimport x86_thiscallcc void @"??1Z@@UAE@XZ"
namespace DontUseDtorAlias {
struct __declspec(dllimport) A { ~A(); };
@@ -687,13 +689,13 @@
inline A::~A() { }
inline B::~B() { }
// Emit a real definition of B's constructor; don't alias it to A's.
- // MO1-DAG: available_externally dllimport x86_thiscallcc void @"\01??1B@DontUseDtorAlias@@QAE@XZ"
+ // MO1-DAG: available_externally dllimport x86_thiscallcc void @"??1B@DontUseDtorAlias@@QAE@XZ"
USECLASS(B)
}
namespace Vtordisp {
// Don't dllimport the vtordisp.
- // MO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @"\01?f@?$C@H@Vtordisp@@$4PPPPPPPM@A@AEXXZ"
+ // MO1-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?f@?$C@H@Vtordisp@@$4PPPPPPPM@A@AEXXZ"
class __declspec(dllimport) Base {
virtual void f() {}
@@ -713,7 +715,7 @@
static int x;
};
template <typename T> int S<T>::x;
- // MSC-DAG: @"\01?x@?$S@H@ClassTemplateStaticDef@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?x@?$S@H@ClassTemplateStaticDef@@2HA" = external dllimport global i32
int f() { return S<int>::x; }
// Partial class template specialization static field:
@@ -736,21 +738,21 @@
template <typename T> NonPOD A<T>::x;
template struct __declspec(dllimport) A<int>;
USEVARTYPE(NonPOD, A<int>::x);
- // MSC-DAG: @"\01?x@?$A@H@PR19933@@2UNonPOD@2@A" = external dllimport global %"struct.PR19933::NonPOD"
+ // MSC-DAG: @"?x@?$A@H@PR19933@@2UNonPOD@2@A" = external dllimport global %"struct.PR19933::NonPOD"
int f();
template <typename T> struct B { static int x; };
template <typename T> int B<T>::x = f();
template struct __declspec(dllimport) B<int>;
USEVAR(B<int>::x);
- // MSC-DAG: @"\01?x@?$B@H@PR19933@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?x@?$B@H@PR19933@@2HA" = external dllimport global i32
constexpr int g() { return 42; }
template <typename T> struct C { static int x; };
template <typename T> int C<T>::x = g();
template struct __declspec(dllimport) C<int>;
USEVAR(C<int>::x);
- // MSC-DAG: @"\01?x@?$C@H@PR19933@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?x@?$C@H@PR19933@@2HA" = external dllimport global i32
template <int I> struct D { static int x, y; };
template <int I> int D<I>::x = I + 1;
@@ -758,8 +760,8 @@
template struct __declspec(dllimport) D<42>;
USEVAR(D<42>::x);
USEVAR(D<42>::y);
- // MSC-DAG: @"\01?x@?$D@$0CK@@PR19933@@2HA" = external dllimport global i32
- // MSC-DAG: @"\01?y@?$D@$0CK@@PR19933@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?x@?$D@$0CK@@PR19933@@2HA" = external dllimport global i32
+ // MSC-DAG: @"?y@?$D@$0CK@@PR19933@@2HA" = external dllimport global i32
}
namespace PR21355 {
@@ -793,43 +795,43 @@
};
extern template struct __declspec(dllimport) A<int>;
void f() { new A<int>(); }
- // MO1-DAG: @"\01??_S?$A@H@PR27319@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] }
+ // MO1-DAG: @"??_S?$A@H@PR27319@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] }
}
// MS ignores DLL attributes on partial specializations.
template <typename T> struct PartiallySpecializedClassTemplate {};
template <typename T> struct __declspec(dllimport) PartiallySpecializedClassTemplate<T*> { void f(); };
USEMEMFUNC(PartiallySpecializedClassTemplate<void*>, f);
-// M32-DAG: declare dso_local x86_thiscallcc void @"\01?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ"
+// M32-DAG: declare dso_local x86_thiscallcc void @"?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN33PartiallySpecializedClassTemplateIPvE1fEv
// Attributes on explicit specializations are honored.
template <typename T> struct ExplicitlySpecializedClassTemplate {};
template <> struct __declspec(dllimport) ExplicitlySpecializedClassTemplate<void*> { void f(); };
USEMEMFUNC(ExplicitlySpecializedClassTemplate<void*>, f);
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv
// MS inherits DLL attributes to partial specializations.
template <typename T> struct __declspec(dllimport) PartiallySpecializedImportedClassTemplate {};
template <typename T> struct PartiallySpecializedImportedClassTemplate<T*> { void f() {} };
USEMEMFUNC(PartiallySpecializedImportedClassTemplate<void*>, f);
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$PartiallySpecializedImportedClassTemplate@PAX@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?f@?$PartiallySpecializedImportedClassTemplate@PAX@@QAEXXZ"
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN41PartiallySpecializedImportedClassTemplateIPvE1fEv
// Attributes on the instantiation take precedence over attributes on the template.
template <typename T> struct __declspec(dllexport) ExplicitlyInstantiatedWithDifferentAttr { void f() {} };
template struct __declspec(dllimport) ExplicitlyInstantiatedWithDifferentAttr<int>;
USEMEMFUNC(ExplicitlyInstantiatedWithDifferentAttr<int>, f);
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ"
template <typename T> struct ExplicitInstantiationDeclImportedDefTemplate { void f() {} ExplicitInstantiationDeclImportedDefTemplate() {}};
extern template struct ExplicitInstantiationDeclImportedDefTemplate<int>;
template struct __declspec(dllimport) ExplicitInstantiationDeclImportedDefTemplate<int>;
USECLASS(ExplicitInstantiationDeclImportedDefTemplate<int>);
USEMEMFUNC(ExplicitInstantiationDeclImportedDefTemplate<int>, f);
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclImportedDefTemplate@H@@QAEXXZ"
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc %struct.ExplicitInstantiationDeclImportedDefTemplate* @"\01??0?$ExplicitInstantiationDeclImportedDefTemplate@H@@QAE@XZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?f@?$ExplicitInstantiationDeclImportedDefTemplate@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc %struct.ExplicitInstantiationDeclImportedDefTemplate* @"??0?$ExplicitInstantiationDeclImportedDefTemplate@H@@QAE@XZ"
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN44ExplicitInstantiationDeclImportedDefTemplateIiE1fEv
template <typename T> struct __declspec(dllimport) ExplicitInstantiationDeclExportedDefImportedTemplate { void f() {} ExplicitInstantiationDeclExportedDefImportedTemplate() {} };
@@ -837,15 +839,15 @@
template struct __declspec(dllexport) ExplicitInstantiationDeclExportedDefImportedTemplate<int>;
USECLASS(ExplicitInstantiationDeclExportedDefImportedTemplate<int>);
USEMEMFUNC(ExplicitInstantiationDeclExportedDefImportedTemplate<int>, f);
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAEXXZ"
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefImportedTemplate* @"\01??0?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAE@XZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?f@?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefImportedTemplate* @"??0?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAE@XZ"
template <typename T> struct PR23770BaseTemplate { void f() {} };
template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {};
extern template struct PR23770DerivedTemplate<int>;
template struct __declspec(dllimport) PR23770DerivedTemplate<int>;
USEMEMFUNC(PR23770BaseTemplate<int>, f);
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?f@?$PR23770BaseTemplate@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?f@?$PR23770BaseTemplate@H@@QAEXXZ"
namespace PR27810 {
template <class T>
@@ -861,7 +863,7 @@
// functions are emitted unless they are used.
USEMEMFUNC(basic_ostream<char>::sentry, foo);
- // M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"\01?foo@sentry@?$basic_ostream@D@PR27810@@QAEXXZ"
+ // M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?foo@sentry@?$basic_ostream@D@PR27810@@QAEXXZ"
// M32-NOT: ??0sentry@?$basic_ostream@D@PR27810@@QAE@XZ
}
@@ -906,69 +908,69 @@
// MS: ClassTemplate<int> gets imported.
struct __declspec(dllimport) DerivedFromTemplate : public ClassTemplate<int> {};
USEMEMFUNC(ClassTemplate<int>, func)
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?func@?$ClassTemplate@H@@QAEXXZ"
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv
// ImportedTemplate is explicitly imported.
struct __declspec(dllimport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {};
USEMEMFUNC(ImportedClassTemplate<int>, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ImportedClassTemplate@H@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN21ImportedClassTemplateIiE4funcEv
// ExportedTemplate is explicitly exported.
struct __declspec(dllimport) DerivedFromExportedTemplate : public ExportedClassTemplate<int> {};
USEMEMFUNC(ExportedClassTemplate<int>, func)
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?func@?$ExportedClassTemplate@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ExportedClassTemplate@H@@QAEXXZ"
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv
// Base class already implicitly instantiated without attribute.
struct DerivedFromTemplateD : public ClassTemplate<double> {};
struct __declspec(dllimport) DerivedFromTemplateD2 : public ClassTemplate<double> {};
USEMEMFUNC(ClassTemplate<double>, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ClassTemplate@N@@QAEXXZ"
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv
// MS: Base class already instantiated with dfferent attribute.
struct __declspec(dllexport) DerivedFromTemplateB : public ClassTemplate<bool> {};
struct __declspec(dllimport) DerivedFromTemplateB2 : public ClassTemplate<bool> {};
USEMEMFUNC(ClassTemplate<bool>, func)
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@_N@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ClassTemplate@_N@@QAEXXZ"
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv
// Base class already specialized without dll attribute.
struct __declspec(dllimport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate<int> {};
USEMEMFUNC(ExplicitlySpecializedTemplate<int>, func)
-// M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"\01?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ"
+// M32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ"
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv
// Base class alredy specialized with export attribute.
struct __declspec(dllimport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate<int> {};
USEMEMFUNC(ExplicitlyExportSpecializedTemplate<int>, func)
-// M32-DAG: define dso_local dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ"
+// M32-DAG: define dso_local dllexport x86_thiscallcc void @"?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ"
// G32-DAG: define dso_local dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv
// Base class already specialized with import attribute.
struct __declspec(dllimport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {};
USEMEMFUNC(ExplicitlyImportSpecializedTemplate<int>, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv
// Base class already instantiated without dll attribute.
struct __declspec(dllimport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {};
USEMEMFUNC(ExplicitlyInstantiatedTemplate<int>, func)
-// M32-DAG: define weak_odr dso_local x86_thiscallcc void @"\01?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local x86_thiscallcc void @"?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ"
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv
// Base class already instantiated with export attribute.
struct __declspec(dllimport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate<int> {};
USEMEMFUNC(ExplicitlyExportInstantiatedTemplate<int>, func)
-// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ"
// G32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv
// Base class already instantiated with import attribute.
struct __declspec(dllimport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {};
USEMEMFUNC(ExplicitlyImportInstantiatedTemplate<int>, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ"
// G32-DAG: declare dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv
// MS: A dll attribute propagates through multiple levels of instantiation.
@@ -976,7 +978,7 @@
template <typename T> struct MiddleClass : public TopClass<T> { };
struct __declspec(dllimport) BottomClass : public MiddleClass<int> { };
USEMEMFUNC(TopClass<int>, func)
-// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$TopClass@H@@QAEXXZ"
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"?func@?$TopClass@H@@QAEXXZ"
// G32-DAG: define linkonce_odr dso_local x86_thiscallcc void @_ZN8TopClassIiE4funcEv
template <typename T> struct ExplicitInstantiationDeclTemplateBase { void func() {} };
@@ -984,7 +986,7 @@
struct __declspec(dllimport) DerivedFromExplicitInstantiationDeclTemplateBase : public ExplicitInstantiationDeclTemplateBase<int> {};
template struct ExplicitInstantiationDeclTemplateBase<int>;
USEMEMFUNC(ExplicitInstantiationDeclTemplateBase<int>, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ"
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN37ExplicitInstantiationDeclTemplateBaseIiE4funcEv
template <typename T> struct ExplicitInstantiationDeclTemplateBase2 { void func() {} };
@@ -992,5 +994,5 @@
struct __declspec(dllimport) DerivedFromExplicitInstantiationDeclTemplateBase2 : public ExplicitInstantiationDeclTemplateBase2<int> {};
template struct __declspec(dllexport) ExplicitInstantiationDeclTemplateBase2<int>;
USEMEMFUNC(ExplicitInstantiationDeclTemplateBase2<int>, func)
-// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitInstantiationDeclTemplateBase2@H@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitInstantiationDeclTemplateBase2@H@@QAEXXZ"
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN38ExplicitInstantiationDeclTemplateBase2IiE4funcEv
diff --git a/test/CodeGenCXX/exceptions-cxx-ehsc.cpp b/test/CodeGenCXX/exceptions-cxx-ehsc.cpp
index e98542e..ae1f463 100644
--- a/test/CodeGenCXX/exceptions-cxx-ehsc.cpp
+++ b/test/CodeGenCXX/exceptions-cxx-ehsc.cpp
@@ -11,9 +11,9 @@
may_throw();
}
}
-// CHECK-LABEL: define dso_local void @"\01?caller@test1@@YAXXZ"(
+// CHECK-LABEL: define dso_local void @"?caller@test1@@YAXXZ"(
// CHECK: call void @never_throws(
-// CHECK: invoke void @"\01?may_throw@test1@@YAXXZ"(
+// CHECK: invoke void @"?may_throw@test1@@YAXXZ"(
namespace test2 {
struct Cleanup { ~Cleanup(); };
@@ -26,6 +26,6 @@
may_throw();
}
}
-// CHECK-LABEL: define dso_local void @"\01?caller@test2@@YAXXZ"(
+// CHECK-LABEL: define dso_local void @"?caller@test2@@YAXXZ"(
// CHECK: invoke void @throws_int(
-// CHECK: invoke void @"\01?may_throw@test2@@YAXXZ"(
+// CHECK: invoke void @"?may_throw@test2@@YAXXZ"(
diff --git a/test/CodeGenCXX/exceptions-cxx-new.cpp b/test/CodeGenCXX/exceptions-cxx-new.cpp
index 3a8ce7d..4906a7b 100644
--- a/test/CodeGenCXX/exceptions-cxx-new.cpp
+++ b/test/CodeGenCXX/exceptions-cxx-new.cpp
@@ -12,16 +12,16 @@
}
}
-// CHECK-LABEL: define dso_local void @"\01?test_catch@@YAXXZ"(
-// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 1)
+// CHECK-LABEL: define dso_local void @"?test_catch@@YAXXZ"(
+// CHECK: invoke i32 @"?f@@YAHH@Z"(i32 1)
// CHECK: to label %[[NORMAL:.*]] unwind label %[[CATCHSWITCH:.*]]
// CHECK: [[CATCHSWITCH]]
// CHECK: %[[CATCHSWITCHPAD:.*]] = catchswitch within none [label %[[CATCH_INT:.*]], label %[[CATCH_DOUBLE:.*]]] unwind to caller
// CHECK: [[CATCH_INT]]
-// CHECK: %[[CATCHPAD_INT:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-// CHECK: call i32 @"\01?f@@YAHH@Z"(i32 2)
+// CHECK: %[[CATCHPAD_INT:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i8* null]
+// CHECK: call i32 @"?f@@YAHH@Z"(i32 2)
// CHECK: catchret from %[[CATCHPAD_INT]] to label %[[LEAVE_INT_CATCH:.*]]
// CHECK: [[LEAVE_INT_CATCH]]
@@ -31,8 +31,8 @@
// CHECK: ret void
// CHECK: [[CATCH_DOUBLE]]
-// CHECK: %[[CATCHPAD_DOUBLE:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"\01??_R0N@8", i32 0, i8* null]
-// CHECK: call i32 @"\01?f@@YAHH@Z"(i32 3)
+// CHECK: %[[CATCHPAD_DOUBLE:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"??_R0N@8", i32 0, i8* null]
+// CHECK: call i32 @"?f@@YAHH@Z"(i32 3)
// CHECK: catchret from %[[CATCHPAD_DOUBLE]] to label %[[LEAVE_DOUBLE_CATCH:.*]]
// CHECK: [[LEAVE_DOUBLE_CATCH]]
@@ -50,22 +50,22 @@
f(1);
}
-// CHECK-LABEL: define dso_local {{.*}} @"\01?test_cleanup@@YAXXZ"(
-// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 1)
+// CHECK-LABEL: define dso_local {{.*}} @"?test_cleanup@@YAXXZ"(
+// CHECK: invoke i32 @"?f@@YAHH@Z"(i32 1)
// CHECK: to label %[[LEAVE_FUNC:.*]] unwind label %[[CLEANUP:.*]]
// CHECK: [[LEAVE_FUNC]]
-// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAEXXZ"(
+// CHECK: call x86_thiscallcc void @"??1Cleanup@@QAE@XZ"(
// CHECK: ret void
// CHECK: [[CLEANUP]]
// CHECK: %[[CLEANUPPAD:.*]] = cleanuppad within none []
-// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAEXXZ"(
+// CHECK: call x86_thiscallcc void @"??1Cleanup@@QAE@XZ"(
// CHECK: cleanupret from %[[CLEANUPPAD]] unwind to caller
-// CHECK-LABEL: define {{.*}} void @"\01??1Cleanup@@QAE@XZ"(
-// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 -1)
+// CHECK-LABEL: define {{.*}} void @"??1Cleanup@@QAE@XZ"(
+// CHECK: invoke i32 @"?f@@YAHH@Z"(i32 -1)
// CHECK: to label %[[LEAVE_FUNC:.*]] unwind label %[[TERMINATE:.*]]
// CHECK: [[LEAVE_FUNC]]
@@ -73,5 +73,5 @@
// CHECK: [[TERMINATE]]
// CHECK: %[[CLEANUPPAD:.*]] = cleanuppad within none []
-// CHECK-NEXT: call void @"\01?terminate@@YAXXZ"() {{.*}} [ "funclet"(token %[[CLEANUPPAD]]) ]
+// CHECK-NEXT: call void @"?terminate@@YAXXZ"() {{.*}} [ "funclet"(token %[[CLEANUPPAD]]) ]
diff --git a/test/CodeGenCXX/exceptions-seh-filter-captures.cpp b/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
index 1f4749f..0e97662 100644
--- a/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
+++ b/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
@@ -20,13 +20,13 @@
// CHECK: store i32 13, i32* %[[l1_ptr]], align 4
// CHECK: invoke void @might_crash()
-// CHECK-LABEL: define internal i32 @"\01?filt$0@0@test_freefunc@@"(i8* %exception_pointers, i8* %frame_pointer)
+// CHECK-LABEL: define internal i32 @"?filt$0@0@test_freefunc@@"(i8* %exception_pointers, i8* %frame_pointer)
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer)
// CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 0)
// CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32*
// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 1)
// CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
-// CHECK: %[[s1:[^ ]*]] = load i32, i32* @"\01?s1@?1??test_freefunc@@9@4HA", align 4
+// CHECK: %[[s1:[^ ]*]] = load i32, i32* @"?s1@?1??test_freefunc@@9@4HA", align 4
// CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
// CHECK: %[[p1:[^ ]*]] = load i32, i32* %[[p1_ptr]]
// CHECK: call i32 (i32, ...) @basic_filter(i32 %[[p1]], i32 %[[l1]], i32 %[[s1]])
@@ -45,14 +45,14 @@
}
}
-// CHECK-LABEL: define dso_local void @"\01?test_method@S@@QEAAXXZ"(%struct.S* %this)
+// CHECK-LABEL: define dso_local void @"?test_method@S@@QEAAXXZ"(%struct.S* %this)
// CHECK: @llvm.localescape(i32* %[[l1_addr:[^, ]*]])
// CHECK: store i32 13, i32* %[[l1_addr]], align 4
// CHECK: invoke void @might_crash()
-// CHECK-LABEL: define internal i32 @"\01?filt$0@0@test_method@S@@"(i8* %exception_pointers, i8* %frame_pointer)
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%struct.S*)* @"\01?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
-// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"\01?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0)
+// CHECK-LABEL: define internal i32 @"?filt$0@0@test_method@S@@"(i8* %exception_pointers, i8* %frame_pointer)
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
+// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0)
// CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
// CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
// CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]])
@@ -70,14 +70,14 @@
lambda();
}
-// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this)
+// CHECK-LABEL: define internal void @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this)
// CHECK: @llvm.localescape(i32* %[[l2_addr:[^, ]*]])
// CHECK: store i32 42, i32* %[[l2_addr]], align 4
// CHECK: invoke void @might_crash()
-// CHECK-LABEL: define internal i32 @"\01?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer)
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%class.anon*)* @"\01??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %frame_pointer)
-// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"\01??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %[[fp]], i32 0)
+// CHECK-LABEL: define internal i32 @"?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer)
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %frame_pointer)
+// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %[[fp]], i32 0)
// CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32*
// CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]]
// CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l2]])
diff --git a/test/CodeGenCXX/exceptions-seh.cpp b/test/CodeGenCXX/exceptions-seh.cpp
index 84159eb..5f88a7b 100644
--- a/test/CodeGenCXX/exceptions-seh.cpp
+++ b/test/CodeGenCXX/exceptions-seh.cpp
@@ -23,26 +23,26 @@
// CXXEH-LABEL: define dso_local void @use_cxx()
// CXXEH-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
-// CXXEH: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// CXXEH: call %struct.HasCleanup* @"??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
// CXXEH: invoke void @might_throw()
// CXXEH: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CXXEH: [[cont]]
-// CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// CXXEH: call void @"??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
// CXXEH: ret void
//
// CXXEH: [[lpad]]
// CXXEH: cleanuppad
-// CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// CXXEH: call void @"??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
// CXXEH: cleanupret
// NOCXX-LABEL: define dso_local void @use_cxx()
// NOCXX-NOT: invoke
-// NOCXX: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// NOCXX: call %struct.HasCleanup* @"??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
// NOCXX-NOT: invoke
// NOCXX: call void @might_throw()
// NOCXX-NOT: invoke
-// NOCXX: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
+// NOCXX: call void @"??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
// NOCXX-NOT: invoke
// NOCXX: ret void
@@ -90,12 +90,12 @@
// CHECK-LABEL: define dso_local void @nested_finally() #{{[0-9]+}}
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// CHECK: invoke void @might_throw()
-// CHECK: call void @"\01?fin$0@0@nested_finally@@"(i8 1, i8* {{.*}})
+// CHECK: call void @"?fin$0@0@nested_finally@@"(i8 1, i8* {{.*}})
-// CHECK-LABEL: define internal void @"\01?fin$0@0@nested_finally@@"
+// CHECK-LABEL: define internal void @"?fin$0@0@nested_finally@@"
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// CHECK: invoke void @might_throw()
-// CHECK: call void @"\01?fin$1@0@nested_finally@@"(i8 1, i8* {{.*}})
+// CHECK: call void @"?fin$1@0@nested_finally@@"(i8 1, i8* {{.*}})
void use_seh_in_lambda() {
([]() {
@@ -108,15 +108,15 @@
might_throw();
}
-// CXXEH-LABEL: define dso_local void @"\01?use_seh_in_lambda@@YAXXZ"()
+// CXXEH-LABEL: define dso_local void @"?use_seh_in_lambda@@YAXXZ"()
// CXXEH-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
// CXXEH: cleanuppad
-// NOCXX-LABEL: define dso_local void @"\01?use_seh_in_lambda@@YAXXZ"()
+// NOCXX-LABEL: define dso_local void @"?use_seh_in_lambda@@YAXXZ"()
// NOCXX-NOT: invoke
// NOCXX: ret void
-// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?0??use_seh_in_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this)
+// CHECK-LABEL: define internal void @"??R<lambda_0>@?0??use_seh_in_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this)
// CXXEH-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// CHECK: invoke void @might_throw() #[[NOINLINE]]
// CHECK: catchpad
@@ -143,24 +143,24 @@
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// CHECK: invoke void @might_throw()
//
-// CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)]
+// CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"?filt$0@0@use_seh_in_inline_func@@" to i8*)]
//
// CHECK: invoke void @might_throw()
//
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 0, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@use_seh_in_inline_func@@"(i8 0, i8* %[[fp]])
// CHECK: ret void
//
// CHECK: cleanuppad
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]])
+// CHECK: call void @"?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]])
-// CHECK-LABEL: define internal i32 @"\01?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}}
+// CHECK-LABEL: define internal i32 @"?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}}
// CHECK: icmp eq i32 %{{.*}}, 424242
// CHECK: zext i1 %{{.*}} to i32
// CHECK: ret i32
-// CHECK-LABEL: define internal void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 %abnormal_termination, i8* %frame_pointer) #{{[0-9]+}}
+// CHECK-LABEL: define internal void @"?fin$0@0@use_seh_in_inline_func@@"(i8 %abnormal_termination, i8* %frame_pointer) #{{[0-9]+}}
// CHECK: store i32 1234, i32* @my_unique_global
// CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} }
diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp
index a7fba38..07c5f72 100644
--- a/test/CodeGenCXX/explicit-instantiation.cpp
+++ b/test/CodeGenCXX/explicit-instantiation.cpp
@@ -119,14 +119,14 @@
// definition of Inner.
template struct Outer<int>;
// CHECK: define weak_odr void @_ZN13NestedClasses5OuterIiE5Inner1fEv
- // CHECK-MS: define weak_odr dso_local x86_thiscallcc void @"\01?f@Inner@?$Outer@H@NestedClasses@@QAEXXZ"
+ // CHECK-MS: define weak_odr dso_local x86_thiscallcc void @"?f@Inner@?$Outer@H@NestedClasses@@QAEXXZ"
// Explicit instantiation declaration of Outer causes explicit instantiation
// declaration of Inner, but not in MSVC mode.
extern template struct Outer<char>;
auto use = &Outer<char>::Inner::f;
// CHECK: {{declare|define available_externally}} void @_ZN13NestedClasses5OuterIcE5Inner1fEv
- // CHECK-MS: define linkonce_odr dso_local x86_thiscallcc void @"\01?f@Inner@?$Outer@D@NestedClasses@@QAEXXZ"
+ // CHECK-MS: define linkonce_odr dso_local x86_thiscallcc void @"?f@Inner@?$Outer@D@NestedClasses@@QAEXXZ"
}
// Check that we emit definitions from explicit instantiations even when they
diff --git a/test/CodeGenCXX/funcsig.cpp b/test/CodeGenCXX/funcsig.cpp
index 16e5f7e..5328ff9 100644
--- a/test/CodeGenCXX/funcsig.cpp
+++ b/test/CodeGenCXX/funcsig.cpp
@@ -12,24 +12,24 @@
void funcNoProto() {
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
-// CHECK-C: @"\01??_C@_0BL@IHLLLCAO@void?5__cdecl?5funcNoProto?$CI?$CJ?$AA@" = linkonce_odr unnamed_addr constant [27 x i8] c"void __cdecl funcNoProto()\00"
-// CHECK-CXX: @"\01??_C@_0BP@PJOECCJN@void?5__cdecl?5funcNoProto?$CIvoid?$CJ?$AA@" = linkonce_odr unnamed_addr constant [31 x i8] c"void __cdecl funcNoProto(void)\00"
+// CHECK-C: @"??_C@_0BL@IHLLLCAO@void?5__cdecl?5funcNoProto?$CI?$CJ?$AA@" = linkonce_odr dso_local unnamed_addr constant [27 x i8] c"void __cdecl funcNoProto()\00"
+// CHECK-CXX: @"??_C@_0BP@PJOECCJN@void?5__cdecl?5funcNoProto?$CIvoid?$CJ?$AA@" = linkonce_odr dso_local unnamed_addr constant [31 x i8] c"void __cdecl funcNoProto(void)\00"
void funcNoParams(void) {
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
-// CHECK: @"\01??_C@_0CA@GBIDFNBN@void?5__cdecl?5funcNoParams?$CIvoid?$CJ?$AA@" = linkonce_odr unnamed_addr constant [32 x i8] c"void __cdecl funcNoParams(void)\00"
+// CHECK: @"??_C@_0CA@GBIDFNBN@void?5__cdecl?5funcNoParams?$CIvoid?$CJ?$AA@" = linkonce_odr dso_local unnamed_addr constant [32 x i8] c"void __cdecl funcNoParams(void)\00"
void freeFunc(int *p, char c) {
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
-// CHECK: @"\01??_C@_0CD@KLGMNNL@void?5__cdecl?5freeFunc?$CIint?5?$CK?0?5cha@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00"
+// CHECK: @"??_C@_0CD@KLGMNNL@void?5__cdecl?5freeFunc?$CIint?5?$CK?0?5cha@" = linkonce_odr dso_local unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00"
#ifdef __cplusplus
void funcVarargs(...) {
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
-// CHECK-CXX: @"\01??_C@_0BO@BOBPLEKP@void?5__cdecl?5funcVarargs?$CI?4?4?4?$CJ?$AA@" = linkonce_odr unnamed_addr constant [30 x i8] c"void __cdecl funcVarargs(...)\00"
+// CHECK-CXX: @"??_C@_0BO@BOBPLEKP@void?5__cdecl?5funcVarargs?$CI?4?4?4?$CJ?$AA@" = linkonce_odr dso_local unnamed_addr constant [30 x i8] c"void __cdecl funcVarargs(...)\00"
struct TopLevelClass {
void topLevelMethod(int *, char);
@@ -37,7 +37,7 @@
void TopLevelClass::topLevelMethod(int *, char) {
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
-// CHECK-CXX: @"\01??_C@_0DL@OBHNMDP@void?5__thiscall?5TopLevelClass?3?3t@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00"
+// CHECK-CXX: @"??_C@_0DL@OBHNMDP@void?5__thiscall?5TopLevelClass?3?3t@" = linkonce_odr dso_local unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00"
namespace NS {
struct NamespacedClass {
@@ -46,6 +46,6 @@
void NamespacedClass::namespacedMethod(int *, char) {
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
}
-// CHECK-CXX: @"\01??_C@_0ED@PFDKIEBA@void?5__thiscall?5NS?3?3NamespacedCl@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00"
+// CHECK-CXX: @"??_C@_0ED@PFDKIEBA@void?5__thiscall?5NS?3?3NamespacedCl@" = linkonce_odr dso_local unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00"
}
#endif
diff --git a/test/CodeGenCXX/hidden-dllimport.cpp b/test/CodeGenCXX/hidden-dllimport.cpp
index 9de0d71..573b421 100644
--- a/test/CodeGenCXX/hidden-dllimport.cpp
+++ b/test/CodeGenCXX/hidden-dllimport.cpp
@@ -2,7 +2,7 @@
// We used to declare this hidden dllimport, which is contradictory.
-// CHECK: declare dllimport void @"\01?bar@foo@@QEAAXXZ"(%struct.foo*)
+// CHECK: declare dllimport void @"?bar@foo@@QEAAXXZ"(%struct.foo*)
struct __attribute__((dllimport)) foo {
void bar() {}
diff --git a/test/CodeGenCXX/inheriting-constructor.cpp b/test/CodeGenCXX/inheriting-constructor.cpp
index 1be59b9..fa3e5ab 100644
--- a/test/CodeGenCXX/inheriting-constructor.cpp
+++ b/test/CodeGenCXX/inheriting-constructor.cpp
@@ -18,8 +18,8 @@
// ITANIUM-LABEL: define void @_ZN1BD2Ev
// ITANIUM-LABEL: define void @_ZN1BD1Ev
// ITANIUM-LABEL: define void @_ZN1BD0Ev
-// WIN32-LABEL: define {{.*}}void @"\01??1B@@UAE@XZ"
-// WIN64-LABEL: define {{.*}}void @"\01??1B@@UEAA@XZ"
+// WIN32-LABEL: define {{.*}}void @"??1B@@UAE@XZ"
+// WIN64-LABEL: define {{.*}}void @"??1B@@UEAA@XZ"
// ITANIUM-LABEL: define linkonce_odr void @_ZN1BCI11AEi(
// ITANIUM: call void @_ZN1BCI21AEi(
@@ -27,15 +27,15 @@
// ITANIUM-LABEL: define linkonce_odr void @_ZN1DCI11CIiEET_(
// ITANIUM: call void @_ZN1DCI21CIiEET_(
-// WIN32-LABEL: define internal {{.*}} @"\01??0B@@QAE@H@Z"(
-// WIN32: call {{.*}} @"\01??0A@@QAE@H@Z"(
-// WIN64-LABEL: define internal {{.*}} @"\01??0B@@QEAA@H@Z"(
-// WIN64: call {{.*}} @"\01??0A@@QEAA@H@Z"(
+// WIN32-LABEL: define internal {{.*}} @"??0B@@QAE@H@Z"(
+// WIN32: call {{.*}} @"??0A@@QAE@H@Z"(
+// WIN64-LABEL: define internal {{.*}} @"??0B@@QEAA@H@Z"(
+// WIN64: call {{.*}} @"??0A@@QEAA@H@Z"(
-// WIN32-LABEL: define internal {{.*}} @"\01??0D@@QAE@H@Z"(
-// WIN32: call {{.*}} @"\01??$?0H@C@@QAE@H@Z"
-// WIN64-LABEL: define internal {{.*}} @"\01??0D@@QEAA@H@Z"(
-// WIN64: call {{.*}} @"\01??$?0H@C@@QEAA@H@Z"
+// WIN32-LABEL: define internal {{.*}} @"??0D@@QAE@H@Z"(
+// WIN32: call {{.*}} @"??$?0H@C@@QAE@H@Z"
+// WIN64-LABEL: define internal {{.*}} @"??0D@@QEAA@H@Z"(
+// WIN64: call {{.*}} @"??$?0H@C@@QEAA@H@Z"
struct Q { Q(int); Q(const Q&); ~Q(); };
struct Z { Z(); Z(int); ~Z(); int n; };
@@ -55,10 +55,10 @@
// ITANIUM: call void @_ZN17noninline_nonvirt1BCI2NS_1AEEiO1QPvU17pass_object_size0({{.*}}, i32 {{.*}}, %{{.*}}* {{.*}}, i8* {{.*}}, i{{32|64}} {{.*}})
// In MSABI, we don't have ctor variants. B ctor forwards to A ctor.
- // MSABI-LABEL: define internal {{.*}} @"\01??0B@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
- // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"(
- // MSABI: call {{.*}} @"\01??0A@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
- // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"(
+ // MSABI-LABEL: define internal {{.*}} @"??0B@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
+ // MSABI: call {{.*}} @"??0Z@@Q{{AE|EAA}}@XZ"(
+ // MSABI: call {{.*}} @"??0A@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
+ // MSABI: call {{.*}} @"??0Z@@Q{{AE|EAA}}@XZ"(
struct C : B { using B::B; };
C c(1, 2, &c);
@@ -66,8 +66,8 @@
// ITANIUM-LABEL: define linkonce_odr void @_ZN17noninline_nonvirt1CCI1NS_1AEEiO1QPvU17pass_object_size0(
// ITANIUM: call void @_ZN17noninline_nonvirt1CCI2NS_1AEEiO1QPvU17pass_object_size0({{.*}}, i32 {{.*}}, %{{.*}}* {{.*}}, i8* {{.*}}, i{{32|64}} {{.*}})
- // MSABI-LABEL: define internal {{.*}} @"\01??0C@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
- // MSABI: call {{.*}} @"\01??0B@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
+ // MSABI-LABEL: define internal {{.*}} @"??0C@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
+ // MSABI: call {{.*}} @"??0B@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
}
namespace noninline_virt {
@@ -81,13 +81,13 @@
// ITANIUM: store {{.*}} @_ZTVN14noninline_virt1BE
// ITANIUM: call void @_ZN1ZC1Ev(
- // MSABI-LABEL: define internal {{.*}} @"\01??0B@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 %{{.*}})
+ // MSABI-LABEL: define internal {{.*}} @"??0B@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 %{{.*}})
// MSABI: %[[COMPLETE:.*]] = icmp ne
// MSABI: br i1 %[[COMPLETE]],
- // MSABI: call {{.*}} @"\01??0A@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
+ // MSABI: call {{.*}} @"??0A@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
// MSABI: br
- // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"(
- // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"(
+ // MSABI: call {{.*}} @"??0Z@@Q{{AE|EAA}}@XZ"(
+ // MSABI: call {{.*}} @"??0Z@@Q{{AE|EAA}}@XZ"(
struct C : B { using B::B; };
C c(1, 2, &c);
@@ -101,12 +101,12 @@
// C constructor forwards to B constructor and A constructor. We pass the args
// to both. FIXME: Can we pass undef here instead, for the base object
// constructor call?
- // MSABI-LABEL: define internal {{.*}} @"\01??0C@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 %{{.*}})
+ // MSABI-LABEL: define internal {{.*}} @"??0C@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 %{{.*}})
// MSABI: %[[COMPLETE:.*]] = icmp ne
// MSABI: br i1 %[[COMPLETE]],
- // MSABI: call {{.*}} @"\01??0A@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
+ // MSABI: call {{.*}} @"??0A@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}})
// MSABI: br
- // MSABI: call {{.*}} @"\01??0B@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 0)
+ // MSABI: call {{.*}} @"??0B@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 0)
}
// For MSABI only, check that inalloca arguments result in inlining.
@@ -118,75 +118,75 @@
// ITANIUM-LABEL: define linkonce_odr void @_ZN16inalloca_nonvirt1BCI1NS_1AEE1QiS1_OS1_(
// ITANIUM: call void @_ZN16inalloca_nonvirt1BCI2NS_1AEE1QiS1_OS1_(
- // MSABI-LABEL: define internal void @"\01??__Eb@inalloca_nonvirt@@YAXXZ"(
+ // MSABI-LABEL: define internal void @"??__Eb@inalloca_nonvirt@@YAXXZ"(
// On Win32, the inalloca call can't be forwarded so we force inlining.
// WIN32: %[[TMP:.*]] = alloca
// WIN32: call i8* @llvm.stacksave()
// WIN32: %[[ARGMEM:.*]] = alloca inalloca
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
// WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
// WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
// WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store i32 2, i32* %[[ARG2]]
// WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
- // WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
+ // WIN32: call {{.*}} @"??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
// WIN32: call void @llvm.stackrestore(
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
- // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"(
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??1Q@@QAE@XZ"(
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
// support that in the non-inlined case, so we force inlining.
// WIN64: %[[TMP:.*]] = alloca
// WIN64: %[[ARG3:.*]] = alloca
// WIN64: %[[ARG1:.*]] = alloca
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]])
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call {{.*}} @"??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call void @"??1Q@@QEAA@XZ"({{.*}}* %[[TMP]])
struct C : B { using B::B; };
C c(1, 2, 3, 4);
- // MSABI-LABEL: define internal void @"\01??__Ec@inalloca_nonvirt@@YAXXZ"(
+ // MSABI-LABEL: define internal void @"??__Ec@inalloca_nonvirt@@YAXXZ"(
// On Win32, the inalloca call can't be forwarded so we force inlining.
// WIN32: %[[TMP:.*]] = alloca
// WIN32: call i8* @llvm.stacksave()
// WIN32: %[[ARGMEM:.*]] = alloca inalloca
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
// WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
// WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
// WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store i32 2, i32* %[[ARG2]]
// WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
- // WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
+ // WIN32: call {{.*}} @"??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
// WIN32: call void @llvm.stackrestore(
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
- // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"(
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??1Q@@QAE@XZ"(
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
// support that in the non-inlined case, so we force inlining.
// WIN64: %[[TMP:.*]] = alloca
// WIN64: %[[ARG3:.*]] = alloca
// WIN64: %[[ARG1:.*]] = alloca
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]])
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call {{.*}} @"??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call void @"??1Q@@QEAA@XZ"({{.*}}* %[[TMP]])
}
namespace inalloca_virt {
@@ -194,79 +194,79 @@
struct B : Z, virtual A { Z z; using A::A; };
B b(1, 2, 3, 4);
- // MSABI-LABEL: define internal void @"\01??__Eb@inalloca_virt@@YAXXZ"(
+ // MSABI-LABEL: define internal void @"??__Eb@inalloca_virt@@YAXXZ"(
// On Win32, the inalloca call can't be forwarded so we force inlining.
// WIN32: %[[TMP:.*]] = alloca
// WIN32: call i8* @llvm.stacksave()
// WIN32: %[[ARGMEM:.*]] = alloca inalloca
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
// WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
// WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
// FIXME: It's dumb to round-trip this though memory and generate a branch.
// WIN32: store i32 1, i32* %[[IS_MOST_DERIVED_ADDR:.*]]
// WIN32: %[[IS_MOST_DERIVED:.*]] = load i32, i32* %[[IS_MOST_DERIVED_ADDR]]
// WIN32: %[[IS_MOST_DERIVED_i1:.*]] = icmp ne i32 %[[IS_MOST_DERIVED]], 0
// WIN32: br i1 %[[IS_MOST_DERIVED_i1]]
//
- // WIN32: store {{.*}} @"\01??_8B@inalloca_virt@@7B@"
+ // WIN32: store {{.*}} @"??_8B@inalloca_virt@@7B@"
// WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store i32 2, i32* %[[ARG2]]
// WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
- // WIN32: call {{.*}} @"\01??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
+ // WIN32: call {{.*}} @"??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
// WIN32: call void @llvm.stackrestore(
// WIN32: br
//
// Note that if we jumped directly to here we would fail to stackrestore and
// destroy the parameters, but that's not actually possible.
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
- // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"(
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??1Q@@QAE@XZ"(
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
// support that in the non-inlined case, so we force inlining.
// WIN64: %[[TMP:.*]] = alloca
// WIN64: %[[ARG3:.*]] = alloca
// WIN64: %[[ARG1:.*]] = alloca
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
// WIN64: br i1
- // WIN64: call {{.*}} @"\01??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
+ // WIN64: call {{.*}} @"??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
// WIN64: br
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]])
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call void @"??1Q@@QEAA@XZ"({{.*}}* %[[TMP]])
struct C : B { using B::B; };
C c(1, 2, 3, 4);
// ITANIUM-LABEL: define linkonce_odr void @_ZN13inalloca_virt1CD1Ev(
- // MSABI-LABEL: define internal void @"\01??__Ec@inalloca_virt@@YAXXZ"(
+ // MSABI-LABEL: define internal void @"??__Ec@inalloca_virt@@YAXXZ"(
// On Win32, the inalloca call can't be forwarded so we force inlining.
// WIN32: %[[TMP:.*]] = alloca
// WIN32: call i8* @llvm.stacksave()
// WIN32: %[[ARGMEM:.*]] = alloca inalloca
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4)
// WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3)
// WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]]
- // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN32: call {{.*}} @"??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1)
// WIN32: store i32 1, i32* %[[IS_MOST_DERIVED_ADDR:.*]]
// WIN32: %[[IS_MOST_DERIVED:.*]] = load i32, i32* %[[IS_MOST_DERIVED_ADDR]]
// WIN32: %[[IS_MOST_DERIVED_i1:.*]] = icmp ne i32 %[[IS_MOST_DERIVED]], 0
// WIN32: br i1 %[[IS_MOST_DERIVED_i1]]
//
- // WIN32: store {{.*}} @"\01??_8C@inalloca_virt@@7B@"
+ // WIN32: store {{.*}} @"??_8C@inalloca_virt@@7B@"
// WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store i32 2, i32* %[[ARG2]]
// WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
// WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
- // WIN32: call {{.*}} @"\01??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
+ // WIN32: call {{.*}} @"??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
// WIN32: call void @llvm.stackrestore(
// WIN32: br
//
@@ -276,32 +276,32 @@
// WIN32: br i1 %[[IS_MOST_DERIVED_i1]]
//
// Note: this block is unreachable.
- // WIN32: store {{.*}} @"\01??_8B@inalloca_virt@@7B@"
+ // WIN32: store {{.*}} @"??_8B@inalloca_virt@@7B@"
// WIN32: br
//
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
- // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
- // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"(
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??0Z@@QAE@XZ"(
+ // WIN32: call {{.*}} @"??1Q@@QAE@XZ"(
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
// support that in the non-inlined case, so we force inlining.
// WIN64: %[[TMP:.*]] = alloca
// WIN64: %[[ARG3:.*]] = alloca
// WIN64: %[[ARG1:.*]] = alloca
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
- // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3)
+ // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1)
// WIN64: br i1
- // WIN64: store {{.*}} @"\01??_8C@inalloca_virt@@7B@"
- // WIN64: call {{.*}} @"\01??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
+ // WIN64: store {{.*}} @"??_8C@inalloca_virt@@7B@"
+ // WIN64: call {{.*}} @"??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
// WIN64: br
// WIN64: br i1
// (Unreachable block)
- // WIN64: store {{.*}} @"\01??_8B@inalloca_virt@@7B@"
+ // WIN64: store {{.*}} @"??_8B@inalloca_virt@@7B@"
// WIN64: br
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
- // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]])
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"(
+ // WIN64: call void @"??1Q@@QEAA@XZ"({{.*}}* %[[TMP]])
}
namespace inline_nonvirt {
diff --git a/test/CodeGenCXX/initializer-list-ctor-order.cpp b/test/CodeGenCXX/initializer-list-ctor-order.cpp
index 70f264c..6bb9c1b 100644
--- a/test/CodeGenCXX/initializer-list-ctor-order.cpp
+++ b/test/CodeGenCXX/initializer-list-ctor-order.cpp
@@ -15,7 +15,7 @@
A a{f(), g()};
}
// CHECK-ITANIUM-LABEL: define void @_Z3foov
-// CHECK-MS-LABEL: define dso_local void @"\01?foo@@YAXXZ"
+// CHECK-MS-LABEL: define dso_local void @"?foo@@YAXXZ"
// CHECK: call i32 @f()
// CHECK: call i32 @g()
@@ -24,6 +24,6 @@
};
B::B() : A{f(), g()} {}
// CHECK-ITANIUM-LABEL: define void @_ZN1BC2Ev
-// CHECK-MS-LABEL: define dso_local x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"
+// CHECK-MS-LABEL: define dso_local x86_thiscallcc %struct.B* @"??0B@@QAE@XZ"
// CHECK: call i32 @f()
// CHECK: call i32 @g()
diff --git a/test/CodeGenCXX/inline-dllexport-member.cpp b/test/CodeGenCXX/inline-dllexport-member.cpp
index ee0e8ce..d6b004d 100644
--- a/test/CodeGenCXX/inline-dllexport-member.cpp
+++ b/test/CodeGenCXX/inline-dllexport-member.cpp
@@ -1,13 +1,13 @@
// RUN: %clang_cc1 -triple i686-windows-win32 -fms-extensions -debug-info-kind=limited -emit-llvm %s -o - \
// RUN: | FileCheck %s
-// CHECK: @"\01?ui@s@@2IB" = weak_odr dso_local dllexport constant i32 0, comdat, align 4, !dbg [[UI:![0-9]+]]
+// CHECK: @"?ui@s@@2IB" = weak_odr dso_local dllexport constant i32 0, comdat, align 4, !dbg [[UI:![0-9]+]]
struct __declspec(dllexport) s {
static const unsigned int ui = 0;
};
// CHECK: [[UI]] = !DIGlobalVariableExpression(var: [[UIV:.*]], expr: !DIExpression())
-// CHECK: [[UIV]] = distinct !DIGlobalVariable(name: "ui", linkageName: "\01?ui@s@@2IB", scope: ![[SCOPE:[0-9]+]],
+// CHECK: [[UIV]] = distinct !DIGlobalVariable(name: "ui", linkageName: "?ui@s@@2IB", scope: ![[SCOPE:[0-9]+]],
// CHECK: ![[SCOPE]] = distinct !DICompileUnit(
diff --git a/test/CodeGenCXX/inline-functions.cpp b/test/CodeGenCXX/inline-functions.cpp
index 9fd8d14..95aec8b 100644
--- a/test/CodeGenCXX/inline-functions.cpp
+++ b/test/CodeGenCXX/inline-functions.cpp
@@ -7,7 +7,7 @@
};
// NORMAL-NOT: define void @_ZN1A1fEv
-// MSVCCOMPAT-NOT: define void @"\01?f@A@@QEAAXXZ"
+// MSVCCOMPAT-NOT: define void @"?f@A@@QEAAXXZ"
void A::f() { }
template<typename> struct B { };
@@ -17,20 +17,20 @@
};
// NORMAL-NOT: _ZN1BIcE1fEv
-// MSVCCOMPAT-NOT: @"\01?f@?$B@D@@QEAAXXZ"
+// MSVCCOMPAT-NOT: @"?f@?$B@D@@QEAAXXZ"
void B<char>::f() { }
// We need a final CHECK line here.
// NORMAL-LABEL: define void @_Z1fv
-// MSVCCOMPAT-LABEL: define dso_local void @"\01?f@@YAXXZ"
+// MSVCCOMPAT-LABEL: define dso_local void @"?f@@YAXXZ"
void f() { }
// <rdar://problem/8740363>
inline void f1(int);
// NORMAL-LABEL: define linkonce_odr void @_Z2f1i
-// MSVCCOMPAT-LABEL: define linkonce_odr dso_local void @"\01?f1@@YAXH@Z"
+// MSVCCOMPAT-LABEL: define linkonce_odr dso_local void @"?f1@@YAXH@Z"
void f1(int) { }
void test_f1() { f1(17); }
@@ -44,7 +44,7 @@
};
// NORMAL-LABEL: define linkonce_odr void @_ZN5test11C4funcEv(
- // MSVCCOMPAT-LABEL: define linkonce_odr dso_local void @"\01?func@C@test1@@QEAAXXZ"(
+ // MSVCCOMPAT-LABEL: define linkonce_odr dso_local void @"?func@C@test1@@QEAAXXZ"(
class C {
public:
@@ -72,47 +72,47 @@
f(a);
}
// NORMAL-LABEL: define linkonce_odr void @_ZN5test21fERKNS_1AE
- // MSVCCOMPAT-LABEL: define linkonce_odr dso_local void @"\01?f@test2@@YAXAEBUA@1@@Z"
+ // MSVCCOMPAT-LABEL: define linkonce_odr dso_local void @"?f@test2@@YAXAEBUA@1@@Z"
}
// NORMAL-NOT: _Z17ExternAndInlineFnv
-// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"\01?ExternAndInlineFn@@YAXXZ"
+// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"?ExternAndInlineFn@@YAXXZ"
extern inline void ExternAndInlineFn() {}
// NORMAL-NOT: _Z18InlineThenExternFnv
-// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"\01?InlineThenExternFn@@YAXXZ"
+// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"?InlineThenExternFn@@YAXXZ"
inline void InlineThenExternFn() {}
extern void InlineThenExternFn();
// NORMAL-LABEL: define void @_Z18ExternThenInlineFnv
-// MSVCCOMPAT-LABEL: define dso_local void @"\01?ExternThenInlineFn@@YAXXZ"
+// MSVCCOMPAT-LABEL: define dso_local void @"?ExternThenInlineFn@@YAXXZ"
extern void ExternThenInlineFn() {}
// NORMAL-NOT: _Z25ExternThenInlineThenDefFnv
-// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"\01?ExternThenInlineThenDefFn@@YAXXZ"
+// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"?ExternThenInlineThenDefFn@@YAXXZ"
extern void ExternThenInlineThenDefFn();
inline void ExternThenInlineThenDefFn();
void ExternThenInlineThenDefFn() {}
// NORMAL-NOT: _Z25InlineThenExternThenDefFnv
-// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"\01?InlineThenExternThenDefFn@@YAXXZ"
+// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"?InlineThenExternThenDefFn@@YAXXZ"
inline void InlineThenExternThenDefFn();
extern void InlineThenExternThenDefFn();
void InlineThenExternThenDefFn() {}
// NORMAL-NOT: _Z17ExternAndConstexprFnv
-// MSVCCOMPAT-LABEL: define weak_odr dso_local i32 @"\01?ExternAndConstexprFn@@YAHXZ"
+// MSVCCOMPAT-LABEL: define weak_odr dso_local i32 @"?ExternAndConstexprFn@@YAHXZ"
extern constexpr int ExternAndConstexprFn() { return 0; }
// NORMAL-NOT: _Z11ConstexprFnv
-// MSVCCOMPAT-NOT: @"\01?ConstexprFn@@YAHXZ"
+// MSVCCOMPAT-NOT: @"?ConstexprFn@@YAHXZ"
constexpr int ConstexprFn() { return 0; }
template <typename T>
extern inline void ExternInlineOnPrimaryTemplate(T);
// NORMAL-LABEL: define void @_Z29ExternInlineOnPrimaryTemplateIiEvT_
-// MSVCCOMPAT-LABEL: define dso_local void @"\01??$ExternInlineOnPrimaryTemplate@H@@YAXH@Z"
+// MSVCCOMPAT-LABEL: define dso_local void @"??$ExternInlineOnPrimaryTemplate@H@@YAXH@Z"
template <>
void ExternInlineOnPrimaryTemplate(int) {}
@@ -120,16 +120,16 @@
extern inline void ExternInlineOnPrimaryTemplateAndSpecialization(T);
// NORMAL-NOT: _Z46ExternInlineOnPrimaryTemplateAndSpecializationIiEvT_
-// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"\01??$ExternInlineOnPrimaryTemplateAndSpecialization@H@@YAXH@Z"
+// MSVCCOMPAT-LABEL: define weak_odr dso_local void @"??$ExternInlineOnPrimaryTemplateAndSpecialization@H@@YAXH@Z"
template <>
extern inline void ExternInlineOnPrimaryTemplateAndSpecialization(int) {}
struct TypeWithInlineMethods {
// NORMAL-NOT: _ZN21TypeWithInlineMethods9StaticFunEv
- // MSVCCOMPAT-NOT: @"\01?StaticFun@TypeWithInlineMethods@@SAXXZ"
+ // MSVCCOMPAT-NOT: @"?StaticFun@TypeWithInlineMethods@@SAXXZ"
static void StaticFun() {}
// NORMAL-NOT: _ZN21TypeWithInlineMethods12NonStaticFunEv
- // MSVCCOMPAT-NOT: @"\01?NonStaticFun@TypeWithInlineMethods@@QEAAXXZ"
+ // MSVCCOMPAT-NOT: @"?NonStaticFun@TypeWithInlineMethods@@QEAAXXZ"
void NonStaticFun() { StaticFun(); }
};
@@ -146,5 +146,5 @@
__attribute__((used)) inline S<int> Foo() { return S<int>(); }
// NORMAL-LABEL: define linkonce_odr void @_ZN7PR229593FooEv(
-// MSVCCOMPAT-LABEL: define linkonce_odr dso_local i8 @"\01?Foo@PR22959@@YA?AU?$S@H@1@XZ"(
+// MSVCCOMPAT-LABEL: define linkonce_odr dso_local i8 @"?Foo@PR22959@@YA?AU?$S@H@1@XZ"(
}
diff --git a/test/CodeGenCXX/mangle-ms-abi-examples.cpp b/test/CodeGenCXX/mangle-ms-abi-examples.cpp
index 6b6ad89..2f8490a 100644
--- a/test/CodeGenCXX/mangle-ms-abi-examples.cpp
+++ b/test/CodeGenCXX/mangle-ms-abi-examples.cpp
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -fms-extensions -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=19.00 | FileCheck %s --check-prefix=CHECK --check-prefix=MSVC2015
// RUN: %clang_cc1 -fms-extensions -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=18.00 | FileCheck %s --check-prefix=CHECK --check-prefix=MSVC2013
-// CHECK: @"\01??_7B@?1??foo@A@@QAEXH@Z@6B@" =
-// CHECK: @"\01??_7D@C@?1??foo@@YAXXZ@6B@" =
-// MSVC2013: define {{.*}} @"\01?baz@E@?3??bar@C@?1??foo@@YAXXZ@QAEXXZ@QAEXXZ"(
-// MSVC2015: define {{.*}} @"\01?baz@E@?1??bar@C@?1??foo@@YAXXZ@QAEXXZ@QAEXXZ"(
+// CHECK: @"??_7B@?1??foo@A@@QAEXH@Z@6B@" =
+// CHECK: @"??_7D@C@?1??foo@@YAXXZ@6B@" =
+// MSVC2013: define {{.*}} @"?baz@E@?3??bar@C@?1??foo@@YAXXZ@QAEXXZ@QAEXXZ"(
+// MSVC2015: define {{.*}} @"?baz@E@?1??bar@C@?1??foo@@YAXXZ@QAEXXZ@QAEXXZ"(
// Microsoft Visual C++ ABI examples.
struct A {
diff --git a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
index ad0299e..23582c6 100644
--- a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
+++ b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
@@ -2,268 +2,268 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck -check-prefix=X64 %s
void foo(const unsigned int) {}
-// CHECK: "\01?foo@@YAXI@Z"
-// X64: "\01?foo@@YAXI@Z"
+// CHECK: "?foo@@YAXI@Z"
+// X64: "?foo@@YAXI@Z"
void foo(const double) {}
-// CHECK: "\01?foo@@YAXN@Z"
-// X64: "\01?foo@@YAXN@Z"
+// CHECK: "?foo@@YAXN@Z"
+// X64: "?foo@@YAXN@Z"
void bar(const volatile double) {}
-// CHECK: "\01?bar@@YAXN@Z"
-// X64: "\01?bar@@YAXN@Z"
+// CHECK: "?bar@@YAXN@Z"
+// X64: "?bar@@YAXN@Z"
void foo_pad(char * x) {}
-// CHECK: "\01?foo_pad@@YAXPAD@Z"
-// X64: "\01?foo_pad@@YAXPEAD@Z"
+// CHECK: "?foo_pad@@YAXPAD@Z"
+// X64: "?foo_pad@@YAXPEAD@Z"
void foo_pbd(const char * x) {}
-// CHECK: "\01?foo_pbd@@YAXPBD@Z"
-// X64: "\01?foo_pbd@@YAXPEBD@Z"
+// CHECK: "?foo_pbd@@YAXPBD@Z"
+// X64: "?foo_pbd@@YAXPEBD@Z"
void foo_pcd(volatile char * x) {}
-// CHECK: "\01?foo_pcd@@YAXPCD@Z"
-// X64: "\01?foo_pcd@@YAXPECD@Z"
+// CHECK: "?foo_pcd@@YAXPCD@Z"
+// X64: "?foo_pcd@@YAXPECD@Z"
void foo_qad(char * const x) {}
-// CHECK: "\01?foo_qad@@YAXQAD@Z"
-// X64: "\01?foo_qad@@YAXQEAD@Z"
+// CHECK: "?foo_qad@@YAXQAD@Z"
+// X64: "?foo_qad@@YAXQEAD@Z"
void foo_rad(char * volatile x) {}
-// CHECK: "\01?foo_rad@@YAXRAD@Z"
-// X64: "\01?foo_rad@@YAXREAD@Z"
+// CHECK: "?foo_rad@@YAXRAD@Z"
+// X64: "?foo_rad@@YAXREAD@Z"
void foo_sad(char * const volatile x) {}
-// CHECK: "\01?foo_sad@@YAXSAD@Z"
-// X64: "\01?foo_sad@@YAXSEAD@Z"
+// CHECK: "?foo_sad@@YAXSAD@Z"
+// X64: "?foo_sad@@YAXSEAD@Z"
void foo_piad(char * __restrict x) {}
-// CHECK: "\01?foo_piad@@YAXPIAD@Z"
-// X64: "\01?foo_piad@@YAXPEIAD@Z"
+// CHECK: "?foo_piad@@YAXPIAD@Z"
+// X64: "?foo_piad@@YAXPEIAD@Z"
void foo_qiad(char * const __restrict x) {}
-// CHECK: "\01?foo_qiad@@YAXQIAD@Z"
-// X64: "\01?foo_qiad@@YAXQEIAD@Z"
+// CHECK: "?foo_qiad@@YAXQIAD@Z"
+// X64: "?foo_qiad@@YAXQEIAD@Z"
void foo_riad(char * volatile __restrict x) {}
-// CHECK: "\01?foo_riad@@YAXRIAD@Z"
-// X64: "\01?foo_riad@@YAXREIAD@Z"
+// CHECK: "?foo_riad@@YAXRIAD@Z"
+// X64: "?foo_riad@@YAXREIAD@Z"
void foo_siad(char * const volatile __restrict x) {}
-// CHECK: "\01?foo_siad@@YAXSIAD@Z"
-// X64: "\01?foo_siad@@YAXSEIAD@Z"
+// CHECK: "?foo_siad@@YAXSIAD@Z"
+// X64: "?foo_siad@@YAXSEIAD@Z"
void foo_papad(char ** x) {}
-// CHECK: "\01?foo_papad@@YAXPAPAD@Z"
-// X64: "\01?foo_papad@@YAXPEAPEAD@Z"
+// CHECK: "?foo_papad@@YAXPAPAD@Z"
+// X64: "?foo_papad@@YAXPEAPEAD@Z"
void foo_papbd(char const ** x) {}
-// CHECK: "\01?foo_papbd@@YAXPAPBD@Z"
-// X64: "\01?foo_papbd@@YAXPEAPEBD@Z"
+// CHECK: "?foo_papbd@@YAXPAPBD@Z"
+// X64: "?foo_papbd@@YAXPEAPEBD@Z"
void foo_papcd(char volatile ** x) {}
-// CHECK: "\01?foo_papcd@@YAXPAPCD@Z"
-// X64: "\01?foo_papcd@@YAXPEAPECD@Z"
+// CHECK: "?foo_papcd@@YAXPAPCD@Z"
+// X64: "?foo_papcd@@YAXPEAPECD@Z"
void foo_pbqad(char * const* x) {}
-// CHECK: "\01?foo_pbqad@@YAXPBQAD@Z"
-// X64: "\01?foo_pbqad@@YAXPEBQEAD@Z"
+// CHECK: "?foo_pbqad@@YAXPBQAD@Z"
+// X64: "?foo_pbqad@@YAXPEBQEAD@Z"
void foo_pcrad(char * volatile* x) {}
-// CHECK: "\01?foo_pcrad@@YAXPCRAD@Z"
-// X64: "\01?foo_pcrad@@YAXPECREAD@Z"
+// CHECK: "?foo_pcrad@@YAXPCRAD@Z"
+// X64: "?foo_pcrad@@YAXPECREAD@Z"
void foo_qapad(char ** const x) {}
-// CHECK: "\01?foo_qapad@@YAXQAPAD@Z"
-// X64: "\01?foo_qapad@@YAXQEAPEAD@Z"
+// CHECK: "?foo_qapad@@YAXQAPAD@Z"
+// X64: "?foo_qapad@@YAXQEAPEAD@Z"
void foo_rapad(char ** volatile x) {}
-// CHECK: "\01?foo_rapad@@YAXRAPAD@Z"
-// X64: "\01?foo_rapad@@YAXREAPEAD@Z"
+// CHECK: "?foo_rapad@@YAXRAPAD@Z"
+// X64: "?foo_rapad@@YAXREAPEAD@Z"
void foo_pbqbd(const char * const* x) {}
-// CHECK: "\01?foo_pbqbd@@YAXPBQBD@Z"
-// X64: "\01?foo_pbqbd@@YAXPEBQEBD@Z"
+// CHECK: "?foo_pbqbd@@YAXPBQBD@Z"
+// X64: "?foo_pbqbd@@YAXPEBQEBD@Z"
void foo_pbqcd(volatile char * const* x) {}
-// CHECK: "\01?foo_pbqcd@@YAXPBQCD@Z"
-// X64: "\01?foo_pbqcd@@YAXPEBQECD@Z"
+// CHECK: "?foo_pbqcd@@YAXPBQCD@Z"
+// X64: "?foo_pbqcd@@YAXPEBQECD@Z"
void foo_pcrbd(const char * volatile* x) {}
-// CHECK: "\01?foo_pcrbd@@YAXPCRBD@Z"
-// X64: "\01?foo_pcrbd@@YAXPECREBD@Z"
+// CHECK: "?foo_pcrbd@@YAXPCRBD@Z"
+// X64: "?foo_pcrbd@@YAXPECREBD@Z"
void foo_pcrcd(volatile char * volatile* x) {}
-// CHECK: "\01?foo_pcrcd@@YAXPCRCD@Z"
-// X64: "\01?foo_pcrcd@@YAXPECRECD@Z"
+// CHECK: "?foo_pcrcd@@YAXPCRCD@Z"
+// X64: "?foo_pcrcd@@YAXPECRECD@Z"
void foo_aad(char &x) {}
-// CHECK: "\01?foo_aad@@YAXAAD@Z"
-// X64: "\01?foo_aad@@YAXAEAD@Z"
+// CHECK: "?foo_aad@@YAXAAD@Z"
+// X64: "?foo_aad@@YAXAEAD@Z"
void foo_abd(const char &x) {}
-// CHECK: "\01?foo_abd@@YAXABD@Z"
-// X64: "\01?foo_abd@@YAXAEBD@Z"
+// CHECK: "?foo_abd@@YAXABD@Z"
+// X64: "?foo_abd@@YAXAEBD@Z"
void foo_aapad(char *&x) {}
-// CHECK: "\01?foo_aapad@@YAXAAPAD@Z"
-// X64: "\01?foo_aapad@@YAXAEAPEAD@Z"
+// CHECK: "?foo_aapad@@YAXAAPAD@Z"
+// X64: "?foo_aapad@@YAXAEAPEAD@Z"
void foo_aapbd(const char *&x) {}
-// CHECK: "\01?foo_aapbd@@YAXAAPBD@Z"
-// X64: "\01?foo_aapbd@@YAXAEAPEBD@Z"
+// CHECK: "?foo_aapbd@@YAXAAPBD@Z"
+// X64: "?foo_aapbd@@YAXAEAPEBD@Z"
void foo_abqad(char * const &x) {}
-// CHECK: "\01?foo_abqad@@YAXABQAD@Z"
-// X64: "\01?foo_abqad@@YAXAEBQEAD@Z"
+// CHECK: "?foo_abqad@@YAXABQAD@Z"
+// X64: "?foo_abqad@@YAXAEBQEAD@Z"
void foo_abqbd(const char * const &x) {}
-// CHECK: "\01?foo_abqbd@@YAXABQBD@Z"
-// X64: "\01?foo_abqbd@@YAXAEBQEBD@Z"
+// CHECK: "?foo_abqbd@@YAXABQBD@Z"
+// X64: "?foo_abqbd@@YAXAEBQEBD@Z"
void foo_aay144h(int (&x)[5][5]) {}
-// CHECK: "\01?foo_aay144h@@YAXAAY144H@Z"
-// X64: "\01?foo_aay144h@@YAXAEAY144H@Z"
+// CHECK: "?foo_aay144h@@YAXAAY144H@Z"
+// X64: "?foo_aay144h@@YAXAEAY144H@Z"
void foo_aay144cbh(const int (&x)[5][5]) {}
-// CHECK: "\01?foo_aay144cbh@@YAXAAY144$$CBH@Z"
-// X64: "\01?foo_aay144cbh@@YAXAEAY144$$CBH@Z"
+// CHECK: "?foo_aay144cbh@@YAXAAY144$$CBH@Z"
+// X64: "?foo_aay144cbh@@YAXAEAY144$$CBH@Z"
void foo_qay144h(int (&&x)[5][5]) {}
-// CHECK: "\01?foo_qay144h@@YAX$$QAY144H@Z"
-// X64: "\01?foo_qay144h@@YAX$$QEAY144H@Z"
+// CHECK: "?foo_qay144h@@YAX$$QAY144H@Z"
+// X64: "?foo_qay144h@@YAX$$QEAY144H@Z"
void foo_qay144cbh(const int (&&x)[5][5]) {}
-// CHECK: "\01?foo_qay144cbh@@YAX$$QAY144$$CBH@Z"
-// X64: "\01?foo_qay144cbh@@YAX$$QEAY144$$CBH@Z"
+// CHECK: "?foo_qay144cbh@@YAX$$QAY144$$CBH@Z"
+// X64: "?foo_qay144cbh@@YAX$$QEAY144$$CBH@Z"
void foo_p6ahxz(int x()) {}
-// CHECK: "\01?foo_p6ahxz@@YAXP6AHXZ@Z"
-// X64: "\01?foo_p6ahxz@@YAXP6AHXZ@Z"
+// CHECK: "?foo_p6ahxz@@YAXP6AHXZ@Z"
+// X64: "?foo_p6ahxz@@YAXP6AHXZ@Z"
void foo_a6ahxz(int (&x)()) {}
-// CHECK: "\01?foo_a6ahxz@@YAXA6AHXZ@Z"
-// X64: "\01?foo_a6ahxz@@YAXA6AHXZ@Z"
+// CHECK: "?foo_a6ahxz@@YAXA6AHXZ@Z"
+// X64: "?foo_a6ahxz@@YAXA6AHXZ@Z"
void foo_q6ahxz(int (&&x)()) {}
-// CHECK: "\01?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
-// X64: "\01?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
+// CHECK: "?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
+// X64: "?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
void foo_qay04h(int x[5][5]) {}
-// CHECK: "\01?foo_qay04h@@YAXQAY04H@Z"
-// X64: "\01?foo_qay04h@@YAXQEAY04H@Z"
+// CHECK: "?foo_qay04h@@YAXQAY04H@Z"
+// X64: "?foo_qay04h@@YAXQEAY04H@Z"
void foo_qay04cbh(const int x[5][5]) {}
-// CHECK: "\01?foo_qay04cbh@@YAXQAY04$$CBH@Z"
-// X64: "\01?foo_qay04cbh@@YAXQEAY04$$CBH@Z"
+// CHECK: "?foo_qay04cbh@@YAXQAY04$$CBH@Z"
+// X64: "?foo_qay04cbh@@YAXQEAY04$$CBH@Z"
typedef double Vector[3];
void foo(Vector*) {}
-// CHECK: "\01?foo@@YAXPAY02N@Z"
-// X64: "\01?foo@@YAXPEAY02N@Z"
+// CHECK: "?foo@@YAXPAY02N@Z"
+// X64: "?foo@@YAXPEAY02N@Z"
void foo(Vector) {}
-// CHECK: "\01?foo@@YAXQAN@Z"
-// X64: "\01?foo@@YAXQEAN@Z"
+// CHECK: "?foo@@YAXQAN@Z"
+// X64: "?foo@@YAXQEAN@Z"
void foo_const(const Vector) {}
-// CHECK: "\01?foo_const@@YAXQBN@Z"
-// X64: "\01?foo_const@@YAXQEBN@Z"
+// CHECK: "?foo_const@@YAXQBN@Z"
+// X64: "?foo_const@@YAXQEBN@Z"
void foo_volatile(volatile Vector) {}
-// CHECK: "\01?foo_volatile@@YAXQCN@Z"
-// X64: "\01?foo_volatile@@YAXQECN@Z"
+// CHECK: "?foo_volatile@@YAXQCN@Z"
+// X64: "?foo_volatile@@YAXQECN@Z"
void foo(Vector*, const Vector, const double) {}
-// CHECK: "\01?foo@@YAXPAY02NQBNN@Z"
-// X64: "\01?foo@@YAXPEAY02NQEBNN@Z"
+// CHECK: "?foo@@YAXPAY02NQBNN@Z"
+// X64: "?foo@@YAXPEAY02NQEBNN@Z"
typedef void (*ConstFunPtr)(int *const d);
void foo_fnptrconst(ConstFunPtr f) { }
-// CHECK: "\01?foo_fnptrconst@@YAXP6AXQAH@Z@Z"
-// X64: "\01?foo_fnptrconst@@YAXP6AXQEAH@Z@Z"
+// CHECK: "?foo_fnptrconst@@YAXP6AXQAH@Z@Z"
+// X64: "?foo_fnptrconst@@YAXP6AXQEAH@Z@Z"
typedef void (*ArrayFunPtr)(int d[1]);
void foo_fnptrarray(ArrayFunPtr f) { }
-// CHECK: "\01?foo_fnptrarray@@YAXP6AXQAH@Z@Z"
-// X64: "\01?foo_fnptrarray@@YAXP6AXQEAH@Z@Z"
+// CHECK: "?foo_fnptrarray@@YAXP6AXQAH@Z@Z"
+// X64: "?foo_fnptrarray@@YAXP6AXQEAH@Z@Z"
void foo_fnptrbackref1(ArrayFunPtr f1, ArrayFunPtr f2) { }
-// CHECK: "\01?foo_fnptrbackref1@@YAXP6AXQAH@Z1@Z"
-// X64: "\01?foo_fnptrbackref1@@YAXP6AXQEAH@Z1@Z"
+// CHECK: "?foo_fnptrbackref1@@YAXP6AXQAH@Z1@Z"
+// X64: "?foo_fnptrbackref1@@YAXP6AXQEAH@Z1@Z"
void foo_fnptrbackref2(ArrayFunPtr f1, ConstFunPtr f2) { }
-// CHECK: "\01?foo_fnptrbackref2@@YAXP6AXQAH@Z1@Z"
-// X64: "\01?foo_fnptrbackref2@@YAXP6AXQEAH@Z1@Z"
+// CHECK: "?foo_fnptrbackref2@@YAXP6AXQAH@Z1@Z"
+// X64: "?foo_fnptrbackref2@@YAXP6AXQEAH@Z1@Z"
typedef void (*NormalFunPtr)(int *d);
void foo_fnptrbackref3(ArrayFunPtr f1, NormalFunPtr f2) { }
-// CHECK: "\01?foo_fnptrbackref3@@YAXP6AXQAH@Z1@Z"
-// X64: "\01?foo_fnptrbackref3@@YAXP6AXQEAH@Z1@Z"
+// CHECK: "?foo_fnptrbackref3@@YAXP6AXQAH@Z1@Z"
+// X64: "?foo_fnptrbackref3@@YAXP6AXQEAH@Z1@Z"
void foo_fnptrbackref4(NormalFunPtr f1, ArrayFunPtr f2) { }
-// CHECK: "\01?foo_fnptrbackref4@@YAXP6AXPAH@Z1@Z"
-// X64: "\01?foo_fnptrbackref4@@YAXP6AXPEAH@Z1@Z"
+// CHECK: "?foo_fnptrbackref4@@YAXP6AXPAH@Z1@Z"
+// X64: "?foo_fnptrbackref4@@YAXP6AXPEAH@Z1@Z"
ArrayFunPtr ret_fnptrarray() { return 0; }
-// CHECK: "\01?ret_fnptrarray@@YAP6AXQAH@ZXZ"
-// X64: "\01?ret_fnptrarray@@YAP6AXQEAH@ZXZ"
+// CHECK: "?ret_fnptrarray@@YAP6AXQAH@ZXZ"
+// X64: "?ret_fnptrarray@@YAP6AXQEAH@ZXZ"
// Test that we mangle the forward decl when we have a redeclaration with a
// slightly different type.
void mangle_fwd(char * const x);
void mangle_fwd(char * x) {}
-// CHECK: "\01?mangle_fwd@@YAXQAD@Z"
-// X64: "\01?mangle_fwd@@YAXQEAD@Z"
+// CHECK: "?mangle_fwd@@YAXQAD@Z"
+// X64: "?mangle_fwd@@YAXQEAD@Z"
void mangle_no_fwd(char * x) {}
-// CHECK: "\01?mangle_no_fwd@@YAXPAD@Z"
-// X64: "\01?mangle_no_fwd@@YAXPEAD@Z"
+// CHECK: "?mangle_no_fwd@@YAXPAD@Z"
+// X64: "?mangle_no_fwd@@YAXPEAD@Z"
// The first argument gets mangled as-if it were written "int *const"
// The second arg should not form a backref because it isn't qualified
void mangle_no_backref0(int[], int *) {}
-// CHECK: "\01?mangle_no_backref0@@YAXQAHPAH@Z"
-// X64: "\01?mangle_no_backref0@@YAXQEAHPEAH@Z"
+// CHECK: "?mangle_no_backref0@@YAXQAHPAH@Z"
+// X64: "?mangle_no_backref0@@YAXQEAHPEAH@Z"
void mangle_no_backref1(int[], int *const) {}
-// CHECK: "\01?mangle_no_backref1@@YAXQAHQAH@Z"
-// X64: "\01?mangle_no_backref1@@YAXQEAHQEAH@Z"
+// CHECK: "?mangle_no_backref1@@YAXQAHQAH@Z"
+// X64: "?mangle_no_backref1@@YAXQEAHQEAH@Z"
typedef void fun_type(void);
typedef void (*ptr_to_fun_type)(void);
// Pointer to function types don't backref with function types
void mangle_no_backref2(fun_type, ptr_to_fun_type) {}
-// CHECK: "\01?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z"
-// X64: "\01?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z"
+// CHECK: "?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z"
+// X64: "?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z"
void mangle_yes_backref0(int[], int []) {}
-// CHECK: "\01?mangle_yes_backref0@@YAXQAH0@Z"
-// X64: "\01?mangle_yes_backref0@@YAXQEAH0@Z"
+// CHECK: "?mangle_yes_backref0@@YAXQAH0@Z"
+// X64: "?mangle_yes_backref0@@YAXQEAH0@Z"
void mangle_yes_backref1(int *const, int *const) {}
-// CHECK: "\01?mangle_yes_backref1@@YAXQAH0@Z"
-// X64: "\01?mangle_yes_backref1@@YAXQEAH0@Z"
+// CHECK: "?mangle_yes_backref1@@YAXQAH0@Z"
+// X64: "?mangle_yes_backref1@@YAXQEAH0@Z"
void mangle_yes_backref2(fun_type *const[], ptr_to_fun_type const[]) {}
-// CHECK: "\01?mangle_yes_backref2@@YAXQBQ6AXXZ0@Z"
-// X64: "\01?mangle_yes_backref2@@YAXQEBQ6AXXZ0@Z"
+// CHECK: "?mangle_yes_backref2@@YAXQBQ6AXXZ0@Z"
+// X64: "?mangle_yes_backref2@@YAXQEBQ6AXXZ0@Z"
void mangle_yes_backref3(ptr_to_fun_type *const, void (**const)(void)) {}
-// CHECK: "\01?mangle_yes_backref3@@YAXQAP6AXXZ0@Z"
-// X64: "\01?mangle_yes_backref3@@YAXQEAP6AXXZ0@Z"
+// CHECK: "?mangle_yes_backref3@@YAXQAP6AXXZ0@Z"
+// X64: "?mangle_yes_backref3@@YAXQEAP6AXXZ0@Z"
void mangle_yes_backref4(int *const __restrict, int *const __restrict) {}
-// CHECK: "\01?mangle_yes_backref4@@YAXQIAH0@Z"
-// X64: "\01?mangle_yes_backref4@@YAXQEIAH0@Z"
+// CHECK: "?mangle_yes_backref4@@YAXQIAH0@Z"
+// X64: "?mangle_yes_backref4@@YAXQEIAH0@Z"
struct S {};
void pr23325(const S[1], const S[]) {}
-// CHECK: "\01?pr23325@@YAXQBUS@@0@Z"
-// X64: "\01?pr23325@@YAXQEBUS@@0@Z"
+// CHECK: "?pr23325@@YAXQBUS@@0@Z"
+// X64: "?pr23325@@YAXQEBUS@@0@Z"
void vla_arg(int i, int a[][i]) {}
-// CHECK: "\01?vla_arg@@YAXHQAY0A@H@Z"
-// X64: "\01?vla_arg@@YAXHQEAY0A@H@Z"
+// CHECK: "?vla_arg@@YAXHQAY0A@H@Z"
+// X64: "?vla_arg@@YAXHQEAY0A@H@Z"
diff --git a/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp b/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
index 5d4b672..c68b97e 100644
--- a/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
+++ b/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
@@ -8,13 +8,13 @@
class C {};
void foo_abbb(A<B<char>, B<char>, B<char> >) {}
-// CHECK: "\01?foo_abbb@@YAXV?$A@V?$B@D@@V1@V1@@@@Z"
+// CHECK: "?foo_abbb@@YAXV?$A@V?$B@D@@V1@V1@@@@Z"
void foo_abb(A<char, B<char>, B<char> >) {}
-// CHECK: "\01?foo_abb@@YAXV?$A@DV?$B@D@@V1@@@@Z"
+// CHECK: "?foo_abb@@YAXV?$A@DV?$B@D@@V1@@@@Z"
void foo_abc(A<char, B<char>, C<char> >) {}
-// CHECK: "\01?foo_abc@@YAXV?$A@DV?$B@D@@V?$C@D@@@@@Z"
+// CHECK: "?foo_abc@@YAXV?$A@DV?$B@D@@V?$C@D@@@@@Z"
void foo_bt(bool a, B<bool(bool)> b) {}
-// CHECK: "\01?foo_bt@@YAX_NV?$B@$$A6A_N_N@Z@@@Z"
+// CHECK: "?foo_bt@@YAX_NV?$B@$$A6A_N_N@Z@@@Z"
namespace N {
template<class X, class Y, class Z>
@@ -29,11 +29,11 @@
}
void foo_abbb(N::A<N::B<char>, N::B<char>, N::B<char> >) {}
-// CHECK: "\01?foo_abbb@@YAXV?$A@V?$B@D@N@@V12@V12@@N@@@Z"
+// CHECK: "?foo_abbb@@YAXV?$A@V?$B@D@N@@V12@V12@@N@@@Z"
void foo_abb(N::A<char, N::B<char>, N::B<char> >) {}
-// CHECK: "\01?foo_abb@@YAXV?$A@DV?$B@D@N@@V12@@N@@@Z"
+// CHECK: "?foo_abb@@YAXV?$A@DV?$B@D@N@@V12@@N@@@Z"
void foo_abc(N::A<char, N::B<char>, N::C<char> >) {}
-// CHECK: "\01?foo_abc@@YAXV?$A@DV?$B@D@N@@V?$C@D@2@@N@@@Z"
+// CHECK: "?foo_abc@@YAXV?$A@DV?$B@D@N@@V?$C@D@2@@N@@@Z"
N::A<char, N::B<char>, N::C<char> > abc_foo() {
// CHECK: ?abc_foo@@YA?AV?$A@DV?$B@D@N@@V?$C@D@2@@N@@XZ
@@ -71,16 +71,16 @@
}
void foo5(NA::Y<NB::Y<NA::Y<NB::Y<NA::X> > > > arg) {}
-// CHECK: "\01?foo5@@YAXV?$Y@V?$Y@V?$Y@V?$Y@VX@NA@@@NB@@@NA@@@NB@@@NA@@@Z"
+// CHECK: "?foo5@@YAXV?$Y@V?$Y@V?$Y@V?$Y@VX@NA@@@NB@@@NA@@@NB@@@NA@@@Z"
void foo11(NA::Y<NA::X>, NB::Y<NA::X>) {}
-// CHECK: "\01?foo11@@YAXV?$Y@VX@NA@@@NA@@V1NB@@@Z"
+// CHECK: "?foo11@@YAXV?$Y@VX@NA@@@NA@@V1NB@@@Z"
void foo112(NA::Y<NA::X>, NB::Y<NB::X>) {}
-// CHECK: "\01?foo112@@YAXV?$Y@VX@NA@@@NA@@V?$Y@VX@NB@@@NB@@@Z"
+// CHECK: "?foo112@@YAXV?$Y@VX@NA@@@NA@@V?$Y@VX@NB@@@NB@@@Z"
void foo22(NA::Y<NB::Y<NA::X> >, NB::Y<NA::Y<NA::X> >) {}
-// CHECK: "\01?foo22@@YAXV?$Y@V?$Y@VX@NA@@@NB@@@NA@@V?$Y@V?$Y@VX@NA@@@NA@@@NB@@@Z"
+// CHECK: "?foo22@@YAXV?$Y@V?$Y@VX@NA@@@NB@@@NA@@V?$Y@V?$Y@VX@NA@@@NA@@@NB@@@Z"
namespace PR13207 {
class A {};
@@ -100,56 +100,56 @@
public:
void foo(I<A> x) {}
};
-// CHECK: "\01?foo@L@PR13207@@QAEXV?$I@VA@PR13207@@@2@@Z"
+// CHECK: "?foo@L@PR13207@@QAEXV?$I@VA@PR13207@@@2@@Z"
void call_l_foo(L* l) { l->foo(I<A>()); }
void foo(I<A> x) {}
-// CHECK: "\01?foo@PR13207@@YAXV?$I@VA@PR13207@@@1@@Z"
+// CHECK: "?foo@PR13207@@YAXV?$I@VA@PR13207@@@1@@Z"
void foo2(I<A> x, I<A> y) { }
-// CHECK: "\01?foo2@PR13207@@YAXV?$I@VA@PR13207@@@1@0@Z"
+// CHECK: "?foo2@PR13207@@YAXV?$I@VA@PR13207@@@1@0@Z"
void bar(J<A,B> x) {}
-// CHECK: "\01?bar@PR13207@@YAXV?$J@VA@PR13207@@VB@2@@1@@Z"
+// CHECK: "?bar@PR13207@@YAXV?$J@VA@PR13207@@VB@2@@1@@Z"
void spam(K<A,B,C> x) {}
-// CHECK: "\01?spam@PR13207@@YAXV?$K@VA@PR13207@@VB@2@VC@2@@1@@Z"
+// CHECK: "?spam@PR13207@@YAXV?$K@VA@PR13207@@VB@2@VC@2@@1@@Z"
void baz(K<char, F<char>, I<char> >) {}
-// CHECK: "\01?baz@PR13207@@YAXV?$K@DV?$F@D@PR13207@@V?$I@D@2@@1@@Z"
+// CHECK: "?baz@PR13207@@YAXV?$K@DV?$F@D@PR13207@@V?$I@D@2@@1@@Z"
void qux(K<char, I<char>, I<char> >) {}
-// CHECK: "\01?qux@PR13207@@YAXV?$K@DV?$I@D@PR13207@@V12@@1@@Z"
+// CHECK: "?qux@PR13207@@YAXV?$K@DV?$I@D@PR13207@@V12@@1@@Z"
namespace NA {
class X {};
template<class T> class Y {};
void foo(Y<X> x) {}
-// CHECK: "\01?foo@NA@PR13207@@YAXV?$Y@VX@NA@PR13207@@@12@@Z"
+// CHECK: "?foo@NA@PR13207@@YAXV?$Y@VX@NA@PR13207@@@12@@Z"
void foofoo(Y<Y<X> > x) {}
-// CHECK: "\01?foofoo@NA@PR13207@@YAXV?$Y@V?$Y@VX@NA@PR13207@@@NA@PR13207@@@12@@Z"
+// CHECK: "?foofoo@NA@PR13207@@YAXV?$Y@V?$Y@VX@NA@PR13207@@@NA@PR13207@@@12@@Z"
}
namespace NB {
class X {};
template<class T> class Y {};
void foo(Y<NA::X> x) {}
-// CHECK: "\01?foo@NB@PR13207@@YAXV?$Y@VX@NA@PR13207@@@12@@Z"
+// CHECK: "?foo@NB@PR13207@@YAXV?$Y@VX@NA@PR13207@@@12@@Z"
void bar(NA::Y<X> x) {}
-// CHECK: "\01?bar@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@NA@2@@Z"
+// CHECK: "?bar@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@NA@2@@Z"
void spam(NA::Y<NA::X> x) {}
-// CHECK: "\01?spam@NB@PR13207@@YAXV?$Y@VX@NA@PR13207@@@NA@2@@Z"
+// CHECK: "?spam@NB@PR13207@@YAXV?$Y@VX@NA@PR13207@@@NA@2@@Z"
void foobar(NA::Y<Y<X> > a, Y<Y<X> >) {}
-// CHECK: "\01?foobar@NB@PR13207@@YAXV?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V312@@Z"
+// CHECK: "?foobar@NB@PR13207@@YAXV?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V312@@Z"
void foobarspam(Y<X> a, NA::Y<Y<X> > b, Y<Y<X> >) {}
-// CHECK: "\01?foobarspam@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@@Z"
+// CHECK: "?foobarspam@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@@Z"
void foobarbaz(Y<X> a, NA::Y<Y<X> > b, Y<Y<X> >, Y<Y<X> > c) {}
-// CHECK: "\01?foobarbaz@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@2@Z"
+// CHECK: "?foobarbaz@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@2@Z"
void foobarbazqux(Y<X> a, NA::Y<Y<X> > b, Y<Y<X> >, Y<Y<X> > c , NA::Y<Y<Y<X> > > d) {}
-// CHECK: "\01?foobarbazqux@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@2V?$Y@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NB@PR13207@@@52@@Z"
+// CHECK: "?foobarbazqux@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@2V?$Y@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NB@PR13207@@@52@@Z"
}
namespace NC {
@@ -157,10 +157,10 @@
template<class T> class Y {};
void foo(Y<NB::X> x) {}
-// CHECK: "\01?foo@NC@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@@Z"
+// CHECK: "?foo@NC@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@@Z"
void foobar(NC::Y<NB::Y<NA::Y<NA::X> > > x) {}
-// CHECK: "\01?foobar@NC@PR13207@@YAXV?$Y@V?$Y@V?$Y@VX@NA@PR13207@@@NA@PR13207@@@NB@PR13207@@@12@@Z"
+// CHECK: "?foobar@NC@PR13207@@YAXV?$Y@V?$Y@V?$Y@VX@NA@PR13207@@@NA@PR13207@@@NB@PR13207@@@12@@Z"
}
}
@@ -175,8 +175,8 @@
fun_normal(1);
fun_tmpl(1);
}
-// CHECK: "\01?fun_normal@fn_space@@YA?AURetVal@1@H@Z"
-// CHECK: "\01??$fun_tmpl@H@fn_space@@YA?AURetVal@0@ABH@Z"
+// CHECK: "?fun_normal@fn_space@@YA?AURetVal@1@H@Z"
+// CHECK: "??$fun_tmpl@H@fn_space@@YA?AURetVal@0@ABH@Z"
template <typename T, RetVal (*F)(T)>
RetVal fun_tmpl_recurse(T t) {
@@ -188,6 +188,6 @@
void fun_instantiate2() {
fun_tmpl_recurse<int, fun_tmpl_recurse<int, ident> >(10);
}
-// CHECK: "\01??$fun_tmpl_recurse@H$1??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@1@H@Z@fn_space@@YA?AURetVal@0@H@Z"
-// CHECK: "\01??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@0@H@Z"
+// CHECK: "??$fun_tmpl_recurse@H$1??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@1@H@Z@fn_space@@YA?AURetVal@0@H@Z"
+// CHECK: "??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@0@H@Z"
}
diff --git a/test/CodeGenCXX/mangle-ms-back-references.cpp b/test/CodeGenCXX/mangle-ms-back-references.cpp
index 25a058a..cd4d1e2 100644
--- a/test/CodeGenCXX/mangle-ms-back-references.cpp
+++ b/test/CodeGenCXX/mangle-ms-back-references.cpp
@@ -1,25 +1,25 @@
// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
void f1(const char* a, const char* b) {}
-// CHECK: "\01?f1@@YAXPBD0@Z"
+// CHECK: "?f1@@YAXPBD0@Z"
void f2(const char* a, char* b) {}
-// CHECK: "\01?f2@@YAXPBDPAD@Z"
+// CHECK: "?f2@@YAXPBDPAD@Z"
void f3(int a, const char* b, const char* c) {}
-// CHECK: "\01?f3@@YAXHPBD0@Z"
+// CHECK: "?f3@@YAXHPBD0@Z"
const char *f4(const char* a, const char* b) { return 0; }
-// CHECK: "\01?f4@@YAPBDPBD0@Z"
+// CHECK: "?f4@@YAPBDPBD0@Z"
void f5(char const* a, unsigned int b, char c, void const* d, char const* e, unsigned int f) {}
-// CHECK: "\01?f5@@YAXPBDIDPBX0I@Z"
+// CHECK: "?f5@@YAXPBDIDPBX0I@Z"
void f6(bool a, bool b) {}
-// CHECK: "\01?f6@@YAX_N0@Z"
+// CHECK: "?f6@@YAX_N0@Z"
void f7(int a, int* b, int c, int* d, bool e, bool f, bool* g) {}
-// CHECK: "\01?f7@@YAXHPAHH0_N1PA_N@Z"
+// CHECK: "?f7@@YAXHPAHH0_N1PA_N@Z"
// FIXME: tests for more than 10 types?
@@ -28,18 +28,18 @@
};
void g1(struct S a) {}
-// CHECK: "\01?g1@@YAXUS@@@Z"
+// CHECK: "?g1@@YAXUS@@@Z"
void g2(struct S a, struct S b) {}
-// CHECK: "\01?g2@@YAXUS@@0@Z"
+// CHECK: "?g2@@YAXUS@@0@Z"
void g3(struct S a, struct S b, struct S* c, struct S* d) {}
-// CHECK: "\01?g3@@YAXUS@@0PAU1@1@Z"
+// CHECK: "?g3@@YAXUS@@0PAU1@1@Z"
void g4(const char* a, struct S* b, const char* c, struct S* d) {
-// CHECK: "\01?g4@@YAXPBDPAUS@@01@Z"
+// CHECK: "?g4@@YAXPBDPAUS@@01@Z"
b->mbb(false, false);
-// CHECK: "\01?mbb@S@@QAEX_N0@Z"
+// CHECK: "?mbb@S@@QAEX_N0@Z"
}
// Make sure that different aliases of built-in types end up mangled as the
@@ -47,22 +47,22 @@
typedef unsigned int uintptr_t;
typedef unsigned int size_t;
void *h(size_t a, uintptr_t b) { return 0; }
-// CHECK: "\01?h@@YAPAXII@Z"
+// CHECK: "?h@@YAPAXII@Z"
// Function pointers might be mangled in a complex way.
typedef void (*VoidFunc)();
typedef int* (*PInt3Func)(int* a, int* b);
void h1(const char* a, const char* b, VoidFunc c, VoidFunc d) {}
-// CHECK: "\01?h1@@YAXPBD0P6AXXZ1@Z"
+// CHECK: "?h1@@YAXPBD0P6AXXZ1@Z"
void h2(void (*f_ptr)(void *), void *arg) {}
-// CHECK: "\01?h2@@YAXP6AXPAX@Z0@Z"
+// CHECK: "?h2@@YAXP6AXPAX@Z0@Z"
PInt3Func h3(PInt3Func x, PInt3Func y, int* z) { return 0; }
-// CHECK: "\01?h3@@YAP6APAHPAH0@ZP6APAH00@Z10@Z"
+// CHECK: "?h3@@YAP6APAHPAH0@ZP6APAH00@Z10@Z"
namespace foo {
void foo() { }
-// CHECK: "\01?foo@0@YAXXZ"
+// CHECK: "?foo@0@YAXXZ"
}
diff --git a/test/CodeGenCXX/mangle-ms-cxx11.cpp b/test/CodeGenCXX/mangle-ms-cxx11.cpp
index f79518d..286c1d0 100644
--- a/test/CodeGenCXX/mangle-ms-cxx11.cpp
+++ b/test/CodeGenCXX/mangle-ms-cxx11.cpp
@@ -7,69 +7,69 @@
using A = int () const;
S<A> a;
-// CHECK-DAG: @"\01?a@FTypeWithQuals@@3U?$S@$$A8@@BAHXZ@1@A"
+// CHECK-DAG: @"?a@FTypeWithQuals@@3U?$S@$$A8@@BAHXZ@1@A"
using B = int () volatile;
S<B> b;
-// CHECK-DAG: @"\01?b@FTypeWithQuals@@3U?$S@$$A8@@CAHXZ@1@A"
+// CHECK-DAG: @"?b@FTypeWithQuals@@3U?$S@$$A8@@CAHXZ@1@A"
using C = int () __restrict;
S<C> c;
-// CHECK-DAG: @"\01?c@FTypeWithQuals@@3U?$S@$$A8@@IAAHXZ@1@A"
+// CHECK-DAG: @"?c@FTypeWithQuals@@3U?$S@$$A8@@IAAHXZ@1@A"
using D = int () const &;
S<D> d;
-// CHECK-DAG: @"\01?d@FTypeWithQuals@@3U?$S@$$A8@@GBAHXZ@1@A"
+// CHECK-DAG: @"?d@FTypeWithQuals@@3U?$S@$$A8@@GBAHXZ@1@A"
using E = int () volatile &;
S<E> e;
-// CHECK-DAG: @"\01?e@FTypeWithQuals@@3U?$S@$$A8@@GCAHXZ@1@A"
+// CHECK-DAG: @"?e@FTypeWithQuals@@3U?$S@$$A8@@GCAHXZ@1@A"
using F = int () __restrict &;
S<F> f;
-// CHECK-DAG: @"\01?f@FTypeWithQuals@@3U?$S@$$A8@@IGAAHXZ@1@A"
+// CHECK-DAG: @"?f@FTypeWithQuals@@3U?$S@$$A8@@IGAAHXZ@1@A"
using G = int () const &&;
S<G> g;
-// CHECK-DAG: @"\01?g@FTypeWithQuals@@3U?$S@$$A8@@HBAHXZ@1@A"
+// CHECK-DAG: @"?g@FTypeWithQuals@@3U?$S@$$A8@@HBAHXZ@1@A"
using H = int () volatile &&;
S<H> h;
-// CHECK-DAG: @"\01?h@FTypeWithQuals@@3U?$S@$$A8@@HCAHXZ@1@A"
+// CHECK-DAG: @"?h@FTypeWithQuals@@3U?$S@$$A8@@HCAHXZ@1@A"
using I = int () __restrict &&;
S<I> i;
-// CHECK-DAG: @"\01?i@FTypeWithQuals@@3U?$S@$$A8@@IHAAHXZ@1@A"
+// CHECK-DAG: @"?i@FTypeWithQuals@@3U?$S@$$A8@@IHAAHXZ@1@A"
using J = int ();
S<J> j;
-// CHECK-DAG: @"\01?j@FTypeWithQuals@@3U?$S@$$A6AHXZ@1@A"
+// CHECK-DAG: @"?j@FTypeWithQuals@@3U?$S@$$A6AHXZ@1@A"
using K = int () &;
S<K> k;
-// CHECK-DAG: @"\01?k@FTypeWithQuals@@3U?$S@$$A8@@GAAHXZ@1@A"
+// CHECK-DAG: @"?k@FTypeWithQuals@@3U?$S@$$A8@@GAAHXZ@1@A"
using L = int () &&;
S<L> l;
-// CHECK-DAG: @"\01?l@FTypeWithQuals@@3U?$S@$$A8@@HAAHXZ@1@A"
+// CHECK-DAG: @"?l@FTypeWithQuals@@3U?$S@$$A8@@HAAHXZ@1@A"
}
-// CHECK: "\01?DeducedType@@3HA"
+// CHECK: "?DeducedType@@3HA"
auto DeducedType = 30;
-// CHECK-DAG: @"\01?Char16Var@@3_SA"
+// CHECK-DAG: @"?Char16Var@@3_SA"
char16_t Char16Var;
-// CHECK-DAG: @"\01?Char32Var@@3_UA"
+// CHECK-DAG: @"?Char32Var@@3_UA"
char32_t Char32Var;
-// CHECK: "\01?LRef@@YAXAAH@Z"
+// CHECK: "?LRef@@YAXAAH@Z"
void LRef(int& a) { }
-// CHECK: "\01?RRef@@YAH$$QAH@Z"
+// CHECK: "?RRef@@YAH$$QAH@Z"
int RRef(int&& a) { return a; }
-// CHECK: "\01?Null@@YAX$$T@Z"
+// CHECK: "?Null@@YAX$$T@Z"
namespace std { typedef decltype(__nullptr) nullptr_t; }
void Null(std::nullptr_t) {}
@@ -87,19 +87,19 @@
extern enum Enum11 : unsigned long { } ULongEnum;
extern enum Enum12 : long long { } SLongLongEnum;
extern enum Enum13 : unsigned long long { } ULongLongEnum;
-// CHECK-DAG: @"\01?Enum@EnumMangling@@3W4Enum01@1@A"
-// CHECK-DAG: @"\01?BoolEnum@EnumMangling@@3W4Enum02@1@A
-// CHECK-DAG: @"\01?CharEnum@EnumMangling@@3W4Enum03@1@A
-// CHECK-DAG: @"\01?SCharEnum@EnumMangling@@3W4Enum04@1@A
-// CHECK-DAG: @"\01?UCharEnum@EnumMangling@@3W4Enum05@1@A
-// CHECK-DAG: @"\01?SShortEnum@EnumMangling@@3W4Enum06@1@A"
-// CHECK-DAG: @"\01?UShortEnum@EnumMangling@@3W4Enum07@1@A"
-// CHECK-DAG: @"\01?SIntEnum@EnumMangling@@3W4Enum08@1@A"
-// CHECK-DAG: @"\01?UIntEnum@EnumMangling@@3W4Enum09@1@A"
-// CHECK-DAG: @"\01?SLongEnum@EnumMangling@@3W4Enum10@1@A"
-// CHECK-DAG: @"\01?ULongEnum@EnumMangling@@3W4Enum11@1@A"
-// CHECK-DAG: @"\01?SLongLongEnum@EnumMangling@@3W4Enum12@1@A"
-// CHECK-DAG: @"\01?ULongLongEnum@EnumMangling@@3W4Enum13@1@A"
+// CHECK-DAG: @"?Enum@EnumMangling@@3W4Enum01@1@A"
+// CHECK-DAG: @"?BoolEnum@EnumMangling@@3W4Enum02@1@A
+// CHECK-DAG: @"?CharEnum@EnumMangling@@3W4Enum03@1@A
+// CHECK-DAG: @"?SCharEnum@EnumMangling@@3W4Enum04@1@A
+// CHECK-DAG: @"?UCharEnum@EnumMangling@@3W4Enum05@1@A
+// CHECK-DAG: @"?SShortEnum@EnumMangling@@3W4Enum06@1@A"
+// CHECK-DAG: @"?UShortEnum@EnumMangling@@3W4Enum07@1@A"
+// CHECK-DAG: @"?SIntEnum@EnumMangling@@3W4Enum08@1@A"
+// CHECK-DAG: @"?UIntEnum@EnumMangling@@3W4Enum09@1@A"
+// CHECK-DAG: @"?SLongEnum@EnumMangling@@3W4Enum10@1@A"
+// CHECK-DAG: @"?ULongEnum@EnumMangling@@3W4Enum11@1@A"
+// CHECK-DAG: @"?SLongLongEnum@EnumMangling@@3W4Enum12@1@A"
+// CHECK-DAG: @"?ULongLongEnum@EnumMangling@@3W4Enum13@1@A"
decltype(Enum) *UseEnum() { return &Enum; }
decltype(BoolEnum) *UseBoolEnum() { return &BoolEnum; }
decltype(CharEnum) *UseCharEnum() { return &CharEnum; }
@@ -126,19 +126,19 @@
extern enum class EnumClass11 : unsigned long { } ULongEnumClass;
extern enum class EnumClass12 : long long { } SLongLongEnumClass;
extern enum class EnumClass13 : unsigned long long { } ULongLongEnumClass;
-// CHECK-DAG: @"\01?EnumClass@EnumMangling@@3W4EnumClass01@1@A"
-// CHECK-DAG: @"\01?BoolEnumClass@EnumMangling@@3W4EnumClass02@1@A
-// CHECK-DAG: @"\01?CharEnumClass@EnumMangling@@3W4EnumClass03@1@A
-// CHECK-DAG: @"\01?SCharEnumClass@EnumMangling@@3W4EnumClass04@1@A
-// CHECK-DAG: @"\01?UCharEnumClass@EnumMangling@@3W4EnumClass05@1@A
-// CHECK-DAG: @"\01?SShortEnumClass@EnumMangling@@3W4EnumClass06@1@A"
-// CHECK-DAG: @"\01?UShortEnumClass@EnumMangling@@3W4EnumClass07@1@A"
-// CHECK-DAG: @"\01?SIntEnumClass@EnumMangling@@3W4EnumClass08@1@A"
-// CHECK-DAG: @"\01?UIntEnumClass@EnumMangling@@3W4EnumClass09@1@A"
-// CHECK-DAG: @"\01?SLongEnumClass@EnumMangling@@3W4EnumClass10@1@A"
-// CHECK-DAG: @"\01?ULongEnumClass@EnumMangling@@3W4EnumClass11@1@A"
-// CHECK-DAG: @"\01?SLongLongEnumClass@EnumMangling@@3W4EnumClass12@1@A"
-// CHECK-DAG: @"\01?ULongLongEnumClass@EnumMangling@@3W4EnumClass13@1@A"
+// CHECK-DAG: @"?EnumClass@EnumMangling@@3W4EnumClass01@1@A"
+// CHECK-DAG: @"?BoolEnumClass@EnumMangling@@3W4EnumClass02@1@A
+// CHECK-DAG: @"?CharEnumClass@EnumMangling@@3W4EnumClass03@1@A
+// CHECK-DAG: @"?SCharEnumClass@EnumMangling@@3W4EnumClass04@1@A
+// CHECK-DAG: @"?UCharEnumClass@EnumMangling@@3W4EnumClass05@1@A
+// CHECK-DAG: @"?SShortEnumClass@EnumMangling@@3W4EnumClass06@1@A"
+// CHECK-DAG: @"?UShortEnumClass@EnumMangling@@3W4EnumClass07@1@A"
+// CHECK-DAG: @"?SIntEnumClass@EnumMangling@@3W4EnumClass08@1@A"
+// CHECK-DAG: @"?UIntEnumClass@EnumMangling@@3W4EnumClass09@1@A"
+// CHECK-DAG: @"?SLongEnumClass@EnumMangling@@3W4EnumClass10@1@A"
+// CHECK-DAG: @"?ULongEnumClass@EnumMangling@@3W4EnumClass11@1@A"
+// CHECK-DAG: @"?SLongLongEnumClass@EnumMangling@@3W4EnumClass12@1@A"
+// CHECK-DAG: @"?ULongLongEnumClass@EnumMangling@@3W4EnumClass13@1@A"
decltype(EnumClass) *UseEnumClass() { return &EnumClass; }
decltype(BoolEnumClass) *UseBoolEnumClass() { return &BoolEnumClass; }
decltype(CharEnumClass) *UseCharEnumClass() { return &CharEnumClass; }
@@ -158,7 +158,7 @@
struct { } a;
decltype(a) fun(decltype(a) x, decltype(a)) { return x; }
-// CHECK-DAG: @"\01?fun@PR18022@@YA?AU<unnamed-type-a>@1@U21@0@Z"
+// CHECK-DAG: @"?fun@PR18022@@YA?AU<unnamed-type-a>@1@U21@0@Z"
void use_fun() { fun(a, a); }
@@ -168,14 +168,14 @@
static auto lambda = [] { static int local; ++local; return local; };
// First, we have the static local variable of type "<lambda_1>" inside of
// "define_lambda".
-// CHECK-DAG: @"\01?lambda@?1??define_lambda@@YAHXZ@4V<lambda_1>@?0??1@YAHXZ@A"
+// CHECK-DAG: @"?lambda@?1??define_lambda@@YAHXZ@4V<lambda_1>@?0??1@YAHXZ@A"
// Next, we have the "operator()" for "<lambda_1>" which is inside of
// "define_lambda".
-// CHECK-DAG: @"\01??R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ"
+// CHECK-DAG: @"??R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ"
// Finally, we have the local which is inside of "<lambda_1>" which is inside of
// "define_lambda". Hooray.
-// MSVC2013-DAG: @"\01?local@?2???R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ@4HA"
-// MSVC2015-DAG: @"\01?local@?1???R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ@4HA"
+// MSVC2013-DAG: @"?local@?2???R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ@4HA"
+// MSVC2015-DAG: @"?local@?1???R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ@4HA"
return lambda();
}
@@ -184,12 +184,12 @@
inline void call_with_lambda_arg1() {
use_lambda_arg([]{});
- // CHECK-DAG: @"\01??$use_lambda_arg@V<lambda_1>@?0??call_with_lambda_arg1@@YAXXZ@@@YAXV<lambda_1>@?0??call_with_lambda_arg1@@YAXXZ@@Z"
+ // CHECK-DAG: @"??$use_lambda_arg@V<lambda_1>@?0??call_with_lambda_arg1@@YAXXZ@@@YAXV<lambda_1>@?0??call_with_lambda_arg1@@YAXXZ@@Z"
}
inline void call_with_lambda_arg2() {
use_lambda_arg([]{});
- // CHECK-DAG: @"\01??$use_lambda_arg@V<lambda_1>@?0??call_with_lambda_arg2@@YAXXZ@@@YAXV<lambda_1>@?0??call_with_lambda_arg2@@YAXXZ@@Z"
+ // CHECK-DAG: @"??$use_lambda_arg@V<lambda_1>@?0??call_with_lambda_arg2@@YAXXZ@@@YAXV<lambda_1>@?0??call_with_lambda_arg2@@YAXXZ@@Z"
}
int call_lambda() {
@@ -204,33 +204,33 @@
void foo() __restrict &&;
};
void A::foo() __restrict & {}
-// CHECK-DAG: @"\01?foo@A@PR19361@@QIGAEXXZ"
+// CHECK-DAG: @"?foo@A@PR19361@@QIGAEXXZ"
void A::foo() __restrict && {}
-// CHECK-DAG: @"\01?foo@A@PR19361@@QIHAEXXZ"
+// CHECK-DAG: @"?foo@A@PR19361@@QIHAEXXZ"
}
int operator"" _deg(long double) { return 0; }
-// CHECK-DAG: @"\01??__K_deg@@YAHO@Z"
+// CHECK-DAG: @"??__K_deg@@YAHO@Z"
template <char...>
void templ_fun_with_pack() {}
template void templ_fun_with_pack<>();
-// CHECK-DAG: @"\01??$templ_fun_with_pack@$S@@YAXXZ"
+// CHECK-DAG: @"??$templ_fun_with_pack@$S@@YAXXZ"
template <typename...>
void templ_fun_with_ty_pack() {}
template void templ_fun_with_ty_pack<>();
-// MSVC2013-DAG: @"\01??$templ_fun_with_ty_pack@$$$V@@YAXXZ"
-// MSVC2015-DAG: @"\01??$templ_fun_with_ty_pack@$$V@@YAXXZ"
+// MSVC2013-DAG: @"??$templ_fun_with_ty_pack@$$$V@@YAXXZ"
+// MSVC2015-DAG: @"??$templ_fun_with_ty_pack@$$V@@YAXXZ"
template <template <class> class...>
void templ_fun_with_templ_templ_pack() {}
template void templ_fun_with_templ_templ_pack<>();
-// MSVC2013-DAG: @"\01??$templ_fun_with_templ_templ_pack@$$$V@@YAXXZ"
-// MSVC2015-DAG: @"\01??$templ_fun_with_templ_templ_pack@$$V@@YAXXZ"
+// MSVC2013-DAG: @"??$templ_fun_with_templ_templ_pack@$$$V@@YAXXZ"
+// MSVC2015-DAG: @"??$templ_fun_with_templ_templ_pack@$$V@@YAXXZ"
namespace PR20047 {
template <typename T>
@@ -243,7 +243,7 @@
void f() {}
template void f<AliasA>();
-// CHECK-DAG: @"\01??$f@$$YAliasA@PR20047@@@PR20047@@YAXXZ"
+// CHECK-DAG: @"??$f@$$YAliasA@PR20047@@@PR20047@@YAXXZ"
}
namespace UnnamedType {
@@ -252,7 +252,7 @@
};
void f(decltype(*A::TD)) {}
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXAAU<unnamed-type-TD>@A@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXAAU<unnamed-type-TD>@A@1@@Z"
template <typename T>
struct B {
@@ -261,7 +261,7 @@
};
void f(decltype(B<int>::e)) {}
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXPAW4<unnamed-type-e>@?$B@H@1@@Z
+// CHECK-DAG: @"?f@UnnamedType@@YAXPAW4<unnamed-type-e>@?$B@H@1@@Z
}
namespace PR24651 {
@@ -276,8 +276,8 @@
f(E);
}
}
-// CHECK-DAG: @"\01??$f@W4<unnamed-type-E>@?1??g@PR24651@@YAXXZ@@PR24651@@YAXW4<unnamed-type-E>@?1??g@0@YAXXZ@@Z"
-// CHECK-DAG: @"\01??$f@W4<unnamed-type-E>@?2??g@PR24651@@YAXXZ@@PR24651@@YAXW4<unnamed-type-E>@?2??g@0@YAXXZ@@Z"
+// CHECK-DAG: @"??$f@W4<unnamed-type-E>@?1??g@PR24651@@YAXXZ@@PR24651@@YAXW4<unnamed-type-E>@?1??g@0@YAXXZ@@Z"
+// CHECK-DAG: @"??$f@W4<unnamed-type-E>@?2??g@PR24651@@YAXXZ@@PR24651@@YAXW4<unnamed-type-E>@?2??g@0@YAXXZ@@Z"
}
namespace PR18204 {
@@ -286,15 +286,15 @@
static union {
int n = f(this);
};
-// CHECK-DAG: @"\01??$f@T<unnamed-type-$S1>@PR18204@@@PR18204@@YAHPAT<unnamed-type-$S1>@0@@Z"
+// CHECK-DAG: @"??$f@T<unnamed-type-$S1>@PR18204@@@PR18204@@YAHPAT<unnamed-type-$S1>@0@@Z"
}
int PR26105() {
auto add = [](int x) { return ([x](int y) { return x + y; }); };
return add(3)(4);
}
-// CHECK-DAG: @"\01??R<lambda_0>@?0??PR26105@@YAHXZ@QBE@H@Z"
-// CHECK-DAG: @"\01??R<lambda_1>@?0???R<lambda_0>@?0??PR26105@@YAHXZ@QBE@H@Z@QBE@H@Z"
+// CHECK-DAG: @"??R<lambda_0>@?0??PR26105@@YAHXZ@QBE@H@Z"
+// CHECK-DAG: @"??R<lambda_1>@?0???R<lambda_0>@?0??PR26105@@YAHXZ@QBE@H@Z@QBE@H@Z"
int __unaligned * unaligned_foo1() { return 0; }
int __unaligned * __unaligned * unaligned_foo2() { return 0; }
@@ -304,13 +304,13 @@
template <typename T> T unaligned_foo6(T t) { return t; }
void unaligned_foo7() { unaligned_foo6<int *>(0); unaligned_foo6<int __unaligned *>(0); }
-// CHECK-DAG: @"\01?unaligned_foo1@@YAPFAHXZ"
-// CHECK-DAG: @"\01?unaligned_foo2@@YAPFAPFAHXZ"
-// CHECK-DAG: @"\01?unaligned_foo3@@YAHXZ"
-// CHECK-DAG: @"\01?unaligned_foo4@@YAXPFAH@Z"
-// CHECK-DAG: @"\01?unaligned_foo5@@YAXPIFAH@Z"
-// CHECK-DAG: @"\01??$unaligned_foo6@PAH@@YAPAHPAH@Z"
-// CHECK-DAG: @"\01??$unaligned_foo6@PFAH@@YAPFAHPFAH@Z"
+// CHECK-DAG: @"?unaligned_foo1@@YAPFAHXZ"
+// CHECK-DAG: @"?unaligned_foo2@@YAPFAPFAHXZ"
+// CHECK-DAG: @"?unaligned_foo3@@YAHXZ"
+// CHECK-DAG: @"?unaligned_foo4@@YAXPFAH@Z"
+// CHECK-DAG: @"?unaligned_foo5@@YAXPIFAH@Z"
+// CHECK-DAG: @"??$unaligned_foo6@PAH@@YAPAHPAH@Z"
+// CHECK-DAG: @"??$unaligned_foo6@PFAH@@YAPFAHPFAH@Z"
// __unaligned qualifier for function types
struct unaligned_foo8_S {
@@ -318,28 +318,28 @@
};
void unaligned_foo8_S::unaligned_foo8() volatile __unaligned {}
-// CHECK-DAG: @"\01?unaligned_foo8@unaligned_foo8_S@@QFCEXXZ"
+// CHECK-DAG: @"?unaligned_foo8@unaligned_foo8_S@@QFCEXXZ"
namespace PR31197 {
struct A {
- // CHECK-DAG: define linkonce_odr dso_local x86_thiscallcc i32* @"\01??R<lambda_1>@x@A@PR31197@@QBE@XZ"(
+ // CHECK-DAG: define linkonce_odr dso_local x86_thiscallcc i32* @"??R<lambda_1>@x@A@PR31197@@QBE@XZ"(
int *x = []() {
static int white;
- // CHECK-DAG: @"\01?white@?1???R<lambda_1>@x@A@PR31197@@QBE@XZ@4HA"
+ // CHECK-DAG: @"?white@?1???R<lambda_1>@x@A@PR31197@@QBE@XZ@4HA"
return &white;
}();
- // CHECK-DAG: define linkonce_odr dso_local x86_thiscallcc i32* @"\01??R<lambda_1>@y@A@PR31197@@QBE@XZ"(
+ // CHECK-DAG: define linkonce_odr dso_local x86_thiscallcc i32* @"??R<lambda_1>@y@A@PR31197@@QBE@XZ"(
int *y = []() {
static int black;
- // CHECK-DAG: @"\01?black@?1???R<lambda_1>@y@A@PR31197@@QBE@XZ@4HA"
+ // CHECK-DAG: @"?black@?1???R<lambda_1>@y@A@PR31197@@QBE@XZ@4HA"
return &black;
}();
using FPtrTy = void(void);
static void default_args(FPtrTy x = [] {}, FPtrTy y = [] {}, int z = [] { return 1; }() + [] { return 2; }()) {}
- // CHECK-DAG: @"\01??R<lambda_1_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
- // CHECK-DAG: @"\01??R<lambda_1_2>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
- // CHECK-DAG: @"\01??R<lambda_2_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
- // CHECK-DAG: @"\01??R<lambda_3_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
+ // CHECK-DAG: @"??R<lambda_1_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
+ // CHECK-DAG: @"??R<lambda_1_2>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
+ // CHECK-DAG: @"??R<lambda_2_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
+ // CHECK-DAG: @"??R<lambda_3_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
};
A a;
@@ -348,5 +348,5 @@
enum { enumerator };
void f(decltype(enumerator)) {}
-// CHECK-DAG: define internal void @"\01?f@@YAXW4<unnamed-enum-enumerator>@@@Z"(
+// CHECK-DAG: define internal void @"?f@@YAXW4<unnamed-enum-enumerator>@@@Z"(
void use_f() { f(enumerator); }
diff --git a/test/CodeGenCXX/mangle-ms-cxx14.cpp b/test/CodeGenCXX/mangle-ms-cxx14.cpp
index 798a390..db282d2 100644
--- a/test/CodeGenCXX/mangle-ms-cxx14.cpp
+++ b/test/CodeGenCXX/mangle-ms-cxx14.cpp
@@ -3,27 +3,27 @@
template <typename> int x = 0;
-// CHECK-DAG: "\01??$x@X@@3HA"
+// CHECK-DAG: "??$x@X@@3HA"
template <> int x<void>;
-// CHECK-DAG: "\01??$x@H@@3HA"
+// CHECK-DAG: "??$x@H@@3HA"
template <> int x<int>;
-// CHECK-DAG: "\01?FunctionWithLocalType@@YA?A?<auto>@@XZ"
+// CHECK-DAG: "?FunctionWithLocalType@@YA?A?<auto>@@XZ"
auto FunctionWithLocalType() {
struct LocalType {};
return LocalType{};
}
-// CHECK-DAG: "\01?ValueFromFunctionWithLocalType@@3ULocalType@?1??FunctionWithLocalType@@YA?A?<auto>@@XZ@A"
+// CHECK-DAG: "?ValueFromFunctionWithLocalType@@3ULocalType@?1??FunctionWithLocalType@@YA?A?<auto>@@XZ@A"
auto ValueFromFunctionWithLocalType = FunctionWithLocalType();
-// CHECK-DAG: "\01??R<lambda_0>@@QBE?A?<auto>@@XZ"
+// CHECK-DAG: "??R<lambda_0>@@QBE?A?<auto>@@XZ"
auto LambdaWithLocalType = [] {
struct LocalType {};
return LocalType{};
};
-// CHECK-DAG: "\01?ValueFromLambdaWithLocalType@@3ULocalType@?1???R<lambda_0>@@QBE?A?<auto>@@XZ@A"
+// CHECK-DAG: "?ValueFromLambdaWithLocalType@@3ULocalType@?1???R<lambda_0>@@QBE?A?<auto>@@XZ@A"
auto ValueFromLambdaWithLocalType = LambdaWithLocalType();
template <typename T>
@@ -35,12 +35,12 @@
return LocalLambdaWithLocalType();
}
-// MSVC2013-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
-// MSVC2013-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
-// MSVC2015-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
-// MSVC2015-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
-// CHECK-DAG: "\01??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z"
-// CHECK-DAG: "\01??R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?1@XZ"
+// MSVC2013-DAG: "?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
+// MSVC2013-DAG: "?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
+// MSVC2015-DAG: "?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
+// MSVC2015-DAG: "?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A"
+// CHECK-DAG: "??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z"
+// CHECK-DAG: "??R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?1@XZ"
auto ValueFromTemplateFuncionWithLocalLambda = TemplateFuncionWithLocalLambda(0);
struct S;
@@ -48,15 +48,15 @@
int WithPMD = 0;
template <> int WithPMD<nullptr>;
-// CHECK-DAG: "\01??$WithPMD@$GA@A@?0@@3HA"
+// CHECK-DAG: "??$WithPMD@$GA@A@?0@@3HA"
template <const int *, const int *>
struct Foo {};
Foo<&x<int>, &x<int>> Zoo;
-// CHECK-DAG: "\01?Zoo@@3U?$Foo@$1??$x@H@@3HA$1?1@3HA@@A"
+// CHECK-DAG: "?Zoo@@3U?$Foo@$1??$x@H@@3HA$1?1@3HA@@A"
template <typename T> T unaligned_x;
extern auto test_unaligned() { return unaligned_x<int __unaligned *>; }
-// CHECK-DAG: "\01??$unaligned_x@PFAH@@3PFAHA"
+// CHECK-DAG: "??$unaligned_x@PFAH@@3PFAHA"
diff --git a/test/CodeGenCXX/mangle-ms-md5.cpp b/test/CodeGenCXX/mangle-ms-md5.cpp
index 6843c3c..740fd61 100644
--- a/test/CodeGenCXX/mangle-ms-md5.cpp
+++ b/test/CodeGenCXX/mangle-ms-md5.cpp
@@ -1,11 +1,11 @@
// RUN: %clang_cc1 -emit-llvm -o - -triple i686-pc-win32 %s | FileCheck %s
int xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
-// CHECK-DAG: @"\01??@bf7ea7b95f260b0b24e7f1e8fc8370ab@" = dso_local global i32 0, align 4
+// CHECK-DAG: @"??@bf7ea7b95f260b0b24e7f1e8fc8370ab@" = dso_local global i32 0, align 4
struct yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy {
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy();
virtual void f();
};
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy::yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy() {}
-// CHECK-DAG: @"\01??@a6a285da2eea70dba6b578022be61d81@??_R4@" = linkonce_odr constant %rtti.CompleteObjectLocator
-// CHECK-DAG: @"\01??@a6a285da2eea70dba6b578022be61d81@" = unnamed_addr alias
+// CHECK-DAG: @"??@a6a285da2eea70dba6b578022be61d81@??_R4@" = linkonce_odr constant %rtti.CompleteObjectLocator
+// CHECK-DAG: @"??@a6a285da2eea70dba6b578022be61d81@" = unnamed_addr alias
diff --git a/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp
index 8b666e4..0054279 100644
--- a/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp
+++ b/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp
@@ -1,189 +1,189 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
void a1() {}
-// CHECK: "\01?a1@@YAXXZ"
+// CHECK: "?a1@@YAXXZ"
int a2() { return 0; }
-// CHECK: "\01?a2@@YAHXZ"
+// CHECK: "?a2@@YAHXZ"
const int a3() { return 0; }
-// CHECK: "\01?a3@@YA?BHXZ"
+// CHECK: "?a3@@YA?BHXZ"
volatile int a4() { return 0; }
-// CHECK: "\01?a4@@YA?CHXZ"
+// CHECK: "?a4@@YA?CHXZ"
const volatile int a5() { return 0; }
-// CHECK: "\01?a5@@YA?DHXZ"
+// CHECK: "?a5@@YA?DHXZ"
float a6() { return 0.0f; }
-// CHECK: "\01?a6@@YAMXZ"
+// CHECK: "?a6@@YAMXZ"
int *b1() { return 0; }
-// CHECK: "\01?b1@@YAPAHXZ"
+// CHECK: "?b1@@YAPAHXZ"
const char *b2() { return 0; }
-// CHECK: "\01?b2@@YAPBDXZ"
+// CHECK: "?b2@@YAPBDXZ"
float *b3() { return 0; }
-// CHECK: "\01?b3@@YAPAMXZ"
+// CHECK: "?b3@@YAPAMXZ"
const float *b4() { return 0; }
-// CHECK: "\01?b4@@YAPBMXZ"
+// CHECK: "?b4@@YAPBMXZ"
volatile float *b5() { return 0; }
-// CHECK: "\01?b5@@YAPCMXZ"
+// CHECK: "?b5@@YAPCMXZ"
const volatile float *b6() { return 0; }
-// CHECK: "\01?b6@@YAPDMXZ"
+// CHECK: "?b6@@YAPDMXZ"
float &b7() { return *(float*)0; }
-// CHECK: "\01?b7@@YAAAMXZ"
+// CHECK: "?b7@@YAAAMXZ"
const float &b8() { return *(float*)0; }
-// CHECK: "\01?b8@@YAABMXZ"
+// CHECK: "?b8@@YAABMXZ"
volatile float &b9() { return *(float*)0; }
-// CHECK: "\01?b9@@YAACMXZ"
+// CHECK: "?b9@@YAACMXZ"
const volatile float &b10() { return *(float*)0; }
-// CHECK: "\01?b10@@YAADMXZ"
+// CHECK: "?b10@@YAADMXZ"
const char** b11() { return 0; }
-// CHECK: "\01?b11@@YAPAPBDXZ"
+// CHECK: "?b11@@YAPAPBDXZ"
class A {};
A c1() { return A(); }
-// CHECK: "\01?c1@@YA?AVA@@XZ"
+// CHECK: "?c1@@YA?AVA@@XZ"
const A c2() { return A(); }
-// CHECK: "\01?c2@@YA?BVA@@XZ"
+// CHECK: "?c2@@YA?BVA@@XZ"
volatile A c3() { return A(); }
-// CHECK: "\01?c3@@YA?CVA@@XZ"
+// CHECK: "?c3@@YA?CVA@@XZ"
const volatile A c4() { return A(); }
-// CHECK: "\01?c4@@YA?DVA@@XZ"
+// CHECK: "?c4@@YA?DVA@@XZ"
const A* c5() { return 0; }
-// CHECK: "\01?c5@@YAPBVA@@XZ"
+// CHECK: "?c5@@YAPBVA@@XZ"
volatile A* c6() { return 0; }
-// CHECK: "\01?c6@@YAPCVA@@XZ"
+// CHECK: "?c6@@YAPCVA@@XZ"
const volatile A* c7() { return 0; }
-// CHECK: "\01?c7@@YAPDVA@@XZ"
+// CHECK: "?c7@@YAPDVA@@XZ"
A &c8() { return *(A*)0; }
-// CHECK: "\01?c8@@YAAAVA@@XZ"
+// CHECK: "?c8@@YAAAVA@@XZ"
const A &c9() { return *(A*)0; }
-// CHECK: "\01?c9@@YAABVA@@XZ"
+// CHECK: "?c9@@YAABVA@@XZ"
volatile A &c10() { return *(A*)0; }
-// CHECK: "\01?c10@@YAACVA@@XZ"
+// CHECK: "?c10@@YAACVA@@XZ"
const volatile A &c11() { return *(A*)0; }
-// CHECK: "\01?c11@@YAADVA@@XZ"
+// CHECK: "?c11@@YAADVA@@XZ"
template<typename T> class B {};
B<int> d1() { return B<int>(); }
-// CHECK: "\01?d1@@YA?AV?$B@H@@XZ"
+// CHECK: "?d1@@YA?AV?$B@H@@XZ"
B<const char*> d2() {return B<const char*>(); }
-// CHECK: "\01?d2@@YA?AV?$B@PBD@@XZ"
+// CHECK: "?d2@@YA?AV?$B@PBD@@XZ"
B<A> d3() {return B<A>(); }
-// CHECK: "\01?d3@@YA?AV?$B@VA@@@@XZ"
+// CHECK: "?d3@@YA?AV?$B@VA@@@@XZ"
B<A>* d4() { return 0; }
-// CHECK: "\01?d4@@YAPAV?$B@VA@@@@XZ"
+// CHECK: "?d4@@YAPAV?$B@VA@@@@XZ"
const B<A>* d5() { return 0; }
-// CHECK: "\01?d5@@YAPBV?$B@VA@@@@XZ"
+// CHECK: "?d5@@YAPBV?$B@VA@@@@XZ"
volatile B<A>* d6() { return 0; }
-// CHECK: "\01?d6@@YAPCV?$B@VA@@@@XZ"
+// CHECK: "?d6@@YAPCV?$B@VA@@@@XZ"
const volatile B<A>* d7() { return 0; }
-// CHECK: "\01?d7@@YAPDV?$B@VA@@@@XZ"
+// CHECK: "?d7@@YAPDV?$B@VA@@@@XZ"
B<A>& d8() { return *(B<A>*)0; }
-// CHECK: "\01?d8@@YAAAV?$B@VA@@@@XZ"
+// CHECK: "?d8@@YAAAV?$B@VA@@@@XZ"
const B<A>& d9() { return *(B<A>*)0; }
-// CHECK: "\01?d9@@YAABV?$B@VA@@@@XZ"
+// CHECK: "?d9@@YAABV?$B@VA@@@@XZ"
volatile B<A>& d10() { return *(B<A>*)0; }
-// CHECK: "\01?d10@@YAACV?$B@VA@@@@XZ"
+// CHECK: "?d10@@YAACV?$B@VA@@@@XZ"
const volatile B<A>& d11() { return *(B<A>*)0; }
-// CHECK: "\01?d11@@YAADV?$B@VA@@@@XZ"
+// CHECK: "?d11@@YAADV?$B@VA@@@@XZ"
enum Enum { DEFAULT };
Enum e1() { return DEFAULT; }
-// CHECK: "\01?e1@@YA?AW4Enum@@XZ"
+// CHECK: "?e1@@YA?AW4Enum@@XZ"
const Enum e2() { return DEFAULT; }
-// CHECK: "\01?e2@@YA?BW4Enum@@XZ"
+// CHECK: "?e2@@YA?BW4Enum@@XZ"
Enum* e3() { return 0; }
-// CHECK: "\01?e3@@YAPAW4Enum@@XZ"
+// CHECK: "?e3@@YAPAW4Enum@@XZ"
Enum& e4() { return *(Enum*)0; }
-// CHECK: "\01?e4@@YAAAW4Enum@@XZ"
+// CHECK: "?e4@@YAAAW4Enum@@XZ"
struct S {};
struct S f1() { struct S s; return s; }
-// CHECK: "\01?f1@@YA?AUS@@XZ"
+// CHECK: "?f1@@YA?AUS@@XZ"
const struct S f2() { struct S s; return s; }
-// CHECK: "\01?f2@@YA?BUS@@XZ"
+// CHECK: "?f2@@YA?BUS@@XZ"
struct S* f3() { return 0; }
-// CHECK: "\01?f3@@YAPAUS@@XZ"
+// CHECK: "?f3@@YAPAUS@@XZ"
const struct S* f4() { return 0; }
-// CHECK: "\01?f4@@YAPBUS@@XZ"
+// CHECK: "?f4@@YAPBUS@@XZ"
const volatile struct S* f5() { return 0; }
-// CHECK: "\01?f5@@YAPDUS@@XZ"
+// CHECK: "?f5@@YAPDUS@@XZ"
struct S& f6() { return *(struct S*)0; }
-// CHECK: "\01?f6@@YAAAUS@@XZ"
+// CHECK: "?f6@@YAAAUS@@XZ"
struct S* const f7() { return 0; }
-// CHECK: "\01?f7@@YAQAUS@@XZ"
+// CHECK: "?f7@@YAQAUS@@XZ"
int S::* f8() { return 0; }
-// CHECK: "\01?f8@@YAPQS@@HXZ"
+// CHECK: "?f8@@YAPQS@@HXZ"
int S::* const f9() { return 0; }
-// CHECK: "\01?f9@@YAQQS@@HXZ"
+// CHECK: "?f9@@YAQQS@@HXZ"
int S::* __restrict f10() { return 0; }
-// CHECK: "\01?f10@@YAPIQS@@HXZ"
+// CHECK: "?f10@@YAPIQS@@HXZ"
int S::* const __restrict f11() { return 0; }
-// CHECK: "\01?f11@@YAQIQS@@HXZ"
+// CHECK: "?f11@@YAQIQS@@HXZ"
typedef int (*function_pointer)(int);
function_pointer g1() { return 0; }
-// CHECK: "\01?g1@@YAP6AHH@ZXZ"
+// CHECK: "?g1@@YAP6AHH@ZXZ"
const function_pointer g2() { return 0; }
-// CHECK: "\01?g2@@YAQ6AHH@ZXZ"
+// CHECK: "?g2@@YAQ6AHH@ZXZ"
function_pointer* g3() { return 0; }
-// CHECK: "\01?g3@@YAPAP6AHH@ZXZ"
+// CHECK: "?g3@@YAPAP6AHH@ZXZ"
const function_pointer* g4() { return 0; }
-// CHECK: "\01?g4@@YAPBQ6AHH@ZXZ"
+// CHECK: "?g4@@YAPBQ6AHH@ZXZ"
extern int &z;
int & __restrict h1() { return z; }
-// CHECK: "\01?h1@@YAAIAHXZ"
+// CHECK: "?h1@@YAAIAHXZ"
diff --git a/test/CodeGenCXX/mangle-ms-string-literals.cpp b/test/CodeGenCXX/mangle-ms-string-literals.cpp
index e5ebc08..ee9994b 100644
--- a/test/CodeGenCXX/mangle-ms-string-literals.cpp
+++ b/test/CodeGenCXX/mangle-ms-string-literals.cpp
@@ -258,262 +258,262 @@
const char *l1 = "\x1";
const char *l0 = "\x0";
-// CHECK: @"\01??_C@_01CNACBAHC@?$PP?$AA@"
-// CHECK: @"\01??_C@_01DEBJCBDD@?$PO?$AA@"
-// CHECK: @"\01??_C@_01BPDEHCPA@?$PN?$AA@"
-// CHECK: @"\01??_C@_01GCPEDLB@?$PM?$AA@"
-// CHECK: @"\01??_C@_01EJGONFHG@?$PL?$AA@"
-// CHECK: @"\01??_C@_01FAHFOEDH@?z?$AA@"
-// CHECK: @"\01??_C@_01HLFILHPE@?y?$AA@"
-// CHECK: @"\01??_C@_01GCEDIGLF@?x?$AA@"
-// CHECK: @"\01??_C@_01OFNLJKHK@?w?$AA@"
-// CHECK: @"\01??_C@_01PMMAKLDL@?v?$AA@"
-// CHECK: @"\01??_C@_01NHONPIPI@?u?$AA@"
-// CHECK: @"\01??_C@_01MOPGMJLJ@?t?$AA@"
-// CHECK: @"\01??_C@_01IBLHFPHO@?s?$AA@"
-// CHECK: @"\01??_C@_01JIKMGODP@?r?$AA@"
-// CHECK: @"\01??_C@_01LDIBDNPM@?q?$AA@"
-// CHECK: @"\01??_C@_01KKJKAMLN@?p?$AA@"
-// CHECK: @"\01??_C@_01GHMAACCD@?o?$AA@"
-// CHECK: @"\01??_C@_01HONLDDGC@?n?$AA@"
-// CHECK: @"\01??_C@_01FFPGGAKB@?m?$AA@"
-// CHECK: @"\01??_C@_01EMONFBOA@?l?$AA@"
-// CHECK: @"\01??_C@_01DKMMHCH@?k?$AA@"
-// CHECK: @"\01??_C@_01BKLHPGGG@?j?$AA@"
-// CHECK: @"\01??_C@_01DBJKKFKF@?i?$AA@"
-// CHECK: @"\01??_C@_01CIIBJEOE@?h?$AA@"
-// CHECK: @"\01??_C@_01KPBJIICL@?g?$AA@"
-// CHECK: @"\01??_C@_01LGACLJGK@?f?$AA@"
-// CHECK: @"\01??_C@_01JNCPOKKJ@?e?$AA@"
-// CHECK: @"\01??_C@_01IEDENLOI@?d?$AA@"
-// CHECK: @"\01??_C@_01MLHFENCP@?c?$AA@"
-// CHECK: @"\01??_C@_01NCGOHMGO@?b?$AA@"
-// CHECK: @"\01??_C@_01PJEDCPKN@?a?$AA@"
-// CHECK: @"\01??_C@_01OAFIBOOM@?$OA?$AA@"
-// CHECK: @"\01??_C@_01LIIGDENA@?$NP?$AA@"
-// CHECK: @"\01??_C@_01KBJNAFJB@?$NO?$AA@"
-// CHECK: @"\01??_C@_01IKLAFGFC@?$NN?$AA@"
-// CHECK: @"\01??_C@_01JDKLGHBD@?$NM?$AA@"
-// CHECK: @"\01??_C@_01NMOKPBNE@?$NL?$AA@"
-// CHECK: @"\01??_C@_01MFPBMAJF@?Z?$AA@"
-// CHECK: @"\01??_C@_01OONMJDFG@?Y?$AA@"
-// CHECK: @"\01??_C@_01PHMHKCBH@?X?$AA@"
-// CHECK: @"\01??_C@_01HAFPLONI@?W?$AA@"
-// CHECK: @"\01??_C@_01GJEEIPJJ@?V?$AA@"
-// CHECK: @"\01??_C@_01ECGJNMFK@?U?$AA@"
-// CHECK: @"\01??_C@_01FLHCONBL@?T?$AA@"
-// CHECK: @"\01??_C@_01BEDDHLNM@?S?$AA@"
-// CHECK: @"\01??_C@_01NCIEKJN@?R?$AA@"
-// CHECK: @"\01??_C@_01CGAFBJFO@?Q?$AA@"
-// CHECK: @"\01??_C@_01DPBOCIBP@?P?$AA@"
-// CHECK: @"\01??_C@_01PCEECGIB@?O?$AA@"
-// CHECK: @"\01??_C@_01OLFPBHMA@?N?$AA@"
-// CHECK: @"\01??_C@_01MAHCEEAD@?M?$AA@"
-// CHECK: @"\01??_C@_01NJGJHFEC@?L?$AA@"
-// CHECK: @"\01??_C@_01JGCIODIF@?K?$AA@"
-// CHECK: @"\01??_C@_01IPDDNCME@?J?$AA@"
-// CHECK: @"\01??_C@_01KEBOIBAH@?I?$AA@"
-// CHECK: @"\01??_C@_01LNAFLAEG@?H?$AA@"
-// CHECK: @"\01??_C@_01DKJNKMIJ@?G?$AA@"
-// CHECK: @"\01??_C@_01CDIGJNMI@?F?$AA@"
-// CHECK: @"\01??_C@_01IKLMOAL@?E?$AA@"
-// CHECK: @"\01??_C@_01BBLAPPEK@?D?$AA@"
-// CHECK: @"\01??_C@_01FOPBGJIN@?C?$AA@"
-// CHECK: @"\01??_C@_01EHOKFIMM@?B?$AA@"
-// CHECK: @"\01??_C@_01GMMHALAP@?A?$AA@"
-// CHECK: @"\01??_C@_01HFNMDKEO@?$MA?$AA@"
-// CHECK: @"\01??_C@_01NNHLFPHH@?$LP?$AA@"
-// CHECK: @"\01??_C@_01MEGAGODG@?$LO?$AA@"
-// CHECK: @"\01??_C@_01OPENDNPF@?$LN?$AA@"
-// CHECK: @"\01??_C@_01PGFGAMLE@?$LM?$AA@"
-// CHECK: @"\01??_C@_01LJBHJKHD@?$LL?$AA@"
-// CHECK: @"\01??_C@_01KAAMKLDC@?$LK?$AA@"
-// CHECK: @"\01??_C@_01ILCBPIPB@?$LJ?$AA@"
-// CHECK: @"\01??_C@_01JCDKMJLA@?$LI?$AA@"
-// CHECK: @"\01??_C@_01BFKCNFHP@?$LH?$AA@"
-// CHECK: @"\01??_C@_01MLJOEDO@?$LG?$AA@"
-// CHECK: @"\01??_C@_01CHJELHPN@?$LF?$AA@"
-// CHECK: @"\01??_C@_01DOIPIGLM@?$LE?$AA@"
-// CHECK: @"\01??_C@_01HBMOBAHL@?$LD?$AA@"
-// CHECK: @"\01??_C@_01GINFCBDK@?$LC?$AA@"
-// CHECK: @"\01??_C@_01EDPIHCPJ@?$LB?$AA@"
-// CHECK: @"\01??_C@_01FKODEDLI@?$LA?$AA@"
-// CHECK: @"\01??_C@_01JHLJENCG@?$KP?$AA@"
-// CHECK: @"\01??_C@_01IOKCHMGH@?$KO?$AA@"
-// CHECK: @"\01??_C@_01KFIPCPKE@?$KN?$AA@"
-// CHECK: @"\01??_C@_01LMJEBOOF@?$KM?$AA@"
-// CHECK: @"\01??_C@_01PDNFIICC@?$KL?$AA@"
-// CHECK: @"\01??_C@_01OKMOLJGD@?$KK?$AA@"
-// CHECK: @"\01??_C@_01MBODOKKA@?$KJ?$AA@"
-// CHECK: @"\01??_C@_01NIPINLOB@?$KI?$AA@"
-// CHECK: @"\01??_C@_01FPGAMHCO@?$KH?$AA@"
-// CHECK: @"\01??_C@_01EGHLPGGP@?$KG?$AA@"
-// CHECK: @"\01??_C@_01GNFGKFKM@?$KF?$AA@"
-// CHECK: @"\01??_C@_01HEENJEON@?$KE?$AA@"
-// CHECK: @"\01??_C@_01DLAMACCK@?$KD?$AA@"
-// CHECK: @"\01??_C@_01CCBHDDGL@?$KC?$AA@"
-// CHECK: @"\01??_C@_01JDKGAKI@?$KB?$AA@"
-// CHECK: @"\01??_C@_01BACBFBOJ@?$KA?$AA@"
-// CHECK: @"\01??_C@_01EIPPHLNF@?$JP?$AA@"
-// CHECK: @"\01??_C@_01FBOEEKJE@?$JO?$AA@"
-// CHECK: @"\01??_C@_01HKMJBJFH@?$JN?$AA@"
-// CHECK: @"\01??_C@_01GDNCCIBG@?$JM?$AA@"
-// CHECK: @"\01??_C@_01CMJDLONB@?$JL?$AA@"
-// CHECK: @"\01??_C@_01DFIIIPJA@?$JK?$AA@"
-// CHECK: @"\01??_C@_01BOKFNMFD@?$JJ?$AA@"
-// CHECK: @"\01??_C@_01HLOONBC@?$JI?$AA@"
-// CHECK: @"\01??_C@_01IACGPBNN@?$JH?$AA@"
-// CHECK: @"\01??_C@_01JJDNMAJM@?$JG?$AA@"
-// CHECK: @"\01??_C@_01LCBAJDFP@?$JF?$AA@"
-// CHECK: @"\01??_C@_01KLALKCBO@?$JE?$AA@"
-// CHECK: @"\01??_C@_01OEEKDENJ@?$JD?$AA@"
-// CHECK: @"\01??_C@_01PNFBAFJI@?$JC?$AA@"
-// CHECK: @"\01??_C@_01NGHMFGFL@?$JB?$AA@"
-// CHECK: @"\01??_C@_01MPGHGHBK@?$JA?$AA@"
-// CHECK: @"\01??_C@_01CDNGJIE@?$IP?$AA@"
-// CHECK: @"\01??_C@_01BLCGFIMF@?$IO?$AA@"
-// CHECK: @"\01??_C@_01DAALALAG@?$IN?$AA@"
-// CHECK: @"\01??_C@_01CJBADKEH@?$IM?$AA@"
-// CHECK: @"\01??_C@_01GGFBKMIA@?$IL?$AA@"
-// CHECK: @"\01??_C@_01HPEKJNMB@?$IK?$AA@"
-// CHECK: @"\01??_C@_01FEGHMOAC@?$IJ?$AA@"
-// CHECK: @"\01??_C@_01ENHMPPED@?$II?$AA@"
-// CHECK: @"\01??_C@_01MKOEODIM@?$IH?$AA@"
-// CHECK: @"\01??_C@_01NDPPNCMN@?$IG?$AA@"
-// CHECK: @"\01??_C@_01PINCIBAO@?$IF?$AA@"
-// CHECK: @"\01??_C@_01OBMJLAEP@?$IE?$AA@"
-// CHECK: @"\01??_C@_01KOIICGII@?$ID?$AA@"
-// CHECK: @"\01??_C@_01LHJDBHMJ@?$IC?$AA@"
-// CHECK: @"\01??_C@_01JMLOEEAK@?$IB?$AA@"
-// CHECK: @"\01??_C@_01IFKFHFEL@?$IA?$AA@"
-// CHECK: @"\01??_C@_01BGIBIIDJ@?$HP?$AA@"
-// CHECK: @"\01??_C@_01PJKLJHI@?$HO?$AA@"
-// CHECK: @"\01??_C@_01CELHOKLL@?$HN?$AA@"
-// CHECK: @"\01??_C@_01DNKMNLPK@?$HM?$AA@"
-// CHECK: @"\01??_C@_01HCONENDN@?$HL?$AA@"
-// CHECK: @"\01??_C@_01GLPGHMHM@z?$AA@"
-// CHECK: @"\01??_C@_01EANLCPLP@y?$AA@"
-// CHECK: @"\01??_C@_01FJMABOPO@x?$AA@"
-// CHECK: @"\01??_C@_01NOFIACDB@w?$AA@"
-// CHECK: @"\01??_C@_01MHEDDDHA@v?$AA@"
-// CHECK: @"\01??_C@_01OMGOGALD@u?$AA@"
-// CHECK: @"\01??_C@_01PFHFFBPC@t?$AA@"
-// CHECK: @"\01??_C@_01LKDEMHDF@s?$AA@"
-// CHECK: @"\01??_C@_01KDCPPGHE@r?$AA@"
-// CHECK: @"\01??_C@_01IIACKFLH@q?$AA@"
-// CHECK: @"\01??_C@_01JBBJJEPG@p?$AA@"
-// CHECK: @"\01??_C@_01FMEDJKGI@o?$AA@"
-// CHECK: @"\01??_C@_01EFFIKLCJ@n?$AA@"
-// CHECK: @"\01??_C@_01GOHFPIOK@m?$AA@"
-// CHECK: @"\01??_C@_01HHGOMJKL@l?$AA@"
-// CHECK: @"\01??_C@_01DICPFPGM@k?$AA@"
-// CHECK: @"\01??_C@_01CBDEGOCN@j?$AA@"
-// CHECK: @"\01??_C@_01KBJDNOO@i?$AA@"
-// CHECK: @"\01??_C@_01BDACAMKP@h?$AA@"
-// CHECK: @"\01??_C@_01JEJKBAGA@g?$AA@"
-// CHECK: @"\01??_C@_01INIBCBCB@f?$AA@"
-// CHECK: @"\01??_C@_01KGKMHCOC@e?$AA@"
-// CHECK: @"\01??_C@_01LPLHEDKD@d?$AA@"
-// CHECK: @"\01??_C@_01PAPGNFGE@c?$AA@"
-// CHECK: @"\01??_C@_01OJONOECF@b?$AA@"
-// CHECK: @"\01??_C@_01MCMALHOG@a?$AA@"
-// CHECK: @"\01??_C@_01NLNLIGKH@?$GA?$AA@"
-// CHECK: @"\01??_C@_01IDAFKMJL@_?$AA@"
-// CHECK: @"\01??_C@_01JKBOJNNK@?$FO?$AA@"
-// CHECK: @"\01??_C@_01LBDDMOBJ@?$FN?$AA@"
-// CHECK: @"\01??_C@_01KICIPPFI@?2?$AA@"
-// CHECK: @"\01??_C@_01OHGJGJJP@?$FL?$AA@"
-// CHECK: @"\01??_C@_01POHCFINO@Z?$AA@"
-// CHECK: @"\01??_C@_01NFFPALBN@Y?$AA@"
-// CHECK: @"\01??_C@_01MMEEDKFM@X?$AA@"
-// CHECK: @"\01??_C@_01ELNMCGJD@W?$AA@"
-// CHECK: @"\01??_C@_01FCMHBHNC@V?$AA@"
-// CHECK: @"\01??_C@_01HJOKEEBB@U?$AA@"
-// CHECK: @"\01??_C@_01GAPBHFFA@T?$AA@"
-// CHECK: @"\01??_C@_01CPLAODJH@S?$AA@"
-// CHECK: @"\01??_C@_01DGKLNCNG@R?$AA@"
-// CHECK: @"\01??_C@_01BNIGIBBF@Q?$AA@"
-// CHECK: @"\01??_C@_01EJNLAFE@P?$AA@"
-// CHECK: @"\01??_C@_01MJMHLOMK@O?$AA@"
-// CHECK: @"\01??_C@_01NANMIPIL@N?$AA@"
-// CHECK: @"\01??_C@_01PLPBNMEI@M?$AA@"
-// CHECK: @"\01??_C@_01OCOKONAJ@L?$AA@"
-// CHECK: @"\01??_C@_01KNKLHLMO@K?$AA@"
-// CHECK: @"\01??_C@_01LELAEKIP@J?$AA@"
-// CHECK: @"\01??_C@_01JPJNBJEM@I?$AA@"
-// CHECK: @"\01??_C@_01IGIGCIAN@H?$AA@"
-// CHECK: @"\01??_C@_01BBODEMC@G?$AA@"
-// CHECK: @"\01??_C@_01BIAFAFID@F?$AA@"
-// CHECK: @"\01??_C@_01DDCIFGEA@E?$AA@"
-// CHECK: @"\01??_C@_01CKDDGHAB@D?$AA@"
-// CHECK: @"\01??_C@_01GFHCPBMG@C?$AA@"
-// CHECK: @"\01??_C@_01HMGJMAIH@B?$AA@"
-// CHECK: @"\01??_C@_01FHEEJDEE@A?$AA@"
-// CHECK: @"\01??_C@_01EOFPKCAF@?$EA?$AA@"
-// CHECK: @"\01??_C@_01OGPIMHDM@?$DP?$AA@"
-// CHECK: @"\01??_C@_01PPODPGHN@?$DO?$AA@"
-// CHECK: @"\01??_C@_01NEMOKFLO@?$DN?$AA@"
-// CHECK: @"\01??_C@_01MNNFJEPP@?$DM?$AA@"
-// CHECK: @"\01??_C@_01ICJEACDI@?$DL?$AA@"
-// CHECK: @"\01??_C@_01JLIPDDHJ@?3?$AA@"
-// CHECK: @"\01??_C@_01LAKCGALK@9?$AA@"
-// CHECK: @"\01??_C@_01KJLJFBPL@8?$AA@"
-// CHECK: @"\01??_C@_01COCBENDE@7?$AA@"
-// CHECK: @"\01??_C@_01DHDKHMHF@6?$AA@"
-// CHECK: @"\01??_C@_01BMBHCPLG@5?$AA@"
-// CHECK: @"\01??_C@_01FAMBOPH@4?$AA@"
-// CHECK: @"\01??_C@_01EKENIIDA@3?$AA@"
-// CHECK: @"\01??_C@_01FDFGLJHB@2?$AA@"
-// CHECK: @"\01??_C@_01HIHLOKLC@1?$AA@"
-// CHECK: @"\01??_C@_01GBGANLPD@0?$AA@"
-// CHECK: @"\01??_C@_01KMDKNFGN@?1?$AA@"
-// CHECK: @"\01??_C@_01LFCBOECM@?4?$AA@"
-// CHECK: @"\01??_C@_01JOAMLHOP@?9?$AA@"
-// CHECK: @"\01??_C@_01IHBHIGKO@?0?$AA@"
-// CHECK: @"\01??_C@_01MIFGBAGJ@?$CL?$AA@"
-// CHECK: @"\01??_C@_01NBENCBCI@?$CK?$AA@"
-// CHECK: @"\01??_C@_01PKGAHCOL@?$CJ?$AA@"
-// CHECK: @"\01??_C@_01ODHLEDKK@?$CI?$AA@"
-// CHECK: @"\01??_C@_01GEODFPGF@?8?$AA@"
-// CHECK: @"\01??_C@_01HNPIGOCE@?$CG?$AA@"
-// CHECK: @"\01??_C@_01FGNFDNOH@?$CF?$AA@"
-// CHECK: @"\01??_C@_01EPMOAMKG@$?$AA@"
-// CHECK: @"\01??_C@_01IPJKGB@?$CD?$AA@"
-// CHECK: @"\01??_C@_01BJJEKLCA@?$CC?$AA@"
-// CHECK: @"\01??_C@_01DCLJPIOD@?$CB?$AA@"
-// CHECK: @"\01??_C@_01CLKCMJKC@?5?$AA@"
-// CHECK: @"\01??_C@_01HDHMODJO@?$BP?$AA@"
-// CHECK: @"\01??_C@_01GKGHNCNP@?$BO?$AA@"
-// CHECK: @"\01??_C@_01EBEKIBBM@?$BN?$AA@"
-// CHECK: @"\01??_C@_01FIFBLAFN@?$BM?$AA@"
-// CHECK: @"\01??_C@_01BHBACGJK@?$BL?$AA@"
-// CHECK: @"\01??_C@_01OALBHNL@?$BK?$AA@"
-// CHECK: @"\01??_C@_01CFCGEEBI@?$BJ?$AA@"
-// CHECK: @"\01??_C@_01DMDNHFFJ@?$BI?$AA@"
-// CHECK: @"\01??_C@_01LLKFGJJG@?$BH?$AA@"
-// CHECK: @"\01??_C@_01KCLOFINH@?$BG?$AA@"
-// CHECK: @"\01??_C@_01IJJDALBE@?$BF?$AA@"
-// CHECK: @"\01??_C@_01JAIIDKFF@?$BE?$AA@"
-// CHECK: @"\01??_C@_01NPMJKMJC@?$BD?$AA@"
-// CHECK: @"\01??_C@_01MGNCJNND@?$BC?$AA@"
-// CHECK: @"\01??_C@_01ONPPMOBA@?$BB?$AA@"
-// CHECK: @"\01??_C@_01PEOEPPFB@?$BA?$AA@"
-// CHECK: @"\01??_C@_01DJLOPBMP@?$AP?$AA@"
-// CHECK: @"\01??_C@_01CAKFMAIO@?$AO?$AA@"
-// CHECK: @"\01??_C@_01LIIJDEN@?$AN?$AA@"
-// CHECK: @"\01??_C@_01BCJDKCAM@?$AM?$AA@"
-// CHECK: @"\01??_C@_01FNNCDEML@?$AL?$AA@"
-// CHECK: @"\01??_C@_01EEMJAFIK@?6?$AA@"
-// CHECK: @"\01??_C@_01GPOEFGEJ@?7?$AA@"
-// CHECK: @"\01??_C@_01HGPPGHAI@?$AI?$AA@"
-// CHECK: @"\01??_C@_01PBGHHLMH@?$AH?$AA@"
-// CHECK: @"\01??_C@_01OIHMEKIG@?$AG?$AA@"
-// CHECK: @"\01??_C@_01MDFBBJEF@?$AF?$AA@"
-// CHECK: @"\01??_C@_01NKEKCIAE@?$AE?$AA@"
-// CHECK: @"\01??_C@_01JFALLOMD@?$AD?$AA@"
-// CHECK: @"\01??_C@_01IMBAIPIC@?$AC?$AA@"
-// CHECK: @"\01??_C@_01KHDNNMEB@?$AB?$AA@"
-// CHECK: @"\01??_C@_01LOCGONAA@?$AA?$AA@"
+// CHECK: @"??_C@_01CNACBAHC@?$PP?$AA@"
+// CHECK: @"??_C@_01DEBJCBDD@?$PO?$AA@"
+// CHECK: @"??_C@_01BPDEHCPA@?$PN?$AA@"
+// CHECK: @"??_C@_01GCPEDLB@?$PM?$AA@"
+// CHECK: @"??_C@_01EJGONFHG@?$PL?$AA@"
+// CHECK: @"??_C@_01FAHFOEDH@?z?$AA@"
+// CHECK: @"??_C@_01HLFILHPE@?y?$AA@"
+// CHECK: @"??_C@_01GCEDIGLF@?x?$AA@"
+// CHECK: @"??_C@_01OFNLJKHK@?w?$AA@"
+// CHECK: @"??_C@_01PMMAKLDL@?v?$AA@"
+// CHECK: @"??_C@_01NHONPIPI@?u?$AA@"
+// CHECK: @"??_C@_01MOPGMJLJ@?t?$AA@"
+// CHECK: @"??_C@_01IBLHFPHO@?s?$AA@"
+// CHECK: @"??_C@_01JIKMGODP@?r?$AA@"
+// CHECK: @"??_C@_01LDIBDNPM@?q?$AA@"
+// CHECK: @"??_C@_01KKJKAMLN@?p?$AA@"
+// CHECK: @"??_C@_01GHMAACCD@?o?$AA@"
+// CHECK: @"??_C@_01HONLDDGC@?n?$AA@"
+// CHECK: @"??_C@_01FFPGGAKB@?m?$AA@"
+// CHECK: @"??_C@_01EMONFBOA@?l?$AA@"
+// CHECK: @"??_C@_01DKMMHCH@?k?$AA@"
+// CHECK: @"??_C@_01BKLHPGGG@?j?$AA@"
+// CHECK: @"??_C@_01DBJKKFKF@?i?$AA@"
+// CHECK: @"??_C@_01CIIBJEOE@?h?$AA@"
+// CHECK: @"??_C@_01KPBJIICL@?g?$AA@"
+// CHECK: @"??_C@_01LGACLJGK@?f?$AA@"
+// CHECK: @"??_C@_01JNCPOKKJ@?e?$AA@"
+// CHECK: @"??_C@_01IEDENLOI@?d?$AA@"
+// CHECK: @"??_C@_01MLHFENCP@?c?$AA@"
+// CHECK: @"??_C@_01NCGOHMGO@?b?$AA@"
+// CHECK: @"??_C@_01PJEDCPKN@?a?$AA@"
+// CHECK: @"??_C@_01OAFIBOOM@?$OA?$AA@"
+// CHECK: @"??_C@_01LIIGDENA@?$NP?$AA@"
+// CHECK: @"??_C@_01KBJNAFJB@?$NO?$AA@"
+// CHECK: @"??_C@_01IKLAFGFC@?$NN?$AA@"
+// CHECK: @"??_C@_01JDKLGHBD@?$NM?$AA@"
+// CHECK: @"??_C@_01NMOKPBNE@?$NL?$AA@"
+// CHECK: @"??_C@_01MFPBMAJF@?Z?$AA@"
+// CHECK: @"??_C@_01OONMJDFG@?Y?$AA@"
+// CHECK: @"??_C@_01PHMHKCBH@?X?$AA@"
+// CHECK: @"??_C@_01HAFPLONI@?W?$AA@"
+// CHECK: @"??_C@_01GJEEIPJJ@?V?$AA@"
+// CHECK: @"??_C@_01ECGJNMFK@?U?$AA@"
+// CHECK: @"??_C@_01FLHCONBL@?T?$AA@"
+// CHECK: @"??_C@_01BEDDHLNM@?S?$AA@"
+// CHECK: @"??_C@_01NCIEKJN@?R?$AA@"
+// CHECK: @"??_C@_01CGAFBJFO@?Q?$AA@"
+// CHECK: @"??_C@_01DPBOCIBP@?P?$AA@"
+// CHECK: @"??_C@_01PCEECGIB@?O?$AA@"
+// CHECK: @"??_C@_01OLFPBHMA@?N?$AA@"
+// CHECK: @"??_C@_01MAHCEEAD@?M?$AA@"
+// CHECK: @"??_C@_01NJGJHFEC@?L?$AA@"
+// CHECK: @"??_C@_01JGCIODIF@?K?$AA@"
+// CHECK: @"??_C@_01IPDDNCME@?J?$AA@"
+// CHECK: @"??_C@_01KEBOIBAH@?I?$AA@"
+// CHECK: @"??_C@_01LNAFLAEG@?H?$AA@"
+// CHECK: @"??_C@_01DKJNKMIJ@?G?$AA@"
+// CHECK: @"??_C@_01CDIGJNMI@?F?$AA@"
+// CHECK: @"??_C@_01IKLMOAL@?E?$AA@"
+// CHECK: @"??_C@_01BBLAPPEK@?D?$AA@"
+// CHECK: @"??_C@_01FOPBGJIN@?C?$AA@"
+// CHECK: @"??_C@_01EHOKFIMM@?B?$AA@"
+// CHECK: @"??_C@_01GMMHALAP@?A?$AA@"
+// CHECK: @"??_C@_01HFNMDKEO@?$MA?$AA@"
+// CHECK: @"??_C@_01NNHLFPHH@?$LP?$AA@"
+// CHECK: @"??_C@_01MEGAGODG@?$LO?$AA@"
+// CHECK: @"??_C@_01OPENDNPF@?$LN?$AA@"
+// CHECK: @"??_C@_01PGFGAMLE@?$LM?$AA@"
+// CHECK: @"??_C@_01LJBHJKHD@?$LL?$AA@"
+// CHECK: @"??_C@_01KAAMKLDC@?$LK?$AA@"
+// CHECK: @"??_C@_01ILCBPIPB@?$LJ?$AA@"
+// CHECK: @"??_C@_01JCDKMJLA@?$LI?$AA@"
+// CHECK: @"??_C@_01BFKCNFHP@?$LH?$AA@"
+// CHECK: @"??_C@_01MLJOEDO@?$LG?$AA@"
+// CHECK: @"??_C@_01CHJELHPN@?$LF?$AA@"
+// CHECK: @"??_C@_01DOIPIGLM@?$LE?$AA@"
+// CHECK: @"??_C@_01HBMOBAHL@?$LD?$AA@"
+// CHECK: @"??_C@_01GINFCBDK@?$LC?$AA@"
+// CHECK: @"??_C@_01EDPIHCPJ@?$LB?$AA@"
+// CHECK: @"??_C@_01FKODEDLI@?$LA?$AA@"
+// CHECK: @"??_C@_01JHLJENCG@?$KP?$AA@"
+// CHECK: @"??_C@_01IOKCHMGH@?$KO?$AA@"
+// CHECK: @"??_C@_01KFIPCPKE@?$KN?$AA@"
+// CHECK: @"??_C@_01LMJEBOOF@?$KM?$AA@"
+// CHECK: @"??_C@_01PDNFIICC@?$KL?$AA@"
+// CHECK: @"??_C@_01OKMOLJGD@?$KK?$AA@"
+// CHECK: @"??_C@_01MBODOKKA@?$KJ?$AA@"
+// CHECK: @"??_C@_01NIPINLOB@?$KI?$AA@"
+// CHECK: @"??_C@_01FPGAMHCO@?$KH?$AA@"
+// CHECK: @"??_C@_01EGHLPGGP@?$KG?$AA@"
+// CHECK: @"??_C@_01GNFGKFKM@?$KF?$AA@"
+// CHECK: @"??_C@_01HEENJEON@?$KE?$AA@"
+// CHECK: @"??_C@_01DLAMACCK@?$KD?$AA@"
+// CHECK: @"??_C@_01CCBHDDGL@?$KC?$AA@"
+// CHECK: @"??_C@_01JDKGAKI@?$KB?$AA@"
+// CHECK: @"??_C@_01BACBFBOJ@?$KA?$AA@"
+// CHECK: @"??_C@_01EIPPHLNF@?$JP?$AA@"
+// CHECK: @"??_C@_01FBOEEKJE@?$JO?$AA@"
+// CHECK: @"??_C@_01HKMJBJFH@?$JN?$AA@"
+// CHECK: @"??_C@_01GDNCCIBG@?$JM?$AA@"
+// CHECK: @"??_C@_01CMJDLONB@?$JL?$AA@"
+// CHECK: @"??_C@_01DFIIIPJA@?$JK?$AA@"
+// CHECK: @"??_C@_01BOKFNMFD@?$JJ?$AA@"
+// CHECK: @"??_C@_01HLOONBC@?$JI?$AA@"
+// CHECK: @"??_C@_01IACGPBNN@?$JH?$AA@"
+// CHECK: @"??_C@_01JJDNMAJM@?$JG?$AA@"
+// CHECK: @"??_C@_01LCBAJDFP@?$JF?$AA@"
+// CHECK: @"??_C@_01KLALKCBO@?$JE?$AA@"
+// CHECK: @"??_C@_01OEEKDENJ@?$JD?$AA@"
+// CHECK: @"??_C@_01PNFBAFJI@?$JC?$AA@"
+// CHECK: @"??_C@_01NGHMFGFL@?$JB?$AA@"
+// CHECK: @"??_C@_01MPGHGHBK@?$JA?$AA@"
+// CHECK: @"??_C@_01CDNGJIE@?$IP?$AA@"
+// CHECK: @"??_C@_01BLCGFIMF@?$IO?$AA@"
+// CHECK: @"??_C@_01DAALALAG@?$IN?$AA@"
+// CHECK: @"??_C@_01CJBADKEH@?$IM?$AA@"
+// CHECK: @"??_C@_01GGFBKMIA@?$IL?$AA@"
+// CHECK: @"??_C@_01HPEKJNMB@?$IK?$AA@"
+// CHECK: @"??_C@_01FEGHMOAC@?$IJ?$AA@"
+// CHECK: @"??_C@_01ENHMPPED@?$II?$AA@"
+// CHECK: @"??_C@_01MKOEODIM@?$IH?$AA@"
+// CHECK: @"??_C@_01NDPPNCMN@?$IG?$AA@"
+// CHECK: @"??_C@_01PINCIBAO@?$IF?$AA@"
+// CHECK: @"??_C@_01OBMJLAEP@?$IE?$AA@"
+// CHECK: @"??_C@_01KOIICGII@?$ID?$AA@"
+// CHECK: @"??_C@_01LHJDBHMJ@?$IC?$AA@"
+// CHECK: @"??_C@_01JMLOEEAK@?$IB?$AA@"
+// CHECK: @"??_C@_01IFKFHFEL@?$IA?$AA@"
+// CHECK: @"??_C@_01BGIBIIDJ@?$HP?$AA@"
+// CHECK: @"??_C@_01PJKLJHI@?$HO?$AA@"
+// CHECK: @"??_C@_01CELHOKLL@?$HN?$AA@"
+// CHECK: @"??_C@_01DNKMNLPK@?$HM?$AA@"
+// CHECK: @"??_C@_01HCONENDN@?$HL?$AA@"
+// CHECK: @"??_C@_01GLPGHMHM@z?$AA@"
+// CHECK: @"??_C@_01EANLCPLP@y?$AA@"
+// CHECK: @"??_C@_01FJMABOPO@x?$AA@"
+// CHECK: @"??_C@_01NOFIACDB@w?$AA@"
+// CHECK: @"??_C@_01MHEDDDHA@v?$AA@"
+// CHECK: @"??_C@_01OMGOGALD@u?$AA@"
+// CHECK: @"??_C@_01PFHFFBPC@t?$AA@"
+// CHECK: @"??_C@_01LKDEMHDF@s?$AA@"
+// CHECK: @"??_C@_01KDCPPGHE@r?$AA@"
+// CHECK: @"??_C@_01IIACKFLH@q?$AA@"
+// CHECK: @"??_C@_01JBBJJEPG@p?$AA@"
+// CHECK: @"??_C@_01FMEDJKGI@o?$AA@"
+// CHECK: @"??_C@_01EFFIKLCJ@n?$AA@"
+// CHECK: @"??_C@_01GOHFPIOK@m?$AA@"
+// CHECK: @"??_C@_01HHGOMJKL@l?$AA@"
+// CHECK: @"??_C@_01DICPFPGM@k?$AA@"
+// CHECK: @"??_C@_01CBDEGOCN@j?$AA@"
+// CHECK: @"??_C@_01KBJDNOO@i?$AA@"
+// CHECK: @"??_C@_01BDACAMKP@h?$AA@"
+// CHECK: @"??_C@_01JEJKBAGA@g?$AA@"
+// CHECK: @"??_C@_01INIBCBCB@f?$AA@"
+// CHECK: @"??_C@_01KGKMHCOC@e?$AA@"
+// CHECK: @"??_C@_01LPLHEDKD@d?$AA@"
+// CHECK: @"??_C@_01PAPGNFGE@c?$AA@"
+// CHECK: @"??_C@_01OJONOECF@b?$AA@"
+// CHECK: @"??_C@_01MCMALHOG@a?$AA@"
+// CHECK: @"??_C@_01NLNLIGKH@?$GA?$AA@"
+// CHECK: @"??_C@_01IDAFKMJL@_?$AA@"
+// CHECK: @"??_C@_01JKBOJNNK@?$FO?$AA@"
+// CHECK: @"??_C@_01LBDDMOBJ@?$FN?$AA@"
+// CHECK: @"??_C@_01KICIPPFI@?2?$AA@"
+// CHECK: @"??_C@_01OHGJGJJP@?$FL?$AA@"
+// CHECK: @"??_C@_01POHCFINO@Z?$AA@"
+// CHECK: @"??_C@_01NFFPALBN@Y?$AA@"
+// CHECK: @"??_C@_01MMEEDKFM@X?$AA@"
+// CHECK: @"??_C@_01ELNMCGJD@W?$AA@"
+// CHECK: @"??_C@_01FCMHBHNC@V?$AA@"
+// CHECK: @"??_C@_01HJOKEEBB@U?$AA@"
+// CHECK: @"??_C@_01GAPBHFFA@T?$AA@"
+// CHECK: @"??_C@_01CPLAODJH@S?$AA@"
+// CHECK: @"??_C@_01DGKLNCNG@R?$AA@"
+// CHECK: @"??_C@_01BNIGIBBF@Q?$AA@"
+// CHECK: @"??_C@_01EJNLAFE@P?$AA@"
+// CHECK: @"??_C@_01MJMHLOMK@O?$AA@"
+// CHECK: @"??_C@_01NANMIPIL@N?$AA@"
+// CHECK: @"??_C@_01PLPBNMEI@M?$AA@"
+// CHECK: @"??_C@_01OCOKONAJ@L?$AA@"
+// CHECK: @"??_C@_01KNKLHLMO@K?$AA@"
+// CHECK: @"??_C@_01LELAEKIP@J?$AA@"
+// CHECK: @"??_C@_01JPJNBJEM@I?$AA@"
+// CHECK: @"??_C@_01IGIGCIAN@H?$AA@"
+// CHECK: @"??_C@_01BBODEMC@G?$AA@"
+// CHECK: @"??_C@_01BIAFAFID@F?$AA@"
+// CHECK: @"??_C@_01DDCIFGEA@E?$AA@"
+// CHECK: @"??_C@_01CKDDGHAB@D?$AA@"
+// CHECK: @"??_C@_01GFHCPBMG@C?$AA@"
+// CHECK: @"??_C@_01HMGJMAIH@B?$AA@"
+// CHECK: @"??_C@_01FHEEJDEE@A?$AA@"
+// CHECK: @"??_C@_01EOFPKCAF@?$EA?$AA@"
+// CHECK: @"??_C@_01OGPIMHDM@?$DP?$AA@"
+// CHECK: @"??_C@_01PPODPGHN@?$DO?$AA@"
+// CHECK: @"??_C@_01NEMOKFLO@?$DN?$AA@"
+// CHECK: @"??_C@_01MNNFJEPP@?$DM?$AA@"
+// CHECK: @"??_C@_01ICJEACDI@?$DL?$AA@"
+// CHECK: @"??_C@_01JLIPDDHJ@?3?$AA@"
+// CHECK: @"??_C@_01LAKCGALK@9?$AA@"
+// CHECK: @"??_C@_01KJLJFBPL@8?$AA@"
+// CHECK: @"??_C@_01COCBENDE@7?$AA@"
+// CHECK: @"??_C@_01DHDKHMHF@6?$AA@"
+// CHECK: @"??_C@_01BMBHCPLG@5?$AA@"
+// CHECK: @"??_C@_01FAMBOPH@4?$AA@"
+// CHECK: @"??_C@_01EKENIIDA@3?$AA@"
+// CHECK: @"??_C@_01FDFGLJHB@2?$AA@"
+// CHECK: @"??_C@_01HIHLOKLC@1?$AA@"
+// CHECK: @"??_C@_01GBGANLPD@0?$AA@"
+// CHECK: @"??_C@_01KMDKNFGN@?1?$AA@"
+// CHECK: @"??_C@_01LFCBOECM@?4?$AA@"
+// CHECK: @"??_C@_01JOAMLHOP@?9?$AA@"
+// CHECK: @"??_C@_01IHBHIGKO@?0?$AA@"
+// CHECK: @"??_C@_01MIFGBAGJ@?$CL?$AA@"
+// CHECK: @"??_C@_01NBENCBCI@?$CK?$AA@"
+// CHECK: @"??_C@_01PKGAHCOL@?$CJ?$AA@"
+// CHECK: @"??_C@_01ODHLEDKK@?$CI?$AA@"
+// CHECK: @"??_C@_01GEODFPGF@?8?$AA@"
+// CHECK: @"??_C@_01HNPIGOCE@?$CG?$AA@"
+// CHECK: @"??_C@_01FGNFDNOH@?$CF?$AA@"
+// CHECK: @"??_C@_01EPMOAMKG@$?$AA@"
+// CHECK: @"??_C@_01IPJKGB@?$CD?$AA@"
+// CHECK: @"??_C@_01BJJEKLCA@?$CC?$AA@"
+// CHECK: @"??_C@_01DCLJPIOD@?$CB?$AA@"
+// CHECK: @"??_C@_01CLKCMJKC@?5?$AA@"
+// CHECK: @"??_C@_01HDHMODJO@?$BP?$AA@"
+// CHECK: @"??_C@_01GKGHNCNP@?$BO?$AA@"
+// CHECK: @"??_C@_01EBEKIBBM@?$BN?$AA@"
+// CHECK: @"??_C@_01FIFBLAFN@?$BM?$AA@"
+// CHECK: @"??_C@_01BHBACGJK@?$BL?$AA@"
+// CHECK: @"??_C@_01OALBHNL@?$BK?$AA@"
+// CHECK: @"??_C@_01CFCGEEBI@?$BJ?$AA@"
+// CHECK: @"??_C@_01DMDNHFFJ@?$BI?$AA@"
+// CHECK: @"??_C@_01LLKFGJJG@?$BH?$AA@"
+// CHECK: @"??_C@_01KCLOFINH@?$BG?$AA@"
+// CHECK: @"??_C@_01IJJDALBE@?$BF?$AA@"
+// CHECK: @"??_C@_01JAIIDKFF@?$BE?$AA@"
+// CHECK: @"??_C@_01NPMJKMJC@?$BD?$AA@"
+// CHECK: @"??_C@_01MGNCJNND@?$BC?$AA@"
+// CHECK: @"??_C@_01ONPPMOBA@?$BB?$AA@"
+// CHECK: @"??_C@_01PEOEPPFB@?$BA?$AA@"
+// CHECK: @"??_C@_01DJLOPBMP@?$AP?$AA@"
+// CHECK: @"??_C@_01CAKFMAIO@?$AO?$AA@"
+// CHECK: @"??_C@_01LIIJDEN@?$AN?$AA@"
+// CHECK: @"??_C@_01BCJDKCAM@?$AM?$AA@"
+// CHECK: @"??_C@_01FNNCDEML@?$AL?$AA@"
+// CHECK: @"??_C@_01EEMJAFIK@?6?$AA@"
+// CHECK: @"??_C@_01GPOEFGEJ@?7?$AA@"
+// CHECK: @"??_C@_01HGPPGHAI@?$AI?$AA@"
+// CHECK: @"??_C@_01PBGHHLMH@?$AH?$AA@"
+// CHECK: @"??_C@_01OIHMEKIG@?$AG?$AA@"
+// CHECK: @"??_C@_01MDFBBJEF@?$AF?$AA@"
+// CHECK: @"??_C@_01NKEKCIAE@?$AE?$AA@"
+// CHECK: @"??_C@_01JFALLOMD@?$AD?$AA@"
+// CHECK: @"??_C@_01IMBAIPIC@?$AC?$AA@"
+// CHECK: @"??_C@_01KHDNNMEB@?$AB?$AA@"
+// CHECK: @"??_C@_01LOCGONAA@?$AA?$AA@"
const wchar_t *wl9 = L"\t";
const wchar_t *wl10 = L"\n";
@@ -614,114 +614,114 @@
const wchar_t *wl125 = L"}";
const wchar_t *wl126 = L"~";
-// CHECK: @"\01??_C@_13KDLDGPGJ@?$AA?7?$AA?$AA@"
-// CHECK: @"\01??_C@_13LBAGMAIH@?$AA?6?$AA?$AA@"
-// CHECK: @"\01??_C@_13JLKKHOC@?$AA?$AL?$AA?$AA@"
-// CHECK: @"\01??_C@_13HOIJIPNN@?$AA?5?$AA?$AA@"
-// CHECK: @"\01??_C@_13MGDFOILI@?$AA?$CB?$AA?$AA@"
-// CHECK: @"\01??_C@_13NEIAEHFG@?$AA?$CC?$AA?$AA@"
-// CHECK: @"\01??_C@_13GMDMCADD@?$AA?$CD?$AA?$AA@"
-// CHECK: @"\01??_C@_13PBOLBIIK@?$AA$?$AA?$AA@"
-// CHECK: @"\01??_C@_13EJFHHPOP@?$AA?$CF?$AA?$AA@"
-// CHECK: @"\01??_C@_13FLOCNAAB@?$AA?$CG?$AA?$AA@"
-// CHECK: @"\01??_C@_13ODFOLHGE@?$AA?8?$AA?$AA@"
-// CHECK: @"\01??_C@_13LLDNKHDC@?$AA?$CI?$AA?$AA@"
-// CHECK: @"\01??_C@_13DIBMAFH@?$AA?$CJ?$AA?$AA@"
-// CHECK: @"\01??_C@_13BBDEGPLJ@?$AA?$CK?$AA?$AA@"
-// CHECK: @"\01??_C@_13KJIIAINM@?$AA?$CL?$AA?$AA@"
-// CHECK: @"\01??_C@_13DEFPDAGF@?$AA?0?$AA?$AA@"
-// CHECK: @"\01??_C@_13IMODFHAA@?$AA?9?$AA?$AA@"
-// CHECK: @"\01??_C@_13JOFGPIOO@?$AA?4?$AA?$AA@"
-// CHECK: @"\01??_C@_13CGOKJPIL@?$AA?1?$AA?$AA@"
-// CHECK: @"\01??_C@_13COJANIEC@?$AA0?$AA?$AA@"
-// CHECK: @"\01??_C@_13JGCMLPCH@?$AA1?$AA?$AA@"
-// CHECK: @"\01??_C@_13IEJJBAMJ@?$AA2?$AA?$AA@"
-// CHECK: @"\01??_C@_13DMCFHHKM@?$AA3?$AA?$AA@"
-// CHECK: @"\01??_C@_13KBPCEPBF@?$AA4?$AA?$AA@"
-// CHECK: @"\01??_C@_13BJEOCIHA@?$AA5?$AA?$AA@"
-// CHECK: @"\01??_C@_13LPLIHJO@?$AA6?$AA?$AA@"
-// CHECK: @"\01??_C@_13LDEHOAPL@?$AA7?$AA?$AA@"
-// CHECK: @"\01??_C@_13OLCEPAKN@?$AA8?$AA?$AA@"
-// CHECK: @"\01??_C@_13FDJIJHMI@?$AA9?$AA?$AA@"
-// CHECK: @"\01??_C@_13EBCNDICG@?$AA?3?$AA?$AA@"
-// CHECK: @"\01??_C@_13PJJBFPED@?$AA?$DL?$AA?$AA@"
-// CHECK: @"\01??_C@_13GEEGGHPK@?$AA?$DM?$AA?$AA@"
-// CHECK: @"\01??_C@_13NMPKAAJP@?$AA?$DN?$AA?$AA@"
-// CHECK: @"\01??_C@_13MOEPKPHB@?$AA?$DO?$AA?$AA@"
-// CHECK: @"\01??_C@_13HGPDMIBE@?$AA?$DP?$AA?$AA@"
-// CHECK: @"\01??_C@_13EFKPHINO@?$AA?$EA?$AA?$AA@"
-// CHECK: @"\01??_C@_13PNBDBPLL@?$AAA?$AA?$AA@"
-// CHECK: @"\01??_C@_13OPKGLAFF@?$AAB?$AA?$AA@"
-// CHECK: @"\01??_C@_13FHBKNHDA@?$AAC?$AA?$AA@"
-// CHECK: @"\01??_C@_13MKMNOPIJ@?$AAD?$AA?$AA@"
-// CHECK: @"\01??_C@_13HCHBIIOM@?$AAE?$AA?$AA@"
-// CHECK: @"\01??_C@_13GAMECHAC@?$AAF?$AA?$AA@"
-// CHECK: @"\01??_C@_13NIHIEAGH@?$AAG?$AA?$AA@"
-// CHECK: @"\01??_C@_13IABLFADB@?$AAH?$AA?$AA@"
-// CHECK: @"\01??_C@_13DIKHDHFE@?$AAI?$AA?$AA@"
-// CHECK: @"\01??_C@_13CKBCJILK@?$AAJ?$AA?$AA@"
-// CHECK: @"\01??_C@_13JCKOPPNP@?$AAK?$AA?$AA@"
-// CHECK: @"\01??_C@_13PHJMHGG@?$AAL?$AA?$AA@"
-// CHECK: @"\01??_C@_13LHMFKAAD@?$AAM?$AA?$AA@"
-// CHECK: @"\01??_C@_13KFHAAPON@?$AAN?$AA?$AA@"
-// CHECK: @"\01??_C@_13BNMMGIII@?$AAO?$AA?$AA@"
-// CHECK: @"\01??_C@_13BFLGCPEB@?$AAP?$AA?$AA@"
-// CHECK: @"\01??_C@_13KNAKEICE@?$AAQ?$AA?$AA@"
-// CHECK: @"\01??_C@_13LPLPOHMK@?$AAR?$AA?$AA@"
-// CHECK: @"\01??_C@_13HADIAKP@?$AAS?$AA?$AA@"
-// CHECK: @"\01??_C@_13JKNELIBG@?$AAT?$AA?$AA@"
-// CHECK: @"\01??_C@_13CCGINPHD@?$AAU?$AA?$AA@"
-// CHECK: @"\01??_C@_13DANNHAJN@?$AAV?$AA?$AA@"
-// CHECK: @"\01??_C@_13IIGBBHPI@?$AAW?$AA?$AA@"
-// CHECK: @"\01??_C@_13NAACAHKO@?$AAX?$AA?$AA@"
-// CHECK: @"\01??_C@_13GILOGAML@?$AAY?$AA?$AA@"
-// CHECK: @"\01??_C@_13HKALMPCF@?$AAZ?$AA?$AA@"
-// CHECK: @"\01??_C@_13MCLHKIEA@?$AA?$FL?$AA?$AA@"
-// CHECK: @"\01??_C@_13FPGAJAPJ@?$AA?2?$AA?$AA@"
-// CHECK: @"\01??_C@_13OHNMPHJM@?$AA?$FN?$AA?$AA@"
-// CHECK: @"\01??_C@_13PFGJFIHC@?$AA?$FO?$AA?$AA@"
-// CHECK: @"\01??_C@_13ENNFDPBH@?$AA_?$AA?$AA@"
-// CHECK: @"\01??_C@_13OFJNNHOA@?$AA?$GA?$AA?$AA@"
-// CHECK: @"\01??_C@_13FNCBLAIF@?$AAa?$AA?$AA@"
-// CHECK: @"\01??_C@_13EPJEBPGL@?$AAb?$AA?$AA@"
-// CHECK: @"\01??_C@_13PHCIHIAO@?$AAc?$AA?$AA@"
-// CHECK: @"\01??_C@_13GKPPEALH@?$AAd?$AA?$AA@"
-// CHECK: @"\01??_C@_13NCEDCHNC@?$AAe?$AA?$AA@"
-// CHECK: @"\01??_C@_13MAPGIIDM@?$AAf?$AA?$AA@"
-// CHECK: @"\01??_C@_13HIEKOPFJ@?$AAg?$AA?$AA@"
-// CHECK: @"\01??_C@_13CACJPPAP@?$AAh?$AA?$AA@"
-// CHECK: @"\01??_C@_13JIJFJIGK@?$AAi?$AA?$AA@"
-// CHECK: @"\01??_C@_13IKCADHIE@?$AAj?$AA?$AA@"
-// CHECK: @"\01??_C@_13DCJMFAOB@?$AAk?$AA?$AA@"
-// CHECK: @"\01??_C@_13KPELGIFI@?$AAl?$AA?$AA@"
-// CHECK: @"\01??_C@_13BHPHAPDN@?$AAm?$AA?$AA@"
-// CHECK: @"\01??_C@_13FECKAND@?$AAn?$AA?$AA@"
-// CHECK: @"\01??_C@_13LNPOMHLG@?$AAo?$AA?$AA@"
-// CHECK: @"\01??_C@_13LFIEIAHP@?$AAp?$AA?$AA@"
-// CHECK: @"\01??_C@_13NDIOHBK@?$AAq?$AA?$AA@"
-// CHECK: @"\01??_C@_13BPINEIPE@?$AAr?$AA?$AA@"
-// CHECK: @"\01??_C@_13KHDBCPJB@?$AAs?$AA?$AA@"
-// CHECK: @"\01??_C@_13DKOGBHCI@?$AAt?$AA?$AA@"
-// CHECK: @"\01??_C@_13ICFKHAEN@?$AAu?$AA?$AA@"
-// CHECK: @"\01??_C@_13JAOPNPKD@?$AAv?$AA?$AA@"
-// CHECK: @"\01??_C@_13CIFDLIMG@?$AAw?$AA?$AA@"
-// CHECK: @"\01??_C@_13HADAKIJA@?$AAx?$AA?$AA@"
-// CHECK: @"\01??_C@_13MIIMMPPF@?$AAy?$AA?$AA@"
-// CHECK: @"\01??_C@_13NKDJGABL@?$AAz?$AA?$AA@"
-// CHECK: @"\01??_C@_13GCIFAHHO@?$AA?$HL?$AA?$AA@"
-// CHECK: @"\01??_C@_13PPFCDPMH@?$AA?$HM?$AA?$AA@"
-// CHECK: @"\01??_C@_13EHOOFIKC@?$AA?$HN?$AA?$AA@"
-// CHECK: @"\01??_C@_13FFFLPHEM@?$AA?$HO?$AA?$AA@"
+// CHECK: @"??_C@_13KDLDGPGJ@?$AA?7?$AA?$AA@"
+// CHECK: @"??_C@_13LBAGMAIH@?$AA?6?$AA?$AA@"
+// CHECK: @"??_C@_13JLKKHOC@?$AA?$AL?$AA?$AA@"
+// CHECK: @"??_C@_13HOIJIPNN@?$AA?5?$AA?$AA@"
+// CHECK: @"??_C@_13MGDFOILI@?$AA?$CB?$AA?$AA@"
+// CHECK: @"??_C@_13NEIAEHFG@?$AA?$CC?$AA?$AA@"
+// CHECK: @"??_C@_13GMDMCADD@?$AA?$CD?$AA?$AA@"
+// CHECK: @"??_C@_13PBOLBIIK@?$AA$?$AA?$AA@"
+// CHECK: @"??_C@_13EJFHHPOP@?$AA?$CF?$AA?$AA@"
+// CHECK: @"??_C@_13FLOCNAAB@?$AA?$CG?$AA?$AA@"
+// CHECK: @"??_C@_13ODFOLHGE@?$AA?8?$AA?$AA@"
+// CHECK: @"??_C@_13LLDNKHDC@?$AA?$CI?$AA?$AA@"
+// CHECK: @"??_C@_13DIBMAFH@?$AA?$CJ?$AA?$AA@"
+// CHECK: @"??_C@_13BBDEGPLJ@?$AA?$CK?$AA?$AA@"
+// CHECK: @"??_C@_13KJIIAINM@?$AA?$CL?$AA?$AA@"
+// CHECK: @"??_C@_13DEFPDAGF@?$AA?0?$AA?$AA@"
+// CHECK: @"??_C@_13IMODFHAA@?$AA?9?$AA?$AA@"
+// CHECK: @"??_C@_13JOFGPIOO@?$AA?4?$AA?$AA@"
+// CHECK: @"??_C@_13CGOKJPIL@?$AA?1?$AA?$AA@"
+// CHECK: @"??_C@_13COJANIEC@?$AA0?$AA?$AA@"
+// CHECK: @"??_C@_13JGCMLPCH@?$AA1?$AA?$AA@"
+// CHECK: @"??_C@_13IEJJBAMJ@?$AA2?$AA?$AA@"
+// CHECK: @"??_C@_13DMCFHHKM@?$AA3?$AA?$AA@"
+// CHECK: @"??_C@_13KBPCEPBF@?$AA4?$AA?$AA@"
+// CHECK: @"??_C@_13BJEOCIHA@?$AA5?$AA?$AA@"
+// CHECK: @"??_C@_13LPLIHJO@?$AA6?$AA?$AA@"
+// CHECK: @"??_C@_13LDEHOAPL@?$AA7?$AA?$AA@"
+// CHECK: @"??_C@_13OLCEPAKN@?$AA8?$AA?$AA@"
+// CHECK: @"??_C@_13FDJIJHMI@?$AA9?$AA?$AA@"
+// CHECK: @"??_C@_13EBCNDICG@?$AA?3?$AA?$AA@"
+// CHECK: @"??_C@_13PJJBFPED@?$AA?$DL?$AA?$AA@"
+// CHECK: @"??_C@_13GEEGGHPK@?$AA?$DM?$AA?$AA@"
+// CHECK: @"??_C@_13NMPKAAJP@?$AA?$DN?$AA?$AA@"
+// CHECK: @"??_C@_13MOEPKPHB@?$AA?$DO?$AA?$AA@"
+// CHECK: @"??_C@_13HGPDMIBE@?$AA?$DP?$AA?$AA@"
+// CHECK: @"??_C@_13EFKPHINO@?$AA?$EA?$AA?$AA@"
+// CHECK: @"??_C@_13PNBDBPLL@?$AAA?$AA?$AA@"
+// CHECK: @"??_C@_13OPKGLAFF@?$AAB?$AA?$AA@"
+// CHECK: @"??_C@_13FHBKNHDA@?$AAC?$AA?$AA@"
+// CHECK: @"??_C@_13MKMNOPIJ@?$AAD?$AA?$AA@"
+// CHECK: @"??_C@_13HCHBIIOM@?$AAE?$AA?$AA@"
+// CHECK: @"??_C@_13GAMECHAC@?$AAF?$AA?$AA@"
+// CHECK: @"??_C@_13NIHIEAGH@?$AAG?$AA?$AA@"
+// CHECK: @"??_C@_13IABLFADB@?$AAH?$AA?$AA@"
+// CHECK: @"??_C@_13DIKHDHFE@?$AAI?$AA?$AA@"
+// CHECK: @"??_C@_13CKBCJILK@?$AAJ?$AA?$AA@"
+// CHECK: @"??_C@_13JCKOPPNP@?$AAK?$AA?$AA@"
+// CHECK: @"??_C@_13PHJMHGG@?$AAL?$AA?$AA@"
+// CHECK: @"??_C@_13LHMFKAAD@?$AAM?$AA?$AA@"
+// CHECK: @"??_C@_13KFHAAPON@?$AAN?$AA?$AA@"
+// CHECK: @"??_C@_13BNMMGIII@?$AAO?$AA?$AA@"
+// CHECK: @"??_C@_13BFLGCPEB@?$AAP?$AA?$AA@"
+// CHECK: @"??_C@_13KNAKEICE@?$AAQ?$AA?$AA@"
+// CHECK: @"??_C@_13LPLPOHMK@?$AAR?$AA?$AA@"
+// CHECK: @"??_C@_13HADIAKP@?$AAS?$AA?$AA@"
+// CHECK: @"??_C@_13JKNELIBG@?$AAT?$AA?$AA@"
+// CHECK: @"??_C@_13CCGINPHD@?$AAU?$AA?$AA@"
+// CHECK: @"??_C@_13DANNHAJN@?$AAV?$AA?$AA@"
+// CHECK: @"??_C@_13IIGBBHPI@?$AAW?$AA?$AA@"
+// CHECK: @"??_C@_13NAACAHKO@?$AAX?$AA?$AA@"
+// CHECK: @"??_C@_13GILOGAML@?$AAY?$AA?$AA@"
+// CHECK: @"??_C@_13HKALMPCF@?$AAZ?$AA?$AA@"
+// CHECK: @"??_C@_13MCLHKIEA@?$AA?$FL?$AA?$AA@"
+// CHECK: @"??_C@_13FPGAJAPJ@?$AA?2?$AA?$AA@"
+// CHECK: @"??_C@_13OHNMPHJM@?$AA?$FN?$AA?$AA@"
+// CHECK: @"??_C@_13PFGJFIHC@?$AA?$FO?$AA?$AA@"
+// CHECK: @"??_C@_13ENNFDPBH@?$AA_?$AA?$AA@"
+// CHECK: @"??_C@_13OFJNNHOA@?$AA?$GA?$AA?$AA@"
+// CHECK: @"??_C@_13FNCBLAIF@?$AAa?$AA?$AA@"
+// CHECK: @"??_C@_13EPJEBPGL@?$AAb?$AA?$AA@"
+// CHECK: @"??_C@_13PHCIHIAO@?$AAc?$AA?$AA@"
+// CHECK: @"??_C@_13GKPPEALH@?$AAd?$AA?$AA@"
+// CHECK: @"??_C@_13NCEDCHNC@?$AAe?$AA?$AA@"
+// CHECK: @"??_C@_13MAPGIIDM@?$AAf?$AA?$AA@"
+// CHECK: @"??_C@_13HIEKOPFJ@?$AAg?$AA?$AA@"
+// CHECK: @"??_C@_13CACJPPAP@?$AAh?$AA?$AA@"
+// CHECK: @"??_C@_13JIJFJIGK@?$AAi?$AA?$AA@"
+// CHECK: @"??_C@_13IKCADHIE@?$AAj?$AA?$AA@"
+// CHECK: @"??_C@_13DCJMFAOB@?$AAk?$AA?$AA@"
+// CHECK: @"??_C@_13KPELGIFI@?$AAl?$AA?$AA@"
+// CHECK: @"??_C@_13BHPHAPDN@?$AAm?$AA?$AA@"
+// CHECK: @"??_C@_13FECKAND@?$AAn?$AA?$AA@"
+// CHECK: @"??_C@_13LNPOMHLG@?$AAo?$AA?$AA@"
+// CHECK: @"??_C@_13LFIEIAHP@?$AAp?$AA?$AA@"
+// CHECK: @"??_C@_13NDIOHBK@?$AAq?$AA?$AA@"
+// CHECK: @"??_C@_13BPINEIPE@?$AAr?$AA?$AA@"
+// CHECK: @"??_C@_13KHDBCPJB@?$AAs?$AA?$AA@"
+// CHECK: @"??_C@_13DKOGBHCI@?$AAt?$AA?$AA@"
+// CHECK: @"??_C@_13ICFKHAEN@?$AAu?$AA?$AA@"
+// CHECK: @"??_C@_13JAOPNPKD@?$AAv?$AA?$AA@"
+// CHECK: @"??_C@_13CIFDLIMG@?$AAw?$AA?$AA@"
+// CHECK: @"??_C@_13HADAKIJA@?$AAx?$AA?$AA@"
+// CHECK: @"??_C@_13MIIMMPPF@?$AAy?$AA?$AA@"
+// CHECK: @"??_C@_13NKDJGABL@?$AAz?$AA?$AA@"
+// CHECK: @"??_C@_13GCIFAHHO@?$AA?$HL?$AA?$AA@"
+// CHECK: @"??_C@_13PPFCDPMH@?$AA?$HM?$AA?$AA@"
+// CHECK: @"??_C@_13EHOOFIKC@?$AA?$HN?$AA?$AA@"
+// CHECK: @"??_C@_13FFFLPHEM@?$AA?$HO?$AA?$AA@"
const char *LongASCIIString = "012345678901234567890123456789ABCDEF";
-// CHECK: @"\01??_C@_0CF@LABBIIMO@012345678901234567890123456789AB@"
+// CHECK: @"??_C@_0CF@LABBIIMO@012345678901234567890123456789AB@"
const wchar_t *LongWideString = L"012345678901234567890123456789ABCDEF";
-// CHECK: @"\01??_C@_1EK@KFPEBLPK@?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AAA?$AAB@"
+// CHECK: @"??_C@_1EK@KFPEBLPK@?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AAA?$AAB@"
const wchar_t *UnicodeLiteral = L"\ud7ff";
-// CHECK: @"\01??_C@_13IIHIAFKH@?W?$PP?$AA?$AA@"
+// CHECK: @"??_C@_13IIHIAFKH@?W?$PP?$AA?$AA@"
const char *U8Literal = u8"hi";
-// CHECK: @"\01??_C@_02PCEFGMJL@hi?$AA@"
+// CHECK: @"??_C@_02PCEFGMJL@hi?$AA@"
const char16_t *U16Literal = u"hi";
-// CHECK: @"\01??_C@_05OMLEGLOC@h?$AAi?$AA?$AA?$AA@"
+// CHECK: @"??_C@_05OMLEGLOC@h?$AAi?$AA?$AA?$AA@"
const char32_t *U32Literal = U"hi";
-// CHECK: @"\01??_C@_0M@GFNAJIPG@h?$AA?$AA?$AAi?$AA?$AA?$AA?$AA?$AA?$AA?$AA@"
+// CHECK: @"??_C@_0M@GFNAJIPG@h?$AA?$AA?$AAi?$AA?$AA?$AA?$AA?$AA?$AA?$AA@"
diff --git a/test/CodeGenCXX/mangle-ms-template-callback.cpp b/test/CodeGenCXX/mangle-ms-template-callback.cpp
index 1a8f82f..25e719f 100644
--- a/test/CodeGenCXX/mangle-ms-template-callback.cpp
+++ b/test/CodeGenCXX/mangle-ms-template-callback.cpp
@@ -14,42 +14,42 @@
class C<Ret(Arg1, Arg2)> {};
C0 callback_void;
-// CHECK: "\01?callback_void@@3V?$C@$$A6AXXZ@@A"
+// CHECK: "?callback_void@@3V?$C@$$A6AXXZ@@A"
volatile C0 callback_void_volatile;
-// CHECK: "\01?callback_void_volatile@@3V?$C@$$A6AXXZ@@C"
+// CHECK: "?callback_void_volatile@@3V?$C@$$A6AXXZ@@C"
class Type {};
C<int(void)> callback_int;
-// CHECK: "\01?callback_int@@3V?$C@$$A6AHXZ@@A"
+// CHECK: "?callback_int@@3V?$C@$$A6AHXZ@@A"
C<Type(void)> callback_Type;
-// CHECK: "\01?callback_Type@@3V?$C@$$A6A?AVType@@XZ@@A"
+// CHECK: "?callback_Type@@3V?$C@$$A6A?AVType@@XZ@@A"
C<void(int)> callback_void_int;
-// CHECK: "\01?callback_void_int@@3V?$C@$$A6AXH@Z@@A"
+// CHECK: "?callback_void_int@@3V?$C@$$A6AXH@Z@@A"
C<int(int)> callback_int_int;
-// CHECK: "\01?callback_int_int@@3V?$C@$$A6AHH@Z@@A"
+// CHECK: "?callback_int_int@@3V?$C@$$A6AHH@Z@@A"
C<void(Type)> callback_void_Type;
-// CHECK: "\01?callback_void_Type@@3V?$C@$$A6AXVType@@@Z@@A"
+// CHECK: "?callback_void_Type@@3V?$C@$$A6AXVType@@@Z@@A"
void foo(C0 c) {}
-// CHECK: "\01?foo@@YAXV?$C@$$A6AXXZ@@@Z"
+// CHECK: "?foo@@YAXV?$C@$$A6AXXZ@@@Z"
// Here be dragons!
// Let's face the magic of template partial specialization...
void function(C<void(void)>) {}
-// CHECK: "\01?function@@YAXV?$C@$$A6AXXZ@@@Z"
+// CHECK: "?function@@YAXV?$C@$$A6AXXZ@@@Z"
template<typename Ret> class C<Ret(*)(void)> {};
void function_pointer(C<void(*)(void)>) {}
-// CHECK: "\01?function_pointer@@YAXV?$C@P6AXXZ@@@Z"
+// CHECK: "?function_pointer@@YAXV?$C@P6AXXZ@@@Z"
// Block equivalent to the previous definitions.
template<typename Ret> class C<Ret(^)(void)> {};
void block(C<void(^)(void)>) {}
-// CHECK: "\01?block@@YAXV?$C@P_EAXXZ@@@Z"
+// CHECK: "?block@@YAXV?$C@P_EAXXZ@@@Z"
// FYI blocks are not present in MSVS, so we're free to choose the spec.
template<typename T> class C<void (T::*)(void)> {};
@@ -58,16 +58,16 @@
void method() {}
};
void member_pointer(C<void (Z::*)(void)>) {}
-// CHECK: "\01?member_pointer@@YAXV?$C@P8Z@@AEXXZ@@@Z"
+// CHECK: "?member_pointer@@YAXV?$C@P8Z@@AEXXZ@@@Z"
template<typename T> void bar(T) {}
void call_bar() {
bar<int (*)(int)>(0);
-// CHECK: "\01??$bar@P6AHH@Z@@YAXP6AHH@Z@Z"
+// CHECK: "??$bar@P6AHH@Z@@YAXP6AHH@Z@Z"
bar<int (^)(int)>(0);
-// CHECK: "\01??$bar@P_EAHH@Z@@YAXP_EAHH@Z@Z"
+// CHECK: "??$bar@P_EAHH@Z@@YAXP_EAHH@Z@Z"
// FYI blocks are not present in MSVS, so we're free to choose the spec.
}
@@ -83,7 +83,7 @@
WrapFnPtr<Thing::VoidStaticMethod>();
WrapFnRef<Thing::VoidStaticMethod>();
}
-// CHECK: call {{.*}} @"\01??$WrapFnPtr@$1?VoidFn@@YAXXZ@@YAXXZ"
-// CHECK: call {{.*}} @"\01??$WrapFnRef@$1?VoidFn@@YAXXZ@@YAXXZ"
-// CHECK: call {{.*}} @"\01??$WrapFnPtr@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
-// CHECK: call {{.*}} @"\01??$WrapFnRef@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"??$WrapFnPtr@$1?VoidFn@@YAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"??$WrapFnRef@$1?VoidFn@@YAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"??$WrapFnPtr@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"??$WrapFnRef@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
diff --git a/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp b/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp
index d26558b..e4a608a 100644
--- a/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp
+++ b/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp
@@ -8,31 +8,31 @@
struct __single_inheritance M;
J<M> m;
-// CHECK-DAG: @"\01?m@@3U?$J@UM@@$0A@@@A"
+// CHECK-DAG: @"?m@@3U?$J@UM@@$0A@@@A"
K<M> m2;
-// CHECK-DAG: @"\01?m2@@3U?$K@UM@@$0?0@@A"
+// CHECK-DAG: @"?m2@@3U?$K@UM@@$0?0@@A"
struct __multiple_inheritance N;
J<N> n;
-// CHECK-DAG: @"\01?n@@3U?$J@UN@@$HA@@@A"
+// CHECK-DAG: @"?n@@3U?$J@UN@@$HA@@@A"
K<N> n2;
-// CHECK-DAG: @"\01?n2@@3U?$K@UN@@$0?0@@A"
+// CHECK-DAG: @"?n2@@3U?$K@UN@@$0?0@@A"
struct __virtual_inheritance O;
J<O> o;
-// CHECK-DAG: @"\01?o@@3U?$J@UO@@$IA@A@@@A"
+// CHECK-DAG: @"?o@@3U?$J@UO@@$IA@A@@@A"
K<O> o2;
-// CHECK-DAG: @"\01?o2@@3U?$K@UO@@$FA@?0@@A"
+// CHECK-DAG: @"?o2@@3U?$K@UO@@$FA@?0@@A"
struct P;
J<P> p;
-// CHECK-DAG: @"\01?p@@3U?$J@UP@@$JA@A@?0@@A"
+// CHECK-DAG: @"?p@@3U?$J@UP@@$JA@A@?0@@A"
K<P> p2;
-// CHECK-DAG: @"\01?p2@@3U?$K@UP@@$GA@A@?0@@A"
+// CHECK-DAG: @"?p2@@3U?$K@UP@@$GA@A@?0@@A"
#pragma pointers_to_members(full_generality, virtual_inheritance)
@@ -57,4 +57,4 @@
// Test that we mangle in the vbptr offset, which is 12 here.
//
-// CHECK: define weak_odr dso_local x86_thiscallcc %struct.ClassTemplate* @"\01??0?$ClassTemplate@$J??_9MostGeneral@@$BA@AEA@M@3@@QAE@XZ"
+// CHECK: define weak_odr dso_local x86_thiscallcc %struct.ClassTemplate* @"??0?$ClassTemplate@$J??_9MostGeneral@@$BA@AEA@M@3@@QAE@XZ"
diff --git a/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp b/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp
index e710abe..3078c5a 100644
--- a/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp
+++ b/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp
@@ -56,31 +56,31 @@
}
// CHECK-LABEL: define {{.*}}ReadFields
-// CHECK: call {{.*}} @"\01??$ReadField@US@@$03@@YAHAAUS@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UM@@$0M@@@YAHAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UV@@$F7A@@@YAHAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UU@@$G3A@A@@@YAHAAUU@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@US@@$07@@YAHAAUS@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UM@@$0BA@@@YAHAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UV@@$FM@A@@@YAHAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UU@@$G7A@A@@@YAHAAUU@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@US@@$03@@YAHAAUS@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UM@@$0M@@@YAHAAUM@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UV@@$F7A@@@YAHAAUV@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UU@@$G3A@A@@@YAHAAUU@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@US@@$07@@YAHAAUS@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UM@@$0BA@@@YAHAAUM@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UV@@$FM@A@@@YAHAAUV@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UU@@$G7A@A@@@YAHAAUU@@@Z"
// MSVC mangles null member pointers in function templates wrong, but it gets
// them right in class templates.
-// CHECK: call {{.*}} @"\01??$ReadField@US@@$0A@@@YAHAAUS@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UM@@$0A@@@YAHAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UV@@$0A@@@YAHAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UU@@$0A@@@YAHAAUU@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@US@@$0A@@@YAHAAUS@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UM@@$0A@@@YAHAAUM@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UV@@$0A@@@YAHAAUV@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UU@@$0A@@@YAHAAUU@@@Z"
// Non-polymorphic null data memptr vs first field memptr. MSVC mangles these
// the same.
-// CHECK: call {{.*}} @"\01??$ReadField@UA@@$0A@@@YAHAAUA@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UA@@$0?0@@YAHAAUA@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UA@@$0A@@@YAHAAUA@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UA@@$0?0@@YAHAAUA@@@Z"
// Indirect fields are handled as-if they were simply members of their enclosing
// record.
-// CHECK: call {{.*}} @"\01??$ReadField@UI@@$0A@@@YAHAAUI@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UI@@$03@@YAHAAUI@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UI@@$0A@@@YAHAAUI@@@Z"
+// CHECK: call {{.*}} @"??$ReadField@UI@@$03@@YAHAAUI@@@Z"
// Test member function pointers.
template <typename T, void (T::*MFP)()>
@@ -119,10 +119,10 @@
}
// CHECK-LABEL: define {{.*}}CallMethods
-// CHECK: call {{.*}} @"\01??$CallMethod@US@@$1?f@1@QAEXXZ@@YAXAAUS@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$H?f@1@QAEXXZA@@@YAXAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$I?f@1@QAEXXZA@A@@@YAXAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$J?f@1@QAEXXZA@A@A@@@YAXAAUU@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@US@@$1?f@1@QAEXXZ@@YAXAAUS@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UM@@$H?f@1@QAEXXZA@@@YAXAAUM@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UV@@$I?f@1@QAEXXZA@A@@@YAXAAUV@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UU@@$J?f@1@QAEXXZA@A@A@@@YAXAAUU@@@Z"
// PR17034: MSVC reuses the same thunk for every virtual g method because they
// are all at vftable offset zero. They then mangle the name of the first thunk
@@ -130,17 +130,17 @@
// bug. We don't follow them here. Instead of ?_91@ backref below, they would
// get ?_9S@@ in every instantiation after the first.
-// CHECK: call {{.*}} @"\01??$CallMethod@US@@$1??_91@$BA@AE@@YAXAAUS@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$H??_91@$BA@AEA@@@YAXAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$I??_91@$BA@AEA@A@@@YAXAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$J??_91@$BA@AEA@A@A@@@YAXAAUU@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@US@@$1??_91@$BA@AE@@YAXAAUS@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UM@@$H??_91@$BA@AEA@@@YAXAAUM@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UV@@$I??_91@$BA@AEA@A@@@YAXAAUV@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UU@@$J??_91@$BA@AEA@A@A@@@YAXAAUU@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UO@@$H??_91@$BA@AE3@@YAXAAUO@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UO@@$H??_91@$BA@AE3@@YAXAAUO@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@US@@$0A@@@YAXAAUS@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$0A@@@YAXAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$0A@@@YAXAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$0A@@@YAXAAUU@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@US@@$0A@@@YAXAAUS@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UM@@$0A@@@YAXAAUM@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UV@@$0A@@@YAXAAUV@@@Z"
+// CHECK: call {{.*}} @"??$CallMethod@UU@@$0A@@@YAXAAUU@@@Z"
namespace NegativeNVOffset {
struct A {};
@@ -152,4 +152,4 @@
template void CallMethod<NegativeNVOffset::C, &NegativeNVOffset::C::f>(NegativeNVOffset::C &);
-// CHECK-LABEL: define {{.*}} @"\01??$CallMethod@UC@NegativeNVOffset@@$I??_912@$BA@AEPPPPPPPM@A@@@YAXAAUC@NegativeNVOffset@@@Z"
+// CHECK-LABEL: define {{.*}} @"??$CallMethod@UC@NegativeNVOffset@@$I??_912@$BA@AEPPPPPPPM@A@@@YAXAAUC@NegativeNVOffset@@@Z"
diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp
index 46ab251..8c6062b 100644
--- a/test/CodeGenCXX/mangle-ms-templates.cpp
+++ b/test/CodeGenCXX/mangle-ms-templates.cpp
@@ -51,118 +51,118 @@
void template_mangling() {
Class<Typename> c1;
-// CHECK: call {{.*}} @"\01??0?$Class@VTypename@@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@VTypename@@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@VTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@VTypename@@@@QEAA@XZ"
Class<const Typename> c1_const;
-// CHECK: call {{.*}} @"\01??0?$Class@$$CBVTypename@@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$CBVTypename@@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$CBVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$CBVTypename@@@@QEAA@XZ"
Class<volatile Typename> c1_volatile;
-// CHECK: call {{.*}} @"\01??0?$Class@$$CCVTypename@@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$CCVTypename@@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$CCVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$CCVTypename@@@@QEAA@XZ"
Class<const volatile Typename> c1_cv;
-// CHECK: call {{.*}} @"\01??0?$Class@$$CDVTypename@@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$CDVTypename@@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$CDVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$CDVTypename@@@@QEAA@XZ"
Class<Nested<Typename> > c2;
-// CHECK: call {{.*}} @"\01??0?$Class@V?$Nested@VTypename@@@@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@V?$Nested@VTypename@@@@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@V?$Nested@VTypename@@@@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@V?$Nested@VTypename@@@@@@QEAA@XZ"
Class<int * const> c_intpc;
-// CHECK: call {{.*}} @"\01??0?$Class@QAH@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@QEAH@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@QAH@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@QEAH@@QEAA@XZ"
Class<int()> c_ft;
-// CHECK: call {{.*}} @"\01??0?$Class@$$A6AHXZ@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$A6AHXZ@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$A6AHXZ@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$A6AHXZ@@QEAA@XZ"
Class<int[]> c_inti;
-// CHECK: call {{.*}} @"\01??0?$Class@$$BY0A@H@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$BY0A@H@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$BY0A@H@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$BY0A@H@@QEAA@XZ"
Class<int[5]> c_int5;
-// CHECK: call {{.*}} @"\01??0?$Class@$$BY04H@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$BY04H@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$BY04H@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$BY04H@@QEAA@XZ"
Class<const int[5]> c_intc5;
-// CHECK: call {{.*}} @"\01??0?$Class@$$BY04$$CBH@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$BY04$$CBH@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$BY04$$CBH@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$BY04$$CBH@@QEAA@XZ"
Class<int * const[5]> c_intpc5;
-// CHECK: call {{.*}} @"\01??0?$Class@$$BY04QAH@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$Class@$$BY04QEAH@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$Class@$$BY04QAH@@QAE@XZ"
+// X64: call {{.*}} @"??0?$Class@$$BY04QEAH@@QEAA@XZ"
BoolTemplate<false> _false;
-// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$BoolTemplate@$0A@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$BoolTemplate@$0A@@@QEAA@XZ"
BoolTemplate<true> _true;
// PR13158
_true.Foo(1);
-// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$00@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$BoolTemplate@$00@@QEAA@XZ"
-// CHECK: call {{.*}} @"\01??$Foo@H@?$BoolTemplate@$00@@QAEXH@Z"
-// X64: call {{.*}} @"\01??$Foo@H@?$BoolTemplate@$00@@QEAAXH@Z"
+// CHECK: call {{.*}} @"??0?$BoolTemplate@$00@@QAE@XZ"
+// X64: call {{.*}} @"??0?$BoolTemplate@$00@@QEAA@XZ"
+// CHECK: call {{.*}} @"??$Foo@H@?$BoolTemplate@$00@@QAEXH@Z"
+// X64: call {{.*}} @"??$Foo@H@?$BoolTemplate@$00@@QEAAXH@Z"
IntTemplate<0> zero;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0A@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0A@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0A@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0A@@@QEAA@XZ"
IntTemplate<5> five;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$04@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$04@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$04@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$04@@QEAA@XZ"
IntTemplate<11> eleven;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0L@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0L@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0L@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0L@@@QEAA@XZ"
IntTemplate<256> _256;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0BAA@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0BAA@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0BAA@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0BAA@@@QEAA@XZ"
IntTemplate<513> _513;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0CAB@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0CAB@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0CAB@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0CAB@@@QEAA@XZ"
IntTemplate<1026> _1026;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0EAC@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0EAC@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0EAC@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0EAC@@@QEAA@XZ"
IntTemplate<65535> ffff;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0PPPP@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0PPPP@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0PPPP@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0PPPP@@@QEAA@XZ"
IntTemplate<-1> neg_1;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?0@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0?0@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0?0@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0?0@@QEAA@XZ"
IntTemplate<-9> neg_9;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?8@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0?8@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0?8@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0?8@@QEAA@XZ"
IntTemplate<-10> neg_10;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?9@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0?9@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0?9@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0?9@@QEAA@XZ"
IntTemplate<-11> neg_11;
-// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?L@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$IntTemplate@$0?L@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$IntTemplate@$0?L@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$IntTemplate@$0?L@@@QEAA@XZ"
UnsignedIntTemplate<4294967295> ffffffff;
-// CHECK: call {{.*}} @"\01??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QEAA@XZ"
LongLongTemplate<-9223372036854775807LL-1LL> int64_min;
-// CHECK: call {{.*}} @"\01??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QEAA@XZ"
LongLongTemplate<9223372036854775807LL> int64_max;
-// CHECK: call {{.*}} @"\01??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QAE@XZ"
+// X64: call {{.*}} @"??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QEAA@XZ"
UnsignedLongLongTemplate<18446744073709551615ULL> uint64_max;
-// CHECK: call {{.*}} @"\01??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ"
+// X64: call {{.*}} @"??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ"
UnsignedLongLongTemplate<(unsigned long long)-1> uint64_neg_1;
-// CHECK: call {{.*}} @"\01??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ"
-// X64: call {{.*}} @"\01??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ"
+// CHECK: call {{.*}} @"??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ"
+// X64: call {{.*}} @"??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ"
}
namespace space {
template<class T> const T& foo(const T& l) { return l; }
}
-// CHECK: "\01??$foo@H@space@@YAABHABH@Z"
-// X64: "\01??$foo@H@space@@YAAEBHAEBH@Z"
+// CHECK: "??$foo@H@space@@YAABHABH@Z"
+// X64: "??$foo@H@space@@YAAEBHAEBH@Z"
void use() {
space::foo(42);
@@ -178,8 +178,8 @@
void spam() {
FunctionPointerTemplate<spam>();
-// CHECK: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
-// X64: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
+// CHECK: "??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
+// X64: "??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
}
// Unlike Itanium, there is no character code to indicate an argument pack.
@@ -190,8 +190,8 @@
variadic_fn_template(0, 1, 3, 4);
variadic_fn_template(0, 1, 'a', "b");
}
-// CHECK: "\01??$variadic_fn_template@HHHH@@YAXABH000@Z"
-// CHECK: "\01??$variadic_fn_template@HHD$$BY01D@@YAXABH0ABDAAY01$$CBD@Z"
+// CHECK: "??$variadic_fn_template@HHHH@@YAXABH000@Z"
+// CHECK: "??$variadic_fn_template@HHD$$BY01D@@YAXABH0ABDAAY01$$CBD@Z"
template <typename ...Ts>
struct VariadicClass {
@@ -202,8 +202,8 @@
VariadicClass<int, char, bool> a;
VariadicClass<bool, char, int> b;
}
-// CHECK: call {{.*}} @"\01??0?$VariadicClass@HD_N@@QAE@XZ"
-// CHECK: call {{.*}} @"\01??0?$VariadicClass@_NDH@@QAE@XZ"
+// CHECK: call {{.*}} @"??0?$VariadicClass@HD_N@@QAE@XZ"
+// CHECK: call {{.*}} @"??0?$VariadicClass@_NDH@@QAE@XZ"
template <typename T>
struct Second {};
@@ -224,7 +224,7 @@
struct Thing<T, true> { };
void template_template_fun(Type<Thing<Second, true>, Second>) { }
-// CHECK: "\01?template_template_fun@@YAXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z"
+// CHECK: "?template_template_fun@@YAXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z"
template <typename T>
void template_template_specialization();
@@ -232,12 +232,12 @@
template <>
void template_template_specialization<void (Type<Thing<Second, true>, Second>)>() {
}
-// CHECK: "\01??$template_template_specialization@$$A6AXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z@@YAXXZ"
+// CHECK: "??$template_template_specialization@$$A6AXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z@@YAXXZ"
// PR16788
template <decltype(nullptr)> struct S1 {};
void f(S1<nullptr>) {}
-// CHECK: "\01?f@@YAXU?$S1@$0A@@@@Z"
+// CHECK: "?f@@YAXU?$S1@$0A@@@@Z"
struct record {
int first;
@@ -248,7 +248,7 @@
};
extern const record inst;
void recref(type1<inst>) {}
-// CHECK: "\01?recref@@YAXU?$type1@$E?inst@@3Urecord@@B@@@Z"
+// CHECK: "?recref@@YAXU?$type1@$E?inst@@3Urecord@@B@@@Z"
struct _GUID {};
struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid;
@@ -260,18 +260,18 @@
struct UUIDType2 {};
void fun(UUIDType1<uuid> a) {}
-// CHECK: "\01?fun@@YAXU?$UUIDType1@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
+// CHECK: "?fun@@YAXU?$UUIDType1@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
void fun(UUIDType2<uuid> b) {}
-// CHECK: "\01?fun@@YAXU?$UUIDType2@Uuuid@@$E?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
+// CHECK: "?fun@@YAXU?$UUIDType2@Uuuid@@$E?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
template <typename T> struct TypeWithFriendDefinition {
friend void FunctionDefinedWithInjectedName(TypeWithFriendDefinition<T>) {}
};
-// CHECK: call {{.*}} @"\01?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
+// CHECK: call {{.*}} @"?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
void CallFunctionDefinedWithInjectedName() {
FunctionDefinedWithInjectedName(TypeWithFriendDefinition<int>());
}
-// CHECK: @"\01?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
+// CHECK: @"?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
// We need to be able to feed GUIDs through a couple rounds of template
// substitution.
@@ -284,5 +284,5 @@
void bar() { UUIDType4::foo(); }
};
template struct UUIDType4<&__uuidof(uuid)>;
-// CHECK: "\01?bar@?$UUIDType4@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ"
-// CHECK: "\01?foo@?$UUIDType3@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ"
+// CHECK: "?bar@?$UUIDType4@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ"
+// CHECK: "?foo@?$UUIDType3@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ"
diff --git a/test/CodeGenCXX/mangle-ms-vector-types.cpp b/test/CodeGenCXX/mangle-ms-vector-types.cpp
index 6974ee1..5b67628 100644
--- a/test/CodeGenCXX/mangle-ms-vector-types.cpp
+++ b/test/CodeGenCXX/mangle-ms-vector-types.cpp
@@ -5,33 +5,33 @@
#include <immintrin.h>
void foo64(__m64) {}
-// CHECK: define dso_local void @"\01?foo64@@YAXT__m64@@@Z"
+// CHECK: define dso_local void @"?foo64@@YAXT__m64@@@Z"
void foo128(__m128) {}
-// CHECK: define dso_local void @"\01?foo128@@YAXT__m128@@@Z"
+// CHECK: define dso_local void @"?foo128@@YAXT__m128@@@Z"
void foo128d(__m128d) {}
-// CHECK: define dso_local void @"\01?foo128d@@YAXU__m128d@@@Z"
+// CHECK: define dso_local void @"?foo128d@@YAXU__m128d@@@Z"
void foo128i(__m128i) {}
-// CHECK: define dso_local void @"\01?foo128i@@YAXT__m128i@@@Z"
+// CHECK: define dso_local void @"?foo128i@@YAXT__m128i@@@Z"
void foo256(__m256) {}
-// CHECK: define dso_local void @"\01?foo256@@YAXT__m256@@@Z"
+// CHECK: define dso_local void @"?foo256@@YAXT__m256@@@Z"
void foo256d(__m256d) {}
-// CHECK: define dso_local void @"\01?foo256d@@YAXU__m256d@@@Z"
+// CHECK: define dso_local void @"?foo256d@@YAXU__m256d@@@Z"
void foo256i(__m256i) {}
-// CHECK: define dso_local void @"\01?foo256i@@YAXT__m256i@@@Z"
+// CHECK: define dso_local void @"?foo256i@@YAXT__m256i@@@Z"
// We have a custom mangling for vector types not standardized by Intel.
void foov8hi(__v8hi) {}
-// CHECK: define dso_local void @"\01?foov8hi@@YAXT?$__vector@F$07@__clang@@@Z"
+// CHECK: define dso_local void @"?foov8hi@@YAXT?$__vector@F$07@__clang@@@Z"
typedef __attribute__((ext_vector_type(4))) int vi4b;
void foovi4b(vi4b) {}
-// CHECK: define dso_local void @"\01?foovi4b@@YAXT?$__vector@H$03@__clang@@@Z"
+// CHECK: define dso_local void @"?foovi4b@@YAXT?$__vector@H$03@__clang@@@Z"
// Clang does not support vectors of complex types, so we can't test the
// mangling of them.
diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp
index 77fde7a..46c011e 100644
--- a/test/CodeGenCXX/mangle-ms.cpp
+++ b/test/CodeGenCXX/mangle-ms.cpp
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=x86_64-pc-win32 -std=c++98| FileCheck -check-prefix X64 %s
int a;
-// CHECK-DAG: @"\01?a@@3HA"
+// CHECK-DAG: @"?a@@3HA"
extern "C++" {
static int __attribute__((used)) ignore_transparent_context;
@@ -11,11 +11,11 @@
namespace N {
int b;
-// CHECK-DAG: @"\01?b@N@@3HA"
+// CHECK-DAG: @"?b@N@@3HA"
namespace {
int anonymous;
-// CHECK-DAG: @"\01?anonymous@?A@N@@3HA"
+// CHECK-DAG: @"?anonymous@?A@N@@3HA"
}
}
@@ -23,38 +23,38 @@
// CHECK-DAG: @c
int _c(void) {return N::anonymous + c;}
-// CHECK-DAG: @"\01?_c@@YAHXZ"
-// X64-DAG: @"\01?_c@@YAHXZ"
+// CHECK-DAG: @"?_c@@YAHXZ"
+// X64-DAG: @"?_c@@YAHXZ"
const int &NeedsReferenceTemporary = 2;
-// CHECK-DAG: @"\01?NeedsReferenceTemporary@@3ABHB" = dso_local constant i32* @"\01?$RT1@NeedsReferenceTemporary@@3ABHB"
-// X64-DAG: @"\01?NeedsReferenceTemporary@@3AEBHEB" = dso_local constant i32* @"\01?$RT1@NeedsReferenceTemporary@@3AEBHEB"
+// CHECK-DAG: @"?NeedsReferenceTemporary@@3ABHB" = dso_local constant i32* @"?$RT1@NeedsReferenceTemporary@@3ABHB"
+// X64-DAG: @"?NeedsReferenceTemporary@@3AEBHEB" = dso_local constant i32* @"?$RT1@NeedsReferenceTemporary@@3AEBHEB"
class foo {
static const short d;
-// CHECK-DAG: @"\01?d@foo@@0FB"
+// CHECK-DAG: @"?d@foo@@0FB"
protected:
static volatile long e;
-// CHECK-DAG: @"\01?e@foo@@1JC"
+// CHECK-DAG: @"?e@foo@@1JC"
public:
static const volatile char f;
-// CHECK-DAG: @"\01?f@foo@@2DD"
+// CHECK-DAG: @"?f@foo@@2DD"
int operator+(int a);
foo(){}
-// CHECK-DAG: @"\01??0foo@@QAE@XZ"
-// X64-DAG: @"\01??0foo@@QEAA@XZ"
+// CHECK-DAG: @"??0foo@@QAE@XZ"
+// X64-DAG: @"??0foo@@QEAA@XZ"
~foo(){}
-// CHECK-DAG: @"\01??1foo@@QAE@XZ"
-// X64-DAG: @"\01??1foo@@QEAA@XZ
+// CHECK-DAG: @"??1foo@@QAE@XZ"
+// X64-DAG: @"??1foo@@QEAA@XZ
foo(int i){}
-// CHECK-DAG: @"\01??0foo@@QAE@H@Z"
-// X64-DAG: @"\01??0foo@@QEAA@H@Z"
+// CHECK-DAG: @"??0foo@@QAE@H@Z"
+// X64-DAG: @"??0foo@@QEAA@H@Z"
foo(char *q){}
-// CHECK-DAG: @"\01??0foo@@QAE@PAD@Z"
-// X64-DAG: @"\01??0foo@@QEAA@PEAD@Z"
+// CHECK-DAG: @"??0foo@@QAE@PAD@Z"
+// X64-DAG: @"??0foo@@QEAA@PEAD@Z"
static foo* static_method() { return 0; }
@@ -79,16 +79,16 @@
};
foo bar() { return foo(); }
-// CHECK-DAG: @"\01?bar@@YA?AVfoo@@XZ"
-// X64-DAG: @"\01?bar@@YA?AVfoo@@XZ"
+// CHECK-DAG: @"?bar@@YA?AVfoo@@XZ"
+// X64-DAG: @"?bar@@YA?AVfoo@@XZ"
int foo::operator+(int a) {
-// CHECK-DAG: @"\01??Hfoo@@QAEHH@Z"
-// X64-DAG: @"\01??Hfoo@@QEAAHH@Z"
+// CHECK-DAG: @"??Hfoo@@QAEHH@Z"
+// X64-DAG: @"??Hfoo@@QEAAHH@Z"
foo::static_method();
-// CHECK-DAG: @"\01?static_method@foo@@SAPAV1@XZ"
-// X64-DAG: @"\01?static_method@foo@@SAPEAV1@XZ"
+// CHECK-DAG: @"?static_method@foo@@SAPAV1@XZ"
+// X64-DAG: @"?static_method@foo@@SAPEAV1@XZ"
bar();
return a;
}
@@ -98,33 +98,33 @@
const volatile char foo::f = 'C';
int bar::g;
-// CHECK-DAG: @"\01?g@bar@@2HA"
+// CHECK-DAG: @"?g@bar@@2HA"
extern int * const h1 = &a;
-// CHECK-DAG: @"\01?h1@@3QAHA"
+// CHECK-DAG: @"?h1@@3QAHA"
extern const int * const h2 = &a;
-// CHECK-DAG: @"\01?h2@@3QBHB"
+// CHECK-DAG: @"?h2@@3QBHB"
extern int * const __restrict h3 = &a;
-// CHECK-DAG: @"\01?h3@@3QIAHIA"
-// X64-DAG: @"\01?h3@@3QEIAHEIA"
+// CHECK-DAG: @"?h3@@3QIAHIA"
+// X64-DAG: @"?h3@@3QEIAHEIA"
int i[10][20];
-// CHECK-DAG: @"\01?i@@3PAY0BE@HA"
+// CHECK-DAG: @"?i@@3PAY0BE@HA"
typedef int (*FunT)(int, int);
FunT FunArr[10][20];
-// CHECK-DAG: @"\01?FunArr@@3PAY0BE@P6AHHH@ZA"
-// X64-DAG: @"\01?FunArr@@3PAY0BE@P6AHHH@ZA"
+// CHECK-DAG: @"?FunArr@@3PAY0BE@P6AHHH@ZA"
+// X64-DAG: @"?FunArr@@3PAY0BE@P6AHHH@ZA"
int (__stdcall *j)(signed char, unsigned char);
-// CHECK-DAG: @"\01?j@@3P6GHCE@ZA"
+// CHECK-DAG: @"?j@@3P6GHCE@ZA"
const volatile char foo2::*k;
-// CHECK-DAG: @"\01?k@@3PTfoo@@DT1@"
-// X64-DAG: @"\01?k@@3PETfoo@@DET1@"
+// CHECK-DAG: @"?k@@3PTfoo@@DT1@"
+// X64-DAG: @"?k@@3PETfoo@@DET1@"
int (foo2::*l)(int);
-// CHECK-DAG: @"\01?l@@3P8foo@@AEHH@ZQ1@"
+// CHECK-DAG: @"?l@@3P8foo@@AEHH@ZQ1@"
// Ensure typedef CV qualifiers are mangled correctly
typedef const int cInt;
@@ -135,141 +135,141 @@
vInt g_vInt = 2;
cvInt g_cvInt = 3;
-// CHECK-DAG: @"\01?g_cInt@@3HB"
-// CHECK-DAG: @"\01?g_vInt@@3HC"
-// CHECK-DAG: @"\01?g_cvInt@@3HD"
+// CHECK-DAG: @"?g_cInt@@3HB"
+// CHECK-DAG: @"?g_vInt@@3HC"
+// CHECK-DAG: @"?g_cvInt@@3HD"
// Static functions are mangled, too.
// Also make sure calling conventions, arglists, and throw specs work.
static void __stdcall alpha(float a, double b) throw() {}
bool __fastcall beta(long long a, wchar_t b) throw(signed char, unsigned char) {
-// CHECK-DAG: @"\01?beta@@YI_N_J_W@Z"
-// X64-DAG: @"\01?beta@@YA_N_J_W@Z"
+// CHECK-DAG: @"?beta@@YI_N_J_W@Z"
+// X64-DAG: @"?beta@@YA_N_J_W@Z"
alpha(0.f, 0.0);
return false;
}
-// CHECK-DAG: @"\01?alpha@@YGXMN@Z"
-// X64-DAG: @"\01?alpha@@YAXMN@Z"
+// CHECK-DAG: @"?alpha@@YGXMN@Z"
+// X64-DAG: @"?alpha@@YAXMN@Z"
// Make sure tag-type mangling works.
void gamma(class foo, struct bar, union baz, enum quux) {}
-// CHECK-DAG: @"\01?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
-// X64-DAG: @"\01?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
+// CHECK-DAG: @"?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
+// X64-DAG: @"?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
// Make sure pointer/reference-type mangling works.
void delta(int * const a, const long &) {}
-// CHECK-DAG: @"\01?delta@@YAXQAHABJ@Z"
-// X64-DAG: @"\01?delta@@YAXQEAHAEBJ@Z"
+// CHECK-DAG: @"?delta@@YAXQAHABJ@Z"
+// X64-DAG: @"?delta@@YAXQEAHAEBJ@Z"
// Array mangling.
void epsilon(int a[][10][20]) {}
-// CHECK-DAG: @"\01?epsilon@@YAXQAY19BE@H@Z"
-// X64-DAG: @"\01?epsilon@@YAXQEAY19BE@H@Z"
+// CHECK-DAG: @"?epsilon@@YAXQAY19BE@H@Z"
+// X64-DAG: @"?epsilon@@YAXQEAY19BE@H@Z"
void zeta(int (*)(int, int)) {}
-// CHECK-DAG: @"\01?zeta@@YAXP6AHHH@Z@Z"
-// X64-DAG: @"\01?zeta@@YAXP6AHHH@Z@Z"
+// CHECK-DAG: @"?zeta@@YAXP6AHHH@Z@Z"
+// X64-DAG: @"?zeta@@YAXP6AHHH@Z@Z"
// Blocks mangling (Clang extension). A block should be mangled slightly
// differently from a similar function pointer.
void eta(int (^)(int, int)) {}
-// CHECK-DAG: @"\01?eta@@YAXP_EAHHH@Z@Z"
+// CHECK-DAG: @"?eta@@YAXP_EAHHH@Z@Z"
typedef int theta_arg(int,int);
void theta(theta_arg^ block) {}
-// CHECK-DAG: @"\01?theta@@YAXP_EAHHH@Z@Z"
+// CHECK-DAG: @"?theta@@YAXP_EAHHH@Z@Z"
void operator_new_delete() {
char *ptr = new char;
-// CHECK-DAG: @"\01??2@YAPAXI@Z"
+// CHECK-DAG: @"??2@YAPAXI@Z"
delete ptr;
-// CHECK-DAG: @"\01??3@YAXPAX@Z"
+// CHECK-DAG: @"??3@YAXPAX@Z"
char *array = new char[42];
-// CHECK-DAG: @"\01??_U@YAPAXI@Z"
+// CHECK-DAG: @"??_U@YAPAXI@Z"
delete [] array;
-// CHECK-DAG: @"\01??_V@YAXPAX@Z"
+// CHECK-DAG: @"??_V@YAXPAX@Z"
}
// PR13022
void (redundant_parens)();
void redundant_parens_use() { redundant_parens(); }
-// CHECK-DAG: @"\01?redundant_parens@@YAXXZ"
-// X64-DAG: @"\01?redundant_parens@@YAXXZ"
+// CHECK-DAG: @"?redundant_parens@@YAXXZ"
+// X64-DAG: @"?redundant_parens@@YAXXZ"
// PR13047
typedef double RGB[3];
RGB color1;
-// CHECK-DAG: @"\01?color1@@3PANA"
+// CHECK-DAG: @"?color1@@3PANA"
extern const RGB color2 = {};
-// CHECK-DAG: @"\01?color2@@3QBNB"
+// CHECK-DAG: @"?color2@@3QBNB"
extern RGB const color3[5] = {};
-// CHECK-DAG: @"\01?color3@@3QAY02$$CBNA"
+// CHECK-DAG: @"?color3@@3QAY02$$CBNA"
extern RGB const ((color4)[5]) = {};
-// CHECK-DAG: @"\01?color4@@3QAY02$$CBNA"
+// CHECK-DAG: @"?color4@@3QAY02$$CBNA"
struct B;
volatile int B::* volatile memptr1;
-// X64-DAG: @"\01?memptr1@@3RESB@@HES1@"
+// X64-DAG: @"?memptr1@@3RESB@@HES1@"
volatile int B::* memptr2;
-// X64-DAG: @"\01?memptr2@@3PESB@@HES1@"
+// X64-DAG: @"?memptr2@@3PESB@@HES1@"
int B::* volatile memptr3;
-// X64-DAG: @"\01?memptr3@@3REQB@@HEQ1@"
+// X64-DAG: @"?memptr3@@3REQB@@HEQ1@"
typedef int (*fun)();
volatile fun B::* volatile funmemptr1;
-// X64-DAG: @"\01?funmemptr1@@3RESB@@R6AHXZES1@"
+// X64-DAG: @"?funmemptr1@@3RESB@@R6AHXZES1@"
volatile fun B::* funmemptr2;
-// X64-DAG: @"\01?funmemptr2@@3PESB@@R6AHXZES1@"
+// X64-DAG: @"?funmemptr2@@3PESB@@R6AHXZES1@"
fun B::* volatile funmemptr3;
-// X64-DAG: @"\01?funmemptr3@@3REQB@@P6AHXZEQ1@"
+// X64-DAG: @"?funmemptr3@@3REQB@@P6AHXZEQ1@"
void (B::* volatile memptrtofun1)();
-// X64-DAG: @"\01?memptrtofun1@@3R8B@@EAAXXZEQ1@"
+// X64-DAG: @"?memptrtofun1@@3R8B@@EAAXXZEQ1@"
const void (B::* memptrtofun2)();
-// X64-DAG: @"\01?memptrtofun2@@3P8B@@EAAXXZEQ1@"
+// X64-DAG: @"?memptrtofun2@@3P8B@@EAAXXZEQ1@"
volatile void (B::* memptrtofun3)();
-// X64-DAG: @"\01?memptrtofun3@@3P8B@@EAAXXZEQ1@"
+// X64-DAG: @"?memptrtofun3@@3P8B@@EAAXXZEQ1@"
int (B::* volatile memptrtofun4)();
-// X64-DAG: @"\01?memptrtofun4@@3R8B@@EAAHXZEQ1@"
+// X64-DAG: @"?memptrtofun4@@3R8B@@EAAHXZEQ1@"
volatile int (B::* memptrtofun5)();
-// X64-DAG: @"\01?memptrtofun5@@3P8B@@EAA?CHXZEQ1@"
+// X64-DAG: @"?memptrtofun5@@3P8B@@EAA?CHXZEQ1@"
const int (B::* memptrtofun6)();
-// X64-DAG: @"\01?memptrtofun6@@3P8B@@EAA?BHXZEQ1@"
+// X64-DAG: @"?memptrtofun6@@3P8B@@EAA?BHXZEQ1@"
fun (B::* volatile memptrtofun7)();
-// X64-DAG: @"\01?memptrtofun7@@3R8B@@EAAP6AHXZXZEQ1@"
+// X64-DAG: @"?memptrtofun7@@3R8B@@EAAP6AHXZXZEQ1@"
volatile fun (B::* memptrtofun8)();
-// X64-DAG: @"\01?memptrtofun8@@3P8B@@EAAR6AHXZXZEQ1@"
+// X64-DAG: @"?memptrtofun8@@3P8B@@EAAR6AHXZXZEQ1@"
const fun (B::* memptrtofun9)();
-// X64-DAG: @"\01?memptrtofun9@@3P8B@@EAAQ6AHXZXZEQ1@"
+// X64-DAG: @"?memptrtofun9@@3P8B@@EAAQ6AHXZXZEQ1@"
// PR12603
enum E {};
-// CHECK-DAG: "\01?fooE@@YA?AW4E@@XZ"
-// X64-DAG: "\01?fooE@@YA?AW4E@@XZ"
+// CHECK-DAG: "?fooE@@YA?AW4E@@XZ"
+// X64-DAG: "?fooE@@YA?AW4E@@XZ"
E fooE() { return E(); }
class X {};
-// CHECK-DAG: "\01?fooX@@YA?AVX@@XZ"
-// X64-DAG: "\01?fooX@@YA?AVX@@XZ"
+// CHECK-DAG: "?fooX@@YA?AVX@@XZ"
+// X64-DAG: "?fooX@@YA?AVX@@XZ"
X fooX() { return X(); }
namespace PR13182 {
extern char s0[];
- // CHECK-DAG: @"\01?s0@PR13182@@3PADA"
+ // CHECK-DAG: @"?s0@PR13182@@3PADA"
extern char s1[42];
- // CHECK-DAG: @"\01?s1@PR13182@@3PADA"
+ // CHECK-DAG: @"?s1@PR13182@@3PADA"
extern const char s2[];
- // CHECK-DAG: @"\01?s2@PR13182@@3QBDB"
+ // CHECK-DAG: @"?s2@PR13182@@3QBDB"
extern const char s3[42];
- // CHECK-DAG: @"\01?s3@PR13182@@3QBDB"
+ // CHECK-DAG: @"?s3@PR13182@@3QBDB"
extern volatile char s4[];
- // CHECK-DAG: @"\01?s4@PR13182@@3RCDC"
+ // CHECK-DAG: @"?s4@PR13182@@3RCDC"
extern const volatile char s5[];
- // CHECK-DAG: @"\01?s5@PR13182@@3SDDD"
+ // CHECK-DAG: @"?s5@PR13182@@3SDDD"
extern const char* const* s6;
- // CHECK-DAG: @"\01?s6@PR13182@@3PBQBDB"
+ // CHECK-DAG: @"?s6@PR13182@@3PBQBDB"
char foo() {
return s0[0] + s1[0] + s2[0] + s3[0] + s4[0] + s5[0] + s6[0][0];
@@ -278,8 +278,8 @@
extern "C" inline void extern_c_func() {
static int local;
-// CHECK-DAG: @"\01?local@?1??extern_c_func@@9@4HA"
-// X64-DAG: @"\01?local@?1??extern_c_func@@9@4HA"
+// CHECK-DAG: @"?local@?1??extern_c_func@@9@4HA"
+// X64-DAG: @"?local@?1??extern_c_func@@9@4HA"
}
void call_extern_c_func() {
@@ -310,7 +310,7 @@
static struct {
int a_field;
} static_variable_in_inline_function = { 20 }, second_static = { 40 };
- // CHECK: @"\01?static_variable_in_inline_function@?1??inline_function_with_local_type@@YAHXZ@4U<unnamed-type-static_variable_in_inline_function>@?1??1@YAHXZ@A"
+ // CHECK: @"?static_variable_in_inline_function@?1??inline_function_with_local_type@@YAHXZ@4U<unnamed-type-static_variable_in_inline_function>@?1??1@YAHXZ@A"
return static_variable_in_inline_function.a_field + second_static.a_field;
}
@@ -325,7 +325,7 @@
int a_field;
} static_variable_in_templated_inline_function = { 20 },
second_static = { 40 };
- // CHECK: @"\01?static_variable_in_templated_inline_function@?1???$templated_inline_function_with_local_type@H@@YAHXZ@4U<unnamed-type-static_variable_in_templated_inline_function>@?1???$templated_inline_function_with_local_type@H@@YAHXZ@A"
+ // CHECK: @"?static_variable_in_templated_inline_function@?1???$templated_inline_function_with_local_type@H@@YAHXZ@4U<unnamed-type-static_variable_in_templated_inline_function>@?1???$templated_inline_function_with_local_type@H@@YAHXZ@A"
return static_variable_in_templated_inline_function.a_field +
second_static.a_field;
@@ -388,16 +388,16 @@
// CHECK-DAG: ??_VTypedefNewDelete@@SAXPAX@Z
void __vectorcall vector_func() { }
-// CHECK-DAG: @"\01?vector_func@@YQXXZ"
+// CHECK-DAG: @"?vector_func@@YQXXZ"
template <void (*)(void)>
void fn_tmpl() {}
template void fn_tmpl<extern_c_func>();
-// CHECK-DAG: @"\01??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ"
+// CHECK-DAG: @"??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ"
extern "C" void __attribute__((overloadable)) overloaded_fn() {}
-// CHECK-DAG: @"\01?overloaded_fn@@$$J0YAXXZ"
+// CHECK-DAG: @"?overloaded_fn@@$$J0YAXXZ"
extern "C" void overloaded_fn2() {}
// CHECK-DAG: @overloaded_fn2
@@ -420,19 +420,19 @@
void f(S::T4) {}
void f(S::T5) {}
void f(S::T6) {}
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXQAPAU<unnamed-type-T1>@S@1@@Z"
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXUT2@S@1@@Z"
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXPAUT4@S@1@@Z"
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXUT4@S@1@@Z"
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXUT5@S@1@@Z"
-// CHECK-DAG: @"\01?f@UnnamedType@@YAXPAU<unnamed-type-T6>@S@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXQAPAU<unnamed-type-T1>@S@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXUT2@S@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXPAUT4@S@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXUT4@S@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXUT5@S@1@@Z"
+// CHECK-DAG: @"?f@UnnamedType@@YAXPAU<unnamed-type-T6>@S@1@@Z"
-// X64-DAG: @"\01?f@UnnamedType@@YAXQEAPEAU<unnamed-type-T1>@S@1@@Z"
-// X64-DAG: @"\01?f@UnnamedType@@YAXUT2@S@1@@Z"
-// X64-DAG: @"\01?f@UnnamedType@@YAXPEAUT4@S@1@@Z"(%"struct.UnnamedType::S::T4"
-// X64-DAG: @"\01?f@UnnamedType@@YAXUT4@S@1@@Z"
-// X64-DAG: @"\01?f@UnnamedType@@YAXUT5@S@1@@Z"
-// X64-DAG: @"\01?f@UnnamedType@@YAXPEAU<unnamed-type-T6>@S@1@@Z"
+// X64-DAG: @"?f@UnnamedType@@YAXQEAPEAU<unnamed-type-T1>@S@1@@Z"
+// X64-DAG: @"?f@UnnamedType@@YAXUT2@S@1@@Z"
+// X64-DAG: @"?f@UnnamedType@@YAXPEAUT4@S@1@@Z"(%"struct.UnnamedType::S::T4"
+// X64-DAG: @"?f@UnnamedType@@YAXUT4@S@1@@Z"
+// X64-DAG: @"?f@UnnamedType@@YAXUT5@S@1@@Z"
+// X64-DAG: @"?f@UnnamedType@@YAXPEAU<unnamed-type-T6>@S@1@@Z"
}
namespace PassObjectSize {
@@ -448,22 +448,22 @@
// void foo(void *const, __clang::__pass_object_size0);
// where __clang is a top-level namespace.
-// CHECK-DAG: define dso_local i32 @"\01?foo@PassObjectSize@@YAHQAHW4__pass_object_size0@__clang@@@Z"
+// CHECK-DAG: define dso_local i32 @"?foo@PassObjectSize@@YAHQAHW4__pass_object_size0@__clang@@@Z"
int foo(int *const i __attribute__((pass_object_size(0)))) { return 0; }
-// CHECK-DAG: define dso_local i32 @"\01?bar@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@@Z"
+// CHECK-DAG: define dso_local i32 @"?bar@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@@Z"
int bar(int *const i __attribute__((pass_object_size(1)))) { return 0; }
-// CHECK-DAG: define dso_local i32 @"\01?qux@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@0W4__pass_object_size0@3@@Z"
+// CHECK-DAG: define dso_local i32 @"?qux@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@0W4__pass_object_size0@3@@Z"
int qux(int *const i __attribute__((pass_object_size(1))), int *const j __attribute__((pass_object_size(0)))) { return 0; }
-// CHECK-DAG: define dso_local i32 @"\01?zot@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@01@Z"
+// CHECK-DAG: define dso_local i32 @"?zot@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@01@Z"
int zot(int *const i __attribute__((pass_object_size(1))), int *const j __attribute__((pass_object_size(1)))) { return 0; }
}
namespace Atomic {
-// CHECK-DAG: define dso_local void @"\01?f@Atomic@@YAXU?$_Atomic@H@__clang@@@Z"(
+// CHECK-DAG: define dso_local void @"?f@Atomic@@YAXU?$_Atomic@H@__clang@@@Z"(
void f(_Atomic(int)) {}
}
namespace Complex {
-// CHECK-DAG: define dso_local void @"\01?f@Complex@@YAXU?$_Complex@H@__clang@@@Z"(
+// CHECK-DAG: define dso_local void @"?f@Complex@@YAXU?$_Complex@H@__clang@@@Z"(
void f(_Complex int) {}
}
@@ -489,5 +489,5 @@
L<H<int *> > b;
m_fn3<int>();
}
-// CHECK-DAG: call {{.*}} @"\01??0?$L@V?$H@PAH@PR26029@@@PR26029@@QAE@XZ"
+// CHECK-DAG: call {{.*}} @"??0?$L@V?$H@PAH@PR26029@@@PR26029@@QAE@XZ"
}
diff --git a/test/CodeGenCXX/mangle-windows.cpp b/test/CodeGenCXX/mangle-windows.cpp
index 51e4bc8..a9d7be1 100644
--- a/test/CodeGenCXX/mangle-windows.cpp
+++ b/test/CodeGenCXX/mangle-windows.cpp
@@ -5,11 +5,11 @@
// RUN: FileCheck --check-prefix=ITANIUM %s
void __stdcall f1(void) {}
-// WIN: define dso_local x86_stdcallcc void @"\01?f1@@YGXXZ"
+// WIN: define dso_local x86_stdcallcc void @"?f1@@YGXXZ"
// ITANIUM: define dso_local x86_stdcallcc void @"\01__Z2f1v@0"
void __fastcall f2(void) {}
-// WIN: define dso_local x86_fastcallcc void @"\01?f2@@YIXXZ"
+// WIN: define dso_local x86_fastcallcc void @"?f2@@YIXXZ"
// ITANIUM: define dso_local x86_fastcallcc void @"\01@_Z2f2v@0"
extern "C" void __stdcall f3(void) {}
@@ -26,11 +26,11 @@
};
void Foo::foo() {}
-// WIN: define dso_local x86_stdcallcc void @"\01?foo@Foo@@QAGXXZ"
+// WIN: define dso_local x86_stdcallcc void @"?foo@Foo@@QAGXXZ"
// ITANIUM: define dso_local x86_stdcallcc void @"\01__ZN3Foo3fooEv@4"
void Foo::bar() {}
-// WIN: define dso_local x86_stdcallcc void @"\01?bar@Foo@@SGXXZ"
+// WIN: define dso_local x86_stdcallcc void @"?bar@Foo@@SGXXZ"
// ITANIUM: define dso_local x86_stdcallcc void @"\01__ZN3Foo3barEv@0"
// Mostly a test that we don't crash and that the names start with a \01.
@@ -38,5 +38,5 @@
// cl produces _++@4
extern "C" void __stdcall operator++(Foo &x) {
}
-// WIN: define dso_local x86_stdcallcc void @"\01??E@YGXAAUFoo@@@Z"
+// WIN: define dso_local x86_stdcallcc void @"??E@YGXAAUFoo@@@Z"
// ITANIUM: define dso_local x86_stdcallcc void @"\01__ZppR3Foo@4"
diff --git a/test/CodeGenCXX/microsoft-abi-arg-order.cpp b/test/CodeGenCXX/microsoft-abi-arg-order.cpp
index 84c77bd..df945f9 100644
--- a/test/CodeGenCXX/microsoft-abi-arg-order.cpp
+++ b/test/CodeGenCXX/microsoft-abi-arg-order.cpp
@@ -13,21 +13,21 @@
// Order of destruction should be left to right.
//
-// X86-LABEL: define dso_local void @"\01?foo@@YAXUA@@00@Z"
+// X86-LABEL: define dso_local void @"?foo@@YAXUA@@00@Z"
// X86: ([[argmem_ty:<{ %struct.A, %struct.A, %struct.A }>]]* inalloca)
// X86: %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %0, i32 0, i32 0
// X86: %[[b:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %0, i32 0, i32 1
// X86: %[[c:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %0, i32 0, i32 2
-// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[a]])
-// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[b]])
-// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[c]])
+// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %[[a]])
+// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %[[b]])
+// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %[[c]])
// X86: ret void
-// X64-LABEL: define dso_local void @"\01?foo@@YAXUA@@00@Z"
+// X64-LABEL: define dso_local void @"?foo@@YAXUA@@00@Z"
// X64: (%struct.A* %[[a:[^,]*]], %struct.A* %[[b:[^,]*]], %struct.A* %[[c:[^)]*]])
-// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[a]])
-// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[b]])
-// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[c]])
+// X64: call void @"??1A@@QEAA@XZ"(%struct.A* %[[a]])
+// X64: call void @"??1A@@QEAA@XZ"(%struct.A* %[[b]])
+// X64: call void @"??1A@@QEAA@XZ"(%struct.A* %[[c]])
// X64: ret void
@@ -38,39 +38,39 @@
// Order of evaluation should be right to left, and we should clean up the right
// things as we unwind.
//
-// X86-LABEL: define dso_local void @"\01?call_foo@@YAXXZ"()
+// X86-LABEL: define dso_local void @"?call_foo@@YAXXZ"()
// X86: call i8* @llvm.stacksave()
// X86: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]]
// X86: %[[arg3:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 2
-// X86: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg3]], i32 3)
+// X86: call x86_thiscallcc %struct.A* @"??0A@@QAE@H@Z"(%struct.A* %[[arg3]], i32 3)
// X86: %[[arg2:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
-// X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg2]], i32 2)
+// X86: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@H@Z"(%struct.A* %[[arg2]], i32 2)
// X86: %[[arg1:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
-// X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg1]], i32 1)
-// X86: call void @"\01?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca %[[argmem]])
+// X86: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@H@Z"(%struct.A* %[[arg1]], i32 1)
+// X86: call void @"?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca %[[argmem]])
// X86: call void @llvm.stackrestore
// X86: ret void
//
// lpad2:
// X86: cleanuppad within none []
-// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg2]])
+// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %[[arg2]])
// X86: cleanupret
//
// ehcleanup:
-// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg3]])
+// X86: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %[[arg3]])
-// X64-LABEL: define dso_local void @"\01?call_foo@@YAXXZ"()
-// X64: call %struct.A* @"\01??0A@@QEAA@H@Z"(%struct.A* %[[arg3:[^,]*]], i32 3)
-// X64: invoke %struct.A* @"\01??0A@@QEAA@H@Z"(%struct.A* %[[arg2:[^,]*]], i32 2)
-// X64: invoke %struct.A* @"\01??0A@@QEAA@H@Z"(%struct.A* %[[arg1:[^,]*]], i32 1)
-// X64: call void @"\01?foo@@YAXUA@@00@Z"
+// X64-LABEL: define dso_local void @"?call_foo@@YAXXZ"()
+// X64: call %struct.A* @"??0A@@QEAA@H@Z"(%struct.A* %[[arg3:[^,]*]], i32 3)
+// X64: invoke %struct.A* @"??0A@@QEAA@H@Z"(%struct.A* %[[arg2:[^,]*]], i32 2)
+// X64: invoke %struct.A* @"??0A@@QEAA@H@Z"(%struct.A* %[[arg1:[^,]*]], i32 1)
+// X64: call void @"?foo@@YAXUA@@00@Z"
// X64: (%struct.A* %[[arg1]], %struct.A* %[[arg2]], %struct.A* %[[arg3]])
// X64: ret void
//
// lpad2:
// X64: cleanuppad within none []
-// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg2]])
+// X64: call void @"??1A@@QEAA@XZ"(%struct.A* %[[arg2]])
// X64: cleanupret
//
// ehcleanup:
-// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg3]])
+// X64: call void @"??1A@@QEAA@XZ"(%struct.A* %[[arg3]])
diff --git a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
index 349d5a0..2814045 100644
--- a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
+++ b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
@@ -5,12 +5,12 @@
};
void check_array_no_cookies() {
-// CHECK: define dso_local void @"\01?check_array_no_cookies@@YAXXZ"() [[NUW:#[0-9]+]]
+// CHECK: define dso_local void @"?check_array_no_cookies@@YAXXZ"() [[NUW:#[0-9]+]]
-// CHECK: call i8* @"\01??_U@YAPAXI@Z"(i32 42)
+// CHECK: call i8* @"??_U@YAPAXI@Z"(i32 42)
ClassWithoutDtor *array = new ClassWithoutDtor[42];
-// CHECK: call void @"\01??_V@YAXPAX@Z"(
+// CHECK: call void @"??_V@YAXPAX@Z"(
delete [] array;
}
@@ -21,10 +21,10 @@
};
void check_array_cookies_simple() {
-// CHECK: define {{.*}} @"\01?check_array_cookies_simple@@YAXXZ"()
+// CHECK: define {{.*}} @"?check_array_cookies_simple@@YAXXZ"()
ClassWithDtor *array = new ClassWithDtor[42];
-// CHECK: [[ALLOCATED:%.*]] = call i8* @"\01??_U@YAPAXI@Z"(i32 46)
+// CHECK: [[ALLOCATED:%.*]] = call i8* @"??_U@YAPAXI@Z"(i32 46)
// 46 = 42 + size of cookie (4)
// CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32*
// CHECK: store i32 42, i32* [[COOKIE]]
@@ -44,9 +44,9 @@
};
void check_array_cookies_aligned() {
-// CHECK: define {{.*}} @"\01?check_array_cookies_aligned@@YAXXZ"()
+// CHECK: define {{.*}} @"?check_array_cookies_aligned@@YAXXZ"()
ClassWithAlignment *array = new ClassWithAlignment[42];
-// CHECK: [[ALLOCATED:%.*]] = call i8* @"\01??_U@YAPAXI@Z"(i32 344)
+// CHECK: [[ALLOCATED:%.*]] = call i8* @"??_U@YAPAXI@Z"(i32 344)
// 344 = 42*8 + size of cookie (8, due to alignment)
// CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32*
// CHECK: store i32 42, i32* [[COOKIE]]
@@ -62,8 +62,8 @@
struct S {
char x[42];
void operator delete[](void *p, __SIZE_TYPE__);
- // CHECK-LABEL: define dso_local void @"\01?delete_s@PR23990@@YAXPAUS@1@@Z"(
- // CHECK: call void @"\01??_VS@PR23990@@SAXPAXI@Z"(i8* {{.*}}, i32 42)
+ // CHECK-LABEL: define dso_local void @"?delete_s@PR23990@@YAXPAUS@1@@Z"(
+ // CHECK: call void @"??_VS@PR23990@@SAXPAXI@Z"(i8* {{.*}}, i32 42)
};
void delete_s(S *s) { delete[] s; }
}
diff --git a/test/CodeGenCXX/microsoft-abi-byval-sret.cpp b/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
index 83b4312..cbedec6 100644
--- a/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
+++ b/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
@@ -18,7 +18,7 @@
return x;
}
-// CHECK-LABEL: define dso_local x86_thiscallcc %struct.A* @"\01?foo@B@@QAE?AUA@@U2@@Z"
+// CHECK-LABEL: define dso_local x86_thiscallcc %struct.A* @"?foo@B@@QAE?AUA@@U2@@Z"
// CHECK: (%struct.B* %this, <{ %struct.A*, %struct.A }>* inalloca)
// CHECK: getelementptr inbounds <{ %struct.A*, %struct.A }>, <{ %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 0
// CHECK: load %struct.A*, %struct.A**
@@ -28,7 +28,7 @@
return x;
}
-// CHECK-LABEL: define dso_local %struct.A* @"\01?bar@B@@QAA?AUA@@U2@@Z"
+// CHECK-LABEL: define dso_local %struct.A* @"?bar@B@@QAA?AUA@@U2@@Z"
// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca)
// CHECK: getelementptr inbounds <{ %struct.B*, %struct.A*, %struct.A }>, <{ %struct.B*, %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 1
// CHECK: load %struct.A*, %struct.A**
@@ -38,7 +38,7 @@
return x;
}
-// CHECK-LABEL: define dso_local x86_stdcallcc %struct.A* @"\01?baz@B@@QAG?AUA@@U2@@Z"
+// CHECK-LABEL: define dso_local x86_stdcallcc %struct.A* @"?baz@B@@QAG?AUA@@U2@@Z"
// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca)
// CHECK: getelementptr inbounds <{ %struct.B*, %struct.A*, %struct.A }>, <{ %struct.B*, %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 1
// CHECK: load %struct.A*, %struct.A**
@@ -48,7 +48,7 @@
return x;
}
-// CHECK-LABEL: define dso_local x86_fastcallcc void @"\01?qux@B@@QAI?AUA@@U2@@Z"
+// CHECK-LABEL: define dso_local x86_fastcallcc void @"?qux@B@@QAI?AUA@@U2@@Z"
// CHECK: (%struct.B* inreg %this, %struct.A* inreg noalias sret %agg.result, <{ %struct.A }>* inalloca)
// CHECK: ret void
@@ -60,11 +60,11 @@
a = b.qux(a);
}
-// CHECK: call x86_thiscallcc %struct.A* @"\01?foo@B@@QAE?AUA@@U2@@Z"
+// CHECK: call x86_thiscallcc %struct.A* @"?foo@B@@QAE?AUA@@U2@@Z"
// CHECK: (%struct.B* %{{[^,]*}}, <{ %struct.A*, %struct.A }>* inalloca %{{[^,]*}})
-// CHECK: call %struct.A* @"\01?bar@B@@QAA?AUA@@U2@@Z"
+// CHECK: call %struct.A* @"?bar@B@@QAA?AUA@@U2@@Z"
// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %{{[^,]*}})
-// CHECK: call x86_stdcallcc %struct.A* @"\01?baz@B@@QAG?AUA@@U2@@Z"
+// CHECK: call x86_stdcallcc %struct.A* @"?baz@B@@QAG?AUA@@U2@@Z"
// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %{{[^,]*}})
-// CHECK: call x86_fastcallcc void @"\01?qux@B@@QAI?AUA@@U2@@Z"
+// CHECK: call x86_fastcallcc void @"?qux@B@@QAI?AUA@@U2@@Z"
// CHECK: (%struct.B* inreg %{{[^,]*}}, %struct.A* inreg sret %{{.*}}, <{ %struct.A }>* inalloca %{{[^,]*}})
diff --git a/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp b/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp
index 2ddd376..45dd4d0 100644
--- a/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp
+++ b/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp
@@ -14,17 +14,17 @@
struct C : A, B { C(); virtual void foo(Agg x); };
C::C() {} // force emission
-// CHECK32-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"\01?foo@C@byval_thunk@@W3AEXUAgg@2@@Z"
+// CHECK32-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?foo@C@byval_thunk@@W3AEXUAgg@2@@Z"
// CHECK32: (%"struct.byval_thunk::C"* %this, <{ %"struct.byval_thunk::Agg" }>* inalloca)
// CHECK32: getelementptr i8, i8* %{{.*}}, i32 -4
-// CHECK32: musttail call x86_thiscallcc void @"\01?foo@C@byval_thunk@@UAEXUAgg@2@@Z"
+// CHECK32: musttail call x86_thiscallcc void @"?foo@C@byval_thunk@@UAEXUAgg@2@@Z"
// CHECK32: (%"struct.byval_thunk::C"* %{{.*}}, <{ %"struct.byval_thunk::Agg" }>* inalloca %0)
// CHECK32-NEXT: ret void
-// CHECK64-LABEL: define linkonce_odr dso_local void @"\01?foo@C@byval_thunk@@W7EAAXUAgg@2@@Z"
+// CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@byval_thunk@@W7EAAXUAgg@2@@Z"
// CHECK64: (%"struct.byval_thunk::C"* %this, %"struct.byval_thunk::Agg"* %x)
// CHECK64: getelementptr i8, i8* %{{.*}}, i32 -8
-// CHECK64: call void @"\01?foo@C@byval_thunk@@UEAAXUAgg@2@@Z"
+// CHECK64: call void @"?foo@C@byval_thunk@@UEAAXUAgg@2@@Z"
// CHECK64: (%"struct.byval_thunk::C"* %{{.*}}, %"struct.byval_thunk::Agg"* %x)
// CHECK64-NOT: call
// CHECK64: ret void
@@ -43,20 +43,20 @@
struct C : A, B { C(); virtual void __stdcall foo(Agg x); };
C::C() {} // force emission
-// CHECK32-LABEL: define linkonce_odr dso_local x86_stdcallcc void @"\01?foo@C@stdcall_thunk@@W3AGXUAgg@2@@Z"
+// CHECK32-LABEL: define linkonce_odr dso_local x86_stdcallcc void @"?foo@C@stdcall_thunk@@W3AGXUAgg@2@@Z"
// CHECK32: (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca)
// CHECK32: %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>, <{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* %0, i32 0, i32 0
// CHECK32: load %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::C"** %[[this_slot]]
// CHECK32: getelementptr i8, i8* %{{.*}}, i32 -4
// CHECK32: store %"struct.stdcall_thunk::C"* %{{.*}}, %"struct.stdcall_thunk::C"** %[[this_slot]]
-// CHECK32: musttail call x86_stdcallcc void @"\01?foo@C@stdcall_thunk@@UAGXUAgg@2@@Z"
+// CHECK32: musttail call x86_stdcallcc void @"?foo@C@stdcall_thunk@@UAGXUAgg@2@@Z"
// CHECK32: (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca %0)
// CHECK32-NEXT: ret void
-// CHECK64-LABEL: define linkonce_odr dso_local void @"\01?foo@C@stdcall_thunk@@W7EAAXUAgg@2@@Z"
+// CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@stdcall_thunk@@W7EAAXUAgg@2@@Z"
// CHECK64: (%"struct.stdcall_thunk::C"* %this, %"struct.stdcall_thunk::Agg"* %x)
// CHECK64: getelementptr i8, i8* %{{.*}}, i32 -8
-// CHECK64: call void @"\01?foo@C@stdcall_thunk@@UEAAXUAgg@2@@Z"
+// CHECK64: call void @"?foo@C@stdcall_thunk@@UEAAXUAgg@2@@Z"
// CHECK64: (%"struct.stdcall_thunk::C"* %{{.*}}, %"struct.stdcall_thunk::Agg"* %x)
// CHECK64-NOT: call
// CHECK64: ret void
@@ -75,20 +75,20 @@
struct C : A, B { C(); virtual Agg __cdecl foo(Agg x); };
C::C() {} // force emission
-// CHECK32-LABEL: define linkonce_odr dso_local %"struct.sret_thunk::Agg"* @"\01?foo@C@sret_thunk@@W3AA?AUAgg@2@U32@@Z"
+// CHECK32-LABEL: define linkonce_odr dso_local %"struct.sret_thunk::Agg"* @"?foo@C@sret_thunk@@W3AA?AUAgg@2@U32@@Z"
// CHECK32: (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca)
// CHECK32: %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>, <{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* %0, i32 0, i32 0
// CHECK32: load %"struct.sret_thunk::C"*, %"struct.sret_thunk::C"** %[[this_slot]]
// CHECK32: getelementptr i8, i8* %{{.*}}, i32 -4
// CHECK32: store %"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::C"** %[[this_slot]]
-// CHECK32: %[[rv:[^ ]*]] = musttail call %"struct.sret_thunk::Agg"* @"\01?foo@C@sret_thunk@@UAA?AUAgg@2@U32@@Z"
+// CHECK32: %[[rv:[^ ]*]] = musttail call %"struct.sret_thunk::Agg"* @"?foo@C@sret_thunk@@UAA?AUAgg@2@U32@@Z"
// CHECK32: (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca %0)
// CHECK32-NEXT: ret %"struct.sret_thunk::Agg"* %[[rv]]
-// CHECK64-LABEL: define linkonce_odr dso_local void @"\01?foo@C@sret_thunk@@W7EAA?AUAgg@2@U32@@Z"
+// CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@sret_thunk@@W7EAA?AUAgg@2@U32@@Z"
// CHECK64: (%"struct.sret_thunk::C"* %this, %"struct.sret_thunk::Agg"* noalias sret %agg.result, %"struct.sret_thunk::Agg"* %x)
// CHECK64: getelementptr i8, i8* %{{.*}}, i32 -8
-// CHECK64: call void @"\01?foo@C@sret_thunk@@UEAA?AUAgg@2@U32@@Z"
+// CHECK64: call void @"?foo@C@sret_thunk@@UEAA?AUAgg@2@U32@@Z"
// CHECK64: (%"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::Agg"* sret %agg.result, %"struct.sret_thunk::Agg"* %x)
// CHECK64-NOT: call
// CHECK64: ret void
diff --git a/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp b/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
index 9b3b144..e6a36e2 100644
--- a/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
+++ b/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
@@ -19,14 +19,14 @@
return sum;
}
-// CHECK-LABEL: define dso_local i32 @"\01?foo@@YAHUA@@ZZ"(<{ %struct.A }>* inalloca, ...)
+// CHECK-LABEL: define dso_local i32 @"?foo@@YAHUA@@ZZ"(<{ %struct.A }>* inalloca, ...)
int main() {
return foo(A(3), 1, 2, 3);
}
// CHECK-LABEL: define dso_local i32 @main()
// CHECK: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.A, i32, i32, i32 }>
-// CHECK: call i32 {{.*bitcast.*}}@"\01?foo@@YAHUA@@ZZ"{{.*}}(<{ %struct.A, i32, i32, i32 }>* inalloca %[[argmem]])
+// CHECK: call i32 {{.*bitcast.*}}@"?foo@@YAHUA@@ZZ"{{.*}}(<{ %struct.A, i32, i32, i32 }>* inalloca %[[argmem]])
void varargs_zero(...);
void varargs_one(int, ...);
@@ -40,13 +40,13 @@
varargs_three(1, 2, 3, x);
}
-// CHECK-LABEL: define dso_local void @"\01?call_var_args@@YAXXZ"()
+// CHECK-LABEL: define dso_local void @"?call_var_args@@YAXXZ"()
// CHECK: call void {{.*bitcast.*varargs_zero.*}}(<{ %struct.A }>* inalloca %{{.*}})
// CHECK: call void {{.*bitcast.*varargs_one.*}}(<{ i32, %struct.A }>* inalloca %{{.*}})
// CHECK: call void {{.*bitcast.*varargs_two.*}}(<{ i32, i32, %struct.A }>* inalloca %{{.*}})
// CHECK: call void {{.*bitcast.*varargs_three.*}}(<{ i32, i32, i32, %struct.A }>* inalloca %{{.*}})
-// CHECK-LABEL: declare dso_local void @"\01?varargs_zero@@YAXZZ"(...)
-// CHECK-LABEL: declare dso_local void @"\01?varargs_one@@YAXHZZ"(i32, ...)
-// CHECK-LABEL: declare dso_local void @"\01?varargs_two@@YAXHHZZ"(i32, i32, ...)
-// CHECK-LABEL: declare dso_local void @"\01?varargs_three@@YAXHHHZZ"(i32, i32, i32, ...)
+// CHECK-LABEL: declare dso_local void @"?varargs_zero@@YAXZZ"(...)
+// CHECK-LABEL: declare dso_local void @"?varargs_one@@YAXHZZ"(i32, ...)
+// CHECK-LABEL: declare dso_local void @"?varargs_two@@YAXHHZZ"(i32, i32, ...)
+// CHECK-LABEL: declare dso_local void @"?varargs_three@@YAXHHHZZ"(i32, i32, i32, ...)
diff --git a/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp b/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp
index 3e15ba2..34e2bc5 100644
--- a/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp
+++ b/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp
@@ -19,9 +19,9 @@
S C::cdecl_sret() { return S(); }
S C::byval_and_sret(S a) { return S(); }
-// CHECK: define dso_local void @"\01?variadic_sret@C@@QAA?AUS@@PBDZZ"(%struct.C* %this, %struct.S* noalias sret %agg.result, i8* %f, ...)
-// CHECK: define dso_local void @"\01?cdecl_sret@C@@QAA?AUS@@XZ"(%struct.C* %this, %struct.S* noalias sret %agg.result)
-// CHECK: define dso_local void @"\01?byval_and_sret@C@@QAA?AUS@@U2@@Z"(%struct.C* %this, %struct.S* noalias sret %agg.result, %struct.S* byval align 4 %a)
+// CHECK: define dso_local void @"?variadic_sret@C@@QAA?AUS@@PBDZZ"(%struct.C* %this, %struct.S* noalias sret %agg.result, i8* %f, ...)
+// CHECK: define dso_local void @"?cdecl_sret@C@@QAA?AUS@@XZ"(%struct.C* %this, %struct.S* noalias sret %agg.result)
+// CHECK: define dso_local void @"?byval_and_sret@C@@QAA?AUS@@U2@@Z"(%struct.C* %this, %struct.S* noalias sret %agg.result, %struct.S* byval align 4 %a)
int main() {
C c;
@@ -30,9 +30,9 @@
c.byval_and_sret(S());
}
// CHECK-LABEL: define dso_local i32 @main()
-// CHECK: call void {{.*}} @"\01?variadic_sret@C@@QAA?AUS@@PBDZZ"
-// CHECK: call void @"\01?cdecl_sret@C@@QAA?AUS@@XZ"
-// CHECK: call void @"\01?byval_and_sret@C@@QAA?AUS@@U2@@Z"
+// CHECK: call void {{.*}} @"?variadic_sret@C@@QAA?AUS@@PBDZZ"
+// CHECK: call void @"?cdecl_sret@C@@QAA?AUS@@XZ"
+// CHECK: call void @"?byval_and_sret@C@@QAA?AUS@@U2@@Z"
// __fastcall has similar issues.
struct A {
@@ -41,4 +41,4 @@
S A::f(int x) {
return S();
}
-// CHECK-LABEL: define dso_local x86_fastcallcc void @"\01?f@A@@QAI?AUS@@H@Z"(%struct.A* inreg %this, %struct.S* inreg noalias sret %agg.result, i32 %x)
+// CHECK-LABEL: define dso_local x86_fastcallcc void @"?f@A@@QAI?AUS@@H@Z"(%struct.A* inreg %this, %struct.S* inreg noalias sret %agg.result, i32 %x)
diff --git a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
index a65f42a..6f42603 100644
--- a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
@@ -7,7 +7,7 @@
};
A a(42);
-// CHECK: @"\01?a@@3UA@@A" = dso_local global { { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"\01??_7A@@6B@", i32 42 }, align 4
+// CHECK: @"?a@@3UA@@A" = dso_local global { { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"??_7A@@6B@", i32 42 }, align 4
struct B {
constexpr B(int y) : y(y) {}
@@ -20,4 +20,4 @@
};
C c;
-// CHECK: @"\01?c@@3UC@@A" = dso_local global { { [1 x i8*] }*, i32, { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"\01??_7C@@6BA@@@", i32 777, { [1 x i8*] }* @"\01??_7C@@6BB@@@", i32 13 }
+// CHECK: @"?c@@3UC@@A" = dso_local global { { [1 x i8*] }*, i32, { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"??_7C@@6BA@@@", i32 777, { [1 x i8*] }* @"??_7C@@6BB@@@", i32 13 }
diff --git a/test/CodeGenCXX/microsoft-abi-default-cc.cpp b/test/CodeGenCXX/microsoft-abi-default-cc.cpp
index 9247cc4..804ee51 100644
--- a/test/CodeGenCXX/microsoft-abi-default-cc.cpp
+++ b/test/CodeGenCXX/microsoft-abi-default-cc.cpp
@@ -13,13 +13,13 @@
void __cdecl foo();
void __cdecl foo() {}
// GCABI-LABEL: define void @_Z3foov()
-// MSABI: define dso_local void @"\01?foo@@YAXXZ"
+// MSABI: define dso_local void @"?foo@@YAXXZ"
void __cdecl bar();
void bar();
void bar() {}
// GCABI-LABEL: define void @_Z3barv()
-// MSABI: define dso_local void @"\01?bar@@YAXXZ"
+// MSABI: define dso_local void @"?bar@@YAXXZ"
// Test that it's OK to mark either the method declaration or method definition
// with a default CC explicitly.
@@ -34,23 +34,23 @@
void METHOD_CC A::baz() {}
// GCABI-LABEL: define void @_ZN1A3bazEv
-// MSABI: define dso_local x86_thiscallcc void @"\01?baz@A@@QAEXXZ"
+// MSABI: define dso_local x86_thiscallcc void @"?baz@A@@QAEXXZ"
void A::qux() {}
// GCABI-LABEL: define void @_ZN1A3quxEv
-// MSABI: define dso_local x86_thiscallcc void @"\01?qux@A@@QAEXXZ"
+// MSABI: define dso_local x86_thiscallcc void @"?qux@A@@QAEXXZ"
void __cdecl static_baz() {}
// GCABI-LABEL: define void @_Z10static_bazv
-// MSABI: define dso_local void @"\01?static_baz@@YAXXZ"
+// MSABI: define dso_local void @"?static_baz@@YAXXZ"
void static_qux() {}
// GCABI-LABEL: define void @_Z10static_quxv
-// MSABI: define dso_local void @"\01?static_qux@@YAXXZ"
+// MSABI: define dso_local void @"?static_qux@@YAXXZ"
namespace PR31656 {
template <int I>
void __cdecl callee(int args[I]);
// GCABI-LABEL: declare void @_ZN7PR316566calleeILi1EEEvPi(
-// MSABI: declare dso_local void @"\01??$callee@$00@PR31656@@YAXQAH@Z"(
+// MSABI: declare dso_local void @"??$callee@$00@PR31656@@YAXQAH@Z"(
void caller() { callee<1>(0); }
}
diff --git a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp
index 07356e4..e45d372 100644
--- a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp
+++ b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp
@@ -7,30 +7,30 @@
struct T {};
T* test0() { return dynamic_cast<T*>((B*)0); }
-// CHECK-LABEL: define dso_local noalias %struct.T* @"\01?test0@@YAPAUT@@XZ"()
+// CHECK-LABEL: define dso_local noalias %struct.T* @"?test0@@YAPAUT@@XZ"()
// CHECK: ret %struct.T* null
T* test1(V* x) { return &dynamic_cast<T&>(*x); }
-// CHECK-LABEL: define dso_local %struct.T* @"\01?test1@@YAPAUT@@PAUV@@@Z"(%struct.V* %x)
+// CHECK-LABEL: define dso_local %struct.T* @"?test1@@YAPAUT@@PAUV@@@Z"(%struct.V* %x)
// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8*
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 1)
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
T* test2(A* x) { return &dynamic_cast<T&>(*x); }
-// CHECK-LABEL: define dso_local %struct.T* @"\01?test2@@YAPAUT@@PAUA@@@Z"(%struct.A* %x)
+// CHECK-LABEL: define dso_local %struct.T* @"?test2@@YAPAUT@@PAUA@@@Z"(%struct.A* %x)
// CHECK: [[CAST:%.*]] = bitcast %struct.A* %x to i8*
// CHECK-NEXT: [[VBPTRPTR:%.*]] = getelementptr inbounds %struct.A, %struct.A* %x, i32 0, i32 0
// CHECK-NEXT: [[VBTBL:%.*]] = load i32*, i32** [[VBPTRPTR]], align 4
// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32, i32* [[VBTBL]], i32 1
// CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4
// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[CAST]], i32 [[VBOFFS]]
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 1)
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
T* test3(B* x) { return &dynamic_cast<T&>(*x); }
-// CHECK-LABEL: define dso_local %struct.T* @"\01?test3@@YAPAUT@@PAUB@@@Z"(%struct.B* %x)
+// CHECK-LABEL: define dso_local %struct.T* @"?test3@@YAPAUT@@PAUB@@@Z"(%struct.B* %x)
// CHECK: [[VOIDP:%.*]] = getelementptr inbounds %struct.B, %struct.B* %x, i32 0, i32 0, i32 0
// CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8, i8* [[VOIDP]], i32 4
// CHECK-NEXT: [[VBPTRPTR:%.*]] = bitcast i8* [[VBPTR:%.*]] to i32**
@@ -39,19 +39,19 @@
// CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4
// CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[VOIDP]], i32 [[DELTA]]
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 1)
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
T* test4(V* x) { return dynamic_cast<T*>(x); }
-// CHECK-LABEL: define dso_local %struct.T* @"\01?test4@@YAPAUT@@PAUV@@@Z"(%struct.V* %x)
+// CHECK-LABEL: define dso_local %struct.T* @"?test4@@YAPAUT@@PAUV@@@Z"(%struct.V* %x)
// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8*
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 0)
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
T* test5(A* x) { return dynamic_cast<T*>(x); }
-// CHECK-LABEL: define dso_local %struct.T* @"\01?test5@@YAPAUT@@PAUA@@@Z"(%struct.A* %x)
+// CHECK-LABEL: define dso_local %struct.T* @"?test5@@YAPAUT@@PAUA@@@Z"(%struct.A* %x)
// CHECK: [[CHECK:%.*]] = icmp eq %struct.A* %x, null
// CHECK-NEXT: br i1 [[CHECK]]
// CHECK: [[VOIDP:%.*]] = bitcast %struct.A* %x to i8*
@@ -60,14 +60,14 @@
// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32, i32* [[VBTBL]], i32 1
// CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4
// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[VOIDP]], i32 [[VBOFFS]]
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i8*), i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 0)
// CHECK-NEXT: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: br label
// CHECK: [[RET:%.*]] = phi %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
T* test6(B* x) { return dynamic_cast<T*>(x); }
-// CHECK-LABEL: define dso_local %struct.T* @"\01?test6@@YAPAUT@@PAUB@@@Z"(%struct.B* %x)
+// CHECK-LABEL: define dso_local %struct.T* @"?test6@@YAPAUT@@PAUB@@@Z"(%struct.B* %x)
// CHECK: [[CHECK:%.*]] = icmp eq %struct.B* %x, null
// CHECK-NEXT: br i1 [[CHECK]]
// CHECK: [[CAST:%.*]] = getelementptr inbounds %struct.B, %struct.B* %x, i32 0, i32 0, i32 0
@@ -78,20 +78,20 @@
// CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4
// CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[CAST]], i32 [[DELTA]]
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* nonnull [[ADJ]], i32 [[DELTA]], i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* nonnull [[ADJ]], i32 [[DELTA]], i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i8*), i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 0)
// CHECK-NEXT: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: br label
// CHECK: [[RET:%.*]] = phi %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
void* test7(V* x) { return dynamic_cast<void*>(x); }
-// CHECK-LABEL: define dso_local i8* @"\01?test7@@YAPAXPAUV@@@Z"(%struct.V* %x)
+// CHECK-LABEL: define dso_local i8* @"?test7@@YAPAXPAUV@@@Z"(%struct.V* %x)
// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8*
// CHECK-NEXT: [[RET:%.*]] = tail call i8* @__RTCastToVoid(i8* [[CAST]])
// CHECK-NEXT: ret i8* [[RET]]
void* test8(A* x) { return dynamic_cast<void*>(x); }
-// CHECK-LABEL: define dso_local i8* @"\01?test8@@YAPAXPAUA@@@Z"(%struct.A* %x)
+// CHECK-LABEL: define dso_local i8* @"?test8@@YAPAXPAUA@@@Z"(%struct.A* %x)
// CHECK: [[CHECK:%.*]] = icmp eq %struct.A* %x, null
// CHECK-NEXT: br i1 [[CHECK]]
// CHECK: [[VOIDP:%.*]] = bitcast %struct.A* %x to i8*
@@ -106,7 +106,7 @@
// CHECK-NEXT: ret i8* [[RET]]
void* test9(B* x) { return dynamic_cast<void*>(x); }
-// CHECK-LABEL: define dso_local i8* @"\01?test9@@YAPAXPAUB@@@Z"(%struct.B* %x)
+// CHECK-LABEL: define dso_local i8* @"?test9@@YAPAXPAUB@@@Z"(%struct.B* %x)
// CHECK: [[CHECK:%.*]] = icmp eq %struct.B* %x, null
// CHECK-NEXT: br i1 [[CHECK]]
// CHECK: [[CAST:%.*]] = getelementptr inbounds %struct.B, %struct.B* %x, i32 0, i32 0, i32 0
@@ -134,10 +134,10 @@
Cleanup c;
return dynamic_cast<S3 *>(&s);
}
-// CHECK-LABEL: define dso_local %"struct.PR25606::S3"* @"\01?f@PR25606@@YAPAUS3@1@AAUS2@1@@Z"(
+// CHECK-LABEL: define dso_local %"struct.PR25606::S3"* @"?f@PR25606@@YAPAUS3@1@AAUS2@1@@Z"(
// CHECK: [[CALL:%.*]] = invoke i8* @__RTDynamicCast
// CHECK: [[BC:%.*]] = bitcast i8* [[CALL]] to %"struct.PR25606::S3"*
-// CHECK: call x86_thiscallcc void @"\01??_DCleanup@PR25606@@QAEXXZ"(
+// CHECK: call x86_thiscallcc void @"??1Cleanup@PR25606@@QAE@XZ"(
// CHECK: ret %"struct.PR25606::S3"* [[BC]]
}
diff --git a/test/CodeGenCXX/microsoft-abi-eh-catch.cpp b/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
index 52351cf..53f8717 100644
--- a/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
+++ b/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
@@ -47,7 +47,7 @@
}
// WIN64-LABEL: define dso_local void @catch_int()
-// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %[[e_addr:[^\]]*]]]
+// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i32* %[[e_addr:[^\]]*]]]
//
// The catchpad instruction starts the lifetime of 'e'. Unfortunately, that
// leaves us with nowhere to put lifetime.start, so we don't emit lifetime
@@ -69,7 +69,7 @@
}
// WIN64-LABEL: define dso_local void @catch_int_unnamed()
-// WIN64: catchpad within %{{.*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// WIN64: catchpad within %{{.*}} [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i8* null]
// WIN64: catchret
struct A {
@@ -96,7 +96,7 @@
// WIN64-LABEL: define dso_local void @catch_a_byval()
// WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A
-// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]]
+// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]]
// WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*
// WIN64: call void @handle_exception(i8* %[[e_i8]])
// WIN64: catchret
@@ -111,7 +111,7 @@
// WIN64-LABEL: define dso_local void @catch_a_ref()
// WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A*
-// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]]
+// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]]
// WIN64: %[[eptr:[^ ]*]] = load %struct.A*, %struct.A** %[[e_addr]]
// WIN64: %[[eptr_i8:[^ ]*]] = bitcast %struct.A* %[[eptr]] to i8*
// WIN64: call void @handle_exception(i8* %[[eptr_i8]])
@@ -145,7 +145,7 @@
// WIN64: %[[catchswitch_outer_scope:[^ ]*]] = catchswitch within none [label %[[catch_int_outer:[^ ]*]]] unwind to caller
//
// WIN64: [[catch_int_outer]]
-// WIN64: %[[catchpad:[^ ]*]] = catchpad within %[[catchswitch_outer_scope]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// WIN64: %[[catchpad:[^ ]*]] = catchpad within %[[catchswitch_outer_scope]] [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i8* null]
// WIN64: invoke void @might_throw()
// WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[catchswitch_inner:[^ ]*]]
//
@@ -153,7 +153,7 @@
// WIN64: %[[catchswitch_inner_scope:[^ ]*]] = catchswitch within %[[catchpad]] [label %[[catch_int_inner:[^ ]*]]] unwind to caller
//
// WIN64: [[catch_int_inner]]
-// WIN64: catchpad within %[[catchswitch_inner_scope]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// WIN64: catchpad within %[[catchswitch_inner_scope]] [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i8* null]
// WIN64-NEXT: call void @might_throw()
// WIN64: catchret {{.*}} to label %[[catchret2:[^ ]*]]
//
diff --git a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
index 01ea9a8..116ce09 100644
--- a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
+++ b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
@@ -15,21 +15,21 @@
}
// With exceptions, we need to clean up at least one of these temporaries.
-// WIN32-LABEL: define dso_local void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {
+// WIN32-LABEL: define dso_local void @"?HasEHCleanup@@YAXXZ"() {{.*}} {
// WIN32: %[[base:.*]] = call i8* @llvm.stacksave()
// If this call throws, we have to restore the stack.
-// WIN32: call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
+// WIN32: call void @"?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
// If this call throws, we have to cleanup the first temporary.
-// WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
+// WIN32: invoke void @"?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
// If this call throws, we have to cleanup the stacksave.
-// WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32: call i32 @"?TakesTwo@@YAHUA@@0@Z"
// WIN32: call void @llvm.stackrestore
// WIN32: ret void
//
// There should be one dtor call for unwinding from the second getA.
// WIN32: cleanuppad
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
-// WIN32-NOT: @"\01??1A@@QAE@XZ"
+// WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
+// WIN32-NOT: @"??1A@@QAE@XZ"
// WIN32: }
void TakeRef(const A &a);
@@ -37,33 +37,33 @@
return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
}
-// WIN32-LABEL: define dso_local i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
+// WIN32-LABEL: define dso_local i32 @"?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
// WIN32: %[[isactive:.*]] = alloca i1
// WIN32: call i8* @llvm.stacksave()
// WIN32: %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]]
// WIN32: %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
-// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
-// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
+// WIN32: call x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
+// WIN32: invoke void @"?TakeRef@@YAXABUA@@@Z"
//
-// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])
+// WIN32: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"(%struct.A* %[[arg1]])
// WIN32: store i1 true, i1* %[[isactive]]
//
// WIN32: %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
-// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
-// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
-// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
+// WIN32: invoke void @"?TakeRef@@YAXABUA@@@Z"
+// WIN32: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32: store i1 false, i1* %[[isactive]]
//
-// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]])
+// WIN32: invoke i32 @"?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]])
// Destroy the two const ref temporaries.
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
// WIN32: ret i32
//
// Conditionally destroy arg1.
// WIN32: %[[cond:.*]] = load i1, i1* %[[isactive]]
// WIN32: br i1 %[[cond]]
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
+// WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %[[arg1]])
// WIN32: }
// Test putting the cleanups inside a conditional.
@@ -72,22 +72,22 @@
return (cond ? TakesTwo(A(), A()) : CouldThrow());
}
-// WIN32-LABEL: define dso_local i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
+// WIN32-LABEL: define dso_local i32 @"?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
// WIN32: store i1 false
// WIN32: br i1
// WIN32: call i8* @llvm.stacksave()
-// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
+// WIN32: call x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"(%struct.A* %{{.*}})
// WIN32: store i1 true
-// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
-// WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"(%struct.A* %{{.*}})
+// WIN32: call i32 @"?TakesTwo@@YAHUA@@0@Z"
//
// WIN32: call void @llvm.stackrestore
//
-// WIN32: call i32 @"\01?CouldThrow@@YAHXZ"()
+// WIN32: call i32 @"?CouldThrow@@YAHXZ"()
//
// Only one dtor in the invoke for arg1
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
-// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
+// WIN32-NOT: invoke x86_thiscallcc void @"??1A@@QAE@XZ"
// WIN32: }
// Now test both.
@@ -95,7 +95,7 @@
return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
}
-// WIN32-O0-LABEL: define dso_local i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
+// WIN32-O0-LABEL: define dso_local i32 @"?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
// WIN32-O0: alloca i1
// WIN32-O0: %[[arg1_cond:.*]] = alloca i1
// Start all four cleanups as deactivated.
@@ -105,32 +105,32 @@
// WIN32-O0: store i1 false
// WIN32-O0: br i1
// True condition.
-// WIN32-O0: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O0: call x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O0: store i1 true
-// WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
-// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O0: invoke void @"?TakeRef@@YAXABUA@@@Z"
+// WIN32-O0: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O0: store i1 true, i1* %[[arg1_cond]]
-// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O0: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O0: store i1 true
-// WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
-// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O0: invoke void @"?TakeRef@@YAXABUA@@@Z"
+// WIN32-O0: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O0: store i1 true
// WIN32-O0: store i1 false, i1* %[[arg1_cond]]
-// WIN32-O0: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32-O0: invoke i32 @"?TakesTwo@@YAHUA@@0@Z"
// False condition.
-// WIN32-O0: invoke i32 @"\01?CouldThrow@@YAHXZ"()
+// WIN32-O0: invoke i32 @"?CouldThrow@@YAHXZ"()
// Two normal cleanups for TakeRef args.
-// WIN32-O0: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
-// WIN32-O0-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32-O0: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
+// WIN32-O0-NOT: invoke x86_thiscallcc void @"??1A@@QAE@XZ"
// WIN32-O0: ret i32
//
// Somewhere in the landing pad soup, we conditionally destroy arg1.
// WIN32-O0: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]]
// WIN32-O0: br i1 %[[isactive]]
-// WIN32-O0: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
+// WIN32-O0: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
// WIN32-O0: }
-// WIN32-O3-LABEL: define dso_local i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
+// WIN32-O3-LABEL: define dso_local i32 @"?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
// WIN32-O3: alloca i1
// WIN32-O3: alloca i1
// WIN32-O3: %[[arg1_cond:.*]] = alloca i1
@@ -143,29 +143,29 @@
// WIN32-O3: store i1 false
// WIN32-O3: br i1
// True condition.
-// WIN32-O3: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O3: call x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O3: store i1 true
-// WIN32-O3: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
-// WIN32-O3: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O3: invoke void @"?TakeRef@@YAXABUA@@@Z"
+// WIN32-O3: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O3: store i1 true, i1* %[[arg1_cond]]
-// WIN32-O3: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O3: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O3: store i1 true
-// WIN32-O3: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
-// WIN32-O3: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32-O3: invoke void @"?TakeRef@@YAXABUA@@@Z"
+// WIN32-O3: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ"
// WIN32-O3: store i1 true
// WIN32-O3: store i1 false, i1* %[[arg1_cond]]
-// WIN32-O3: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32-O3: invoke i32 @"?TakesTwo@@YAHUA@@0@Z"
// False condition.
-// WIN32-O3: invoke i32 @"\01?CouldThrow@@YAHXZ"()
+// WIN32-O3: invoke i32 @"?CouldThrow@@YAHXZ"()
// Two normal cleanups for TakeRef args.
-// WIN32-O3: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
-// WIN32-O3-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32-O3: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
+// WIN32-O3-NOT: invoke x86_thiscallcc void @"??1A@@QAE@XZ"
// WIN32-O3: ret i32
//
// Somewhere in the landing pad soup, we conditionally destroy arg1.
// WIN32-O3: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]]
// WIN32-O3: br i1 %[[isactive]]
-// WIN32-O3: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
+// WIN32-O3: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}})
// WIN32-O3: }
namespace crash_on_partial_destroy {
@@ -187,7 +187,7 @@
// Verify that we don't bother with a vbtable lookup when adjusting the this
// pointer to call a base destructor from a constructor while unwinding.
-// WIN32-LABEL: define dso_local {{.*}} @"\01??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} {
+// WIN32-LABEL: define dso_local {{.*}} @"??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} {
// WIN32: cleanuppad
//
// We shouldn't do any vbptr loads, just constant GEPs.
@@ -195,7 +195,7 @@
// WIN32: getelementptr i8, i8* %{{.*}}, i32 4
// WIN32-NOT: load
// WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"*
-// WIN32: call x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ"
+// WIN32: call x86_thiscallcc void @"??1B@crash_on_partial_destroy@@UAE@XZ"
//
// WIN32-NOT: load
// WIN32: bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8*
@@ -203,7 +203,7 @@
// WIN32: getelementptr inbounds i8, i8* %{{.*}}, i32 4
// WIN32-NOT: load
// WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
-// WIN32: call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}})
// WIN32: }
}
@@ -217,16 +217,16 @@
g();
}
-// WIN32-LABEL: define dso_local void @"\01?f@dont_call_terminate@@YAXXZ"()
-// WIN32: invoke void @"\01?g@dont_call_terminate@@YAXXZ"()
+// WIN32-LABEL: define dso_local void @"?f@dont_call_terminate@@YAXXZ"()
+// WIN32: invoke void @"?g@dont_call_terminate@@YAXXZ"()
// WIN32-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// WIN32: [[cont]]
-// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"??1C@dont_call_terminate@@QAE@XZ"({{.*}})
//
// WIN32: [[lpad]]
// WIN32-NEXT: cleanuppad
-// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"??1C@dont_call_terminate@@QAE@XZ"({{.*}})
}
namespace noexcept_false_dtor {
@@ -239,11 +239,11 @@
}
}
-// WIN32-LABEL: define dso_local void @"\01?f@noexcept_false_dtor@@YAXXZ"()
-// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"()
-// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
+// WIN32-LABEL: define dso_local void @"?f@noexcept_false_dtor@@YAXXZ"()
+// WIN32: invoke i32 @"?CouldThrow@@YAHXZ"()
+// WIN32: call x86_thiscallcc void @"??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
// WIN32: cleanuppad
-// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
+// WIN32: call x86_thiscallcc void @"??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
// WIN32: cleanupret
namespace lifetime_marker {
@@ -256,21 +256,21 @@
g();
}
-// WIN32-LIFETIME-LABEL: define dso_local void @"\01?f@lifetime_marker@@YAXXZ"()
+// WIN32-LIFETIME-LABEL: define dso_local void @"?f@lifetime_marker@@YAXXZ"()
// WIN32-LIFETIME: %[[c:.*]] = alloca %"struct.lifetime_marker::C"
// WIN32-LIFETIME: %[[bc0:.*]] = bitcast %"struct.lifetime_marker::C"* %c to i8*
// WIN32-LIFETIME: call void @llvm.lifetime.start.p0i8(i64 1, i8* %[[bc0]])
-// WIN32-LIFETIME: invoke void @"\01?g@lifetime_marker@@YAXXZ"()
+// WIN32-LIFETIME: invoke void @"?g@lifetime_marker@@YAXXZ"()
// WIN32-LIFETIME-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad0:[^ ]*]]
//
// WIN32-LIFETIME: [[cont]]
-// WIN32-LIFETIME: call x86_thiscallcc void @"\01??1C@lifetime_marker@@QAE@XZ"({{.*}})
+// WIN32-LIFETIME: call x86_thiscallcc void @"??1C@lifetime_marker@@QAE@XZ"({{.*}})
// WIN32-LIFETIME: %[[bc1:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8*
// WIN32-LIFETIME: call void @llvm.lifetime.end.p0i8(i64 1, i8* %[[bc1]])
//
// WIN32-LIFETIME: [[lpad0]]
// WIN32-LIFETIME-NEXT: cleanuppad
-// WIN32-LIFETIME: call x86_thiscallcc void @"\01??1C@lifetime_marker@@QAE@XZ"({{.*}})
+// WIN32-LIFETIME: call x86_thiscallcc void @"??1C@lifetime_marker@@QAE@XZ"({{.*}})
// WIN32-LIFETIME: cleanupret {{.*}} unwind label %[[lpad1:[^ ]*]]
//
// WIN32-LIFETIME: [[lpad1]]
@@ -293,7 +293,7 @@
};
class_0::class_0() {
- // WIN32: define dso_local x86_thiscallcc %struct.class_0* @"\01??0class_0@@QAE@XZ"(%struct.class_0* returned %this, i32 %is_most_derived)
+ // WIN32: define dso_local x86_thiscallcc %struct.class_0* @"??0class_0@@QAE@XZ"(%struct.class_0* returned %this, i32 %is_most_derived)
// WIN32: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
// WIN32: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
// WIN32: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
@@ -309,7 +309,7 @@
// WIN32-NEXT: %[[SHOULD_CALL_VBASE_DTOR:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
// WIN32-NEXT: br i1 %[[SHOULD_CALL_VBASE_DTOR]], label %[[DTOR_VBASE:.*]], label %[[SKIP_VBASE:.*]]
// WIN32: [[DTOR_VBASE]]
- // WIN32-NEXT: call x86_thiscallcc void @"\01??1class_2@@UAE@XZ"
+ // WIN32-NEXT: call x86_thiscallcc void @"??1class_2@@UAE@XZ"
// WIN32: br label %[[SKIP_VBASE]]
// WIN32: [[SKIP_VBASE]]
}
diff --git a/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp b/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
index 9c60ceb..394b834 100644
--- a/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
+++ b/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
@@ -6,11 +6,11 @@
may_throw();
}
-// CHECK-LABEL: define dso_local void @"\01?never_throws@@YAXXZ"()
+// CHECK-LABEL: define dso_local void @"?never_throws@@YAXXZ"()
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
-// CHECK: invoke void @"\01?may_throw@@YAXXZ"()
+// CHECK: invoke void @"?may_throw@@YAXXZ"()
// CHECK: %[[cp:.*]] = cleanuppad within none []
-// MSVC2013: call void @"\01?terminate@@YAXXZ"()
+// MSVC2013: call void @"?terminate@@YAXXZ"()
// MSVC2015: call void @__std_terminate()
// CHECK-SAME: [ "funclet"(token %[[cp]]) ]
// CHECK-NEXT: unreachable
diff --git a/test/CodeGenCXX/microsoft-abi-extern-template.cpp b/test/CodeGenCXX/microsoft-abi-extern-template.cpp
index 2576875..8359236 100644
--- a/test/CodeGenCXX/microsoft-abi-extern-template.cpp
+++ b/test/CodeGenCXX/microsoft-abi-extern-template.cpp
@@ -3,17 +3,17 @@
// Even though Foo<int> has an extern template declaration, we have to emit our
// own copy the vftable when emitting the available externally constructor.
-// CHECK: @"\01??_7?$Foo@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [
-// CHECK-SAME: i8* bitcast (i8* (%struct.Foo*, i32)* @"\01??_G?$Foo@H@@UEAAPEAXI@Z" to i8*)
+// CHECK: @"??_7?$Foo@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [
+// CHECK-SAME: i8* bitcast (i8* (%struct.Foo*, i32)* @"??_G?$Foo@H@@UEAAPEAXI@Z" to i8*)
// CHECK-SAME: ] }, comdat
-// CHECK-LABEL: define dso_local %struct.Foo* @"\01?f@@YAPEAU?$Foo@H@@XZ"()
-// CHECK: call %struct.Foo* @"\01??0?$Foo@H@@QEAA@XZ"(%struct.Foo* %{{.*}})
+// CHECK-LABEL: define dso_local %struct.Foo* @"?f@@YAPEAU?$Foo@H@@XZ"()
+// CHECK: call %struct.Foo* @"??0?$Foo@H@@QEAA@XZ"(%struct.Foo* %{{.*}})
-// CHECK: define available_externally dso_local %struct.Foo* @"\01??0?$Foo@H@@QEAA@XZ"(%struct.Foo* returned %this)
-// CHECK: store {{.*}} @"\01??_7?$Foo@H@@6B@"
+// CHECK: define available_externally dso_local %struct.Foo* @"??0?$Foo@H@@QEAA@XZ"(%struct.Foo* returned %this)
+// CHECK: store {{.*}} @"??_7?$Foo@H@@6B@"
-// CHECK: define linkonce_odr dso_local i8* @"\01??_G?$Foo@H@@UEAAPEAXI@Z"(%struct.Foo* %this, i32 %should_call_delete)
+// CHECK: define linkonce_odr dso_local i8* @"??_G?$Foo@H@@UEAAPEAXI@Z"(%struct.Foo* %this, i32 %should_call_delete)
struct Base {
virtual ~Base();
diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
index 47ee9ac..0f54d30 100644
--- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
@@ -15,17 +15,17 @@
struct PR26313_Z;
int PR26313_Z::**a = nullptr;
int PR26313_Z::*b = *a;
-// CHECK-DAG: @"\01?a@@3PAPQPR26313_Z@@HA" = dso_local global %0* null, align 4
-// CHECK-DAG: @"\01?b@@3PQPR26313_Z@@HQ1@" = dso_local global { i32, i32, i32 } { i32 0, i32 0, i32 -1 }, align 4
+// CHECK-DAG: @"?a@@3PAPQPR26313_Z@@HA" = dso_local global %0* null, align 4
+// CHECK-DAG: @"?b@@3PQPR26313_Z@@HQ1@" = dso_local global { i32, i32, i32 } { i32 0, i32 0, i32 -1 }, align 4
namespace PR20947 {
struct A;
int A::**a = nullptr;
-// CHECK-DAG: @"\01?a@PR20947@@3PAPQA@1@HA" = dso_local global %{{.*}}* null, align 4
+// CHECK-DAG: @"?a@PR20947@@3PAPQA@1@HA" = dso_local global %{{.*}}* null, align 4
struct B;
int B::*&b = b;
-// CHECK-DAG: @"\01?b@PR20947@@3AAPQB@1@HA" = dso_local global %{{.*}}* null, align 4
+// CHECK-DAG: @"?b@PR20947@@3AAPQB@1@HA" = dso_local global %{{.*}}* null, align 4
}
namespace PR20017 {
@@ -35,7 +35,7 @@
};
struct B;
auto a = &A<B>::m_fn1;
-// CHECK-DAG: @"\01?a@PR20017@@3P8?$A@UB@PR20017@@@1@AEPQB@1@HXZQ21@" = dso_local global i8* bitcast ({ i32, i32, i32 } ({{.*}}*)* @"\01?m_fn1@?$A@UB@PR20017@@@PR20017@@QAEPQB@2@HXZ" to i8*), align 4
+// CHECK-DAG: @"?a@PR20017@@3P8?$A@UB@PR20017@@@1@AEPQB@1@HXZQ21@" = dso_local global i8* bitcast ({ i32, i32, i32 } ({{.*}}*)* @"?m_fn1@?$A@UB@PR20017@@@PR20017@@QAEPQB@2@HXZ" to i8*), align 4
}
#ifndef INCOMPLETE_VIRTUAL
@@ -89,24 +89,24 @@
int NonZeroVBPtr::*n_d_memptr;
int Unspecified::*u_d_memptr;
int UnspecSingle::*us_d_memptr;
-// CHECK: @"\01?s_d_memptr@@3PQSingle@@HQ1@" = dso_local global i32 -1, align 4
-// CHECK: @"\01?p_d_memptr@@3PQPolymorphic@@HQ1@" = dso_local global i32 0, align 4
-// CHECK: @"\01?m_d_memptr@@3PQMultiple@@HQ1@" = dso_local global i32 -1, align 4
-// CHECK: @"\01?v_d_memptr@@3PQVirtual@@HQ1@" = dso_local global { i32, i32 }
+// CHECK: @"?s_d_memptr@@3PQSingle@@HQ1@" = dso_local global i32 -1, align 4
+// CHECK: @"?p_d_memptr@@3PQPolymorphic@@HQ1@" = dso_local global i32 0, align 4
+// CHECK: @"?m_d_memptr@@3PQMultiple@@HQ1@" = dso_local global i32 -1, align 4
+// CHECK: @"?v_d_memptr@@3PQVirtual@@HQ1@" = dso_local global { i32, i32 }
// CHECK: { i32 0, i32 -1 }, align 4
-// CHECK: @"\01?n_d_memptr@@3PQNonZeroVBPtr@@HQ1@" = dso_local global { i32, i32 }
+// CHECK: @"?n_d_memptr@@3PQNonZeroVBPtr@@HQ1@" = dso_local global { i32, i32 }
// CHECK: { i32 0, i32 -1 }, align 4
-// CHECK: @"\01?u_d_memptr@@3PQUnspecified@@HQ1@" = dso_local global { i32, i32, i32 }
+// CHECK: @"?u_d_memptr@@3PQUnspecified@@HQ1@" = dso_local global { i32, i32, i32 }
// CHECK: { i32 0, i32 0, i32 -1 }, align 4
-// CHECK: @"\01?us_d_memptr@@3PQUnspecSingle@@HQ1@" = dso_local global { i32, i32, i32 }
+// CHECK: @"?us_d_memptr@@3PQUnspecSingle@@HQ1@" = dso_local global { i32, i32, i32 }
// CHECK: { i32 0, i32 0, i32 -1 }, align 4
void (Single ::*s_f_memptr)();
void (Multiple::*m_f_memptr)();
void (Virtual ::*v_f_memptr)();
-// CHECK: @"\01?s_f_memptr@@3P8Single@@AEXXZQ1@" = dso_local global i8* null, align 4
-// CHECK: @"\01?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = dso_local global { i8*, i32 } zeroinitializer, align 4
-// CHECK: @"\01?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = dso_local global { i8*, i32, i32 } zeroinitializer, align 4
+// CHECK: @"?s_f_memptr@@3P8Single@@AEXXZQ1@" = dso_local global i8* null, align 4
+// CHECK: @"?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = dso_local global { i8*, i32 } zeroinitializer, align 4
+// CHECK: @"?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = dso_local global { i8*, i32, i32 } zeroinitializer, align 4
// We can define Unspecified after locking in the inheritance model.
struct Unspecified : Multiple, Virtual {
@@ -125,16 +125,16 @@
void (Virtual ::*v_f_mp)() = &Virtual::foo;
void (Unspecified::*u_f_mp)() = &Unspecified::foo;
void (UnspecSingle::*us_f_mp)() = &UnspecSingle::foo;
-// CHECK: @"\01?s_f_mp@Const@@3P8Single@@AEXXZQ2@" =
-// CHECK: global i8* bitcast ({{.*}} @"\01?foo@Single@@QAEXXZ" to i8*), align 4
-// CHECK: @"\01?m_f_mp@Const@@3P8Multiple@@AEXXZQ2@" =
-// CHECK: global { i8*, i32 } { i8* bitcast ({{.*}} @"\01?foo@B2@@QAEXXZ" to i8*), i32 4 }, align 4
-// CHECK: @"\01?v_f_mp@Const@@3P8Virtual@@AEXXZQ2@" =
-// CHECK: global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 4
-// CHECK: @"\01?u_f_mp@Const@@3P8Unspecified@@AEXXZQ2@" =
-// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
-// CHECK: @"\01?us_f_mp@Const@@3P8UnspecSingle@@AEXXZQ2@" =
-// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
+// CHECK: @"?s_f_mp@Const@@3P8Single@@AEXXZQ2@" =
+// CHECK: global i8* bitcast ({{.*}} @"?foo@Single@@QAEXXZ" to i8*), align 4
+// CHECK: @"?m_f_mp@Const@@3P8Multiple@@AEXXZQ2@" =
+// CHECK: global { i8*, i32 } { i8* bitcast ({{.*}} @"?foo@B2@@QAEXXZ" to i8*), i32 4 }, align 4
+// CHECK: @"?v_f_mp@Const@@3P8Virtual@@AEXXZQ2@" =
+// CHECK: global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 4
+// CHECK: @"?u_f_mp@Const@@3P8Unspecified@@AEXXZQ2@" =
+// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
+// CHECK: @"?us_f_mp@Const@@3P8UnspecSingle@@AEXXZQ2@" =
+// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"?foo@UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
}
namespace CastParam {
@@ -150,16 +150,16 @@
struct C : B, A { int c; };
void (A::*ptr1)(void *) = (void (A::*)(void *)) &A::foo;
-// CHECK: @"\01?ptr1@CastParam@@3P8A@1@AEXPAX@ZQ21@" =
-// CHECK: global i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), align 4
+// CHECK: @"?ptr1@CastParam@@3P8A@1@AEXPAX@ZQ21@" =
+// CHECK: global i8* bitcast (void ({{.*}})* @"?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), align 4
// Try a reinterpret_cast followed by a memptr conversion.
void (C::*ptr2)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) &A::foo;
-// CHECK: @"\01?ptr2@CastParam@@3P8C@1@AEXPAX@ZQ21@" =
-// CHECK: global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 4
+// CHECK: @"?ptr2@CastParam@@3P8C@1@AEXPAX@ZQ21@" =
+// CHECK: global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 4
void (C::*ptr3)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) (void (A::*)(A *)) 0;
-// CHECK: @"\01?ptr3@CastParam@@3P8C@1@AEXPAX@ZQ21@" =
+// CHECK: @"?ptr3@CastParam@@3P8C@1@AEXPAX@ZQ21@" =
// CHECK: global { i8*, i32 } zeroinitializer, align 4
struct D : C {
@@ -170,11 +170,11 @@
// Try a cast that changes the inheritance model. Null for D is 0, but null for
// C is -1. We need the cast to long in order to hit the non-APValue path.
int C::*ptr4 = (int C::*) (int D::*) (long D::*) 0;
-// CHECK: @"\01?ptr4@CastParam@@3PQC@1@HQ21@" = dso_local global i32 -1, align 4
+// CHECK: @"?ptr4@CastParam@@3PQC@1@HQ21@" = dso_local global i32 -1, align 4
// MSVC rejects this but we accept it.
int C::*ptr5 = (int C::*) (long D::*) 0;
-// CHECK: @"\01?ptr5@CastParam@@3PQC@1@HQ21@" = dso_local global i32 -1, align 4
+// CHECK: @"?ptr5@CastParam@@3PQC@1@HQ21@" = dso_local global i32 -1, align 4
}
struct UnspecWithVBPtr;
@@ -191,23 +191,23 @@
void (Virtual ::*v_f_memptr)() = &Virtual::foo;
void (Unspecified::*u_f_memptr)() = &Unspecified::foo;
void (UnspecWithVBPtr::*u2_f_memptr)() = &UnspecWithVBPtr::foo;
-// CHECK: define dso_local void @"\01?EmitNonVirtualMemberPointers@@YAXXZ"() {{.*}} {
+// CHECK: define dso_local void @"?EmitNonVirtualMemberPointers@@YAXXZ"() {{.*}} {
// CHECK: alloca i8*, align 4
// CHECK: alloca { i8*, i32 }, align 4
// CHECK: alloca { i8*, i32, i32 }, align 4
// CHECK: alloca { i8*, i32, i32, i32 }, align 4
-// CHECK: store i8* bitcast (void (%{{.*}}*)* @"\01?foo@Single@@QAEXXZ" to i8*), i8** %{{.*}}, align 4
+// CHECK: store i8* bitcast (void (%{{.*}}*)* @"?foo@Single@@QAEXXZ" to i8*), i8** %{{.*}}, align 4
// CHECK: store { i8*, i32 }
-// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Multiple@@QAEXXZ" to i8*), i32 0 },
+// CHECK: { i8* bitcast (void (%{{.*}}*)* @"?foo@Multiple@@QAEXXZ" to i8*), i32 0 },
// CHECK: { i8*, i32 }* %{{.*}}, align 4
// CHECK: store { i8*, i32, i32 }
-// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 },
+// CHECK: { i8* bitcast (void (%{{.*}}*)* @"?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 },
// CHECK: { i8*, i32, i32 }* %{{.*}}, align 4
// CHECK: store { i8*, i32, i32, i32 }
-// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 },
+// CHECK: { i8* bitcast (void (%{{.*}}*)* @"?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 },
// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 4
// CHECK: store { i8*, i32, i32, i32 }
-// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@UnspecWithVBPtr@@QAEXXZ" to i8*),
+// CHECK: { i8* bitcast (void (%{{.*}}*)* @"?foo@UnspecWithVBPtr@@QAEXXZ" to i8*),
// CHECK: i32 0, i32 0, i32 0 },
// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 4
// CHECK: ret void
@@ -221,7 +221,7 @@
if (memptr)
memptr = 0;
// Check that member pointers use the right offsets and that null is -1.
-// CHECK: define dso_local void @"\01?podMemPtrs@@YAXXZ"() {{.*}} {
+// CHECK: define dso_local void @"?podMemPtrs@@YAXXZ"() {{.*}} {
// CHECK: %[[memptr:.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 0, i32* %[[memptr]], align 4
// CHECK-NEXT: store i32 4, i32* %[[memptr]], align 4
@@ -241,7 +241,7 @@
memptr = 0;
// Member pointers for polymorphic classes include the vtable slot in their
// offset and use 0 to represent null.
-// CHECK: define dso_local void @"\01?polymorphicMemPtrs@@YAXXZ"() {{.*}} {
+// CHECK: define dso_local void @"?polymorphicMemPtrs@@YAXXZ"() {{.*}} {
// CHECK: %[[memptr:.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 4, i32* %[[memptr]], align 4
// CHECK-NEXT: store i32 8, i32* %[[memptr]], align 4
@@ -255,7 +255,7 @@
bool nullTestDataUnspecified(int Unspecified::*mp) {
return mp;
-// CHECK: define dso_local zeroext i1 @"\01?nullTestDataUnspecified@@YA_NPQUnspecified@@H@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?nullTestDataUnspecified@@YA_NPQUnspecified@@H@Z"{{.*}} {
// CHECK: %{{.*}} = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
// CHECK: store { i32, i32, i32 } {{.*}} align 4
// CHECK: %[[mp:.*]] = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
@@ -271,13 +271,13 @@
// CHECK: }
// Pass this large type indirectly.
-// X64-LABEL: define dso_local zeroext i1 @"\01?nullTestDataUnspecified@@
+// X64-LABEL: define dso_local zeroext i1 @"?nullTestDataUnspecified@@
// X64: ({ i32, i32, i32 }*)
}
bool nullTestFunctionUnspecified(void (Unspecified::*mp)()) {
return mp;
-// CHECK: define dso_local zeroext i1 @"\01?nullTestFunctionUnspecified@@YA_NP8Unspecified@@AEXXZ@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?nullTestFunctionUnspecified@@YA_NP8Unspecified@@AEXXZ@Z"{{.*}} {
// CHECK: %{{.*}} = load { i8*, i32, i32, i32 }, { i8*, i32, i32, i32 }* %{{.*}}, align 4
// CHECK: store { i8*, i32, i32, i32 } {{.*}} align 4
// CHECK: %[[mp:.*]] = load { i8*, i32, i32, i32 }, { i8*, i32, i32, i32 }* %{{.*}}, align 4
@@ -291,7 +291,7 @@
return o->*memptr;
// Test that we can unpack this aggregate member pointer and load the member
// data pointer.
-// CHECK: define dso_local i32 @"\01?loadDataMemberPointerVirtual@@YAHPAUVirtual@@PQ1@H@Z"{{.*}} {
+// CHECK: define dso_local i32 @"?loadDataMemberPointerVirtual@@YAHPAUVirtual@@PQ1@H@Z"{{.*}} {
// CHECK: %[[o:.*]] = load %{{.*}}*, %{{.*}}** %{{.*}}, align 4
// CHECK: %[[memptr:.*]] = load { i32, i32 }, { i32, i32 }* %{{.*}}, align 4
// CHECK: %[[memptr0:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 0
@@ -312,7 +312,7 @@
// A two-field data memptr on x64 gets coerced to i64 and is passed in a
// register or memory.
-// X64-LABEL: define dso_local i32 @"\01?loadDataMemberPointerVirtual@@YAHPEAUVirtual@@PEQ1@H@Z"
+// X64-LABEL: define dso_local i32 @"?loadDataMemberPointerVirtual@@YAHPEAUVirtual@@PEQ1@H@Z"
// X64: (%struct.Virtual* %o, i64 %memptr.coerce)
}
@@ -320,7 +320,7 @@
return o->*memptr;
// Test that we can unpack this aggregate member pointer and load the member
// data pointer.
-// CHECK: define dso_local i32 @"\01?loadDataMemberPointerUnspecified@@YAHPAUUnspecified@@PQ1@H@Z"{{.*}} {
+// CHECK: define dso_local i32 @"?loadDataMemberPointerUnspecified@@YAHPAUUnspecified@@PQ1@H@Z"{{.*}} {
// CHECK: %[[o:.*]] = load %{{.*}}*, %{{.*}}** %{{.*}}, align 4
// CHECK: %[[memptr:.*]] = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
// CHECK: %[[memptr0:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 0
@@ -351,12 +351,12 @@
void callMemberPointerSingle(Single *o, void (Single::*memptr)()) {
(o->*memptr)();
// Just look for an indirect thiscall.
-// CHECK: define dso_local void @"\01?callMemberPointerSingle@@{{.*}} {{.*}} {
+// CHECK: define dso_local void @"?callMemberPointerSingle@@{{.*}} {{.*}} {
// CHECK: call x86_thiscallcc void %{{.*}}(%{{.*}} %{{.*}})
// CHECK: ret void
// CHECK: }
-// X64-LABEL: define dso_local void @"\01?callMemberPointerSingle@@
+// X64-LABEL: define dso_local void @"?callMemberPointerSingle@@
// X64: (%struct.Single* %o, i8* %memptr)
// X64: bitcast i8* %{{[^ ]*}} to void (%struct.Single*)*
// X64: ret void
@@ -364,7 +364,7 @@
void callMemberPointerMultiple(Multiple *o, void (Multiple::*memptr)()) {
(o->*memptr)();
-// CHECK: define dso_local void @"\01?callMemberPointerMultiple@@{{.*}} {
+// CHECK: define dso_local void @"?callMemberPointerMultiple@@{{.*}} {
// CHECK: %[[memptr0:.*]] = extractvalue { i8*, i32 } %{{.*}}, 0
// CHECK: %[[memptr1:.*]] = extractvalue { i8*, i32 } %{{.*}}, 1
// CHECK: %[[this_adjusted:.*]] = getelementptr inbounds i8, i8* %{{.*}}, i32 %[[memptr1]]
@@ -378,7 +378,7 @@
void callMemberPointerVirtualBase(Virtual *o, void (Virtual::*memptr)()) {
(o->*memptr)();
// This shares a lot with virtual data member pointers.
-// CHECK: define dso_local void @"\01?callMemberPointerVirtualBase@@{{.*}} {
+// CHECK: define dso_local void @"?callMemberPointerVirtualBase@@{{.*}} {
// CHECK: %[[memptr0:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 0
// CHECK: %[[memptr1:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 1
// CHECK: %[[memptr2:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 2
@@ -400,21 +400,21 @@
bool compareSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) {
return l == r;
// Should only be one comparison here.
-// CHECK: define dso_local zeroext i1 @"\01?compareSingleFunctionMemptr@@YA_NP8Single@@AEXXZ0@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?compareSingleFunctionMemptr@@YA_NP8Single@@AEXXZ0@Z"{{.*}} {
// CHECK-NOT: icmp
// CHECK: %[[r:.*]] = icmp eq
// CHECK-NOT: icmp
// CHECK: ret i1 %[[r]]
// CHECK: }
-// X64-LABEL: define dso_local zeroext i1 @"\01?compareSingleFunctionMemptr@@
+// X64-LABEL: define dso_local zeroext i1 @"?compareSingleFunctionMemptr@@
// X64: (i8* %{{[^,]*}}, i8* %{{[^)]*}})
}
bool compareNeqSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) {
return l != r;
// Should only be one comparison here.
-// CHECK: define dso_local zeroext i1 @"\01?compareNeqSingleFunctionMemptr@@YA_NP8Single@@AEXXZ0@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?compareNeqSingleFunctionMemptr@@YA_NP8Single@@AEXXZ0@Z"{{.*}} {
// CHECK-NOT: icmp
// CHECK: %[[r:.*]] = icmp ne
// CHECK-NOT: icmp
@@ -424,7 +424,7 @@
bool unspecFuncMemptrEq(void (Unspecified::*l)(), void (Unspecified::*r)()) {
return l == r;
-// CHECK: define dso_local zeroext i1 @"\01?unspecFuncMemptrEq@@YA_NP8Unspecified@@AEXXZ0@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?unspecFuncMemptrEq@@YA_NP8Unspecified@@AEXXZ0@Z"{{.*}} {
// CHECK: %[[lhs0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[l:.*]], 0
// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r:.*]], 0
// CHECK: %[[cmp0:.*]] = icmp eq i8* %[[lhs0]], %{{.*}}
@@ -445,13 +445,13 @@
// CHECK: ret i1 %{{.*}}
// CHECK: }
-// X64-LABEL: define dso_local zeroext i1 @"\01?unspecFuncMemptrEq@@
+// X64-LABEL: define dso_local zeroext i1 @"?unspecFuncMemptrEq@@
// X64: ({ i8*, i32, i32, i32 }*, { i8*, i32, i32, i32 }*)
}
bool unspecFuncMemptrNeq(void (Unspecified::*l)(), void (Unspecified::*r)()) {
return l != r;
-// CHECK: define dso_local zeroext i1 @"\01?unspecFuncMemptrNeq@@YA_NP8Unspecified@@AEXXZ0@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?unspecFuncMemptrNeq@@YA_NP8Unspecified@@AEXXZ0@Z"{{.*}} {
// CHECK: %[[lhs0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[l:.*]], 0
// CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r:.*]], 0
// CHECK: %[[cmp0:.*]] = icmp ne i8* %[[lhs0]], %{{.*}}
@@ -475,7 +475,7 @@
bool unspecDataMemptrEq(int Unspecified::*l, int Unspecified::*r) {
return l == r;
-// CHECK: define dso_local zeroext i1 @"\01?unspecDataMemptrEq@@YA_NPQUnspecified@@H0@Z"{{.*}} {
+// CHECK: define dso_local zeroext i1 @"?unspecDataMemptrEq@@YA_NPQUnspecified@@H0@Z"{{.*}} {
// CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 0
// CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 0
// CHECK: icmp eq i32
@@ -490,13 +490,13 @@
// CHECK: ret i1
// CHECK: }
-// X64-LABEL: define dso_local zeroext i1 @"\01?unspecDataMemptrEq@@
+// X64-LABEL: define dso_local zeroext i1 @"?unspecDataMemptrEq@@
// X64: ({ i32, i32, i32 }*, { i32, i32, i32 }*)
}
void (Multiple::*convertB2FuncToMultiple(void (B2::*mp)()))() {
return mp;
-// CHECK: define dso_local i64 @"\01?convertB2FuncToMultiple@@YAP8Multiple@@AEXXZP8B2@@AEXXZ@Z"{{.*}} {
+// CHECK: define dso_local i64 @"?convertB2FuncToMultiple@@YAP8Multiple@@AEXXZP8B2@@AEXXZ@Z"{{.*}} {
// CHECK: store
// CHECK: %[[mp:.*]] = load i8*, i8** %{{.*}}, align 4
// CHECK: icmp ne i8* %[[mp]], null
@@ -520,7 +520,7 @@
// LLVM from optimizing away the branch. This is likely a bug in
// lib/CodeGen/TargetInfo.cpp with how we classify memptr types for returns.
//
-// CHECK: define dso_local i32 @"\01?convertMultipleFuncToB2@@YAP8B2@@AEXXZP8Multiple@@AEXXZ@Z"{{.*}} {
+// CHECK: define dso_local i32 @"?convertMultipleFuncToB2@@YAP8B2@@AEXXZP8Multiple@@AEXXZ@Z"{{.*}} {
// CHECK: store
// CHECK: %[[src:.*]] = load { i8*, i32 }, { i8*, i32 }* %{{.*}}, align 4
// CHECK: extractvalue { i8*, i32 } %[[src]], 0
@@ -545,7 +545,7 @@
void (D::*convertCToD(void (C::*mp)()))() {
return mp;
-// CHECK: define dso_local void @"\01?convertCToD@Test1@@YAP8D@1@AEXXZP8C@1@AEXXZ@Z"{{.*}} {
+// CHECK: define dso_local void @"?convertCToD@Test1@@YAP8D@1@AEXXZP8C@1@AEXXZ@Z"{{.*}} {
// CHECK: store
// CHECK: load { i8*, i32, i32 }, { i8*, i32, i32 }* %{{.*}}, align 4
// CHECK: extractvalue { i8*, i32, i32 } %{{.*}}, 0
@@ -585,7 +585,7 @@
int A::*reinterpret(int B::*mp) {
return reinterpret_cast<int A::*>(mp);
-// CHECK: define dso_local i32 @"\01?reinterpret@Test2@@YAPQA@1@HPQB@1@H@Z"{{.*}} {
+// CHECK: define dso_local i32 @"?reinterpret@Test2@@YAPQA@1@HPQB@1@H@Z"{{.*}} {
// CHECK-NOT: select
// CHECK: ret i32
// CHECK: }
@@ -593,7 +593,7 @@
int A::*reinterpret(int C::*mp) {
return reinterpret_cast<int A::*>(mp);
-// CHECK: define dso_local i32 @"\01?reinterpret@Test2@@YAPQA@1@HPQC@1@H@Z"{{.*}} {
+// CHECK: define dso_local i32 @"?reinterpret@Test2@@YAPQA@1@HPQC@1@H@Z"{{.*}} {
// CHECK: %[[mp:.*]] = load i32, i32*
// CHECK: %[[cmp:.*]] = icmp ne i32 %[[mp]], 0
// CHECK: select i1 %[[cmp]], i32 %[[mp]], i32 -1
@@ -612,7 +612,7 @@
int *load_data(A *a, int A::*mp) {
return &(a->*mp);
-// CHECK-LABEL: define dso_local i32* @"\01?load_data@Test3@@YAPAHPAUA@1@PQ21@H@Z"{{.*}} {
+// CHECK-LABEL: define dso_local i32* @"?load_data@Test3@@YAPAHPAUA@1@PQ21@H@Z"{{.*}} {
// CHECK: %[[a:.*]] = load %"struct.Test3::A"*, %"struct.Test3::A"** %{{.*}}, align 4
// CHECK: %[[mp:.*]] = load i32, i32* %{{.*}}, align 4
// CHECK: %[[a_i8:.*]] = bitcast %"struct.Test3::A"* %[[a]] to i8*
@@ -631,11 +631,11 @@
void (C::*getmp())() {
return &C::g;
}
-// CHECK-LABEL: define dso_local i64 @"\01?getmp@Test4@@YAP8C@1@AEXXZXZ"()
-// CHECK: store { i8*, i32 } { i8* bitcast (void (%"struct.Test4::C"*, ...)* @"\01??_9C@Test4@@$BA@AE" to i8*), i32 4 }, { i8*, i32 }* %{{.*}}
+// CHECK-LABEL: define dso_local i64 @"?getmp@Test4@@YAP8C@1@AEXXZXZ"()
+// CHECK: store { i8*, i32 } { i8* bitcast (void (%"struct.Test4::C"*, ...)* @"??_9C@Test4@@$BA@AE" to i8*), i32 4 }, { i8*, i32 }* %{{.*}}
//
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@Test4@@$BA@AE"(%"struct.Test4::C"* %this, ...) {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@Test4@@$BA@AE"(%"struct.Test4::C"* %this, ...) {{.*}} comdat
// CHECK-NOT: getelementptr
// CHECK: load void (%"struct.Test4::C"*, ...)**, void (%"struct.Test4::C"*, ...)*** %{{.*}}
// CHECK: getelementptr inbounds void (%"struct.Test4::C"*, ...)*, void (%"struct.Test4::C"*, ...)** %{{.*}}, i64 0
@@ -651,8 +651,8 @@
};
struct B : public A {};
void test() { void (B::*a)() = &B::f; }
-// CHECK-LABEL: define dso_local void @"\01?test@pr20007@@YAXXZ"
-// CHECK: store i8* bitcast (void (%"struct.pr20007::A"*)* @"\01?f@A@pr20007@@QAEXXZ" to i8*)
+// CHECK-LABEL: define dso_local void @"?test@pr20007@@YAXXZ"
+// CHECK: store i8* bitcast (void (%"struct.pr20007::A"*)* @"?f@A@pr20007@@QAEXXZ" to i8*)
}
namespace pr20007_kw {
@@ -663,8 +663,8 @@
struct __single_inheritance B;
struct B : public A {};
void test() { void (B::*a)() = &B::f; }
-// CHECK-LABEL: define dso_local void @"\01?test@pr20007_kw@@YAXXZ"
-// CHECK: store i8* bitcast (void (%"struct.pr20007_kw::A"*)* @"\01?f@A@pr20007_kw@@QAEXXZ" to i8*)
+// CHECK-LABEL: define dso_local void @"?test@pr20007_kw@@YAXXZ"
+// CHECK: store i8* bitcast (void (%"struct.pr20007_kw::A"*)* @"?f@A@pr20007_kw@@QAEXXZ" to i8*)
}
namespace pr20007_pragma {
@@ -678,7 +678,7 @@
static_assert(sizeof(int B::*) == 4, "");
static_assert(sizeof(int A::*) == 4, "");
#pragma pointers_to_members(best_case)
-// CHECK-LABEL: define dso_local void @"\01?test@pr20007_pragma@@YAXXZ"
+// CHECK-LABEL: define dso_local void @"?test@pr20007_pragma@@YAXXZ"
}
namespace pr20007_pragma2 {
@@ -692,7 +692,7 @@
static_assert(sizeof(int B::*) == 4, "");
static_assert(sizeof(int A::*) == 12, "");
#pragma pointers_to_members(best_case)
-// CHECK-LABEL: define dso_local void @"\01?test@pr20007_pragma2@@YAXXZ"
+// CHECK-LABEL: define dso_local void @"?test@pr20007_pragma2@@YAXXZ"
}
namespace pr23823 {
@@ -738,8 +738,8 @@
typedef void (D::*DMemPtrTy)();
-// CHECK-LABEL: define dso_local void @"\01?get_memptr@pr23878@@YAP8D@1@AEXXZXZ"
-// CHECK: @"\01??_9C@pr23878@@$BA@AE" to i8*), i32 0, i32 4
+// CHECK-LABEL: define dso_local void @"?get_memptr@pr23878@@YAP8D@1@AEXXZXZ"
+// CHECK: @"??_9C@pr23878@@$BA@AE" to i8*), i32 0, i32 4
DMemPtrTy get_memptr() { return &D::f; }
}
@@ -755,14 +755,14 @@
// CHECK-LABEL: foo_fun
void foo_fun() {
- // CHECK: store i8* bitcast (void (%class.CA*)* @"\01?OnHelp@CA@@QAEXXZ" to i8*), i8**
+ // CHECK: store i8* bitcast (void (%class.CA*)* @"?OnHelp@CA@@QAEXXZ" to i8*), i8**
f func = (f)&CA::OnHelp;
}
namespace PR24703 {
struct S;
void f(int S::*&p) {}
-// CHECK-LABEL: define dso_local void @"\01?f@PR24703@@YAXAAPQS@1@H@Z"(
+// CHECK-LABEL: define dso_local void @"?f@PR24703@@YAXAAPQS@1@H@Z"(
}
namespace ReferenceToMPTWithIncompleteClass {
@@ -771,14 +771,14 @@
struct K;
extern K *k;
-// CHECK-LABEL: @"\01?f@ReferenceToMPTWithIncompleteClass@@YAIAAPQS@1@H@Z"(
+// CHECK-LABEL: @"?f@ReferenceToMPTWithIncompleteClass@@YAIAAPQS@1@H@Z"(
// CHECK: ret i32 12
unsigned f(int S::*&p) { return sizeof p; }
-// CHECK-LABEL: @"\01?g@ReferenceToMPTWithIncompleteClass@@YA_NAAPQJ@1@H0@Z"(
+// CHECK-LABEL: @"?g@ReferenceToMPTWithIncompleteClass@@YA_NAAPQJ@1@H0@Z"(
bool g(int J::*&p, int J::*&q) { return p == q; }
-// CHECK-LABEL: @"\01?h@ReferenceToMPTWithIncompleteClass@@YAHAAPQK@1@H@Z"(
+// CHECK-LABEL: @"?h@ReferenceToMPTWithIncompleteClass@@YAHAAPQK@1@H@Z"(
int h(int K::*&p) { return k->*p; }
}
@@ -790,5 +790,5 @@
void printd();
};
void A::printd() { JSMethod<A, &A::printd>(); }
-// CHECK-LABEL: @"\01??$JSMethod@VA@PMFInTemplateArgument@@$1?printd@12@AAEHH@Z@PMFInTemplateArgument@@YAXXZ"(
+// CHECK-LABEL: @"??$JSMethod@VA@PMFInTemplateArgument@@$1?printd@12@AAEHH@Z@PMFInTemplateArgument@@YAXXZ"(
}
diff --git a/test/CodeGenCXX/microsoft-abi-methods.cpp b/test/CodeGenCXX/microsoft-abi-methods.cpp
index 6dbbf45..f4186a2 100644
--- a/test/CodeGenCXX/microsoft-abi-methods.cpp
+++ b/test/CodeGenCXX/microsoft-abi-methods.cpp
@@ -18,11 +18,11 @@
instance.simple_method();
// Make sure that the call uses the right calling convention:
-// CHECK: call x86_thiscallcc void @"\01?simple_method@C@@QAEXXZ"
+// CHECK: call x86_thiscallcc void @"?simple_method@C@@QAEXXZ"
// CHECK: ret
// Make sure that the definition uses the right calling convention:
-// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"\01?simple_method@C@@QAEXXZ"
+// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"?simple_method@C@@QAEXXZ"
// CHECK: ret
}
@@ -30,11 +30,11 @@
C instance;
instance.cdecl_method();
// Make sure that the call uses the right calling convention:
-// CHECK: call void @"\01?cdecl_method@C@@QAAXXZ"
+// CHECK: call void @"?cdecl_method@C@@QAAXXZ"
// CHECK: ret
// Make sure that the definition uses the right calling convention:
-// CHECK: define linkonce_odr dso_local void @"\01?cdecl_method@C@@QAAXXZ"
+// CHECK: define linkonce_odr dso_local void @"?cdecl_method@C@@QAAXXZ"
// CHECK: ret
}
@@ -42,21 +42,21 @@
C instance;
instance.vararg_method("Hello");
// Make sure that the call uses the right calling convention:
-// CHECK: call void (%class.C*, i8*, ...) @"\01?vararg_method@C@@QAAXPBDZZ"
+// CHECK: call void (%class.C*, i8*, ...) @"?vararg_method@C@@QAAXPBDZZ"
// CHECK: ret
// Make sure that the definition uses the right calling convention:
-// CHECK: define linkonce_odr dso_local void @"\01?vararg_method@C@@QAAXPBDZZ"
+// CHECK: define linkonce_odr dso_local void @"?vararg_method@C@@QAAXPBDZZ"
}
void call_static_method() {
C::static_method();
// Make sure that the call uses the right calling convention:
-// CHECK: call void @"\01?static_method@C@@SAXXZ"
+// CHECK: call void @"?static_method@C@@SAXXZ"
// CHECK: ret
// Make sure that the definition uses the right calling convention:
-// CHECK: define linkonce_odr dso_local void @"\01?static_method@C@@SAXXZ"
+// CHECK: define linkonce_odr dso_local void @"?static_method@C@@SAXXZ"
}
class Base {
@@ -71,19 +71,19 @@
Child c;
// Make sure that the Base constructor call in the Child constructor uses
// the right calling convention:
-// CHECK: define linkonce_odr dso_local x86_thiscallcc %class.Child* @"\01??0Child@@QAE@XZ"
-// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %class.Base* @"\01??0Base@@QAE@XZ"
+// CHECK: define linkonce_odr dso_local x86_thiscallcc %class.Child* @"??0Child@@QAE@XZ"
+// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %class.Base* @"??0Base@@QAE@XZ"
// CHECK: ret
-// Make sure that the Base constructor definition uses the right CC:
-// CHECK: define linkonce_odr dso_local x86_thiscallcc %class.Base* @"\01??0Base@@QAE@XZ"
-
// Make sure that the Base destructor call in the Child denstructor uses
// the right calling convention:
-// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"\01??1Child@@QAE@XZ"
-// CHECK: call x86_thiscallcc void @"\01??1Base@@QAE@XZ"
+// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"??1Child@@QAE@XZ"
+// CHECK: call x86_thiscallcc void @"??1Base@@QAE@XZ"
// CHECK: ret
+// Make sure that the Base constructor definition uses the right CC:
+// CHECK: define linkonce_odr dso_local x86_thiscallcc %class.Base* @"??0Base@@QAE@XZ"
+
// Make sure that the Base destructor definition uses the right CC:
-// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"\01??1Base@@QAE@XZ"
+// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"??1Base@@QAE@XZ"
}
diff --git a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
index 6dc0158..cefbdaf 100644
--- a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
@@ -19,7 +19,7 @@
extern "C" void foo(void *);
void call_left_no_override(ChildNoOverride *child) {
-// CHECK-LABEL: define dso_local void @"\01?call_left_no_override
+// CHECK-LABEL: define dso_local void @"?call_left_no_override
// CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride
child->left();
@@ -34,7 +34,7 @@
}
void ChildOverride::left() {
-// CHECK-LABEL: define dso_local x86_thiscallcc void @"\01?left@ChildOverride@@UAEXXZ"
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"?left@ChildOverride@@UAEXXZ"
// CHECK-SAME: (%struct.ChildOverride* %[[THIS:.*]])
//
// No need to adjust 'this' as the ChildOverride's layout begins with Left.
@@ -49,7 +49,7 @@
}
void call_left_override(ChildOverride *child) {
-// CHECK-LABEL: define dso_local void @"\01?call_left_override
+// CHECK-LABEL: define dso_local void @"?call_left_override
// CHECK: %[[CHILD:.*]] = load %struct.ChildOverride
child->left();
@@ -63,7 +63,7 @@
}
void call_right_no_override(ChildNoOverride *child) {
-// CHECK-LABEL: define dso_local void @"\01?call_right_no_override
+// CHECK-LABEL: define dso_local void @"?call_right_no_override
// CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride
child->right();
@@ -83,7 +83,7 @@
}
void ChildOverride::right() {
-// CHECK-LABEL: define dso_local x86_thiscallcc void @"\01?right@ChildOverride@@UAEXXZ"(i8*
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"?right@ChildOverride@@UAEXXZ"(i8*
//
// ChildOverride::right gets 'this' cast to Right* in ECX (i.e. this+4) so we
// need to adjust 'this' before use.
@@ -106,7 +106,7 @@
}
void call_right_override(ChildOverride *child) {
-// CHECK-LABEL: define dso_local void @"\01?call_right_override
+// CHECK-LABEL: define dso_local void @"?call_right_override
// CHECK: %[[CHILD:.*]] = load %struct.ChildOverride
child->right();
@@ -132,7 +132,7 @@
};
void GrandchildOverride::right() {
-// CHECK-LABEL: define dso_local x86_thiscallcc void @"\01?right@GrandchildOverride@@UAEXXZ"(i8*
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"?right@GrandchildOverride@@UAEXXZ"(i8*
//
// CHECK: %[[THIS_STORE:.*]] = alloca %struct.GrandchildOverride*, align 4
// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.GrandchildOverride*, align 4
@@ -158,37 +158,37 @@
void emit_ctors() {
Left l;
- // CHECK-LABEL: define {{.*}} @"\01??0Left@@QAE@XZ"
+ // CHECK-LABEL: define {{.*}} @"??0Left@@QAE@XZ"
// CHECK-NOT: getelementptr
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7Left@@6B@" to i32 (...)**)
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7Left@@6B@" to i32 (...)**)
// CHECK: ret
Right r;
- // CHECK-LABEL: define {{.*}} @"\01??0Right@@QAE@XZ"
+ // CHECK-LABEL: define {{.*}} @"??0Right@@QAE@XZ"
// CHECK-NOT: getelementptr
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7Right@@6B@" to i32 (...)**)
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7Right@@6B@" to i32 (...)**)
// CHECK: ret
ChildOverride co;
- // CHECK-LABEL: define {{.*}} @"\01??0ChildOverride@@QAE@XZ"
+ // CHECK-LABEL: define {{.*}} @"??0ChildOverride@@QAE@XZ"
// CHECK: %[[THIS:.*]] = load %struct.ChildOverride*, %struct.ChildOverride**
// CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7ChildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7ChildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 4
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7ChildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7ChildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: ret
GrandchildOverride gc;
- // CHECK-LABEL: define {{.*}} @"\01??0GrandchildOverride@@QAE@XZ"
+ // CHECK-LABEL: define {{.*}} @"??0GrandchildOverride@@QAE@XZ"
// CHECK: %[[THIS:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride**
// CHECK: %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7GrandchildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7GrandchildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 4
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7GrandchildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7GrandchildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: ret
}
@@ -202,10 +202,10 @@
};
void call_asymmetric_child_complete_dtor() {
- // CHECK-LABEL: define dso_local void @"\01?call_asymmetric_child_complete_dtor@@YAXXZ"
+ // CHECK-LABEL: define dso_local void @"?call_asymmetric_child_complete_dtor@@YAXXZ"
AsymmetricChild obj;
- // CHECK: call x86_thiscallcc %struct.AsymmetricChild* @"\01??0AsymmetricChild@@QAE@XZ"(%struct.AsymmetricChild* %[[OBJ:.*]])
+ // CHECK: call x86_thiscallcc %struct.AsymmetricChild* @"??0AsymmetricChild@@QAE@XZ"(%struct.AsymmetricChild* %[[OBJ:.*]])
// CHECK-NOT: getelementptr
- // CHECK: call x86_thiscallcc void @"\01??1AsymmetricChild@@UAE@XZ"(%struct.AsymmetricChild* %[[OBJ]])
+ // CHECK: call x86_thiscallcc void @"??1AsymmetricChild@@UAE@XZ"(%struct.AsymmetricChild* %[[OBJ]])
// CHECK: ret
}
diff --git a/test/CodeGenCXX/microsoft-abi-rtti.cpp b/test/CodeGenCXX/microsoft-abi-rtti.cpp
index 5738b60..a9ec5f3 100644
--- a/test/CodeGenCXX/microsoft-abi-rtti.cpp
+++ b/test/CodeGenCXX/microsoft-abi-rtti.cpp
@@ -26,242 +26,242 @@
struct A2 : Z2, Y2 {};
struct B2 : virtual A2 { B2() {} virtual void f() {} } b2;
-// CHECK-DAG: @"\01??_R4B2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUB2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3B2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 4, %rtti.BaseClassDescriptor** getelementptr inbounds ([5 x %rtti.BaseClassDescriptor*], [5 x %rtti.BaseClassDescriptor*]* @"\01??_R2B2@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2B2@@8" = linkonce_odr constant [5 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B2@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A2@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@Z2@@8", %rtti.BaseClassDescriptor* @"\01??_R13A@3EA@Y2@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@B2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i8*), i32 3, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@A@3FA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUA2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3A2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 1, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*], [4 x %rtti.BaseClassDescriptor*]* @"\01??_R2A2@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2A2@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A2@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EA@Y2@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUZ2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3Z2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2Z2@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2Z2@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R13?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUY2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3Y2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2Y2@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2Y2@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y2@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@A@3EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" }, comdat
-// CHECK-DAG: @"\01??_R13A@3EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" }, comdat
-// CHECK-DAG: @"\01??_R4B2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 12, i32 8, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" }, comdat
-// CHECK-DAG: @"\01??_R4A2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" }, comdat
-// CHECK-DAG: @"\01??_R4A2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" }, comdat
-// CHECK-DAG: @"\01??_R4Y2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" }, comdat
-// CHECK-DAG: @"\01??_R4Z2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" }, comdat
-// CHECK-DAG: @"\01??_R4B1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUB1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3B1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"\01??_R2B1@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2B1@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A1@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@B1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@A@3FA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUA1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3A1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2A1@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2A1@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A1@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" }, comdat
-// CHECK-DAG: @"\01??_R4A1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" }, comdat
-// CHECK-DAG: @"\01??_R4Y1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUY1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3Y1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 6, %rtti.BaseClassDescriptor** getelementptr inbounds ([7 x %rtti.BaseClassDescriptor*], [7 x %rtti.BaseClassDescriptor*]* @"\01??_R2Y1@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2Y1@@8" = linkonce_odr constant [7 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@Y1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i8*), i32 5, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@W1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUW1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3W1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*], [4 x %rtti.BaseClassDescriptor*]* @"\01??_R2W1@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2W1@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@A@3FA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUV1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3V1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"\01??_R2V1@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2V1@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUX1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3X1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2X1@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2X1@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@A@3EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" }, comdat
-// CHECK-DAG: @"\01??_R4W1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" }, comdat
-// CHECK-DAG: @"\01??_R4V1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" }, comdat
-// CHECK-DAG: @"\01??_R4X1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" }, comdat
-// CHECK-DAG: @"\01??_R4C@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUC@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3C@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*], [4 x %rtti.BaseClassDescriptor*]* @"\01??_R2C@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2C@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@C@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EA@B@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EA@A@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@C@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" }, comdat
-// CHECK-DAG: @"\01??_R13?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUB@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3B@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"\01??_R2B@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2B@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUA@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3A@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2A@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2A@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R13?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" }, comdat
-// CHECK-DAG: @"\01??_R4Y@@6BZ@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AVY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3Y@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 9, %rtti.BaseClassDescriptor** getelementptr inbounds ([10 x %rtti.BaseClassDescriptor*], [10 x %rtti.BaseClassDescriptor*]* @"\01??_R2Y@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2Y@@8" = linkonce_odr constant [10 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@Z@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EN@W@@8", %rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@M@@8", %rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@N@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33FN@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33EJ@X@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33FN@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33EJ@X@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@Y@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i8*), i32 8, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EN@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AVZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3Z@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2Z@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2Z@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" }, comdat
-// CHECK-DAG: @"\01??_R13?0A@EN@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i8*), i32 4, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AVW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3W@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 5, %rtti.BaseClassDescriptor** getelementptr inbounds ([6 x %rtti.BaseClassDescriptor*], [6 x %rtti.BaseClassDescriptor*]* @"\01??_R2W@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2W@@8" = linkonce_odr constant [6 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EN@M@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EN@N@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FN@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EJ@X@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i8*), i32 4, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" }, comdat
-// CHECK-DAG: @"\01??_R13?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3M@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"\01??_R2M@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2M@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@M@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@N@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUN@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3N@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2N@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2N@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@N@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" }, comdat
-// CHECK-DAG: @"\01??_R13?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@A@3FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 93, %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AVV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3V@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"\01??_R2V@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2V@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@?0A@EA@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" }, comdat
-// CHECK-DAG: @"\01??_R0?AUX@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" }, comdat
-// CHECK-DAG: @"\01??_R3X@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"\01??_R2X@@8", i32 0, i32 0) }, comdat
-// CHECK-DAG: @"\01??_R2X@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8", %rtti.BaseClassDescriptor* null], comdat
-// CHECK-DAG: @"\01??_R1A@A@3EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 73, %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" }, comdat
-// CHECK-DAG: @"\01??_R17?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 8, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" }, comdat
-// CHECK-DAG: @"\01??_R17?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 8, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@33FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 4, i32 4, i32 93, %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" }, comdat
-// CHECK-DAG: @"\01??_R1A@33EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 4, i32 4, i32 73, %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" }, comdat
-// CHECK-DAG: @"\01??_R4Y@@6BW@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" }, comdat
-// CHECK-DAG: @"\01??_R4W@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" }, comdat
-// CHECK-DAG: @"\01??_R4Z@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" }, comdat
-// CHECK-DAG: @"\01??_R4V@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" }, comdat
-// CHECK-DAG: @"\01??_R4X@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" }, comdat
+// CHECK-DAG: @"??_R4B2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUB2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3B2@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUB2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" }, comdat
+// CHECK-DAG: @"??_R3B2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 4, %rtti.BaseClassDescriptor** getelementptr inbounds ([5 x %rtti.BaseClassDescriptor*], [5 x %rtti.BaseClassDescriptor*]* @"??_R2B2@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2B2@@8" = linkonce_odr constant [5 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@B2@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3FA@A2@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3EA@Z2@@8", %rtti.BaseClassDescriptor* @"??_R13A@3EA@Y2@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@B2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUB2@@@8" to i8*), i32 3, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3B2@@8" }, comdat
+// CHECK-DAG: @"??_R1A@A@3FA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUA2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" }, comdat
+// CHECK-DAG: @"??_R3A2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 1, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*], [4 x %rtti.BaseClassDescriptor*]* @"??_R2A2@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2A2@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A2@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Z2@@8", %rtti.BaseClassDescriptor* @"??_R13?0A@EA@Y2@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Z2@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUZ2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" }, comdat
+// CHECK-DAG: @"??_R3Z2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2Z2@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2Z2@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Z2@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R13?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUY2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" }, comdat
+// CHECK-DAG: @"??_R3Y2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2Y2@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2Y2@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Y2@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" }, comdat
+// CHECK-DAG: @"??_R1A@A@3EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Z2@@8" }, comdat
+// CHECK-DAG: @"??_R13A@3EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" }, comdat
+// CHECK-DAG: @"??_R4B2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 12, i32 8, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUB2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3B2@@8" }, comdat
+// CHECK-DAG: @"??_R4A2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" }, comdat
+// CHECK-DAG: @"??_R4A2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" }, comdat
+// CHECK-DAG: @"??_R4Y2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" }, comdat
+// CHECK-DAG: @"??_R4Z2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUZ2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3Z2@@8" }, comdat
+// CHECK-DAG: @"??_R4B1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUB1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3B1@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUB1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" }, comdat
+// CHECK-DAG: @"??_R3B1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"??_R2B1@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2B1@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@B1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3FA@A1@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@B1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUB1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3B1@@8" }, comdat
+// CHECK-DAG: @"??_R1A@A@3FA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"??_R3A1@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUA1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" }, comdat
+// CHECK-DAG: @"??_R3A1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2A1@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2A1@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A1@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3A1@@8" }, comdat
+// CHECK-DAG: @"??_R4A1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUA1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3A1@@8" }, comdat
+// CHECK-DAG: @"??_R4Y1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUY1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3Y1@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUY1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" }, comdat
+// CHECK-DAG: @"??_R3Y1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 6, %rtti.BaseClassDescriptor** getelementptr inbounds ([7 x %rtti.BaseClassDescriptor*], [7 x %rtti.BaseClassDescriptor*]* @"??_R2Y1@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2Y1@@8" = linkonce_odr constant [7 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Y1@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@W1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@Y1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUY1@@@8" to i8*), i32 5, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Y1@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@W1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUW1@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3W1@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUW1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" }, comdat
+// CHECK-DAG: @"??_R3W1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*], [4 x %rtti.BaseClassDescriptor*]* @"??_R2W1@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2W1@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@W1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@A@3FA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"??_R3V1@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUV1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" }, comdat
+// CHECK-DAG: @"??_R3V1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"??_R2V1@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2V1@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@V1@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3V1@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3X1@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUX1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" }, comdat
+// CHECK-DAG: @"??_R3X1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2X1@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2X1@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X1@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@A@3EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3X1@@8" }, comdat
+// CHECK-DAG: @"??_R4W1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUW1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3W1@@8" }, comdat
+// CHECK-DAG: @"??_R4V1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUV1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3V1@@8" }, comdat
+// CHECK-DAG: @"??_R4X1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"??_R0?AUX1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3X1@@8" }, comdat
+// CHECK-DAG: @"??_R4C@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUC@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3C@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUC@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" }, comdat
+// CHECK-DAG: @"??_R3C@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*], [4 x %rtti.BaseClassDescriptor*]* @"??_R2C@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2C@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@C@@8", %rtti.BaseClassDescriptor* @"??_R13?0A@EA@B@@8", %rtti.BaseClassDescriptor* @"??_R13?0A@EA@A@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@C@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUC@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3C@@8" }, comdat
+// CHECK-DAG: @"??_R13?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3B@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUB@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" }, comdat
+// CHECK-DAG: @"??_R3B@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"??_R2B@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2B@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@B@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3B@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3A@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUA@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" }, comdat
+// CHECK-DAG: @"??_R3A@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2A@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2A@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R13?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3A@@8" }, comdat
+// CHECK-DAG: @"??_R4Y@@6BZ@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVY@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3Y@@8" }, comdat
+// CHECK-DAG: @"??_R0?AVY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" }, comdat
+// CHECK-DAG: @"??_R3Y@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 9, %rtti.BaseClassDescriptor** getelementptr inbounds ([10 x %rtti.BaseClassDescriptor*], [10 x %rtti.BaseClassDescriptor*]* @"??_R2Y@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2Y@@8" = linkonce_odr constant [10 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Y@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EN@Z@@8", %rtti.BaseClassDescriptor* @"??_R13?0A@EN@W@@8", %rtti.BaseClassDescriptor* @"??_R17?0A@EN@M@@8", %rtti.BaseClassDescriptor* @"??_R17?0A@EN@N@@8", %rtti.BaseClassDescriptor* @"??_R1A@33FN@V@@8", %rtti.BaseClassDescriptor* @"??_R1A@33EJ@X@@8", %rtti.BaseClassDescriptor* @"??_R1A@33FN@V@@8", %rtti.BaseClassDescriptor* @"??_R1A@33EJ@X@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@Y@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVY@@@8" to i8*), i32 8, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Y@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EN@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3Z@@8" }, comdat
+// CHECK-DAG: @"??_R0?AVZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" }, comdat
+// CHECK-DAG: @"??_R3Z@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2Z@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2Z@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Z@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3Z@@8" }, comdat
+// CHECK-DAG: @"??_R13?0A@EN@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVW@@@8" to i8*), i32 4, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3W@@8" }, comdat
+// CHECK-DAG: @"??_R0?AVW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" }, comdat
+// CHECK-DAG: @"??_R3W@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 5, %rtti.BaseClassDescriptor** getelementptr inbounds ([6 x %rtti.BaseClassDescriptor*], [6 x %rtti.BaseClassDescriptor*]* @"??_R2W@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2W@@8" = linkonce_odr constant [6 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@W@@8", %rtti.BaseClassDescriptor* @"??_R13?0A@EN@M@@8", %rtti.BaseClassDescriptor* @"??_R13?0A@EN@N@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3FN@V@@8", %rtti.BaseClassDescriptor* @"??_R1A@A@3EJ@X@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVW@@@8" to i8*), i32 4, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3W@@8" }, comdat
+// CHECK-DAG: @"??_R13?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3M@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
+// CHECK-DAG: @"??_R3M@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"??_R2M@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2M@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@M@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EN@N@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3M@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3N@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUN@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" }, comdat
+// CHECK-DAG: @"??_R3N@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2N@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2N@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@N@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3N@@8" }, comdat
+// CHECK-DAG: @"??_R13?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3N@@8" }, comdat
+// CHECK-DAG: @"??_R1A@A@3FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 93, %rtti.ClassHierarchyDescriptor* @"??_R3V@@8" }, comdat
+// CHECK-DAG: @"??_R0?AVV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" }, comdat
+// CHECK-DAG: @"??_R3V@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*], [3 x %rtti.BaseClassDescriptor*]* @"??_R2V@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2V@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@V@@8", %rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3V@@8" }, comdat
+// CHECK-DAG: @"??_R1A@?0A@EA@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"??_R3X@@8" }, comdat
+// CHECK-DAG: @"??_R0?AUX@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" }, comdat
+// CHECK-DAG: @"??_R3X@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*], [2 x %rtti.BaseClassDescriptor*]* @"??_R2X@@8", i32 0, i32 0) }, comdat
+// CHECK-DAG: @"??_R2X@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X@@8", %rtti.BaseClassDescriptor* null], comdat
+// CHECK-DAG: @"??_R1A@A@3EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 73, %rtti.ClassHierarchyDescriptor* @"??_R3X@@8" }, comdat
+// CHECK-DAG: @"??_R17?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i8*), i32 1, i32 8, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3M@@8" }, comdat
+// CHECK-DAG: @"??_R17?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i8*), i32 0, i32 8, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"??_R3N@@8" }, comdat
+// CHECK-DAG: @"??_R1A@33FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 4, i32 4, i32 93, %rtti.ClassHierarchyDescriptor* @"??_R3V@@8" }, comdat
+// CHECK-DAG: @"??_R1A@33EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 4, i32 4, i32 73, %rtti.ClassHierarchyDescriptor* @"??_R3X@@8" }, comdat
+// CHECK-DAG: @"??_R4Y@@6BW@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVY@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3Y@@8" }, comdat
+// CHECK-DAG: @"??_R4W@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVW@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3W@@8" }, comdat
+// CHECK-DAG: @"??_R4Z@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVZ@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3Z@@8" }, comdat
+// CHECK-DAG: @"??_R4V@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3V@@8" }, comdat
+// CHECK-DAG: @"??_R4X@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"??_R3X@@8" }, comdat
-// X64-DAG: @"\01??_R4B2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4B2@@6BZ2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUB2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" }, comdat
-// X64-DAG: @"\01??_R3B2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([5 x i32]* @"\01??_R2B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2B2@@8" = linkonce_odr constant [5 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17A@3EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@B2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 3, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@A@3FA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUA2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" }, comdat
-// X64-DAG: @"\01??_R3A2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 1, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"\01??_R2A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2A2@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUZ2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" }, comdat
-// X64-DAG: @"\01??_R3Z2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2Z2@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R17?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUY2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" }, comdat
-// X64-DAG: @"\01??_R3Y2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2Y2@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@A@3EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R17A@3EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4B2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 24, i32 12, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4B2@@6BY2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4A2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4A2@@6BZ2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4A2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4A2@@6BY2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4Y2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y2@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4Z2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Z2@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4B1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4B1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUB1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" }, comdat
-// X64-DAG: @"\01??_R3B1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2B1@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@B1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@A@3FA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUA1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" }, comdat
-// X64-DAG: @"\01??_R3A1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2A1@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4A1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4A1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4Y1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUY1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" }, comdat
-// X64-DAG: @"\01??_R3Y1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 6, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([7 x i32]* @"\01??_R2Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2Y1@@8" = linkonce_odr constant [7 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@Y1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 5, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@W1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUW1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" }, comdat
-// X64-DAG: @"\01??_R3W1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"\01??_R2W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2W1@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@A@3FA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUV1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" }, comdat
-// X64-DAG: @"\01??_R3V1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2V1@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUX1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" }, comdat
-// X64-DAG: @"\01??_R3X1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2X1@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@A@3EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4W1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4W1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4V1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4V1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4X1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4X1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4C@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4C@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUC@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" }, comdat
-// X64-DAG: @"\01??_R3C@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"\01??_R2C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2C@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EA@B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@C@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R17?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUB@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" }, comdat
-// X64-DAG: @"\01??_R3B@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2B@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUA@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" }, comdat
-// X64-DAG: @"\01??_R3A@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2A@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R17?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4Y@@6BZ@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y@@6BZ@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AVY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" }, comdat
-// X64-DAG: @"\01??_R3Y@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 9, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([10 x i32]* @"\01??_R2Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2Y@@8" = linkonce_odr constant [10 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1BA@?0A@EN@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1BA@?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@Y@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 8, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EN@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AVZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" }, comdat
-// X64-DAG: @"\01??_R3Z@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2Z@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R17?0A@EN@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 4, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AVW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" }, comdat
-// X64-DAG: @"\01??_R3W@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 5, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([6 x i32]* @"\01??_R2W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2W@@8" = linkonce_odr constant [6 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 4, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R17?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
-// X64-DAG: @"\01??_R3M@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2M@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUN@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" }, comdat
-// X64-DAG: @"\01??_R3N@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2N@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R17?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@A@3FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 0, i32 4, i32 93, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AVV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" }, comdat
-// X64-DAG: @"\01??_R3V@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2V@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@?0A@EA@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R0?AUX@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" }, comdat
-// X64-DAG: @"\01??_R3X@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R2X@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
-// X64-DAG: @"\01??_R1A@A@3EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 73, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1BA@?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 16, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1BA@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 16, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@73FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 8, i32 4, i32 93, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R1A@73EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 8, i32 4, i32 73, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4Y@@6BW@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y@@6BW@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4W@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4Z@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Z@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4V@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4V@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
-// X64-DAG: @"\01??_R4X@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4X@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4B2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4B2@@6BZ2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUB2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" }, comdat
+// X64-DAG: @"??_R3B2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([5 x i32]* @"??_R2B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2B2@@8" = linkonce_odr constant [5 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3FA@A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17A@3EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@B2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 3, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@A@3FA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUA2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" }, comdat
+// X64-DAG: @"??_R3A2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 1, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"??_R2A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2A2@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17?0A@EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUZ2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" }, comdat
+// X64-DAG: @"??_R3Z2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2Z2@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R17?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUY2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" }, comdat
+// X64-DAG: @"??_R3Y2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2Y2@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@A@3EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R17A@3EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4B2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 24, i32 12, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4B2@@6BY2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4A2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4A2@@6BZ2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4A2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4A2@@6BY2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4Y2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4Y2@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4Z2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4Z2@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4B1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUB1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4B1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUB1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" }, comdat
+// X64-DAG: @"??_R3B1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"??_R2B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2B1@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3FA@A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@B1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUB1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@A@3FA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUA1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" }, comdat
+// X64-DAG: @"??_R3A1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2A1@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4A1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4A1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4Y1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUY1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4Y1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUY1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" }, comdat
+// X64-DAG: @"??_R3Y1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 6, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([7 x i32]* @"??_R2Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2Y1@@8" = linkonce_odr constant [7 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@Y1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUY1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 5, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EA@W1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUW1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUW1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" }, comdat
+// X64-DAG: @"??_R3W1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"??_R2W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2W1@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@A@3FA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUV1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" }, comdat
+// X64-DAG: @"??_R3V1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"??_R2V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2V1@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUX1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" }, comdat
+// X64-DAG: @"??_R3X1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2X1@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@A@3EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4W1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUW1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4W1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4V1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4V1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4X1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4X1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4C@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUC@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4C@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUC@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" }, comdat
+// X64-DAG: @"??_R3C@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"??_R2C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2C@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17?0A@EA@B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@C@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUC@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R17?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUB@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" }, comdat
+// X64-DAG: @"??_R3B@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"??_R2B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2B@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUA@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" }, comdat
+// X64-DAG: @"??_R3A@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2A@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R17?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4Y@@6BZ@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4Y@@6BZ@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AVY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" }, comdat
+// X64-DAG: @"??_R3Y@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 9, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([10 x i32]* @"??_R2Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2Y@@8" = linkonce_odr constant [10 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EN@Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17?0A@EN@W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1BA@?0A@EN@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1BA@?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@73FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@73EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@73FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@73EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@Y@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 8, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EN@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AVZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" }, comdat
+// X64-DAG: @"??_R3Z@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2Z@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R17?0A@EN@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 4, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AVW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" }, comdat
+// X64-DAG: @"??_R3W@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 5, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([6 x i32]* @"??_R2W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2W@@8" = linkonce_odr constant [6 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17?0A@EN@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R17?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@A@3EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 4, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R17?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
+// X64-DAG: @"??_R3M@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"??_R2M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2M@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUN@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" }, comdat
+// X64-DAG: @"??_R3N@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2N@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R17?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@A@3FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 0, i32 4, i32 93, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AVV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" }, comdat
+// X64-DAG: @"??_R3V@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"??_R2V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2V@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@?0A@EA@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@?0A@EA@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R0?AUX@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" }, comdat
+// X64-DAG: @"??_R3X@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R2X@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
+// X64-DAG: @"??_R1A@A@3EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 73, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1BA@?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 16, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1BA@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 16, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@73FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 8, i32 4, i32 93, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R1A@73EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 8, i32 4, i32 73, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4Y@@6BW@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4Y@@6BW@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4W@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4W@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4Z@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4Z@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4V@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4V@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
+// X64-DAG: @"??_R4X@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4X@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
diff --git a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
index acd8653..36c9ca4 100644
--- a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -79,117 +79,114 @@
// Returning structs that fit into a register.
Small small_return() { return Small(); }
// LINUX-LABEL: define void @_Z12small_returnv(%struct.Small* noalias sret %agg.result)
-// WIN32: define dso_local i32 @"\01?small_return@@YA?AUSmall@@XZ"()
-// WIN64: define dso_local i32 @"\01?small_return@@YA?AUSmall@@XZ"()
+// WIN32: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"()
+// WIN64: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"()
Medium medium_return() { return Medium(); }
// LINUX-LABEL: define void @_Z13medium_returnv(%struct.Medium* noalias sret %agg.result)
-// WIN32: define dso_local i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
-// WIN64: define dso_local i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
+// WIN32: define dso_local i64 @"?medium_return@@YA?AUMedium@@XZ"()
+// WIN64: define dso_local i64 @"?medium_return@@YA?AUMedium@@XZ"()
// Returning structs that fit into a register but are not POD.
SmallCpp11NotCpp03Pod small_non_pod_return() { return SmallCpp11NotCpp03Pod(); }
// LINUX-LABEL: define void @_Z20small_non_pod_returnv(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
-// WIN32: define dso_local void @"\01?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
-// WIN64: define dso_local void @"\01?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
+// WIN32: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
+// WIN64: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
SmallWithCtor small_with_ctor_return() { return SmallWithCtor(); }
// LINUX-LABEL: define void @_Z22small_with_ctor_returnv(%struct.SmallWithCtor* noalias sret %agg.result)
-// WIN32: define dso_local void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
-// WIN64: define dso_local void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
+// WIN32: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
+// WIN64: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
// FIXME: The 'sret' mark here doesn't seem to be enough to convince LLVM to
// preserve the hidden sret pointer in R0 across the function.
-// WOA: define dso_local arm_aapcs_vfpcc void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
SmallWithVftable small_with_vftable_return() { return SmallWithVftable(); }
// LINUX-LABEL: define void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret %agg.result)
-// WIN32: define dso_local void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
-// WIN64: define dso_local void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
+// WIN32: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
+// WIN64: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
MediumWithCopyCtor medium_with_copy_ctor_return() { return MediumWithCopyCtor(); }
// LINUX-LABEL: define void @_Z28medium_with_copy_ctor_returnv(%struct.MediumWithCopyCtor* noalias sret %agg.result)
-// WIN32: define dso_local void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
-// WIN64: define dso_local void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
-// WOA: define dso_local arm_aapcs_vfpcc void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
+// WIN32: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
+// WIN64: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
// Returning a large struct that doesn't fit into a register.
Big big_return() { return Big(); }
// LINUX-LABEL: define void @_Z10big_returnv(%struct.Big* noalias sret %agg.result)
-// WIN32: define dso_local void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
-// WIN64: define dso_local void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
+// WIN32: define dso_local void @"?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
+// WIN64: define dso_local void @"?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
void small_arg(Small s) {}
// LINUX-LABEL: define void @_Z9small_arg5Small(i32 %s.0)
-// WIN32: define dso_local void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.0)
-// WIN64: define dso_local void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.coerce)
-// WOA: define dso_local arm_aapcs_vfpcc void @"\01?small_arg@@YAXUSmall@@@Z"([1 x i32] %s.coerce)
+// WIN32: define dso_local void @"?small_arg@@YAXUSmall@@@Z"(i32 %s.0)
+// WIN64: define dso_local void @"?small_arg@@YAXUSmall@@@Z"(i32 %s.coerce)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?small_arg@@YAXUSmall@@@Z"([1 x i32] %s.coerce)
void medium_arg(Medium s) {}
// LINUX-LABEL: define void @_Z10medium_arg6Medium(i32 %s.0, i32 %s.1)
-// WIN32: define dso_local void @"\01?medium_arg@@YAXUMedium@@@Z"(i32 %s.0, i32 %s.1)
-// WIN64: define dso_local void @"\01?medium_arg@@YAXUMedium@@@Z"(i64 %s.coerce)
-// WOA: define dso_local arm_aapcs_vfpcc void @"\01?medium_arg@@YAXUMedium@@@Z"([2 x i32] %s.coerce)
+// WIN32: define dso_local void @"?medium_arg@@YAXUMedium@@@Z"(i32 %s.0, i32 %s.1)
+// WIN64: define dso_local void @"?medium_arg@@YAXUMedium@@@Z"(i64 %s.coerce)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_arg@@YAXUMedium@@@Z"([2 x i32] %s.coerce)
void base_no_byval_arg(BaseNoByval s) {}
// LINUX-LABEL: define void @_Z17base_no_byval_arg11BaseNoByval(%struct.BaseNoByval* byval align 4 %s)
-// WIN32: define dso_local void @"\01?base_no_byval_arg@@YAXUBaseNoByval@@@Z"(i32 %s.0, i32 %s.1)
-// WIN64: define dso_local void @"\01?base_no_byval_arg@@YAXUBaseNoByval@@@Z"(i64 %s.coerce)
-// WOA: define dso_local arm_aapcs_vfpcc void @"\01?base_no_byval_arg@@YAXUBaseNoByval@@@Z"([2 x i32] %s.coerce)
+// WIN32: define dso_local void @"?base_no_byval_arg@@YAXUBaseNoByval@@@Z"(i32 %s.0, i32 %s.1)
+// WIN64: define dso_local void @"?base_no_byval_arg@@YAXUBaseNoByval@@@Z"(i64 %s.coerce)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?base_no_byval_arg@@YAXUBaseNoByval@@@Z"([2 x i32] %s.coerce)
void small_arg_with_ctor(SmallWithCtor s) {}
// LINUX-LABEL: define void @_Z19small_arg_with_ctor13SmallWithCtor(%struct.SmallWithCtor* byval align 4 %s)
-// WIN32: define dso_local void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.0)
-// WIN64: define dso_local void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.coerce)
-// WOA: define dso_local arm_aapcs_vfpcc void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"([1 x i32] %s.coerce)
+// WIN32: define dso_local void @"?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.0)
+// WIN64: define dso_local void @"?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.coerce)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"([1 x i32] %s.coerce)
// FIXME: We could coerce to a series of i32s here if we wanted to.
void multibyte_arg(Multibyte s) {}
// LINUX-LABEL: define void @_Z13multibyte_arg9Multibyte(%struct.Multibyte* byval align 4 %s)
-// WIN32: define dso_local void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"(%struct.Multibyte* byval align 4 %s)
-// WIN64: define dso_local void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"(i32 %s.coerce)
-// WOA: define dso_local arm_aapcs_vfpcc void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"([1 x i32] %s.coerce)
+// WIN32: define dso_local void @"?multibyte_arg@@YAXUMultibyte@@@Z"(%struct.Multibyte* byval align 4 %s)
+// WIN64: define dso_local void @"?multibyte_arg@@YAXUMultibyte@@@Z"(i32 %s.coerce)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?multibyte_arg@@YAXUMultibyte@@@Z"([1 x i32] %s.coerce)
void packed_arg(Packed s) {}
// LINUX-LABEL: define void @_Z10packed_arg6Packed(%struct.Packed* byval align 4 %s)
-// WIN32: define dso_local void @"\01?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* byval align 4 %s)
-// WIN64: define dso_local void @"\01?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* %s)
+// WIN32: define dso_local void @"?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* byval align 4 %s)
+// WIN64: define dso_local void @"?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* %s)
// Test that dtors are invoked in the callee.
void small_arg_with_dtor(SmallWithDtor s) {}
-// WIN32: define dso_local void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca) {{.*}} {
-// WIN32: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
+// WIN32: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca) {{.*}} {
+// WIN32: call x86_thiscallcc void @"??1SmallWithDtor@@QAE@XZ"
// WIN32: }
-// WIN64: define dso_local void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
-// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"
+// WIN64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
+// WIN64: call void @"??1SmallWithDtor@@QEAA@XZ"
// WIN64: }
// FIXME: MSVC incompatible!
-// WOA: define dso_local arm_aapcs_vfpcc void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
-// WOA: call arm_aapcs_vfpcc void @"\01??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
+// WOA: call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s)
// WOA: }
void call_small_arg_with_dtor() {
small_arg_with_dtor(SmallWithDtor());
}
-// The temporary is copied, so it's destroyed in the caller as well as the
-// callee.
-// WIN64-LABEL: define dso_local void @"\01?call_small_arg_with_dtor@@YAXXZ"()
-// WIN64: call %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QEAA@XZ"
-// WIN64: call void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %{{.*}})
-// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"
+// WIN64-LABEL: define dso_local void @"?call_small_arg_with_dtor@@YAXXZ"()
+// WIN64: call %struct.SmallWithDtor* @"??0SmallWithDtor@@QEAA@XZ"
+// WIN64: call void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %{{.*}})
// WIN64: ret void
// Test that references aren't destroyed in the callee.
void ref_small_arg_with_dtor(const SmallWithDtor &s) { }
-// WIN32: define dso_local void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s) {{.*}} {
-// WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
+// WIN32: define dso_local void @"?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s) {{.*}} {
+// WIN32-NOT: call x86_thiscallcc void @"??1SmallWithDtor@@QAE@XZ"
// WIN32: }
-// WIN64-LABEL: define dso_local void @"\01?ref_small_arg_with_dtor@@YAXAEBUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s)
+// WIN64-LABEL: define dso_local void @"?ref_small_arg_with_dtor@@YAXAEBUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s)
void big_arg_with_dtor(BigWithDtor s) {}
-// WIN64-LABEL: define dso_local void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %s)
-// WIN64: call void @"\01??1BigWithDtor@@QEAA@XZ"
+// WIN64-LABEL: define dso_local void @"?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %s)
+// WIN64: call void @"??1BigWithDtor@@QEAA@XZ"
// WIN64: }
void call_big_arg_with_dtor() {
@@ -197,20 +194,20 @@
}
// We can elide the copy of the temporary in the caller, because this object is
// larger than 8 bytes and is passed indirectly.
-// WIN64-LABEL: define dso_local void @"\01?call_big_arg_with_dtor@@YAXXZ"()
-// WIN64: call %struct.BigWithDtor* @"\01??0BigWithDtor@@QEAA@XZ"
-// WIN64: call void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %{{.*}})
-// WIN64-NOT: call void @"\01??1BigWithDtor@@QEAA@XZ"
+// WIN64-LABEL: define dso_local void @"?call_big_arg_with_dtor@@YAXXZ"()
+// WIN64: call %struct.BigWithDtor* @"??0BigWithDtor@@QEAA@XZ"
+// WIN64: call void @"?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %{{.*}})
+// WIN64-NOT: call void @"??1BigWithDtor@@QEAA@XZ"
// WIN64: ret void
// Test that temporaries passed by reference are destroyed in the caller.
void temporary_ref_with_dtor() {
ref_small_arg_with_dtor(SmallWithDtor());
}
-// WIN32: define dso_local void @"\01?temporary_ref_with_dtor@@YAXXZ"() {{.*}} {
-// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
-// WIN32: call void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"
-// WIN32: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
+// WIN32: define dso_local void @"?temporary_ref_with_dtor@@YAXXZ"() {{.*}} {
+// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE@XZ"
+// WIN32: call void @"?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"
+// WIN32: call x86_thiscallcc void @"??1SmallWithDtor@@QAE@XZ"
// WIN32: }
void takes_two_by_val_with_dtor(SmallWithDtor a, SmallWithDtor b);
@@ -219,28 +216,28 @@
}
// When exceptions are off, we don't have any cleanups. See
// microsoft-abi-exceptions.cpp for these cleanups.
-// WIN32: define dso_local void @"\01?eh_cleanup_arg_with_dtor@@YAXXZ"() {{.*}} {
-// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
-// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
-// WIN32: call void @"\01?takes_two_by_val_with_dtor@@YAXUSmallWithDtor@@0@Z"
-// WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
+// WIN32: define dso_local void @"?eh_cleanup_arg_with_dtor@@YAXXZ"() {{.*}} {
+// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE@XZ"
+// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE@XZ"
+// WIN32: call void @"?takes_two_by_val_with_dtor@@YAXUSmallWithDtor@@0@Z"
+// WIN32-NOT: call x86_thiscallcc void @"??1SmallWithDtor@@QAE@XZ"
// WIN32: }
void small_arg_with_vftable(SmallWithVftable s) {}
// LINUX-LABEL: define void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s)
-// WIN32: define dso_local void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca)
-// WIN64: define dso_local void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
+// WIN32: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca)
+// WIN64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {}
// LINUX-LABEL: define void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s)
-// WIN32: define dso_local void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca)
-// WIN64: define dso_local void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
-// WOA: define dso_local arm_aapcs_vfpcc void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
+// WIN32: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca)
+// WIN64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
void big_arg(Big s) {}
// LINUX-LABEL: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s)
-// WIN32: define dso_local void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* byval align 4 %s)
-// WIN64: define dso_local void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* %s)
+// WIN32: define dso_local void @"?big_arg@@YAXUBig@@@Z"(%struct.Big* byval align 4 %s)
+// WIN64: define dso_local void @"?big_arg@@YAXUBig@@@Z"(%struct.Big* %s)
// PR27607: We would attempt to load i32 value out of the reference instead of
// just loading the pointer from the struct during argument expansion.
@@ -250,8 +247,8 @@
};
void takes_ref_field(RefField s) {}
// LINUX-LABEL: define void @_Z15takes_ref_field8RefField(%struct.RefField* byval align 4 %s)
-// WIN32: define dso_local void @"\01?takes_ref_field@@YAXURefField@@@Z"(i32* %s.0)
-// WIN64: define dso_local void @"\01?takes_ref_field@@YAXURefField@@@Z"(i64 %s.coerce)
+// WIN32: define dso_local void @"?takes_ref_field@@YAXURefField@@@Z"(i32* %s.0)
+// WIN64: define dso_local void @"?takes_ref_field@@YAXURefField@@@Z"(i64 %s.coerce)
void pass_ref_field() {
int x;
@@ -259,57 +256,57 @@
}
// LINUX-LABEL: define void @_Z14pass_ref_fieldv()
// LINUX: call void @_Z15takes_ref_field8RefField(%struct.RefField* byval align 4 %{{.*}})
-// WIN32-LABEL: define dso_local void @"\01?pass_ref_field@@YAXXZ"()
-// WIN32: call void @"\01?takes_ref_field@@YAXURefField@@@Z"(i32* %{{.*}})
-// WIN64-LABEL: define dso_local void @"\01?pass_ref_field@@YAXXZ"()
-// WIN64: call void @"\01?takes_ref_field@@YAXURefField@@@Z"(i64 %{{.*}})
+// WIN32-LABEL: define dso_local void @"?pass_ref_field@@YAXXZ"()
+// WIN32: call void @"?takes_ref_field@@YAXURefField@@@Z"(i32* %{{.*}})
+// WIN64-LABEL: define dso_local void @"?pass_ref_field@@YAXXZ"()
+// WIN64: call void @"?takes_ref_field@@YAXURefField@@@Z"(i64 %{{.*}})
class Class {
public:
Small thiscall_method_small() { return Small(); }
// LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
- // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
- // WIN64: define linkonce_odr dso_local void @"\01?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
+ // WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
SmallWithCtor thiscall_method_small_with_ctor() { return SmallWithCtor(); }
// LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(%struct.SmallWithCtor* noalias sret %agg.result, %class.Class* %this)
- // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
- // WIN64: define linkonce_odr dso_local void @"\01?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
+ // WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
Small __cdecl cdecl_method_small() { return Small(); }
// LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
- // WIN32: define {{.*}} void @"\01?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
- // WIN64: define linkonce_odr dso_local void @"\01?cdecl_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
+ // WIN32: define {{.*}} void @"?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
+ // WIN64: define linkonce_odr dso_local void @"?cdecl_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
Big __cdecl cdecl_method_big() { return Big(); }
// LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(%struct.Big* noalias sret %agg.result, %class.Class* %this)
- // WIN32: define {{.*}} void @"\01?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
- // WIN64: define linkonce_odr dso_local void @"\01?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
+ // WIN32: define {{.*}} void @"?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
+ // WIN64: define linkonce_odr dso_local void @"?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
void thiscall_method_arg(Empty s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Empty(%class.Class* %this)
- // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmpty@@@Z"(%class.Class* %this, %struct.Empty* byval align 4 %s)
- // WIN64: define linkonce_odr dso_local void @"\01?thiscall_method_arg@Class@@QEAAXUEmpty@@@Z"(%class.Class* %this, i8 %s.coerce)
+ // WIN32: define {{.*}} void @"?thiscall_method_arg@Class@@QAEXUEmpty@@@Z"(%class.Class* %this, %struct.Empty* byval align 4 %s)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg@Class@@QEAAXUEmpty@@@Z"(%class.Class* %this, i8 %s.coerce)
void thiscall_method_arg(EmptyWithCtor s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13EmptyWithCtor(%class.Class* %this)
- // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmptyWithCtor@@@Z"(%class.Class* %this, %struct.EmptyWithCtor* byval align 4 %s)
- // WIN64: define linkonce_odr dso_local void @"\01?thiscall_method_arg@Class@@QEAAXUEmptyWithCtor@@@Z"(%class.Class* %this, i8 %s.coerce)
+ // WIN32: define {{.*}} void @"?thiscall_method_arg@Class@@QAEXUEmptyWithCtor@@@Z"(%class.Class* %this, %struct.EmptyWithCtor* byval align 4 %s)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg@Class@@QEAAXUEmptyWithCtor@@@Z"(%class.Class* %this, i8 %s.coerce)
void thiscall_method_arg(Small s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Small(%class.Class* %this, i32 %s.0)
- // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmall@@@Z"(%class.Class* %this, i32 %s.0)
- // WIN64: define linkonce_odr dso_local void @"\01?thiscall_method_arg@Class@@QEAAXUSmall@@@Z"(%class.Class* %this, i32 %s.coerce)
+ // WIN32: define {{.*}} void @"?thiscall_method_arg@Class@@QAEXUSmall@@@Z"(%class.Class* %this, i32 %s.0)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg@Class@@QEAAXUSmall@@@Z"(%class.Class* %this, i32 %s.coerce)
void thiscall_method_arg(SmallWithCtor s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13SmallWithCtor(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s)
- // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.0)
- // WIN64: define linkonce_odr dso_local void @"\01?thiscall_method_arg@Class@@QEAAXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.coerce)
+ // WIN32: define {{.*}} void @"?thiscall_method_arg@Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.0)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg@Class@@QEAAXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.coerce)
void thiscall_method_arg(Big s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE3Big(%class.Class* %this, %struct.Big* byval align 4 %s)
- // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUBig@@@Z"(%class.Class* %this, %struct.Big* byval align 4 %s)
- // WIN64: define linkonce_odr dso_local void @"\01?thiscall_method_arg@Class@@QEAAXUBig@@@Z"(%class.Class* %this, %struct.Big* %s)
+ // WIN32: define {{.*}} void @"?thiscall_method_arg@Class@@QAEXUBig@@@Z"(%class.Class* %this, %struct.Big* byval align 4 %s)
+ // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg@Class@@QEAAXUBig@@@Z"(%class.Class* %this, %struct.Big* %s)
};
void use_class() {
@@ -333,14 +330,14 @@
};
void g(X) {
}
-// WIN32: define dso_local void @"\01?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca) {{.*}} {
-// WIN32: call x86_thiscallcc void @"\01??1X@@QAE@XZ"(%struct.X* {{.*}})
+// WIN32: define dso_local void @"?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca) {{.*}} {
+// WIN32: call x86_thiscallcc void @"??1X@@QAE@XZ"(%struct.X* {{.*}})
// WIN32: }
void f() {
g(X());
}
-// WIN32: define dso_local void @"\01?f@@YAXXZ"() {{.*}} {
-// WIN32-NOT: call {{.*}} @"\01??1X@@QAE@XZ"
+// WIN32: define dso_local void @"?f@@YAXXZ"() {{.*}} {
+// WIN32-NOT: call {{.*}} @"??1X@@QAE@XZ"
// WIN32: }
@@ -362,13 +359,13 @@
b.b = 13;
int c = foo(NonTrivial(), b);
}
-// WIN32-LABEL: define dso_local void @"\01?bar@test2@@YAXXZ"() {{.*}} {
+// WIN32-LABEL: define dso_local void @"?bar@test2@@YAXXZ"() {{.*}} {
// WIN32: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty:<{ %"struct.test2::NonTrivial", %"struct.test2::POD" }>]]
// WIN32: getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
// WIN32: call void @llvm.memcpy
// WIN32: getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
-// WIN32: call x86_thiscallcc %"struct.test2::NonTrivial"* @"\01??0NonTrivial@test2@@QAE@XZ"
-// WIN32: call i32 @"\01?foo@test2@@YAHUNonTrivial@1@UPOD@1@@Z"([[argmem_ty]]* inalloca %argmem)
+// WIN32: call x86_thiscallcc %"struct.test2::NonTrivial"* @"??0NonTrivial@test2@@QAE@XZ"
+// WIN32: call i32 @"?foo@test2@@YAHUNonTrivial@1@UPOD@1@@Z"([[argmem_ty]]* inalloca %argmem)
// WIN32: ret void
// WIN32: }
@@ -384,7 +381,7 @@
int a;
};
void foo(NonTrivial a, bool b) { }
-// WIN32-LABEL: define dso_local void @"\01?foo@test3@@YAXUNonTrivial@1@_N@Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca)
+// WIN32-LABEL: define dso_local void @"?foo@test3@@YAXUNonTrivial@1@_N@Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca)
}
@@ -399,7 +396,7 @@
struct ForwardDeclare1 {};
void fn2(FnPtr1 a, SmallWithDtor b) { fn1(a, b); };
-// WIN32-LABEL: define dso_local void @"\01?fn2@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"
+// WIN32-LABEL: define dso_local void @"?fn2@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"
// WIN32: %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty:<{ {}\*, %struct.SmallWithDtor }>]], [[argmem_ty:<{ {}\*, %struct.SmallWithDtor }>]]* %{{.*}}, i32 0, i32 0
// WIN32: %[[a1:[^ ]*]] = bitcast {}** %[[a]] to void [[dst_ty:\(%struct.ForwardDeclare1\*\)\*]]*
// WIN32: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]]
@@ -410,7 +407,7 @@
// WIN32: %[[gep2:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
// WIN32: %[[addr:[^ ]*]] = bitcast {}** %[[gep2]] to void [[dst_ty]]*
// WIN32: store void [[dst_ty]] %[[a2]], void [[dst_ty]]* %[[addr]], align 4
-// WIN32: call void @"\01?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca %[[argmem]])
+// WIN32: call void @"?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca %[[argmem]])
namespace pr30293 {
// Virtual methods living in a secondary vtable take i8* as their 'this'
@@ -430,11 +427,11 @@
};
void C::g() { return h(SmallWithDtor()); }
-// WIN32-LABEL: define dso_local x86_thiscallcc void @"\01?g@C@pr30293@@QAEXXZ"(%"struct.pr30293::C"* %this)
-// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
-// WIN32: call void @"\01?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca %{{[^,)]*}})
-// WIN32: declare dso_local void @"\01?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca)
+// WIN32-LABEL: define dso_local x86_thiscallcc void @"?g@C@pr30293@@QAEXXZ"(%"struct.pr30293::C"* %this)
+// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE@XZ"
+// WIN32: call void @"?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca %{{[^,)]*}})
+// WIN32: declare dso_local void @"?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca)
-// WIN64-LABEL: define dso_local void @"\01?g@C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* %this)
-// WIN64: declare dso_local void @"\01?h@C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8*, i32)
+// WIN64-LABEL: define dso_local void @"?g@C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* %this)
+// WIN64: declare dso_local void @"?h@C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8*, i32)
}
diff --git a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
index fe0c371..db95266 100644
--- a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -fms-extensions -fno-threadsafe-statics -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s
// CHECK: @llvm.global_ctors = appending global [5 x { i32, void ()*, i8* }] [
-// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Eselectany1@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"\01?selectany1@@3US@@A", i32 0, i32 0) },
-// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Eselectany2@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"\01?selectany2@@3US@@A", i32 0, i32 0) },
-// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Es@?$ExportedTemplate@H@@2US@@A@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"\01?s@?$ExportedTemplate@H@@2US@@A", i32 0, i32 0) },
-// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ", i8* bitcast (%class.A* @"\01?foo@?$B@H@@2VA@@A" to i8*) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Eselectany1@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?selectany1@@3US@@A", i32 0, i32 0) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Eselectany2@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?selectany2@@3US@@A", i32 0, i32 0) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Es@?$ExportedTemplate@H@@2US@@A@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate@H@@2US@@A", i32 0, i32 0) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Efoo@?$B@H@@2VA@@A@YAXXZ", i8* bitcast (%class.A* @"?foo@?$B@H@@2VA@@A" to i8*) },
// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp, i8* null }
// CHECK: ]
@@ -15,26 +15,26 @@
S s;
-// CHECK: define internal void @"\01??__Es@@YAXXZ"()
-// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
-// CHECK: call i32 @atexit(void ()* @"\01??__Fs@@YAXXZ")
+// CHECK: define internal void @"??__Es@@YAXXZ"()
+// CHECK: call x86_thiscallcc %struct.S* @"??0S@@QAE@XZ"
+// CHECK: call i32 @atexit(void ()* @"??__Fs@@YAXXZ")
// CHECK: ret void
-// CHECK: define internal void @"\01??__Fs@@YAXXZ"()
-// CHECK: call x86_thiscallcc void @"\01??1S@@QAE@XZ"
+// CHECK: define internal void @"??__Fs@@YAXXZ"()
+// CHECK: call x86_thiscallcc void @"??1S@@QAE@XZ"
// CHECK: ret void
// These globals should have initializers comdat associative with the global.
// See @llvm.global_ctors above.
__declspec(selectany) S selectany1;
__declspec(selectany) S selectany2;
-// CHECK: define linkonce_odr dso_local void @"\01??__Eselectany1@@YAXXZ"() {{.*}} comdat
-// CHECK-NOT: @"\01??_Bselectany1
-// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
+// CHECK: define linkonce_odr dso_local void @"??__Eselectany1@@YAXXZ"() {{.*}} comdat
+// CHECK-NOT: @"??_Bselectany1
+// CHECK: call x86_thiscallcc %struct.S* @"??0S@@QAE@XZ"
// CHECK: ret void
-// CHECK: define linkonce_odr dso_local void @"\01??__Eselectany2@@YAXXZ"() {{.*}} comdat
-// CHECK-NOT: @"\01??_Bselectany2
-// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
+// CHECK: define linkonce_odr dso_local void @"??__Eselectany2@@YAXXZ"() {{.*}} comdat
+// CHECK-NOT: @"??_Bselectany2
+// CHECK: call x86_thiscallcc %struct.S* @"??0S@@QAE@XZ"
// CHECK: ret void
// The implicitly instantiated static data member should have initializer
@@ -51,9 +51,9 @@
static S TheS;
}
-// CHECK-LABEL: define dso_local void @"\01?StaticLocal@@YAXXZ"()
-// CHECK: load i32, i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
-// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
+// CHECK-LABEL: define dso_local void @"?StaticLocal@@YAXXZ"()
+// CHECK: load i32, i32* @"?$S1@?1??StaticLocal@@YAXXZ@4IA"
+// CHECK: store i32 {{.*}}, i32* @"?$S1@?1??StaticLocal@@YAXXZ@4IA"
// CHECK: ret
void MultipleStatics() {
@@ -93,8 +93,8 @@
static S S34;
static S S35;
}
-// CHECK-LABEL: define dso_local void @"\01?MultipleStatics@@YAXXZ"()
-// CHECK: load i32, i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA"
+// CHECK-LABEL: define dso_local void @"?MultipleStatics@@YAXXZ"()
+// CHECK: load i32, i32* @"?$S1@?1??MultipleStatics@@YAXXZ@4IA"
// CHECK: and i32 {{.*}}, 1
// CHECK: and i32 {{.*}}, 2
// CHECK: and i32 {{.*}}, 4
@@ -102,7 +102,7 @@
// CHECK: and i32 {{.*}}, 16
// ...
// CHECK: and i32 {{.*}}, -2147483648
-// CHECK: load i32, i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA.1"
+// CHECK: load i32, i32* @"?$S1@?1??MultipleStatics@@YAXXZ@4IA.1"
// CHECK: and i32 {{.*}}, 1
// CHECK: and i32 {{.*}}, 2
// CHECK: and i32 {{.*}}, 4
@@ -133,7 +133,7 @@
return s;
}
-// CHECK-LABEL: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.S* @"\01?UnreachableStatic@@YAAAUS@@XZ"() {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.S* @"?UnreachableStatic@@YAAAUS@@XZ"() {{.*}} comdat
// CHECK: and i32 {{.*}}, 2
// CHECK: or i32 {{.*}}, 2
// CHECK: ret
@@ -143,54 +143,54 @@
return TheS;
}
-// CHECK-LABEL: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.S* @"\01?getS@@YAAAUS@@XZ"() {{.*}} comdat
-// CHECK: load i32, i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51"
+// CHECK-LABEL: define linkonce_odr dso_local dereferenceable({{[0-9]+}}) %struct.S* @"?getS@@YAAAUS@@XZ"() {{.*}} comdat
+// CHECK: load i32, i32* @"??_B?1??getS@@YAAAUS@@XZ@51"
// CHECK: and i32 {{.*}}, 1
// CHECK: icmp eq i32 {{.*}}, 0
// CHECK: br i1
// init:
// CHECK: or i32 {{.*}}, 1
-// CHECK: store i32 {{.*}}, i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51"
-// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"(%struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A")
-// CHECK: call i32 @atexit(void ()* @"\01??__FTheS@?1??getS@@YAAAUS@@XZ@YAXXZ")
+// CHECK: store i32 {{.*}}, i32* @"??_B?1??getS@@YAAAUS@@XZ@51"
+// CHECK: call x86_thiscallcc %struct.S* @"??0S@@QAE@XZ"(%struct.S* @"?TheS@?1??getS@@YAAAUS@@XZ@4U2@A")
+// CHECK: call i32 @atexit(void ()* @"??__FTheS@?1??getS@@YAAAUS@@XZ@YAXXZ")
// CHECK: br label
// init.end:
-// CHECK: ret %struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A"
+// CHECK: ret %struct.S* @"?TheS@?1??getS@@YAAAUS@@XZ@4U2@A"
inline int enum_in_function() {
- // CHECK-LABEL: define linkonce_odr dso_local i32 @"\01?enum_in_function@@YAHXZ"() {{.*}} comdat
+ // CHECK-LABEL: define linkonce_odr dso_local i32 @"?enum_in_function@@YAHXZ"() {{.*}} comdat
static enum e { foo, bar, baz } x;
- // CHECK: @"\01?x@?1??enum_in_function@@YAHXZ@4W4e@?1??1@YAHXZ@A"
+ // CHECK: @"?x@?1??enum_in_function@@YAHXZ@4W4e@?1??1@YAHXZ@A"
static int y;
- // CHECK: @"\01?y@?1??enum_in_function@@YAHXZ@4HA"
+ // CHECK: @"?y@?1??enum_in_function@@YAHXZ@4HA"
return x + y;
};
struct T {
enum e { foo, bar, baz };
int enum_in_struct() {
- // CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc i32 @"\01?enum_in_struct@T@@QAEHXZ"({{.*}}) {{.*}} comdat
+ // CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc i32 @"?enum_in_struct@T@@QAEHXZ"({{.*}}) {{.*}} comdat
static int x;
- // CHECK: @"\01?x@?1??enum_in_struct@T@@QAEHXZ@4HA"
+ // CHECK: @"?x@?1??enum_in_struct@T@@QAEHXZ@4HA"
return x++;
}
};
inline int switch_test(int x) {
- // CHECK-LABEL: define linkonce_odr dso_local i32 @"\01?switch_test@@YAHH@Z"(i32 %x) {{.*}} comdat
+ // CHECK-LABEL: define linkonce_odr dso_local i32 @"?switch_test@@YAHH@Z"(i32 %x) {{.*}} comdat
switch (x) {
static int a;
- // CHECK: @"\01?a@?3??switch_test@@YAHH@Z@4HA"
+ // CHECK: @"?a@?3??switch_test@@YAHH@Z@4HA"
case 0:
a++;
return 1;
case 1:
static int b;
- // CHECK: @"\01?b@?3??switch_test@@YAHH@Z@4HA"
+ // CHECK: @"?b@?3??switch_test@@YAHH@Z@4HA"
return b++;
case 2: {
static int c;
- // CHECK: @"\01?c@?4??switch_test@@YAHH@Z@4HA"
+ // CHECK: @"?c@?4??switch_test@@YAHH@Z@4HA"
return b + c++;
}
};
@@ -198,8 +198,8 @@
int f();
inline void switch_test2() {
- // CHECK-LABEL: define linkonce_odr dso_local void @"\01?switch_test2@@YAXXZ"() {{.*}} comdat
- // CHECK: @"\01?x@?2??switch_test2@@YAXXZ@4HA"
+ // CHECK-LABEL: define linkonce_odr dso_local void @"?switch_test2@@YAXXZ"() {{.*}} comdat
+ // CHECK: @"?x@?2??switch_test2@@YAXXZ@4HA"
switch (1) default: static int x = f();
}
@@ -213,9 +213,9 @@
template struct __declspec(dllimport) A<int>;
inline int switch_test3() {
- // CHECK-LABEL: define linkonce_odr dso_local i32 @"\01?switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ"() {{.*}} comdat
+ // CHECK-LABEL: define linkonce_odr dso_local i32 @"?switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ"() {{.*}} comdat
static int local;
- // CHECK: @"\01?local@?1??switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ@4HA"
+ // CHECK: @"?local@?1??switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ@4HA"
return local++;
}
}
@@ -231,21 +231,21 @@
DynamicDLLImportInitVSMangling::switch_test3();
}
-// CHECK: define linkonce_odr dso_local void @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ"() {{.*}} comdat
+// CHECK: define linkonce_odr dso_local void @"??__Efoo@?$B@H@@2VA@@A@YAXXZ"() {{.*}} comdat
// CHECK-NOT: and
// CHECK-NOT: ?_Bfoo@
-// CHECK: call x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"
-// CHECK: call i32 @atexit(void ()* @"\01??__Ffoo@?$B@H@@2VA@@A@YAXXZ")
+// CHECK: call x86_thiscallcc %class.A* @"??0A@@QAE@XZ"
+// CHECK: call i32 @atexit(void ()* @"??__Ffoo@?$B@H@@2VA@@A@YAXXZ")
// CHECK: ret void
-// CHECK: define linkonce_odr dso_local x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"({{.*}}) {{.*}} comdat
+// CHECK: define linkonce_odr dso_local x86_thiscallcc %class.A* @"??0A@@QAE@XZ"({{.*}}) {{.*}} comdat
-// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) {{.*}} comdat
+// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) {{.*}} comdat
-// CHECK: define internal void @"\01??__Ffoo@?$B@H@@2VA@@A@YAXXZ"
-// CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"{{.*}}foo
+// CHECK: define internal void @"??__Ffoo@?$B@H@@2VA@@A@YAXXZ"
+// CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"{{.*}}foo
// CHECK: ret void
// CHECK: define internal void @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp()
-// CHECK: call void @"\01??__Es@@YAXXZ"()
+// CHECK: call void @"??__Es@@YAXXZ"()
// CHECK: ret void
diff --git a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
index 4c0a9be..1aa0893 100644
--- a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
@@ -5,7 +5,7 @@
~A() {}
};
template class A<char>;
-// CHECK-DAG: define weak_odr dso_local x86_thiscallcc void @"\01??1?$A@D@test1@@AAE@XZ"
+// CHECK-DAG: define weak_odr dso_local x86_thiscallcc void @"??1?$A@D@test1@@AAE@XZ"
}
namespace test2 {
@@ -22,14 +22,14 @@
void foo() {
B b;
}
-// CHECK-DAG: @"\01??1B@test2@@UAE@XZ" = dso_local alias void (%"struct.test2::B"*), bitcast (void (%"struct.test2::A"*)* @"\01??1A@test2@@UAE@XZ" to void (%"struct.test2::B"*)*)
+// CHECK-DAG: @"??1B@test2@@UAE@XZ" = dso_local alias void (%"struct.test2::B"*), bitcast (void (%"struct.test2::A"*)* @"??1A@test2@@UAE@XZ" to void (%"struct.test2::B"*)*)
}
namespace test3 {
struct A { virtual ~A(); };
A::~A() {}
}
-// CHECK-DAG: define dso_local x86_thiscallcc void @"\01??1A@test3@@UAE@XZ"(
+// CHECK-DAG: define dso_local x86_thiscallcc void @"??1A@test3@@UAE@XZ"(
namespace test3 {
template <typename T>
struct B : A {
@@ -39,4 +39,4 @@
}
// This has to be weak, and emitting weak aliases is fragile, so we don't do the
// aliasing.
-// CHECK-DAG: define weak_odr dso_local x86_thiscallcc void @"\01??1?$B@H@test3@@UAE@XZ"(
+// CHECK-DAG: define weak_odr dso_local x86_thiscallcc void @"??1?$B@H@test3@@UAE@XZ"(
diff --git a/test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp b/test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp
index f9e1880..6c4f370 100644
--- a/test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp
@@ -8,5 +8,5 @@
};
template <class T> void foo(T t) { new ImplicitCtor; }
void bar() { foo(0); }
-// CHECK: store {{.*}} @"\01??_7ImplicitCtor@vtable_referenced_from_template@@6B@"
+// CHECK: store {{.*}} @"??_7ImplicitCtor@vtable_referenced_from_template@@6B@"
}
diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp
index 138af04..97b90ce 100644
--- a/test/CodeGenCXX/microsoft-abi-structors.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -20,7 +20,7 @@
void no_constructor_destructor_infinite_recursion() {
A a;
-// CHECK: define linkonce_odr dso_local x86_thiscallcc %"class.basic::A"* @"\01??0A@basic@@QAE@XZ"(%"class.basic::A"* returned %this) {{.*}} comdat {{.*}} {
+// CHECK: define linkonce_odr dso_local x86_thiscallcc %"class.basic::A"* @"??0A@basic@@QAE@XZ"(%"class.basic::A"* returned %this) {{.*}} comdat {{.*}} {
// CHECK: [[THIS_ADDR:%[.0-9A-Z_a-z]+]] = alloca %"class.basic::A"*, align 4
// CHECK-NEXT: store %"class.basic::A"* %this, %"class.basic::A"** [[THIS_ADDR]], align 4
// CHECK-NEXT: [[T1:%[.0-9A-Z_a-z]+]] = load %"class.basic::A"*, %"class.basic::A"** [[THIS_ADDR]]
@@ -30,8 +30,8 @@
A::~A() {
// Make sure that the destructor doesn't call itself:
-// CHECK: define {{.*}} @"\01??1A@basic@@QAE@XZ"
-// CHECK-NOT: call void @"\01??1A@basic@@QAE@XZ"
+// CHECK: define {{.*}} @"??1A@basic@@QAE@XZ"
+// CHECK-NOT: call void @"??1A@basic@@QAE@XZ"
// CHECK: ret
}
@@ -41,23 +41,23 @@
// Tests that we can define constructors outside the class (PR12784).
B::B() {
- // CHECK: define dso_local x86_thiscallcc %"struct.basic::B"* @"\01??0B@basic@@QAE@XZ"(%"struct.basic::B"* returned %this)
+ // CHECK: define dso_local x86_thiscallcc %"struct.basic::B"* @"??0B@basic@@QAE@XZ"(%"struct.basic::B"* returned %this)
// CHECK: ret
}
struct C {
virtual ~C() {
-// DTORS: define linkonce_odr dso_local x86_thiscallcc i8* @"\01??_GC@basic@@UAEPAXI@Z"(%"struct.basic::C"* %this, i32 %should_call_delete) {{.*}} comdat {{.*}} {
+// DTORS: define linkonce_odr dso_local x86_thiscallcc i8* @"??_GC@basic@@UAEPAXI@Z"(%"struct.basic::C"* %this, i32 %should_call_delete) {{.*}} comdat {{.*}} {
// DTORS: store i32 %should_call_delete, i32* %[[SHOULD_DELETE_VAR:[0-9a-z._]+]], align 4
// DTORS: store i8* %{{.*}}, i8** %[[RETVAL:[0-9a-z._]+]]
// DTORS: %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i32, i32* %[[SHOULD_DELETE_VAR]]
-// DTORS: call x86_thiscallcc void @"\01??1C@basic@@UAE@XZ"(%"struct.basic::C"* %[[THIS:[0-9a-z]+]])
+// DTORS: call x86_thiscallcc void @"??1C@basic@@UAE@XZ"(%"struct.basic::C"* %[[THIS:[0-9a-z]+]])
// DTORS-NEXT: %[[CONDITION:[0-9]+]] = icmp eq i32 %[[SHOULD_DELETE_VALUE]], 0
// DTORS-NEXT: br i1 %[[CONDITION]], label %[[CONTINUE_LABEL:[0-9a-z._]+]], label %[[CALL_DELETE_LABEL:[0-9a-z._]+]]
//
// DTORS: [[CALL_DELETE_LABEL]]
// DTORS-NEXT: %[[THIS_AS_VOID:[0-9a-z]+]] = bitcast %"struct.basic::C"* %[[THIS]] to i8*
-// DTORS-NEXT: call void @"\01??3@YAXPAX@Z"(i8* %[[THIS_AS_VOID]])
+// DTORS-NEXT: call void @"??3@YAXPAX@Z"(i8* %[[THIS_AS_VOID]])
// DTORS-NEXT: br label %[[CONTINUE_LABEL]]
//
// DTORS: [[CONTINUE_LABEL]]
@@ -65,7 +65,7 @@
// DTORS-NEXT: ret i8* %[[RET]]
// Check that we do the mangling correctly on x64.
-// DTORS-X64: @"\01??_GC@basic@@UEAAPEAXI@Z"
+// DTORS-X64: @"??_GC@basic@@UEAAPEAXI@Z"
}
virtual void foo();
};
@@ -77,11 +77,11 @@
C c;
// The vftable pointer should point at the beginning of the vftable.
// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to i32 (...)***
-// CHECK: store i32 (...)** bitcast ({ [2 x i8*] }* @"\01??_7C@basic@@6B@" to i32 (...)**), i32 (...)*** [[THIS_PTR]]
+// CHECK: store i32 (...)** bitcast ({ [2 x i8*] }* @"??_7C@basic@@6B@" to i32 (...)**), i32 (...)*** [[THIS_PTR]]
}
void call_complete_dtor(C *obj_ptr) {
-// CHECK: define dso_local void @"\01?call_complete_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
+// CHECK: define dso_local void @"?call_complete_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
obj_ptr->~C();
// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"*, %"struct.basic::C"** %{{.*}}, align 4
// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)***
@@ -93,7 +93,7 @@
}
void call_deleting_dtor(C *obj_ptr) {
-// CHECK: define dso_local void @"\01?call_deleting_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
+// CHECK: define dso_local void @"?call_deleting_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
delete obj_ptr;
// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"*, %"struct.basic::C"** %{{.*}}, align 4
// CHECK: br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]]
@@ -108,7 +108,7 @@
}
void call_deleting_dtor_and_global_delete(C *obj_ptr) {
-// CHECK: define dso_local void @"\01?call_deleting_dtor_and_global_delete@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
+// CHECK: define dso_local void @"?call_deleting_dtor_and_global_delete@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
::delete obj_ptr;
// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"*, %"struct.basic::C"** %{{.*}}, align 4
// CHECK: br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]]
@@ -119,7 +119,7 @@
// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
// CHECK-NEXT: %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]]
// CHECK-NEXT: %[[CALL:.*]] = call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 0)
-// CHECK-NEXT: call void @"\01??3@YAXPAX@Z"(i8* %[[CALL]])
+// CHECK-NEXT: call void @"??3@YAXPAX@Z"(i8* %[[CALL]])
// CHECK: ret void
}
@@ -129,12 +129,12 @@
D() {
static int ctor_static = foo();
// CHECK that the static in the ctor gets mangled correctly:
- // CHECK: @"\01?ctor_static@?1???0D@basic@@QAE@XZ@4HA"
+ // CHECK: @"?ctor_static@?1???0D@basic@@QAE@XZ@4HA"
}
~D() {
static int dtor_static = foo();
// CHECK that the static in the dtor gets mangled correctly:
- // CHECK: @"\01?dtor_static@?1???1D@basic@@QAE@XZ@4HA"
+ // CHECK: @"?dtor_static@?1???1D@basic@@QAE@XZ@4HA"
}
};
@@ -155,7 +155,7 @@
};
C::~C() {
-// CHECK-LABEL: define dso_local x86_thiscallcc void @"\01??1C@dtor_in_second_nvbase@@UAE@XZ"
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"??1C@dtor_in_second_nvbase@@UAE@XZ"
// CHECK: (%"struct.dtor_in_second_nvbase::C"* %this)
// No this adjustment!
// CHECK-NOT: getelementptr
@@ -164,7 +164,7 @@
// CHECK: bitcast %"struct.dtor_in_second_nvbase::C"* %{{.*}} to i8*
// CHECK: getelementptr inbounds i8, i8* %{{.*}}, i32 4
// CHECK: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::B"*
-// CHECK: call x86_thiscallcc void @"\01??1B@dtor_in_second_nvbase@@UAE@XZ"
+// CHECK: call x86_thiscallcc void @"??1B@dtor_in_second_nvbase@@UAE@XZ"
// CHECK: (%"struct.dtor_in_second_nvbase::B"* %{{.*}})
// CHECK: ret void
}
@@ -172,12 +172,12 @@
void foo() {
C c;
}
-// DTORS2-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"\01??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z"
+// DTORS2-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z"
// DTORS2: (%"struct.dtor_in_second_nvbase::C"* %this, i32 %should_call_delete)
// Do an adjustment from B* to C*.
// DTORS2: getelementptr i8, i8* %{{.*}}, i32 -4
// DTORS2: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::C"*
-// DTORS2: %[[CALL:.*]] = tail call x86_thiscallcc i8* @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z"
+// DTORS2: %[[CALL:.*]] = tail call x86_thiscallcc i8* @"??_GC@dtor_in_second_nvbase@@UAEPAXI@Z"
// DTORS2: ret i8* %[[CALL]]
}
@@ -196,7 +196,7 @@
struct F : D, E { ~F(); int f; };
F::~F() {
-// CHECK-LABEL: define dso_local x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"(%"struct.test2::F"*{{[^,]*}})
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"??1F@test2@@UAE@XZ"(%"struct.test2::F"*{{[^,]*}})
// Do an adjustment from C vbase subobject to F as though F was the
// complete type.
// CHECK: getelementptr inbounds i8, i8* %{{.*}}, i32 -20
@@ -207,11 +207,11 @@
void foo() {
F f;
}
-// DTORS3-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"\01??_DF@test2@@QAEXXZ"({{.*}} {{.*}} comdat
+// DTORS3-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"??_DF@test2@@QAEXXZ"({{.*}} {{.*}} comdat
// Do an adjustment from C* to F*.
// DTORS3: getelementptr i8, i8* %{{.*}}, i32 20
// DTORS3: bitcast i8* %{{.*}} to %"struct.test2::F"*
-// DTORS3: call x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"
+// DTORS3: call x86_thiscallcc void @"??1F@test2@@UAE@XZ"
// DTORS3: ret void
}
@@ -228,8 +228,8 @@
};
B::B() {
- // CHECK: define dso_local x86_thiscallcc %"struct.constructors::B"* @"\01??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* returned %this)
- // CHECK: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
+ // CHECK: define dso_local x86_thiscallcc %"struct.constructors::B"* @"??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* returned %this)
+ // CHECK: call x86_thiscallcc %"struct.constructors::A"* @"??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
// CHECK: ret
}
@@ -238,7 +238,7 @@
};
C::C() {
- // CHECK: define dso_local x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* returned %this, i32 %is_most_derived)
+ // CHECK: define dso_local x86_thiscallcc %"struct.constructors::C"* @"??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* returned %this, i32 %is_most_derived)
// TODO: make sure this works in the Release build too;
// CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
// CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
@@ -249,23 +249,23 @@
// CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::C"* %{{.*}} to i8*
// CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0
// CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
- // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8C@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
+ // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"??_8C@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
// CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to i8*
// CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4
// CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
- // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
+ // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
// CHECK-NEXT: br label %[[SKIP_VBASES]]
//
// CHECK: [[SKIP_VBASES]]
// Class C does not define or override methods, so shouldn't change the vfptr.
- // CHECK-NOT: @"\01??_7C@constructors@@6B@"
+ // CHECK-NOT: @"??_7C@constructors@@6B@"
// CHECK: ret
}
void create_C() {
C c;
- // CHECK: define dso_local void @"\01?create_C@constructors@@YAXXZ"()
- // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %c, i32 1)
+ // CHECK: define dso_local void @"?create_C@constructors@@YAXXZ"()
+ // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %c, i32 1)
// CHECK: ret
}
@@ -274,7 +274,7 @@
};
D::D() {
- // CHECK: define dso_local x86_thiscallcc %"struct.constructors::D"* @"\01??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* returned %this, i32 %is_most_derived) unnamed_addr
+ // CHECK: define dso_local x86_thiscallcc %"struct.constructors::D"* @"??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* returned %this, i32 %is_most_derived) unnamed_addr
// CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
// CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
// CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
@@ -284,15 +284,15 @@
// CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::D"* %{{.*}} to i8*
// CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0
// CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
- // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8D@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
+ // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"??_8D@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
// CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to i8*
// CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4
// CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
- // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
+ // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
// CHECK-NEXT: br label %[[SKIP_VBASES]]
//
// CHECK: [[SKIP_VBASES]]
- // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
+ // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
// CHECK: ret
}
@@ -301,7 +301,7 @@
};
E::E() {
- // CHECK: define dso_local x86_thiscallcc %"struct.constructors::E"* @"\01??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* returned %this, i32 %is_most_derived) unnamed_addr
+ // CHECK: define dso_local x86_thiscallcc %"struct.constructors::E"* @"??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* returned %this, i32 %is_most_derived) unnamed_addr
// CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
// CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
// CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
@@ -311,15 +311,15 @@
// CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::E"* %{{.*}} to i8*
// CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0
// CHECK-NEXT: %[[vbptr_E:.*]] = bitcast i8* %[[offs]] to i32**
- // CHECK-NEXT: store i32* getelementptr inbounds ([3 x i32], [3 x i32]* @"\01??_8E@constructors@@7B01@@", i32 0, i32 0), i32** %[[vbptr_E]]
+ // CHECK-NEXT: store i32* getelementptr inbounds ([3 x i32], [3 x i32]* @"??_8E@constructors@@7B01@@", i32 0, i32 0), i32** %[[vbptr_E]]
// CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 4
// CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to i32**
- // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8E@constructors@@7BC@1@@", i32 0, i32 0), i32** %[[vbptr_C]]
+ // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"??_8E@constructors@@7BC@1@@", i32 0, i32 0), i32** %[[vbptr_C]]
// CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to i8*
// CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4
// CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
- // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
- // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
+ // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
+ // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
// CHECK-NEXT: br label %[[SKIP_VBASES]]
//
// CHECK: [[SKIP_VBASES]]
@@ -333,7 +333,7 @@
};
F::F() {}
-// CHECK: define dso_local x86_thiscallcc %"struct.constructors::F"* @"\01??0F@constructors@@QAE@XZ"
+// CHECK: define dso_local x86_thiscallcc %"struct.constructors::F"* @"??0F@constructors@@QAE@XZ"
} // end namespace constructors
@@ -345,12 +345,12 @@
void call_nv_complete(A *a) {
a->~A();
-// CHECK: define dso_local void @"\01?call_nv_complete@dtors@@YAXPAUA@1@@Z"
-// CHECK: call x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
+// CHECK: define dso_local void @"?call_nv_complete@dtors@@YAXPAUA@1@@Z"
+// CHECK: call x86_thiscallcc void @"??1A@dtors@@QAE@XZ"
// CHECK: ret
}
-// CHECK: declare dso_local x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
+// CHECK: declare dso_local x86_thiscallcc void @"??1A@dtors@@QAE@XZ"
// Now try some virtual bases, where we need the complete dtor.
@@ -360,24 +360,24 @@
void call_vbase_complete(D *d) {
d->~D();
-// CHECK: define dso_local void @"\01?call_vbase_complete@dtors@@YAXPAUD@1@@Z"
-// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
+// CHECK: define dso_local void @"?call_vbase_complete@dtors@@YAXPAUD@1@@Z"
+// CHECK: call x86_thiscallcc void @"??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
// CHECK: ret
}
// The complete dtor should call the base dtors for D and the vbase A (once).
-// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"({{.*}}) {{.*}} comdat
+// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"??_DD@dtors@@QAEXXZ"({{.*}}) {{.*}} comdat
// CHECK-NOT: call
-// CHECK: call x86_thiscallcc void @"\01??1D@dtors@@QAE@XZ"
+// CHECK: call x86_thiscallcc void @"??1D@dtors@@QAE@XZ"
// CHECK-NOT: call
-// CHECK: call x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
+// CHECK: call x86_thiscallcc void @"??1A@dtors@@QAE@XZ"
// CHECK-NOT: call
// CHECK: ret
void destroy_d_complete() {
D d;
-// CHECK: define dso_local void @"\01?destroy_d_complete@dtors@@YAXXZ"
-// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
+// CHECK: define dso_local void @"?destroy_d_complete@dtors@@YAXXZ"
+// CHECK: call x86_thiscallcc void @"??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
// CHECK: ret
}
@@ -386,9 +386,9 @@
// a vftable.
void call_nv_deleting_dtor(D *d) {
delete d;
-// CHECK: define dso_local void @"\01?call_nv_deleting_dtor@dtors@@YAXPAUD@1@@Z"
-// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
-// CHECK: call void @"\01??3@YAXPAX@Z"
+// CHECK: define dso_local void @"?call_nv_deleting_dtor@dtors@@YAXPAUD@1@@Z"
+// CHECK: call x86_thiscallcc void @"??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
+// CHECK: call void @"??3@YAXPAX@Z"
// CHECK: ret
}
@@ -404,11 +404,11 @@
B::B(int *a) {}
B::B(const char *a, ...) {}
B::B(short *a) {}
-// CHECK: define dso_local x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z"
+// CHECK: define dso_local x86_thiscallcc %"struct.test1::B"* @"??0B@test1@@QAE@PAH@Z"
// CHECK: (%"struct.test1::B"* returned %this, i32* %a, i32 %is_most_derived)
-// CHECK: define dso_local %"struct.test1::B"* @"\01??0B@test1@@QAA@PBDZZ"
+// CHECK: define dso_local %"struct.test1::B"* @"??0B@test1@@QAA@PBDZZ"
// CHECK: (%"struct.test1::B"* returned %this, i32 %is_most_derived, i8* %a, ...)
-// CHECK: define dso_local x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAF@Z"
+// CHECK: define dso_local x86_thiscallcc %"struct.test1::B"* @"??0B@test1@@QAE@PAF@Z"
// CHECK: (%"struct.test1::B"* returned %this, i16* %a, i32 %is_most_derived)
void construct_b() {
@@ -416,10 +416,10 @@
B b1(&a);
B b2("%d %d", 1, 2);
}
-// CHECK-LABEL: define dso_local void @"\01?construct_b@test1@@YAXXZ"()
-// CHECK: call x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z"
+// CHECK-LABEL: define dso_local void @"?construct_b@test1@@YAXXZ"()
+// CHECK: call x86_thiscallcc %"struct.test1::B"* @"??0B@test1@@QAE@PAH@Z"
// CHECK: (%"struct.test1::B"* {{.*}}, i32* {{.*}}, i32 1)
-// CHECK: call %"struct.test1::B"* (%"struct.test1::B"*, i32, i8*, ...) @"\01??0B@test1@@QAA@PBDZZ"
+// CHECK: call %"struct.test1::B"* (%"struct.test1::B"*, i32, i8*, ...) @"??0B@test1@@QAA@PBDZZ"
// CHECK: (%"struct.test1::B"* {{.*}}, i32 1, i8* {{.*}}, i32 1, i32 2)
}
@@ -432,7 +432,7 @@
void CreateCopy(ImplicitCopy *a) {
new ImplicitCopy(*a);
}
-// CHECK: store {{.*}} @"\01??_7ImplicitCopy@implicit_copy_vtable@@6B@"
+// CHECK: store {{.*}} @"??_7ImplicitCopy@implicit_copy_vtable@@6B@"
struct MoveOnly {
MoveOnly(MoveOnly &&o) = default;
@@ -440,7 +440,7 @@
};
MoveOnly &&f();
void g() { new MoveOnly(f()); }
-// CHECK: store {{.*}} @"\01??_7MoveOnly@implicit_copy_vtable@@6B@"
+// CHECK: store {{.*}} @"??_7MoveOnly@implicit_copy_vtable@@6B@"
}
namespace delegating_ctor {
@@ -451,11 +451,11 @@
};
X::X(int) : X() {}
}
-// CHECK: define dso_local x86_thiscallcc %"struct.delegating_ctor::X"* @"\01??0X@delegating_ctor@@QAE@H@Z"(
+// CHECK: define dso_local x86_thiscallcc %"struct.delegating_ctor::X"* @"??0X@delegating_ctor@@QAE@H@Z"(
// CHECK: %[[is_most_derived_addr:.*]] = alloca i32, align 4
// CHECK: store i32 %is_most_derived, i32* %[[is_most_derived_addr]]
// CHECK: %[[is_most_derived:.*]] = load i32, i32* %[[is_most_derived_addr]]
-// CHECK: call x86_thiscallcc {{.*}}* @"\01??0X@delegating_ctor@@QAE@XZ"({{.*}} i32 %[[is_most_derived]])
+// CHECK: call x86_thiscallcc {{.*}}* @"??0X@delegating_ctor@@QAE@XZ"({{.*}} i32 %[[is_most_derived]])
// Dtor thunks for classes in anonymous namespaces should be internal, not
// linkonce_odr.
@@ -467,9 +467,9 @@
void *getA() {
return (void*)new A();
}
-// CHECK: define internal x86_thiscallcc i8* @"\01??_GA@?A@@UAEPAXI@Z"
+// CHECK: define internal x86_thiscallcc i8* @"??_GA@?A@@UAEPAXI@Z"
// CHECK: (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete)
-// CHECK: define internal x86_thiscallcc void @"\01??1A@?A@@UAE@XZ"
+// CHECK: define internal x86_thiscallcc void @"??1A@?A@@UAE@XZ"
// CHECK: (%"struct.(anonymous namespace)::A"* %this)
// Check that we correctly transform __stdcall to __thiscall for ctors and
@@ -477,9 +477,9 @@
class G {
public:
__stdcall G() {};
-// DTORS4: define linkonce_odr dso_local x86_thiscallcc %class.G* @"\01??0G@@QAE@XZ"
+// DTORS4: define linkonce_odr dso_local x86_thiscallcc %class.G* @"??0G@@QAE@XZ"
__stdcall ~G() {};
-// DTORS4: define linkonce_odr dso_local x86_thiscallcc void @"\01??1G@@QAE@XZ"
+// DTORS4: define linkonce_odr dso_local x86_thiscallcc void @"??1G@@QAE@XZ"
};
extern void testG() {
diff --git a/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp b/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
index 767286e..a5bb874 100644
--- a/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
+++ b/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
@@ -6,79 +6,79 @@
~S();
};
-// CHECK-DAG: @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A" = linkonce_odr dso_local thread_local global %struct.S zeroinitializer
-// CHECK-DAG: @"\01??__J?1??f@@YAAAUS@@XZ@51" = linkonce_odr thread_local global i32 0
-// CHECK-DAG: @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A" = linkonce_odr dso_local global %struct.S zeroinitializer
-// CHECK-DAG: @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" = linkonce_odr global i32 0
+// CHECK-DAG: @"?s@?1??f@@YAAAUS@@XZ@4U2@A" = linkonce_odr dso_local thread_local global %struct.S zeroinitializer
+// CHECK-DAG: @"??__J?1??f@@YAAAUS@@XZ@51" = linkonce_odr thread_local global i32 0
+// CHECK-DAG: @"?s@?1??g@@YAAAUS@@XZ@4U2@A" = linkonce_odr dso_local global %struct.S zeroinitializer
+// CHECK-DAG: @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA" = linkonce_odr global i32 0
// CHECK-DAG: @_Init_thread_epoch = external thread_local global i32, align 4
-// CHECK-DAG: @"\01?j@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr dso_local thread_local global %struct.S zeroinitializer
-// CHECK-DAG: @"\01??__J?1??h@@YAAAUS@@_N@Z@51" = linkonce_odr thread_local global i32 0
-// CHECK-DAG: @"\01?i@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr dso_local global %struct.S zeroinitializer
-// CHECK-DAG: @"\01?$TSS0@?1??h@@YAAAUS@@_N@Z@4HA" = linkonce_odr global i32 0
-// CHECK-DAG: @"\01?i@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4
-// CHECK-DAG: @"\01?$TSS0@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4
+// CHECK-DAG: @"?j@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr dso_local thread_local global %struct.S zeroinitializer
+// CHECK-DAG: @"??__J?1??h@@YAAAUS@@_N@Z@51" = linkonce_odr thread_local global i32 0
+// CHECK-DAG: @"?i@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr dso_local global %struct.S zeroinitializer
+// CHECK-DAG: @"?$TSS0@?1??h@@YAAAUS@@_N@Z@4HA" = linkonce_odr global i32 0
+// CHECK-DAG: @"?i@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4
+// CHECK-DAG: @"?$TSS0@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4
-// CHECK-LABEL: define {{.*}} @"\01?f@@YAAAUS@@XZ"()
+// CHECK-LABEL: define {{.*}} @"?f@@YAAAUS@@XZ"()
// CHECK-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
extern inline S &f() {
static thread_local S s;
-// CHECK: %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
+// CHECK: %[[guard:.*]] = load i32, i32* @"??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT: %[[mask:.*]] = and i32 %[[guard]], 1
// CHECK-NEXT: %[[cmp:.*]] = icmp eq i32 %[[mask]], 0
// CHECK-NEXT: br i1 %[[cmp]], label %[[init:.*]], label %[[init_end:.*]], !prof ![[unlikely_threadlocal:.*]]
//
// CHECK: [[init]]:
// CHECK-NEXT: %[[or:.*]] = or i32 %[[guard]], 1
-// CHECK-NEXT: store i32 %[[or]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
-// CHECK-NEXT: invoke {{.*}} @"\01??0S@@QAE@XZ"(%struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A")
+// CHECK-NEXT: store i32 %[[or]], i32* @"??__J?1??f@@YAAAUS@@XZ@51"
+// CHECK-NEXT: invoke {{.*}} @"??0S@@QAE@XZ"(%struct.S* @"?s@?1??f@@YAAAUS@@XZ@4U2@A")
// CHECK-NEXT: to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]
//
// CHECK: [[invoke_cont]]:
-// CHECK-NEXT: call i32 @__tlregdtor(void ()* @"\01??__Fs@?1??f@@YAAAUS@@XZ@YAXXZ")
+// CHECK-NEXT: call i32 @__tlregdtor(void ()* @"??__Fs@?1??f@@YAAAUS@@XZ@YAXXZ")
// CHECK-NEXT: br label %[[init_end:.*]]
// CHECK: [[init_end]]:
-// CHECK-NEXT: ret %struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A"
+// CHECK-NEXT: ret %struct.S* @"?s@?1??f@@YAAAUS@@XZ@4U2@A"
// CHECK: [[lpad:.*]]:
// CHECK-NEXT: cleanuppad within none []
-// CHECK: %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
+// CHECK: %[[guard:.*]] = load i32, i32* @"??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT: %[[mask:.*]] = and i32 %[[guard]], -2
-// CHECK-NEXT: store i32 %[[mask]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
+// CHECK-NEXT: store i32 %[[mask]], i32* @"??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT: cleanupret {{.*}} unwind to caller
return s;
}
-// CHECK-LABEL: define {{.*}} @"\01?g@@YAAAUS@@XZ"()
+// CHECK-LABEL: define {{.*}} @"?g@@YAAAUS@@XZ"()
extern inline S &g() {
static S s;
-// CHECK: %[[guard:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4
+// CHECK: %[[guard:.*]] = load atomic i32, i32* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4
// CHECK-NEXT: %[[epoch:.*]] = load i32, i32* @_Init_thread_epoch
// CHECK-NEXT: %[[cmp:.*]] = icmp sgt i32 %[[guard]], %[[epoch]]
// CHECK-NEXT: br i1 %[[cmp]], label %[[init_attempt:.*]], label %[[init_end:.*]], !prof ![[unlikely_staticlocal:.*]]
//
// CHECK: [[init_attempt]]:
-// CHECK-NEXT: call void @_Init_thread_header(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
-// CHECK-NEXT: %[[guard2:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4
+// CHECK-NEXT: call void @_Init_thread_header(i32* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
+// CHECK-NEXT: %[[guard2:.*]] = load atomic i32, i32* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4
// CHECK-NEXT: %[[cmp2:.*]] = icmp eq i32 %[[guard2]], -1
// CHECK-NEXT: br i1 %[[cmp2]], label %[[init:.*]], label %[[init_end:.*]]
//
// CHECK: [[init]]:
-// CHECK-NEXT: invoke {{.*}} @"\01??0S@@QAE@XZ"(%struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A")
+// CHECK-NEXT: invoke {{.*}} @"??0S@@QAE@XZ"(%struct.S* @"?s@?1??g@@YAAAUS@@XZ@4U2@A")
// CHECK-NEXT: to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]
//
// CHECK: [[invoke_cont]]:
-// CHECK-NEXT: call i32 @atexit(void ()* @"\01??__Fs@?1??g@@YAAAUS@@XZ@YAXXZ")
-// CHECK-NEXT: call void @_Init_thread_footer(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
+// CHECK-NEXT: call i32 @atexit(void ()* @"??__Fs@?1??g@@YAAAUS@@XZ@YAXXZ")
+// CHECK-NEXT: call void @_Init_thread_footer(i32* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
// CHECK-NEXT: br label %init.end
//
// CHECK: [[init_end]]:
-// CHECK-NEXT: ret %struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A"
+// CHECK-NEXT: ret %struct.S* @"?s@?1??g@@YAAAUS@@XZ@4U2@A"
//
// CHECK: [[lpad]]:
// CHECK-NEXT: cleanuppad within none []
-// CHECK: call void @_Init_thread_abort(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
+// CHECK: call void @_Init_thread_abort(i32* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
// CHECK-NEXT: cleanupret {{.*}} unwind to caller
return s;
}
@@ -89,7 +89,7 @@
return b ? j : i;
}
-// CHECK-LABEL: define dso_local i32 @"\01?g1@@YAHXZ"()
+// CHECK-LABEL: define dso_local i32 @"?g1@@YAHXZ"()
int f1();
int g1() {
static int i = f1();
diff --git a/test/CodeGenCXX/microsoft-abi-throw.cpp b/test/CodeGenCXX/microsoft-abi-throw.cpp
index 51076f8..8800e97 100644
--- a/test/CodeGenCXX/microsoft-abi-throw.cpp
+++ b/test/CodeGenCXX/microsoft-abi-throw.cpp
@@ -1,23 +1,23 @@
// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions -fms-extensions | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions -fms-extensions -DSTD | FileCheck %s
-// CHECK-DAG: @"\01??_R0?AUY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUY@@\00" }, comdat
-// CHECK-DAG: @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUY@@@8" to i8*), i32 0, i32 -1, i32 0, i32 8, i8* bitcast (%struct.Y* (%struct.Y*, %struct.Y*, i32)* @"\01??0Y@@QAE@ABU0@@Z" to i8*) }, section ".xdata", comdat
-// CHECK-DAG: @"\01??_R0?AUZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUZ@@\00" }, comdat
-// CHECK-DAG: @"_CT??_R0?AUZ@@@81" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUZ@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* null }, section ".xdata", comdat
-// CHECK-DAG: @"\01??_R0?AUW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUW@@\00" }, comdat
-// CHECK-DAG: @"_CT??_R0?AUW@@@8??0W@@QAE@ABU0@@Z44" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUW@@@8" to i8*), i32 4, i32 -1, i32 0, i32 4, i8* bitcast (%struct.W* (%struct.W*, %struct.W*, i32)* @"\01??0W@@QAE@ABU0@@Z" to i8*) }, section ".xdata", comdat
-// CHECK-DAG: @"\01??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
-// CHECK-DAG: @"_CT??_R0?AUM@@@818" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 8, i32 -1, i32 0, i32 1, i8* null }, section ".xdata", comdat
-// CHECK-DAG: @"\01??_R0?AUV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUV@@\00" }, comdat
-// CHECK-DAG: @"_CT??_R0?AUV@@@81044" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i32 0, i32 4, i32 4, i32 1, i8* null }, section ".xdata", comdat
+// CHECK-DAG: @"??_R0?AUY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUY@@\00" }, comdat
+// CHECK-DAG: @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUY@@@8" to i8*), i32 0, i32 -1, i32 0, i32 8, i8* bitcast (%struct.Y* (%struct.Y*, %struct.Y*, i32)* @"??0Y@@QAE@ABU0@@Z" to i8*) }, section ".xdata", comdat
+// CHECK-DAG: @"??_R0?AUZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUZ@@\00" }, comdat
+// CHECK-DAG: @"_CT??_R0?AUZ@@@81" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUZ@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* null }, section ".xdata", comdat
+// CHECK-DAG: @"??_R0?AUW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUW@@\00" }, comdat
+// CHECK-DAG: @"_CT??_R0?AUW@@@8??0W@@QAE@ABU0@@Z44" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUW@@@8" to i8*), i32 4, i32 -1, i32 0, i32 4, i8* bitcast (%struct.W* (%struct.W*, %struct.W*, i32)* @"??0W@@QAE@ABU0@@Z" to i8*) }, section ".xdata", comdat
+// CHECK-DAG: @"??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
+// CHECK-DAG: @"_CT??_R0?AUM@@@818" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUM@@@8" to i8*), i32 8, i32 -1, i32 0, i32 1, i8* null }, section ".xdata", comdat
+// CHECK-DAG: @"??_R0?AUV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUV@@\00" }, comdat
+// CHECK-DAG: @"_CT??_R0?AUV@@@81044" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUV@@@8" to i8*), i32 0, i32 4, i32 4, i32 1, i8* null }, section ".xdata", comdat
// CHECK-DAG: @"_CTA5?AUY@@" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.5 { i32 5, [5 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8", %eh.CatchableType* @"_CT??_R0?AUZ@@@81", %eh.CatchableType* @"_CT??_R0?AUW@@@8??0W@@QAE@ABU0@@Z44", %eh.CatchableType* @"_CT??_R0?AUM@@@818", %eh.CatchableType* @"_CT??_R0?AUV@@@81044"] }, section ".xdata", comdat
-// CHECK-DAG: @"_TI5?AUY@@" = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* bitcast (void (%struct.Y*)* @"\01??_DY@@QAEXXZ" to i8*), i8* null, i8* bitcast (%eh.CatchableTypeArray.5* @"_CTA5?AUY@@" to i8*) }, section ".xdata", comdat
-// CHECK-DAG: @"_CT??_R0?AUDefault@@@8??_ODefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor13* @"\01??_R0?AUDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Default*, %struct.Default*)* @"\01??_ODefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
-// CHECK-DAG: @"_CT??_R0?AUVariadic@@@8??_OVariadic@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor14* @"\01??_R0?AUVariadic@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Variadic*, %struct.Variadic*)* @"\01??_OVariadic@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
-// CHECK-DAG: @"_CT??_R0?AUTemplateWithDefault@@@8??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor25* @"\01??_R0?AUTemplateWithDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.TemplateWithDefault*, %struct.TemplateWithDefault*)* @"\01??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
+// CHECK-DAG: @"_TI5?AUY@@" = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* bitcast (void (%struct.Y*)* @"??_DY@@QAEXXZ" to i8*), i8* null, i8* bitcast (%eh.CatchableTypeArray.5* @"_CTA5?AUY@@" to i8*) }, section ".xdata", comdat
+// CHECK-DAG: @"_CT??_R0?AUDefault@@@8??_ODefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor13* @"??_R0?AUDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Default*, %struct.Default*)* @"??_ODefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
+// CHECK-DAG: @"_CT??_R0?AUVariadic@@@8??_OVariadic@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor14* @"??_R0?AUVariadic@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Variadic*, %struct.Variadic*)* @"??_OVariadic@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
+// CHECK-DAG: @"_CT??_R0?AUTemplateWithDefault@@@8??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor25* @"??_R0?AUTemplateWithDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.TemplateWithDefault*, %struct.TemplateWithDefault*)* @"??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
// CHECK-DAG: @"_CTA2$$T" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.2 { i32 2, [2 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0$$T@84", %eh.CatchableType* @"_CT??_R0PAX@84"] }, section ".xdata", comdat
-// CHECK-DAG: @"_CT??_R0P6AXXZ@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0P6AXXZ@8" to i8*), i32 0, i32 -1, i32 0, i32 4, i8* null }, section ".xdata", comdat
+// CHECK-DAG: @"_CT??_R0P6AXXZ@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0P6AXXZ@8" to i8*), i32 0, i32 -1, i32 0, i32 4, i8* null }, section ".xdata", comdat
// CHECK-DAG: @_CTA1P6AXXZ = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0P6AXXZ@84"] }, section ".xdata", comdat
// CHECK-DAG: @_TI1P6AXXZ = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1P6AXXZ to i8*) }, section ".xdata", comdat
// CHECK-DAG: @_TIU2PAPFAH = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 4, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.2* @_CTA2PAPFAH to i8*) }, section ".xdata", comdat
@@ -33,21 +33,21 @@
struct Y : Z, W, virtual V {};
void f(const Y &y) {
- // CHECK-LABEL: @"\01?f@@YAXABUY@@@Z"
- // CHECK: call x86_thiscallcc %struct.Y* @"\01??0Y@@QAE@ABU0@@Z"(%struct.Y* %[[mem:.*]], %struct.Y*
+ // CHECK-LABEL: @"?f@@YAXABUY@@@Z"
+ // CHECK: call x86_thiscallcc %struct.Y* @"??0Y@@QAE@ABU0@@Z"(%struct.Y* %[[mem:.*]], %struct.Y*
// CHECK: %[[cast:.*]] = bitcast %struct.Y* %[[mem]] to i8*
// CHECK: call void @_CxxThrowException(i8* %[[cast]], %eh.ThrowInfo* @"_TI5?AUY@@")
throw y;
}
void g(const int *const *y) {
- // CHECK-LABEL: @"\01?g@@YAXPBQBH@Z"
+ // CHECK-LABEL: @"?g@@YAXPBQBH@Z"
// CHECK: call void @_CxxThrowException(i8* %{{.*}}, %eh.ThrowInfo* @_TIC2PAPBH)
throw y;
}
void h(__unaligned int * __unaligned *y) {
- // CHECK-LABEL: @"\01?h@@YAXPFAPFAH@Z"
+ // CHECK-LABEL: @"?h@@YAXPFAPFAH@Z"
// CHECK: call void @_CxxThrowException(i8* %{{.*}}, %eh.ThrowInfo* @_TIU2PAPFAH)
throw y;
}
@@ -56,14 +56,14 @@
Default(Default &, int = 42);
};
-// CHECK-LABEL: @"\01??_ODefault@@QAEXAAU0@@Z"
+// CHECK-LABEL: @"??_ODefault@@QAEXAAU0@@Z"
// CHECK: %[[src_addr:.*]] = alloca
// CHECK: %[[this_addr:.*]] = alloca
// CHECK: store {{.*}} %src, {{.*}} %[[src_addr]], align 4
// CHECK: store {{.*}} %this, {{.*}} %[[this_addr]], align 4
// CHECK: %[[this:.*]] = load {{.*}} %[[this_addr]]
// CHECK: %[[src:.*]] = load {{.*}} %[[src_addr]]
-// CHECK: call x86_thiscallcc {{.*}} @"\01??0Default@@QAE@AAU0@H@Z"({{.*}} %[[this]], {{.*}} %[[src]], i32 42)
+// CHECK: call x86_thiscallcc {{.*}} @"??0Default@@QAE@AAU0@H@Z"({{.*}} %[[this]], {{.*}} %[[src]], i32 42)
// CHECK: ret void
void h(Default &d) {
@@ -78,14 +78,14 @@
throw v;
}
-// CHECK-LABEL: @"\01??_OVariadic@@QAEXAAU0@@Z"
+// CHECK-LABEL: @"??_OVariadic@@QAEXAAU0@@Z"
// CHECK: %[[src_addr:.*]] = alloca
// CHECK: %[[this_addr:.*]] = alloca
// CHECK: store {{.*}} %src, {{.*}} %[[src_addr:.*]], align
// CHECK: store {{.*}} %this, {{.*}} %[[this_addr:.*]], align
// CHECK: %[[this:.*]] = load {{.*}} %[[this_addr]]
// CHECK: %[[src:.*]] = load {{.*}} %[[src_addr]]
-// CHECK: call {{.*}} @"\01??0Variadic@@QAA@AAU0@ZZ"({{.*}} %[[this]], {{.*}} %[[src]])
+// CHECK: call {{.*}} @"??0Variadic@@QAA@AAU0@ZZ"({{.*}} %[[this]], {{.*}} %[[src]])
// CHECK: ret void
struct TemplateWithDefault {
@@ -118,13 +118,13 @@
using namespace std;
void *GetExceptionInfo_test0() {
-// CHECK-LABEL: @"\01?GetExceptionInfo_test0@@YAPAXXZ"
+// CHECK-LABEL: @"?GetExceptionInfo_test0@@YAPAXXZ"
// CHECK: ret i8* bitcast (%eh.ThrowInfo* @_TI1H to i8*)
return __GetExceptionInfo(0);
}
void *GetExceptionInfo_test1() {
-// CHECK-LABEL: @"\01?GetExceptionInfo_test1@@YAPAXXZ"
+// CHECK-LABEL: @"?GetExceptionInfo_test1@@YAPAXXZ"
// CHECK: ret i8* bitcast (%eh.ThrowInfo* @_TI1P6AXXZ to i8*)
return __GetExceptionInfo<void (*)()>(&h);
}
diff --git a/test/CodeGenCXX/microsoft-abi-thunks.cpp b/test/CodeGenCXX/microsoft-abi-thunks.cpp
index e6fb45d..c2f64f3 100644
--- a/test/CodeGenCXX/microsoft-abi-thunks.cpp
+++ b/test/CodeGenCXX/microsoft-abi-thunks.cpp
@@ -10,7 +10,7 @@
virtual ~A();
virtual void public_f();
// Make sure we don't emit unneeded thunks:
- // XMANGLING-NOT: @"\01?public_f@A@@QAEXXZ"
+ // XMANGLING-NOT: @"?public_f@A@@QAEXXZ"
protected:
virtual void protected_f();
private:
@@ -31,45 +31,45 @@
C();
virtual ~C();
- // MANGLING-DAG: declare {{.*}} @"\01??1C@@UAE@XZ"({{.*}})
- // MANGLING-DAG: define {{.*}} @"\01??_GC@@UAEPAXI@Z"({{.*}})
- // MANGLING-DAG: define {{.*}} @"\01??_EC@@W3AEPAXI@Z"({{.*}}) {{.*}} comdat
- // MANGLING-X64-DAG: declare {{.*}} @"\01??1C@@UEAA@XZ"({{.*}})
- // MANGLING-X64-DAG: define {{.*}} @"\01??_GC@@UEAAPEAXI@Z"({{.*}})
- // MANGLING-X64-DAG: define {{.*}} @"\01??_EC@@W7EAAPEAXI@Z"({{.*}}) {{.*}} comdat
+ // MANGLING-DAG: declare {{.*}} @"??1C@@UAE@XZ"({{.*}})
+ // MANGLING-DAG: define {{.*}} @"??_GC@@UAEPAXI@Z"({{.*}})
+ // MANGLING-DAG: define {{.*}} @"??_EC@@W3AEPAXI@Z"({{.*}}) {{.*}} comdat
+ // MANGLING-X64-DAG: declare {{.*}} @"??1C@@UEAA@XZ"({{.*}})
+ // MANGLING-X64-DAG: define {{.*}} @"??_GC@@UEAAPEAXI@Z"({{.*}})
+ // MANGLING-X64-DAG: define {{.*}} @"??_EC@@W7EAAPEAXI@Z"({{.*}}) {{.*}} comdat
// Overrides public_f() of two subobjects with distinct vfptrs, thus needs a thunk.
virtual void public_f();
- // MANGLING-DAG: @"\01?public_f@C@@UAEXXZ"
- // MANGLING-DAG: @"\01?public_f@C@@W3AEXXZ"
- // MANGLING-X64-DAG: @"\01?public_f@C@@UEAAXXZ"
- // MANGLING-X64-DAG: @"\01?public_f@C@@W7EAAXXZ"
+ // MANGLING-DAG: @"?public_f@C@@UAEXXZ"
+ // MANGLING-DAG: @"?public_f@C@@W3AEXXZ"
+ // MANGLING-X64-DAG: @"?public_f@C@@UEAAXXZ"
+ // MANGLING-X64-DAG: @"?public_f@C@@W7EAAXXZ"
protected:
virtual void protected_f();
- // MANGLING-DAG: @"\01?protected_f@C@@MAEXXZ"
- // MANGLING-DAG: @"\01?protected_f@C@@O3AEXXZ"
- // MANGLING-X64-DAG: @"\01?protected_f@C@@MEAAXXZ"
- // MANGLING-X64-DAG: @"\01?protected_f@C@@O7EAAXXZ"
+ // MANGLING-DAG: @"?protected_f@C@@MAEXXZ"
+ // MANGLING-DAG: @"?protected_f@C@@O3AEXXZ"
+ // MANGLING-X64-DAG: @"?protected_f@C@@MEAAXXZ"
+ // MANGLING-X64-DAG: @"?protected_f@C@@O7EAAXXZ"
private:
virtual void private_f();
- // MANGLING-DAG: @"\01?private_f@C@@EAEXXZ"
- // MANGLING-DAG: @"\01?private_f@C@@G3AEXXZ"
- // MANGLING-X64-DAG: @"\01?private_f@C@@EEAAXXZ"
- // MANGLING-X64-DAG: @"\01?private_f@C@@G7EAAXXZ"
+ // MANGLING-DAG: @"?private_f@C@@EAEXXZ"
+ // MANGLING-DAG: @"?private_f@C@@G3AEXXZ"
+ // MANGLING-X64-DAG: @"?private_f@C@@EEAAXXZ"
+ // MANGLING-X64-DAG: @"?private_f@C@@G7EAAXXZ"
};
C::C() {} // Emits vftable and forces thunk generation.
-// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) {{.*}} comdat
+// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) {{.*}} comdat
// CODEGEN: getelementptr i8, i8* {{.*}}, i32 -4
// FIXME: should actually call _EC, not _GC.
-// CODEGEN: call x86_thiscallcc i8* @"\01??_GC@@UAEPAXI@Z"
+// CODEGEN: call x86_thiscallcc i8* @"??_GC@@UAEPAXI@Z"
// CODEGEN: ret
-// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C*
+// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?public_f@C@@W3AEXXZ"(%struct.C*
// CODEGEN: getelementptr i8, i8* {{.*}}, i32 -4
-// CODEGEN: call x86_thiscallcc void @"\01?public_f@C@@UAEXXZ"(%struct.C*
+// CODEGEN: call x86_thiscallcc void @"?public_f@C@@UAEXXZ"(%struct.C*
// CODEGEN: ret
void zoo(C* obj) {
@@ -83,16 +83,16 @@
struct E : D {
E();
virtual C* goo();
- // MANGLING-DAG: @"\01?goo@E@@UAEPAUC@@XZ"
- // MANGLING-DAG: @"\01?goo@E@@QAEPAUB@@XZ"
- // MANGLING-X64-DAG: @"\01?goo@E@@UEAAPEAUC@@XZ"
- // MANGLING-X64-DAG: @"\01?goo@E@@QEAAPEAUB@@XZ"
+ // MANGLING-DAG: @"?goo@E@@UAEPAUC@@XZ"
+ // MANGLING-DAG: @"?goo@E@@QAEPAUB@@XZ"
+ // MANGLING-X64-DAG: @"?goo@E@@UEAAPEAUC@@XZ"
+ // MANGLING-X64-DAG: @"?goo@E@@QEAAPEAUB@@XZ"
};
E::E() {} // Emits vftable and forces thunk generation.
-// CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ"{{.*}} comdat
-// CODEGEN: call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ"
+// CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc %struct.C* @"?goo@E@@QAEPAUB@@XZ"{{.*}} comdat
+// CODEGEN: call x86_thiscallcc %struct.C* @"?goo@E@@UAEPAUC@@XZ"
// CODEGEN: getelementptr inbounds i8, i8* {{.*}}, i32 4
// CODEGEN: ret
@@ -107,12 +107,12 @@
struct H : E {
virtual G* goo();
- // MANGLING-DAG: @"\01?goo@H@@UAEPAUG@@XZ"
- // MANGLING-DAG: @"\01?goo@H@@QAEPAUB@@XZ"
- // MANGLING-DAG: @"\01?goo@H@@QAEPAUC@@XZ"
- // MANGLING-X64-DAG: @"\01?goo@H@@UEAAPEAUG@@XZ"
- // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUB@@XZ"
- // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUC@@XZ"
+ // MANGLING-DAG: @"?goo@H@@UAEPAUG@@XZ"
+ // MANGLING-DAG: @"?goo@H@@QAEPAUB@@XZ"
+ // MANGLING-DAG: @"?goo@H@@QAEPAUC@@XZ"
+ // MANGLING-X64-DAG: @"?goo@H@@UEAAPEAUG@@XZ"
+ // MANGLING-X64-DAG: @"?goo@H@@QEAAPEAUB@@XZ"
+ // MANGLING-X64-DAG: @"?goo@H@@QEAAPEAUC@@XZ"
};
H h;
@@ -124,8 +124,8 @@
I::I() {} // Emits vftable and forces thunk generation.
-// CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc %struct.{{[BF]}}* @"\01?goo@I@@QAEPAUB@@XZ"{{.*}} comdat
-// CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"\01?goo@I@@UAEPAUF@@XZ"
+// CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc %struct.{{[BF]}}* @"?goo@I@@QAEPAUB@@XZ"{{.*}} comdat
+// CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"?goo@I@@UAEPAUF@@XZ"
// CODEGEN: %[[ORIG_RET_i8:.*]] = bitcast %struct.F* %[[ORIG_RET]] to i8*
// CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ORIG_RET_i8]], i32 4
// CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32**
@@ -160,5 +160,5 @@
E::E() {}
E e;
// Class with internal linkage has internal linkage thunks.
-// CODEGEN: define internal x86_thiscallcc %struct.C* @"\01?goo@E@?A@@QAEPAUB@@XZ"
+// CODEGEN: define internal x86_thiscallcc %struct.C* @"?goo@E@?A@@QAEPAUB@@XZ"
}
diff --git a/test/CodeGenCXX/microsoft-abi-try-throw.cpp b/test/CodeGenCXX/microsoft-abi-try-throw.cpp
index caf68b6..1a1e941 100644
--- a/test/CodeGenCXX/microsoft-abi-try-throw.cpp
+++ b/test/CodeGenCXX/microsoft-abi-try-throw.cpp
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTRY | FileCheck %s -check-prefix=TRY
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTHROW | FileCheck %s -check-prefix=THROW
-// THROW-DAG: @"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
-// THROW-DAG: @"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i32 -1, i32 0, i32 4, i8* null }, section ".xdata", comdat
+// THROW-DAG: @"??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
+// THROW-DAG: @"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"??_R0H@8" to i8*), i32 0, i32 -1, i32 0, i32 4, i8* null }, section ".xdata", comdat
// THROW-DAG: @_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0H@84"] }, section ".xdata", comdat
// THROW-DAG: @_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1H to i8*) }, section ".xdata", comdat
@@ -16,10 +16,10 @@
int rv = 0;
#ifdef TRY
try {
- external(); // TRY: invoke void @"\01?external@@YAXXZ"
+ external(); // TRY: invoke void @"?external@@YAXXZ"
} catch (int) {
rv = 1;
- // TRY: catchpad within {{.*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ // TRY: catchpad within {{.*}} [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i8* null]
// TRY: catchret
}
#endif
@@ -33,13 +33,13 @@
}
#ifdef TRY
-// TRY-LABEL: define dso_local void @"\01?qual_catch@@YAXXZ"
+// TRY-LABEL: define dso_local void @"?qual_catch@@YAXXZ"
void qual_catch() {
try {
external();
} catch (const int *) {
}
- // TRY: catchpad within {{.*}} [%rtti.TypeDescriptor4* @"\01??_R0PAH@8", i32 1, i8* null]
+ // TRY: catchpad within {{.*}} [%rtti.TypeDescriptor4* @"??_R0PAH@8", i32 1, i8* null]
// TRY: catchret
}
#endif
diff --git a/test/CodeGenCXX/microsoft-abi-typeid.cpp b/test/CodeGenCXX/microsoft-abi-typeid.cpp
index 3152c31..a571654 100644
--- a/test/CodeGenCXX/microsoft-abi-typeid.cpp
+++ b/test/CodeGenCXX/microsoft-abi-typeid.cpp
@@ -12,20 +12,20 @@
A* fn();
const std::type_info* test0_typeid() { return &typeid(int); }
-// CHECK-LABEL: define dso_local %struct.type_info* @"\01?test0_typeid@@YAPBUtype_info@@XZ"()
-// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to %struct.type_info*)
+// CHECK-LABEL: define dso_local %struct.type_info* @"?test0_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"??_R0H@8" to %struct.type_info*)
const std::type_info* test1_typeid() { return &typeid(A); }
-// CHECK-LABEL: define dso_local %struct.type_info* @"\01?test1_typeid@@YAPBUtype_info@@XZ"()
-// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to %struct.type_info*)
+// CHECK-LABEL: define dso_local %struct.type_info* @"?test1_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to %struct.type_info*)
const std::type_info* test2_typeid() { return &typeid(&a); }
-// CHECK-LABEL: define dso_local %struct.type_info* @"\01?test2_typeid@@YAPBUtype_info@@XZ"()
-// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"\01??_R0PAUA@@@8" to %struct.type_info*)
+// CHECK-LABEL: define dso_local %struct.type_info* @"?test2_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"??_R0PAUA@@@8" to %struct.type_info*)
const std::type_info* test3_typeid() { return &typeid(*fn()); }
-// CHECK-LABEL: define dso_local %struct.type_info* @"\01?test3_typeid@@YAPBUtype_info@@XZ"()
-// CHECK: [[CALL:%.*]] = tail call %struct.A* @"\01?fn@@YAPAUA@@XZ"()
+// CHECK-LABEL: define dso_local %struct.type_info* @"?test3_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: [[CALL:%.*]] = tail call %struct.A* @"?fn@@YAPAUA@@XZ"()
// CHECK-NEXT: [[CMP:%.*]] = icmp eq %struct.A* [[CALL]], null
// CHECK-NEXT: br i1 [[CMP]]
// CHECK: tail call i8* @__RTtypeid(i8* null)
@@ -41,12 +41,12 @@
// CHECK-NEXT: ret %struct.type_info* [[RET]]
const std::type_info* test4_typeid() { return &typeid(b); }
-// CHECK: define dso_local %struct.type_info* @"\01?test4_typeid@@YAPBUtype_info@@XZ"()
-// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to %struct.type_info*)
+// CHECK: define dso_local %struct.type_info* @"?test4_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"??_R0H@8" to %struct.type_info*)
const std::type_info* test5_typeid() { return &typeid(v); }
-// CHECK: define dso_local %struct.type_info* @"\01?test5_typeid@@YAPBUtype_info@@XZ"()
-// CHECK: [[RT:%.*]] = tail call i8* @__RTtypeid(i8* bitcast (%struct.V* @"\01?v@@3UV@@A" to i8*))
+// CHECK: define dso_local %struct.type_info* @"?test5_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: [[RT:%.*]] = tail call i8* @__RTtypeid(i8* bitcast (%struct.V* @"?v@@3UV@@A" to i8*))
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[RT]] to %struct.type_info*
// CHECK-NEXT: ret %struct.type_info* [[RET]]
@@ -63,7 +63,7 @@
typeid(poly);
}
}
-// CHECK-LABEL: define dso_local void @"\01?f@PR26329@@YAXABUPolymorphic@1@@Z"(
+// CHECK-LABEL: define dso_local void @"?f@PR26329@@YAXABUPolymorphic@1@@Z"(
// CHECK: %[[cs:.*]] = catchswitch within none [label %{{.*}}] unwind to caller
// CHECK: %[[cp:.*]] = catchpad within %[[cs]] [i8* null, i32 64, i8* null]
// CHECK: invoke i8* @__RTtypeid(i8* {{.*}}) [ "funclet"(token %[[cp]]) ]
diff --git a/test/CodeGenCXX/microsoft-abi-vbtables.cpp b/test/CodeGenCXX/microsoft-abi-vbtables.cpp
index df06894..46e159c 100644
--- a/test/CodeGenCXX/microsoft-abi-vbtables.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vbtables.cpp
@@ -19,11 +19,11 @@
// C: vbptr C
// int c
-// CHECK-DAG: @"\01??_8D@Test1@@7B01@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 8, i32 12, i32 20]
-// CHECK-DAG: @"\01??_8D@Test1@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
-// CHECK-DAG: @"\01??_8D@Test1@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -12]
-// CHECK-DAG: @"\01??_8C@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
-// CHECK-DAG: @"\01??_8B@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test1@@7B01@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 8, i32 12, i32 20]
+// CHECK-DAG: @"??_8D@Test1@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
+// CHECK-DAG: @"??_8D@Test1@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -12]
+// CHECK-DAG: @"??_8C@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8B@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
}
namespace Test2 {
@@ -42,10 +42,10 @@
// D: int d
// A: int a
-// CHECK-DAG: @"\01??_8D@Test2@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 20]
-// CHECK-DAG: @"\01??_8D@Test2@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 12]
-// CHECK-DAG: @"\01??_8C@Test2@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
-// CHECK-DAG: @"\01??_8B@Test2@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test2@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 20]
+// CHECK-DAG: @"??_8D@Test2@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"??_8C@Test2@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8B@Test2@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
}
namespace Test3 {
@@ -54,7 +54,7 @@
struct C : virtual A, virtual B { int c; };
C c;
-// CHECK-DAG: @"\01??_8C@Test3@@7B@" = {{.*}} [3 x i32] [i32 0, i32 8, i32 12]
+// CHECK-DAG: @"??_8C@Test3@@7B@" = {{.*}} [3 x i32] [i32 0, i32 8, i32 12]
}
namespace Test4 {
@@ -64,8 +64,8 @@
struct C : B, virtual A { int c; };
C c; // Force vbtable emission.
-// CHECK-DAG: @"\01??_8C@Test4@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
-// CHECK-DAG: @"\01??_8B@Test4@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8C@Test4@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"??_8B@Test4@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
}
namespace Test5 {
@@ -77,10 +77,10 @@
struct D : B, C { int d; };
D d; // Force vbtable emission.
-// CHECK-DAG: @"\01??_8D@Test5@@7BB@1@@"
-// CHECK-DAG: @"\01??_8D@Test5@@7BC@1@@"
-// CHECK-DAG: @"\01??_8C@Test5@@7B@"
-// CHECK-DAG: @"\01??_8B@Test5@@7B@"
+// CHECK-DAG: @"??_8D@Test5@@7BB@1@@"
+// CHECK-DAG: @"??_8D@Test5@@7BC@1@@"
+// CHECK-DAG: @"??_8C@Test5@@7B@"
+// CHECK-DAG: @"??_8B@Test5@@7B@"
}
namespace Test6 {
@@ -94,22 +94,22 @@
struct G : F, virtual E { int g; };
G g;
-// CHECK-DAG: @"\01??_8G@Test6@@7BB@1@E@1@F@1@@" =
-// CHECK-DAG: @"\01??_8G@Test6@@7BC@1@E@1@F@1@@" =
-// CHECK-DAG: @"\01??_8G@Test6@@7BB@1@F@1@@" =
-// CHECK-DAG: @"\01??_8G@Test6@@7BC@1@F@1@@" =
-// CHECK-DAG: @"\01??_8G@Test6@@7BB@1@E@1@@" =
-// CHECK-DAG: @"\01??_8G@Test6@@7BC@1@E@1@@" =
-// CHECK-DAG: @"\01??_8F@Test6@@7BB@1@E@1@@" = {{.*}} [2 x i32] [i32 0, i32 52]
-// CHECK-DAG: @"\01??_8F@Test6@@7BC@1@E@1@@" = {{.*}} [2 x i32] [i32 0, i32 44]
-// CHECK-DAG: @"\01??_8F@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 24]
-// CHECK-DAG: @"\01??_8F@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 16]
-// CHECK-DAG: @"\01??_8C@Test6@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
-// CHECK-DAG: @"\01??_8B@Test6@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
-// CHECK-DAG: @"\01??_8E@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 28]
-// CHECK-DAG: @"\01??_8E@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 20]
-// CHECK-DAG: @"\01??_8D@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 24]
-// CHECK-DAG: @"\01??_8D@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"??_8G@Test6@@7BB@1@E@1@F@1@@" =
+// CHECK-DAG: @"??_8G@Test6@@7BC@1@E@1@F@1@@" =
+// CHECK-DAG: @"??_8G@Test6@@7BB@1@F@1@@" =
+// CHECK-DAG: @"??_8G@Test6@@7BC@1@F@1@@" =
+// CHECK-DAG: @"??_8G@Test6@@7BB@1@E@1@@" =
+// CHECK-DAG: @"??_8G@Test6@@7BC@1@E@1@@" =
+// CHECK-DAG: @"??_8F@Test6@@7BB@1@E@1@@" = {{.*}} [2 x i32] [i32 0, i32 52]
+// CHECK-DAG: @"??_8F@Test6@@7BC@1@E@1@@" = {{.*}} [2 x i32] [i32 0, i32 44]
+// CHECK-DAG: @"??_8F@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 24]
+// CHECK-DAG: @"??_8F@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"??_8C@Test6@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"??_8B@Test6@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8E@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 28]
+// CHECK-DAG: @"??_8E@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 20]
+// CHECK-DAG: @"??_8D@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 24]
+// CHECK-DAG: @"??_8D@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 16]
}
namespace Test7 {
@@ -121,8 +121,8 @@
struct E : B, D, virtual A, virtual C { int e; };
E o;
-// CHECK-DAG: @"\01??_8E@Test7@@7B@" = {{.*}} [3 x i32] [i32 0, i32 12, i32 16]
-// CHECK-DAG: @"\01??_8D@Test7@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8E@Test7@@7B@" = {{.*}} [3 x i32] [i32 0, i32 12, i32 16]
+// CHECK-DAG: @"??_8D@Test7@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
}
namespace Test8 {
@@ -133,10 +133,10 @@
struct D : virtual C { int d; };
D o;
-// CHECK-DAG: @"\01??_8D@Test8@@7B01@@" = {{.*}} [3 x i32] [i32 0, i32 8, i32 12]
-// CHECK-DAG: @"\01??_8D@Test8@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
-// CHECK-DAG: @"\01??_8C@Test8@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
-// CHECK-DAG: @"\01??_8B@Test8@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test8@@7B01@@" = {{.*}} [3 x i32] [i32 0, i32 8, i32 12]
+// CHECK-DAG: @"??_8D@Test8@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
+// CHECK-DAG: @"??_8C@Test8@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"??_8B@Test8@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
}
namespace Test9 {
@@ -150,17 +150,17 @@
struct E : virtual D { };
E e;
-// CHECK-DAG: @"\01??_8E@Test9@@7B01@@" =
-// CHECK-DAG: @"\01??_8E@Test9@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test9@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test9@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test9@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test9@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test9@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test9@@7B01@@" =
-// CHECK-DAG: @"\01??_8C@Test9@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8BB@Test9@@7B@" =
-// CHECK-DAG: @"\01??_8B@Test9@@7B@" =
+// CHECK-DAG: @"??_8E@Test9@@7B01@@" =
+// CHECK-DAG: @"??_8E@Test9@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test9@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test9@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test9@@7B@" =
+// CHECK-DAG: @"??_8D@Test9@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test9@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test9@@7B01@@" =
+// CHECK-DAG: @"??_8C@Test9@@7BB@1@@" =
+// CHECK-DAG: @"??_8BB@Test9@@7B@" =
+// CHECK-DAG: @"??_8B@Test9@@7B@" =
}
namespace Test10 {
@@ -170,8 +170,8 @@
struct D : B, C { int d; };
D d;
-// CHECK-DAG: @"\01??_8D@Test10@@7B@" =
-// CHECK-DAG: @"\01??_8C@Test10@@7B@" =
+// CHECK-DAG: @"??_8D@Test10@@7B@" =
+// CHECK-DAG: @"??_8C@Test10@@7B@" =
}
@@ -185,12 +185,12 @@
struct F : D, E { int f; };
F f;
-// CHECK-DAG: @"\01??_8F@Test11@@7BD@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 28]
-// CHECK-DAG: @"\01??_8F@Test11@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16]
-// CHECK-DAG: @"\01??_8E@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 12]
-// CHECK-DAG: @"\01??_8C@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
-// CHECK-DAG: @"\01??_8D@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 12]
-// CHECK-DAG: @"\01??_8B@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8F@Test11@@7BD@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 28]
+// CHECK-DAG: @"??_8F@Test11@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"??_8E@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"??_8C@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"??_8B@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
}
@@ -203,17 +203,17 @@
struct E : D, C, B { int e; };
E e;
-// CHECK-DAG: @"\01??_8E@Test12@@7BC@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test12@@7BB@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test12@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test12@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test12@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test12@@7B01@@" =
-// CHECK-DAG: @"\01??_8C@Test12@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test12@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test12@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test12@@7B@" =
-// CHECK-DAG: @"\01??_8B@Test12@@7B@" =
+// CHECK-DAG: @"??_8E@Test12@@7BC@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test12@@7BB@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test12@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test12@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test12@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test12@@7B01@@" =
+// CHECK-DAG: @"??_8C@Test12@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test12@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test12@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test12@@7B@" =
+// CHECK-DAG: @"??_8B@Test12@@7B@" =
}
namespace Test13 {
@@ -224,17 +224,17 @@
struct E : D, C, B { int e; };
E e;
-// CHECK-DAG: @"\01??_8E@Test13@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test13@@7BC@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test13@@7BB@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test13@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test13@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test13@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test13@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test13@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test13@@7B01@@" =
-// CHECK-DAG: @"\01??_8C@Test13@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8B@Test13@@7B@" =
+// CHECK-DAG: @"??_8E@Test13@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test13@@7BC@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test13@@7BB@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test13@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test13@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test13@@7B@" =
+// CHECK-DAG: @"??_8D@Test13@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test13@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test13@@7B01@@" =
+// CHECK-DAG: @"??_8C@Test13@@7BB@1@@" =
+// CHECK-DAG: @"??_8B@Test13@@7B@" =
}
namespace Test14 {
@@ -245,15 +245,15 @@
struct E : D, virtual C, virtual B { int e; };
E e;
-// CHECK-DAG: @"\01??_8E@Test14@@7B@" =
-// CHECK-DAG: @"\01??_8E@Test14@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test14@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test14@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test14@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test14@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test14@@7B01@@" =
-// CHECK-DAG: @"\01??_8C@Test14@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8B@Test14@@7B@" =
+// CHECK-DAG: @"??_8E@Test14@@7B@" =
+// CHECK-DAG: @"??_8E@Test14@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test14@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test14@@7B@" =
+// CHECK-DAG: @"??_8D@Test14@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test14@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test14@@7B01@@" =
+// CHECK-DAG: @"??_8C@Test14@@7BB@1@@" =
+// CHECK-DAG: @"??_8B@Test14@@7B@" =
}
namespace Test15 {
@@ -264,14 +264,14 @@
struct E : D, C, B { int e; };
E e;
-// CHECK-DAG: @"\01??_8E@Test15@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test15@@7BB@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test15@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test15@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test15@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test15@@7B01@@" =
-// CHECK-DAG: @"\01??_8D@Test15@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8B@Test15@@7B@" =
+// CHECK-DAG: @"??_8E@Test15@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test15@@7BB@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test15@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test15@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test15@@7B@" =
+// CHECK-DAG: @"??_8D@Test15@@7B01@@" =
+// CHECK-DAG: @"??_8D@Test15@@7BB@1@@" =
+// CHECK-DAG: @"??_8B@Test15@@7B@" =
}
namespace Test16 {
@@ -283,23 +283,23 @@
struct F : E, D, C, B { int f; }; // ambig
F f;
-// CHECK-DAG: @"\01??_8F@Test16@@7BE@1@@" =
-// CHECK-DAG: @"\01??_8F@Test16@@7BD@1@E@1@@" =
-// CHECK-DAG: @"\01??_8F@Test16@@7BC@1@E@1@@" =
-// CHECK-DAG: @"\01??_8F@Test16@@7BB@1@E@1@@" =
-// CHECK-DAG: @"\01??_8F@Test16@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8F@Test16@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8F@Test16@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8E@Test16@@7B01@@" =
-// CHECK-DAG: @"\01??_8E@Test16@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test16@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test16@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test16@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test16@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test16@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test16@@7B01@@" =
-// CHECK-DAG: @"\01??_8C@Test16@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8B@Test16@@7B@" =
+// CHECK-DAG: @"??_8F@Test16@@7BE@1@@" =
+// CHECK-DAG: @"??_8F@Test16@@7BD@1@E@1@@" =
+// CHECK-DAG: @"??_8F@Test16@@7BC@1@E@1@@" =
+// CHECK-DAG: @"??_8F@Test16@@7BB@1@E@1@@" =
+// CHECK-DAG: @"??_8F@Test16@@7BD@1@@" =
+// CHECK-DAG: @"??_8F@Test16@@7BC@1@@" =
+// CHECK-DAG: @"??_8F@Test16@@7BB@1@@" =
+// CHECK-DAG: @"??_8E@Test16@@7B01@@" =
+// CHECK-DAG: @"??_8E@Test16@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test16@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test16@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test16@@7B@" =
+// CHECK-DAG: @"??_8D@Test16@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test16@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test16@@7B01@@" =
+// CHECK-DAG: @"??_8C@Test16@@7BB@1@@" =
+// CHECK-DAG: @"??_8B@Test16@@7B@" =
}
namespace Test17 {
@@ -318,16 +318,16 @@
struct K : virtual J { int k; }; // ambig
K k;
-// CHECK-DAG: @"\01??_8K@Test17@@7B01@@" =
-// CHECK-DAG: @"\01??_8J@Test17@@7B@" =
-// CHECK-DAG: @"\01??_8I@Test17@@7B01@@" =
-// CHECK-DAG: @"\01??_8H@Test17@@7B@" =
-// CHECK-DAG: @"\01??_8G@Test17@@7B01@@" =
-// CHECK-DAG: @"\01??_8F@Test17@@7B@" =
-// CHECK-DAG: @"\01??_8E@Test17@@7B01@@" =
-// CHECK-DAG: @"\01??_8D@Test17@@7B@" =
-// CHECK-DAG: @"\01??_8C@Test17@@7B01@@" =
-// CHECK-DAG: @"\01??_8B@Test17@@7B@" =
+// CHECK-DAG: @"??_8K@Test17@@7B01@@" =
+// CHECK-DAG: @"??_8J@Test17@@7B@" =
+// CHECK-DAG: @"??_8I@Test17@@7B01@@" =
+// CHECK-DAG: @"??_8H@Test17@@7B@" =
+// CHECK-DAG: @"??_8G@Test17@@7B01@@" =
+// CHECK-DAG: @"??_8F@Test17@@7B@" =
+// CHECK-DAG: @"??_8E@Test17@@7B01@@" =
+// CHECK-DAG: @"??_8D@Test17@@7B@" =
+// CHECK-DAG: @"??_8C@Test17@@7B01@@" =
+// CHECK-DAG: @"??_8B@Test17@@7B@" =
}
namespace Test18 {
@@ -338,14 +338,14 @@
struct E : D, C, B { int e; };
E e;
-// CHECK-DAG: @"\01??_8E@Test18@@7BC@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test18@@7BB@1@D@1@@" =
-// CHECK-DAG: @"\01??_8E@Test18@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test18@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8B@Test18@@7B@" =
-// CHECK-DAG: @"\01??_8C@Test18@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test18@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test18@@7BB@1@@" =
+// CHECK-DAG: @"??_8E@Test18@@7BC@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test18@@7BB@1@D@1@@" =
+// CHECK-DAG: @"??_8E@Test18@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test18@@7BB@1@@" =
+// CHECK-DAG: @"??_8B@Test18@@7B@" =
+// CHECK-DAG: @"??_8C@Test18@@7B@" =
+// CHECK-DAG: @"??_8D@Test18@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test18@@7BB@1@@" =
}
namespace Test19 {
@@ -356,16 +356,16 @@
struct E : virtual D, virtual C, virtual B { int e; };
E e;
-// CHECK-DAG: @"\01??_8E@Test19@@7B01@@" =
-// CHECK-DAG: @"\01??_8E@Test19@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test19@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test19@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8D@Test19@@7B@" =
-// CHECK-DAG: @"\01??_8D@Test19@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8D@Test19@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8C@Test19@@7B01@@" =
-// CHECK-DAG: @"\01??_8C@Test19@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8B@Test19@@7B@" =
+// CHECK-DAG: @"??_8E@Test19@@7B01@@" =
+// CHECK-DAG: @"??_8E@Test19@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test19@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test19@@7BB@1@@" =
+// CHECK-DAG: @"??_8D@Test19@@7B@" =
+// CHECK-DAG: @"??_8D@Test19@@7BC@1@@" =
+// CHECK-DAG: @"??_8D@Test19@@7BB@1@@" =
+// CHECK-DAG: @"??_8C@Test19@@7B01@@" =
+// CHECK-DAG: @"??_8C@Test19@@7BB@1@@" =
+// CHECK-DAG: @"??_8B@Test19@@7B@" =
}
namespace Test20 {
@@ -377,10 +377,10 @@
struct E : C, D { int e; };
E f;
-// CHECK-DAG: @"\01??_8E@Test20@@7BC@1@@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 20, i32 24]
-// CHECK-DAG: @"\01??_8E@Test20@@7BD@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16]
-// CHECK-DAG: @"\01??_8D@Test20@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
-// CHECK-DAG: @"\01??_8C@Test20@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8E@Test20@@7BC@1@@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 20, i32 24]
+// CHECK-DAG: @"??_8E@Test20@@7BD@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"??_8D@Test20@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8C@Test20@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
}
namespace Test21 {
@@ -394,21 +394,21 @@
struct H : F, G { int h; };
H h;
-// CHECK-DAG: @"\01??_8H@Test21@@7B@" =
-// CHECK-DAG: @"\01??_8H@Test21@@7BC@1@F@1@@" =
-// CHECK-DAG: @"\01??_8H@Test21@@7BD@1@F@1@@" =
-// CHECK-DAG: @"\01??_8H@Test21@@7BC@1@G@1@@" =
-// CHECK-DAG: @"\01??_8H@Test21@@7BD@1@G@1@@" =
-// CHECK-DAG: @"\01??_8G@Test21@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8G@Test21@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8F@Test21@@7B@" =
-// CHECK-DAG: @"\01??_8F@Test21@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8F@Test21@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8E@Test21@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8E@Test21@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8D@Test21@@7B@" =
-// CHECK-DAG: @"\01??_8B@Test21@@7B@" =
-// CHECK-DAG: @"\01??_8C@Test21@@7B@" =
+// CHECK-DAG: @"??_8H@Test21@@7B@" =
+// CHECK-DAG: @"??_8H@Test21@@7BC@1@F@1@@" =
+// CHECK-DAG: @"??_8H@Test21@@7BD@1@F@1@@" =
+// CHECK-DAG: @"??_8H@Test21@@7BC@1@G@1@@" =
+// CHECK-DAG: @"??_8H@Test21@@7BD@1@G@1@@" =
+// CHECK-DAG: @"??_8G@Test21@@7BC@1@@" =
+// CHECK-DAG: @"??_8G@Test21@@7BD@1@@" =
+// CHECK-DAG: @"??_8F@Test21@@7B@" =
+// CHECK-DAG: @"??_8F@Test21@@7BC@1@@" =
+// CHECK-DAG: @"??_8F@Test21@@7BD@1@@" =
+// CHECK-DAG: @"??_8E@Test21@@7BC@1@@" =
+// CHECK-DAG: @"??_8E@Test21@@7BD@1@@" =
+// CHECK-DAG: @"??_8D@Test21@@7B@" =
+// CHECK-DAG: @"??_8B@Test21@@7B@" =
+// CHECK-DAG: @"??_8C@Test21@@7B@" =
}
namespace Test22 {
@@ -418,8 +418,8 @@
struct D : B, virtual C { int d; };
D d;
-// CHECK-DAG: @"\01??_8D@Test22@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 12, i32 16]
-// CHECK-DAG: @"\01??_8B@Test22@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test22@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 12, i32 16]
+// CHECK-DAG: @"??_8B@Test22@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
}
namespace Test23 {
@@ -430,8 +430,8 @@
struct D : virtual C, B { int d; };
D d;
-// CHECK-DAG: @"\01??_8D@Test23@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
-// CHECK-DAG: @"\01??_8B@Test23@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test23@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
+// CHECK-DAG: @"??_8B@Test23@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
}
namespace Test24 {
@@ -444,8 +444,8 @@
};
D d;
-// CHECK-DAG: @"\01??_8D@Test24@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
-// CHECK-DAG: @"\01??_8B@Test24@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"??_8D@Test24@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
+// CHECK-DAG: @"??_8B@Test24@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
}
namespace Test25 {
@@ -458,8 +458,8 @@
struct D : virtual C, B { int d; };
D d;
-// CHECK-DAG: @"\01??_8D@Test25@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 -4, i32 16, i32 12]
-// CHECK-DAG: @"\01??_8B@Test25@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 8]
+// CHECK-DAG: @"??_8D@Test25@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 -4, i32 16, i32 12]
+// CHECK-DAG: @"??_8B@Test25@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 8]
}
namespace Test26 {
@@ -474,8 +474,8 @@
struct F: virtual C, D, E { int f; };
F f;
// F reuses the D's vbptr, even though D is laid out after E.
-// CHECK-DAG: @"\01??_8F@Test26@@7BD@1@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 16, i32 12, i32 20]
-// CHECK-DAG: @"\01??_8F@Test26@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 28]
+// CHECK-DAG: @"??_8F@Test26@@7BD@1@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 16, i32 12, i32 20]
+// CHECK-DAG: @"??_8F@Test26@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 28]
}
namespace Test27 {
@@ -489,14 +489,14 @@
struct G : F, D, C, B {};
G x;
-// CHECK-DAG: @"\01??_8G@Test27@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BB@1@F@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@D@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@E@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@F@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8G@Test27@@7BF@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BB@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BB@1@F@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BC@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BC@1@D@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BC@1@E@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BC@1@F@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BD@1@@" =
+// CHECK-DAG: @"??_8G@Test27@@7BF@1@@" =
}
namespace Test28 {
@@ -509,14 +509,14 @@
struct F : virtual E, virtual D, virtual C {};
F x;
-// CHECK-DAG: @"\01??_8F@Test28@@7B01@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BB@1@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@D@1@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@D@1@E@1@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@E@1@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BD@1@@" =
-// CHECK-DAG: @"\01??_8F@Test28@@7BE@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7B01@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BB@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BC@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BC@1@D@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BC@1@D@1@E@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BC@1@E@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BD@1@@" =
+// CHECK-DAG: @"??_8F@Test28@@7BE@1@@" =
}
namespace Test29 {
@@ -526,7 +526,7 @@
struct D : C {};
D d;
-// CHECK-DAG: @"\01??_8D@Test29@@7BB@1@@" = linkonce_odr unnamed_addr constant [2 x i32] zeroinitializer
+// CHECK-DAG: @"??_8D@Test29@@7BB@1@@" = linkonce_odr unnamed_addr constant [2 x i32] zeroinitializer
}
namespace Test30 {
@@ -537,5 +537,5 @@
extern template class B<int>;
template B<int>::B();
-// CHECK-DAG: @"\01??_8?$B@H@Test30@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 4], comdat
+// CHECK-DAG: @"??_8?$B@H@Test30@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 4], comdat
}
diff --git a/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp
index 968955f..65370ab 100644
--- a/test/CodeGenCXX/microsoft-abi-vftables.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vftables.cpp
@@ -1,45 +1,45 @@
// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -fms-extensions -emit-llvm -o - -O1 -disable-llvm-passes | FileCheck %s -check-prefix=NO-RTTI
// RUN: %clang_cc1 %s -triple=i386-pc-win32 -fms-extensions -emit-llvm -o - -O1 -disable-llvm-passes | FileCheck %s -check-prefix=RTTI
-// RTTI-DAG: $"\01??_7S@@6B@" = comdat largest
-// RTTI-DAG: $"\01??_7V@@6B@" = comdat largest
+// RTTI-DAG: $"??_7S@@6B@" = comdat largest
+// RTTI-DAG: $"??_7V@@6B@" = comdat largest
struct S {
virtual ~S();
} s;
-// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4S@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] }, comdat($"\01??_7S@@6B@")
-// RTTI-DAG: @"\01??_7S@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_S]], i32 0, i32 0, i32 1)
+// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4S@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GS@@UAEPAXI@Z" to i8*)] }, comdat($"??_7S@@6B@")
+// RTTI-DAG: @"??_7S@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_S]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] }
+// NO-RTTI-DAG: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GS@@UAEPAXI@Z" to i8*)] }
struct __declspec(dllimport) U {
virtual ~U();
} u;
-// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4U@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] }
-// RTTI-DAG: @"\01??_SU@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_U]], i32 0, i32 0, i32 1)
+// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4U@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GU@@UAEPAXI@Z" to i8*)] }
+// RTTI-DAG: @"??_SU@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_U]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"\01??_SU@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] }
+// NO-RTTI-DAG: @"??_SU@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GU@@UAEPAXI@Z" to i8*)] }
struct __declspec(dllexport) V {
virtual ~V();
} v;
-// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4V@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)] }, comdat($"\01??_7V@@6B@")
-// RTTI-DAG: @"\01??_7V@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_V]], i32 0, i32 0, i32 1)
+// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4V@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GV@@UAEPAXI@Z" to i8*)] }, comdat($"??_7V@@6B@")
+// RTTI-DAG: @"??_7V@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_V]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"\01??_7V@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)] }
+// NO-RTTI-DAG: @"??_7V@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GV@@UAEPAXI@Z" to i8*)] }
namespace {
struct W {
virtual ~W() {}
} w;
}
-// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] }
-// RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_W]], i32 0, i32 0, i32 1)
+// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GW@?A@@UAEPAXI@Z" to i8*)] }
+// RTTI-DAG: @"??_7W@?A@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_W]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] }
+// NO-RTTI-DAG: @"??_7W@?A@@6B@" = internal unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GW@?A@@UAEPAXI@Z" to i8*)] }
struct X {};
template <class> struct Y : virtual X {
@@ -49,7 +49,7 @@
extern template class Y<int>;
template Y<int>::Y();
-// RTTI-DAG: [[VTABLE_Y:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$Y@H@@6B@" to i8*), i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)] }, comdat($"\01??_7?$Y@H@@6B@")
-// RTTI-DAG: @"\01??_7?$Y@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_Y]], i32 0, i32 0, i32 1)
+// RTTI-DAG: [[VTABLE_Y:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4?$Y@H@@6B@" to i8*), i8* bitcast (i8* (%struct.Y*, i32)* @"??_G?$Y@H@@UAEPAXI@Z" to i8*)] }, comdat($"??_7?$Y@H@@6B@")
+// RTTI-DAG: @"??_7?$Y@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_Y]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"\01??_7?$Y@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)] }, comdat
+// NO-RTTI-DAG: @"??_7?$Y@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (i8* (%struct.Y*, i32)* @"??_G?$Y@H@@UAEPAXI@Z" to i8*)] }, comdat
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
index bb18d99..0120299 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
@@ -23,7 +23,7 @@
D::D() {} // Forces vftable emission.
-// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"\01?f@D@@$4PPPPPPPM@A@AEXXZ"
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f@D@@$4PPPPPPPM@A@AEXXZ"
// Note that the vtordisp is applied before really adjusting to D*.
// CHECK: %[[COERCE_LOAD:.*]] = load %struct.D*, %struct.D** %{{.*}}
// CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}}
@@ -33,10 +33,10 @@
// CHECK: %[[VTORDISP:.*]] = load i32, i32* %[[VTORDISP_PTR]]
// CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
// CHECK: %[[ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
-// CHECK: call x86_thiscallcc void @"\01?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]])
+// CHECK: call x86_thiscallcc void @"?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]])
// CHECK: ret void
-// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"\01?f@D@@$4PPPPPPPI@3AEXXZ"
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f@D@@$4PPPPPPPI@3AEXXZ"
// CHECK: %[[COERCE_LOAD:.*]] = load %struct.D*, %struct.D** %{{.*}}
// CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}}
// CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8*
@@ -46,7 +46,7 @@
// CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
// CHECK: %[[VTORDISP_ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
// CHECK: %[[ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[VTORDISP_ADJUSTED_i8]], i32 -4
-// CHECK: call x86_thiscallcc void @"\01?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]])
+// CHECK: call x86_thiscallcc void @"?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]])
// CHECK: ret void
struct E : virtual A {
@@ -66,7 +66,7 @@
G::G() {} // Forces vftable emission.
-// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"\01?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*
// CHECK: %[[COERCE_LOAD:.*]] = load %struct.E*, %struct.E** %{{.*}}
// CHECK: %[[ECX:.*]] = load %struct.E*, %struct.E** %{{.*}}
// CHECK: %[[ECX_i8:.*]] = bitcast %struct.E* %[[ECX]] to i8*
@@ -82,5 +82,5 @@
// CHECK: %[[VBASE_OFFSET:.*]] = load i32, i32* %[[VBOFFSET_PTR]]
// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
// CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %[[VBASE]], i32 8
-// CHECK: call x86_thiscallcc void @"\01?f@E@@UAEXXZ"(i8* %[[ARG_i8]])
+// CHECK: call x86_thiscallcc void @"?f@E@@UAEXXZ"(i8* %[[ARG_i8]])
// CHECK: ret void
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
index 394d967..212c8dc 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
@@ -20,7 +20,7 @@
};
B::B() {
- // CHECK-LABEL: define dso_local x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"
+ // CHECK-LABEL: define dso_local x86_thiscallcc %struct.B* @"??0B@@QAE@XZ"
// CHECK: %[[THIS:.*]] = load %struct.B*, %struct.B**
// CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
@@ -33,7 +33,7 @@
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %{{.*}}
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [3 x i8*] }* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+ // CHECK: store i32 (...)** bitcast ({ [3 x i8*] }* @"??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// Initialize vtorDisp:
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
@@ -51,7 +51,7 @@
}
B::~B() {
- // CHECK-LABEL: define dso_local x86_thiscallcc void @"\01??1B@@UAE@XZ"
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1B@@UAE@XZ"
// Store initial this:
// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B*
// CHECK: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR]], align 4
@@ -68,7 +68,7 @@
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %{{.*}}
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [3 x i8*] }* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+ // CHECK: store i32 (...)** bitcast ({ [3 x i8*] }* @"??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// Initialize vtorDisp:
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
@@ -86,31 +86,31 @@
// CHECK: ret
- // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B*
+ // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"??_DB@@QAEXXZ"(%struct.B*
// CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** {{.*}}
// CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK2: %[[B_i8:.*]] = getelementptr i8, i8* %[[THIS_i8]], i32 8
// CHECK2: %[[B:.*]] = bitcast i8* %[[B_i8]] to %struct.B*
- // CHECK2: call x86_thiscallcc void @"\01??1B@@UAE@XZ"(%struct.B* %[[B]])
+ // CHECK2: call x86_thiscallcc void @"??1B@@UAE@XZ"(%struct.B* %[[B]])
// CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 8
// CHECK2: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
- // CHECK2: call x86_thiscallcc void @"\01??1VBase@@UAE@XZ"(%struct.VBase* %[[VBASE]])
+ // CHECK2: call x86_thiscallcc void @"??1VBase@@UAE@XZ"(%struct.VBase* %[[VBASE]])
// CHECK2: ret
- // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"\01??_GB@@UAEPAXI@Z"
+ // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_GB@@UAEPAXI@Z"
// CHECK2: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR:.*]], align 4
// CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
// CHECK2: %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK2: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_PARAM_i8:.*]], i32 -8
// CHECK2: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
- // CHECK2: call x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B* %[[THIS]])
+ // CHECK2: call x86_thiscallcc void @"??_DB@@QAEXXZ"(%struct.B* %[[THIS]])
// ...
// CHECK2: ret
}
void B::foo() {
-// CHECK-LABEL: define dso_local x86_thiscallcc void @"\01?foo@B@@UAEXXZ"(i8*
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"?foo@B@@UAEXXZ"(i8*
//
// B::foo gets 'this' cast to VBase* in ECX (i.e. this+8) so we
// need to adjust 'this' before use.
@@ -149,7 +149,7 @@
}
void call_vbase_bar(B *obj) {
-// CHECK-LABEL: define dso_local void @"\01?call_vbase_bar@@YAXPAUB@@@Z"(%struct.B* %obj)
+// CHECK-LABEL: define dso_local void @"?call_vbase_bar@@YAXPAUB@@@Z"(%struct.B* %obj)
// CHECK: %[[OBJ:.*]] = load %struct.B
obj->bar();
@@ -184,7 +184,7 @@
}
void delete_B(B *obj) {
-// CHECK-LABEL: define dso_local void @"\01?delete_B@@YAXPAUB@@@Z"(%struct.B* %obj)
+// CHECK-LABEL: define dso_local void @"?delete_B@@YAXPAUB@@@Z"(%struct.B* %obj)
// CHECK: %[[OBJ:.*]] = load %struct.B
delete obj;
@@ -216,11 +216,11 @@
}
void call_complete_dtor() {
- // CHECK-LABEL: define dso_local void @"\01?call_complete_dtor@@YAXXZ"
+ // CHECK-LABEL: define dso_local void @"?call_complete_dtor@@YAXXZ"
B b;
- // CHECK: call x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"(%struct.B* %[[B:.*]], i32 1)
+ // CHECK: call x86_thiscallcc %struct.B* @"??0B@@QAE@XZ"(%struct.B* %[[B:.*]], i32 1)
// CHECK-NOT: getelementptr
- // CHECK: call x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B* %[[B]])
+ // CHECK: call x86_thiscallcc void @"??_DB@@QAEXXZ"(%struct.B* %[[B]])
// CHECK: ret
}
@@ -231,7 +231,7 @@
// Used to crash on an assertion.
C::C() {
-// CHECK-LABEL: define dso_local x86_thiscallcc %struct.C* @"\01??0C@@QAE@XZ"
+// CHECK-LABEL: define dso_local x86_thiscallcc %struct.C* @"??0C@@QAE@XZ"
}
namespace multiple_vbases {
@@ -255,11 +255,11 @@
};
D::D() {
- // CHECK-LABEL: define dso_local x86_thiscallcc %"struct.multiple_vbases::D"* @"\01??0D@multiple_vbases@@QAE@XZ"
+ // CHECK-LABEL: define dso_local x86_thiscallcc %"struct.multiple_vbases::D"* @"??0D@multiple_vbases@@QAE@XZ"
// Just make sure we emit 3 vtordisps after initializing vfptrs.
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7D@multiple_vbases@@6BA@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7D@multiple_vbases@@6BB@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7D@multiple_vbases@@6BC@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7D@multiple_vbases@@6BA@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7D@multiple_vbases@@6BB@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7D@multiple_vbases@@6BC@1@@" to i32 (...)**), i32 (...)*** %{{.*}}
// ...
// CHECK: store i32 %{{.*}}, i32* %{{.*}}
// CHECK: store i32 %{{.*}}, i32* %{{.*}}
@@ -295,7 +295,7 @@
} d;
D::~D() {
- // CHECK-LABEL: define dso_local x86_thiscallcc void @"\01??1D@diamond@@UAE@XZ"(%"struct.diamond::D"*{{.*}})
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1D@diamond@@UAE@XZ"(%"struct.diamond::D"*{{.*}})
// Store initial this:
// CHECK: %[[THIS_ADDR:.*]] = alloca %"struct.diamond::D"*
// CHECK: store %"struct.diamond::D"* %{{.*}}, %"struct.diamond::D"** %[[THIS_ADDR]], align 4
@@ -313,13 +313,13 @@
// CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 16
// FIXME: We might consider changing the dtor this parameter type to i8*.
// CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::C"*
- // CHECK: call x86_thiscallcc void @"\01??1C@diamond@@UAE@XZ"(%"struct.diamond::C"* %[[ARG]])
+ // CHECK: call x86_thiscallcc void @"??1C@diamond@@UAE@XZ"(%"struct.diamond::C"* %[[ARG]])
// CHECK: %[[B:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to %"struct.diamond::B"*
// CHECK: %[[B_i8:.*]] = bitcast %"struct.diamond::B"* %[[B]] to i8*
// CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %[[B_i8]], i32 4
// CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::B"*
- // CHECK: call x86_thiscallcc void @"\01??1B@diamond@@UAE@XZ"(%"struct.diamond::B"* %[[ARG]])
+ // CHECK: call x86_thiscallcc void @"??1B@diamond@@UAE@XZ"(%"struct.diamond::B"* %[[ARG]])
// CHECK: ret void
}
@@ -334,20 +334,20 @@
// call to B() from C().
void callC() { C x; }
-// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::C"* @"\01??0C@test2@@QAE@XZ"
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::C"* @"??0C@test2@@QAE@XZ"
// CHECK: (%"struct.test2::C"* returned %this, i32 %is_most_derived)
// CHECK: br i1
// Virtual bases
-// CHECK: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
+// CHECK: call x86_thiscallcc %"struct.test2::A"* @"??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK: br label
// Non-virtual bases
-// CHECK: call x86_thiscallcc %"struct.test2::B"* @"\01??0B@test2@@QAE@XZ"(%"struct.test2::B"* %{{.*}}, i32 0)
-// CHECK: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
+// CHECK: call x86_thiscallcc %"struct.test2::B"* @"??0B@test2@@QAE@XZ"(%"struct.test2::B"* %{{.*}}, i32 0)
+// CHECK: call x86_thiscallcc %"struct.test2::A"* @"??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK: ret
-// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::B"* @"\01??0B@test2@@QAE@XZ"
+// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::B"* @"??0B@test2@@QAE@XZ"
// CHECK2: (%"struct.test2::B"* returned %this, i32 %is_most_derived)
-// CHECK2: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
+// CHECK2: call x86_thiscallcc %"struct.test2::A"* @"??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK2: ret
}
@@ -374,7 +374,7 @@
};
void D::bar() {
- // CHECK-LABEL: define dso_local x86_thiscallcc void @"\01?bar@D@test3@@UAEXXZ"(%"struct.test3::D"* %this)
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"?bar@D@test3@@UAEXXZ"(%"struct.test3::D"* %this)
C::foo();
// Shouldn't need any vbtable lookups. All we have to do is adjust to C*,
@@ -385,7 +385,7 @@
// CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.test3::C"*
// CHECK: %[[C_i8:.*]] = bitcast %"struct.test3::C"* %[[C]] to i8*
// CHECK: %[[ARG:.*]] = getelementptr i8, i8* %[[C_i8]], i32 4
- // CHECK: call x86_thiscallcc void @"\01?foo@C@test3@@UAEXXZ"(i8* %[[ARG]])
+ // CHECK: call x86_thiscallcc void @"?foo@C@test3@@UAEXXZ"(i8* %[[ARG]])
// CHECK: ret
}
}
@@ -408,20 +408,20 @@
void foo(void*);
C::~C() {
- // CHECK-LABEL: define dso_local x86_thiscallcc void @"\01??1C@test4@@UAE@XZ"(%"struct.test4::C"* %this)
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1C@test4@@UAE@XZ"(%"struct.test4::C"* %this)
// In this case "this" points to the most derived class, so no GEPs needed.
// CHECK-NOT: getelementptr
// CHECK-NOT: bitcast
// CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7C@test4@@6BB@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7C@test4@@6BB@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
foo(this);
// CHECK: ret
}
void destroy(C *obj) {
- // CHECK-LABEL: define dso_local void @"\01?destroy@test4@@YAXPAUC@1@@Z"(%"struct.test4::C"* %obj)
+ // CHECK-LABEL: define dso_local void @"?destroy@test4@@YAXPAUC@1@@Z"(%"struct.test4::C"* %obj)
delete obj;
// CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to i8* (%"struct.test4::C"*, i32)***
@@ -443,18 +443,18 @@
};
E::~E() {
- // CHECK-LABEL: define dso_local x86_thiscallcc void @"\01??1E@test4@@UAE@XZ"(%"struct.test4::E"* %this)
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1E@test4@@UAE@XZ"(%"struct.test4::E"* %this)
// In this case "this" points to the most derived class, so no GEPs needed.
// CHECK-NOT: getelementptr
// CHECK-NOT: bitcast
// CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to i32 (...)***
- // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7E@test4@@6BD@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
+ // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7E@test4@@6BD@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
foo(this);
}
void destroy(E *obj) {
- // CHECK-LABEL: define dso_local void @"\01?destroy@test4@@YAXPAUE@1@@Z"(%"struct.test4::E"* %obj)
+ // CHECK-LABEL: define dso_local void @"?destroy@test4@@YAXPAUE@1@@Z"(%"struct.test4::E"* %obj)
// CHECK-NOT: getelementptr
// CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8*
@@ -488,7 +488,7 @@
};
C::C() : B() {}
-// CHECK-LABEL: define dso_local x86_thiscallcc %"struct.test5::C"* @"\01??0C@test5@@QAE@XZ"(
+// CHECK-LABEL: define dso_local x86_thiscallcc %"struct.test5::C"* @"??0C@test5@@QAE@XZ"(
// CHECK: %[[THIS:.*]] = load %"struct.test5::C"*, %"struct.test5::C"**
// CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
@@ -512,9 +512,9 @@
void callit(C *p) {
static_cast<B*>(p)->g();
}
-// CHECK-LABEL: define dso_local void @"\01?callit@pr27621@@YAXPAUC@1@@Z"(%"struct.pr27621::C"* %{{.*}})
+// CHECK-LABEL: define dso_local void @"?callit@pr27621@@YAXPAUC@1@@Z"(%"struct.pr27621::C"* %{{.*}})
// CHECK: %[[B_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 4
-// CHECK: call x86_thiscallcc void @"\01?g@C@pr27621@@UAEXXZ"(i8* %[[B_i8]])
+// CHECK: call x86_thiscallcc void @"?g@C@pr27621@@UAEXXZ"(i8* %[[B_i8]])
}
namespace test6 {
@@ -528,7 +528,7 @@
D();
};
D::D() : C() {}
-// CHECK-LABEL: define dso_local x86_thiscallcc %"class.test6::D"* @"\01??0D@test6@@AAE@XZ"(
+// CHECK-LABEL: define dso_local x86_thiscallcc %"class.test6::D"* @"??0D@test6@@AAE@XZ"(
// CHECK: %[[THIS:.*]] = load %"class.test6::D"*, %"class.test6::D"**
// CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
@@ -538,3 +538,20 @@
// CHECK: %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[C_i8]], i32 8
// CHECK: call void @llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false)
}
+
+namespace pr36921 {
+struct A {
+ virtual ~A() {}
+};
+struct B {
+ virtual ~B() {}
+};
+struct C : virtual B {};
+struct D : virtual A, C {};
+D d;
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_GD@pr36921@@UAEPAXI@Z"(
+// CHECK: %[[THIS:.*]] = load %"struct.pr36921::D"*, %"struct.pr36921::D"**
+// CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.pr36921::D"* %[[THIS_RELOAD]] to i8*
+// CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -4
+// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.pr36921::D"*
+}
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
index 0c37570..ef8a5e4 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
@@ -53,24 +53,24 @@
auto ptr7 = &C::plugh;
-// CHECK32-LABEL: define dso_local void @"\01?f@@YAXXZ"()
-// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$BA@AE" to i8*), i8** %ptr
-// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$B3AE" to i8*), i8** %ptr2
-// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$B7AE" to i8*), i8** %ptr3
-// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"\01??_9D@?A@@$BA@AE" to i8*), i8** %ptr4
+// CHECK32-LABEL: define dso_local void @"?f@@YAXXZ"()
+// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BA@AE" to i8*), i8** %ptr
+// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B3AE" to i8*), i8** %ptr2
+// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B7AE" to i8*), i8** %ptr3
+// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A@@$BA@AE" to i8*), i8** %ptr4
// CHECK32: }
//
-// CHECK64-LABEL: define dso_local void @"\01?f@@YAXXZ"()
-// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$BA@AA" to i8*), i8** %ptr
-// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$B7AA" to i8*), i8** %ptr2
-// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$BBA@AA" to i8*), i8** %ptr3
-// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"\01??_9D@?A@@$BA@AA" to i8*), i8** %ptr
+// CHECK64-LABEL: define dso_local void @"?f@@YAXXZ"()
+// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BA@AA" to i8*), i8** %ptr
+// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B7AA" to i8*), i8** %ptr2
+// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BBA@AA" to i8*), i8** %ptr3
+// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A@@$BA@AA" to i8*), i8** %ptr
// CHECK64: }
}
// Thunk for calling the 1st virtual function in C with no parameters.
-// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BA@AE"(%struct.C* %this, ...)
+// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@@$BA@AE"(%struct.C* %this, ...)
// CHECK32: #[[ATTR:[0-9]+]]
// CHECK32-NOT: unnamed_addr
// CHECK32: comdat
@@ -80,7 +80,7 @@
// CHECK32-NEXT: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BA@AA"(%struct.C* %this, ...)
+// CHECK64-LABEL: define linkonce_odr void @"??_9C@@$BA@AA"(%struct.C* %this, ...)
// CHECK64: #[[ATTR:[0-9]+]]
// CHECK64-NOT: unnamed_addr
// CHECK64: comdat
@@ -91,7 +91,7 @@
// CHECK64: }
// Thunk for calling the 2nd virtual function in C, taking int and double as parameters, returning int.
-// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$B3AE"(%struct.C* %this, ...)
+// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@@$B3AE"(%struct.C* %this, ...)
// CHECK32: #[[ATTR]] comdat
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 1
// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
@@ -99,7 +99,7 @@
// CHECK32-NEXT: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$B7AA"(%struct.C* %this, ...)
+// CHECK64-LABEL: define linkonce_odr void @"??_9C@@$B7AA"(%struct.C* %this, ...)
// CHECK64: #[[ATTR]] comdat
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 1
// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
@@ -108,7 +108,7 @@
// CHECK64: }
// Thunk for calling the 3rd virtual function in C, taking an int parameter, returning a struct.
-// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$B7AE"(%struct.C* %this, ...)
+// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@@$B7AE"(%struct.C* %this, ...)
// CHECK32: #[[ATTR]] comdat
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 2
// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
@@ -116,7 +116,7 @@
// CHECK32-NEXT: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBA@AA"(%struct.C* %this, ...)
+// CHECK64-LABEL: define linkonce_odr void @"??_9C@@$BBA@AA"(%struct.C* %this, ...)
// CHECK64: #[[ATTR]] comdat
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 2
// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
@@ -125,7 +125,7 @@
// CHECK64: }
// Thunk for calling the virtual function in internal class D.
-// CHECK32-LABEL: define internal x86_thiscallcc void @"\01??_9D@?A@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this, ...)
+// CHECK32-LABEL: define internal x86_thiscallcc void @"??_9D@?A@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this, ...)
// CHECK32: #[[ATTR]]
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0
// CHECK32: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]]
@@ -133,7 +133,7 @@
// CHECK32-NEXT: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define internal void @"\01??_9D@?A@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this, ...)
+// CHECK64-LABEL: define internal void @"??_9D@?A@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this, ...)
// CHECK64: #[[ATTR]]
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0
// CHECK64: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]]
@@ -143,14 +143,14 @@
// Thunk for calling the fourth virtual function in C, taking a struct parameter
// and returning a struct.
-// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BM@AE"(%struct.C* %this, ...) {{.*}} comdat
+// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@@$BM@AE"(%struct.C* %this, ...) {{.*}} comdat
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 3
// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
// CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
// CHECK32-NEXT: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBI@AA"(%struct.C* %this, ...) {{.*}} comdat
+// CHECK64-LABEL: define linkonce_odr void @"??_9C@@$BBI@AA"(%struct.C* %this, ...) {{.*}} comdat
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 3
// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
// CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
@@ -158,28 +158,28 @@
// CHECK64: }
// Thunk for calling the fifth virtual function in C which uses the __cdecl calling convention.
-// CHECK32-LABEL: define linkonce_odr void @"\01??_9C@@$BBA@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
+// CHECK32-LABEL: define linkonce_odr void @"??_9C@@$BBA@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 4
// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
// CHECK32: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
// CHECK32: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BCA@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
+// CHECK64-LABEL: define linkonce_odr void @"??_9C@@$BCA@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 4
// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
// CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
// CHECK64: ret void
// CHECK64: }
-// CHECK32: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BBE@AE"(%struct.C* %this, ...) {{.*}} comdat align 2 {
+// CHECK32: define linkonce_odr x86_thiscallcc void @"??_9C@@$BBE@AE"(%struct.C* %this, ...) {{.*}} comdat align 2 {
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 5
// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
// CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
// CHECK32: ret void
// CHECK32: }
-// CHECK64: define linkonce_odr void @"\01??_9C@@$BCI@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
+// CHECK64: define linkonce_odr void @"??_9C@@$BCI@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 5
// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
// CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
diff --git a/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp b/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp
index 058458b..607ec81 100644
--- a/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp
@@ -19,11 +19,11 @@
}
}
-// CHECK-LABEL: define dso_local void @"\01?f@num_params@@YAXPAUC@1@@Z"(%"struct.num_params::C"* %c)
-// CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"\01??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0)
-// CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"\01??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0, i32 0)
+// CHECK-LABEL: define dso_local void @"?f@num_params@@YAXPAUC@1@@Z"(%"struct.num_params::C"* %c)
+// CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0)
+// CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0, i32 0)
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@num_params@@$BA@AE"(%"struct.num_params::C"* %this, ...) {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@num_params@@$BA@AE"(%"struct.num_params::C"* %this, ...) {{.*}} comdat
// CHECK: musttail call x86_thiscallcc void (%"struct.num_params::C"*, ...) %{{.*}}(%"struct.num_params::C"* %{{.*}}, ...)
// CHECK-NEXT: ret void
@@ -41,11 +41,11 @@
}
}
-// CHECK-LABEL: define dso_local i64 @"\01?f@i64_return@@YA_JPAUC@1@@Z"(%"struct.i64_return::C"* %c)
-// CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.i64_return::C"*, ...)* @"\01??_9C@i64_return@@$BA@AE" to i32 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}})
-// CHECK: call x86_thiscallcc i64 bitcast (void (%"struct.i64_return::C"*, ...)* @"\01??_9C@i64_return@@$BA@AE" to i64 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}})
+// CHECK-LABEL: define dso_local i64 @"?f@i64_return@@YA_JPAUC@1@@Z"(%"struct.i64_return::C"* %c)
+// CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.i64_return::C"*, ...)* @"??_9C@i64_return@@$BA@AE" to i32 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}})
+// CHECK: call x86_thiscallcc i64 bitcast (void (%"struct.i64_return::C"*, ...)* @"??_9C@i64_return@@$BA@AE" to i64 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}})
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@i64_return@@$BA@AE"(%"struct.i64_return::C"* %this, ...) {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@i64_return@@$BA@AE"(%"struct.i64_return::C"* %this, ...) {{.*}} comdat
// CHECK: musttail call x86_thiscallcc void (%"struct.i64_return::C"*, ...) %{{.*}}(%"struct.i64_return::C"* %{{.*}}, ...)
// CHECK-NEXT: ret void
@@ -63,11 +63,11 @@
}
}
-// CHECK-LABEL: define dso_local void @"\01?f@sret@@YAXPAUC@1@@Z"(%"struct.sret::C"* %c)
-// CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.sret::C"*, ...)* @"\01??_9C@sret@@$BA@AE" to i32 (%"struct.sret::C"*)*)(%"struct.sret::C"* %{{.*}})
-// CHECK: call x86_thiscallcc void bitcast (void (%"struct.sret::C"*, ...)* @"\01??_9C@sret@@$BA@AE" to void (%"struct.sret::C"*, %"struct.sret::Big"*)*)(%"struct.sret::C"* %{{.*}}, %"struct.sret::Big"* sret %{{.*}})
+// CHECK-LABEL: define dso_local void @"?f@sret@@YAXPAUC@1@@Z"(%"struct.sret::C"* %c)
+// CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.sret::C"*, ...)* @"??_9C@sret@@$BA@AE" to i32 (%"struct.sret::C"*)*)(%"struct.sret::C"* %{{.*}})
+// CHECK: call x86_thiscallcc void bitcast (void (%"struct.sret::C"*, ...)* @"??_9C@sret@@$BA@AE" to void (%"struct.sret::C"*, %"struct.sret::Big"*)*)(%"struct.sret::C"* %{{.*}}, %"struct.sret::Big"* sret %{{.*}})
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@sret@@$BA@AE"(%"struct.sret::C"* %this, ...) {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@sret@@$BA@AE"(%"struct.sret::C"* %this, ...) {{.*}} comdat
// CHECK: musttail call x86_thiscallcc void (%"struct.sret::C"*, ...) %{{.*}}(%"struct.sret::C"* %{{.*}}, ...)
// CHECK-NEXT: ret void
@@ -92,10 +92,10 @@
}
}
-// CHECK-LABEL: define dso_local void @"\01?f@cdecl_inalloca@@YAXPAUC@1@@Z"(%"struct.cdecl_inalloca::C"* %c)
-// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AA" to void (%"struct.cdecl_inalloca::C"*)*)(%"struct.cdecl_inalloca::C"* %{{.*}})
-// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AA" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca %{{.*}})
+// CHECK-LABEL: define dso_local void @"?f@cdecl_inalloca@@YAXPAUC@1@@Z"(%"struct.cdecl_inalloca::C"* %c)
+// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"??_9C@cdecl_inalloca@@$BA@AA" to void (%"struct.cdecl_inalloca::C"*)*)(%"struct.cdecl_inalloca::C"* %{{.*}})
+// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"??_9C@cdecl_inalloca@@$BA@AA" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca %{{.*}})
-// CHECK-LABEL: define linkonce_odr void @"\01??_9C@cdecl_inalloca@@$BA@AA"(%"struct.cdecl_inalloca::C"* %this, ...) {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr void @"??_9C@cdecl_inalloca@@$BA@AA"(%"struct.cdecl_inalloca::C"* %this, ...) {{.*}} comdat
// CHECK: musttail call void (%"struct.cdecl_inalloca::C"*, ...) %{{.*}}(%"struct.cdecl_inalloca::C"* %{{.*}}, ...)
// CHECK-NEXT: ret void
diff --git a/test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp b/test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp
index 97ab199..59e8b0b 100644
--- a/test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp
@@ -7,7 +7,7 @@
return &A::f;
}
-// CHECK: define linkonce_odr x86_fastcallcc void @"\01??_9A@@$BA@AI"(%struct.A* inreg %this, ...) {{.*}} comdat align 2 {
+// CHECK: define linkonce_odr x86_fastcallcc void @"??_9A@@$BA@AI"(%struct.A* inreg %this, ...) {{.*}} comdat align 2 {
// CHECK: [[VPTR:%.*]] = getelementptr inbounds void (%struct.A*, ...)*, void (%struct.A*, ...)** %{{.*}}, i64 0
// CHECK: [[CALLEE:%.*]] = load void (%struct.A*, ...)*, void (%struct.A*, ...)** [[VPTR]]
// CHECK: musttail call x86_fastcallcc void (%struct.A*, ...) [[CALLEE]](%struct.A* inreg %{{.*}}, ...)
diff --git a/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp b/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp
index d23a4a9..972428a 100644
--- a/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp
@@ -8,5 +8,5 @@
virtual void f();
};
void (B::*MemPtr)(void) = &B::f;
-// CHECK-DAG: @"\01?MemPtr@PR23452@@3P8B@1@AEXXZQ21@" = dso_local global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01??_9B@PR23452@@$BA@AE" to i8*), i32 0, i32 4 }
+// CHECK-DAG: @"?MemPtr@PR23452@@3P8B@1@AEXXZQ21@" = dso_local global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"??_9B@PR23452@@$BA@AE" to i8*), i32 0, i32 4 }
}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp
index 86314cf..62289e4 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp
@@ -24,8 +24,8 @@
// CHECK-LABEL: VFTable indices for 'test1::X' (1 entry)
// CHECK-NEXT: 0 | void test1::X::f()
- // MANGLING-DAG: @"\01??_7X@test1@@6BA@1@@"
- // MANGLING-DAG: @"\01??_7X@test1@@6BB@1@@"
+ // MANGLING-DAG: @"??_7X@test1@@6BA@1@@"
+ // MANGLING-DAG: @"??_7X@test1@@6BB@1@@"
// Overrides only the left child's method (A::f), needs no thunks.
virtual void f();
@@ -108,7 +108,7 @@
// CHECK-LABEL: VFTable indices for 'test4::X' (1 entry).
// CHECK-NEXT: 0 | void test4::X::f()
- // MANGLING-DAG: @"\01??_7X@test4@@6B@"
+ // MANGLING-DAG: @"??_7X@test4@@6B@"
virtual void f();
} x;
@@ -141,8 +141,8 @@
// CHECK-LABEL: VFTable indices for 'test5::X' (1 entry).
// CHECK-NEXT: 0 | void test5::X::f()
- // MANGLING-DAG: @"\01??_7X@test5@@6BA@1@@"
- // MANGLING-DAG: @"\01??_7X@test5@@6BB@1@@"
+ // MANGLING-DAG: @"??_7X@test5@@6BA@1@@"
+ // MANGLING-DAG: @"??_7X@test5@@6BB@1@@"
// Overrides both C::f and A::f.
virtual void f();
@@ -241,8 +241,8 @@
// CHECK-LABEL: VFTable indices for 'test8::X' (1 entry).
// CHECK-NEXT: 1 | void test8::X::h()
- // MANGLING-DAG: @"\01??_7X@test8@@6BA@1@@"
- // MANGLING-DAG: @"\01??_7X@test8@@6BB@1@@"
+ // MANGLING-DAG: @"??_7X@test8@@6BA@1@@"
+ // MANGLING-DAG: @"??_7X@test8@@6BB@1@@"
virtual void h();
} x;
@@ -290,10 +290,10 @@
// CHECK-LABEL: VFTable indices for 'test9::X' (1 entry).
// CHECK-NEXT: 1 | void test9::X::z()
- // MANGLING-DAG: @"\01??_7X@test9@@6BA@1@C@1@@"
- // MANGLING-DAG: @"\01??_7X@test9@@6BA@1@D@1@@"
- // MANGLING-DAG: @"\01??_7X@test9@@6BB@1@C@1@@"
- // MANGLING-DAG: @"\01??_7X@test9@@6BB@1@D@1@@"
+ // MANGLING-DAG: @"??_7X@test9@@6BA@1@C@1@@"
+ // MANGLING-DAG: @"??_7X@test9@@6BA@1@D@1@@"
+ // MANGLING-DAG: @"??_7X@test9@@6BB@1@C@1@@"
+ // MANGLING-DAG: @"??_7X@test9@@6BB@1@D@1@@"
virtual void z();
} x;
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp
index 76182a2..85022fc 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp
@@ -23,8 +23,8 @@
// CHECK-NEXT: via vfptr at offset 4
// CHECK-NEXT: 0 | void C::g()
- // MANGLING-DAG: @"\01??_7C@@6BA@@@"
- // MANGLING-DAG: @"\01??_7C@@6BB@@@"
+ // MANGLING-DAG: @"??_7C@@6BA@@@"
+ // MANGLING-DAG: @"??_7C@@6BB@@@"
// Overrides only the right child's method (B::g),
// needs this adjustment but not thunks.
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp
index 232c0d9..f7b79a9 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp
@@ -36,7 +36,7 @@
// CHECK-LABEL: VFTable indices for 'test1::X' (1 entry).
// CHECK-NEXT: 2 | test1::C *test1::X::foo()
- // MANGLING-DAG: @"\01??_7X@test1@@6B@"
+ // MANGLING-DAG: @"??_7X@test1@@6B@"
virtual C* foo();
} x;
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
index 7679c55..e34c4d0 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
@@ -29,8 +29,8 @@
// CHECK-LABEL: VFTable indices for 'test1::X' (1 entry).
// CHECK-NEXT: 0 | void test1::X::g()
- // BITCODE-DAG: @"\01??_7X@test1@@6BA@1@@"
- // BITCODE-DAG: @"\01??_7X@test1@@6BB@1@@"
+ // BITCODE-DAG: @"??_7X@test1@@6BA@1@@"
+ // BITCODE-DAG: @"??_7X@test1@@6BB@1@@"
virtual void g();
} x;
@@ -71,9 +71,9 @@
// CHECK-NEXT: via vfptr at offset 4
// CHECK-NEXT: 0 | void test2::X::g()
- // BITCODE-DAG: @"\01??_7X@test2@@6BA@1@@"
- // BITCODE-DAG: @"\01??_7X@test2@@6BB@1@@"
- // BITCODE-DAG: @"\01??_7X@test2@@6BC@1@@"
+ // BITCODE-DAG: @"??_7X@test2@@6BA@1@@"
+ // BITCODE-DAG: @"??_7X@test2@@6BB@1@@"
+ // BITCODE-DAG: @"??_7X@test2@@6BC@1@@"
virtual void g();
} x;
@@ -154,7 +154,7 @@
virtual int bar();
};
-// BITCODE-LABEL: define {{.*}}\01?ffun@test4@@YAXAAUC@1@@Z
+// BITCODE-LABEL: define {{.*}}"?ffun@test4@@YAXAAUC@1@@Z
void ffun(C &c) {
// BITCODE: [[THIS1:%.+]] = bitcast %"struct.test4::C"* {{.*}} to i8*
// BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, i8* [[THIS1]], i32 4
@@ -162,7 +162,7 @@
c.bar();
}
-// BITCODE-LABEL: define {{.*}}\01?fop@test4@@YAXAAUC@1@@Z
+// BITCODE-LABEL: define {{.*}}"?fop@test4@@YAXAAUC@1@@Z
void fop(C &c) {
// BITCODE: [[THIS1:%.+]] = bitcast %"struct.test4::C"* {{.*}} to i8*
// BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, i8* [[THIS1]], i32 4
@@ -189,12 +189,12 @@
whatsthis = this;
}
-// BITCODE-LABEL: define dso_local void @"\01?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca)
+// BITCODE-LABEL: define dso_local void @"?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca)
// BITCODE: %[[thisaddr:[^ ]*]] = getelementptr inbounds <{ i8*, %"struct.pr30293::NonTrivial" }>, <{ i8*, %"struct.pr30293::NonTrivial" }>* {{.*}}, i32 0, i32 0
// BITCODE: %[[thisaddr1:[^ ]*]] = bitcast i8** %[[thisaddr]] to %"struct.pr30293::C"**
// BITCODE: %[[this1:[^ ]*]] = load %"struct.pr30293::C"*, %"struct.pr30293::C"** %[[thisaddr1]], align 4
// BITCODE: %[[this2:[^ ]*]] = bitcast %"struct.pr30293::C"* %[[this1]] to i8*
// BITCODE: %[[this3:[^ ]*]] = getelementptr inbounds i8, i8* %[[this2]], i32 -4
// BITCODE: %[[this4:[^ ]*]] = bitcast i8* %[[this3]] to %"struct.pr30293::C"*
-// BITCODE: store %"struct.pr30293::C"* %[[this4]], %"struct.pr30293::C"** @"\01?whatsthis@pr30293@@3PAUC@1@A", align 4
+// BITCODE: store %"struct.pr30293::C"* %[[this4]], %"struct.pr30293::C"** @"?whatsthis@pr30293@@3PAUC@1@A", align 4
}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
index feba91c..38e6ed5 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
@@ -26,10 +26,10 @@
// VFTABLES-NEXT: [return adjustment (to type 'struct test1::C *'): 0 non-virtual]
// VFTABLES-NEXT: 2 | test1::D *test1::J::foo()
-// GLOBALS-LABEL: @"\01??_7J@test1@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
-// GLOBALS: @"\01?foo@J@test1@@QAEPAUB@2@XZ"
-// GLOBALS: @"\01?foo@J@test1@@QAEPAUC@2@XZ"
-// GLOBALS: @"\01?foo@J@test1@@UAEPAUD@2@XZ"
+// GLOBALS-LABEL: @"??_7J@test1@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
+// GLOBALS: @"?foo@J@test1@@QAEPAUB@2@XZ"
+// GLOBALS: @"?foo@J@test1@@QAEPAUC@2@XZ"
+// GLOBALS: @"?foo@J@test1@@UAEPAUD@2@XZ"
K::K() {}
@@ -44,26 +44,26 @@
// Only B to C requires adjustment, but we get 3 thunks in K's vftable, two of
// which are trivial.
-// GLOBALS-LABEL: @"\01??_7K@test1@@6B@" = linkonce_odr unnamed_addr constant { [4 x i8*] }
-// GLOBALS: @"\01?foo@K@test1@@QAEPAUB@2@XZ"
-// GLOBALS: @"\01?foo@K@test1@@QAEPAUC@2@XZ"
-// GLOBALS: @"\01?foo@K@test1@@QAEPAUD@2@XZ"
-// GLOBALS: @"\01?foo@K@test1@@UAEPAUE@2@XZ"
+// GLOBALS-LABEL: @"??_7K@test1@@6B@" = linkonce_odr unnamed_addr constant { [4 x i8*] }
+// GLOBALS: @"?foo@K@test1@@QAEPAUB@2@XZ"
+// GLOBALS: @"?foo@K@test1@@QAEPAUC@2@XZ"
+// GLOBALS: @"?foo@K@test1@@QAEPAUD@2@XZ"
+// GLOBALS: @"?foo@K@test1@@UAEPAUE@2@XZ"
// This thunk has a return adjustment.
-// CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUB@2@XZ"
-// CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ"
+// CODEGEN-LABEL: define {{.*}} @"?foo@K@test1@@QAEPAUB@2@XZ"
+// CODEGEN: call {{.*}} @"?foo@K@test1@@UAEPAUE@2@XZ"
// CODEGEN: icmp {{.*}}, null
// CODEGEN: getelementptr
// CODEGEN: ret
// These two don't.
-// CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUC@2@XZ"
-// CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ"
+// CODEGEN-LABEL: define {{.*}} @"?foo@K@test1@@QAEPAUC@2@XZ"
+// CODEGEN: call {{.*}} @"?foo@K@test1@@UAEPAUE@2@XZ"
// CODEGEN-NEXT: ret
-// CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUD@2@XZ"
-// CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ"
+// CODEGEN-LABEL: define {{.*}} @"?foo@K@test1@@QAEPAUD@2@XZ"
+// CODEGEN: call {{.*}} @"?foo@K@test1@@UAEPAUE@2@XZ"
// CODEGEN-NEXT: ret
}
@@ -90,7 +90,7 @@
// VFTABLES-NEXT: [return adjustment (to type 'struct test2::B *'): 4 non-virtual]
// VFTABLES-NEXT: 1 | test2::D *test2::J::foo()
-// GLOBALS-LABEL: @"\01??_7J@test2@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
+// GLOBALS-LABEL: @"??_7J@test2@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
K::K() {}
@@ -101,7 +101,7 @@
// VFTABLES-NEXT: [return adjustment (to type 'struct test2::D *'): 0 non-virtual]
// VFTABLES-NEXT: 2 | test2::E *test2::K::foo()
-// GLOBALS-LABEL: @"\01??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
+// GLOBALS-LABEL: @"??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
}
@@ -124,9 +124,9 @@
C::C() {}
-// GLOBALS-LABEL: @"\01??_7C@pr20479@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
-// GLOBALS: @"\01?f@B@pr20479@@QAEPAUA@2@XZ"
-// GLOBALS: @"\01?f@B@pr20479@@UAEPAU12@XZ"
+// GLOBALS-LABEL: @"??_7C@pr20479@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
+// GLOBALS: @"?f@B@pr20479@@QAEPAUA@2@XZ"
+// GLOBALS: @"?f@B@pr20479@@UAEPAU12@XZ"
}
namespace pr21073 {
@@ -151,9 +151,9 @@
C::C() {}
-// GLOBALS-LABEL: @"\01??_7C@pr21073@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
-// GLOBALS: @"\01?f@B@pr21073@@WPPPPPPPI@AEPAUA@2@XZ"
-// GLOBALS: @"\01?f@B@pr21073@@WPPPPPPPI@AEPAU12@XZ"
+// GLOBALS-LABEL: @"??_7C@pr21073@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
+// GLOBALS: @"?f@B@pr21073@@WPPPPPPPI@AEPAUA@2@XZ"
+// GLOBALS: @"?f@B@pr21073@@WPPPPPPPI@AEPAU12@XZ"
}
namespace pr21073_2 {
@@ -168,9 +168,9 @@
// VFTABLES-NEXT: [return adjustment (to type 'struct pr21073_2::A *'): vbase #1, 0 non-virtual]
// VFTABLES-NEXT: 1 | pr21073_2::C *pr21073_2::C::foo()
-// GLOBALS-LABEL: @"\01??_7D@pr21073_2@@6B@" = {{.*}} constant { [2 x i8*] }
-// GLOBALS: @"\01?foo@C@pr21073_2@@QAEPAUA@2@XZ"
-// GLOBALS: @"\01?foo@C@pr21073_2@@UAEPAU12@XZ"
+// GLOBALS-LABEL: @"??_7D@pr21073_2@@6B@" = {{.*}} constant { [2 x i8*] }
+// GLOBALS: @"?foo@C@pr21073_2@@QAEPAUA@2@XZ"
+// GLOBALS: @"?foo@C@pr21073_2@@UAEPAU12@XZ"
}
namespace test3 {
@@ -196,10 +196,10 @@
// VFTABLES-NEXT: [return adjustment (to type 'struct test3::D *'): 0 non-virtual]
// VFTABLES-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
-// GLOBALS-LABEL: @"\01??_7D@test3@@6B@" = {{.*}} constant { [3 x i8*] }
-// GLOBALS: @"\01?fn@D@test3@@$4PPPPPPPM@A@AEPAUA@2@XZ"
-// GLOBALS: @"\01?fn@D@test3@@$4PPPPPPPM@A@AEPAUB@2@XZ"
-// GLOBALS: @"\01?fn@D@test3@@$4PPPPPPPM@A@AEPAU12@XZ"
+// GLOBALS-LABEL: @"??_7D@test3@@6B@" = {{.*}} constant { [3 x i8*] }
+// GLOBALS: @"?fn@D@test3@@$4PPPPPPPM@A@AEPAUA@2@XZ"
+// GLOBALS: @"?fn@D@test3@@$4PPPPPPPM@A@AEPAUB@2@XZ"
+// GLOBALS: @"?fn@D@test3@@$4PPPPPPPM@A@AEPAU12@XZ"
}
namespace pr34302 {
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
index 738c15d..f84ffd5 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
@@ -19,7 +19,7 @@
int ia;
};
A a;
-// EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
+// EMITS-VFTABLE-DAG: @"??_7A@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
void use(A *obj) { obj->f(); }
struct B : A {
@@ -39,7 +39,7 @@
virtual void j();
};
B b;
-// EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] }
+// EMITS-VFTABLE-DAG: @"??_7B@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] }
void use(B *obj) { obj->f(); }
struct C {
@@ -54,7 +54,7 @@
virtual void f();
};
void C::f() {}
-// NO-VFTABLE-NOT: @"\01??_7C@@6B@"
+// NO-VFTABLE-NOT: @"??_7C@@6B@"
void use(C *obj) { obj->f(); }
struct D {
@@ -69,7 +69,7 @@
virtual ~D();
};
D d;
-// EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
+// EMITS-VFTABLE-DAG: @"??_7D@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
void use(D *obj) { obj->f(); }
struct E : A {
@@ -89,7 +89,7 @@
virtual void i();
};
void E::i() {}
-// NO-VFTABLE-NOT: @"\01??_7E@@6B@"
+// NO-VFTABLE-NOT: @"??_7E@@6B@"
void use(E *obj) { obj->i(); }
struct F : A {
@@ -107,7 +107,7 @@
virtual ~F();
};
F f;
-// EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] }
+// EMITS-VFTABLE-DAG: @"??_7F@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] }
void use(F *obj) { obj->i(); }
struct G : E {
@@ -128,7 +128,7 @@
virtual void j();
};
void G::j() {}
-// NO-VFTABLE-NOT: @"\01??_7G@@6B@"
+// NO-VFTABLE-NOT: @"??_7G@@6B@"
void use(G *obj) { obj->j(); }
// Test that the usual Itanium-style key method does not emit a vtable.
@@ -136,7 +136,7 @@
virtual void f();
};
void H::f() {}
-// NO-VFTABLE-NOT: @"\01??_7H@@6B@"
+// NO-VFTABLE-NOT: @"??_7H@@6B@"
struct Empty { };
@@ -295,7 +295,7 @@
// CHECK-NEXT: 0 | void S::f() [deleted]
virtual void f() = delete;
S();
- // EMITS-VFTABLE-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] }
+ // EMITS-VFTABLE-DAG: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] }
};
S::S() {}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
index e26d333..c5ce69f 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
@@ -67,10 +67,10 @@
// CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual]
virtual void f();
- // MANGLING-DAG: @"\01?f@A@simple@@$4PPPPPPPM@A@AEXXZ"
+ // MANGLING-DAG: @"?f@A@simple@@$4PPPPPPPM@A@AEXXZ"
virtual ~A();
- // MANGLING-DAG: @"\01??_EA@simple@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EA@simple@@$4PPPPPPPM@A@AEPAXI@Z"
};
A a;
@@ -102,11 +102,11 @@
B() { use_somewhere_else(this); }
virtual void f();
- // MANGLING-DAG: @"\01?f@B@simple@@$4PPPPPPPE@A@AEXXZ"
+ // MANGLING-DAG: @"?f@B@simple@@$4PPPPPPPE@A@AEXXZ"
// Has an implicit destructor.
- // MANGLING-DAG: @"\01??_EB@simple@@$4PPPPPPPE@7AEPAXI@Z"
- // MANGLING-DAG: @"\01??_EB@simple@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EB@simple@@$4PPPPPPPE@7AEPAXI@Z"
+ // MANGLING-DAG: @"??_EB@simple@@$4PPPPPPPM@A@AEPAXI@Z"
};
B b;
@@ -147,12 +147,12 @@
int x;
virtual void f();
- // MANGLING-DAG: @"\01?f@C@simple@@$4PPPPPPPA@3AEXXZ"
- // MANGLING-DAG: @"\01?f@C@simple@@$4PPPPPPPE@A@AEXXZ"
+ // MANGLING-DAG: @"?f@C@simple@@$4PPPPPPPA@3AEXXZ"
+ // MANGLING-DAG: @"?f@C@simple@@$4PPPPPPPE@A@AEXXZ"
virtual ~C();
- // MANGLING-DAG: @"\01??_EC@simple@@$4PPPPPPPA@M@AEPAXI@Z"
- // MANGLING-DAG: @"\01??_EC@simple@@$4PPPPPPPE@7AEPAXI@Z"
- // MANGLING-DAG: @"\01??_EC@simple@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EC@simple@@$4PPPPPPPA@M@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EC@simple@@$4PPPPPPPE@7AEPAXI@Z"
+ // MANGLING-DAG: @"??_EC@simple@@$4PPPPPPPM@A@AEPAXI@Z"
};
C c;
@@ -167,7 +167,7 @@
D();
int z;
- // MANGLING-DAG: @"\01?f@B@simple@@$4PPPPPPPE@3AEXXZ"
+ // MANGLING-DAG: @"?f@B@simple@@$4PPPPPPPE@3AEXXZ"
};
D::D() {}
@@ -192,7 +192,7 @@
virtual void g(); // Force a vtordisp.
int f;
- // MANGLING-DAG: @"\01?g@F@simple@@$4PPPPPPPM@A@AEXXZ"{{.*}}??_EF@simple@@$4PPPPPPPM@A@AEPAXI@Z
+ // MANGLING-DAG: @"?g@F@simple@@$4PPPPPPPM@A@AEXXZ"{{.*}}??_EF@simple@@$4PPPPPPPM@A@AEPAXI@Z
// MANGLING-DAG: ?f@E@simple@@UAEXXZ{{.*}}??_EF@simple@@$4PPPPPPPE@7AEPAXI@Z
};
@@ -213,8 +213,8 @@
G();
int g;
- // MANGLING-DAG: @"\01?g@F@simple@@$4PPPPPPPM@3AEXXZ"{{.*}}@"\01??_EG@simple@@$4PPPPPPPM@A@AEPAXI@Z"
- // MANGLING-DAG: @"\01?f@E@simple@@UAEXXZ"{{.*}}@"\01??_EG@simple@@$4PPPPPPPE@7AEPAXI@Z"
+ // MANGLING-DAG: @"?g@F@simple@@$4PPPPPPPM@3AEXXZ"{{.*}}@"??_EG@simple@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"?f@E@simple@@UAEXXZ"{{.*}}@"??_EG@simple@@$4PPPPPPPE@7AEPAXI@Z"
};
G::G() {}
@@ -248,11 +248,11 @@
// CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
// `vtordispex{8,8,4294967292,8}'
- // MANGLING-DAG: @"\01?f@A@simple@@$R477PPPPPPPM@7AEXXZ"
+ // MANGLING-DAG: @"?f@A@simple@@$R477PPPPPPPM@7AEXXZ"
virtual ~A();
// vtordisp{4294967292,0}
- // MANGLING-DAG: @"\01??_EA@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EA@extended@@$4PPPPPPPM@A@AEPAXI@Z"
};
A a;
@@ -273,7 +273,7 @@
// CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
// vtordisp{4294967292,0}
- // MANGLING-DAG: @"\01??_EB@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EB@extended@@$4PPPPPPPM@A@AEPAXI@Z"
};
B b;
@@ -290,10 +290,10 @@
// CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
// `vtordispex{12,8,4294967292,8}'
- // MANGLING-DAG: @"\01?f@A@simple@@$R4M@7PPPPPPPM@7AEXXZ"
+ // MANGLING-DAG: @"?f@A@simple@@$R4M@7PPPPPPPM@7AEXXZ"
int x;
virtual ~C();
- // MANGLING-DAG: @"\01??_EC@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EC@extended@@$4PPPPPPPM@A@AEPAXI@Z"
};
C c;
@@ -316,10 +316,10 @@
// CHECK-NEXT: vboffset at 8 in the vbtable, 12 non-virtual]
// `vtordispex{8,8,4294967292,12}'
- // MANGLING-DAG: @"\01?f@D@extended@@$R477PPPPPPPM@M@AEXXZ"
+ // MANGLING-DAG: @"?f@D@extended@@$R477PPPPPPPM@M@AEXXZ"
virtual ~E();
- // MANGLING-DAG: @"\01??_EE@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EE@extended@@$4PPPPPPPM@A@AEPAXI@Z"
};
E e;
@@ -336,10 +336,10 @@
// CHECK-NEXT: vboffset at 12 in the vbtable, 12 non-virtual]
// `vtordispex{20,12,4294967292,12}'
- // MANGLING-DAG: @"\01?f@D@extended@@$R4BE@M@PPPPPPPM@M@AEXXZ"
+ // MANGLING-DAG: @"?f@D@extended@@$R4BE@M@PPPPPPPM@M@AEXXZ"
int x;
virtual ~F();
- // MANGLING-DAG: @"\01??_EF@extended@@$4PPPPPPPM@M@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EF@extended@@$4PPPPPPPM@M@AEPAXI@Z"
};
F f;
@@ -365,7 +365,7 @@
virtual ~G();
// vtordisp{4294967292,0}
- // MANGLING-DAG: @"\01??_EG@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"??_EG@extended@@$4PPPPPPPM@A@AEPAXI@Z"
};
G g;
@@ -385,8 +385,8 @@
// CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left,
// CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
- // MANGLING-DAG: @"\01?f@A@simple@@$R477PPPPPPPM@7AEXXZ"
- // MANGLING-DAG: @"\01??_EH@extended@@$4PPPPPPPM@BA@AEPAXI@Z"
+ // MANGLING-DAG: @"?f@A@simple@@$R477PPPPPPPM@7AEXXZ"
+ // MANGLING-DAG: @"??_EH@extended@@$4PPPPPPPM@BA@AEPAXI@Z"
};
H h;
@@ -407,7 +407,7 @@
// CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, vbptr at 20 to the left,
// CHECK-NEXT: vboffset at 8 in the vbtable, 16 non-virtual]
- // MANGLING-DAG: @"\01?f@B@simple@@$R4BE@7PPPPPPPE@BA@AEXXZ"
+ // MANGLING-DAG: @"?f@B@simple@@$R4BE@7PPPPPPPE@BA@AEXXZ"
int a;
virtual ~A();
};
@@ -442,7 +442,7 @@
// CHECK-NEXT: 0 | void pr19408::C::f()
// CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual]
- // MANGLING-DAG: @"\01?f@C@pr19408@@$4PPPPPPPM@3AEXXZ"
+ // MANGLING-DAG: @"?f@C@pr19408@@$4PPPPPPPM@3AEXXZ"
D();
int d;
};
@@ -463,10 +463,10 @@
virtual ~B();
protected:
virtual void prot();
- // MANGLING-DAG: @"\01?prot@B@access@@$2PPPPPPPM@A@AEXXZ"
+ // MANGLING-DAG: @"?prot@B@access@@$2PPPPPPPM@A@AEXXZ"
private:
virtual void priv();
- // MANGLING-DAG: @"\01?priv@B@access@@$0PPPPPPPM@A@AEXXZ"
+ // MANGLING-DAG: @"?priv@B@access@@$0PPPPPPPM@A@AEXXZ"
};
B b;
@@ -474,8 +474,8 @@
struct C : virtual B {
virtual ~C();
- // MANGLING-DAG: @"\01?prot@B@access@@$R277PPPPPPPM@7AEXXZ"
- // MANGLING-DAG: @"\01?priv@B@access@@$R077PPPPPPPM@7AEXXZ"
+ // MANGLING-DAG: @"?prot@B@access@@$R277PPPPPPPM@7AEXXZ"
+ // MANGLING-DAG: @"?priv@B@access@@$R077PPPPPPPM@7AEXXZ"
};
C c;
@@ -503,7 +503,7 @@
// CHECK-NEXT: 0 | void pr19505::B::f()
// CHECK-NEXT: 1 | void pr19505::A::z()
- // MANGLING-DAG: @"\01??_7X@pr19505@@6BB@1@@" = {{.*}}@"\01?f@B@pr19505@@UAEXXZ"
+ // MANGLING-DAG: @"??_7X@pr19505@@6BB@1@@" = {{.*}}@"?f@B@pr19505@@UAEXXZ"
} x;
void build_vftable(X *obj) { obj->g(); }
@@ -530,7 +530,7 @@
// CHECK-NEXT: 1 | void pr19506::X::g()
// CHECK-NEXT: [this adjustment: vtordisp at -4, -12 non-virtual]
- // MANGLING-DAG: @"\01??_7X@pr19506@@6BB@1@@" = {{.*}}@"\01?f@B@pr19506@@UAEXXZ"
+ // MANGLING-DAG: @"??_7X@pr19506@@6BB@1@@" = {{.*}}@"?f@B@pr19506@@UAEXXZ"
} x;
void build_vftable(X *obj) { obj->g(); }
@@ -562,7 +562,7 @@
// CHECK-NEXT: 1 | void pr19519::C::g()
// CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual]
- // MANGLING-DAG: @"\01??_7X@pr19519@@6B@" = {{.*}}@"\01?g@C@pr19519@@$4PPPPPPPM@3AEXXZ"
+ // MANGLING-DAG: @"??_7X@pr19519@@6B@" = {{.*}}@"?g@C@pr19519@@$4PPPPPPPM@3AEXXZ"
};
X::X() {}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
index 3633d7c..8e309ac 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
@@ -22,7 +22,7 @@
// CHECK-NEXT: vbtable index 1, vfptr at offset 0
// CHECK-NEXT: 0 | void C::f()
- // MANGLING-DAG: @"\01??_7C@@6B@"
+ // MANGLING-DAG: @"??_7C@@6B@"
virtual void f() {}
};
@@ -44,8 +44,8 @@
// CHECK-NEXT: via vbtable index 1, vfptr at offset 0
// CHECK-NEXT: 0 | void D::f()
- // MANGLING-DAG: @"\01??_7D@@6B0@@"
- // MANGLING-DAG: @"\01??_7D@@6BA@@@"
+ // MANGLING-DAG: @"??_7D@@6B0@@"
+ // MANGLING-DAG: @"??_7D@@6BA@@@"
virtual void f();
virtual void h();
@@ -60,7 +60,7 @@
// X and A get reordered in the layout since X doesn't have a vfptr while A has.
struct Y : X, A { };
-// MANGLING-DAG: @"\01??_7Y@Test1@@6B@"
+// MANGLING-DAG: @"??_7Y@Test1@@6B@"
struct Z : virtual Y {
Z();
@@ -70,7 +70,7 @@
// CHECK-NOT: VFTable indices for 'Test1::Z'
- // MANGLING-DAG: @"\01??_7Z@Test1@@6B@"
+ // MANGLING-DAG: @"??_7Z@Test1@@6B@"
};
Z::Z() {}
@@ -92,9 +92,9 @@
// CHECK-LABEL: VFTable indices for 'Test2::X' (1 entry).
// CHECK-NEXT: 0 | void Test2::X::h()
- // MANGLING-DAG: @"\01??_7X@Test2@@6B01@@"
- // MANGLING-DAG: @"\01??_7X@Test2@@6BA@@@"
- // MANGLING-DAG: @"\01??_7X@Test2@@6BB@@@"
+ // MANGLING-DAG: @"??_7X@Test2@@6B01@@"
+ // MANGLING-DAG: @"??_7X@Test2@@6BA@@@"
+ // MANGLING-DAG: @"??_7X@Test2@@6BB@@@"
virtual void h();
};
@@ -106,7 +106,7 @@
namespace Test3 {
struct X : virtual A {
- // MANGLING-DAG: @"\01??_7X@Test3@@6B@"
+ // MANGLING-DAG: @"??_7X@Test3@@6B@"
};
struct Y: virtual X {
@@ -117,7 +117,7 @@
// CHECK-NOT: VFTable indices for 'Test3::Y'
- // MANGLING-DAG: @"\01??_7Y@Test3@@6B@"
+ // MANGLING-DAG: @"??_7Y@Test3@@6B@"
};
Y::Y() {}
@@ -142,10 +142,10 @@
// CHECK-NOT: VFTable indices for 'Test4::X'
- // MANGLING-DAG: @"\01??_7X@Test4@@6B@"
+ // MANGLING-DAG: @"??_7X@Test4@@6B@"
// Also check the mangling of the thunk.
- // MANGLING-DAG: define linkonce_odr dso_local x86_thiscallcc void @"\01?f@C@@WPPPPPPPI@AEXXZ"
+ // MANGLING-DAG: define linkonce_odr dso_local x86_thiscallcc void @"?f@C@@WPPPPPPPI@AEXXZ"
};
X::X() {}
@@ -155,7 +155,7 @@
// New methods are added to the base's vftable.
struct X : A {
- // MANGLING-DAG: @"\01??_7X@Test5@@6B@"
+ // MANGLING-DAG: @"??_7X@Test5@@6B@"
virtual void g();
};
@@ -171,8 +171,8 @@
// CHECK-LABEL: VFTable indices for 'Test5::Y' (1 entry).
// CHECK-NEXT: 0 | void Test5::Y::h()
- // MANGLING-DAG: @"\01??_7Y@Test5@@6B01@@"
- // MANGLING-DAG: @"\01??_7Y@Test5@@6BX@1@@"
+ // MANGLING-DAG: @"??_7Y@Test5@@6B01@@"
+ // MANGLING-DAG: @"??_7Y@Test5@@6BX@1@@"
virtual void h();
};
@@ -191,7 +191,7 @@
// CHECK-NOT: VFTable indices for 'Test6::X'
- // MANGLING-DAG: @"\01??_7X@Test6@@6B@"
+ // MANGLING-DAG: @"??_7X@Test6@@6B@"
};
X::X() {}
@@ -200,7 +200,7 @@
namespace Test7 {
struct X : C {
- // MANGLING-DAG: @"\01??_7X@Test7@@6B@"
+ // MANGLING-DAG: @"??_7X@Test7@@6B@"
};
struct Y : virtual X {
@@ -215,7 +215,7 @@
// CHECK-NOT: VFTable indices for 'Test7::Y'
- // MANGLING-DAG: @"\01??_7Y@Test7@@6B@"
+ // MANGLING-DAG: @"??_7Y@Test7@@6B@"
};
Y::Y() {}
@@ -236,8 +236,8 @@
// CHECK-NEXT: via vbtable index 1, vfptr at offset 0
// CHECK-NEXT: 0 | void Test8::X::f()
- // MANGLING-DAG: @"\01??_7X@Test8@@6BA@@@"
- // MANGLING-DAG: @"\01??_7X@Test8@@6BD@@@"
+ // MANGLING-DAG: @"??_7X@Test8@@6BA@@@"
+ // MANGLING-DAG: @"??_7X@Test8@@6BD@@@"
virtual void f();
};
@@ -299,8 +299,8 @@
// CHECK-LABEL: VFTable indices for 'Test9::Y' (1 entry).
// CHECK-NEXT: 0 | void Test9::Y::h()
- // MANGLING-DAG: @"\01??_7Y@Test9@@6B01@@"
- // MANGLING-DAG: @"\01??_7Y@Test9@@6BX@1@@"
+ // MANGLING-DAG: @"??_7Y@Test9@@6B01@@"
+ // MANGLING-DAG: @"??_7Y@Test9@@6BX@1@@"
virtual void h();
};
@@ -322,10 +322,10 @@
// CHECK-NOT: VFTable indices for 'Test9::Z'
- // MANGLING-DAG: @"\01??_7Z@Test9@@6BX@1@@"
- // MANGLING-DAG: @"\01??_7Z@Test9@@6BY@1@@"
+ // MANGLING-DAG: @"??_7Z@Test9@@6BX@1@@"
+ // MANGLING-DAG: @"??_7Z@Test9@@6BY@1@@"
- // MANGLING-DAG: @"\01??_7Z@Test9@@6B@"
+ // MANGLING-DAG: @"??_7Z@Test9@@6B@"
};
Z::Z() {}
@@ -355,12 +355,12 @@
// CHECK-NOT: VFTable indices for 'Test9::W'
- // MANGLING-DAG: @"\01??_7W@Test9@@6BA@@@"
- // MANGLING-DAG: @"\01??_7W@Test9@@6BD@@@"
- // MANGLING-DAG: @"\01??_7W@Test9@@6BX@1@@"
+ // MANGLING-DAG: @"??_7W@Test9@@6BA@@@"
+ // MANGLING-DAG: @"??_7W@Test9@@6BD@@@"
+ // MANGLING-DAG: @"??_7W@Test9@@6BX@1@@"
- // MANGLING-DAG: @"\01??_7W@Test9@@6B@"
- // MANGLING-DAG: @"\01??_7W@Test9@@6BY@1@@"
+ // MANGLING-DAG: @"??_7W@Test9@@6B@"
+ // MANGLING-DAG: @"??_7W@Test9@@6BY@1@@"
};
W::W() {}
@@ -404,12 +404,12 @@
// CHECK-NEXT: via vbtable index 2, vfptr at offset 0
// CHECK-NEXT: 0 | void Test9::T::g()
- // MANGLING-DAG: @"\01??_7T@Test9@@6BA@@@"
- // MANGLING-DAG: @"\01??_7T@Test9@@6BD@@@"
- // MANGLING-DAG: @"\01??_7T@Test9@@6BX@1@@"
+ // MANGLING-DAG: @"??_7T@Test9@@6BA@@@"
+ // MANGLING-DAG: @"??_7T@Test9@@6BD@@@"
+ // MANGLING-DAG: @"??_7T@Test9@@6BX@1@@"
- // MANGLING-DAG: @"\01??_7T@Test9@@6B@"
- // MANGLING-DAG: @"\01??_7T@Test9@@6BY@1@@"
+ // MANGLING-DAG: @"??_7T@Test9@@6B@"
+ // MANGLING-DAG: @"??_7T@Test9@@6BY@1@@"
virtual void f();
virtual void g();
@@ -443,8 +443,8 @@
struct Y { virtual void g(); };
struct Z : virtual X, Y {
- // MANGLING-DAG: @"\01??_7Z@Test11@@6BY@1@@"
- // MANGLING-DAG: @"\01??_7Z@Test11@@6BX@1@@"
+ // MANGLING-DAG: @"??_7Z@Test11@@6BY@1@@"
+ // MANGLING-DAG: @"??_7Z@Test11@@6BX@1@@"
};
Z z;
@@ -468,7 +468,7 @@
// CHECK-NEXT: 1 | void A::z()
int z;
- // MANGLING-DAG: @"\01??_7Z@Test12@@6BA@@@" = {{.*}}@"\01?f@Y@Test12@@UAEXXZ"
+ // MANGLING-DAG: @"??_7Z@Test12@@6BA@@@" = {{.*}}@"?f@Y@Test12@@UAEXXZ"
};
struct W : Z {
@@ -478,7 +478,7 @@
W();
int w;
- // MANGLING-DAG: @"\01??_7W@Test12@@6BA@@@" = {{.*}}@"\01?f@Y@Test12@@UAEXXZ"
+ // MANGLING-DAG: @"??_7W@Test12@@6BA@@@" = {{.*}}@"?f@Y@Test12@@UAEXXZ"
};
W::W() {}
@@ -683,10 +683,10 @@
};
C c;
-// MANGLING-DAG: @"\01??_7A@pr17748@@6B@"
-// MANGLING-DAG: @"\01??_7B@pr17748@@6B@"
-// MANGLING-DAG: @"\01??_7C@pr17748@@6BA@1@@"
-// MANGLING-DAG: @"\01??_7C@pr17748@@6BB@1@@"
+// MANGLING-DAG: @"??_7A@pr17748@@6B@"
+// MANGLING-DAG: @"??_7B@pr17748@@6B@"
+// MANGLING-DAG: @"??_7C@pr17748@@6BA@1@@"
+// MANGLING-DAG: @"??_7C@pr17748@@6BB@1@@"
}
namespace pr19066 {
@@ -721,9 +721,9 @@
// Each MDC only has one vftable.
-// MANGLING-DAG: @"\01??_7D@pr19240@@6B@"
-// MANGLING-DAG: @"\01??_7A@pr19240@@6B@"
-// MANGLING-DAG: @"\01??_7B@pr19240@@6B@"
+// MANGLING-DAG: @"??_7D@pr19240@@6B@"
+// MANGLING-DAG: @"??_7A@pr19240@@6B@"
+// MANGLING-DAG: @"??_7B@pr19240@@6B@"
}
@@ -746,7 +746,7 @@
Z();
int z;
- // MANGLING-DAG: @"\01??_7Z@pr19408@@6B@" = {{.*}}@"\01?f@Y@pr19408@@W3AEXXZ"
+ // MANGLING-DAG: @"??_7Z@pr19408@@6B@" = {{.*}}@"?f@Y@pr19408@@W3AEXXZ"
};
Z::Z() {}
@@ -759,7 +759,7 @@
W();
int w;
- // MANGLING-DAG: @"\01??_7W@pr19408@@6BY@1@@" = {{.*}}@"\01?f@Y@pr19408@@W3AEXXZ"
+ // MANGLING-DAG: @"??_7W@pr19408@@6BY@1@@" = {{.*}}@"?f@Y@pr19408@@W3AEXXZ"
};
W::W() {}
@@ -771,7 +771,7 @@
};
struct __declspec(dllexport) B : virtual A {
virtual void f() = 0;
- // MANGLING-DAG: @"\01??_7B@Test13@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] }
+ // MANGLING-DAG: @"??_7B@Test13@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] }
};
}
@@ -788,8 +788,8 @@
// CHECK-LABEL: VFTable for 'pr21031_1::B' in 'pr21031_1::C' (1 entry)
// CHECK-NEXT: 0 | void pr21031_1::B::g()
-// MANGLING-DAG: @"\01??_7C@pr21031_1@@6BB@1@@" = {{.*}} constant { [1 x i8*] }
-// MANGLING-DAG: @"\01??_7C@pr21031_1@@6B@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7C@pr21031_1@@6BB@1@@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7C@pr21031_1@@6B@" = {{.*}} constant { [1 x i8*] }
}
namespace pr21031_2 {
@@ -804,8 +804,8 @@
// CHECK-LABEL: VFTable for 'pr21031_2::A' in 'pr21031_2::B' in 'pr21031_2::C' (1 entry)
// CHECK-NEXT: 0 | void pr21031_2::A::f()
-// MANGLING-DAG: @"\01??_7C@pr21031_2@@6BA@1@@" = {{.*}} constant { [1 x i8*] }
-// MANGLING-DAG: @"\01??_7C@pr21031_2@@6BB@1@@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7C@pr21031_2@@6BA@1@@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7C@pr21031_2@@6BB@1@@" = {{.*}} constant { [1 x i8*] }
}
namespace pr21062_1 {
@@ -818,7 +818,7 @@
// CHECK-LABEL: VFTable for 'pr21062_1::A' in 'pr21062_1::D' (1 entry)
// CHECK-NEXT: 0 | void pr21062_1::A::f()
-// MANGLING-DAG: @"\01??_7D@pr21062_1@@6B@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7D@pr21062_1@@6B@" = {{.*}} constant { [1 x i8*] }
}
namespace pr21062_2 {
@@ -831,7 +831,7 @@
// CHECK-LABEL: VFTable for 'pr21062_2::A' in 'pr21062_2::D' (1 entry)
// CHECK-NEXT: 0 | void pr21062_2::A::f()
-// MANGLING-DAG: @"\01??_7D@pr21062_2@@6B@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7D@pr21062_2@@6B@" = {{.*}} constant { [1 x i8*] }
}
namespace pr21064 {
@@ -843,5 +843,5 @@
// CHECK-LABEL: VFTable for 'pr21064::B' in 'pr21064::C' in 'pr21064::D' (1 entry)
// CHECK-NEXT: 0 | void pr21064::B::f()
-// MANGLING-DAG: @"\01??_7D@pr21064@@6B@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"??_7D@pr21064@@6B@" = {{.*}} constant { [1 x i8*] }
}
diff --git a/test/CodeGenCXX/microsoft-compatibility.cpp b/test/CodeGenCXX/microsoft-compatibility.cpp
index 0fd2e4d..64d10a5 100644
--- a/test/CodeGenCXX/microsoft-compatibility.cpp
+++ b/test/CodeGenCXX/microsoft-compatibility.cpp
@@ -8,7 +8,7 @@
template <>
const int S<char>::x[] = {1};
-// CHECK-LABEL: @"\01?x@?$S@D@@2QBHB" = weak_odr dso_local constant [1 x i32] [i32 1], comdat
+// CHECK-LABEL: @"?x@?$S@D@@2QBHB" = weak_odr dso_local constant [1 x i32] [i32 1], comdat
template<class T>
void destroy(T *p) {
@@ -21,10 +21,10 @@
}
// CHECK-LABEL: define dso_local void @f()
-// CHECK: call void @"\01??$destroy@X@@YAXPAX@Z"
+// CHECK: call void @"??$destroy@X@@YAXPAX@Z"
// CHECK: ret void
-// CHECK-LABEL: define linkonce_odr dso_local void @"\01??$destroy@X@@YAXPAX@Z"(i8* %p)
+// CHECK-LABEL: define linkonce_odr dso_local void @"??$destroy@X@@YAXPAX@Z"(i8* %p)
// The pseudo-dtor expr should not generate calls to anything.
// CHECK-NOT: call
// CHECK-NOT: invoke
diff --git a/test/CodeGenCXX/microsoft-new.cpp b/test/CodeGenCXX/microsoft-new.cpp
index 7857e47..01b0960 100644
--- a/test/CodeGenCXX/microsoft-new.cpp
+++ b/test/CodeGenCXX/microsoft-new.cpp
@@ -13,7 +13,7 @@
// MSVC will fall back on the non-array operator new.
void *a;
int *p = new(arbitrary) int[4];
- // CHECK: call i8* @"\01??2@YAPAXIUarbitrary_t@@@Z"(i32 16, %struct.arbitrary_t*
+ // CHECK: call i8* @"??2@YAPAXIUarbitrary_t@@@Z"(i32 16, %struct.arbitrary_t*
}
struct S {
@@ -22,9 +22,9 @@
void g() {
S *s = new(arbitrary) S[2];
- // CHECK: call i8* @"\01??_US@PR13164@@SAPAXIUarbitrary_t@@@Z"(i32 2, %struct.arbitrary_t*
+ // CHECK: call i8* @"??_US@PR13164@@SAPAXIUarbitrary_t@@@Z"(i32 2, %struct.arbitrary_t*
S *s1 = new(arbitrary) S;
- // CHECK: call i8* @"\01??2@YAPAXIUarbitrary_t@@@Z"(i32 1, %struct.arbitrary_t*
+ // CHECK: call i8* @"??2@YAPAXIUarbitrary_t@@@Z"(i32 1, %struct.arbitrary_t*
}
struct T {
@@ -34,6 +34,6 @@
void h() {
// This should still call the global operator new[].
T *t = new(arbitrary2) T[2];
- // CHECK: call i8* @"\01??_U@YAPAXIUarbitrary2_t@@@Z"(i32 2, %struct.arbitrary2_t*
+ // CHECK: call i8* @"??_U@YAPAXIUarbitrary2_t@@@Z"(i32 2, %struct.arbitrary2_t*
}
}
diff --git a/test/CodeGenCXX/microsoft-no-rtti-data.cpp b/test/CodeGenCXX/microsoft-no-rtti-data.cpp
index 0525590..3d218ed 100644
--- a/test/CodeGenCXX/microsoft-no-rtti-data.cpp
+++ b/test/CodeGenCXX/microsoft-no-rtti-data.cpp
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 %s -fno-rtti-data -triple=i386-pc-win32 -o - -emit-llvm | FileCheck %s
// vftable shouldn't have RTTI data in it.
-// CHECK-NOT: @"\01??_R4S@@6B@"
-// CHECK: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] }, comdat
+// CHECK-NOT: @"??_R4S@@6B@"
+// CHECK: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GS@@UAEPAXI@Z" to i8*)] }, comdat
struct type_info;
namespace std { using ::type_info; }
@@ -19,4 +19,4 @@
const std::type_info &ti = typeid(*getS());
const U &u = dynamic_cast<U &>(*getS());
-// CHECK: call i8* @__RTDynamicCast(i8* %{{.+}}, i32 0, i8* bitcast ({{.*}} @"\01??_R0?AUS@@@8" to i8*), i8* bitcast ({{.*}} @"\01??_R0?AUU@@@8" to i8*), i32 1)
+// CHECK: call i8* @__RTDynamicCast(i8* %{{.+}}, i32 0, i8* bitcast ({{.*}} @"??_R0?AUS@@@8" to i8*), i8* bitcast ({{.*}} @"??_R0?AUU@@@8" to i8*), i32 1)
diff --git a/test/CodeGenCXX/microsoft-templ-uuidof.cpp b/test/CodeGenCXX/microsoft-templ-uuidof.cpp
index 74d6069..7d40a15 100644
--- a/test/CodeGenCXX/microsoft-templ-uuidof.cpp
+++ b/test/CodeGenCXX/microsoft-templ-uuidof.cpp
@@ -15,13 +15,15 @@
struct __declspec(uuid("{CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC}")) C {};
+// CHECK-DAG: @_GUID_aaaaaaaa_aaaa_aaaa_aaaa_aaaaaaaaaaaa = linkonce_odr dso_local
+
const _GUID &xa = __uuidof(X<A>);
-// CHECK-DAG: @"\01?xa@@3ABU_GUID@@B" = {{.*}} @_GUID_aaaaaaaa_aaaa_aaaa_aaaa_aaaaaaaaaaaa
+// CHECK-DAG: @"?xa@@3ABU_GUID@@B" = {{.*}} @_GUID_aaaaaaaa_aaaa_aaaa_aaaa_aaaaaaaaaaaa
const _GUID &xb = __uuidof(X<B>);
-// CHECK-DAG: @"\01?xb@@3ABU_GUID@@B" = {{.*}} @_GUID_bbbbbbbb_bbbb_bbbb_bbbb_bbbbbbbbbbbb
+// CHECK-DAG: @"?xb@@3ABU_GUID@@B" = {{.*}} @_GUID_bbbbbbbb_bbbb_bbbb_bbbb_bbbbbbbbbbbb
const _GUID &xc = __uuidof(X<C>);
-// CHECK-DAG: @"\01?xc@@3ABU_GUID@@B" = {{.*}} @_GUID_cccccccc_cccc_cccc_cccc_cccccccccccc
+// CHECK-DAG: @"?xc@@3ABU_GUID@@B" = {{.*}} @_GUID_cccccccc_cccc_cccc_cccc_cccccccccccc
template <>
struct __declspec(uuid("{DDDDDDDD-DDDD-DDDD-DDDD-DDDDDDDDDDDD}")) X<C> {};
@@ -31,7 +33,7 @@
};
const _GUID &xd = __uuidof(X<C>);
-// CHECK-DAG: @"\01?xd@@3ABU_GUID@@B" = {{.*}} @_GUID_dddddddd_dddd_dddd_dddd_dddddddddddd
+// CHECK-DAG: @"?xd@@3ABU_GUID@@B" = {{.*}} @_GUID_dddddddd_dddd_dddd_dddd_dddddddddddd
const _GUID &yd = __uuidof(Y<X<C> >);
-// CHECK-DAG: @"\01?yd@@3ABU_GUID@@B" = {{.*}} @_GUID_dddddddd_dddd_dddd_dddd_dddddddddddd
+// CHECK-DAG: @"?yd@@3ABU_GUID@@B" = {{.*}} @_GUID_dddddddd_dddd_dddd_dddd_dddddddddddd
diff --git a/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp b/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp
index d043fc1..2537361 100644
--- a/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp
+++ b/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp
@@ -17,6 +17,6 @@
};
};
-// CHECK: @"\01?x@S@@2FB" = weak_odr dso_local dllexport constant i16 42, comdat, align 2
-// CHECK: @"\01?y@S@@2W4Enum@@B" = weak_odr dso_local dllexport constant i32 2, comdat, align 4
+// CHECK: @"?x@S@@2FB" = weak_odr dso_local dllexport constant i16 42, comdat, align 2
+// CHECK: @"?y@S@@2W4Enum@@B" = weak_odr dso_local dllexport constant i32 2, comdat, align 4
// CHECK-NOT: NonExported
diff --git a/test/CodeGenCXX/ms-integer-static-data-members.cpp b/test/CodeGenCXX/ms-integer-static-data-members.cpp
index 1ac5648..9841435 100644
--- a/test/CodeGenCXX/ms-integer-static-data-members.cpp
+++ b/test/CodeGenCXX/ms-integer-static-data-members.cpp
@@ -33,20 +33,20 @@
// No initialization.
-// CHECK-DAG: @"\01?NoInit_Ref@S@@2HB" = external dso_local constant i32
+// CHECK-DAG: @"?NoInit_Ref@S@@2HB" = external dso_local constant i32
// Inline initialization, no real definiton, not referenced.
-// CHECK-NOT: @"\01?Inline_NotDef_NotRef@S@@2HB" = {{.*}} constant i32 5
+// CHECK-NOT: @"?Inline_NotDef_NotRef@S@@2HB" = {{.*}} constant i32 5
// Inline initialization, no real definiton, referenced.
-// CHECK-DAG: @"\01?Inline_NotDef_Ref@S@@2HB" = linkonce_odr dso_local constant i32 5, comdat, align 4
+// CHECK-DAG: @"?Inline_NotDef_Ref@S@@2HB" = linkonce_odr dso_local constant i32 5, comdat, align 4
// Inline initialization, real definiton, not referenced.
-// CHECK-NOT: @"\01?Inline_Def_NotRef@S@@2HB" = dso_local constant i32 5, align 4
+// CHECK-NOT: @"?Inline_Def_NotRef@S@@2HB" = dso_local constant i32 5, align 4
// Inline initialization, real definiton, referenced.
-// CHECK-DAG: @"\01?Inline_Def_Ref@S@@2HB" = linkonce_odr dso_local constant i32 5, comdat, align 4
+// CHECK-DAG: @"?Inline_Def_Ref@S@@2HB" = linkonce_odr dso_local constant i32 5, comdat, align 4
// Out-of-line initialization.
-// CHECK-DAG: @"\01?OutOfLine_Def_NotRef@S@@2HB" = dso_local constant i32 5, align 4
-// CHECK-DAG: @"\01?OutOfLine_Def_Ref@S@@2HB" = dso_local constant i32 5, align 4
+// CHECK-DAG: @"?OutOfLine_Def_NotRef@S@@2HB" = dso_local constant i32 5, align 4
+// CHECK-DAG: @"?OutOfLine_Def_Ref@S@@2HB" = dso_local constant i32 5, align 4
diff --git a/test/CodeGenCXX/ms-novtable.cpp b/test/CodeGenCXX/ms-novtable.cpp
index 8d54878..db0cf68 100644
--- a/test/CodeGenCXX/ms-novtable.cpp
+++ b/test/CodeGenCXX/ms-novtable.cpp
@@ -1,14 +1,14 @@
// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -fms-extensions -fms-compatibility -fno-rtti -o - | FileCheck %s
-// CHECK-NOT: @"\01??_7C@@6B@"
+// CHECK-NOT: @"??_7C@@6B@"
-// CHECK-DAG: @"\01??_7A2@@6B@"
+// CHECK-DAG: @"??_7A2@@6B@"
-// CHECK-DAG: @"\01??_7B2@@6B@"
+// CHECK-DAG: @"??_7B2@@6B@"
-// CHECK-NOT: @"\01??_7B1@@6B@"
+// CHECK-NOT: @"??_7B1@@6B@"
-// CHECK-NOT: @"\01??_7A1@@6B@"
+// CHECK-NOT: @"??_7A1@@6B@"
struct __declspec(novtable) A1 {
virtual void a();
diff --git a/test/CodeGenCXX/ms-property.cpp b/test/CodeGenCXX/ms-property.cpp
index 8c1c7a6..4f01528 100644
--- a/test/CodeGenCXX/ms-property.cpp
+++ b/test/CodeGenCXX/ms-property.cpp
@@ -53,61 +53,61 @@
Test1 t(argc);
S *p1 = 0;
St<float> *p2 = 0;
- // CHECK: call i32 @"\01?GetX@S@@QEAAHHH@Z"(%class.S* %{{.+}}, i32 223, i32 11)
+ // CHECK: call i32 @"?GetX@S@@QEAAHHH@Z"(%class.S* %{{.+}}, i32 223, i32 11)
int j = p1->x[223][11];
// CHECK: [[J:%.+]] = load i32, i32* %
- // CHECK-NEXT: call void @"\01?PutX@S@@QEAAXHHH@Z"(%class.S* %{{.+}}, i32 23, i32 1, i32 [[J]])
+ // CHECK-NEXT: call void @"?PutX@S@@QEAAXHHH@Z"(%class.S* %{{.+}}, i32 23, i32 1, i32 [[J]])
p1->x[23][1] = j;
- // CHECK: call float @"\01?GetX@?$St@M@@QEAAMMM@Z"(%class.St* %{{.+}}, float 2.230000e+02, float 1.100000e+01)
+ // CHECK: call float @"?GetX@?$St@M@@QEAAMMM@Z"(%class.St* %{{.+}}, float 2.230000e+02, float 1.100000e+01)
float j1 = p2->x[223][11];
// CHECK: [[J1:%.+]] = load float, float* %
- // CHECK-NEXT: [[CALL:%.+]] = call float @"\01?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* %{{.+}}, float 2.300000e+01, float 1.000000e+00, float [[J1]])
+ // CHECK-NEXT: [[CALL:%.+]] = call float @"?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* %{{.+}}, float 2.300000e+01, float 1.000000e+00, float [[J1]])
// CHECK-NEXT: [[CONV:%.+]] = fptosi float [[CALL]] to i32
// CHECK-NEXT: store i32 [[CONV]], i32*
argc = p2->x[23][1] = j1;
- // CHECK: [[IDX:%.+]] = call i32 @"\01?idx@@YAHXZ"()
+ // CHECK: [[IDX:%.+]] = call i32 @"?idx@@YAHXZ"()
// CHECK-NEXT: [[CONV:%.+]] = sitofp i32 [[IDX]] to float
- // CHECK-NEXT: [[GET:%.+]] = call float @"\01?GetX@?$St@M@@QEAAMMM@Z"(%class.St* %{{.+}}, float [[CONV]], float 1.000000e+00)
+ // CHECK-NEXT: [[GET:%.+]] = call float @"?GetX@?$St@M@@QEAAMMM@Z"(%class.St* %{{.+}}, float [[CONV]], float 1.000000e+00)
// CHECK-NEXT: [[INC:%.+]] = fadd float [[GET]], 1.000000e+00
// CHECK-NEXT: [[CONV:%.+]] = sitofp i32 [[IDX]] to float
- // CHECK-NEXT: call float @"\01?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* %{{.+}}, float [[CONV]], float 1.000000e+00, float [[INC]])
+ // CHECK-NEXT: call float @"?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* %{{.+}}, float [[CONV]], float 1.000000e+00, float [[INC]])
++p2->x[idx()][1];
- // CHECK: call void @"\01??$foo@H@@YAXHH@Z"(i32 %{{.+}}, i32 %{{.+}})
+ // CHECK: call void @"??$foo@H@@YAXHH@Z"(i32 %{{.+}}, i32 %{{.+}})
foo(argc, (int)argv[0][0]);
// CHECK: [[P2:%.+]] = load %class.St*, %class.St** %
- // CHECK: [[T_X:%.+]] = call i32 @"\01?get_x@Test1@@QEBAHXZ"(%class.Test1* %{{.+}})
// CHECK: [[P1:%.+]] = load %class.S*, %class.S** %
- // CHECK: [[P1_X_22_33:%.+]] = call i32 @"\01?GetX@S@@QEAAHHH@Z"(%class.S* [[P1]], i32 22, i32 33)
+ // CHECK: [[P1_X_22_33:%.+]] = call i32 @"?GetX@S@@QEAAHHH@Z"(%class.S* [[P1]], i32 22, i32 33)
// CHECK: [[CAST:%.+]] = sitofp i32 [[P1_X_22_33]] to double
// CHECK: [[ARGC:%.+]] = load i32, i32* %
+ // CHECK: [[T_X:%.+]] = call i32 @"?get_x@Test1@@QEBAHXZ"(%class.Test1* %{{.+}})
// CHECK: [[CAST2:%.+]] = trunc i32 [[T_X]] to i8
- // CHECK: call void @"\01?PutY@?$St@M@@QEAAXDHN@Z"(%class.St* [[P2]], i8 [[CAST2]], i32 [[ARGC]], double [[CAST]])
+ // CHECK: call void @"?PutY@?$St@M@@QEAAXDHN@Z"(%class.St* [[P2]], i8 [[CAST2]], i32 [[ARGC]], double [[CAST]])
p2->y[t.X][argc] = p1->x[22][33];
// CHECK: [[P2_1:%.+]] = load %class.St*, %class.St**
// CHECK: [[P2_2:%.+]] = load %class.St*, %class.St**
// CHECK: [[P1:%.+]] = load %class.S*, %class.S**
// CHECK: [[ARGC:%.+]] = load i32, i32* %
- // CHECK: [[P1_X_ARGC_0:%.+]] = call i32 @"\01?GetX@S@@QEAAHHH@Z"(%class.S* [[P1]], i32 [[ARGC]], i32 0)
+ // CHECK: [[P1_X_ARGC_0:%.+]] = call i32 @"?GetX@S@@QEAAHHH@Z"(%class.S* [[P1]], i32 [[ARGC]], i32 0)
// CHECK: [[CAST:%.+]] = trunc i32 [[P1_X_ARGC_0]] to i8
- // CHECK: [[P2_Y_p1_X_ARGC_0_T:%.+]] = call i8 @"\01?GetY@?$St@M@@QEAADDVTest1@@@Z"(%class.St* [[P2_2]], i8 [[CAST]], %class.Test1* %{{.+}})
+ // CHECK: [[P2_Y_p1_X_ARGC_0_T:%.+]] = call i8 @"?GetY@?$St@M@@QEAADDVTest1@@@Z"(%class.St* [[P2_2]], i8 [[CAST]], %class.Test1* %{{.+}})
// CHECK: [[CAST:%.+]] = sitofp i8 [[P2_Y_p1_X_ARGC_0_T]] to float
// CHECK: [[J:%.+]] = load i32, i32* %
// CHECK: [[CAST1:%.+]] = sitofp i32 [[J]] to float
// CHECK: [[J:%.+]] = load i32, i32* %
// CHECK: [[CAST2:%.+]] = sitofp i32 [[J]] to float
- // CHECK: call float @"\01?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* [[P2_1]], float [[CAST2]], float [[CAST1]], float [[CAST]])
+ // CHECK: call float @"?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* [[P2_1]], float [[CAST2]], float [[CAST1]], float [[CAST]])
p2->x[j][j] = p2->y[p1->x[argc][0]][t];
- // CHECK: [[CALL:%.+]] = call %class.Test1* @"\01?GetTest1@Test1@@SAPEAV1@XZ"()
- // CHECK-NEXT: call i32 @"\01?get_x@Test1@@QEBAHXZ"(%class.Test1* [[CALL]])
+ // CHECK: [[CALL:%.+]] = call %class.Test1* @"?GetTest1@Test1@@SAPEAV1@XZ"()
+ // CHECK-NEXT: call i32 @"?get_x@Test1@@QEBAHXZ"(%class.Test1* [[CALL]])
return Test1::GetTest1()->X;
}
-// CHECK: define linkonce_odr dso_local void @"\01??$foo@H@@YAXHH@Z"(i32 %{{.+}}, i32 %{{.+}})
-// CHECK: call i32 @"\01?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR:%.+]], i32 %{{.+}} i32 %{{.+}})
-// CHECK: call i32 @"\01?PutX@?$St@H@@QEAAHHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}}, i32 %{{.+}}, i32 %{{.+}})
-// CHECK: call i32 @"\01?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}} i32 %{{.+}})
-// CHECK: call void @"\01?PutY@?$St@H@@QEAAXDHN@Z"(%class.St{{.+}}* [[BAR]], i8 %{{.+}}, i32 %{{.+}}, double %{{.+}}
-// CHECK: call i32 @"\01?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}} i32 %{{.+}})
-// CHECK: call i8 @"\01?GetY@?$St@H@@QEAADDVTest1@@@Z"(%class.St{{.+}}* [[BAR]], i8 %{{.+}}, %class.Test1* %{{.+}})
-// CHECK: call i32 @"\01?PutX@?$St@H@@QEAAHHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}}, i32 %{{.+}}, i32 %{{.+}})
+// CHECK: define linkonce_odr dso_local void @"??$foo@H@@YAXHH@Z"(i32 %{{.+}}, i32 %{{.+}})
+// CHECK: call i32 @"?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR:%.+]], i32 %{{.+}} i32 %{{.+}})
+// CHECK: call i32 @"?PutX@?$St@H@@QEAAHHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}}, i32 %{{.+}}, i32 %{{.+}})
+// CHECK: call i32 @"?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}} i32 %{{.+}})
+// CHECK: call void @"?PutY@?$St@H@@QEAAXDHN@Z"(%class.St{{.+}}* [[BAR]], i8 %{{.+}}, i32 %{{.+}}, double %{{.+}}
+// CHECK: call i32 @"?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}} i32 %{{.+}})
+// CHECK: call i8 @"?GetY@?$St@H@@QEAADDVTest1@@@Z"(%class.St{{.+}}* [[BAR]], i8 %{{.+}}, %class.Test1* %{{.+}})
+// CHECK: call i32 @"?PutX@?$St@H@@QEAAHHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}}, i32 %{{.+}}, i32 %{{.+}})
#endif //HEADER
diff --git a/test/CodeGenCXX/ms-thread_local.cpp b/test/CodeGenCXX/ms-thread_local.cpp
index 793e528..76eba52 100644
--- a/test/CodeGenCXX/ms-thread_local.cpp
+++ b/test/CodeGenCXX/ms-thread_local.cpp
@@ -5,18 +5,18 @@
~A();
};
-// CHECK-DAG: $"\01??$a@X@@3UA@@A" = comdat any
-// CHECK-DAG: @"\01??$a@X@@3UA@@A" = linkonce_odr dso_local thread_local global %struct.A zeroinitializer, comdat, align 1
-// CHECK-DAG: @"\01??__E?$a@X@@YAXXZ$initializer$" = internal constant void ()* @"\01??__E?$a@X@@YAXXZ", section ".CRT$XDU", comdat($"\01??$a@X@@3UA@@A")
+// CHECK-DAG: $"??$a@X@@3UA@@A" = comdat any
+// CHECK-DAG: @"??$a@X@@3UA@@A" = linkonce_odr dso_local thread_local global %struct.A zeroinitializer, comdat, align 1
+// CHECK-DAG: @"??__E?$a@X@@YAXXZ$initializer$" = internal constant void ()* @"??__E?$a@X@@YAXXZ", section ".CRT$XDU", comdat($"??$a@X@@3UA@@A")
template <typename T>
thread_local A a = A();
-// CHECK-DAG: @"\01?b@@3UA@@A" = dso_local thread_local global %struct.A zeroinitializer, align 1
+// CHECK-DAG: @"?b@@3UA@@A" = dso_local thread_local global %struct.A zeroinitializer, align 1
// CHECK-DAG: @"__tls_init$initializer$" = internal constant void ()* @__tls_init, section ".CRT$XDU"
thread_local A b;
// CHECK-LABEL: define internal void @__tls_init()
-// CHECK: call void @"\01??__Eb@@YAXXZ"
+// CHECK: call void @"??__Eb@@YAXXZ"
thread_local A &c = b;
thread_local A &d = c;
diff --git a/test/CodeGenCXX/ms_wide_predefined_expr.cpp b/test/CodeGenCXX/ms_wide_predefined_expr.cpp
index 03c78d9..bdfd1cd 100644
--- a/test/CodeGenCXX/ms_wide_predefined_expr.cpp
+++ b/test/CodeGenCXX/ms_wide_predefined_expr.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -fms-extensions -triple i686-pc-win32 -emit-llvm -o - | FileCheck %s
-// CHECK: @"\01??_C@_19DPFBEKIN@?$AAf?$AAu?$AAn?$AAc?$AA?$AA@" = linkonce_odr unnamed_addr constant [5 x i16] [i16 102, i16 117, i16 110, i16 99, i16 0], comdat, align 2
+// CHECK: @"??_C@_19DPFBEKIN@?$AAf?$AAu?$AAn?$AAc?$AA?$AA@" = linkonce_odr dso_local unnamed_addr constant [5 x i16] [i16 102, i16 117, i16 110, i16 99, i16 0], comdat, align 2
void wprint(const wchar_t*);
diff --git a/test/CodeGenCXX/msabi-blocks.cpp b/test/CodeGenCXX/msabi-blocks.cpp
index bee59d9..02d0958 100644
--- a/test/CodeGenCXX/msabi-blocks.cpp
+++ b/test/CodeGenCXX/msabi-blocks.cpp
@@ -7,25 +7,25 @@
static int i = 0;
};
-// CHECK-X86-DAG: @"\01?i@?1??_block_invoke@@YAXPAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?1??_block_invoke@@YAXPEAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?1??_block_invoke@@YAXPAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?1??_block_invoke@@YAXPEAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
void f(void) {
static int i = 0;
^{ static int i = e(); }();
-// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?1??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?1??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
^{ static int i = e(); }();
-// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_2@@YAXPAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_2@@YAXPEAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?1??_block_invoke_2@@YAXPAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?1??_block_invoke_2@@YAXPEAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
^{ ^{ static int i = e(); }(); }();
-// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_3@@YAXPAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_3@@YAXPEAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPEAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?1??_block_invoke_3@@YAXPAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?1??_block_invoke_3@@YAXPEAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPEAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
}
@@ -36,47 +36,47 @@
template void g<char>(void);
-// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
template void g<int>(void);
-// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
inline void h(void) {
^{ static int i = e(); }();
}
-// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
struct s {
int i = ^{ static int i = e(); return ++i; }();
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@0s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@0s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1@0s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1@0s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
int j = ^{ static int i = e(); return ++i; }();
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@j@s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@j@s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1@j@s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1@j@s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
void m(int i = ^{ static int i = e(); return ++i; }(),
int j = ^{ static int i = e(); return ++i; }()) {}
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
void n(int = ^{ static int i = e(); return ++i; }(),
int = ^{ static int i = e(); return ++i; }()) {}
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
};
@@ -84,8 +84,8 @@
struct u {
int i = ^{ static int i = e(); return ++i; }();
-// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@0u@t@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
-// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@0u@t@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"?i@?0??_block_invoke_1@0u@t@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"?i@?0??_block_invoke_1@0u@t@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
};
};
diff --git a/test/CodeGenCXX/msabi-swiftcall-cc.cpp b/test/CodeGenCXX/msabi-swiftcall-cc.cpp
index 5a5453a..e74c6b0 100644
--- a/test/CodeGenCXX/msabi-swiftcall-cc.cpp
+++ b/test/CodeGenCXX/msabi-swiftcall-cc.cpp
@@ -1,28 +1,28 @@
// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fdeclspec -emit-llvm %s -o - | FileCheck %s
void __attribute__((__swiftcall__)) f() {}
-// CHECK-DAG: @"\01?f@@YSXXZ"
+// CHECK-DAG: @"?f@@YSXXZ"
void (__attribute__((__swiftcall__)) *p)();
-// CHECK-DAG: @"\01?p@@3P6SXXZA"
+// CHECK-DAG: @"?p@@3P6SXXZA"
namespace {
void __attribute__((__swiftcall__)) __attribute__((__used__)) f() { }
-// CHECK-DAG: "\01?f@?A@@YSXXZ"
+// CHECK-DAG: "?f@?A@@YSXXZ"
}
namespace n {
void __attribute__((__swiftcall__)) f() {}
-// CHECK-DAG: "\01?f@n@@YSXXZ"
+// CHECK-DAG: "?f@n@@YSXXZ"
}
struct __declspec(dllexport) S {
S(const S &) = delete;
S & operator=(const S &) = delete;
void __attribute__((__swiftcall__)) m() { }
- // CHECK-DAG: "\01?m@S@@QASXXZ"
+ // CHECK-DAG: "?m@S@@QASXXZ"
};
void f(void (__attribute__((__swiftcall__))())) {}
-// CHECK-DAG: "\01?f@@YAXP6SXXZ@Z"
+// CHECK-DAG: "?f@@YAXP6SXXZ@Z"
diff --git a/test/CodeGenCXX/optnone-pragma-optimize-off.cpp b/test/CodeGenCXX/optnone-pragma-optimize-off.cpp
new file mode 100644
index 0000000..d750c4c
--- /dev/null
+++ b/test/CodeGenCXX/optnone-pragma-optimize-off.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -O1 -disable-llvm-passes -emit-llvm -o - | FileCheck %s
+
+// Test the attributes for the lambda function contains 'optnone' as result of
+// the _Pragma("clang optimize off").
+
+_Pragma("clang optimize off")
+
+void foo(int p) {
+ auto lambda = [&p]() { ++p; };
+ lambda();
+ // CHECK: define {{.*}} @"_ZZ3fooiENK3$_0clEv"({{.*}}) #[[LAMBDA_ATR:[0-9]+]]
+}
+
+_Pragma("clang optimize on")
+
+// CHECK: attributes #[[LAMBDA_ATR]] = { {{.*}} optnone {{.*}} }
\ No newline at end of file
diff --git a/test/CodeGenCXX/personality.cpp b/test/CodeGenCXX/personality.cpp
new file mode 100644
index 0000000..dc62229
--- /dev/null
+++ b/test/CodeGenCXX/personality.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SJLJ
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN
+// %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH
+// %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fseh-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH-X86
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fseh-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH-X64
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SJLJ
+
+extern void g();
+
+// CHECK-GNU: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-GNU-DWARF: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-GNU-SEH: personality i8* bitcast (i32 (...)* @__gxx_personality_seh0 to i8*)
+// CHECK-GNU-SJLJ: personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*)
+
+// CHECK-WIN: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+// CHECK-WIN-DWARF: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-WIN-SEH: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+// CHECK-WIN-SJLJ: personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*)
+
+void f() {
+ try {
+ g();
+ } catch (...) {
+ }
+}
+
+#if defined(__SEH_EXCEPTIONS__)
+// CHECK-WIN-SEH-X86: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
+// CHECK-WIN-SEH-X64: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+
+void h(void) {
+ __try {
+ g();
+ } __finally {
+ }
+}
+#endif
+
diff --git a/test/CodeGenCXX/pr20719.cpp b/test/CodeGenCXX/pr20719.cpp
index 1c3b21b..79fdd74 100644
--- a/test/CodeGenCXX/pr20719.cpp
+++ b/test/CodeGenCXX/pr20719.cpp
@@ -2,8 +2,8 @@
// Make sure that we emit H's constructor twice: once with the first lambda
// inside of 'lep' and again with the second lambda inside of 'lep'.
-// CHECK-DAG: @"\01??0?$H@V<lambda_1>@?0???$lep@X@@YAXXZ@@@QAE@XZ"
-// CHECK-DAG: @"\01??0?$H@V<lambda_2>@?0???$lep@X@@YAXXZ@@@QAE@XZ"
+// CHECK-DAG: @"??0?$H@V<lambda_1>@?0???$lep@X@@YAXXZ@@@QAE@XZ"
+// CHECK-DAG: @"??0?$H@V<lambda_2>@?0???$lep@X@@YAXXZ@@@QAE@XZ"
template <typename>
struct H {
diff --git a/test/CodeGenCXX/pr20897.cpp b/test/CodeGenCXX/pr20897.cpp
index 16e122b..73995fc 100644
--- a/test/CodeGenCXX/pr20897.cpp
+++ b/test/CodeGenCXX/pr20897.cpp
@@ -3,7 +3,7 @@
// __declspec(dllexport) causes us to export the implicit constructor.
struct __declspec(dllexport) Derived : virtual Base {
-// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc %struct.Derived* @"\01??0Derived@@QAE@ABU0@@Z"
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc %struct.Derived* @"??0Derived@@QAE@ABU0@@Z"
// CHECK: %[[this:.*]] = load %struct.Derived*, %struct.Derived** {{.*}}
// CHECK-NEXT: store %struct.Derived* %[[this]], %struct.Derived** %[[retval:.*]]
// CHECK: %[[dest_a_gep:.*]] = getelementptr inbounds %struct.Derived, %struct.Derived* %[[this]], i32 0, i32 1
@@ -18,7 +18,7 @@
// __declspec(dllexport) causes us to export the implicit copy constructor.
struct __declspec(dllexport) Derived2 : virtual Base {
-// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc %struct.Derived2* @"\01??0Derived2@@QAE@ABU0@@Z"
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc %struct.Derived2* @"??0Derived2@@QAE@ABU0@@Z"
// CHECK: %[[this:.*]] = load %struct.Derived2*, %struct.Derived2** {{.*}}
// CHECK-NEXT: store %struct.Derived2* %[[this]], %struct.Derived2** %[[retval:.*]]
// CHECK: %[[dest_a_gep:.*]] = getelementptr inbounds %struct.Derived2, %struct.Derived2* %[[this]], i32 0, i32 1
diff --git a/test/CodeGenCXX/pr28360.cpp b/test/CodeGenCXX/pr28360.cpp
index af226df..6bf2ea7 100644
--- a/test/CodeGenCXX/pr28360.cpp
+++ b/test/CodeGenCXX/pr28360.cpp
@@ -10,7 +10,7 @@
void Baz() { Bar(&A::Foo); }
-// CHECK-LABEL: define dso_local void @"\01?Baz@@YAXXZ"(
+// CHECK-LABEL: define dso_local void @"?Baz@@YAXXZ"(
// CHECK: %[[ref_tmp:.*]] = alloca i8*, align 4
-// CHECK: store i8* bitcast (void (%struct.A*)* @"\01?Foo@A@@QAEXXZ" to i8*), i8** %[[ref_tmp]], align 4
-// CHECK: call void @"\01?Bar@@YAXABQ8A@@AEXXZ@Z"(i8** dereferenceable(4) %[[ref_tmp]])
+// CHECK: store i8* bitcast (void (%struct.A*)* @"?Foo@A@@QAEXXZ" to i8*), i8** %[[ref_tmp]], align 4
+// CHECK: call void @"?Bar@@YAXABQ8A@@AEXXZ@Z"(i8** dereferenceable(4) %[[ref_tmp]])
diff --git a/test/CodeGenCXX/pr30731.cpp b/test/CodeGenCXX/pr30731.cpp
index f985c26..36da43f 100644
--- a/test/CodeGenCXX/pr30731.cpp
+++ b/test/CodeGenCXX/pr30731.cpp
@@ -16,6 +16,6 @@
void f(S* s) { s->f(); }
-// CHECK-LABEL: define dso_local void @"\01?f@@YAXPAUS@@@Z"
+// CHECK-LABEL: define dso_local void @"?f@@YAXPAUS@@@Z"
// CHECK: call
// CHECK: ret void
diff --git a/test/CodeGenCXX/pr33080.cpp b/test/CodeGenCXX/pr33080.cpp
index 782327e..bae47cc 100644
--- a/test/CodeGenCXX/pr33080.cpp
+++ b/test/CodeGenCXX/pr33080.cpp
@@ -21,6 +21,10 @@
void ja(__unaligned struct A *, __unaligned struct A *__unaligned *, __unaligned struct A *__unaligned *__unaligned *) {}
// CHECK: define {{(dso_local )?}}void @_Z2jaPU11__unaligned1APU11__unalignedS1_PU11__unalignedS3_(
+struct A;
+void memptr(void (A::*a)(int) __unaligned) {}
+// CHECK: define {{.*}} @_Z6memptrM1AU11__unalignedFviE(
+
void jb(__unaligned struct A *, __unaligned struct A **, __unaligned struct A *__unaligned *__unaligned *) {}
// CHECK: @_Z2jbPU11__unaligned1APS1_PU11__unalignedPU11__unalignedS1_(
diff --git a/test/CodeGenCXX/pragma-init_seg.cpp b/test/CodeGenCXX/pragma-init_seg.cpp
index 8fecb1e..8b33b85 100644
--- a/test/CodeGenCXX/pragma-init_seg.cpp
+++ b/test/CodeGenCXX/pragma-init_seg.cpp
@@ -2,24 +2,24 @@
int f();
-// CHECK: $"\01?x@selectany_init@@3HA" = comdat any
-// CHECK: $"\01?x@?$A@H@explicit_template_instantiation@@2HB" = comdat any
-// CHECK: $"\01?x@?$A@H@implicit_template_instantiation@@2HB" = comdat any
+// CHECK: $"?x@selectany_init@@3HA" = comdat any
+// CHECK: $"?x@?$A@H@explicit_template_instantiation@@2HB" = comdat any
+// CHECK: $"?x@?$A@H@implicit_template_instantiation@@2HB" = comdat any
namespace simple_init {
#pragma init_seg(compiler)
int x = f();
-// CHECK: @"\01?x@simple_init@@3HA" = dso_local global i32 0, align 4
-// CHECK: @__cxx_init_fn_ptr = private constant void ()* @"\01??__Ex@simple_init@@YAXXZ", section ".CRT$XCC"
+// CHECK: @"?x@simple_init@@3HA" = dso_local global i32 0, align 4
+// CHECK: @__cxx_init_fn_ptr = private constant void ()* @"??__Ex@simple_init@@YAXXZ", section ".CRT$XCC"
#pragma init_seg(lib)
int y = f();
-// CHECK: @"\01?y@simple_init@@3HA" = dso_local global i32 0, align 4
-// CHECK: @__cxx_init_fn_ptr.1 = private constant void ()* @"\01??__Ey@simple_init@@YAXXZ", section ".CRT$XCL"
+// CHECK: @"?y@simple_init@@3HA" = dso_local global i32 0, align 4
+// CHECK: @__cxx_init_fn_ptr.1 = private constant void ()* @"??__Ey@simple_init@@YAXXZ", section ".CRT$XCL"
#pragma init_seg(user)
int z = f();
-// CHECK: @"\01?z@simple_init@@3HA" = dso_local global i32 0, align 4
+// CHECK: @"?z@simple_init@@3HA" = dso_local global i32 0, align 4
// No function pointer! This one goes on @llvm.global_ctors.
}
@@ -28,31 +28,31 @@
namespace internal_init {
namespace {
int x = f();
-// CHECK: @"\01?x@?A@internal_init@@3HA" = internal global i32 0, align 4
-// CHECK: @__cxx_init_fn_ptr.2 = private constant void ()* @"\01??__Ex@?A@internal_init@@YAXXZ", section ".asdf"
+// CHECK: @"?x@?A@internal_init@@3HA" = internal global i32 0, align 4
+// CHECK: @__cxx_init_fn_ptr.2 = private constant void ()* @"??__Ex@?A@internal_init@@YAXXZ", section ".asdf"
}
}
namespace selectany_init {
int __declspec(selectany) x = f();
-// CHECK: @"\01?x@selectany_init@@3HA" = weak_odr dso_local global i32 0, comdat, align 4
-// CHECK: @__cxx_init_fn_ptr.3 = private constant void ()* @"\01??__Ex@selectany_init@@YAXXZ", section ".asdf", comdat($"\01?x@selectany_init@@3HA")
+// CHECK: @"?x@selectany_init@@3HA" = weak_odr dso_local global i32 0, comdat, align 4
+// CHECK: @__cxx_init_fn_ptr.3 = private constant void ()* @"??__Ex@selectany_init@@YAXXZ", section ".asdf", comdat($"?x@selectany_init@@3HA")
}
namespace explicit_template_instantiation {
template <typename T> struct A { static const int x; };
template <typename T> const int A<T>::x = f();
template struct A<int>;
-// CHECK: @"\01?x@?$A@H@explicit_template_instantiation@@2HB" = weak_odr dso_local global i32 0, comdat, align 4
-// CHECK: @__cxx_init_fn_ptr.4 = private constant void ()* @"\01??__Ex@?$A@H@explicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"\01?x@?$A@H@explicit_template_instantiation@@2HB")
+// CHECK: @"?x@?$A@H@explicit_template_instantiation@@2HB" = weak_odr dso_local global i32 0, comdat, align 4
+// CHECK: @__cxx_init_fn_ptr.4 = private constant void ()* @"??__Ex@?$A@H@explicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"?x@?$A@H@explicit_template_instantiation@@2HB")
}
namespace implicit_template_instantiation {
template <typename T> struct A { static const int x; };
template <typename T> const int A<T>::x = f();
int g() { return A<int>::x; }
-// CHECK: @"\01?x@?$A@H@implicit_template_instantiation@@2HB" = linkonce_odr dso_local global i32 0, comdat, align 4
-// CHECK: @__cxx_init_fn_ptr.5 = private constant void ()* @"\01??__Ex@?$A@H@implicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"\01?x@?$A@H@implicit_template_instantiation@@2HB")
+// CHECK: @"?x@?$A@H@implicit_template_instantiation@@2HB" = linkonce_odr dso_local global i32 0, comdat, align 4
+// CHECK: @__cxx_init_fn_ptr.5 = private constant void ()* @"??__Ex@?$A@H@implicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"?x@?$A@H@implicit_template_instantiation@@2HB")
}
// ... and here's where we emitted user level ctors.
diff --git a/test/CodeGenCXX/regcall.cpp b/test/CodeGenCXX/regcall.cpp
index ea1f878..a9af4a4 100644
--- a/test/CodeGenCXX/regcall.cpp
+++ b/test/CodeGenCXX/regcall.cpp
@@ -15,15 +15,15 @@
return lambda(p);
}
// CHECK-LIN: call x86_regcallcc {{.+}} @_Z15__regcall3__foo
-// CHECK-WIN64: call x86_regcallcc {{.+}} @"\01?foo@@YwHH@Z"
-// CHECK-WIN32: call x86_regcallcc {{.+}} @"\01?foo@@YwHH@Z"
+// CHECK-WIN64: call x86_regcallcc {{.+}} @"?foo@@YwHH@Z"
+// CHECK-WIN32: call x86_regcallcc {{.+}} @"?foo@@YwHH@Z"
int __regcall foo (int i){
return i;
}
// CHECK-LIN: define x86_regcallcc {{.+}}@_Z15__regcall3__foo
-// CHECK-WIN64: define dso_local x86_regcallcc {{.+}}@"\01?foo@@YwHH@Z"
-// CHECK-WIN32: define dso_local x86_regcallcc {{.+}}@"\01?foo@@YwHH@Z"
+// CHECK-WIN64: define dso_local x86_regcallcc {{.+}}@"?foo@@YwHH@Z"
+// CHECK-WIN32: define dso_local x86_regcallcc {{.+}}@"?foo@@YwHH@Z"
// used to give a body to test_class functions
static int x = 0;
@@ -37,8 +37,8 @@
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classC1Ev
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classC2Ev
// Windows ignores calling convention on constructor/destructors.
- // CHECK-WIN64-DAG: define linkonce_odr dso_local %class.test_class* @"\01??0test_class@@QEAA@XZ"
- // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc %class.test_class* @"\01??0test_class@@QAE@XZ"
+ // CHECK-WIN64-DAG: define linkonce_odr dso_local %class.test_class* @"??0test_class@@QEAA@XZ"
+ // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc %class.test_class* @"??0test_class@@QAE@XZ"
#ifndef WIN_TEST
__regcall
@@ -47,43 +47,43 @@
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD2Ev
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD1Ev
// Windows ignores calling convention on constructor/destructors.
- // CHECK-WIN64-DAG: define linkonce_odr dso_local void @"\01??_Dtest_class@@QEAAXXZ"
- // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"\01??_Dtest_class@@QAEXXZ"
+ // CHECK-WIN64-DAG: define linkonce_odr dso_local void @"??1test_class@@QEAA@XZ"
+ // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"??1test_class@@QAE@XZ"
test_class& __regcall operator+=(const test_class&){
return *this;
}
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc dereferenceable(4) %class.test_class* @_ZN10test_classpLERKS_
- // CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc dereferenceable(4) %class.test_class* @"\01??Ytest_class@@QEAwAEAV0@AEBV0@@Z"
- // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc dereferenceable(4) %class.test_class* @"\01??Ytest_class@@QAwAAV0@ABV0@@Z"
+ // CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc dereferenceable(4) %class.test_class* @"??Ytest_class@@QEAwAEAV0@AEBV0@@Z"
+ // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc dereferenceable(4) %class.test_class* @"??Ytest_class@@QAwAAV0@ABV0@@Z"
void __regcall do_thing(){}
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_class20__regcall3__do_thingEv
- // CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc void @"\01?do_thing@test_class@@QEAwXXZ"
- // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc void @"\01?do_thing@test_class@@QAwXXZ"
+ // CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc void @"?do_thing@test_class@@QEAwXXZ"
+ // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc void @"?do_thing@test_class@@QAwXXZ"
template<typename T>
void __regcall tempFunc(T i){}
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_class20__regcall3__tempFuncIiEEvT_
- // CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc void @"\01??$freeTempFunc@H@@YwXH@Z"
- // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc void @"\01??$freeTempFunc@H@@YwXH@Z"
+ // CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc void @"??$freeTempFunc@H@@YwXH@Z"
+ // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc void @"??$freeTempFunc@H@@YwXH@Z"
};
bool __regcall operator ==(const test_class&, const test_class&){ --x; return false;}
// CHECK-LIN-DAG: define x86_regcallcc zeroext i1 @_ZeqRK10test_classS1_
-// CHECK-WIN64-DAG: define dso_local x86_regcallcc zeroext i1 @"\01??8@Yw_NAEBVtest_class@@0@Z"
-// CHECK-WIN32-DAG: define dso_local x86_regcallcc zeroext i1 @"\01??8@Yw_NABVtest_class@@0@Z"
+// CHECK-WIN64-DAG: define dso_local x86_regcallcc zeroext i1 @"??8@Yw_NAEBVtest_class@@0@Z"
+// CHECK-WIN32-DAG: define dso_local x86_regcallcc zeroext i1 @"??8@Yw_NABVtest_class@@0@Z"
test_class __regcall operator""_test_class (unsigned long long) { ++x; return test_class{};}
// CHECK-LIN64-DAG: define x86_regcallcc void @_Zli11_test_classy(%class.test_class* noalias sret %agg.result, i64)
// CHECK-LIN32-DAG: define x86_regcallcc void @_Zli11_test_classy(%class.test_class* inreg noalias sret %agg.result, i64)
-// CHECK-WIN64-DAG: \01??__K_test_class@@Yw?AVtest_class@@_K@Z"
-// CHECK-WIN32-DAG: \01??__K_test_class@@Yw?AVtest_class@@_K@Z"
+// CHECK-WIN64-DAG: ??__K_test_class@@Yw?AVtest_class@@_K@Z"
+// CHECK-WIN32-DAG: ??__K_test_class@@Yw?AVtest_class@@_K@Z"
template<typename T>
void __regcall freeTempFunc(T i){}
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_Z24__regcall3__freeTempFuncIiEvT_
-// CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc void @"\01??$freeTempFunc@H@@YwXH@Z"
-// CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc void @"\01??$freeTempFunc@H@@YwXH@Z"
+// CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc void @"??$freeTempFunc@H@@YwXH@Z"
+// CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc void @"??$freeTempFunc@H@@YwXH@Z"
// class to force generation of functions
void force_gen() {
@@ -101,5 +101,5 @@
}
// CHECK-LIN64-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 16 %f)
// CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* inreg noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 4 %f)
-// CHECK-WIN64-DAG: define dso_local x86_regcallcc { double, double } @"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
-// CHECK-WIN32-DAG: define dso_local x86_regcallcc { double, double } @"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
+// CHECK-WIN64-DAG: define dso_local x86_regcallcc { double, double } @"?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
+// CHECK-WIN32-DAG: define dso_local x86_regcallcc { double, double } @"?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
diff --git a/test/CodeGenCXX/rtti-hidden.cpp b/test/CodeGenCXX/rtti-hidden.cpp
new file mode 100644
index 0000000..3ae487f
--- /dev/null
+++ b/test/CodeGenCXX/rtti-hidden.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -o - | FileCheck %s
+
+// Test that this is not hidden.
+// CHECK: @_ZTVN10__cxxabiv120__si_class_type_infoE = external global
+
+class foo {
+ virtual void baz();
+};
+struct __attribute__((__visibility__("hidden"))) bar : public foo {};
+bar zed;
diff --git a/test/CodeGenCXX/runtime-dllstorage.cpp b/test/CodeGenCXX/runtime-dllstorage.cpp
index 4fcc903..74ba66f 100644
--- a/test/CodeGenCXX/runtime-dllstorage.cpp
+++ b/test/CodeGenCXX/runtime-dllstorage.cpp
@@ -106,15 +106,16 @@
}
// CHECK-MS-DAG: @_Init_thread_epoch = external thread_local global i32
-// CHECK-MS-DAG: declare i32 @__tlregdtor(void ()*)
-// CHECK-MS-DAG: declare i32 @atexit(void ()*)
+// CHECK-MS-DAG: declare dso_local i32 @__tlregdtor(void ()*)
+// CHECK-MS-DAG: declare dso_local i32 @atexit(void ()*)
// CHECK-MS-DYNAMIC-DAG: declare dllimport {{.*}} void @_CxxThrowException
// CHECK-MS-STATIC-DAG: declare {{.*}} void @_CxxThrowException
-// CHECK-MS-DAG: declare dso_local noalias i8* @"\01??2@YAPAXI@Z"
-// CHECK-MS-DAG: declare void @_Init_thread_header(i32*)
-// CHECK-MS-DAG: declare void @_Init_thread_footer(i32*)
+// CHECK-MS-DAG: declare dso_local noalias i8* @"??2@YAPAXI@Z"
+// CHECK-MS-DAG: declare dso_local void @_Init_thread_header(i32*)
+// CHECK-MS-DAG: declare dso_local void @_Init_thread_footer(i32*)
-// CHECK-IA-DAG: declare i32 @__gxx_personality_v0(...)
+// CHECK-IA-DAG: @_ZTH1t = dso_local alias void (), void ()* @__tls_init
+// CHECK-IA-DAG: declare dso_local i32 @__gxx_personality_v0(...)
// CHECK-IA-DAG: define linkonce_odr hidden void @__clang_call_terminate(i8*)
// CHECK-DYNAMIC-IA-DAG: declare dllimport i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*)
@@ -134,25 +135,25 @@
// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport void @__cxa_guard_release(i64*)
// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dllimport void @__cxa_guard_release(i64*)
// CHECK-DYANMIC-IA-DAG: declare dllimport void @_ZSt9terminatev()
-// CHECK-DYNAMIC-NODECL-IA-DAG: declare void @_ZSt9terminatev()
+// CHECK-DYNAMIC-NODECL-IA-DAG: declare dso_local void @_ZSt9terminatev()
// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport void @_ZSt9terminatev()
// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dso_local dllexport void @_ZSt9terminatev()
-// CHECK-STATIC-IA-DAG: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*)
-// CHECK-STATIC-IA-DAG: declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
-// CHECK-STATIC-IA-DAG: declare i8* @__cxa_allocate_exception(i32)
-// CHECK-STATIC-IA-DAG: declare void @__cxa_throw(i8*, i8*, i8*)
-// CHECK-STATIC-DECL-IA-DAG: declare i32 @__cxa_guard_acquire(i64*)
-// CHECK-STATIC-NODECL-IA-DAG: declare i32 @__cxa_guard_acquire(i64*)
-// CHECK-STATIC-IMPORT-IA-DAG: declare i32 @__cxa_guard_acquire(i64*)
+// CHECK-STATIC-IA-DAG: declare dso_local i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*)
+// CHECK-STATIC-IA-DAG: declare dso_local i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
+// CHECK-STATIC-IA-DAG: declare dso_local i8* @__cxa_allocate_exception(i32)
+// CHECK-STATIC-IA-DAG: declare dso_local void @__cxa_throw(i8*, i8*, i8*)
+// CHECK-STATIC-DECL-IA-DAG: declare dso_local i32 @__cxa_guard_acquire(i64*)
+// CHECK-STATIC-NODECL-IA-DAG: declare dso_local i32 @__cxa_guard_acquire(i64*)
+// CHECK-STATIC-IMPORT-IA-DAG: declare dso_local i32 @__cxa_guard_acquire(i64*)
// CHECK-STATIC-EXPORT-IA-DAG: declare dso_local i32 @__cxa_guard_acquire(i64*)
// CHECK-IA-DAG: declare dso_local noalias i8* @_Znwj(i32)
-// CHECK-STATIC-DECL-IA-DAG: declare void @__cxa_guard_release(i64*)
-// CHECK-STATIC-NODECL-IA-DAG: declare void @__cxa_guard_release(i64*)
-// CHECK-STATIC-IMPORT-IA-DAG: declare void @__cxa_guard_release(i64*)
+// CHECK-STATIC-DECL-IA-DAG: declare dso_local void @__cxa_guard_release(i64*)
+// CHECK-STATIC-NODECL-IA-DAG: declare dso_local void @__cxa_guard_release(i64*)
+// CHECK-STATIC-IMPORT-IA-DAG: declare dso_local void @__cxa_guard_release(i64*)
// CHECK-STATIC-EXPORT-IA-DAG: declare dso_local void @__cxa_guard_release(i64*)
-// CHECK-STATIC-IA-DAG: declare void @_ZSt9terminatev()
-// CHECK-STATIC-NODECL-IA-DAG: declare void @_ZSt9terminatev()
-// CHECK-STATIC-IMPORT-IA-DAG: declare void @_ZSt9terminatev()
+// CHECK-STATIC-IA-DAG: declare dso_local void @_ZSt9terminatev()
+// CHECK-STATIC-NODECL-IA-DAG: declare dso_local void @_ZSt9terminatev()
+// CHECK-STATIC-IMPORT-IA-DAG: declare dso_local void @_ZSt9terminatev()
// CHECK-STATIC-EXPORT-IA-DAG: declare dso_local dllexport void @_ZSt9terminatev()
diff --git a/test/CodeGenCXX/stack-reuse-exceptions.cpp b/test/CodeGenCXX/stack-reuse-exceptions.cpp
new file mode 100644
index 0000000..de870c5
--- /dev/null
+++ b/test/CodeGenCXX/stack-reuse-exceptions.cpp
@@ -0,0 +1,189 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -o - -emit-llvm -O1 \
+// RUN: -fexceptions -fcxx-exceptions | FileCheck %s
+//
+// We should emit lifetime.ends for these temporaries in both the 'exception'
+// and 'normal' paths in functions.
+//
+// -O1 is necessary to make lifetime markers appear.
+
+struct Large {
+ int cs[32];
+};
+
+Large getLarge();
+
+// Used to ensure we emit invokes.
+struct NontrivialDtor {
+ int i;
+ ~NontrivialDtor();
+};
+
+// CHECK-LABEL: define void @_Z33cleanupsAreEmittedWithoutTryCatchv
+void cleanupsAreEmittedWithoutTryCatch() {
+// CHECK: %[[CLEAN:[^ ]+]] = bitcast %struct.NontrivialDtor* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]])
+// CHECK: %[[T1:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CONT:[^ ]+]] unwind label %[[LPAD:[^ ]+]]
+//
+// CHECK: [[CONT]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK: %[[T2:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CONT2:[^ ]+]] unwind label %[[LPAD2:.+]]
+//
+// CHECK: [[CONT2]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]])
+// CHECK: ret void
+//
+// CHECK: [[LPAD]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK: br label %[[EHCLEANUP:.+]]
+//
+// CHECK: [[LPAD2]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK: br label %[[EHCLEANUP]]
+//
+// CHECK: [[EHCLEANUP]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]])
+
+ NontrivialDtor clean;
+
+ getLarge();
+ getLarge();
+}
+
+// CHECK-LABEL: define void @_Z30cleanupsAreEmittedWithTryCatchv
+void cleanupsAreEmittedWithTryCatch() {
+// CHECK: %[[CLEAN:[^ ]+]] = bitcast %struct.NontrivialDtor* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]])
+// CHECK: %[[T1:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CONT:[^ ]+]] unwind label %[[LPAD:[^ ]+]]
+//
+// CHECK: [[CONT]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK: %[[T2:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CONT2:[^ ]+]] unwind label %[[LPAD2:.+]]
+//
+// CHECK: [[CONT2]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK: br label %[[TRY_CONT:.+]]
+//
+// CHECK: [[LPAD]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK: br label %[[CATCH:.+]]
+//
+// CHECK: [[LPAD2]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK: br label %[[CATCH]]
+//
+// CHECK: [[CATCH]]:
+// CHECK-NOT: call void @llvm.lifetime
+// CHECK: invoke void
+// CHECK-NEXT: to label %[[TRY_CONT]] unwind label %[[OUTER_LPAD:.+]]
+//
+// CHECK: [[TRY_CONT]]:
+// CHECK: %[[T_OUTER:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T_OUTER]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[OUTER_CONT:[^ ]+]] unwind label %[[OUTER_LPAD2:.+]]
+//
+// CHECK: [[OUTER_CONT]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T_OUTER]])
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]])
+// CHECK: ret void
+//
+// CHECK: [[OUTER_LPAD]]:
+// CHECK-NOT: call void @llvm.lifetime
+// CHECK: br label %[[EHCLEANUP:.+]]
+//
+// CHECK: [[OUTER_LPAD2]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T_OUTER]])
+// CHECK: br label %[[EHCLEANUP]]
+//
+// CHECK: [[EHCLEANUP]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]])
+
+ NontrivialDtor clean;
+
+ try {
+ getLarge();
+ getLarge();
+ } catch (...) {}
+
+ getLarge();
+}
+
+// CHECK-LABEL: define void @_Z39cleanupInTryHappensBeforeCleanupInCatchv
+void cleanupInTryHappensBeforeCleanupInCatch() {
+// CHECK: %[[T1:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CONT:[^ ]+]] unwind label %[[LPAD:[^ ]+]]
+//
+// CHECK: [[CONT]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK: br label %[[TRY_CONT]]
+//
+// CHECK: [[LPAD]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T1]])
+// CHECK: br i1 {{[^,]+}}, label %[[CATCH_INT_MATCH:[^,]+]], label %[[CATCH_ALL:.+]]
+//
+// CHECK: [[CATCH_INT_MATCH]]:
+// CHECK: %[[T2:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CATCH_INT_CONT:[^ ]+]] unwind label %[[CATCH_INT_LPAD:[^ ]+]]
+//
+// CHECK: [[CATCH_INT_CONT]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK: br label %[[TRY_CONT]]
+//
+// CHECK: [[TRY_CONT]]:
+// CHECK: ret void
+//
+// CHECK: [[CATCH_ALL]]:
+// CHECK: %[[T3:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8*
+// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* nonnull %[[T3]])
+// CHECK-NEXT: invoke void @_Z8getLargev
+// CHECK-NEXT: to label %[[CATCH_ALL_CONT:[^ ]+]] unwind label %[[CATCH_ALL_LPAD:[^ ]+]]
+//
+// CHECK: [[CATCH_ALL_CONT]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T3]])
+// CHECK: br label %[[TRY_CONT]]
+//
+// CHECK: [[CATCH_ALL_LPAD]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T3]])
+//
+// CHECK: [[CATCH_INT_LPAD]]:
+// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T2]])
+// CHECK-NOT: call void @llvm.lifetime
+
+ try {
+ getLarge();
+ } catch (const int &) {
+ getLarge();
+ } catch (...) {
+ getLarge();
+ }
+}
+
+// FIXME: We don't currently emit lifetime markers for aggregate by-value
+// temporaries (e.g. given a function `Large combine(Large, Large);`
+// combine(getLarge(), getLarge()) "leaks" two `Large`s). We probably should. We
+// also don't emit markers for things like:
+//
+// {
+// Large L = getLarge();
+// combine(L, L);
+// }
+//
+// Though this arguably isn't as bad, since we pass a pointer to `L` as one of
+// the two args.
diff --git a/test/CodeGenCXX/trap-fnattr.cpp b/test/CodeGenCXX/trap-fnattr.cpp
index 79fb813..166bbad 100644
--- a/test/CodeGenCXX/trap-fnattr.cpp
+++ b/test/CodeGenCXX/trap-fnattr.cpp
@@ -1,29 +1,29 @@
// RUN: %clang_cc1 -O0 -emit-llvm -ftrapv -ftrap-function=mytrap %s -o - | FileCheck %s -check-prefix=TRAPFUNC
// RUN: %clang_cc1 -O0 -emit-llvm -ftrapv %s -o - | FileCheck %s -check-prefix=NOOPTION
-// TRAPFUNC-LABEL: define {{(dso_local )?}}void @{{_Z12test_builtinv|\"\\01\?test_builtin@@YAXXZ\"}}
+// TRAPFUNC-LABEL: define {{(dso_local )?}}void @{{_Z12test_builtinv|\"\?test_builtin@@YAXXZ\"}}
// TRAPFUNC: call void @llvm.trap() [[ATTR0:#[0-9]+]]
-// NOOPTION-LABEL: define {{(dso_local )?}}void @{{_Z12test_builtinv|\"\\01\?test_builtin@@YAXXZ\"}}
+// NOOPTION-LABEL: define {{(dso_local )?}}void @{{_Z12test_builtinv|\"\?test_builtin@@YAXXZ\"}}
// NOOPTION: call void @llvm.trap(){{$}}
void test_builtin(void) {
__builtin_trap();
}
-// TRAPFUNC-LABEL: define {{.*}}i32 @{{_Z13test_noreturnv|\"\\01\?test_noreturn@@YAHXZ\"}}
+// TRAPFUNC-LABEL: define {{.*}}i32 @{{_Z13test_noreturnv|\"\?test_noreturn@@YAHXZ\"}}
// TRAPFUNC: call void @llvm.trap() [[ATTR0]]
-// NOOPTION-LABEL: define {{.*}}i32 @{{_Z13test_noreturnv|\"\\01\?test_noreturn@@YAHXZ\"}}
+// NOOPTION-LABEL: define {{.*}}i32 @{{_Z13test_noreturnv|\"\?test_noreturn@@YAHXZ\"}}
// NOOPTION: call void @llvm.trap(){{$}}
int test_noreturn(void) {
}
-// TRAPFUNC-LABEL: define {{.*}}i32 @{{_Z17test_add_overflowii|\"\\01\?test_add_overflow@@YAHHH@Z\"}}
+// TRAPFUNC-LABEL: define {{.*}}i32 @{{_Z17test_add_overflowii|\"\?test_add_overflow@@YAHHH@Z\"}}
// TRAPFUNC: call void @llvm.trap() [[ATTR1:#[0-9]+]]
-// NOOPTION-LABEL: define {{.*}}i32 @{{_Z17test_add_overflowii|\"\\01\?test_add_overflow@@YAHHH@Z\"}}
+// NOOPTION-LABEL: define {{.*}}i32 @{{_Z17test_add_overflowii|\"\?test_add_overflow@@YAHHH@Z\"}}
// NOOPTION: call void @llvm.trap() [[ATTR2:#[0-9]+]]
int test_add_overflow(int a, int b) {
diff --git a/test/CodeGenCXX/type-metadata.cpp b/test/CodeGenCXX/type-metadata.cpp
index 172636c..be415c3 100644
--- a/test/CodeGenCXX/type-metadata.cpp
+++ b/test/CodeGenCXX/type-metadata.cpp
@@ -53,13 +53,13 @@
// ITANIUM-SAME: !type [[FA16:![0-9]+]]
// ITANIUM-DIAG-SAME: !type [[ALL16]]
-// MS: comdat($"\01??_7A@@6B@"), !type [[A8:![0-9]+]]
-// MS: comdat($"\01??_7B@@6B0@@"), !type [[B8:![0-9]+]]
-// MS: comdat($"\01??_7B@@6BA@@@"), !type [[A8]]
-// MS: comdat($"\01??_7C@@6B@"), !type [[A8]]
-// MS: comdat($"\01??_7D@?A@@6BB@@@"), !type [[B8]], !type [[D8:![0-9]+]]
-// MS: comdat($"\01??_7D@?A@@6BA@@@"), !type [[A8]]
-// MS: comdat($"\01??_7FA@?1??foo@@YAXXZ@6B@"), !type [[A8]], !type [[FA8:![0-9]+]]
+// MS: comdat($"??_7A@@6B@"), !type [[A8:![0-9]+]]
+// MS: comdat($"??_7B@@6B0@@"), !type [[B8:![0-9]+]]
+// MS: comdat($"??_7B@@6BA@@@"), !type [[A8]]
+// MS: comdat($"??_7C@@6B@"), !type [[A8]]
+// MS: comdat($"??_7D@?A@@6BB@@@"), !type [[B8]], !type [[D8:![0-9]+]]
+// MS: comdat($"??_7D@?A@@6BA@@@"), !type [[A8]]
+// MS: comdat($"??_7FA@?1??foo@@YAXXZ@6B@"), !type [[A8]], !type [[FA8:![0-9]+]]
struct A {
A();
@@ -104,7 +104,7 @@
}
// ITANIUM: define hidden void @_Z2afP1A
-// MS: define dso_local void @"\01?af@@YAXPEAUA@@@Z"
+// MS: define dso_local void @"?af@@YAXPEAUA@@@Z"
void af(A *a) {
// TT-ITANIUM: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT:%[^ ]*]], metadata !"_ZTS1A")
// TT-MS: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT:%[^ ]*]], metadata !"?AUA@@")
@@ -136,7 +136,7 @@
}
// ITANIUM: define internal void @_Z3df1PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?df1@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?df1@@YAXPEAUD@?A@@@Z"
void df1(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]])
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUA@@")
@@ -146,7 +146,7 @@
}
// ITANIUM: define internal void @_Z3dg1PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?dg1@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?dg1@@YAXPEAUD@?A@@@Z"
void dg1(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUB@@")
@@ -156,7 +156,7 @@
}
// ITANIUM: define internal void @_Z3dh1PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?dh1@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?dh1@@YAXPEAUD@?A@@@Z"
void dh1(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE]])
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]])
@@ -166,7 +166,7 @@
}
// ITANIUM: define internal void @_Z3df2PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?df2@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?df2@@YAXPEAUD@?A@@@Z"
__attribute__((no_sanitize("cfi")))
void df2(D *d) {
// CFI-NVT-NOT: call i1 @llvm.type.test
@@ -176,7 +176,7 @@
}
// ITANIUM: define internal void @_Z3df3PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?df3@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?df3@@YAXPEAUD@?A@@@Z"
__attribute__((no_sanitize("address"))) __attribute__((no_sanitize("cfi-vcall")))
void df3(D *d) {
// CFI-NVT-NOT: call i1 @llvm.type.test
@@ -214,7 +214,7 @@
};
// ITANIUM: define hidden void @_ZN5test21fEPNS_1DE
-// MS: define dso_local void @"\01?f@test2@@YAXPEAUD@1@@Z"
+// MS: define dso_local void @"?f@test2@@YAXPEAUD@1@@Z"
void f(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTSN5test21DE")
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUA@test2@@")
diff --git a/test/CodeGenCXX/ubsan-vtable-checks.cpp b/test/CodeGenCXX/ubsan-vtable-checks.cpp
index 494455b..ec4a21a 100644
--- a/test/CodeGenCXX/ubsan-vtable-checks.cpp
+++ b/test/CodeGenCXX/ubsan-vtable-checks.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=null %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NULL --check-prefix=ITANIUM
// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=null %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NULL --check-prefix=MSABI
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=ITANIUM
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=MSABI
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=MSABI --check-prefix=CHECK-VPTR-MS
struct T {
virtual ~T() {}
virtual int v() { return 1; }
@@ -14,8 +14,10 @@
U::~U() {}
+// CHECK-VPTR-MS: @__ubsan_vptr_type_cache = external dso_local
+
// ITANIUM: define i32 @_Z5get_vP1T
-// MSABI: define dso_local i32 @"\01?get_v
+// MSABI: define dso_local i32 @"?get_v
int get_v(T* t) {
// First, we check that vtable is not loaded before a type check.
// CHECK-NULL-NOT: load {{.*}} (%struct.T*{{.*}})**, {{.*}} (%struct.T*{{.*}})***
@@ -28,7 +30,7 @@
}
// ITANIUM: define void @_Z9delete_itP1T
-// MSABI: define dso_local void @"\01?delete_it
+// MSABI: define dso_local void @"?delete_it
void delete_it(T *t) {
// First, we check that vtable is not loaded before a type check.
// CHECK-VPTR-NOT: load {{.*}} (%struct.T*{{.*}})**, {{.*}} (%struct.T*{{.*}})***
@@ -40,7 +42,7 @@
}
// ITANIUM: define %struct.U* @_Z7dyncastP1T
-// MSABI: define dso_local %struct.U* @"\01?dyncast
+// MSABI: define dso_local %struct.U* @"?dyncast
U* dyncast(T *t) {
// First, we check that dynamic_cast is not called before a type check.
// CHECK-VPTR-NOT: call i8* @__{{dynamic_cast|RTDynamicCast}}
diff --git a/test/CodeGenCXX/uncopyable-args.cpp b/test/CodeGenCXX/uncopyable-args.cpp
index 4c0241d..baada1c 100644
--- a/test/CodeGenCXX/uncopyable-args.cpp
+++ b/test/CodeGenCXX/uncopyable-args.cpp
@@ -19,7 +19,7 @@
// CHECK: call void @_ZN7trivial3fooENS_1AE(i8* %{{.*}})
// CHECK-LABEL: declare void @_ZN7trivial3fooENS_1AE(i8*)
-// WIN64-LABEL: declare dso_local void @"\01?foo@trivial@@YAXUA@1@@Z"(i64)
+// WIN64-LABEL: declare dso_local void @"?foo@trivial@@YAXUA@1@@Z"(i64)
}
namespace default_ctor {
@@ -40,7 +40,7 @@
// CHECK: call void @_ZN12default_ctor3fooENS_1AE(i8* %{{.*}})
// CHECK-LABEL: declare void @_ZN12default_ctor3fooENS_1AE(i8*)
-// WIN64-LABEL: declare dso_local void @"\01?foo@default_ctor@@YAXUA@1@@Z"(i64)
+// WIN64-LABEL: declare dso_local void @"?foo@default_ctor@@YAXUA@1@@Z"(i64)
}
namespace move_ctor {
@@ -63,7 +63,7 @@
// NEWABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*)
// OLDABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(i8*)
-// WIN64-LABEL: declare dso_local void @"\01?foo@move_ctor@@YAXUA@1@@Z"(%"struct.move_ctor::A"*)
+// WIN64-LABEL: declare dso_local void @"?foo@move_ctor@@YAXUA@1@@Z"(%"struct.move_ctor::A"*)
}
namespace all_deleted {
@@ -85,7 +85,7 @@
// NEWABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*)
// OLDABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(i8*)
-// WIN64-LABEL: declare dso_local void @"\01?foo@all_deleted@@YAXUA@1@@Z"(%"struct.all_deleted::A"*)
+// WIN64-LABEL: declare dso_local void @"?foo@all_deleted@@YAXUA@1@@Z"(%"struct.all_deleted::A"*)
}
namespace implicitly_deleted {
@@ -107,8 +107,8 @@
// OLDABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(i8*)
// In MSVC 2013, the copy ctor is not deleted by a move assignment. In MSVC 2015, it is.
-// WIN64-18-LABEL: declare dso_local void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(i64
-// WIN64-19-LABEL: declare dso_local void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(%"struct.implicitly_deleted::A"*)
+// WIN64-18-LABEL: declare dso_local void @"?foo@implicitly_deleted@@YAXUA@1@@Z"(i64
+// WIN64-19-LABEL: declare dso_local void @"?foo@implicitly_deleted@@YAXUA@1@@Z"(%"struct.implicitly_deleted::A"*)
}
namespace one_deleted {
@@ -129,7 +129,7 @@
// NEWABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*)
// OLDABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(i8*)
-// WIN64-LABEL: declare dso_local void @"\01?foo@one_deleted@@YAXUA@1@@Z"(%"struct.one_deleted::A"*)
+// WIN64-LABEL: declare dso_local void @"?foo@one_deleted@@YAXUA@1@@Z"(%"struct.one_deleted::A"*)
}
namespace copy_defaulted {
@@ -149,7 +149,7 @@
// CHECK: call void @_ZN14copy_defaulted3fooENS_1AE(i8* %{{.*}})
// CHECK-LABEL: declare void @_ZN14copy_defaulted3fooENS_1AE(i8*)
-// WIN64-LABEL: declare dso_local void @"\01?foo@copy_defaulted@@YAXUA@1@@Z"(i64)
+// WIN64-LABEL: declare dso_local void @"?foo@copy_defaulted@@YAXUA@1@@Z"(i64)
}
namespace move_defaulted {
@@ -169,7 +169,7 @@
// CHECK: call void @_ZN14move_defaulted3fooENS_1AE(i8* %{{.*}})
// CHECK-LABEL: declare void @_ZN14move_defaulted3fooENS_1AE(i8*)
-// WIN64-LABEL: declare dso_local void @"\01?foo@move_defaulted@@YAXUA@1@@Z"(%"struct.move_defaulted::A"*)
+// WIN64-LABEL: declare dso_local void @"?foo@move_defaulted@@YAXUA@1@@Z"(%"struct.move_defaulted::A"*)
}
namespace trivial_defaulted {
@@ -188,7 +188,7 @@
// CHECK: call void @_ZN17trivial_defaulted3fooENS_1AE(i8* %{{.*}})
// CHECK-LABEL: declare void @_ZN17trivial_defaulted3fooENS_1AE(i8*)
-// WIN64-LABEL: declare dso_local void @"\01?foo@trivial_defaulted@@YAXUA@1@@Z"(i64)
+// WIN64-LABEL: declare dso_local void @"?foo@trivial_defaulted@@YAXUA@1@@Z"(i64)
}
namespace two_copy_ctors {
@@ -211,7 +211,7 @@
// NEWABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"*)
// OLDABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* byval
-// WIN64-LABEL: declare dso_local void @"\01?foo@two_copy_ctors@@YAXUB@1@@Z"(%"struct.two_copy_ctors::B"*)
+// WIN64-LABEL: declare dso_local void @"?foo@two_copy_ctors@@YAXUB@1@@Z"(%"struct.two_copy_ctors::B"*)
}
namespace definition_only {
@@ -223,7 +223,7 @@
void *foo(A a) { return a.p; }
// NEWABI-LABEL: define i8* @_ZN15definition_only3fooENS_1AE(%"struct.definition_only::A"*
// OLDABI-LABEL: define i8* @_ZN15definition_only3fooENS_1AE(i8*
-// WIN64-LABEL: define dso_local i8* @"\01?foo@definition_only@@YAPEAXUA@1@@Z"(%"struct.definition_only::A"*
+// WIN64-LABEL: define dso_local i8* @"?foo@definition_only@@YAPEAXUA@1@@Z"(%"struct.definition_only::A"*
}
namespace deleted_by_member {
@@ -239,7 +239,7 @@
void *foo(A a) { return a.b.p; }
// NEWABI-LABEL: define i8* @_ZN17deleted_by_member3fooENS_1AE(%"struct.deleted_by_member::A"*
// OLDABI-LABEL: define i8* @_ZN17deleted_by_member3fooENS_1AE(i8*
-// WIN64-LABEL: define dso_local i8* @"\01?foo@deleted_by_member@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member::A"*
+// WIN64-LABEL: define dso_local i8* @"?foo@deleted_by_member@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member::A"*
}
namespace deleted_by_base {
@@ -254,7 +254,7 @@
void *foo(A a) { return a.p; }
// NEWABI-LABEL: define i8* @_ZN15deleted_by_base3fooENS_1AE(%"struct.deleted_by_base::A"*
// OLDABI-LABEL: define i8* @_ZN15deleted_by_base3fooENS_1AE(i8*
-// WIN64-LABEL: define dso_local i8* @"\01?foo@deleted_by_base@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base::A"*
+// WIN64-LABEL: define dso_local i8* @"?foo@deleted_by_base@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base::A"*
}
namespace deleted_by_member_copy {
@@ -270,7 +270,7 @@
void *foo(A a) { return a.b.p; }
// NEWABI-LABEL: define i8* @_ZN22deleted_by_member_copy3fooENS_1AE(%"struct.deleted_by_member_copy::A"*
// OLDABI-LABEL: define i8* @_ZN22deleted_by_member_copy3fooENS_1AE(i8*
-// WIN64-LABEL: define dso_local i8* @"\01?foo@deleted_by_member_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member_copy::A"*
+// WIN64-LABEL: define dso_local i8* @"?foo@deleted_by_member_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member_copy::A"*
}
namespace deleted_by_base_copy {
@@ -285,7 +285,7 @@
void *foo(A a) { return a.p; }
// NEWABI-LABEL: define i8* @_ZN20deleted_by_base_copy3fooENS_1AE(%"struct.deleted_by_base_copy::A"*
// OLDABI-LABEL: define i8* @_ZN20deleted_by_base_copy3fooENS_1AE(i8*
-// WIN64-LABEL: define dso_local i8* @"\01?foo@deleted_by_base_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base_copy::A"*
+// WIN64-LABEL: define dso_local i8* @"?foo@deleted_by_base_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base_copy::A"*
}
namespace explicit_delete {
@@ -296,7 +296,7 @@
};
// NEWABI-LABEL: define i8* @_ZN15explicit_delete3fooENS_1AE(%"struct.explicit_delete::A"*
// OLDABI-LABEL: define i8* @_ZN15explicit_delete3fooENS_1AE(i8*
-// WIN64-LABEL: define dso_local i8* @"\01?foo@explicit_delete@@YAPEAXUA@1@@Z"(%"struct.explicit_delete::A"*
+// WIN64-LABEL: define dso_local i8* @"?foo@explicit_delete@@YAPEAXUA@1@@Z"(%"struct.explicit_delete::A"*
void *foo(A a) { return a.p; }
}
@@ -309,7 +309,7 @@
};
// NEWABI-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(%"struct.implicitly_deleted_copy_ctor::A"*
// OLDABI-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(i32*
-// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAAEAHUA@1@@Z"(%"struct.implicitly_deleted_copy_ctor::A"*
+// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAAEAHUA@1@@Z"(%"struct.implicitly_deleted_copy_ctor::A"*
int &foo(A a) { return a.ref; }
struct B {
@@ -319,7 +319,7 @@
};
int &foo(B b) { return b.ref; }
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1BE(i32*
-// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAAEAHUB@1@@Z"(i64
+// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAAEAHUB@1@@Z"(i64
struct X { X(const X&); };
struct Y { Y(const Y&) = default; };
@@ -332,7 +332,7 @@
};
int foo(C c) { return c.n; }
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1CE(%"union.implicitly_deleted_copy_ctor::C"*
-// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHTC@1@@Z"(%"union.implicitly_deleted_copy_ctor::C"*
+// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHTC@1@@Z"(%"union.implicitly_deleted_copy_ctor::C"*
struct D {
D &operator=(const D&);
@@ -344,7 +344,7 @@
};
int foo(D d) { return d.n; }
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1DE(%"struct.implicitly_deleted_copy_ctor::D"*
-// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHUD@1@@Z"(%"struct.implicitly_deleted_copy_ctor::D"*
+// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHUD@1@@Z"(%"struct.implicitly_deleted_copy_ctor::D"*
union E {
// Passed direct: has non-deleted trivial copy ctor.
@@ -354,7 +354,7 @@
};
int foo(E e) { return e.n; }
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1EE(i32
-// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHTE@1@@Z"(i32
+// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHTE@1@@Z"(i32
struct F {
// Passed direct: has non-deleted trivial copy ctor.
@@ -366,5 +366,5 @@
};
int foo(F f) { return f.n; }
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1FE(i32
-// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHUF@1@@Z"(i32
+// WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHUF@1@@Z"(i32
}
diff --git a/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp b/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp
index f63f9bf..8f41302 100644
--- a/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp
+++ b/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp
@@ -10,17 +10,17 @@
void vararg(...);
void test(X x) {
- // CHECK-LABEL: define dso_local void @"\01?test@@YAXUX@@@Z"
+ // CHECK-LABEL: define dso_local void @"?test@@YAXUX@@@Z"
// X86: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.X }>
- // X86: call void (<{ %struct.X }>*, ...) bitcast (void (...)* @"\01?vararg@@YAXZZ" to void (<{ %struct.X }>*, ...)*)(<{ %struct.X }>* inalloca %[[argmem]])
+ // X86: call void (<{ %struct.X }>*, ...) bitcast (void (...)* @"?vararg@@YAXZZ" to void (<{ %struct.X }>*, ...)*)(<{ %struct.X }>* inalloca %[[argmem]])
// X64: alloca %struct.X
// X64: %[[agg:[^ ]*]] = alloca %struct.X
// X64: %[[valptr:[^ ]*]] = getelementptr inbounds %struct.X, %struct.X* %[[agg]], i32 0, i32 0
// X64: %[[val:[^ ]*]] = load i32, i32* %[[valptr]]
- // X64: call void (...) @"\01?vararg@@YAXZZ"(i32 %[[val]])
+ // X64: call void (...) @"?vararg@@YAXZZ"(i32 %[[val]])
// CHECK-NOT: llvm.trap
vararg(x);
diff --git a/test/CodeGenCXX/virtual-base-cast.cpp b/test/CodeGenCXX/virtual-base-cast.cpp
index b2f2b4f..d3a7999 100644
--- a/test/CodeGenCXX/virtual-base-cast.cpp
+++ b/test/CodeGenCXX/virtual-base-cast.cpp
@@ -18,7 +18,7 @@
// CHECK: load i32, i32* [[CASTVBASEOFFSETPTRA]]
// CHECK: }
-// MSVC: @"\01?a@@YAPAUA@@XZ"() [[NUW:#[0-9]+]] {
+// MSVC: @"?a@@YAPAUA@@XZ"() [[NUW:#[0-9]+]] {
// MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* {{.*}}, i32 0
// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
// MSVC: %[[vbtable:.*]] = load i32*, i32** %[[vbptr]]
@@ -35,7 +35,7 @@
// CHECK: }
// Same as 'a' except we use a different vbtable offset.
-// MSVC: @"\01?b@@YAPAUB@@XZ"() [[NUW:#[0-9]+]] {
+// MSVC: @"?b@@YAPAUB@@XZ"() [[NUW:#[0-9]+]] {
// MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* {{.*}}, i32 0
// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
// MSVC: %[[vbtable:.*]] = load i32*, i32** %[[vbptr]]
@@ -54,7 +54,7 @@
// CHECK: }
// Same as 'a' except we use a different vbtable offset.
-// MSVC: @"\01?c@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] {
+// MSVC: @"?c@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] {
// MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* {{.*}}, i32 0
// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
// MSVC: %[[vbtable:.*]] = load i32*, i32** %[[vbptr]]
@@ -73,7 +73,7 @@
// Same as 'c' except the vbptr offset is 4, changing the initial GEP and the
// final add.
-// MSVC: @"\01?d@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] {
+// MSVC: @"?d@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] {
// MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* {{.*}}, i32 4
// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
// MSVC: %[[vbtable:.*]] = load i32*, i32** %[[vbptr]]
diff --git a/test/CodeGenCXX/vtable-assume-load.cpp b/test/CodeGenCXX/vtable-assume-load.cpp
index 9ca77ed..d1c2350 100644
--- a/test/CodeGenCXX/vtable-assume-load.cpp
+++ b/test/CodeGenCXX/vtable-assume-load.cpp
@@ -163,8 +163,8 @@
void g(S &s) { s.foo(); }
// if struct has novtable specifier, then we can't generate assumes
-// CHECK-MS-LABEL: define dso_local void @"\01?test@testMS@@YAXXZ"()
-// CHECK-MS: call x86_thiscallcc %"struct.testMS::S"* @"\01??0S@testMS@@QAE@XZ"(
+// CHECK-MS-LABEL: define dso_local void @"?test@testMS@@YAXXZ"()
+// CHECK-MS: call x86_thiscallcc %"struct.testMS::S"* @"??0S@testMS@@QAE@XZ"(
// CHECK-MS-NOT: @llvm.assume
// CHECK-MS-LABEL: {{^}}}
diff --git a/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp b/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp
index c2f2a07..20ba4bc 100644
--- a/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp
+++ b/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp
@@ -10,8 +10,8 @@
extern template class t<char>;
template class __declspec(dllexport) t<char>;
-// CHECK-MS: dllexport {{.*}} @"\01??4?$t@D@@QAEAAV0@ABV0@@Z"
-// CHECK-MS: dllexport {{.*}} @"\01??4?$s@D@@QAEAAU0@ABU0@@Z"
+// CHECK-MS: dllexport {{.*}} @"??4?$t@D@@QAEAAV0@ABV0@@Z"
+// CHECK-MS: dllexport {{.*}} @"??4?$s@D@@QAEAAU0@ABU0@@Z"
// CHECK-IA: dllexport {{.*}} @_ZN1tIcEaSERKS0_
// CHECK-IA: dllexport {{.*}} @_ZN1sIcEaSERKS0_
diff --git a/test/CodeGenCXX/windows-itanium-exceptions.cpp b/test/CodeGenCXX/windows-itanium-exceptions.cpp
index b2c8707..1bca4e8 100644
--- a/test/CodeGenCXX/windows-itanium-exceptions.cpp
+++ b/test/CodeGenCXX/windows-itanium-exceptions.cpp
@@ -10,7 +10,7 @@
try { except(); } catch (...) { }
}
-// CHECK: @_ZTIi = external constant i8*
+// CHECK: @_ZTIi = external dso_local constant i8*
// CHECK: define {{.*}}void @_Z6exceptv() {{.*}} {
// CHECK: %exception = call {{.*}}i8* @__cxa_allocate_exception(i32 4)
diff --git a/test/CodeGenCoroutines/coro-eh-cleanup.cpp b/test/CodeGenCoroutines/coro-eh-cleanup.cpp
index 5a3ecd1..9801151 100644
--- a/test/CodeGenCoroutines/coro-eh-cleanup.cpp
+++ b/test/CodeGenCoroutines/coro-eh-cleanup.cpp
@@ -45,18 +45,18 @@
co_return;
}
-// CHECK: @"\01?f@@YA?AUcoro_t@@XZ"(
-// CHECK: invoke void @"\01?may_throw@@YAXXZ"()
+// CHECK: @"?f@@YA?AUcoro_t@@XZ"(
+// CHECK: invoke void @"?may_throw@@YAXXZ"()
// CHECK: to label %[[CONT:.+]] unwind label %[[EHCLEANUP:.+]]
// CHECK: [[EHCLEANUP]]:
// CHECK: %[[INNERPAD:.+]] = cleanuppad within none []
-// CHECK: call void @"\01??_DCleanup@@QEAAXXZ"(
+// CHECK: call void @"??1Cleanup@@QEAA@XZ"(
// CHECK: cleanupret from %{{.+}} unwind label %[[CATCHDISPATCH:.+]]
// CHECK: [[CATCHDISPATCH]]:
// CHECK: catchswitch within none [label %[[CATCHPAD:.+]]] unwind label %[[COROENDBB:.+]]
// CHECK: [[CATCHPAD]]:
-// CHECK: call void @"\01?unhandled_exception@promise_type@coro_t@@QEAAXXZ"
+// CHECK: call void @"?unhandled_exception@promise_type@coro_t@@QEAAXXZ"
// CHECK: [[COROENDBB]]:
// CHECK-NEXT: %[[CLPAD:.+]] = cleanuppad within none
diff --git a/test/CodeGenCoroutines/coro-promise-dtor.cpp b/test/CodeGenCoroutines/coro-promise-dtor.cpp
index 5cc4720..bc190c9 100644
--- a/test/CodeGenCoroutines/coro-promise-dtor.cpp
+++ b/test/CodeGenCoroutines/coro-promise-dtor.cpp
@@ -28,12 +28,12 @@
co_return;
}
-// CHECK-LABEL: define dso_local void @"\01?f@@YA?AUcoro_t@@XZ"(
+// CHECK-LABEL: define dso_local void @"?f@@YA?AUcoro_t@@XZ"(
// CHECK: %gro.active = alloca i1
// CHECK: store i1 false, i1* %gro.active
-// CHECK: invoke %"struct.coro_t::promise_type"* @"\01??0promise_type@coro_t@@QEAA@XZ"(
-// CHECK: invoke void @"\01?get_return_object@promise_type@coro_t@@QEAA?AU2@XZ"(
+// CHECK: invoke %"struct.coro_t::promise_type"* @"??0promise_type@coro_t@@QEAA@XZ"(
+// CHECK: invoke void @"?get_return_object@promise_type@coro_t@@QEAA?AU2@XZ"(
// CHECK: store i1 true, i1* %gro.active
// CHECK: %[[IS_ACTIVE:.+]] = load i1, i1* %gro.active
@@ -44,4 +44,4 @@
// CHECK: br i1 %[[NRVO]], label %{{.+}}, label %[[DTOR:.+]]
// CHECK: [[DTOR]]:
-// CHECK: call void @"\01??_Dcoro_t@@QEAAXXZ"(
+// CHECK: call void @"??1coro_t@@QEAA@XZ"(
diff --git a/test/CodeGenCoroutines/coro-unhandled-exception.cpp b/test/CodeGenCoroutines/coro-unhandled-exception.cpp
index e26a518..4ea00a5 100644
--- a/test/CodeGenCoroutines/coro-unhandled-exception.cpp
+++ b/test/CodeGenCoroutines/coro-unhandled-exception.cpp
@@ -32,25 +32,25 @@
co_return;
}
-// CHECK: @"\01?f@@YA?AUcoro_t@@XZ"(
-// CHECK: invoke void @"\01?may_throw@@YAXXZ"()
+// CHECK: @"?f@@YA?AUcoro_t@@XZ"(
+// CHECK: invoke void @"?may_throw@@YAXXZ"()
// CHECK: to label %{{.+}} unwind label %[[EHCLEANUP:.+]]
// CHECK: [[EHCLEANUP]]:
// CHECK: %[[INNERPAD:.+]] = cleanuppad within none []
-// CHECK: call void @"\01??_DCleanup@@QEAAXXZ"(
+// CHECK: call void @"??1Cleanup@@QEAA@XZ"(
// CHECK: cleanupret from %[[INNERPAD]] unwind label %[[CATCHSW:.+]]
// CHECK: [[CATCHSW]]:
// CHECK: %[[CATCHSWTOK:.+]] = catchswitch within none [label %[[CATCH:.+]]] unwind label
// CHECK: [[CATCH]]:
// CHECK: %[[CATCHTOK:.+]] = catchpad within [[CATCHSWTOK:.+]]
-// CHECK: call void @"\01?unhandled_exception@promise_type@coro_t@@QEAAXXZ"
+// CHECK: call void @"?unhandled_exception@promise_type@coro_t@@QEAAXXZ"
// CHECK: catchret from %[[CATCHTOK]] to label %[[CATCHRETDEST:.+]]
// CHECK: [[CATCHRETDEST]]:
// CHECK-NEXT: br label %[[TRYCONT:.+]]
// CHECK: [[TRYCONT]]:
// CHECK-NEXT: br label %[[COROFIN:.+]]
// CHECK: [[COROFIN]]:
-// CHECK-NEXT: invoke void @"\01?final_suspend@promise_type@coro_t@@QEAA?AUsuspend_never@coroutines_v1@experimental@std@@XZ"(
+// CHECK-NEXT: invoke void @"?final_suspend@promise_type@coro_t@@QEAA?AUsuspend_never@coroutines_v1@experimental@std@@XZ"(
// CHECK-LPAD: @_Z1fv(
// CHECK-LPAD: invoke void @_Z9may_throwv()
diff --git a/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp b/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
index 1921c06..26e3794 100644
--- a/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
+++ b/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
@@ -17,9 +17,9 @@
extern "C" void f() {
A a;
B b;
- // CHECK: call void @"\01??__LA@@QEAA?AUno_suspend@@XZ"(
+ // CHECK: call void @"??__LA@@QEAA?AUno_suspend@@XZ"(
a.operator co_await();
- // CHECK-NEXT: call i8 @"\01??__L@YA?AUno_suspend@@AEBUB@@@Z"(
+ // CHECK-NEXT: call i8 @"??__L@YA?AUno_suspend@@AEBUB@@@Z"(
operator co_await(b);
}
diff --git a/test/CodeGenObjC/Inputs/strong_in_union.h b/test/CodeGenObjC/Inputs/strong_in_union.h
new file mode 100644
index 0000000..abe4549
--- /dev/null
+++ b/test/CodeGenObjC/Inputs/strong_in_union.h
@@ -0,0 +1,10 @@
+#ifndef STRONG_IN_UNION_H
+#define STRONG_IN_UNION_H
+#pragma clang system_header
+
+typedef union {
+ id f0;
+ int *f1;
+} U;
+
+#endif // STRONG_IN_UNION_H
diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m
index 7871369..3243952 100644
--- a/test/CodeGenObjC/arc.m
+++ b/test/CodeGenObjC/arc.m
@@ -1526,6 +1526,37 @@
};
}
+// Be sure that we emit lifetime intrinsics only after dtors
+struct AggDtor {
+ char cs[40];
+ id x;
+};
+
+struct AggDtor getAggDtor(void);
+
+// CHECK-LABEL: define void @test71
+void test71(void) {
+ // FIXME: It would be nice if the __destructor_8_s40 for the first call (and
+ // the following lifetime.end) came before the second call.
+ //
+ // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP1:[^ ]+]] to i8*
+ // CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* %[[T]])
+ // CHECK: call void @getAggDtor(%struct.AggDtor* sret %[[TMP1]])
+ // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP2:[^ ]+]] to i8*
+ // CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* %[[T]])
+ // CHECK: call void @getAggDtor(%struct.AggDtor* sret %[[TMP2]])
+ // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP2]] to i8**
+ // CHECK: call void @__destructor_8_s40(i8** %[[T]])
+ // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP2:[^ ]+]] to i8*
+ // CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* %[[T]])
+ // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP1]] to i8**
+ // CHECK: call void @__destructor_8_s40(i8** %[[T]])
+ // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP1:[^ ]+]] to i8*
+ // CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* %[[T]])
+ getAggDtor();
+ getAggDtor();
+}
+
// ARC-ALIEN: attributes [[NLB]] = { nonlazybind }
// ARC-NATIVE: attributes [[NLB]] = { nonlazybind }
// CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/CodeGenObjC/nontrivial-c-struct-exception.m b/test/CodeGenObjC/nontrivial-c-struct-exception.m
index a926a6d..7db53bb 100644
--- a/test/CodeGenObjC/nontrivial-c-struct-exception.m
+++ b/test/CodeGenObjC/nontrivial-c-struct-exception.m
@@ -1,12 +1,18 @@
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -fobjc-exceptions -fexceptions -fobjc-arc-exceptions -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -fobjc-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
// CHECK: %[[STRUCT_STRONG:.*]] = type { i32, i8* }
+// CHECK: %[[STRUCT_WEAK:.*]] = type { i32, i8* }
typedef struct {
int i;
id f1;
} Strong;
+typedef struct {
+ int i;
+ __weak id f1;
+} Weak;
+
// CHECK: define void @testStrongException()
// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8
// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_STRONG]], align 8
@@ -31,3 +37,26 @@
void testStrongException(void) {
calleeStrong(genStrong(), genStrong());
}
+
+// CHECK: define void @testWeakException()
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]], align 8
+// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_WEAK]], align 8
+// CHECK: call void @genWeak(%[[STRUCT_WEAK]]* sret %[[AGG_TMP]])
+// CHECK: invoke void @genWeak(%[[STRUCT_WEAK]]* sret %[[AGG_TMP1]])
+
+// CHECK: call void @calleeWeak(%[[STRUCT_WEAK]]* %[[AGG_TMP]], %[[STRUCT_WEAK]]* %[[AGG_TMP1]])
+// CHECK: ret void
+
+// CHECK: landingpad { i8*, i32 }
+// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_TMP]] to i8**
+// CHECK: call void @__destructor_8_w8(i8** %[[V3]])
+// CHECK: br label
+
+// CHECK: resume
+
+Weak genWeak(void);
+void calleeWeak(Weak, Weak);
+
+void testWeakException(void) {
+ calleeWeak(genWeak(), genWeak());
+}
diff --git a/test/CodeGenObjC/objc-container-subscripting-1.m b/test/CodeGenObjC/objc-container-subscripting-1.m
index f9322fa..18f2f8c 100644
--- a/test/CodeGenObjC/objc-container-subscripting-1.m
+++ b/test/CodeGenObjC/objc-container-subscripting-1.m
@@ -25,8 +25,8 @@
// CHECK-NEXT: store i8* [[CALL]], i8** [[OLDOBJ:%.*]], align 8
val = (array[10] = oldObject);
-// CHECK: [[THREE:%.*]] = load {{%.*}} [[array:%.*]], align 8
-// CHECK-NEXT: [[FOUR:%.*]] = load i8*, i8** [[oldObject:%.*]], align 8
+// CHECK: [[FOUR:%.*]] = load i8*, i8** [[oldObject:%.*]], align 8
+// CHECK-NEXT: [[THREE:%.*]] = load {{%.*}} [[array:%.*]], align 8
// CHECK-NEXT: [[FIVE:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.2
// CHECK-NEXT: [[SIX:%.*]] = bitcast {{%.*}} [[THREE]] to i8*
// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i32)*)(i8* [[SIX]], i8* [[FIVE]], i8* [[FOUR]], i32 10)
@@ -45,9 +45,9 @@
val = (dictionary[key] = newObject);
-// CHECK: [[TWELVE:%.*]] = load {{%.*}} [[DICTIONARY]], align 8
+// CHECK: [[FOURTEEN:%.*]] = load i8*, i8** [[NEWOBJECT:%.*]], align 8
+// CHECK-NEXT: [[TWELVE:%.*]] = load {{%.*}} [[DICTIONARY]], align 8
// CHECK-NEXT: [[THIRTEEN:%.*]] = load i8*, i8** [[KEY]], align 8
-// CHECK-NEXT: [[FOURTEEN:%.*]] = load i8*, i8** [[NEWOBJECT:%.*]], align 8
// CHECK-NEXT: [[SIXTEEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.6
// CHECK-NEXT: [[SEVENTEEN:%.*]] = bitcast {{%.*}} [[TWELVE]] to i8*
// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i8*)*)(i8* [[SEVENTEEN]], i8* [[SIXTEEN]], i8* [[FOURTEEN]], i8* [[THIRTEEN]])
diff --git a/test/CodeGenObjC/objc-non-trivial-struct-nrvo.m b/test/CodeGenObjC/objc-non-trivial-struct-nrvo.m
new file mode 100644
index 0000000..798aba2
--- /dev/null
+++ b/test/CodeGenObjC/objc-non-trivial-struct-nrvo.m
@@ -0,0 +1,134 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck %s
+
+// CHECK: %[[STRUCT_TRIVIAL:.*]] = type { i32 }
+// CHECK: %[[STRUCT_TRIVIALBIG:.*]] = type { [64 x i32] }
+// CHECK: %[[STRUCT_STRONG:.*]] = type { i8* }
+// CHECK: %[[STRUCT_WEAK:.*]] = type { i8* }
+
+typedef struct {
+ int x;
+} Trivial;
+
+typedef struct {
+ int x[64];
+} TrivialBig;
+
+typedef struct {
+ id x;
+} Strong;
+
+typedef struct {
+ __weak id x;
+} Weak;
+
+// CHECK: define i32 @testTrivial()
+// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL]], align 4
+// CHECK-NEXT: call void @func0(%[[STRUCT_TRIVIAL]]* %[[RETVAL]])
+// CHECK-NOT: memcpy
+// CHECK: ret i32 %
+
+void func0(Trivial *);
+
+Trivial testTrivial(void) {
+ Trivial a;
+ func0(&a);
+ return a;
+}
+
+void func1(TrivialBig *);
+
+// CHECK: define void @testTrivialBig(%[[STRUCT_TRIVIALBIG]]* noalias sret %[[AGG_RESULT:.*]])
+// CHECK-NOT: alloca
+// CHECK: call void @func1(%[[STRUCT_TRIVIALBIG]]* %[[AGG_RESULT]])
+// CHECK-NEXT: ret void
+
+TrivialBig testTrivialBig(void) {
+ TrivialBig a;
+ func1(&a);
+ return a;
+}
+
+// CHECK: define i8* @testStrong()
+// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8
+// CHECK: %[[NRVO:.*]] = alloca i1, align 1
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONG]]* %[[RETVAL]] to i8**
+// CHECK: call void @__default_constructor_8_s0(i8** %[[V0]])
+// CHECK: store i1 true, i1* %[[NRVO]], align 1
+// CHECK: %[[NRVO_VAL:.*]] = load i1, i1* %[[NRVO]], align 1
+// CHECK: br i1 %[[NRVO_VAL]],
+
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONG]]* %[[RETVAL]] to i8**
+// CHECK: call void @__destructor_8_s0(i8** %[[V1]])
+// CHECK: br
+
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0
+// CHECK: %[[V2:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8
+// CHECK: ret i8* %[[V2]]
+
+Strong testStrong(void) {
+ Strong a;
+ return a;
+}
+
+// CHECK: define void @testWeak(%[[STRUCT_WEAK]]* noalias sret %[[AGG_RESULT:.*]])
+// CHECK: %[[NRVO:.*]] = alloca i1, align 1
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// CHECK: call void @__default_constructor_8_w0(i8** %[[V0]])
+// CHECK: store i1 true, i1* %[[NRVO]], align 1
+// CHECK: %[[NRVO_VAL:.*]] = load i1, i1* %[[NRVO]], align 1
+// CHECK: br i1 %[[NRVO_VAL]],
+
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// CHECK: call void @__destructor_8_w0(i8** %[[V1]])
+// CHECK: br
+
+// CHECK-NOT: call
+// CHECK: ret void
+
+Weak testWeak(void) {
+ Weak a;
+ return a;
+}
+
+// CHECK: define void @testWeak2(
+// CHECK: call void @__default_constructor_8_w0(
+// CHECK: call void @__default_constructor_8_w0(
+// CHECK: call void @__copy_constructor_8_8_w0(
+// CHECK: call void @__copy_constructor_8_8_w0(
+// CHECK: call void @__destructor_8_w0(
+// CHECK: call void @__destructor_8_w0(
+
+Weak testWeak2(int c) {
+ Weak a, b;
+ if (c)
+ return a;
+ else
+ return b;
+}
+
+// CHECK: define internal void @"\01-[C1 foo1]"(%[[STRUCT_WEAK]]* noalias sret %[[AGG_RESULT:.*]], %{{.*}}* %{{.*}}, i8* %{{.*}})
+// CHECK: %[[NRVO:.*]] = alloca i1, align 1
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// CHECK: call void @__default_constructor_8_w0(i8** %[[V0]])
+// CHECK: store i1 true, i1* %[[NRVO]], align 1
+// CHECK: %[[NRVO_VAL:.*]] = load i1, i1* %[[NRVO]], align 1
+// CHECK: br i1 %[[NRVO_VAL]],
+
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// CHECK: call void @__destructor_8_w0(i8** %[[V1]])
+// CHECK: br
+
+// CHECK-NOT: call
+// CHECK: ret void
+
+__attribute__((objc_root_class))
+@interface C1
+- (Weak)foo1;
+@end
+
+@implementation C1
+- (Weak)foo1 {
+ Weak a;
+ return a;
+}
+@end
diff --git a/test/CodeGenObjC/personality.m b/test/CodeGenObjC/personality.m
new file mode 100644
index 0000000..4176394
--- /dev/null
+++ b/test/CodeGenObjC/personality.m
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-MINGW-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-MINGW-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-MINGW-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ
+
+void g(void);
+
+// CHECK-MACOSX-FRAGILE: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+// CHECK-NS: personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
+// CHECK-GNUSTEP-1_7: personality i8* bitcast (i32 (...)* @__gnustep_objc_personality_v0 to i8*)
+// CHECK-GNUSTEP: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*)
+// CHECK-GCC: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*)
+// CHECK-GCC-SEH: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_seh0 to i8*)
+// CHECK-GCC-SJLJ: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*)
+// CHECK-OBJFW: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*)
+// CHECK-OBJFW-SEH: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_seh0 to i8*)
+// CHECK-OBJFW-SJLJ: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*)
+
+// CHECK-WIN-MACOSX-FRAGILE: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+// CHECK-WIN-MACOSX-FRAGILE-DWARF: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+// CHECK-WIN-MACOSX-FRAGILE-SEH: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+// CHECK-WIN-MACOSX-FRAGILE-SJLJ: personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*)
+// CHECK-WIN-NS: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+
+// CHECK-MACOSX-FRAGILE-MINGW-DWARF: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+// CHECK-MACOSX-FRAGILE-MINGW-SEH: personality i8* bitcast (i32 (...)* @__gcc_personality_seh0 to i8*)
+// CHECK-MACOSX-FRAGILE-MINGW-SJLJ: personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*)
+
+void f(void) {
+ @try {
+ g();
+ } @catch (...) {
+ }
+}
+
+#if defined(__SEH_EXCEPTIONS__)
+// CHECK-WIN-SEH-X86: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
+// CHECK-WIN-SEH-X64: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+
+void h(void) {
+ __try {
+ i();
+ } __finally {
+ }
+}
+#endif
+
diff --git a/test/CodeGenObjC/strong-in-c-struct.m b/test/CodeGenObjC/strong-in-c-struct.m
index c48c663..6310943 100644
--- a/test/CodeGenObjC/strong-in-c-struct.m
+++ b/test/CodeGenObjC/strong-in-c-struct.m
@@ -1,4 +1,11 @@
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - -DUSESTRUCT -I %S/Inputs %s | FileCheck %s
+
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-pch -I %S/Inputs -o %t %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -include-pch %t -emit-llvm -o - -DUSESTRUCT -I %S/Inputs %s | FileCheck %s
+
+#ifndef HEADER
+#define HEADER
+#include "strong_in_union.h"
typedef void (^BlockTy)(void);
@@ -63,6 +70,10 @@
volatile char i6;
} Bitfield1;
+#endif
+
+#ifdef USESTRUCT
+
StrongSmall getStrongSmall(void);
StrongOuter getStrongOuter(void);
void calleeStrongSmall(StrongSmall);
@@ -520,3 +531,13 @@
void test_copy_constructor_Bitfield1(Bitfield1 *a) {
Bitfield1 t = *a;
}
+
+// CHECK: define void @test_strong_in_union()
+// CHECK: alloca %{{.*}}
+// CHECK-NEXT: ret void
+
+void test_strong_in_union() {
+ U t;
+}
+
+#endif /* USESTRUCT */
diff --git a/test/CodeGenObjC/weak-in-c-struct.m b/test/CodeGenObjC/weak-in-c-struct.m
new file mode 100644
index 0000000..b0f4c08
--- /dev/null
+++ b/test/CodeGenObjC/weak-in-c-struct.m
@@ -0,0 +1,193 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - %s | FileCheck -check-prefix=ARM64 -check-prefix=COMMON %s
+// RUN: %clang_cc1 -triple thumbv7-apple-ios10 -fobjc-arc -fblocks -fobjc-runtime=ios-10.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13 -fobjc-arc -fblocks -fobjc-runtime=macosx-10.13.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s
+// RUN: %clang_cc1 -triple i386-apple-macosx10.13.0 -fobjc-arc -fblocks -fobjc-runtime=macosx-fragile-10.13.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s
+
+typedef void (^BlockTy)(void);
+
+// COMMON: %[[STRUCT_WEAK:.*]] = type { i32, i8* }
+
+typedef struct {
+ int f0;
+ __weak id f1;
+} Weak;
+
+Weak getWeak(void);
+void calleeWeak(Weak);
+
+// ARM64: define void @test_constructor_destructor_Weak()
+// ARM64: %[[T:.*]] = alloca %[[STRUCT_WEAK]], align 8
+// ARM64: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[T]] to i8**
+// ARM64: call void @__default_constructor_8_w8(i8** %[[V0]])
+// ARM64: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[T]] to i8**
+// ARM64: call void @__destructor_8_w8(i8** %[[V1]])
+// ARM64: ret void
+
+// ARM64: define linkonce_odr hidden void @__default_constructor_8_w8(i8** %[[DST:.*]])
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V1]] = bitcast i8** %[[V0]] to i8*
+// ARM64: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8
+// ARM64: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
+// ARM64: %[[V4:.*]] = bitcast i8** %[[V3]] to i8*
+// ARM64: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V4]], i8 0, i64 8, i1 false)
+
+// ARM64: define linkonce_odr hidden void @__destructor_8_w8(i8** %[[DST:.*]])
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
+// ARM64: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8
+// ARM64: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
+// ARM64: call void @objc_destroyWeak(i8** %[[V3]])
+
+void test_constructor_destructor_Weak(void) {
+ Weak t;
+}
+
+// ARM64: define void @test_copy_constructor_Weak(%[[STRUCT_WEAK]]* %{{.*}})
+// ARM64: call void @__copy_constructor_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}})
+// ARM64: call void @__destructor_8_w8(i8** %{{.*}})
+
+// ARM64: define linkonce_odr hidden void @__copy_constructor_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32*
+// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32*
+// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8
+// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8
+// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8*
+// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8
+// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
+// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*
+// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8
+// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**
+// ARM64: call void @objc_copyWeak(i8** %[[V7]], i8** %[[V10]])
+
+void test_copy_constructor_Weak(Weak *s) {
+ Weak t = *s;
+}
+
+// ARM64: define void @test_copy_assignment_Weak(%[[STRUCT_WEAK]]* %{{.*}}, %[[STRUCT_WEAK]]* %{{.*}})
+// ARM64: call void @__copy_assignment_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}})
+
+// ARM64: define linkonce_odr hidden void @__copy_assignment_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32*
+// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32*
+// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8
+// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8
+// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8*
+// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8
+// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
+// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*
+// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8
+// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**
+// ARM64: %[[V11:.*]] = call i8* @objc_loadWeakRetained(i8** %[[V10]])
+// ARM64: %[[V12:.*]] = call i8* @objc_storeWeak(i8** %[[V7]], i8* %[[V11]])
+// ARM64: call void @objc_release(i8* %[[V11]])
+
+void test_copy_assignment_Weak(Weak *d, Weak *s) {
+ *d = *s;
+}
+
+// ARM64: define internal void @__Block_byref_object_copy_(i8*, i8*)
+// ARM64: call void @__move_constructor_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}})
+
+// ARM64: define linkonce_odr hidden void @__move_constructor_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32*
+// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32*
+// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8
+// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8
+// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8*
+// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8
+// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
+// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*
+// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8
+// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**
+// ARM64: call void @objc_moveWeak(i8** %[[V7]], i8** %[[V10]])
+
+void test_move_constructor_Weak(void) {
+ __block Weak t;
+ BlockTy b = ^{ (void)t; };
+}
+
+// ARM64: define void @test_move_assignment_Weak(%[[STRUCT_WEAK]]* %{{.*}})
+// ARM64: call void @__move_assignment_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}})
+
+// ARM64: define linkonce_odr hidden void @__move_assignment_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32*
+// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32*
+// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8
+// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8
+// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8*
+// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8
+// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
+// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*
+// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8
+// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**
+// ARM64: %[[V11:.*]] = call i8* @objc_loadWeakRetained(i8** %[[V10]])
+// ARM64: %[[V12:.*]] = call i8* @objc_storeWeak(i8** %[[V7]], i8* %[[V11]])
+// ARM64: call void @objc_destroyWeak(i8** %[[V10]])
+// ARM64: call void @objc_release(i8* %[[V11]])
+
+void test_move_assignment_Weak(Weak *p) {
+ *p = getWeak();
+}
+
+// COMMON: define void @test_parameter_Weak(%[[STRUCT_WEAK]]* %[[A:.*]])
+// COMMON: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[A]] to i8**
+// COMMON: call void @__destructor_{{.*}}(i8** %[[V0]])
+
+void test_parameter_Weak(Weak a) {
+}
+
+// COMMON: define void @test_argument_Weak(%[[STRUCT_WEAK]]* %[[A:.*]])
+// COMMON: %[[A_ADDR:.*]] = alloca %[[STRUCT_WEAK]]*
+// COMMON: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]]
+// COMMON: store %[[STRUCT_WEAK]]* %[[A]], %[[STRUCT_WEAK]]** %[[A_ADDR]]
+// COMMON: %[[V0:.*]] = load %[[STRUCT_WEAK]]*, %[[STRUCT_WEAK]]** %[[A_ADDR]]
+// COMMON: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_TMP]] to i8**
+// COMMON: %[[V2:.*]] = bitcast %[[STRUCT_WEAK]]* %[[V0]] to i8**
+// COMMON: call void @__copy_constructor_{{.*}}(i8** %[[V1]], i8** %[[V2]])
+// COMMON: call void @calleeWeak(%[[STRUCT_WEAK]]* %[[AGG_TMP]])
+// COMMON-NEXT: ret
+
+void test_argument_Weak(Weak *a) {
+ calleeWeak(*a);
+}
+
+// COMMON: define void @test_return_Weak(%[[STRUCT_WEAK]]* noalias sret %[[AGG_RESULT:.*]], %[[STRUCT_WEAK]]* %[[A:.*]])
+// COMMON: %[[A_ADDR:.*]] = alloca %[[STRUCT_WEAK]]*
+// COMMON: store %[[STRUCT_WEAK]]* %[[A]], %[[STRUCT_WEAK]]** %[[A_ADDR]]
+// COMMON: %[[V0:.*]] = load %[[STRUCT_WEAK]]*, %[[STRUCT_WEAK]]** %[[A_ADDR]]
+// COMMON: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
+// COMMON: %[[V2:.*]] = bitcast %[[STRUCT_WEAK]]* %[[V0]] to i8**
+// COMMON: call void @__copy_constructor_{{.*}}(i8** %[[V1]], i8** %[[V2]])
+// COMMON: ret void
+
+Weak test_return_Weak(Weak *a) {
+ return *a;
+}
diff --git a/test/CodeGenObjCXX/arc-marker-funclet.mm b/test/CodeGenObjCXX/arc-marker-funclet.mm
new file mode 100644
index 0000000..900c278
--- /dev/null
+++ b/test/CodeGenObjCXX/arc-marker-funclet.mm
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fobjc-runtime=ios-6.0 -fobjc-arc \
+// RUN: -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s
+
+id f();
+void g() {
+ try {
+ f();
+ } catch (...) {
+ f();
+ }
+}
+
+// CHECK: call i8* @"?f@@YAPAUobjc_object@@XZ"() [ "funclet"(token %1) ]
+// CHECK-NEXT: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ]
+
+// The corresponding f() call was invoked from the entry basic block.
+// CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""(){{$}}
diff --git a/test/CodeGenObjCXX/arc-special-member-functions.mm b/test/CodeGenObjCXX/arc-special-member-functions.mm
index af161dd..278c779 100644
--- a/test/CodeGenObjCXX/arc-special-member-functions.mm
+++ b/test/CodeGenObjCXX/arc-special-member-functions.mm
@@ -31,6 +31,8 @@
void test_ObjCMember_copy_assign(ObjCMember m1, ObjCMember m2) {
// CHECK: {{call.*_ZN10ObjCMemberaSERKS_}}
m1 = m2;
+ // CHECK-NEXT: call void @_ZN10ObjCMemberD1Ev(
+ // CHECK-NEXT: call void @_ZN10ObjCMemberD1Ev(
// CHECK-NEXT: ret void
}
@@ -58,6 +60,8 @@
void test_ObjCArrayMember_copy_assign(ObjCArrayMember m1, ObjCArrayMember m2) {
// CHECK: {{call.*@_ZN15ObjCArrayMemberaSERKS_}}
m1 = m2;
+ // CHECK-NEXT: call void @_ZN15ObjCArrayMemberD1Ev(
+ // CHECK-NEXT: call void @_ZN15ObjCArrayMemberD1Ev(
// CHECK-NEXT: ret void
}
@@ -79,7 +83,8 @@
void test_ObjCBlockMember_copy_construct_destruct(ObjCBlockMember m1) {
// CHECK: call void @_ZN15ObjCBlockMemberC1ERKS_
ObjCBlockMember m2 = m1;
- // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev
+ // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(
+ // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(
// CHECK-NEXT: ret void
}
@@ -87,6 +92,8 @@
void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) {
// CHECK: {{call.*_ZN15ObjCBlockMemberaSERKS_}}
m1 = m2;
+ // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(
+ // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(
// CHECK-NEXT: ret void
}
diff --git a/test/CodeGenObjCXX/debug-info-line.mm b/test/CodeGenObjCXX/debug-info-line.mm
index 98ec2ce..7cdb4d2 100644
--- a/test/CodeGenObjCXX/debug-info-line.mm
+++ b/test/CodeGenObjCXX/debug-info-line.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -debug-info-kind=line-tables-only -fblocks -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-gnu -fcxx-exceptions -fexceptions -debug-info-kind=line-tables-only -fblocks -emit-llvm %s -o - | FileCheck %s
void fn();
diff --git a/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm b/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
index 45a8f63..910a7db 100644
--- a/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
+++ b/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
@@ -9,12 +9,12 @@
// Verify that we destruct things from left to right in the MS C++ ABI: a, b, c, d.
//
-// CHECK-LABEL: define dso_local void @"\01?test_arc_order@@YAXUA@@PAUobjc_object@@01@Z"
+// CHECK-LABEL: define dso_local void @"?test_arc_order@@YAXUA@@PAUobjc_object@@01@Z"
// CHECK: (<{ %struct.A, i8*, %struct.A, i8* }>* inalloca)
void test_arc_order(A a, id __attribute__((ns_consumed)) b , A c, id __attribute__((ns_consumed)) d) {
- // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %{{.*}})
+ // CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %{{.*}})
// CHECK: call void @objc_storeStrong(i8** %{{.*}}, i8* null)
- // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %{{.*}})
+ // CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %{{.*}})
// CHECK: call void @objc_storeStrong(i8** %{{.*}}, i8* null)
// CHECK: ret void
}
diff --git a/test/CodeGenObjCXX/msabi-objc-extensions.mm b/test/CodeGenObjCXX/msabi-objc-extensions.mm
index e6a6813..2f724a9 100644
--- a/test/CodeGenObjCXX/msabi-objc-extensions.mm
+++ b/test/CodeGenObjCXX/msabi-objc-extensions.mm
@@ -6,61 +6,61 @@
@class I;
void f(id<P>, id, id<P>, id) {}
-// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@PAUobjc_object@@01@Z"
+// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@PAUobjc_object@@01@Z"
void f(id, id<P>, id<P>, id) {}
-// CHECK-LABEL: "\01?f@@YAXPAUobjc_object@@PAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@10@Z"
+// CHECK-LABEL: "?f@@YAXPAUobjc_object@@PAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@10@Z"
void f(id<P>, id<P>) {}
-// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@0@Z"
+// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@0@Z"
void f(id<P>) {}
-// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@@Z"
+// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@@Z"
void f(id<P, Q>) {}
-// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
+// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
void f(Class<P>) {}
-// CHECK-LABEL: "\01?f@@YAXPAU?$objc_class@U?$Protocol@UP@@@__ObjC@@@@@Z"
+// CHECK-LABEL: "?f@@YAXPAU?$objc_class@U?$Protocol@UP@@@__ObjC@@@@@Z"
void f(Class<P, Q>) {}
-// CHECK-LABEL: "\01?f@@YAXPAU?$objc_class@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
+// CHECK-LABEL: "?f@@YAXPAU?$objc_class@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
void f(I<P> *) {}
-// CHECK-LABEL: "\01?f@@YAXPAU?$I@U?$Protocol@UP@@@__ObjC@@@@@Z"
+// CHECK-LABEL: "?f@@YAXPAU?$I@U?$Protocol@UP@@@__ObjC@@@@@Z"
void f(I<P, Q> *) {}
-// CHECK-LABEL: "\01?f@@YAXPAU?$I@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
+// CHECK-LABEL: "?f@@YAXPAU?$I@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
template <typename>
struct S {};
void f(S<__unsafe_unretained id>) {}
-// CHECK-LABEL: "\01?f@@YAXU?$S@PAUobjc_object@@@@@Z"
+// CHECK-LABEL: "?f@@YAXU?$S@PAUobjc_object@@@@@Z"
void f(S<__autoreleasing id>) {}
-// CHECK-LABEL: "\01?f@@YAXU?$S@U?$Autoreleasing@PAUobjc_object@@@__ObjC@@@@@Z"
+// CHECK-LABEL: "?f@@YAXU?$S@U?$Autoreleasing@PAUobjc_object@@@__ObjC@@@@@Z"
void f(S<__strong id>) {}
-// CHECK-LABEL: "\01?f@@YAXU?$S@U?$Strong@PAUobjc_object@@@__ObjC@@@@@Z"
+// CHECK-LABEL: "?f@@YAXU?$S@U?$Strong@PAUobjc_object@@@__ObjC@@@@@Z"
void f(S<__weak id>) {}
-// CHECK-LABEL: "\01?f@@YAXU?$S@U?$Weak@PAUobjc_object@@@__ObjC@@@@@Z"
+// CHECK-LABEL: "?f@@YAXU?$S@U?$Weak@PAUobjc_object@@@__ObjC@@@@@Z"
void w(__weak id) {}
-// CHECK-LABEL: "\01?w@@YAXPAUobjc_object@@@Z"
+// CHECK-LABEL: "?w@@YAXPAUobjc_object@@@Z"
void s(__strong id) {}
-// CHECK-LABEL: "\01?s@@YAXPAUobjc_object@@@Z"
+// CHECK-LABEL: "?s@@YAXPAUobjc_object@@@Z"
void a(__autoreleasing id) {}
-// CHECK-LABEL: "\01?a@@YAXPAUobjc_object@@@Z"
+// CHECK-LABEL: "?a@@YAXPAUobjc_object@@@Z"
void u(__unsafe_unretained id) {}
-// CHECK-LABEL: "\01?u@@YAXPAUobjc_object@@@Z"
+// CHECK-LABEL: "?u@@YAXPAUobjc_object@@@Z"
S<__autoreleasing id> g() { return S<__autoreleasing id>(); }
-// CHECK-LABEL: "\01?g@@YA?AU?$S@U?$Autoreleasing@PAUobjc_object@@@__ObjC@@@@XZ"
+// CHECK-LABEL: "?g@@YA?AU?$S@U?$Autoreleasing@PAUobjc_object@@@__ObjC@@@@XZ"
__autoreleasing id h() { return nullptr; }
-// CHECK-LABEL: "\01?h@@YAPAUobjc_object@@XZ"
+// CHECK-LABEL: "?h@@YAPAUobjc_object@@XZ"
diff --git a/test/CodeGenObjCXX/msabi-objc-types.mm b/test/CodeGenObjCXX/msabi-objc-types.mm
index 28b9f9d..192dd4c 100644
--- a/test/CodeGenObjCXX/msabi-objc-types.mm
+++ b/test/CodeGenObjCXX/msabi-objc-types.mm
@@ -3,166 +3,166 @@
@class I;
id kid;
-// CHECK: @"\01?kid@@3PAUobjc_object@@A" = dso_local global
+// CHECK: @"?kid@@3PAUobjc_object@@A" = dso_local global
Class klass;
-// CHECK: @"\01?klass@@3PAUobjc_class@@A" = dso_local global
+// CHECK: @"?klass@@3PAUobjc_class@@A" = dso_local global
I *kI;
-// CHECK: @"\01?kI@@3PAUI@@A" = dso_local global
+// CHECK: @"?kI@@3PAUI@@A" = dso_local global
void f(I *) {}
-// CHECK-LABEL: "\01?f@@YAXPAUI@@@Z"
+// CHECK-LABEL: "?f@@YAXPAUI@@@Z"
void f(const I *) {}
-// CHECK-LABEL: "\01?f@@YAXPBUI@@@Z"
+// CHECK-LABEL: "?f@@YAXPBUI@@@Z"
void f(I &) {}
-// CHECK-LABEL: "\01?f@@YAXAAUI@@@Z"
+// CHECK-LABEL: "?f@@YAXAAUI@@@Z"
void f(const I &) {}
-// CHECK-LABEL: "\01?f@@YAXABUI@@@Z"
+// CHECK-LABEL: "?f@@YAXABUI@@@Z"
void f(const I &&) {}
-// CHECK-LABEL: "\01?f@@YAX$$QBUI@@@Z"
+// CHECK-LABEL: "?f@@YAX$$QBUI@@@Z"
void g(id) {}
-// CHECK-LABEL: "\01?g@@YAXPAUobjc_object@@@Z"
+// CHECK-LABEL: "?g@@YAXPAUobjc_object@@@Z"
void g(id &) {}
-// CHECK-LABEL: "\01?g@@YAXAAPAUobjc_object@@@Z"
+// CHECK-LABEL: "?g@@YAXAAPAUobjc_object@@@Z"
void g(const id &) {}
-// CHECK-LABEL: "\01?g@@YAXABQAUobjc_object@@@Z"
+// CHECK-LABEL: "?g@@YAXABQAUobjc_object@@@Z"
void g(id &&) {}
-// CHECK-LABEL: "\01?g@@YAX$$QAPAUobjc_object@@@Z"
+// CHECK-LABEL: "?g@@YAX$$QAPAUobjc_object@@@Z"
void h(Class) {}
-// CHECK-LABEL: "\01?h@@YAXPAUobjc_class@@@Z"
+// CHECK-LABEL: "?h@@YAXPAUobjc_class@@@Z"
void h(Class &) {}
-// CHECK-LABEL: "\01?h@@YAXAAPAUobjc_class@@@Z"
+// CHECK-LABEL: "?h@@YAXAAPAUobjc_class@@@Z"
void h(const Class &) {}
-// CHECK-LABEL: "\01?h@@YAXABQAUobjc_class@@@Z"
+// CHECK-LABEL: "?h@@YAXABQAUobjc_class@@@Z"
void h(Class &&) {}
-// CHECK-LABEL: "\01?h@@YAX$$QAPAUobjc_class@@@Z"
+// CHECK-LABEL: "?h@@YAX$$QAPAUobjc_class@@@Z"
I *i() { return nullptr; }
-// CHECK-LABEL: "\01?i@@YAPAUI@@XZ"
+// CHECK-LABEL: "?i@@YAPAUI@@XZ"
const I *j() { return nullptr; }
-// CHECK-LABEL: "\01?j@@YAPBUI@@XZ"
+// CHECK-LABEL: "?j@@YAPBUI@@XZ"
I &k() { return *kI; }
-// CHECK-LABEL: "\01?k@@YAAAUI@@XZ"
+// CHECK-LABEL: "?k@@YAAAUI@@XZ"
const I &l() { return *kI; }
-// CHECK-LABEL: "\01?l@@YAABUI@@XZ"
+// CHECK-LABEL: "?l@@YAABUI@@XZ"
void m(const id) {}
-// CHECK-LABEL: "\01?m@@YAXQAUobjc_object@@@Z"
+// CHECK-LABEL: "?m@@YAXQAUobjc_object@@@Z"
void m(const I *) {}
-// CHECK-LABEL: "\01?m@@YAXPBUI@@@Z"
+// CHECK-LABEL: "?m@@YAXPBUI@@@Z"
void n(SEL) {}
-// CHECK-LABEL: "\01?n@@YAXPAUobjc_selector@@@Z"
+// CHECK-LABEL: "?n@@YAXPAUobjc_selector@@@Z"
void n(SEL *) {}
-// CHECK-LABEL: "\01?n@@YAXPAPAUobjc_selector@@@Z"
+// CHECK-LABEL: "?n@@YAXPAPAUobjc_selector@@@Z"
void n(const SEL *) {}
-// CHECK-LABEL: "\01?n@@YAXPBQAUobjc_selector@@@Z"
+// CHECK-LABEL: "?n@@YAXPBQAUobjc_selector@@@Z"
void n(SEL &) {}
-// CHECK-LABEL: "\01?n@@YAXAAPAUobjc_selector@@@Z"
+// CHECK-LABEL: "?n@@YAXAAPAUobjc_selector@@@Z"
void n(const SEL &) {}
-// CHECK-LABEL: "\01?n@@YAXABQAUobjc_selector@@@Z"
+// CHECK-LABEL: "?n@@YAXABQAUobjc_selector@@@Z"
void n(SEL &&) {}
-// CHECK-LABEL: "\01?n@@YAX$$QAPAUobjc_selector@@@Z"
+// CHECK-LABEL: "?n@@YAX$$QAPAUobjc_selector@@@Z"
struct __declspec(dllexport) s {
struct s &operator=(const struct s &) = delete;
void m(I *) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPAUI@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPAUI@@@Z"
void m(const I *) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPBUI@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPBUI@@@Z"
void m(I &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXAAUI@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXAAUI@@@Z"
void m(const I &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXABUI@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXABUI@@@Z"
void m(I &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QAUI@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QAUI@@@Z"
void m(const I &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QBUI@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QBUI@@@Z"
void m(id) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPAUobjc_object@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPAUobjc_object@@@Z"
void m(id &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXAAPAUobjc_object@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXAAPAUobjc_object@@@Z"
void m(id &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QAPAUobjc_object@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QAPAUobjc_object@@@Z"
void m(const id &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXABQAUobjc_object@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXABQAUobjc_object@@@Z"
void m(const id &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QBQAUobjc_object@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QBQAUobjc_object@@@Z"
void m(Class *) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPAPAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPAPAUobjc_class@@@Z"
void m(const Class *) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPBQAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPBQAUobjc_class@@@Z"
void m(Class) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPAUobjc_class@@@Z"
void m(Class &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXAAPAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXAAPAUobjc_class@@@Z"
void m(const Class &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXABQAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXABQAUobjc_class@@@Z"
void m(Class &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QAPAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QAPAUobjc_class@@@Z"
void m(const Class &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QBQAUobjc_class@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QBQAUobjc_class@@@Z"
void m(SEL) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPAUobjc_selector@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPAUobjc_selector@@@Z"
void m(SEL *) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPAPAUobjc_selector@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPAPAUobjc_selector@@@Z"
void m(const SEL *) {}
- // CHECK-LABEL: "\01?m@s@@QAAXPBQAUobjc_selector@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXPBQAUobjc_selector@@@Z"
void m(SEL &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXAAPAUobjc_selector@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXAAPAUobjc_selector@@@Z"
void m(const SEL &) {}
- // CHECK-LABEL: "\01?m@s@@QAAXABQAUobjc_selector@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAXABQAUobjc_selector@@@Z"
void m(SEL &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QAPAUobjc_selector@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QAPAUobjc_selector@@@Z"
void m(const SEL &&) {}
- // CHECK-LABEL: "\01?m@s@@QAAX$$QBQAUobjc_selector@@@Z"
+ // CHECK-LABEL: "?m@s@@QAAX$$QBQAUobjc_selector@@@Z"
};
template <typename T>
@@ -179,14 +179,14 @@
};
template struct t<id>;
-// CHECK-LABEL: "\01??0?$t@PAUobjc_object@@@@QAA@XZ"
+// CHECK-LABEL: "??0?$t@PAUobjc_object@@@@QAA@XZ"
template struct t<remove_pointer<id>::type>;
-// CHECK-LABEL: "\01??0?$t@Uobjc_object@@@@QAA@XZ"
+// CHECK-LABEL: "??0?$t@Uobjc_object@@@@QAA@XZ"
template struct t<SEL>;
-// CHECK-LABEL: "\01??0?$t@PAUobjc_selector@@@@QAA@XZ"
+// CHECK-LABEL: "??0?$t@PAUobjc_selector@@@@QAA@XZ"
template struct t<remove_pointer<SEL>::type>;
-// CHECK-LABEL: "\01??0?$t@Uobjc_selector@@@@QAA@XZ"
+// CHECK-LABEL: "??0?$t@Uobjc_selector@@@@QAA@XZ"
diff --git a/test/CodeGenObjCXX/trivial_abi.mm b/test/CodeGenObjCXX/objc-struct-cxx-abi.mm
similarity index 73%
rename from test/CodeGenObjCXX/trivial_abi.mm
rename to test/CodeGenObjCXX/objc-struct-cxx-abi.mm
index 6a20578d..de8c5f9 100644
--- a/test/CodeGenObjCXX/trivial_abi.mm
+++ b/test/CodeGenObjCXX/objc-struct-cxx-abi.mm
@@ -1,27 +1,60 @@
// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -emit-llvm -o - -DTRIVIALABI %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -fclang-abi-compat=4.0 -emit-llvm -o - -DTRIVIALABI %s | FileCheck %s
+
+// Check that structs consisting solely of __strong or __weak pointer fields are
+// destructed in the callee function and structs consisting solely of __strong
+// pointer fields are passed directly.
// CHECK: %[[STRUCT_STRONGWEAK:.*]] = type { i8*, i8* }
// CHECK: %[[STRUCT_STRONG:.*]] = type { i8* }
// CHECK: %[[STRUCT_S:.*]] = type { i8* }
+// CHECK: %[[STRUCT_CONTAINSNONTRIVIAL:.*]] = type { %{{.*}}, i8* }
+#ifdef TRIVIALABI
struct __attribute__((trivial_abi)) StrongWeak {
+#else
+struct StrongWeak {
+#endif
id fstrong;
__weak id fweak;
};
+#ifdef TRIVIALABI
struct __attribute__((trivial_abi)) Strong {
+#else
+struct Strong {
+#endif
id fstrong;
};
template<class T>
+#ifdef TRIVIALABI
struct __attribute__((trivial_abi)) S {
+#else
+struct S {
+#endif
T a;
};
+struct NonTrivial {
+ NonTrivial();
+ NonTrivial(const NonTrivial &);
+ ~NonTrivial();
+ int *a;
+};
+
+// This struct is not passed directly nor destructed in the callee because f0
+// has type NonTrivial.
+struct ContainsNonTrivial {
+ NonTrivial f0;
+ id f1;
+};
+
// CHECK: define void @_Z19testParamStrongWeak10StrongWeak(%[[STRUCT_STRONGWEAK]]* %{{.*}})
-// CHECK-NOT: call
-// CHECK: ret void
+// CHECK: call %struct.StrongWeak* @_ZN10StrongWeakD1Ev(
+// CHECK-NEXT: ret void
void testParamStrongWeak(StrongWeak a) {
}
@@ -33,7 +66,7 @@
// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]])
// CHECK: call void @_Z19testParamStrongWeak10StrongWeak(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]])
-// CHECK: %[[CALL1:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakD1Ev(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]])
+// CHECK-NOT: call
// CHECK: ret void
void testCallStrongWeak(StrongWeak *a) {
@@ -96,8 +129,23 @@
}
// CHECK: define void @_Z21testParamWeakTemplate1SIU6__weakP11objc_objectE(%[[STRUCT_S]]* %{{.*}})
+// CHECK: call %struct.S* @_ZN1SIU6__weakP11objc_objectED1Ev(
+// CHECK-NEXT: ret void
+
+void testParamWeakTemplate(S<__weak id> a) {
+}
+
+// CHECK: define void @_Z27testParamContainsNonTrivial18ContainsNonTrivial(%[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})
// CHECK-NOT: call
// CHECK: ret void
-void testParamWeakTemplate(S<__weak id> a) {
+void testParamContainsNonTrivial(ContainsNonTrivial a) {
+}
+
+// CHECK: define void @_Z26testCallContainsNonTrivialP18ContainsNonTrivial(
+// CHECK: call void @_Z27testParamContainsNonTrivial18ContainsNonTrivial(%[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})
+// CHECK: call %struct.ContainsNonTrivial* @_ZN18ContainsNonTrivialD1Ev(%[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})
+
+void testCallContainsNonTrivial(ContainsNonTrivial *a) {
+ testParamContainsNonTrivial(*a);
}
diff --git a/test/CodeGenObjCXX/personality.mm b/test/CodeGenObjCXX/personality.mm
new file mode 100644
index 0000000..c2b4789
--- /dev/null
+++ b/test/CodeGenObjCXX/personality.mm
@@ -0,0 +1,129 @@
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS-DWARF
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ
+
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ
+
+void g(void);
+
+@interface use
++ (void)e:(id)xception;
+@end
+
+// CHECK-MACOSX-FRAGILE: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-MACOSX-FRAGILE-SEH: personality i8* bitcast (i32 (...)* @__gxx_personality_seh0 to i8*)
+// CHECK-MACOSX-FRAGILE-SJLJ: personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*)
+// CHECK-NS: personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
+// CHECK-GNUSTEP-1_7: personality i8* bitcast (i32 (...)* @__gnustep_objcxx_personality_v0 to i8*)
+// CHECK-GNUSTEP: personality i8* bitcast (i32 (...)* @__gnustep_objcxx_personality_v0 to i8*)
+// CHECK-GCC: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*)
+// CHECK-GCC-SEH: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_seh0 to i8*)
+// CHECK-GCC-SJLJ: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*)
+// CHECK-OBJFW: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*)
+// CHECK-OBJFW-SEH: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_seh0 to i8*)
+// CHECK-OBJFW-SJLJ: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*)
+
+// CHECK-WIN-MACOSX-FRAGILE: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+// CHECK-WIN-MACOSX-FRAGILE-DWARF: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-WIN-MACOSX-FRAGILE-SEH: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+// CHECK-WIN-MACOSX-FRAGILE-SJLJ: personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*)
+// CHECK-WIN-NS: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+// CHECK-WIN-NS-DWARF: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-WIN-NS-SJLJ: personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*)
+
+void f(void) {
+ @try {
+ g();
+ } @catch (id xception) {
+ [use e:xception];
+ }
+}
+
+#if defined(__SEH_EXCEPTIONS__)
+// CHECK-WIN-SEH-X86: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
+// CHECK-WIN-SEH-X64: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+
+void h(void) {
+ __try {
+ i();
+ } __finally {
+ }
+}
+#endif
+
+
diff --git a/test/CodeGenObjCXX/property-dot-copy-elision.mm b/test/CodeGenObjCXX/property-dot-copy-elision.mm
new file mode 100644
index 0000000..c13a7d9
--- /dev/null
+++ b/test/CodeGenObjCXX/property-dot-copy-elision.mm
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++1z -fobjc-arc -o - %s | FileCheck %s
+
+struct S0 {
+ ~S0();
+ id f;
+};
+
+struct S1 {
+ S1();
+ ~S1();
+ S1(S0);
+ id f;
+};
+
+@interface C
+@property S1 f;
+@end
+@implementation C
+@end
+
+// CHECK-LABEL: define void @_Z5test0P1C(
+// CHECK: %{{.*}} = alloca %
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_S1:.*]], align
+// CHECK: %[[AGG_TMP_1:.*]] = alloca %[[STRUCT_S0:.*]], align
+// CHECK: call void @_ZN2S0C1Ev(%[[STRUCT_S0]]* %[[AGG_TMP_1]])
+// CHECK: call void @_ZN2S1C1E2S0(%[[STRUCT_S1]]* %[[AGG_TMP]], %[[STRUCT_S0]]* %[[AGG_TMP_1]])
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %[[STRUCT_S1]]*)*)(i8* %{{.*}}, i8* %{{.*}}, %[[STRUCT_S1]]* %[[AGG_TMP]])
+
+void test0(C *c) {
+ c.f = S0();
+}
+
+// CHECK: define void @_Z5test1P1C(
+// CHECK: %{{.*}} = alloca %
+// CHECK: %[[TEMP_LVALUE:.*]] = alloca %[[STRUCT_S1:.*]], align
+// CHECK: call void @_ZN2S1C1Ev(%[[STRUCT_S1]]* %[[TEMP_LVALUE]])
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %[[STRUCT_S1]]*)*)(i8* %{{.*}}, i8* %{{.*}}, %[[STRUCT_S1]]* %[[TEMP_LVALUE]])
+
+void test1(C *c) {
+ c.f = S1();
+}
diff --git a/test/CodeGenObjCXX/property-objects.mm b/test/CodeGenObjCXX/property-objects.mm
index 8e0b6ae..62188e8 100644
--- a/test/CodeGenObjCXX/property-objects.mm
+++ b/test/CodeGenObjCXX/property-objects.mm
@@ -119,11 +119,11 @@
// CHECK: define void @_Z6testB0P1B([[B:%.*]]*
// CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8
// CHECK: [[TEMP:%.*]] = alloca [[B0:%.*]], align 8
-// CHECK: load [[B]]*, [[B]]** [[BVAR]]
-// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[B0]], [[B0]]* [[TEMP]], i32 0, i32 0
+// CHECK: [[X:%.*]] = getelementptr inbounds [[B0]], [[B0]]* [[TEMP]], i32 0, i32 0
// CHECK-NEXT: [[T0:%.*]] = call i32 @_Z9b_makeIntv()
// CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64
// CHECK-NEXT: store i64 [[T1]], i64* [[X]], align 8
+// CHECK: load [[B]]*, [[B]]** [[BVAR]]
// CHECK-NOT: call
// CHECK: call void @llvm.memcpy
// CHECK-NOT: call
@@ -161,12 +161,12 @@
// CHECK: define void @_Z6testB2P1B([[B]]*
// CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8
-// CHECK: load [[B]]*, [[B]]** [[BVAR]]
-// CHECK-NOT: call
+// CHECK: call void @llvm.dbg.declare(
// CHECK: call void @_ZN2B3C1Ev(
// CHECK-NEXT: [[T0:%.*]] = call i64 @_ZN2B3cv2B1Ev(
// CHECK-NOT: call
// CHECK: store i64 [[T0]],
+// CHECK: load [[B]]*, [[B]]** [[BVAR]]
// CHECK-NOT: call
// CHECK: call void @llvm.memcpy
// CHECK-NOT: call
diff --git a/test/CodeGenOpenCL/addr-space-struct-arg.cl b/test/CodeGenOpenCL/addr-space-struct-arg.cl
index 01ae1b3..f8d7073 100644
--- a/test/CodeGenOpenCL/addr-space-struct-arg.cl
+++ b/test/CodeGenOpenCL/addr-space-struct-arg.cl
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -ffake-address-space-map -triple i686-pc-darwin | FileCheck -enable-var-scope -check-prefixes=COM,X86 %s
-// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -triple amdgcn-amdhsa-amd | FileCheck -enable-var-scope -check-prefixes=COM,AMDGCN %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=COM,AMDGCN %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL2.0 -O0 -finclude-default-header -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=COM,AMDGCN,AMDGCN20 %s
typedef struct {
int cells[9];
@@ -35,6 +36,9 @@
int2 y[20];
};
+#if __OPENCL_C_VERSION__ >= 200
+struct LargeStructOneMember g_s;
+#endif
// X86-LABEL: define void @foo(%struct.Mat4X4* noalias sret %agg.result, %struct.Mat3X3* byval align 4 %in)
// AMDGCN-LABEL: define %struct.Mat4X4 @foo([9 x i32] %in.coerce)
@@ -80,10 +84,42 @@
}
// AMDGCN-LABEL: define void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %u)
+// AMDGCN-NOT: addrspacecast
+// AMDGCN: store <2 x i32> %{{.*}}, <2 x i32> addrspace(5)*
void FuncOneLargeMember(struct LargeStructOneMember u) {
u.x[0] = (int2)(0, 0);
}
+// AMDGCN20-LABEL: define void @test_indirect_arg_globl()
+// AMDGCN20: %[[byval_temp:.*]] = alloca %struct.LargeStructOneMember, align 8, addrspace(5)
+// AMDGCN20: %[[r0:.*]] = bitcast %struct.LargeStructOneMember addrspace(5)* %[[byval_temp]] to i8 addrspace(5)*
+// AMDGCN20: call void @llvm.memcpy.p5i8.p1i8.i64(i8 addrspace(5)* align 8 %[[r0]], i8 addrspace(1)* align 8 bitcast (%struct.LargeStructOneMember addrspace(1)* @g_s to i8 addrspace(1)*), i64 800, i1 false)
+// AMDGCN20: call void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %[[byval_temp]])
+#if __OPENCL_C_VERSION__ >= 200
+void test_indirect_arg_globl(void) {
+ FuncOneLargeMember(g_s);
+}
+#endif
+
+// AMDGCN-LABEL: define amdgpu_kernel void @test_indirect_arg_local()
+// AMDGCN: %[[byval_temp:.*]] = alloca %struct.LargeStructOneMember, align 8, addrspace(5)
+// AMDGCN: %[[r0:.*]] = bitcast %struct.LargeStructOneMember addrspace(5)* %[[byval_temp]] to i8 addrspace(5)*
+// AMDGCN: call void @llvm.memcpy.p5i8.p3i8.i64(i8 addrspace(5)* align 8 %[[r0]], i8 addrspace(3)* align 8 bitcast (%struct.LargeStructOneMember addrspace(3)* @test_indirect_arg_local.l_s to i8 addrspace(3)*), i64 800, i1 false)
+// AMDGCN: call void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %[[byval_temp]])
+kernel void test_indirect_arg_local(void) {
+ local struct LargeStructOneMember l_s;
+ FuncOneLargeMember(l_s);
+}
+
+// AMDGCN-LABEL: define void @test_indirect_arg_private()
+// AMDGCN: %[[p_s:.*]] = alloca %struct.LargeStructOneMember, align 8, addrspace(5)
+// AMDGCN-NOT: @llvm.memcpy
+// AMDGCN-NEXT: call void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval align 8 %[[p_s]])
+void test_indirect_arg_private(void) {
+ struct LargeStructOneMember p_s;
+ FuncOneLargeMember(p_s);
+}
+
// AMDGCN-LABEL: define amdgpu_kernel void @KernelOneMember
// AMDGCN-SAME: (<2 x i32> %[[u_coerce:.*]])
// AMDGCN: %[[u:.*]] = alloca %struct.StructOneMember, align 8, addrspace(5)
@@ -112,7 +148,6 @@
u.y[0] = (int2)(0, 0);
}
-
// AMDGCN-LABEL: define amdgpu_kernel void @KernelTwoMember
// AMDGCN-SAME: (%struct.StructTwoMember %[[u_coerce:.*]])
// AMDGCN: %[[u:.*]] = alloca %struct.StructTwoMember, align 8, addrspace(5)
diff --git a/test/CodeGenOpenCL/amdgpu-attrs.cl b/test/CodeGenOpenCL/amdgpu-attrs.cl
index 2696123..ad13a2c 100644
--- a/test/CodeGenOpenCL/amdgpu-attrs.cl
+++ b/test/CodeGenOpenCL/amdgpu-attrs.cl
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple amdgcn-- -target-cpu tahiti -O0 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -target-cpu tahiti -O0 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple amdgcn-- -target-cpu tahiti -O0 -emit-llvm -o - %s | FileCheck %s -check-prefix=NONAMDHSA
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O0 -emit-llvm -verify -o - %s | FileCheck -check-prefix=X86 %s
__attribute__((amdgpu_flat_work_group_size(0, 0))) // expected-no-diagnostics
@@ -138,12 +139,18 @@
// CHECK: define amdgpu_kernel void @reqd_work_group_size_32_2_1_flat_work_group_size_16_128() [[FLAT_WORK_GROUP_SIZE_16_128:#[0-9]+]]
}
+void a_function() {
+// CHECK: define void @a_function() [[A_FUNCTION:#[0-9]+]]
+}
+
// Make sure this is silently accepted on other targets.
// X86-NOT: "amdgpu-flat-work-group-size"
// X86-NOT: "amdgpu-waves-per-eu"
// X86-NOT: "amdgpu-num-vgpr"
// X86-NOT: "amdgpu-num-sgpr"
+// X86-NOT: "amdgpu-implicitarg-num-bytes"
+// NONAMDHSA-NOT: "amdgpu-implicitarg-num-bytes"
// CHECK-NOT: "amdgpu-flat-work-group-size"="0,0"
// CHECK-NOT: "amdgpu-waves-per-eu"="0"
@@ -151,28 +158,30 @@
// CHECK-NOT: "amdgpu-num-sgpr"="0"
// CHECK-NOT: "amdgpu-num-vgpr"="0"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_64_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="64,64"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_16_128]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="16,128"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_4]] = { convergent noinline nounwind optnone "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32"
-// CHECK-DAG: attributes [[NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-vgpr"="64"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_64_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="64,64" "amdgpu-implicitarg-num-bytes"="48"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_16_128]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="16,128" "amdgpu-implicitarg-num-bytes"="48"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_4]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32"
+// CHECK-DAG: attributes [[NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-vgpr"="64"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-vgpr"="64"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="48" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
+
+// CHECK-DAG: attributes [[A_FUNCTION]] = { convergent noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false"
diff --git a/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl b/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
index 875c35c..75fcecc 100644
--- a/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
+++ b/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -O0 -emit-llvm -o - -triple amdgcn | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -O0 -emit-llvm -o - -triple amdgcn | FileCheck %s
typedef struct {int a;} ndrange_t;
@@ -36,23 +36,23 @@
enqueue_kernel(default_queue, flags, ndrange, block);
}
-// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_kernel(<{ i32, i32, i8*, i8 addrspace(1)*, i8 }>)
+// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_kernel(<{ i32, i32, i8 addrspace(1)*, i8 }>)
// CHECK-SAME: #[[ATTR:[0-9]+]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}}
// CHECK: entry:
-// CHECK: %1 = alloca <{ i32, i32, i8*, i8 addrspace(1)*, i8 }>, align 8, addrspace(5)
-// CHECK: store <{ i32, i32, i8*, i8 addrspace(1)*, i8 }> %0, <{ i32, i32, i8*, i8 addrspace(1)*, i8 }> addrspace(5)* %1, align 8
-// CHECK: %2 = addrspacecast <{ i32, i32, i8*, i8 addrspace(1)*, i8 }> addrspace(5)* %1 to i8*
+// CHECK: %1 = alloca <{ i32, i32, i8 addrspace(1)*, i8 }>, align 8, addrspace(5)
+// CHECK: store <{ i32, i32, i8 addrspace(1)*, i8 }> %0, <{ i32, i32, i8 addrspace(1)*, i8 }> addrspace(5)* %1, align 8
+// CHECK: %2 = addrspacecast <{ i32, i32, i8 addrspace(1)*, i8 }> addrspace(5)* %1 to i8*
// CHECK: call void @__test_block_invoke(i8* %2)
// CHECK: ret void
// CHECK:}
-// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_2_kernel(<{ i32, i32, i8*, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>)
+// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_2_kernel(<{ i32, i32, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>)
// CHECK-SAME: #[[ATTR]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}}
-// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_3_kernel(<{ i32, i32, i8*, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>, i8 addrspace(3)*)
+// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_3_kernel(<{ i32, i32, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>, i8 addrspace(3)*)
// CHECK-SAME: #[[ATTR]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}}
-// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_4_kernel(<{ i32, i32, i8*, i64, i64 addrspace(1)* }>)
+// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_4_kernel(<{ i32, i32, i64, i64 addrspace(1)* }>)
// CHECK-SAME: #[[ATTR]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}}
// CHECK: attributes #[[ATTR]] = { nounwind "enqueued-block" }
diff --git a/test/CodeGenOpenCL/amdgpu-env-amdgcn.cl b/test/CodeGenOpenCL/amdgpu-env-amdgcn.cl
index f6c6f32..bcb00be 100644
--- a/test/CodeGenOpenCL/amdgpu-env-amdgcn.cl
+++ b/test/CodeGenOpenCL/amdgpu-env-amdgcn.cl
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 %s -O0 -triple amdgcn -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 %s -O0 -triple amdgcn---opencl -emit-llvm -o - | FileCheck %s
-// CHECK: target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5"
+// CHECK: target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5"
void foo(void) {}
diff --git a/test/CodeGenOpenCL/blocks.cl b/test/CodeGenOpenCL/blocks.cl
index 5e7a3db..0e125fd 100644
--- a/test/CodeGenOpenCL/blocks.cl
+++ b/test/CodeGenOpenCL/blocks.cl
@@ -1,10 +1,7 @@
// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck -check-prefixes=COMMON,SPIR %s
// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=COMMON,AMDGCN %s
-// SPIR: %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* }
-// AMDGCN: %struct.__opencl_block_literal_generic = type { i32, i32, i8* }
-// SPIR: @__block_literal_global = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 12, i32 4, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* @block_A_block_invoke to i8*) to i8 addrspace(4)*) }
-// AMDGCN: @__block_literal_global = internal addrspace(1) constant { i32, i32, i8* } { i32 16, i32 8, i8* bitcast (void (i8*, i8 addrspace(3)*)* @block_A_block_invoke to i8*) }
+// COMMON: @__block_literal_global = internal addrspace(1) constant { i32, i32 } { i32 8, i32 4 }
// COMMON-NOT: .str
// SPIR-LABEL: define internal {{.*}}void @block_A_block_invoke(i8 addrspace(4)* %.block_descriptor, i8 addrspace(3)* %a)
@@ -20,44 +17,32 @@
// COMMON-NOT: %block.flags
// COMMON-NOT: %block.reserved
// COMMON-NOT: %block.descriptor
- // SPIR: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %block, i32 0, i32 0
- // AMDGCN: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i8*, i32 }>, <{ i32, i32, i8*, i32 }> addrspace(5)* %block, i32 0, i32 0
- // SPIR: store i32 16, i32* %[[block_size]]
- // AMDGCN: store i32 20, i32 addrspace(5)* %[[block_size]]
- // SPIR: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %block, i32 0, i32 1
- // AMDGCN: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i8*, i32 }>, <{ i32, i32, i8*, i32 }> addrspace(5)* %block, i32 0, i32 1
+ // SPIR: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }>* %[[block:.*]], i32 0, i32 0
+ // AMDGCN: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }> addrspace(5)* %[[block:.*]], i32 0, i32 0
+ // SPIR: store i32 12, i32* %[[block_size]]
+ // AMDGCN: store i32 12, i32 addrspace(5)* %[[block_size]]
+ // SPIR: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }>* %[[block]], i32 0, i32 1
+ // AMDGCN: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }> addrspace(5)* %[[block]], i32 0, i32 1
// SPIR: store i32 4, i32* %[[block_align]]
- // AMDGCN: store i32 8, i32 addrspace(5)* %[[block_align]]
- // SPIR: %[[block_invoke:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %[[block:.*]], i32 0, i32 2
- // SPIR: store i8 addrspace(4)* addrspacecast (i8* bitcast (i32 (i8 addrspace(4)*)* @__foo_block_invoke to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %[[block_invoke]]
- // SPIR: %[[block_captured:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %[[block]], i32 0, i32 3
+ // AMDGCN: store i32 4, i32 addrspace(5)* %[[block_align]]
+ // SPIR: %[[block_captured:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }>* %[[block]], i32 0, i32 2
// SPIR: %[[i_value:.*]] = load i32, i32* %i
// SPIR: store i32 %[[i_value]], i32* %[[block_captured]],
- // SPIR: %[[blk_ptr:.*]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32 }>* %[[block]] to i32 ()*
+ // SPIR: %[[blk_ptr:.*]] = bitcast <{ i32, i32, i32 }>* %[[block]] to i32 ()*
// SPIR: %[[blk_gen_ptr:.*]] = addrspacecast i32 ()* %[[blk_ptr]] to i32 () addrspace(4)*
// SPIR: store i32 () addrspace(4)* %[[blk_gen_ptr]], i32 () addrspace(4)** %[[block_B:.*]],
- // SPIR: %[[blk_gen_ptr:.*]] = load i32 () addrspace(4)*, i32 () addrspace(4)** %[[block_B]]
- // SPIR: %[[block_literal:.*]] = bitcast i32 () addrspace(4)* %[[blk_gen_ptr]] to %struct.__opencl_block_literal_generic addrspace(4)*
- // SPIR: %[[invoke_addr:.*]] = getelementptr inbounds %struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic addrspace(4)* %[[block_literal]], i32 0, i32 2
- // SPIR: %[[blk_gen_ptr:.*]] = bitcast %struct.__opencl_block_literal_generic addrspace(4)* %[[block_literal]] to i8 addrspace(4)*
- // SPIR: %[[invoke_func_ptr:.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %[[invoke_addr]]
- // SPIR: %[[invoke_func:.*]] = addrspacecast i8 addrspace(4)* %[[invoke_func_ptr]] to i32 (i8 addrspace(4)*)*
- // SPIR: call {{.*}}i32 %[[invoke_func]](i8 addrspace(4)* %[[blk_gen_ptr]])
- // AMDGCN: %[[block_invoke:.*]] = getelementptr inbounds <{ i32, i32, i8*, i32 }>, <{ i32, i32, i8*, i32 }> addrspace(5)* %[[block:.*]], i32 0, i32 2
- // AMDGCN: store i8* bitcast (i32 (i8*)* @__foo_block_invoke to i8*), i8* addrspace(5)* %[[block_invoke]]
- // AMDGCN: %[[block_captured:.*]] = getelementptr inbounds <{ i32, i32, i8*, i32 }>, <{ i32, i32, i8*, i32 }> addrspace(5)* %[[block]], i32 0, i32 3
+ // SPIR: %[[block_literal:.*]] = load i32 () addrspace(4)*, i32 () addrspace(4)** %[[block_B]]
+ // SPIR: %[[blk_gen_ptr:.*]] = bitcast i32 () addrspace(4)* %[[block_literal]] to i8 addrspace(4)*
+ // SPIR: call {{.*}}i32 @__foo_block_invoke(i8 addrspace(4)* %[[blk_gen_ptr]])
+ // AMDGCN: %[[block_captured:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }> addrspace(5)* %[[block]], i32 0, i32 2
// AMDGCN: %[[i_value:.*]] = load i32, i32 addrspace(5)* %i
// AMDGCN: store i32 %[[i_value]], i32 addrspace(5)* %[[block_captured]],
- // AMDGCN: %[[blk_ptr:.*]] = bitcast <{ i32, i32, i8*, i32 }> addrspace(5)* %[[block]] to i32 () addrspace(5)*
+ // AMDGCN: %[[blk_ptr:.*]] = bitcast <{ i32, i32, i32 }> addrspace(5)* %[[block]] to i32 () addrspace(5)*
// AMDGCN: %[[blk_gen_ptr:.*]] = addrspacecast i32 () addrspace(5)* %[[blk_ptr]] to i32 ()*
// AMDGCN: store i32 ()* %[[blk_gen_ptr]], i32 ()* addrspace(5)* %[[block_B:.*]],
- // AMDGCN: %[[blk_gen_ptr:.*]] = load i32 ()*, i32 ()* addrspace(5)* %[[block_B]]
- // AMDGCN: %[[block_literal:.*]] = bitcast i32 ()* %[[blk_gen_ptr]] to %struct.__opencl_block_literal_generic*
- // AMDGCN: %[[invoke_addr:.*]] = getelementptr inbounds %struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic* %[[block_literal]], i32 0, i32 2
- // AMDGCN: %[[blk_gen_ptr:.*]] = bitcast %struct.__opencl_block_literal_generic* %[[block_literal]] to i8*
- // AMDGCN: %[[invoke_func_ptr:.*]] = load i8*, i8** %[[invoke_addr]]
- // AMDGCN: %[[invoke_func:.*]] = bitcast i8* %[[invoke_func_ptr]] to i32 (i8*)*
- // AMDGCN: call {{.*}}i32 %[[invoke_func]](i8* %[[blk_gen_ptr]])
+ // AMDGCN: %[[block_literal:.*]] = load i32 ()*, i32 ()* addrspace(5)* %[[block_B]]
+ // AMDGCN: %[[blk_gen_ptr:.*]] = bitcast i32 ()* %[[block_literal]] to i8*
+ // AMDGCN: call {{.*}}i32 @__foo_block_invoke(i8* %[[blk_gen_ptr]])
int (^ block_B)(void) = ^{
return i;
@@ -66,12 +51,12 @@
}
// SPIR-LABEL: define internal {{.*}}i32 @__foo_block_invoke(i8 addrspace(4)* %.block_descriptor)
-// SPIR: %[[block:.*]] = bitcast i8 addrspace(4)* %.block_descriptor to <{ i32, i32, i8 addrspace(4)*, i32 }> addrspace(4)*
-// SPIR: %[[block_capture_addr:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }> addrspace(4)* %[[block]], i32 0, i32 3
+// SPIR: %[[block:.*]] = bitcast i8 addrspace(4)* %.block_descriptor to <{ i32, i32, i32 }> addrspace(4)*
+// SPIR: %[[block_capture_addr:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }> addrspace(4)* %[[block]], i32 0, i32 2
// SPIR: %[[block_capture:.*]] = load i32, i32 addrspace(4)* %[[block_capture_addr]]
// AMDGCN-LABEL: define internal {{.*}}i32 @__foo_block_invoke(i8* %.block_descriptor)
-// AMDGCN: %[[block:.*]] = bitcast i8* %.block_descriptor to <{ i32, i32, i8*, i32 }>*
-// AMDGCN: %[[block_capture_addr:.*]] = getelementptr inbounds <{ i32, i32, i8*, i32 }>, <{ i32, i32, i8*, i32 }>* %[[block]], i32 0, i32 3
+// AMDGCN: %[[block:.*]] = bitcast i8* %.block_descriptor to <{ i32, i32, i32 }>*
+// AMDGCN: %[[block_capture_addr:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }>* %[[block]], i32 0, i32 2
// AMDGCN: %[[block_capture:.*]] = load i32, i32* %[[block_capture_addr]]
// COMMON-NOT: define{{.*}}@__foo_block_invoke_kernel
diff --git a/test/CodeGenOpenCL/byval.cl b/test/CodeGenOpenCL/byval.cl
index 592d96f..05c72c5 100644
--- a/test/CodeGenOpenCL/byval.cl
+++ b/test/CodeGenOpenCL/byval.cl
@@ -1,5 +1,4 @@
// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn %s | FileCheck %s
-// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn---opencl %s | FileCheck %s
struct A {
int x[100];
diff --git a/test/CodeGenOpenCL/cl20-device-side-enqueue.cl b/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
index 005bce7..148ed4a 100644
--- a/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
+++ b/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
@@ -6,27 +6,25 @@
typedef void (^bl_t)(local void *);
typedef struct {int a;} ndrange_t;
-// COMMON: %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* }
-
// For a block global variable, first emit the block literal as a global variable, then emit the block variable itself.
-// COMMON: [[BL_GLOBAL:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* [[INV_G:@[^ ]+]] to i8*) to i8 addrspace(4)*) }
-// COMMON: @block_G = addrspace(1) constant void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BL_GLOBAL]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*)
+// COMMON: [[BL_GLOBAL:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: @block_G = addrspace(1) constant void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BL_GLOBAL]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*)
// For anonymous blocks without captures, emit block literals as global variable.
-// COMMON: [[BLG1:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG2:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG3:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG4:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG5:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG6:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*, i8 addrspace(3)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG7:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG8:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVG8:@[^ ]+]] to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG9:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* [[INVG9:@[^ ]+]] to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG10:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
-// COMMON: [[BLG11:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
+// COMMON: [[BLG1:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG2:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG3:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG4:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG5:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG6:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG7:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG8:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG9:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG10:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG11:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
// Emits block literal [[BL_GLOBAL]], invoke function [[INV_G]] and global block variable @block_G
-// COMMON: define internal spir_func void [[INV_G]](i8 addrspace(4)* %{{.*}}, i8 addrspace(3)* %{{.*}})
+// COMMON: define internal spir_func void [[INV_G:.*]](i8 addrspace(4)* %{{.*}}, i8 addrspace(3)* %{{.*}})
const bl_t block_G = (bl_t) ^ (local void *a) {};
void callee(int id, __global int *out) {
@@ -52,9 +50,8 @@
// COMMON: [[NDR:%[a-z0-9]+]] = alloca %struct.ndrange_t, align 4
// COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // COMMON: store i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVL1:@__device_side_enqueue_block_invoke[^ ]*]] to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %block.invoke
- // B32: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32, i32 addrspace(1)* }>* %block to void ()*
- // B64: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32 addrspace(1)*, i32 }>* %block to void ()*
+ // B32: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i32 addrspace(1)*, i32, i32 addrspace(1)* }>* %block to void ()*
+ // B64: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i32 addrspace(1)*, i32 addrspace(1)*, i32 }>* %block to void ()*
// COMMON: [[BL_I8:%[0-9]+]] = addrspacecast void ()* [[BL]] to i8 addrspace(4)*
// COMMON-LABEL: call i32 @__enqueue_kernel_basic(
// COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* byval [[NDR]]{{([0-9]+)?}},
@@ -70,8 +67,7 @@
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
// COMMON: [[WAIT_EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** %event_wait_list to %opencl.clk_event_t{{.*}}* addrspace(4)*
// COMMON: [[EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** %clk_event to %opencl.clk_event_t{{.*}}* addrspace(4)*
- // COMMON: store i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVL2:@__device_side_enqueue_block_invoke[^ ]*]] to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %block.invoke
- // COMMON: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block3 to void ()*
+ // COMMON: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block3 to void ()*
// COMMON: [[BL_I8:%[0-9]+]] = addrspacecast void ()* [[BL]] to i8 addrspace(4)*
// COMMON-LABEL: call i32 @__enqueue_kernel_basic_events
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]],
@@ -95,7 +91,7 @@
// COMMON-LABEL: call i32 @__enqueue_kernel_vaargs(
// COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK1:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG1]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG1]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange,
@@ -116,7 +112,7 @@
// COMMON-LABEL: call i32 @__enqueue_kernel_vaargs(
// COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK2:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG2]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG2]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange,
@@ -140,7 +136,7 @@
// COMMON-LABEL: call i32 @__enqueue_kernel_events_vaargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}} [[WAIT_EVNT]], %opencl.clk_event_t{{.*}} [[EVNT]],
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK3:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG3]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG3]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange, 2, event_wait_list2, &clk_event,
@@ -164,7 +160,7 @@
// COMMON-LABEL: call i32 @__enqueue_kernel_events_vaargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]],
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK4:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG4]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG4]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange, 2, event_wait_list2, &clk_event,
@@ -186,7 +182,7 @@
// COMMON-LABEL: call i32 @__enqueue_kernel_vaargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK5:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG5]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG5]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange,
@@ -215,7 +211,7 @@
// COMMON-LABEL: call i32 @__enqueue_kernel_vaargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK6:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG6]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 3,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG6]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 3,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange,
@@ -236,7 +232,7 @@
// COMMON-LABEL: call i32 @__enqueue_kernel_vaargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK7:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG7]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG7]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
// B32-SAME: i32* %[[TMP1]])
// B64-SAME: i64* %[[TMP1]])
enqueue_kernel(default_queue, flags, ndrange,
@@ -248,21 +244,19 @@
// Emits global block literal [[BLG8]] and invoke function [[INVG8]].
// The full type of these expressions are long (and repeated elsewhere), so we
// capture it as part of the regex for convenience and clarity.
- // COMMON: store void () addrspace(4)* addrspacecast (void () addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to void () addrspace(1)*) to void () addrspace(4)*), void () addrspace(4)** %block_A
+ // COMMON: store void () addrspace(4)* addrspacecast (void () addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to void () addrspace(1)*) to void () addrspace(4)*), void () addrspace(4)** %block_A
void (^const block_A)(void) = ^{
return;
};
// Emits global block literal [[BLG9]] and invoke function [[INVG9]].
- // COMMON: store void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG9]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*), void (i8 addrspace(3)*) addrspace(4)** %block_B
+ // COMMON: store void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG9]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*), void (i8 addrspace(3)*) addrspace(4)** %block_B
void (^const block_B)(local void *) = ^(local void *a) {
return;
};
// Uses global block literal [[BLG8]] and invoke function [[INVG8]].
- // COMMON: [[r1:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* getelementptr inbounds (%struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic addrspace(4)* addrspacecast (%struct.__opencl_block_literal_generic addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to %struct.__opencl_block_literal_generic addrspace(1)*) to %struct.__opencl_block_literal_generic addrspace(4)*), i32 0, i32 2)
- // COMMON: [[r2:%.*]] = addrspacecast i8 addrspace(4)* [[r1]] to void (i8 addrspace(4)*)*
- // COMMON: call spir_func void [[r2]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON: call spir_func void [[INVG8:.*]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
block_A();
// Emits global block literal [[BLG8]] and block kernel [[INVGK8]]. [[INVGK8]] calls [[INVG8]].
@@ -271,19 +265,17 @@
// COMMON-LABEL: call i32 @__enqueue_kernel_basic(
// COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* byval [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK8:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
enqueue_kernel(default_queue, flags, ndrange, block_A);
// Uses block kernel [[INVGK8]] and global block literal [[BLG8]].
// COMMON: call i32 @__get_kernel_work_group_size_impl(
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK8]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
unsigned size = get_kernel_work_group_size(block_A);
// Uses global block literal [[BLG8]] and invoke function [[INVG8]]. Make sure no redundant block literal and invoke functions are emitted.
- // COMMON: [[r1:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* getelementptr inbounds (%struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic addrspace(4)* addrspacecast (%struct.__opencl_block_literal_generic addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to %struct.__opencl_block_literal_generic addrspace(1)*) to %struct.__opencl_block_literal_generic addrspace(4)*), i32 0, i32 2)
- // COMMON: [[r2:%.*]] = addrspacecast i8 addrspace(4)* [[r1]] to void (i8 addrspace(4)*)*
- // COMMON: call spir_func void [[r2]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON: call spir_func void [[INVG8]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
block_A();
void (^block_C)(void) = ^{
@@ -291,7 +283,6 @@
};
// Emits block literal on stack and block kernel [[INVLK3]].
- // COMMON: store i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVL3:@__device_side_enqueue_block_invoke[^ ]*]] to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %block.invoke
// COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
// COMMON: [[BL_I8:%[0-9]+]] = addrspacecast void ()* {{.*}} to i8 addrspace(4)*
@@ -301,34 +292,34 @@
// COMMON-SAME: i8 addrspace(4)* [[BL_I8]])
enqueue_kernel(default_queue, flags, ndrange, block_C);
- // Emits global block literal [[BLG9]] and block kernel [[INVGK9]]. [[INVGK9]] calls [[INV9]].
+ // Emits global block literal [[BLG9]] and block kernel [[INVGK9]]. [[INVGK9]] calls [[INVG9]].
// COMMON: call i32 @__get_kernel_work_group_size_impl(
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK9:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG9]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG9]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_work_group_size(block_B);
// Uses global block literal [[BLG8]] and block kernel [[INVGK8]]. Make sure no redundant block literal ind invoke functions are emitted.
// COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK8]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_preferred_work_group_size_multiple(block_A);
// Uses global block literal [[BL_GLOBAL]] and block kernel [[INV_G_K]]. [[INV_G_K]] calls [[INV_G]].
// COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INV_G_K:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BL_GLOBAL]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BL_GLOBAL]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_preferred_work_group_size_multiple(block_G);
// Emits global block literal [[BLG10]] and block kernel [[INVGK10]].
// COMMON: call i32 @__get_kernel_max_sub_group_size_for_ndrange_impl(%struct.ndrange_t* {{[^,]+}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK10:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG10]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG10]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_max_sub_group_size_for_ndrange(ndrange, ^(){});
// Emits global block literal [[BLG11]] and block kernel [[INVGK11]].
// COMMON: call i32 @__get_kernel_sub_group_count_for_ndrange_impl(%struct.ndrange_t* {{[^,]+}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK11:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG11]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG11]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_sub_group_count_for_ndrange(ndrange, ^(){});
}
@@ -350,7 +341,7 @@
// COMMON: }
// COMMON: define internal spir_kernel void [[INVGK7]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}})
// COMMON: define internal spir_func void [[INVG8]](i8 addrspace(4)*{{.*}})
-// COMMON: define internal spir_func void [[INVG9]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)* %{{.*}})
+// COMMON: define internal spir_func void [[INVG9:.*]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)* %{{.*}})
// COMMON: define internal spir_kernel void [[INVGK8]](i8 addrspace(4)*{{.*}})
// COMMON: define internal spir_kernel void [[INVLK3]](i8 addrspace(4)*{{.*}})
// COMMON: define internal spir_kernel void [[INVGK9]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}})
diff --git a/test/CodeGenOpenCL/inline-asm-amdgcn.cl b/test/CodeGenOpenCL/inline-asm-amdgcn.cl
new file mode 100644
index 0000000..ccd9821
--- /dev/null
+++ b/test/CodeGenOpenCL/inline-asm-amdgcn.cl
@@ -0,0 +1,8 @@
+// REQUIRES: amdgpu-registered-target
+// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn %s | FileCheck %s
+
+kernel void test_long(int arg0) {
+ long v15_16;
+ // CHECK: tail call i64 asm sideeffect "v_lshlrev_b64 v[15:16], 0, $0", "={v[15:16]},v"(i32 %arg0)
+ __asm volatile("v_lshlrev_b64 v[15:16], 0, %0" : "={v[15:16]}"(v15_16) : "v"(arg0));
+}
diff --git a/test/Driver/Inputs/libomptarget/libomptarget-nvptx-sm_20.bc b/test/Driver/Inputs/libomptarget/libomptarget-nvptx-sm_20.bc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Driver/Inputs/libomptarget/libomptarget-nvptx-sm_20.bc
diff --git a/test/Driver/Inputs/resource_dir/lib/linux/libclang_rt.hwasan-x86_64.a.syms b/test/Driver/Inputs/resource_dir/lib/linux/libclang_rt.hwasan-x86_64.a.syms
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/linux/libclang_rt.hwasan-x86_64.a.syms
diff --git a/test/Driver/XRay/xray-instrument-os.c b/test/Driver/XRay/xray-instrument-os.c
index 86b109b..7e22136 100644
--- a/test/Driver/XRay/xray-instrument-os.c
+++ b/test/Driver/XRay/xray-instrument-os.c
@@ -1,4 +1,4 @@
// RUN: not %clang -o /dev/null -v -fxray-instrument -c %s
-// XFAIL: -linux-
+// XFAIL: -linux-, -freebsd
// REQUIRES-ANY: amd64, x86_64, x86_64h, arm, aarch64, arm64
typedef int a;
diff --git a/test/Driver/android-pie.c b/test/Driver/android-pie.c
index 2569c55..052c0bc 100644
--- a/test/Driver/android-pie.c
+++ b/test/Driver/android-pie.c
@@ -64,3 +64,20 @@
// RUN: | FileCheck --check-prefix=NO-PIE %s
// RUN: %clang %s -### -o %t.o 2>&1 -pie -no-pie --target=arm-linux-androideabi24 \
// RUN: | FileCheck --check-prefix=NO-PIE %s
+
+// Static/shared/relocatable disable -pie
+
+// RUN: %clang %s -### --target=aarch64-linux-android -static 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-STATIC
+// CHECK-STATIC-NOT: "-pie"
+// CHECK-STATIC: -static
+
+// RUN: %clang %s -### --target=aarch64-linux-android -shared 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-SHARED
+// CHECK-SHARED-NOT: "-pie"
+// CHECK-SHARED: "-shared"
+
+// RUN: %clang %s -### --target=aarch64-linux-android -r 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-RELOCATABLE
+// CHECK-RELOCATABLE-NOT: "-pie"
+// CHECK-RELOCATABLE: "-r"
diff --git a/test/Driver/arm-execute-only.c b/test/Driver/arm-execute-only.c
index c226a7f..866d727 100644
--- a/test/Driver/arm-execute-only.c
+++ b/test/Driver/arm-execute-only.c
@@ -21,10 +21,6 @@
// RUN: %clang -target armv7m-eabi -x assembler -mexecute-only %s -c -### 2>&1 \
// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY -check-prefix CHECK-NO-EXECUTE-ONLY-ASM
-//
-// CHECK-NO-EXECUTE-ONLY-NOT: "-backend-option" "-arm-execute-only"
-// CHECK-EXECUTE-ONLY: "-backend-option" "-arm-execute-only"
-
// CHECK-EXECUTE-ONLY-NOT-SUPPORTED: error: execute only is not supported for the thumbv6m sub-architecture
// CHECK-EXECUTE-ONLY-NO-MOVT: error: option '-mexecute-only' cannot be specified with '-mno-movt'
// CHECK-EXECUTE-ONLY-LONG-CALLS: error: option '-mexecute-only' cannot be specified with '-mlong-calls'
diff --git a/test/Driver/fno-escaping-block-tail-calls.c b/test/Driver/fno-escaping-block-tail-calls.c
index 2d1b0a3..14372c0 100644
--- a/test/Driver/fno-escaping-block-tail-calls.c
+++ b/test/Driver/fno-escaping-block-tail-calls.c
@@ -4,4 +4,6 @@
// RUN: %clang -### %s -fno-escaping-block-tail-calls -fescaping-block-tail-calls 2> %t
// RUN: FileCheck --check-prefix=CHECK-NO-DISABLE < %t %s
+// RUN: %clang -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-NO-DISABLE < %t %s
// CHECK-NO-DISABLE-NOT: "-fno-escaping-block-tail-calls"
diff --git a/test/Driver/fsanitize-blacklist.c b/test/Driver/fsanitize-blacklist.c
index 0dce1a2..ffd637c 100644
--- a/test/Driver/fsanitize-blacklist.c
+++ b/test/Driver/fsanitize-blacklist.c
@@ -23,7 +23,7 @@
// Check that the default blacklist is not added as an extra dependency.
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-BLACKLIST-ASAN --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
// CHECK-DEFAULT-BLACKLIST-ASAN: -fsanitize-blacklist={{.*[^w]}}asan_blacklist.txt
-// RUN: %clang -target aarch64-linux-gnu -fsanitize=hwaddress -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-BLACKLIST-HWASAN --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-BLACKLIST-HWASAN --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
// CHECK-DEFAULT-BLACKLIST-HWASAN: -fsanitize-blacklist={{.*}}hwasan_blacklist.txt
// RUN: %clang -target x86_64-linux-gnu -fsanitize=integer -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c
index d92df55..a2f12c6 100644
--- a/test/Driver/fsanitize.c
+++ b/test/Driver/fsanitize.c
@@ -83,13 +83,13 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANA
// CHECK-SANKA-SANA: '-fsanitize=kernel-address' not allowed with '-fsanitize=address'
-// RUN: %clang -target aarch64-linux-gnu -fsanitize=hwaddress,thread -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANT
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress,thread -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANT
// CHECK-SANHA-SANT: '-fsanitize=hwaddress' not allowed with '-fsanitize=thread'
-// RUN: %clang -target aarch64-linux-gnu -fsanitize=hwaddress,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANM
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANM
// CHECK-SANHA-SANM: '-fsanitize=hwaddress' not allowed with '-fsanitize=memory'
-// RUN: %clang -target aarch64-linux-gnu -fsanitize=hwaddress,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANA
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANA
// CHECK-SANHA-SANA: '-fsanitize=hwaddress' not allowed with '-fsanitize=address'
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,leak -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANL
@@ -388,6 +388,25 @@
// RUN: %clang -target armv7-apple-ios7 -miphoneos-version-min=7.0 -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-IOS
// CHECK-ASAN-IOS: -fsanitize=address
+// RUN %clang -target i386-pc-openbsd -fsanitize=undefined %s -### 2>&1 | FileCheck --check-prefix=CHECK-UBSAN-OPENBSD
+// CHECK-UBSAN-OPENBSD: -fsanitize=undefined
+
+// RUN: %clang -target i386-pc-openbsd -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-OPENBSD
+// CHECK-ASAN-OPENBSD: unsupported option '-fsanitize=address' for target 'i386-pc-openbsd'
+
+// RUN: %clang -target i386-pc-openbsd -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-OPENBSD
+// CHECK-LSAN-OPENBSD: unsupported option '-fsanitize=leak' for target 'i386-pc-openbsd'
+
+// RUN: %clang -target i386-pc-openbsd -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-OPENBSD
+// CHECK-TSAN-OPENBSD: unsupported option '-fsanitize=thread' for target 'i386-pc-openbsd'
+
+// RUN: %clang -target i386-pc-openbsd -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-OPENBSD
+// CHECK-MSAN-OPENBSD: unsupported option '-fsanitize=memory' for target 'i386-pc-openbsd'
+
+// RUN: %clang -target i386-pc-openbsd -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-OPENBSD
+// RUN: %clang -target i386-pc-openbsd -fsanitize=efficiency-working-set %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-OPENBSD
+// CHECK-ESAN-OPENBSD: error: unsupported option '-fsanitize=efficiency-{{.*}}' for target 'i386-pc-openbsd'
+
// RUN: %clang -target x86_64-apple-darwin -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-DARWIN
// CHECK-LSAN-X86-64-DARWIN-NOT: unsupported option
@@ -468,7 +487,7 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize-trap=address -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-TRAP
// CHECK-ASAN-TRAP: error: unsupported argument 'address' to option '-fsanitize-trap'
-// RUN: %clang -target aarch64-linux-gnu -fsanitize-trap=hwaddress -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-TRAP
+// RUN: %clang -target x86_64-linux-gnu -fsanitize-trap=hwaddress -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-TRAP
// CHECK-HWASAN-TRAP: error: unsupported argument 'hwaddress' to option '-fsanitize-trap'
// RUN: %clang -target x86_64-apple-darwin10 -mmacosx-version-min=10.7 -flto -fsanitize=cfi-vcall -fno-sanitize-trap=cfi -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOTRAP-OLD-MACOS
@@ -599,7 +618,7 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-minimal-runtime -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-UBSAN-MINIMAL
// CHECK-ASAN-UBSAN-MINIMAL: error: invalid argument '-fsanitize-minimal-runtime' not allowed with '-fsanitize=address'
-// RUN: %clang -target aarch64-linux-gnu -fsanitize=hwaddress -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-MINIMAL
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-MINIMAL
// CHECK-HWASAN-MINIMAL: error: invalid argument '-fsanitize-minimal-runtime' not allowed with '-fsanitize=hwaddress'
// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -flto -fvisibility=hidden -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-MINIMAL
@@ -644,8 +663,5 @@
// CHECK-SCUDO-MSAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=memory'
// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-TSAN
// CHECK-SCUDO-TSAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=thread'
-// RUN: %clang -target aarch64-linux-gnu -fsanitize=scudo,hwaddress %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-HWASAN
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,hwaddress %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-HWASAN
// CHECK-SCUDO-HWASAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=hwaddress'
-
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-X86_64
-// CHECK-SANHA-X86_64: unsupported option '-fsanitize=hwaddress' for target
diff --git a/test/Driver/fuchsia.c b/test/Driver/fuchsia.c
index 57dbc73..1ec7935 100644
--- a/test/Driver/fuchsia.c
+++ b/test/Driver/fuchsia.c
@@ -10,6 +10,8 @@
// CHECK: "-fuse-init-array"
// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]"
// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include"
+// CHECK: "-fsanitize=safe-stack"
+// CHECK: "-stack-protector" "2"
// CHECK: "-fno-common"
// CHECK: {{.*}}ld.lld{{.*}}" "-z" "rodynamic"
// CHECK: "--sysroot=[[SYSROOT]]"
@@ -84,31 +86,31 @@
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=fuzzer 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-FUZZER-X86
-// CHECK-FUZZER-X86: "-fsanitize=fuzzer,fuzzer-no-link"
+// CHECK-FUZZER-X86: "-fsanitize=fuzzer,fuzzer-no-link,safe-stack"
// CHECK-FUZZER-X86: "{{.*[/\\]}}libclang_rt.fuzzer-x86_64.a"
// RUN: %clang %s -### --target=aarch64-fuchsia \
// RUN: -fsanitize=fuzzer 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-FUZZER-AARCH64
-// CHECK-FUZZER-AARCH64: "-fsanitize=fuzzer,fuzzer-no-link"
+// CHECK-FUZZER-AARCH64: "-fsanitize=fuzzer,fuzzer-no-link,safe-stack"
// CHECK-FUZZER-AARCH64: "{{.*[/\\]}}libclang_rt.fuzzer-aarch64.a"
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=scudo 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-X86
-// CHECK-SCUDO-X86: "-fsanitize=scudo"
+// CHECK-SCUDO-X86: "-fsanitize=safe-stack,scudo"
// CHECK-SCUDO-X86: "-pie"
// CHECK-SCUDO-X86: "{{.*[/\\]}}libclang_rt.scudo-x86_64.so"
// RUN: %clang %s -### --target=aarch64-fuchsia \
// RUN: -fsanitize=scudo 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-AARCH64
-// CHECK-SCUDO-AARCH64: "-fsanitize=scudo"
+// CHECK-SCUDO-AARCH64: "-fsanitize=safe-stack,scudo"
// CHECK-SCUDO-AARCH64: "-pie"
// CHECK-SCUDO-AARCH64: "{{.*[/\\]}}libclang_rt.scudo-aarch64.so"
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=scudo -fPIC -shared 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-SHARED
-// CHECK-SCUDO-SHARED: "-fsanitize=scudo"
+// CHECK-SCUDO-SHARED: "-fsanitize=safe-stack,scudo"
// CHECK-SCUDO-SHARED: "{{.*[/\\]}}libclang_rt.scudo-x86_64.so"
diff --git a/test/Driver/hexagon-packets.c b/test/Driver/hexagon-packets.c
new file mode 100644
index 0000000..820c731
--- /dev/null
+++ b/test/Driver/hexagon-packets.c
@@ -0,0 +1,10 @@
+// RUN: %clang -target hexagon -### -mpackets %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-PACKETS
+
+// RUN: %clang -target hexagon -### -mno-packets %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-PACKETS
+
+// CHECK-PACKETS: "-target-feature" "+packets"
+
+// CHECK-NO-PACKETS: "-target-feature" "-packets"
+
diff --git a/test/Driver/lto.cu b/test/Driver/lto.cu
new file mode 100644
index 0000000..821dfcd
--- /dev/null
+++ b/test/Driver/lto.cu
@@ -0,0 +1,80 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+
+// -flto causes a switch to llvm-bc object files.
+// RUN: %clangxx -nocudainc -nocudalib -ccc-print-phases -c %s -flto 2> %t
+// RUN: FileCheck -check-prefix=CHECK-COMPILE-ACTIONS < %t %s
+//
+// CHECK-COMPILE-ACTIONS: 2: compiler, {1}, ir, (host-cuda)
+// CHECK-COMPILE-ACTIONS-NOT: lto-bc
+// CHECK-COMPILE-ACTIONS: 12: backend, {11}, lto-bc, (host-cuda)
+
+// RUN: %clangxx -nocudainc -nocudalib -ccc-print-phases %s -flto 2> %t
+// RUN: FileCheck -check-prefix=CHECK-COMPILELINK-ACTIONS < %t %s
+//
+// CHECK-COMPILELINK-ACTIONS: 0: input, "{{.*}}lto.cu", cuda, (host-cuda)
+// CHECK-COMPILELINK-ACTIONS: 1: preprocessor, {0}, cuda-cpp-output
+// CHECK-COMPILELINK-ACTIONS: 2: compiler, {1}, ir, (host-cuda)
+// CHECK-COMPILELINK-ACTIONS: 3: input, "{{.*}}lto.cu", cuda, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 4: preprocessor, {3}, cuda-cpp-output, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 5: compiler, {4}, ir, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 6: backend, {5}, assembler, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 7: assembler, {6}, object, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 8: offload, "device-cuda (nvptx{{.*}}-nvidia-cuda:sm_20)" {7}, object
+// CHECK-COMPILELINK-ACTIONS: 9: offload, "device-cuda (nvptx{{.*}}-nvidia-cuda:sm_20)" {6}, assembler
+// CHECK-COMPILELINK-ACTIONS: 10: linker, {8, 9}, cuda-fatbin, (device-cuda)
+// CHECK-COMPILELINK-ACTIONS: 11: offload, "host-cuda {{.*}}" {2}, "device-cuda{{.*}}" {10}, ir
+// CHECK-COMPILELINK-ACTIONS: 12: backend, {11}, lto-bc, (host-cuda)
+// CHECK-COMPILELINK-ACTIONS: 13: linker, {12}, image, (host-cuda)
+
+// llvm-bc and llvm-ll outputs need to match regular suffixes
+// (unfortunately).
+// RUN: %clangxx %s -nocudainc -nocudalib -flto -save-temps -### 2> %t
+// RUN: FileCheck -check-prefix=CHECK-COMPILELINK-SUFFIXES < %t %s
+//
+// CHECK-COMPILELINK-SUFFIXES: "-o" "[[CPP:.*lto-host.*\.cui]]" "-x" "cuda" "{{.*}}lto.cu"
+// CHECK-COMPILELINK-SUFFIXES: "-o" "[[BC:.*lto-host.*\.bc]]" {{.*}}[[CPP]]"
+// CHECK-COMPILELINK-SUFFIXES: "-o" "[[OBJ:.*lto-host.*\.o]]" {{.*}}[[BC]]"
+// CHECK-COMPILELINK-SUFFIXES: "{{.*}}a.{{(out|exe)}}" {{.*}}[[OBJ]]"
+
+// RUN: %clangxx %s -nocudainc -nocudalib -flto -S -### 2> %t
+// RUN: FileCheck -check-prefix=CHECK-COMPILE-SUFFIXES < %t %s
+//
+// CHECK-COMPILE-SUFFIXES: "-o" "{{.*}}lto.s" "-x" "cuda" "{{.*}}lto.cu"
+
+// RUN: not %clangxx -nocudainc -nocudalib %s -emit-llvm 2>&1 \
+// RUN: | FileCheck --check-prefix=LLVM-LINK %s
+// LLVM-LINK: -emit-llvm cannot be used when linking
+
+// -flto should cause link using gold plugin
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-LTO-ACTION < %t %s
+//
+// CHECK-LINK-LTO-ACTION: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+
+// -flto=full should cause link using gold plugin
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto=full 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-FULL-ACTION < %t %s
+//
+// CHECK-LINK-FULL-ACTION: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+
+// Check that subsequent -fno-lto takes precedence
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto=full -fno-lto 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-NOLTO-ACTION < %t %s
+//
+// CHECK-LINK-NOLTO-ACTION-NOT: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+
+// -flto passes along an explicit debugger tuning argument.
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto -glldb 2> %t
+// RUN: FileCheck -check-prefix=CHECK-TUNING-LLDB < %t %s
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto -g 2> %t
+// RUN: FileCheck -check-prefix=CHECK-NO-TUNING < %t %s
+//
+// CHECK-TUNING-LLDB: "-plugin-opt=-debugger-tune=lldb"
+// CHECK-NO-TUNING-NOT: "-plugin-opt=-debugger-tune
diff --git a/test/Driver/openmp-offload-gpu.c b/test/Driver/openmp-offload-gpu.c
index 16c321b..152e03a 100644
--- a/test/Driver/openmp-offload-gpu.c
+++ b/test/Driver/openmp-offload-gpu.c
@@ -142,3 +142,26 @@
// RUN: | FileCheck -check-prefix=CHK-NOLIBDEVICE %s
// CHK-NOLIBDEVICE-NOT: error:{{.*}}sm_60
+
+/// ###########################################################################
+
+/// Check that the runtime bitcode library is part of the compile line. Create a bogus
+/// bitcode library and add it to the LIBRARY_PATH.
+// RUN: env LIBRARY_PATH=%S/Inputs/libomptarget %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
+// RUN: -Xopenmp-target -march=sm_20 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda \
+// RUN: -fopenmp-relocatable-target -save-temps -no-canonical-prefixes %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-BCLIB %s
+
+// CHK-BCLIB: clang{{.*}}-triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-cuda-bitcode{{.*}}libomptarget-nvptx-sm_20.bc
+// CHK-BCLIB-NOT: {{error:|warning:}}
+
+/// ###########################################################################
+
+/// Check that the warning is thrown when the libomptarget bitcode library is not found.
+/// Libomptarget requires sm_35 or newer so an sm_20 bitcode library should never exist.
+// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
+// RUN: -Xopenmp-target -march=sm_20 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda \
+// RUN: -fopenmp-relocatable-target -save-temps -no-canonical-prefixes %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-BCLIB-WARN %s
+
+// CHK-BCLIB-WARN: No library 'libomptarget-nvptx-sm_20.bc' found in the default clang lib directory or in LIBRARY_PATH. Expect degraded performance due to no inlining of runtime functions on target devices.
diff --git a/test/Driver/riscv-arch.c b/test/Driver/riscv-arch.c
new file mode 100644
index 0000000..21d17b7
--- /dev/null
+++ b/test/Driver/riscv-arch.c
@@ -0,0 +1,89 @@
+// RUN: %clang -target riscv32-unknown-elf -march=rv32i -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32im -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ima -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imaf -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imafd -### %s -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ic -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imc -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imac -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imafc -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imafdc -### %s -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ia -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iaf -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iafd -### %s -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iac -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iafc -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iafdc -### %s -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32g -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32gc -### %s -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64i -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64im -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64ima -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imaf -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imafd -### %s -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64ic -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imc -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imac -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imafc -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imafdc -### %s -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64ia -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64iaf -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64iafd -### %s -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64iac -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64iafc -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64iafdc -### %s -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64g -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64gc -### %s -fsyntax-only 2>&1 | FileCheck %s
+
+// CHECK-NOT: error: invalid arch name '
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32 -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32 %s
+// RV32: error: invalid arch name 'rv32'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32m -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32M %s
+// RV32M: error: invalid arch name 'rv32m'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32id -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32ID %s
+// RV32ID: error: invalid arch name 'rv32id'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32l -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32L %s
+// RV32L: error: invalid arch name 'rv32l'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imadf -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32IMADF %s
+// RV32IMADF: error: invalid arch name 'rv32imadf'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imm -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32IMM %s
+// RV32IMM: error: invalid arch name 'rv32imm'
+
+// RUN: %clang -target riscv32-unknown-elf -march=RV32I -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32I-UPPER %s
+// RV32I-UPPER: error: invalid arch name 'RV32I'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64 -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64 %s
+// RV64: error: invalid arch name 'rv64'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64m -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64M %s
+// RV64M: error: invalid arch name 'rv64m'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64id -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64ID %s
+// RV64ID: error: invalid arch name 'rv64id'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64l -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64L %s
+// RV64L: error: invalid arch name 'rv64l'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imadf -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64IMADF %s
+// RV64IMADF: error: invalid arch name 'rv64imadf'
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imm -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64IMM %s
+// RV64IMM: error: invalid arch name 'rv64imm'
+
+// RUN: %clang -target riscv64-unknown-elf -march=RV64I -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64I-UPPER %s
+// RV64I-UPPER: error: invalid arch name 'RV64I'
diff --git a/test/Driver/sanitizer-ld.c b/test/Driver/sanitizer-ld.c
index 107cf9d..c3d628a 100644
--- a/test/Driver/sanitizer-ld.c
+++ b/test/Driver/sanitizer-ld.c
@@ -514,7 +514,7 @@
// RUN: --sysroot=%S/Inputs/basic_android_tree \
// RUN: | FileCheck --check-prefix=CHECK-CFI-CROSS-DSO-ANDROID %s
// CHECK-CFI-CROSS-DSO-ANDROID: "{{.*}}ld{{(.exe)?}}"
-// CHECK-CFI-CROSS-DSO-ANDROID-NOT: libclang_rt.
+// CHECK-CFI-CROSS-DSO-ANDROID-NOT: libclang_rt.cfi
// Cross-DSO CFI with diagnostics on Android links just the UBSAN runtime.
// RUN: %clang -fsanitize=cfi -fsanitize-cfi-cross-dso %s -### -o %t.o 2>&1 \
@@ -696,54 +696,100 @@
// CHECK-SCUDO-ANDROID-STATIC: "-lpthread"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target x86_64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-HWASAN-X86-64-LINUX %s
+//
+// CHECK-HWASAN-X86-64-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-HWASAN-X86-64-LINUX: "-pie"
+// CHECK-HWASAN-X86-64-LINUX-NOT: "-lc"
+// CHECK-HWASAN-X86-64-LINUX: libclang_rt.hwasan-x86_64.a"
+// CHECK-HWASAN-X86-64-LINUX-NOT: "--export-dynamic"
+// CHECK-HWASAN-X86-64-LINUX: "--dynamic-list={{.*}}libclang_rt.hwasan-x86_64.a.syms"
+// CHECK-HWASAN-X86-64-LINUX-NOT: "--export-dynamic"
+// CHECK-HWASAN-X86-64-LINUX: "-lpthread"
+// CHECK-HWASAN-X86-64-LINUX: "-lrt"
+// CHECK-HWASAN-X86-64-LINUX: "-ldl"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target x86_64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
+// RUN: -shared-libsan -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-SHARED-HWASAN-X86-64-LINUX %s
+//
+// CHECK-SHARED-HWASAN-X86-64-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-SHARED-HWASAN-X86-64-LINUX: "-pie"
+// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "-lc"
+// CHECK-SHARED-HWASAN-X86-64-LINUX: libclang_rt.hwasan-x86_64.so"
+// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "-lpthread"
+// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "-lrt"
+// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "-ldl"
+// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "--export-dynamic"
+// CHECK-SHARED-HWASAN-X86-64-LINUX-NOT: "--dynamic-list"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.so -shared 2>&1 \
+// RUN: -target x86_64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
+// RUN: -shared-libsan -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-DSO-SHARED-HWASAN-X86-64-LINUX %s
+//
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-DSO_SHARED-HWASAN-X86-64-LINUX: "-pie"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "-lc"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX: libclang_rt.hwasan-x86_64.so"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "-lpthread"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "-lrt"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "-ldl"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "--export-dynamic"
+// CHECK-DSO-SHARED-HWASAN-X86-64-LINUX-NOT: "--dynamic-list"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
-// RUN: | FileCheck --check-prefix=CHECK-HWASAN-LINUX %s
+// RUN: | FileCheck --check-prefix=CHECK-HWASAN-AARCH64-LINUX %s
//
-// CHECK-HWASAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
-// CHECK-HWASAN-LINUX-NOT: "-lc"
-// CHECK-HWASAN-LINUX: libclang_rt.hwasan-aarch64.a"
-// CHECK-HWASAN-LINUX-NOT: "--export-dynamic"
-// CHECK-HWASAN-LINUX: "--dynamic-list={{.*}}libclang_rt.hwasan-aarch64.a.syms"
-// CHECK-HWASAN-LINUX-NOT: "--export-dynamic"
-// CHECK-HWASAN-LINUX: "-lpthread"
-// CHECK-HWASAN-LINUX: "-lrt"
-// CHECK-HWASAN-LINUX: "-ldl"
-
-// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress -shared-libsan \
-// RUN: -resource-dir=%S/Inputs/resource_dir \
-// RUN: --sysroot=%S/Inputs/basic_linux_tree \
-// RUN: | FileCheck --check-prefix=CHECK-SHARED-HWASAN-LINUX %s
+// CHECK-HWASAN-AARCH64-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-HWASAN-AARCH64-LINUX: "-pie"
+// CHECK-HWASAN-AARCH64-LINUX-NOT: "-lc"
+// CHECK-HWASAN-AARCH64-LINUX: libclang_rt.hwasan-aarch64.a"
+// CHECK-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic"
+// CHECK-HWASAN-AARCH64-LINUX: "--dynamic-list={{.*}}libclang_rt.hwasan-aarch64.a.syms"
+// CHECK-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic"
+// CHECK-HWASAN-AARCH64-LINUX: "-lpthread"
+// CHECK-HWASAN-AARCH64-LINUX: "-lrt"
+// CHECK-HWASAN-AARCH64-LINUX: "-ldl"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
// RUN: -shared-libsan \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
-// RUN: | FileCheck --check-prefix=CHECK-SHARED-HWASAN-LINUX %s
+// RUN: | FileCheck --check-prefix=CHECK-SHARED-HWASAN-AARCH64-LINUX %s
//
-// CHECK-SHARED-HWASAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
-// CHECK-SHARED-HWASAN-LINUX-NOT: "-lc"
-// CHECK-SHARED-HWASAN-LINUX: libclang_rt.hwasan-aarch64.so"
-// CHECK-SHARED-HWASAN-LINUX-NOT: "-lpthread"
-// CHECK-SHARED-HWASAN-LINUX-NOT: "-lrt"
-// CHECK-SHARED-HWASAN-LINUX-NOT: "-ldl"
-// CHECK-SHARED-HWASAN-LINUX-NOT: "--export-dynamic"
-// CHECK-SHARED-HWASAN-LINUX-NOT: "--dynamic-list"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX: "-pie"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lc"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX: libclang_rt.hwasan-aarch64.so"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lpthread"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lrt"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "-ldl"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic"
+// CHECK-SHARED-HWASAN-AARCH64-LINUX-NOT: "--dynamic-list"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.so -shared 2>&1 \
-// RUN: -target aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress -shared-libsan \
-// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: -target aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
+// RUN: -shared-libsan -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
-// RUN: | FileCheck --check-prefix=CHECK-DSO-SHARED-HWASAN-LINUX %s
+// RUN: | FileCheck --check-prefix=CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX %s
//
-// CHECK-DSO-SHARED-HWASAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
-// CHECK-DSO-SHARED-HWASAN-LINUX-NOT: "-lc"
-// CHECK-DSO-SHARED-HWASAN-LINUX: libclang_rt.hwasan-aarch64.so"
-// CHECK-DSO-SHARED-HWASAN-LINUX-NOT: "-lpthread"
-// CHECK-DSO-SHARED-HWASAN-LINUX-NOT: "-lrt"
-// CHECK-DSO-SHARED-HWASAN-LINUX-NOT: "-ldl"
-// CHECK-DSO-SHARED-HWASAN-LINUX-NOT: "--export-dynamic"
-// CHECK-DSO-SHARED-HWASAN-LINUX-NOT: "--dynamic-list"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-DSO_SHARED-HWASAN-AARCH64-LINUX: "-pie"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lc"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX: libclang_rt.hwasan-aarch64.so"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lpthread"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lrt"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-ldl"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic"
+// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "--dynamic-list"
diff --git a/test/Driver/thinlto.cu b/test/Driver/thinlto.cu
new file mode 100644
index 0000000..c5a76b0
--- /dev/null
+++ b/test/Driver/thinlto.cu
@@ -0,0 +1,54 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+
+// -flto=thin causes a switch to llvm-bc object files.
+// RUN: %clangxx -ccc-print-phases -nocudainc -nocudalib -c %s -flto=thin 2> %t
+// RUN: FileCheck -check-prefix=CHECK-COMPILE-ACTIONS < %t %s
+//
+// CHECK-COMPILE-ACTIONS: 2: compiler, {1}, ir, (host-cuda)
+// CHECK-COMPILE-ACTIONS-NOT: lto-bc
+// CHECK-COMPILE-ACTIONS: 12: backend, {11}, lto-bc, (host-cuda)
+
+// RUN: %clangxx -ccc-print-phases -nocudainc -nocudalib %s -flto=thin 2> %t
+// RUN: FileCheck -check-prefix=CHECK-COMPILELINK-ACTIONS < %t %s
+//
+// CHECK-COMPILELINK-ACTIONS: 0: input, "{{.*}}thinlto.cu", cuda, (host-cuda)
+// CHECK-COMPILELINK-ACTIONS: 1: preprocessor, {0}, cuda-cpp-output
+// CHECK-COMPILELINK-ACTIONS: 2: compiler, {1}, ir, (host-cuda)
+// CHECK-COMPILELINK-ACTIONS: 3: input, "{{.*}}thinlto.cu", cuda, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 4: preprocessor, {3}, cuda-cpp-output, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 5: compiler, {4}, ir, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 6: backend, {5}, assembler, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 7: assembler, {6}, object, (device-cuda, sm_20)
+// CHECK-COMPILELINK-ACTIONS: 8: offload, "device-cuda (nvptx{{.*}}-nvidia-cuda:sm_20)" {7}, object
+// CHECK-COMPILELINK-ACTIONS: 9: offload, "device-cuda (nvptx{{.*}}-nvidia-cuda:sm_20)" {6}, assembler
+// CHECK-COMPILELINK-ACTIONS: 10: linker, {8, 9}, cuda-fatbin, (device-cuda)
+// CHECK-COMPILELINK-ACTIONS: 11: offload, "host-cuda {{.*}}" {2}, "device-cuda{{.*}}" {10}, ir
+// CHECK-COMPILELINK-ACTIONS: 12: backend, {11}, lto-bc, (host-cuda)
+// CHECK-COMPILELINK-ACTIONS: 13: linker, {12}, image, (host-cuda)
+
+// -flto=thin should cause link using gold plugin with thinlto option,
+// also confirm that it takes precedence over earlier -fno-lto and -flto=full.
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto=full -fno-lto -flto=thin 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-THIN-ACTION < %t %s
+//
+// CHECK-LINK-THIN-ACTION: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+// CHECK-LINK-THIN-ACTION: "-plugin-opt=thinlto"
+
+// Check that subsequent -flto=full takes precedence
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto=thin -flto=full 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-FULL-ACTION < %t %s
+//
+// CHECK-LINK-FULL-ACTION: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+// CHECK-LINK-FULL-ACTION-NOT: "-plugin-opt=thinlto"
+
+// Check that subsequent -fno-lto takes precedence
+// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: -target x86_64-unknown-linux -### %s -flto=thin -fno-lto 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-NOLTO-ACTION < %t %s
+//
+// CHECK-LINK-NOLTO-ACTION-NOT: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+// CHECK-LINK-NOLTO-ACTION-NOT: "-plugin-opt=thinlto"
diff --git a/test/Index/Inputs/reparse-issue.h b/test/Index/Inputs/reparse-issue.h
new file mode 100644
index 0000000..79f1d88
--- /dev/null
+++ b/test/Index/Inputs/reparse-issue.h
@@ -0,0 +1,3 @@
+
+asdf;
+
diff --git a/test/Index/Inputs/reparse-issue.h-0 b/test/Index/Inputs/reparse-issue.h-0
new file mode 100644
index 0000000..f004abf
--- /dev/null
+++ b/test/Index/Inputs/reparse-issue.h-0
@@ -0,0 +1,4 @@
+//
+//
+asdf;
+
diff --git a/test/Index/Inputs/reparse-issue.h-1 b/test/Index/Inputs/reparse-issue.h-1
new file mode 100644
index 0000000..9f9dde8
--- /dev/null
+++ b/test/Index/Inputs/reparse-issue.h-1
@@ -0,0 +1,5 @@
+//
+//
+//
+asdf;
+
diff --git a/test/Index/missing_vfs.c b/test/Index/missing_vfs.c
new file mode 100644
index 0000000..61aedd4
--- /dev/null
+++ b/test/Index/missing_vfs.c
@@ -0,0 +1,6 @@
+// RUN: c-index-test -test-load-source local %s -ivfsoverlay %t/does-not-exist.yaml &> %t.out
+// RUN: FileCheck -check-prefix=STDERR %s < %t.out
+// STDERR: fatal error: virtual filesystem overlay file '{{.*}}' not found
+// RUN: FileCheck %s < %t.out
+// CHECK: missing_vfs.c:[[@LINE+1]]:6: FunctionDecl=foo:[[@LINE+1]]:6
+void foo(void);
diff --git a/test/Index/reparsed-live-issue.cpp b/test/Index/reparsed-live-issue.cpp
new file mode 100644
index 0000000..56423de
--- /dev/null
+++ b/test/Index/reparsed-live-issue.cpp
@@ -0,0 +1,4 @@
+// RUN: env CINDEXTEST_EDITING=1 LIBCLANG_DISABLE_CRASH_RECOVERY=1 c-index-test -test-load-source-reparse 2 none -remap-file-0=%S/Inputs/reparse-issue.h,%S/Inputs/reparse-issue.h-0 -remap-file-1=%S/Inputs/reparse-issue.h,%S/Inputs/reparse-issue.h-1 -- %s 2>&1 | FileCheck %s
+#include "Inputs/reparse-issue.h"
+
+// CHECK: reparse-issue.h:4:1:{1:1-1:1}: error: C++ requires a type specifier for all declarations
diff --git a/test/Misc/ast-dump-decl.cpp b/test/Misc/ast-dump-decl.cpp
index c689149..21ba7ec 100644
--- a/test/Misc/ast-dump-decl.cpp
+++ b/test/Misc/ast-dump-decl.cpp
@@ -360,7 +360,9 @@
template<> void foo<int>(int a) { }
};
// CHECK: ClassScopeFunctionSpecializationDecl
-// CHECK-NEXT: CXXMethod{{.*}} 'foo' 'void (int)'
+// CHECK-NEXT: CXXMethod{{.*}} foo 'void (int)'
+// CHECK-NEXT: ParmVarDecl
+// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: TemplateArgument{{.*}} 'int'
namespace TestTemplateTypeParmDecl {
diff --git a/test/Sema/attr-print.cpp b/test/Misc/attr-print-emit.cpp
similarity index 96%
rename from test/Sema/attr-print.cpp
rename to test/Misc/attr-print-emit.cpp
index 1828c3b..cc7413b 100644
--- a/test/Sema/attr-print.cpp
+++ b/test/Misc/attr-print-emit.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 %s -ast-print | FileCheck %s
+// RUN: %clang -emit-ast -o %t.ast %s
+// RUN: %clang_cc1 %t.ast -ast-print | FileCheck %s
// CHECK: void xla(int a) __attribute__((xray_log_args(1)));
void xla(int a) __attribute__((xray_log_args(1)));
diff --git a/test/Misc/pragma-attribute-supported-attributes-list.test b/test/Misc/pragma-attribute-supported-attributes-list.test
index 1004459..c911c50 100644
--- a/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -2,7 +2,7 @@
// The number of supported attributes should never go down!
-// CHECK: #pragma clang attribute supports 67 attributes:
+// CHECK: #pragma clang attribute supports 68 attributes:
// CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function)
@@ -12,6 +12,7 @@
// CHECK-NEXT: AlignValue (SubjectMatchRule_variable, SubjectMatchRule_type_alias)
// CHECK-NEXT: AllocSize (SubjectMatchRule_function)
// CHECK-NEXT: Annotate ()
+// CHECK-NEXT: AnyX86NoCfCheck (SubjectMatchRule_hasType_functionType)
// CHECK-NEXT: AssumeAligned (SubjectMatchRule_objc_method, SubjectMatchRule_function)
// CHECK-NEXT: Availability ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable))
// CHECK-NEXT: CXX11NoReturn (SubjectMatchRule_function)
diff --git a/test/Modules/Inputs/bad-private-include/Bad.framework/Headers/Bad.h b/test/Modules/Inputs/bad-private-include/Bad.framework/Headers/Bad.h
new file mode 100644
index 0000000..eea0549
--- /dev/null
+++ b/test/Modules/Inputs/bad-private-include/Bad.framework/Headers/Bad.h
@@ -0,0 +1 @@
+#import <Bad/Shared.h>
\ No newline at end of file
diff --git a/test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.modulemap b/test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.modulemap
new file mode 100644
index 0000000..11612dc
--- /dev/null
+++ b/test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.modulemap
@@ -0,0 +1,5 @@
+framework module Bad {
+ umbrella header "Bad.h"
+ export *
+ module * { export * }
+}
diff --git a/test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.private.modulemap b/test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.private.modulemap
new file mode 100644
index 0000000..043139d
--- /dev/null
+++ b/test/Modules/Inputs/bad-private-include/Bad.framework/Modules/module.private.modulemap
@@ -0,0 +1,5 @@
+framework module Bad_Private {
+ umbrella header "BadPrivate.h"
+ export *
+ module * { export * }
+}
diff --git a/test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/BadPrivate.h b/test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/BadPrivate.h
new file mode 100644
index 0000000..eea0549
--- /dev/null
+++ b/test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/BadPrivate.h
@@ -0,0 +1 @@
+#import <Bad/Shared.h>
\ No newline at end of file
diff --git a/test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/Shared.h b/test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/Shared.h
new file mode 100644
index 0000000..4f1defd
--- /dev/null
+++ b/test/Modules/Inputs/bad-private-include/Bad.framework/PrivateHeaders/Shared.h
@@ -0,0 +1,3 @@
+struct SomeDecl {
+ int x;
+};
diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map
index 4788daa..93fe468 100644
--- a/test/Modules/Inputs/module.map
+++ b/test/Modules/Inputs/module.map
@@ -460,3 +460,13 @@
header "innerstructredef.h"
}
}
+
+module template_nontrivial0 {
+ header "template-nontrivial0.h"
+ export *
+}
+
+module template_nontrivial1 {
+ header "template-nontrivial1.h"
+ export *
+}
diff --git a/test/Modules/Inputs/self-referencing-lambda/a.h b/test/Modules/Inputs/self-referencing-lambda/a.h
new file mode 100644
index 0000000..756fe18
--- /dev/null
+++ b/test/Modules/Inputs/self-referencing-lambda/a.h
@@ -0,0 +1,4 @@
+void f() {
+ int x = 0;
+ auto q = [xm = x]{};
+}
diff --git a/test/Modules/Inputs/self-referencing-lambda/module.modulemap b/test/Modules/Inputs/self-referencing-lambda/module.modulemap
new file mode 100644
index 0000000..812ca9d
--- /dev/null
+++ b/test/Modules/Inputs/self-referencing-lambda/module.modulemap
@@ -0,0 +1,4 @@
+module "a.h" {
+ header "a.h"
+ export *
+}
diff --git a/test/Modules/Inputs/template-nontrivial0.h b/test/Modules/Inputs/template-nontrivial0.h
new file mode 100644
index 0000000..cff080e
--- /dev/null
+++ b/test/Modules/Inputs/template-nontrivial0.h
@@ -0,0 +1,13 @@
+template <class T>
+struct Class0 {
+ Class0();
+ Class0(const Class0<T> &);
+ ~Class0();
+ T *p;
+};
+
+struct S0 {
+ id x;
+};
+
+Class0<S0> returnNonTrivial();
diff --git a/test/Modules/Inputs/template-nontrivial1.h b/test/Modules/Inputs/template-nontrivial1.h
new file mode 100644
index 0000000..24136f0
--- /dev/null
+++ b/test/Modules/Inputs/template-nontrivial1.h
@@ -0,0 +1,6 @@
+@import template_nontrivial0;
+
+struct S1 {
+ S1();
+ Class0<S0> a;
+};
diff --git a/test/Modules/bad-private-include.m b/test/Modules/bad-private-include.m
new file mode 100644
index 0000000..e12b280
--- /dev/null
+++ b/test/Modules/bad-private-include.m
@@ -0,0 +1,6 @@
+// RUN: rm -rf %t.cache
+// RUN: %clang_cc1 -fmodules-cache-path=%t.cache -fmodules -fimplicit-module-maps -F %S/Inputs/bad-private-include %s -verify
+
+// expected-no-diagnostics
+
+@import Bad;
diff --git a/test/Modules/implicit-private-with-submodule.m b/test/Modules/implicit-private-with-submodule.m
index 1779341..a1c5b92 100644
--- a/test/Modules/implicit-private-with-submodule.m
+++ b/test/Modules/implicit-private-with-submodule.m
@@ -13,7 +13,7 @@
// expected-warning@Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap:1{{private submodule 'A.Private' in private module map, expected top-level module}}
// expected-note@Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap:1{{rename 'A.Private' to ensure it can be found by name}}
-// CHECK: fix-it:"{{.*}}module.private.modulemap":{1:20-1:27}:"A_Private"
+// CHECK: fix-it:"{{.*}}module.private.modulemap":{1:18-1:27}:"A_Private"
#ifndef HEADER
#define HEADER
diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp
index 5991dd0..fc193fa 100644
--- a/test/Modules/odr_hash.cpp
+++ b/test/Modules/odr_hash.cpp
@@ -2287,6 +2287,128 @@
} // namespace BaseClass
+namespace PointersAndReferences {
+#if defined(FIRST) || defined(SECOND)
+template<typename> struct Wrapper{};
+#endif
+
+#if defined(FIRST)
+struct S1 {
+ Wrapper<int*> x;
+};
+#elif defined(SECOND)
+struct S1 {
+ Wrapper<float*> x;
+};
+#else
+S1 s1;
+// expected-error@first.h:* {{PointersAndReferences::S1::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S1' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S2 {
+ Wrapper<int &&> x;
+};
+#elif defined(SECOND)
+struct S2 {
+ Wrapper<float &&> x;
+};
+#else
+S2 s2;
+// expected-error@first.h:* {{PointersAndReferences::S2::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S2' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S3 {
+ Wrapper<int *> x;
+};
+#elif defined(SECOND)
+struct S3 {
+ Wrapper<float *> x;
+};
+#else
+S3 s3;
+// expected-error@first.h:* {{PointersAndReferences::S3::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S3' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S4 {
+ Wrapper<int &> x;
+};
+#elif defined(SECOND)
+struct S4 {
+ Wrapper<float &> x;
+};
+#else
+S4 s4;
+// expected-error@first.h:* {{PointersAndReferences::S4::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S4' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S5 {
+ Wrapper<S5 *> x;
+};
+#elif defined(SECOND)
+struct S5 {
+ Wrapper<const S5 *> x;
+};
+#else
+S5 s5;
+// expected-error@second.h:* {{'PointersAndReferences::S5::x' from module 'SecondModule' is not present in definition of 'PointersAndReferences::S5' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S6 {
+ Wrapper<int &> x;
+};
+#elif defined(SECOND)
+struct S6 {
+ Wrapper<const int &> x;
+};
+#else
+S6 s6;
+// expected-error@first.h:* {{PointersAndReferences::S6::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S6' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+#define DECLS \
+ Wrapper<int *> x1; \
+ Wrapper<float *> x2; \
+ Wrapper<const float *> x3; \
+ Wrapper<int &> x4; \
+ Wrapper<int &&> x5; \
+ Wrapper<const int &> x6; \
+ Wrapper<S1 *> x7; \
+ Wrapper<S1 &> x8; \
+ Wrapper<S1 &&> x9;
+
+#if defined(FIRST) || defined(SECOND)
+struct Valid1 {
+ DECLS
+};
+#else
+Valid1 v1;
+#endif
+
+#if defined(FIRST) || defined(SECOND)
+struct Invalid1 {
+ DECLS
+ ACCESS
+};
+#else
+Invalid1 i1;
+// expected-error@second.h:* {{'PointersAndReferences::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
+// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
+#endif
+#undef DECLS
+} // namespace PointersAndReferences
+
+
// Collection of interesting cases below.
// Naive parsing of AST can lead to cycles in processing. Ensure
diff --git a/test/Modules/self-referencing-lambda.cpp b/test/Modules/self-referencing-lambda.cpp
new file mode 100644
index 0000000..1e75d44
--- /dev/null
+++ b/test/Modules/self-referencing-lambda.cpp
@@ -0,0 +1,5 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/self-referencing-lambda %s -verify -emit-obj -std=c++14 -o %t2.o
+// expected-no-diagnostics
+
+#include "a.h"
diff --git a/test/Modules/templates.mm b/test/Modules/templates.mm
index 9c3f327..95e7a9c 100644
--- a/test/Modules/templates.mm
+++ b/test/Modules/templates.mm
@@ -122,3 +122,13 @@
static_assert(alignof(decltype(a)) == 2, "");
static_assert(alignof(decltype(b)) == 2, "");
}
+
+// Check that returnNonTrivial doesn't return Class0<S0> directly in registers.
+
+// CHECK: declare void @_Z16returnNonTrivialv(%struct.Class0* sret)
+
+@import template_nontrivial0;
+@import template_nontrivial1;
+
+S1::S1() : a(returnNonTrivial()) {
+}
diff --git a/test/OpenMP/declare_target_codegen.cpp b/test/OpenMP/declare_target_codegen.cpp
new file mode 100644
index 0000000..ad6718c
--- /dev/null
+++ b/test/OpenMP/declare_target_codegen.cpp
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o -| FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// expected-no-diagnostics
+
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// CHECK-NOT: define {{.*}}{{baz1|baz4|maini1}}
+// CHECK-DAG: @{{.*}}maini1{{.*}}aaa = internal global i64 23,
+// CHECK-DAG: @b = global i32 15,
+// CHECK-DAG: @d = global i32 0,
+// CHECK-DAG: @c = external global i32,
+
+// CHECK-DAG: define {{.*}}i32 @{{.*}}{{foo|bar|baz2|baz3}}{{.*}}()
+
+#ifndef HEADER
+#define HEADER
+
+int foo();
+
+int baz1();
+
+int baz2();
+
+int baz4() { return 5; }
+
+#pragma omp declare target
+int foo() { return 0; }
+int b = 15;
+int d;
+#pragma omp end declare target
+int c;
+
+int bar() { return 1 + foo() + bar() + baz1() + baz2(); }
+
+int maini1() {
+ int a;
+ static long aa = 32;
+// CHECK-DAG: define void @__omp_offloading_{{.*}}maini1{{.*}}_l[[@LINE+1]](i32* dereferenceable{{.*}}, i64 {{.*}}, i64 {{.*}})
+#pragma omp target map(tofrom \
+ : a)
+ {
+ static long aaa = 23;
+ a = foo() + bar() + b + c + d + aa + aaa;
+ }
+ return baz4();
+}
+
+int baz3();
+int baz2() {
+// CHECK-DAG: define void @__omp_offloading_{{.*}}baz2{{.*}}_l[[@LINE+1]](i64 {{.*}})
+#pragma omp target
+ ++c;
+ return 2 + baz3();
+}
+int baz3() { return 2 + baz2(); }
+
+// CHECK-NOT: define {{.*}}{{baz1|baz4|maini1}}
+#endif // HEADER
diff --git a/test/OpenMP/declare_target_codegen_globalization.cpp b/test/OpenMP/declare_target_codegen_globalization.cpp
new file mode 100644
index 0000000..db0df9b
--- /dev/null
+++ b/test/OpenMP/declare_target_codegen_globalization.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s
+// expected-no-diagnostics
+
+int foo(int &a) { return a; }
+
+int bar() {
+ int a;
+ return foo(a);
+}
+
+// CHECK: define void @__omp_offloading_{{.*}}maini1{{.*}}_l[[@LINE+5]](i32* dereferenceable{{.*}})
+// CHECK-NOT: @__kmpc_data_sharing_push_stack
+
+int maini1() {
+ int a;
+#pragma omp target parallel map(from:a)
+ {
+ int b;
+ a = foo(b) + bar();
+ }
+ return a;
+}
+
+// parallel region
+// CHECK: define {{.*}}void @{{.*}}(i32* noalias {{.*}}, i32* noalias {{.*}}, i32* dereferenceable{{.*}})
+// CHECK: [[RES:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i64 4, i16 0)
+// CHECK: [[GLOBALS:%.+]] = bitcast i8* [[RES]] to [[GLOBAL_ST:%struct[.].*]]*
+// CHECK: [[B_ADDR:%.+]] = getelementptr inbounds [[GLOBAL_ST]], [[GLOBAL_ST]]* [[GLOBALS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: call {{.*}}[[FOO:@.*foo.*]](i32* dereferenceable{{.*}} [[B_ADDR]])
+// CHECK: call {{.*}}[[BAR:@.*bar.*]]()
+// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[RES]])
+// CHECK: ret void
+
+// CHECK: define {{.*}}[[FOO]](i32* dereferenceable{{.*}})
+// CHECK-NOT: @__kmpc_data_sharing_push_stack
+
+// CHECK: define {{.*}}[[BAR]]()
+// CHECK: [[RES:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i64 4, i16 0)
+// CHECK: [[GLOBALS:%.+]] = bitcast i8* [[RES]] to [[GLOBAL_ST:%struct[.].*]]*
+// CHECK: [[A_ADDR:%.+]] = getelementptr inbounds [[GLOBAL_ST]], [[GLOBAL_ST]]* [[GLOBALS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: call {{.*}}[[FOO]](i32* dereferenceable{{.*}} [[A_ADDR]])
+// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[RES]])
+// CHECK: ret i32
diff --git a/test/OpenMP/declare_target_link_codegen.cpp b/test/OpenMP/declare_target_link_codegen.cpp
new file mode 100644
index 0000000..ceeb5a0
--- /dev/null
+++ b/test/OpenMP/declare_target_link_codegen.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix HOST --check-prefix CHECK
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix DEVICE --check-prefix CHECK
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - | FileCheck %s --check-prefix DEVICE --check-prefix CHECK
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o -| FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+// expected-no-diagnostics
+
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+#ifndef HEADER
+#define HEADER
+
+// HOST: @c = external global i32,
+// DEVICE-NOT: @c =
+// DEVICE: @c_decl_tgt_link_ptr = common global i32* null
+// HOST: @c_decl_tgt_link_ptr = global i32* @c
+// HOST: [[SIZES:@.+]] = private unnamed_addr constant [2 x i64] [i64 4, i64 4]
+// HOST: [[MAPTYPES:@.+]] = private unnamed_addr constant [2 x i64] [i64 35, i64 531]
+// CHECK: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"c_decl_tgt_link_ptr\00"
+// CHECK: @.omp_offloading.entry.c_decl_tgt_link_ptr = weak constant %struct.__tgt_offload_entry { i8* bitcast (i32** @c_decl_tgt_link_ptr to i8*), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name, i32 0, i32 0), i64 8, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK: @llvm.used = appending global [1 x i8*] [i8* bitcast (i32** @c_decl_tgt_link_ptr to i8*)]
+
+extern int c;
+#pragma omp declare target link(c)
+
+int maini1() {
+ int a;
+#pragma omp target map(tofrom : a)
+ {
+ a = c;
+ }
+ return 0;
+}
+
+// DEVICE: define void @__omp_offloading_{{.*}}_{{.*}}maini1{{.*}}_l[[@LINE-7]](i32* dereferenceable{{[^,]*}}
+// DEVICE: [[C_REF:%.+]] = load i32*, i32** @c_decl_tgt_link_ptr,
+// DEVICE: [[C:%.+]] = load i32, i32* [[C_REF]],
+// DEVICE: store i32 [[C]], i32* %
+
+// HOST: define {{.*}}i32 @{{.*}}maini1{{.*}}()
+// HOST: [[BASEPTRS:%.+]] = alloca [2 x i8*],
+// HOST: [[PTRS:%.+]] = alloca [2 x i8*],
+// HOST: getelementptr inbounds [2 x i8*], [2 x i8*]* [[BASEPTRS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// HOST: getelementptr inbounds [2 x i8*], [2 x i8*]* [[PTRS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// HOST: [[BP1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BASEPTRS]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+// HOST: [[BP1_CAST:%.+]] = bitcast i8** [[BP1]] to i32***
+// HOST: store i32** @c_decl_tgt_link_ptr, i32*** [[BP1_CAST]],
+// HOST: [[P1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[PTRS]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+// HOST: [[P1_CAST:%.+]] = bitcast i8** [[P1]] to i32**
+// HOST: store i32* @c, i32** [[P1_CAST]],
+// HOST: [[BP0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BASEPTRS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// HOST: [[P0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[PTRS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// HOST: call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 2, i8** [[BP0]], i8** [[P0]], i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[SIZES]], i{{[0-9]+}} 0, i{{[0-9]+}} 0), i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPTYPES]], i{{[0-9]+}} 0, i{{[0-9]+}} 0))
+// HOST: call void @__omp_offloading_{{.*}}_{{.*}}maini1{{.*}}_l[[@LINE-26]](i32* %{{[^,]+}})
+
+// HOST: define internal void @__omp_offloading_{{.*}}_{{.*}}maini1{{.*}}_l[[@LINE-28]](i32* dereferenceable{{.*}})
+// HOST: [[C:%.*]] = load i32, i32* @c,
+// HOST: store i32 [[C]], i32* %
+
+// CHECK: !{i32 1, !"c_decl_tgt_link_ptr", i32 0, i32 {{[0-9]+}}}
+#endif // HEADER
diff --git a/test/OpenMP/for_codegen.cpp b/test/OpenMP/for_codegen.cpp
index 7c295a0..e26bbaa 100644
--- a/test/OpenMP/for_codegen.cpp
+++ b/test/OpenMP/for_codegen.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope | FileCheck %s --check-prefix=CHECK --check-prefix=LIFETIME
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
@@ -25,8 +25,20 @@
// CHECK-LABEL: loop_with_counter_collapse
void loop_with_counter_collapse() {
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
// CHECK: call void @__kmpc_for_static_init_8(%ident_t* @
// CHECK: call void @__kmpc_for_static_fini(%ident_t* @
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
#pragma omp for collapse(2)
for (int i = 0; i < 4; i++) {
for (int j = i; j < 4; j++) {
diff --git a/test/OpenMP/nvptx_data_sharing.cpp b/test/OpenMP/nvptx_data_sharing.cpp
index 53bac3c..68245c9 100644
--- a/test/OpenMP/nvptx_data_sharing.cpp
+++ b/test/OpenMP/nvptx_data_sharing.cpp
@@ -1,4 +1,4 @@
-// Test device data sharing codegen.
+// Test device global memory data sharing codegen.
///==========================================================================///
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
@@ -15,43 +15,93 @@
int a = 10;
#pragma omp parallel
{
- a = 1000;
+ a = 1000;
+ }
+ int b = 100;
+ int c = 1000;
+ #pragma omp parallel private(c)
+ {
+ int *c1 = &c;
+ b = a + 10000;
}
}
}
/// ========= In the worker function ========= ///
-
-// CK1: define internal void @__omp_offloading_{{.*}}test_ds{{.*}}worker() [[ATTR1:#.*]] {
-// CK1: [[SHAREDARGS:%.+]] = alloca i8**
-// CK1: call i1 @__kmpc_kernel_parallel(i8** %work_fn, i8*** [[SHAREDARGS]], i16 1)
-// CK1: [[SHARGSTMP:%.+]] = load i8**, i8*** [[SHAREDARGS]]
-// CK1: call void @__omp_outlined___wrapper{{.*}}({{.*}}, i8** [[SHARGSTMP]])
+// CK1: {{.*}}define internal void @__omp_offloading{{.*}}test_ds{{.*}}_worker()
+// CK1: call void @llvm.nvvm.barrier0()
+// CK1: call void @__kmpc_data_sharing_init_stack
/// ========= In the kernel function ========= ///
-// CK1: {{.*}}define void @__omp_offloading{{.*}}test_ds{{.*}}() [[ATTR2:#.*]] {
+// CK1: {{.*}}define void @__omp_offloading{{.*}}test_ds{{.*}}()
// CK1: [[SHAREDARGS1:%.+]] = alloca i8**
-// CK1: call void @__kmpc_kernel_prepare_parallel({{.*}}, i8*** [[SHAREDARGS1]], i32 1, i16 1)
+// CK1: [[SHAREDARGS2:%.+]] = alloca i8**
+// CK1: call void @__kmpc_kernel_init
+// CK1: call void @__kmpc_data_sharing_init_stack
+// CK1: [[GLOBALSTACK:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i64 8, i16 0)
+// CK1: [[GLOBALSTACK2:%.+]] = bitcast i8* [[GLOBALSTACK]] to %struct._globalized_locals_ty*
+// CK1: [[A:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[GLOBALSTACK2]], i32 0, i32 0
+// CK1: [[B:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[GLOBALSTACK2]], i32 0, i32 1
+// CK1: store i32 10, i32* [[A]]
+// CK1: call void @__kmpc_kernel_prepare_parallel({{.*}}, i16 1)
+// CK1: call void @__kmpc_begin_sharing_variables(i8*** [[SHAREDARGS1]], i64 1)
// CK1: [[SHARGSTMP1:%.+]] = load i8**, i8*** [[SHAREDARGS1]]
-// CK1: [[SHARGSTMP2:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP1]]
-// CK1: [[SHAREDVAR:%.+]] = bitcast i32* {{.*}} to i8*
+// CK1: [[SHARGSTMP2:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP1]], i64 0
+// CK1: [[SHAREDVAR:%.+]] = bitcast i32* [[A]] to i8*
// CK1: store i8* [[SHAREDVAR]], i8** [[SHARGSTMP2]]
+// CK1: call void @llvm.nvvm.barrier0()
+// CK1: call void @llvm.nvvm.barrier0()
+// CK1: call void @__kmpc_end_sharing_variables()
+// CK1: store i32 100, i32* [[B]]
+// CK1: call void @__kmpc_kernel_prepare_parallel({{.*}}, i16 1)
+// CK1: call void @__kmpc_begin_sharing_variables(i8*** [[SHAREDARGS2]], i64 2)
+// CK1: [[SHARGSTMP3:%.+]] = load i8**, i8*** [[SHAREDARGS2]]
+// CK1: [[SHARGSTMP4:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP3]], i64 0
+// CK1: [[SHAREDVAR1:%.+]] = bitcast i32* [[B]] to i8*
+// CK1: store i8* [[SHAREDVAR1]], i8** [[SHARGSTMP4]]
+// CK1: [[SHARGSTMP12:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP3]], i64 1
+// CK1: [[SHAREDVAR2:%.+]] = bitcast i32* [[A]] to i8*
+// CK1: store i8* [[SHAREDVAR2]], i8** [[SHARGSTMP12]]
+// CK1: call void @llvm.nvvm.barrier0()
+// CK1: call void @llvm.nvvm.barrier0()
+// CK1: call void @__kmpc_end_sharing_variables()
+// CK1: call void @__kmpc_data_sharing_pop_stack(i8* [[GLOBALSTACK]])
+// CK1: call void @__kmpc_kernel_deinit(i16 1)
/// ========= In the data sharing wrapper function ========= ///
-// CK1: {{.*}}define internal void @__omp_outlined___wrapper({{.*}}i8**) [[ATTR1]] {
-// CK1: [[SHAREDARGS2:%.+]] = alloca i8**
-// CK1: store i8** %2, i8*** [[SHAREDARGS2]]
-// CK1: [[SHARGSTMP3:%.+]] = load i8**, i8*** [[SHAREDARGS2]]
-// CK1: [[SHARGSTMP4:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP3]]
-// CK1: [[SHARGSTMP5:%.+]] = bitcast i8** [[SHARGSTMP4]] to i32**
-// CK1: [[SHARGSTMP6:%.+]] = load i32*, i32** [[SHARGSTMP5]]
-// CK1: call void @__omp_outlined__({{.*}}, i32* [[SHARGSTMP6]])
+// CK1: {{.*}}define internal void @__omp_outlined{{.*}}wrapper({{.*}})
+// CK1: [[SHAREDARGS4:%.+]] = alloca i8**
+// CK1: call void @__kmpc_get_shared_variables(i8*** [[SHAREDARGS4]])
+// CK1: [[SHARGSTMP13:%.+]] = load i8**, i8*** [[SHAREDARGS4]]
+// CK1: [[SHARGSTMP14:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP13]], i64 0
+// CK1: [[SHARGSTMP15:%.+]] = bitcast i8** [[SHARGSTMP14]] to i32**
+// CK1: [[SHARGSTMP16:%.+]] = load i32*, i32** [[SHARGSTMP15]]
+// CK1: call void @__omp_outlined__{{.*}}({{.*}}, i32* [[SHARGSTMP16]])
-/// ========= Attributes ========= ///
+/// outlined function for the second parallel region ///
-// CK1-NOT: attributes [[ATTR1]] = { {{.*}}"has-nvptx-shared-depot"{{.*}} }
-// CK1: attributes [[ATTR2]] = { {{.*}}"has-nvptx-shared-depot"{{.*}} }
+// CK1: define internal void @{{.+}}(i32* noalias %{{.+}}, i32* noalias %{{.+}}, i32* dereferenceable{{.+}}, i32* dereferenceable{{.+}})
+// CK1: [[RES:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i64 4, i16 0)
+// CK1: [[GLOBALS:%.+]] = bitcast i8* [[RES]] to [[GLOBAL_TY:%.+]]*
+// CK1: [[C_ADDR:%.+]] = getelementptr inbounds [[GLOBAL_TY]], [[GLOBAL_TY]]* [[GLOBALS]], i32 0, i32 0
+// CK1: store i32* [[C_ADDR]], i32** %
+// CK1: call void @__kmpc_data_sharing_pop_stack(i8* [[RES]])
+
+/// ========= In the data sharing wrapper function ========= ///
+
+// CK1: {{.*}}define internal void @__omp_outlined{{.*}}wrapper({{.*}})
+// CK1: [[SHAREDARGS3:%.+]] = alloca i8**
+// CK1: call void @__kmpc_get_shared_variables(i8*** [[SHAREDARGS3]])
+// CK1: [[SHARGSTMP5:%.+]] = load i8**, i8*** [[SHAREDARGS3]]
+// CK1: [[SHARGSTMP6:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP5]], i64 0
+// CK1: [[SHARGSTMP7:%.+]] = bitcast i8** [[SHARGSTMP6]] to i32**
+// CK1: [[SHARGSTMP8:%.+]] = load i32*, i32** [[SHARGSTMP7]]
+// CK1: [[SHARGSTMP9:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP5]], i64 1
+// CK1: [[SHARGSTMP10:%.+]] = bitcast i8** [[SHARGSTMP9]] to i32**
+// CK1: [[SHARGSTMP11:%.+]] = load i32*, i32** [[SHARGSTMP10]]
+// CK1: call void @__omp_outlined__{{.*}}({{.*}}, i32* [[SHARGSTMP8]], i32* [[SHARGSTMP11]])
#endif
+
diff --git a/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp b/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp
new file mode 100644
index 0000000..bb75680
--- /dev/null
+++ b/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -o - | FileCheck %s --check-prefix HOST --check-prefix CHECK
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix DEVICE --check-prefix CHECK
+// RUN: %clang_cc1 -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - | FileCheck %s --check-prefix DEVICE --check-prefix CHECK
+
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o - | FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o -| FileCheck %s --check-prefix SIMD-ONLY
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - | FileCheck %s --check-prefix SIMD-ONLY
+
+#ifndef HEADER
+#define HEADER
+
+// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
+
+// DEVICE-DAG: [[C_ADDR:.+]] = internal global i32 0,
+// DEVICE-DAG: [[CD_ADDR:@.+]] = global %struct.S zeroinitializer,
+// HOST-DAG: @[[C_ADDR:.+]] = internal global i32 0,
+// HOST-DAG: @[[CD_ADDR:.+]] = global %struct.S zeroinitializer,
+
+#pragma omp declare target
+int foo() { return 0; }
+#pragma omp end declare target
+int bar() { return 0; }
+#pragma omp declare target (bar)
+int baz() { return 0; }
+
+#pragma omp declare target
+int doo() { return 0; }
+#pragma omp end declare target
+int car() { return 0; }
+#pragma omp declare target (bar)
+int caz() { return 0; }
+
+// DEVICE-DAG: define i32 [[FOO:@.*foo.*]]()
+// DEVICE-DAG: define i32 [[BAR:@.*bar.*]]()
+// DEVICE-DAG: define i32 [[BAZ:@.*baz.*]]()
+// DEVICE-DAG: define i32 [[DOO:@.*doo.*]]()
+// DEVICE-DAG: define i32 [[CAR:@.*car.*]]()
+// DEVICE-DAG: define i32 [[CAZ:@.*caz.*]]()
+
+static int c = foo() + bar() + baz();
+#pragma omp declare target (c)
+// HOST-DAG: @[[C_CTOR:__omp_offloading__.+_c_l44_ctor]] = private constant i8 0
+// DEVICE-DAG: define internal void [[C_CTOR:@__omp_offloading__.+_c_l44_ctor]]()
+// DEVICE-DAG: call i32 [[FOO]]()
+// DEVICE-DAG: call i32 [[BAR]]()
+// DEVICE-DAG: call i32 [[BAZ]]()
+// DEVICE-DAG: ret void
+
+struct S {
+ int a;
+ S() = default;
+ S(int a) : a(a) {}
+ ~S() { a = 0; }
+};
+
+#pragma omp declare target
+S cd = doo() + car() + caz() + baz();
+#pragma omp end declare target
+// HOST-DAG: @[[CD_CTOR:__omp_offloading__.+_cd_l61_ctor]] = private constant i8 0
+// DEVICE-DAG: define internal void [[CD_CTOR:@__omp_offloading__.+_cd_l61_ctor]]()
+// DEVICE-DAG: call i32 [[DOO]]()
+// DEVICE-DAG: call i32 [[CAR]]()
+// DEVICE-DAG: call i32 [[CAZ]]()
+// DEVICE-DAG: ret void
+
+// HOST-DAG: @[[CD_DTOR:__omp_offloading__.+_cd_l61_dtor]] = private constant i8 0
+// DEVICE-DAG: define internal void [[CD_DTOR:@__omp_offloading__.+_cd_l61_dtor]]()
+// DEVICE-DAG: call void
+// DEVICE-DAG: ret void
+
+// HOST-DAG: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[C_ADDR]]\00"
+// HOST-DAG: @.omp_offloading.entry.[[C_ADDR]] = internal constant %struct.__tgt_offload_entry { i8* bitcast (i32* @[[C_ADDR]] to i8*), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name{{.*}}, i32 0, i32 0), i64 4, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// HOST-DAG: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[CD_ADDR]]\00"
+// HOST-DAG: @.omp_offloading.entry.[[CD_ADDR]] = constant %struct.__tgt_offload_entry { i8* bitcast (%struct.S* @[[CD_ADDR]] to i8*), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name{{.*}}, i32 0, i32 0), i64 4, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// HOST-DAG: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[C_CTOR]]\00"
+// HOST-DAG: @.omp_offloading.entry.[[C_CTOR]] = weak constant %struct.__tgt_offload_entry { i8* @[[C_CTOR]], i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name{{.*}}, i32 0, i32 0), i64 0, i32 2, i32 0 }, section ".omp_offloading.entries", align 1
+// HOST-DAG: @.omp_offloading.entry_name{{.*}}= internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[CD_CTOR]]\00"
+// HOST-DAG: @.omp_offloading.entry.[[CD_CTOR]] = weak constant %struct.__tgt_offload_entry { i8* @[[CD_CTOR]], i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name{{.*}}, i32 0, i32 0), i64 0, i32 2, i32 0 }, section ".omp_offloading.entries", align 1
+// HOST-DAG: @.omp_offloading.entry_name{{.*}}= internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[CD_DTOR]]\00"
+// HOST-DAG: @.omp_offloading.entry.[[CD_DTOR]] = weak constant %struct.__tgt_offload_entry { i8* @[[CD_DTOR]], i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name{{.*}}, i32 0, i32 0), i64 0, i32 4, i32 0 }, section ".omp_offloading.entries", align 1
+int maini1() {
+ int a;
+#pragma omp target map(tofrom : a)
+ {
+ a = c;
+ }
+ return 0;
+}
+
+// DEVICE: define void @__omp_offloading_{{.*}}_{{.*}}maini1{{.*}}_l[[@LINE-7]](i32* dereferenceable{{[^,]*}}
+// DEVICE: [[C:%.+]] = load i32, i32* [[C_ADDR]],
+// DEVICE: store i32 [[C]], i32* %
+
+// HOST: define internal void @__omp_offloading_{{.*}}_{{.*}}maini1{{.*}}_l[[@LINE-11]](i32* dereferenceable{{.*}})
+// HOST: [[C:%.*]] = load i32, i32* @[[C_ADDR]],
+// HOST: store i32 [[C]], i32* %
+
+// HOST-DAG: !{i32 1, !"[[CD_ADDR]]", i32 0, i32 {{[0-9]+}}}
+// HOST-DAG: !{i32 1, !"[[C_ADDR]]", i32 0, i32 {{[0-9]+}}}
+
+// DEVICE: !nvvm.annotations
+// DEVICE-DAG: !{void ()* [[C_CTOR]], !"kernel", i32 1}
+// DEVICE-DAG: !{void ()* [[CD_CTOR]], !"kernel", i32 1}
+// DEVICE-DAG: !{void ()* [[CD_DTOR]], !"kernel", i32 1}
+
+#endif // HEADER
+
diff --git a/test/OpenMP/nvptx_parallel_codegen.cpp b/test/OpenMP/nvptx_parallel_codegen.cpp
index ba889bf..5aa9a21 100644
--- a/test/OpenMP/nvptx_parallel_codegen.cpp
+++ b/test/OpenMP/nvptx_parallel_codegen.cpp
@@ -64,254 +64,243 @@
// CHECK-NOT: define {{.*}}void {{@__omp_offloading_.+template.+l17}}_worker()
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l26}}_worker()
+// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
+// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
+// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
+// CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]],
+// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
+//
+// CHECK: [[AWAIT_WORK]]
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]]
+// CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
+// store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
+// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
+// CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
+// CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
+//
+// CHECK: [[SEL_WORKERS]]
+// CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]]
+// CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0
+// CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]]
+//
+// CHECK: [[EXEC_PARALLEL]]
+// CHECK: [[WF1:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
+// CHECK: [[WM1:%.+]] = icmp eq i8* [[WF1]], bitcast (void (i16, i32)* [[PARALLEL_FN1:@.+]]_wrapper to i8*)
+// CHECK: br i1 [[WM1]], label {{%?}}[[EXEC_PFN1:.+]], label {{%?}}[[CHECK_NEXT1:.+]]
+//
+// CHECK: [[EXEC_PFN1]]
+// CHECK: call void [[PARALLEL_FN1]]_wrapper(
+// CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
+//
+// CHECK: [[CHECK_NEXT1]]
+// CHECK: [[WF2:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
+// CHECK: [[WM2:%.+]] = icmp eq i8* [[WF2]], bitcast (void (i16, i32)* [[PARALLEL_FN2:@.+]]_wrapper to i8*)
+// CHECK: br i1 [[WM2]], label {{%?}}[[EXEC_PFN2:.+]], label {{%?}}[[CHECK_NEXT2:.+]]
+//
+// CHECK: [[EXEC_PFN2]]
+// CHECK: call void [[PARALLEL_FN2]]_wrapper(
+// CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
+//
+// CHECK: [[CHECK_NEXT2]]
+// CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
+//
+// CHECK: [[TERM_PARALLEL]]
+// CHECK: call void @__kmpc_kernel_end_parallel()
+// CHECK: br label {{%?}}[[BAR_PARALLEL]]
+//
+// CHECK: [[BAR_PARALLEL]]
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: br label {{%?}}[[AWAIT_WORK]]
+//
+// CHECK: [[EXIT]]
+// CHECK: ret void
+// CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l26]](i[[SZ:32|64]]
+// Create local storage for each capture.
+// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]],
+// CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]]
+// Store captures in the context.
+// CHECK-64-DAG:[[REF_A:%.+]] = bitcast i[[SZ]]* [[LOCAL_A]] to i32*
+//
+// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+// CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
+// CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
+// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
+//
+// CHECK: [[WORKER]]
+// CHECK: {{call|invoke}} void [[T6]]_worker()
+// CHECK: br label {{%?}}[[EXIT:.+]]
+//
+// CHECK: [[CHECK_MASTER]]
+// CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+// CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+// CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]],
+// CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]]
+//
+// CHECK: [[MASTER]]
+// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+// CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
+// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN1]]_wrapper to i8*),
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_serialized_parallel(
+// CHECK: {{call|invoke}} void [[PARALLEL_FN3:@.+]](
+// CHECK: call void @__kmpc_end_serialized_parallel(
+// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN2]]_wrapper to i8*),
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK-64-DAG: load i32, i32* [[REF_A]]
+// CHECK-32-DAG: load i32, i32* [[LOCAL_A]]
+// CHECK: br label {{%?}}[[TERMINATE:.+]]
+//
+// CHECK: [[TERMINATE]]
+// CHECK: call void @__kmpc_kernel_deinit(
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: br label {{%?}}[[EXIT]]
+//
+// CHECK: [[EXIT]]
+// CHECK: ret void
+// CHECK-DAG: define internal void [[PARALLEL_FN1]](
+// CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
+// CHECK: store i[[SZ]] 42, i[[SZ]]* %a,
+// CHECK: ret void
+// CHECK-DAG: define internal void [[PARALLEL_FN3]](
+// CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
+// CHECK: store i[[SZ]] 43, i[[SZ]]* %a,
+// CHECK: ret void
+// CHECK-DAG: define internal void [[PARALLEL_FN2]](
+// CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
+// CHECK: store i[[SZ]] 44, i[[SZ]]* %a,
+// CHECK: ret void
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l26}}_worker()
- // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
- // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
- // CHECK: store i8* null, i8** [[OMP_WORK_FN]],
- // CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]],
- // CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
- //
- // CHECK: [[AWAIT_WORK]]
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]],
- // CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
- // store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
- // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
- // CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
- // CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
- //
- // CHECK: [[SEL_WORKERS]]
- // CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]]
- // CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0
- // CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]]
- //
- // CHECK: [[EXEC_PARALLEL]]
- // CHECK: [[WF1:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
- // CHECK: [[WM1:%.+]] = icmp eq i8* [[WF1]], bitcast (void (i16, i32, i8**)* [[PARALLEL_FN1:@.+]]_wrapper to i8*)
- // CHECK: br i1 [[WM1]], label {{%?}}[[EXEC_PFN1:.+]], label {{%?}}[[CHECK_NEXT1:.+]]
- //
- // CHECK: [[EXEC_PFN1]]
- // CHECK: call void [[PARALLEL_FN1]]_wrapper(
- // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
- //
- // CHECK: [[CHECK_NEXT1]]
- // CHECK: [[WF2:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
- // CHECK: [[WM2:%.+]] = icmp eq i8* [[WF2]], bitcast (void (i16, i32, i8**)* [[PARALLEL_FN2:@.+]]_wrapper to i8*)
- // CHECK: br i1 [[WM2]], label {{%?}}[[EXEC_PFN2:.+]], label {{%?}}[[CHECK_NEXT2:.+]]
- //
- // CHECK: [[EXEC_PFN2]]
- // CHECK: call void [[PARALLEL_FN2]]_wrapper(
- // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
- //
- // CHECK: [[CHECK_NEXT2]]
- // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
- //
- // CHECK: [[TERM_PARALLEL]]
- // CHECK: call void @__kmpc_kernel_end_parallel()
- // CHECK: br label {{%?}}[[BAR_PARALLEL]]
- //
- // CHECK: [[BAR_PARALLEL]]
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: br label {{%?}}[[AWAIT_WORK]]
- //
- // CHECK: [[EXIT]]
- // CHECK: ret void
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l43}}_worker()
+// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
+// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
+// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
+// CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]],
+// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
+//
+// CHECK: [[AWAIT_WORK]]
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]],
+// CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
+// store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
+// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
+// CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
+// CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
+//
+// CHECK: [[SEL_WORKERS]]
+// CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]]
+// CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0
+// CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]]
+//
+// CHECK: [[EXEC_PARALLEL]]
+// CHECK: [[WF:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
+// CHECK: [[WM:%.+]] = icmp eq i8* [[WF]], bitcast (void (i16, i32)* [[PARALLEL_FN4:@.+]]_wrapper to i8*)
+// CHECK: br i1 [[WM]], label {{%?}}[[EXEC_PFN:.+]], label {{%?}}[[CHECK_NEXT:.+]]
+//
+// CHECK: [[EXEC_PFN]]
+// CHECK: call void [[PARALLEL_FN4]]_wrapper(
+// CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
+//
+// CHECK: [[CHECK_NEXT]]
+// CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
+//
+// CHECK: [[TERM_PARALLEL]]
+// CHECK: call void @__kmpc_kernel_end_parallel()
+// CHECK: br label {{%?}}[[BAR_PARALLEL]]
+//
+// CHECK: [[BAR_PARALLEL]]
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: br label {{%?}}[[AWAIT_WORK]]
+//
+// CHECK: [[EXIT]]
+// CHECK: ret void
- // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l26]](i[[SZ:32|64]]
- // Create local storage for each capture.
- // CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]],
- // CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]]
- // Store captures in the context.
- // CHECK-64-DAG:[[REF_A:%.+]] = bitcast i[[SZ]]* [[LOCAL_A]] to i32*
- //
- // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
- // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
- // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
- // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
- //
- // CHECK: [[WORKER]]
- // CHECK: {{call|invoke}} void [[T6]]_worker()
- // CHECK: br label {{%?}}[[EXIT:.+]]
- //
- // CHECK: [[CHECK_MASTER]]
- // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
- // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]],
- // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]]
- //
- // CHECK: [[MASTER]]
- // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
- // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
- // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32, i8**)* [[PARALLEL_FN1]]_wrapper to i8*),
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: call void @__kmpc_serialized_parallel(
- // CHECK: {{call|invoke}} void [[PARALLEL_FN3:@.+]](
- // CHECK: call void @__kmpc_end_serialized_parallel(
- // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32, i8**)* [[PARALLEL_FN2]]_wrapper to i8*),
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK-64-DAG: load i32, i32* [[REF_A]]
- // CHECK-32-DAG: load i32, i32* [[LOCAL_A]]
- // CHECK: br label {{%?}}[[TERMINATE:.+]]
- //
- // CHECK: [[TERMINATE]]
- // CHECK: call void @__kmpc_kernel_deinit(
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: br label {{%?}}[[EXIT]]
- //
- // CHECK: [[EXIT]]
- // CHECK: ret void
+// CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l43]](i[[SZ:32|64]]
+// Create local storage for each capture.
+// CHECK: [[LOCAL_N:%.+]] = alloca i[[SZ]],
+// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]],
+// CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]],
+// CHECK: [[LOCAL_B:%.+]] = alloca [10 x i32]*
+// CHECK-DAG: store i[[SZ]] [[ARG_N:%.+]], i[[SZ]]* [[LOCAL_N]]
+// CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]]
+// CHECK-DAG: store i[[SZ]] [[ARG_AA:%.+]], i[[SZ]]* [[LOCAL_AA]]
+// CHECK-DAG: store [10 x i32]* [[ARG_B:%.+]], [10 x i32]** [[LOCAL_B]]
+// Store captures in the context.
+// CHECK-64-DAG:[[REF_N:%.+]] = bitcast i[[SZ]]* [[LOCAL_N]] to i32*
+// CHECK-64-DAG:[[REF_A:%.+]] = bitcast i[[SZ]]* [[LOCAL_A]] to i32*
+// CHECK-DAG: [[REF_AA:%.+]] = bitcast i[[SZ]]* [[LOCAL_AA]] to i16*
+// CHECK-DAG: [[REF_B:%.+]] = load [10 x i32]*, [10 x i32]** [[LOCAL_B]],
+//
+// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+// CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
+// CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
+// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
+//
+// CHECK: [[WORKER]]
+// CHECK: {{call|invoke}} void [[T6]]_worker()
+// CHECK: br label {{%?}}[[EXIT:.+]]
+//
+// CHECK: [[CHECK_MASTER]]
+// CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+// CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+// CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]],
+// CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]]
+//
+// CHECK: [[MASTER]]
+// CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+// CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+// CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
+// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
+// CHECK-64: [[N:%.+]] = load i32, i32* [[REF_N]],
+// CHECK-32: [[N:%.+]] = load i32, i32* [[LOCAL_N]],
+// CHECK: [[CMP:%.+]] = icmp sgt i32 [[N]], 1000
+// CHECK: br i1 [[CMP]], label {{%?}}[[IF_THEN:.+]], label {{%?}}[[IF_ELSE:.+]]
+//
+// CHECK: [[IF_THEN]]
+// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN4]]_wrapper to i8*),
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: br label {{%?}}[[IF_END:.+]]
+//
+// CHECK: [[IF_ELSE]]
+// CHECK: call void @__kmpc_serialized_parallel(
+// CHECK: {{call|invoke}} void [[PARALLEL_FN4]](
+// CHECK: call void @__kmpc_end_serialized_parallel(
+// br label [[IF_END]]
+//
+// CHECK: [[IF_END]]
+// CHECK-64-DAG: load i32, i32* [[REF_A]]
+// CHECK-32-DAG: load i32, i32* [[LOCAL_A]]
+// CHECK-DAG: load i16, i16* [[REF_AA]]
+// CHECK-DAG: getelementptr inbounds [10 x i32], [10 x i32]* [[REF_B]], i[[SZ]] 0, i[[SZ]] 2
+//
+// CHECK: br label {{%?}}[[TERMINATE:.+]]
+//
+// CHECK: [[TERMINATE]]
+// CHECK: call void @__kmpc_kernel_deinit(
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: br label {{%?}}[[EXIT]]
+//
+// CHECK: [[EXIT]]
+// CHECK: ret void
- // CHECK-DAG: define internal void [[PARALLEL_FN1]](
- // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
- // CHECK: store i[[SZ]] 42, i[[SZ]]* %a,
- // CHECK: ret void
-
- // CHECK-DAG: define internal void [[PARALLEL_FN3]](
- // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
- // CHECK: store i[[SZ]] 43, i[[SZ]]* %a,
- // CHECK: ret void
-
- // CHECK-DAG: define internal void [[PARALLEL_FN2]](
- // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
- // CHECK: store i[[SZ]] 44, i[[SZ]]* %a,
- // CHECK: ret void
-
-
-
-
-
-
-
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l43}}_worker()
- // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
- // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
- // CHECK: store i8* null, i8** [[OMP_WORK_FN]],
- // CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]],
- // CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
- //
- // CHECK: [[AWAIT_WORK]]
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]],
- // CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
- // store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
- // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
- // CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
- // CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
- //
- // CHECK: [[SEL_WORKERS]]
- // CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]]
- // CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0
- // CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]]
- //
- // CHECK: [[EXEC_PARALLEL]]
- // CHECK: [[WF:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
- // CHECK: [[WM:%.+]] = icmp eq i8* [[WF]], bitcast (void (i16, i32, i8**)* [[PARALLEL_FN4:@.+]]_wrapper to i8*)
- // CHECK: br i1 [[WM]], label {{%?}}[[EXEC_PFN:.+]], label {{%?}}[[CHECK_NEXT:.+]]
- //
- // CHECK: [[EXEC_PFN]]
- // CHECK: call void [[PARALLEL_FN4]]_wrapper(
- // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
- //
- // CHECK: [[CHECK_NEXT]]
- // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
- //
- // CHECK: [[TERM_PARALLEL]]
- // CHECK: call void @__kmpc_kernel_end_parallel()
- // CHECK: br label {{%?}}[[BAR_PARALLEL]]
- //
- // CHECK: [[BAR_PARALLEL]]
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: br label {{%?}}[[AWAIT_WORK]]
- //
- // CHECK: [[EXIT]]
- // CHECK: ret void
-
- // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l43]](i[[SZ:32|64]]
- // Create local storage for each capture.
- // CHECK: [[LOCAL_N:%.+]] = alloca i[[SZ]],
- // CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]],
- // CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]],
- // CHECK: [[LOCAL_B:%.+]] = alloca [10 x i32]*
- // CHECK-DAG: store i[[SZ]] [[ARG_N:%.+]], i[[SZ]]* [[LOCAL_N]]
- // CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]]
- // CHECK-DAG: store i[[SZ]] [[ARG_AA:%.+]], i[[SZ]]* [[LOCAL_AA]]
- // CHECK-DAG: store [10 x i32]* [[ARG_B:%.+]], [10 x i32]** [[LOCAL_B]]
- // Store captures in the context.
- // CHECK-64-DAG:[[REF_N:%.+]] = bitcast i[[SZ]]* [[LOCAL_N]] to i32*
- // CHECK-64-DAG:[[REF_A:%.+]] = bitcast i[[SZ]]* [[LOCAL_A]] to i32*
- // CHECK-DAG: [[REF_AA:%.+]] = bitcast i[[SZ]]* [[LOCAL_AA]] to i16*
- // CHECK-DAG: [[REF_B:%.+]] = load [10 x i32]*, [10 x i32]** [[LOCAL_B]],
- //
- // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
- // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]]
- // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
- // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
- //
- // CHECK: [[WORKER]]
- // CHECK: {{call|invoke}} void [[T6]]_worker()
- // CHECK: br label {{%?}}[[EXIT:.+]]
- //
- // CHECK: [[CHECK_MASTER]]
- // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
- // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]],
- // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]]
- //
- // CHECK: [[MASTER]]
- // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]]
- // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
- // CHECK-64: [[N:%.+]] = load i32, i32* [[REF_N]],
- // CHECK-32: [[N:%.+]] = load i32, i32* [[LOCAL_N]],
- // CHECK: [[CMP:%.+]] = icmp sgt i32 [[N]], 1000
- // CHECK: br i1 [[CMP]], label {{%?}}[[IF_THEN:.+]], label {{%?}}[[IF_ELSE:.+]]
- //
- // CHECK: [[IF_THEN]]
- // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32, i8**)* [[PARALLEL_FN4]]_wrapper to i8*),
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: br label {{%?}}[[IF_END:.+]]
- //
- // CHECK: [[IF_ELSE]]
- // CHECK: call void @__kmpc_serialized_parallel(
- // CHECK: {{call|invoke}} void [[PARALLEL_FN4]](
- // CHECK: call void @__kmpc_end_serialized_parallel(
- // br label [[IF_END]]
- //
- // CHECK: [[IF_END]]
- // CHECK-64-DAG: load i32, i32* [[REF_A]]
- // CHECK-32-DAG: load i32, i32* [[LOCAL_A]]
- // CHECK-DAG: load i16, i16* [[REF_AA]]
- // CHECK-DAG: getelementptr inbounds [10 x i32], [10 x i32]* [[REF_B]], i[[SZ]] 0, i[[SZ]] 2
- //
- // CHECK: br label {{%?}}[[TERMINATE:.+]]
- //
- // CHECK: [[TERMINATE]]
- // CHECK: call void @__kmpc_kernel_deinit(
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: br label {{%?}}[[EXIT]]
- //
- // CHECK: [[EXIT]]
- // CHECK: ret void
-
- // CHECK: define internal void [[PARALLEL_FN4]](
- // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
- // CHECK: store i[[SZ]] 45, i[[SZ]]* %a,
- // CHECK: ret void
+// CHECK: define internal void [[PARALLEL_FN4]](
+// CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
+// CHECK: store i[[SZ]] 45, i[[SZ]]* %a,
+// CHECK: ret void
#endif
diff --git a/test/OpenMP/nvptx_target_teams_codegen.cpp b/test/OpenMP/nvptx_target_teams_codegen.cpp
index ff5967b..d547c16 100644
--- a/test/OpenMP/nvptx_target_teams_codegen.cpp
+++ b/test/OpenMP/nvptx_target_teams_codegen.cpp
@@ -60,7 +60,7 @@
//
// CHECK: [[AWAIT_WORK]]
// CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], i8*** %shared_args, i16 1)
+ // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], i16 1)
// CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
// store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
@@ -146,7 +146,7 @@
//
// CHECK: [[AWAIT_WORK]]
// CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], i8*** %shared_args, i16 1)
+ // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], i16 1)
// CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
// store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
diff --git a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp
index fc3f253..73647c4 100644
--- a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp
+++ b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp
@@ -22,7 +22,7 @@
tx a[N];
short aa[N];
tx b[10];
- tx c[M][M];
+ tx c[M][M];
tx f = n;
tx l;
int k;
@@ -47,7 +47,7 @@
for(int i = 0; i < M; i++) {
for(int j = 0; j < M; j++) {
k = M;
- c[i][j] = i+j*f+k;
+ c[i][j] = i + j * f + k;
}
}
diff --git a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp
new file mode 100644
index 0000000..af72f3b
--- /dev/null
+++ b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp
@@ -0,0 +1,98 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+int a;
+
+int foo(int *a);
+
+int main(int argc, char **argv) {
+#pragma omp target teams distribute parallel for map(tofrom:a) if(parallel:argc)
+ for (int i= 0; i < argc; ++i)
+ a = foo(&i) + foo(&a) + foo(&argc);
+ return 0;
+}
+
+// CHECK: define internal void @__omp_offloading_{{.*}}_main_l[[@LINE-6]]_worker()
+// CHECK: [[TID:%.+]] = call i32 @__kmpc_global_thread_num(%ident_t* @
+// CHECK: call void [[PARALLEL:@.+]]_wrapper(i16 0, i32 [[TID]])
+
+// CHECK: define void @__omp_offloading_{{.*}}_main_l[[@LINE-10]](i{{64|32}} %{{[^,].*}}, i32* dereferenceable{{[^,]*}}, i{{64|32}} %{{[^,)]*}})
+// CHECK: [[TID:%.+]] = call i32 @__kmpc_global_thread_num(%ident_t* @
+// CHECK: call void @__kmpc_kernel_init(
+// CHECK: call void @__kmpc_data_sharing_init_stack()
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void @__kmpc_kernel_prepare_parallel(
+// CHECK: call void @__kmpc_begin_sharing_variables(i8*** [[BUF_PTR_PTR:%[^,]+]], i{{64|32}} 4)
+// CHECK: [[BUF_PTR:%.+]] = load i8**, i8*** [[BUF_PTR_PTR]],
+// CHECK: [[LB:%.+]] = inttoptr i{{64|32}} [[LB_:%.*]] to i8*
+// CHECK: store i8* [[LB]], i8** [[BUF_PTR]],
+// CHECK: [[BUF_PTR1:%.+]] = getelementptr inbounds i8*, i8** [[BUF_PTR]], i{{[0-9]+}} 1
+// CHECK: [[UB:%.+]] = inttoptr i{{64|32}} [[UB_:%.*]] to i8*
+// CHECK: store i8* [[UB]], i8** [[BUF_PTR1]],
+// CHECK: [[BUF_PTR2:%.+]] = getelementptr inbounds i8*, i8** [[BUF_PTR]], i{{[0-9]+}} 2
+// CHECK: [[ARGC:%.+]] = inttoptr i{{64|32}} [[ARGC_:%.*]] to i8*
+// CHECK: store i8* [[ARGC]], i8** [[BUF_PTR2]],
+// CHECK: [[BUF_PTR3:%.+]] = getelementptr inbounds i8*, i8** [[BUF_PTR]], i{{[0-9]+}} 3
+// CHECK: [[A_PTR:%.+]] = bitcast i32* [[A_ADDR:%.*]] to i8*
+// CHECK: store i8* [[A_PTR]], i8** [[BUF_PTR3]],
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_end_sharing_variables()
+// CHECK: br label
+
+// CHECK: call void @__kmpc_serialized_parallel(%ident_t* @
+// CHECK: [[GTID_ADDR:%.*]] = load i32*, i32** %
+// CHECK: call void [[PARALLEL]](i32* [[GTID_ADDR]], i32* %{{.+}}, i{{64|32}} [[LB_]], i{{64|32}} [[UB_]], i{{64|32}} [[ARGC_]], i32* [[A_ADDR]])
+// CHECK: call void @__kmpc_end_serialized_parallel(%ident_t* @
+// CHECK: br label %
+
+
+// CHECK: call void @__kmpc_for_static_fini(%ident_t* @
+
+// CHECK: call void @__kmpc_kernel_deinit(i16 1)
+// CHECK: call void @llvm.nvvm.barrier0()
+
+// CHECK: define internal void [[PARALLEL]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i{{64|32}} %{{.+}}, i{{64|32}} %{{.+}}, i{{64|32}} %{{.+}}, i32* dereferenceable{{.*}})
+// CHECK: [[RES:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i{{64|32}} 8, i16 0)
+// CHECK: [[GLOBALS:%.+]] = bitcast i8* [[RES]] to [[GLOBAL_TY:%.+]]*
+// CHECK: [[I:%.+]] = getelementptr inbounds [[GLOBAL_TY]], [[GLOBAL_TY]]* [[GLOBALS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: [[ARGC_VAL:%.+]] = load i32, i32* %
+// CHECK: [[ARGC:%.+]] = getelementptr inbounds [[GLOBAL_TY]], [[GLOBAL_TY]]* [[GLOBALS]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
+// CHECK: store i32 [[ARGC_VAL]], i32* [[ARGC]],
+
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call i32 [[FOO:@.+foo.+]](i32* [[I]])
+// CHECK: call i32 [[FOO]](i32* %{{.+}})
+// CHECK: call i32 [[FOO]](i32* [[ARGC]])
+// CHECK: call void @__kmpc_for_static_fini(
+
+// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[RES]])
+
+// define internal void [[PARALLEL]]_wrapper(i16 zeroext, i32)
+// CHECK: call void @__kmpc_get_shared_variables(i8*** [[BUF_PTR_PTR:%.+]])
+// CHECK: [[BUF_PTR:%.+]] = load i8**, i8*** [[BUF_PTR_PTR]],
+// CHECK: [[BUF_PTR0:%.+]] = getelementptr inbounds i8*, i8** [[BUF_PTR]], i{{[0-9]+}} 0
+// CHECK: [[LB_PTR:%.+]] = bitcast i8** [[BUF_PTR0]] to i{{64|32}}*
+// CHECK: [[LB:%.+]] = load i{{64|32}}, i{{64|32}}* [[LB_PTR]],
+// CHECK: [[BUF_PTR1:%.+]] = getelementptr inbounds i8*, i8** [[BUF_PTR]], i{{[0-9]+}} 1
+// CHECK: [[UB_PTR:%.+]] = bitcast i8** [[BUF_PTR1]] to i{{64|32}}*
+// CHECK: [[UB:%.+]] = load i{{64|32}}, i{{64|32}}* [[UB_PTR]],
+// CHECK: [[BUF_PTR2:%.+]] = getelementptr inbounds i8*, i8** [[BUF_PTR]], i{{[0-9]+}} 2
+// CHECK: [[ARGC_ADDR:%.+]] = bitcast i8** [[BUF_PTR2]] to i32*
+// CHECK: [[ARGC:%.+]] = load i32, i32* [[ARGC_ADDR]],
+// CHECK-64: [[ARGC_CAST:%.+]] = zext i32 [[ARGC]] to i64
+// CHECK: [[BUF_PTR3:%.+]] = getelementptr inbounds i8*, i8** [[BUF_PTR]], i{{[0-9]+}} 3
+// CHECK: [[A_ADDR_REF:%.+]] = bitcast i8** [[BUF_PTR3]] to i32**
+// CHECK: [[A_ADDR:%.+]] = load i32*, i32** [[A_ADDR_REF]],
+// CHECK-64: call void [[PARALLEL]](i32* %{{.+}}, i32* %{{.+}}, i64 [[LB]], i64 [[UB]], i64 [[ARGC_CAST]], i32* [[A_ADDR]])
+// CHECK-32: call void [[PARALLEL]](i32* %{{.+}}, i32* %{{.+}}, i32 [[LB]], i32 [[UB]], i32 [[ARGC]], i32* [[A_ADDR]])
+// CHECK: ret void
+
+#endif
diff --git a/test/OpenMP/nvptx_teams_codegen.cpp b/test/OpenMP/nvptx_teams_codegen.cpp
index b26d47c..017b447 100644
--- a/test/OpenMP/nvptx_teams_codegen.cpp
+++ b/test/OpenMP/nvptx_teams_codegen.cpp
@@ -36,8 +36,12 @@
// CK1: store {{.+}} 0, {{.+}},
// CK1: store i{{[0-9]+}} [[ARGC]], i{{[0-9]+}}* [[ARGCADDR]],
// CK1-64: [[CONV:%.+]] = bitcast i{{[0-9]+}}* [[ARGCADDR]] to i{{[0-9]+}}*
-// CK1-64: store i{{[0-9]+}}* [[CONV]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
-// CK1-32: store i{{[0-9]+}}* [[ARGCADDR]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
+// CK1: call i8* @__kmpc_data_sharing_push_stack(i{{[0-9]+}} 4, i16 0)
+// CK1-64: [[ARG:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[CONV]]
+// CK1-32: [[ARG:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[ARGCADDR]]
+// CK1: [[ARGCADDR:%.+]] = getelementptr inbounds %struct.{{.*}}, %struct.{{.*}}* %{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CK1: store i{{[0-9]+}} [[ARG]], i{{[0-9]+}}* [[ARGCADDR]],
+// CK1: store i{{[0-9]+}}* [[ARGCADDR]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
// CK1: [[ARGCADDR_PTR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[ARGCADDR_PTR]],
// CK1: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[ARGCADDR_PTR_REF]],
// CK1-NOT: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_teams(
@@ -49,6 +53,10 @@
// CK1: [[ARGCADDR_PTR:%.+]] = alloca i{{.+}}***,
// CK1: [[ARGCADDR:%.+]] = alloca i{{.+}}**,
// CK1: store i{{.+}}** [[ARGC]], i{{.+}}*** [[ARGCADDR]]
+// CK1: call i8* @__kmpc_data_sharing_push_stack(i{{[0-9]+}} {{4|8}}, i16 0)
+// CK1: [[ARG:%.+]] = load i{{[0-9]+}}**, i{{[0-9]+}}*** [[ARGCADDR]]
+// CK1: [[ARGCADDR:%.+]] = getelementptr inbounds %struct.{{.*}}, %struct.{{.*}}* %{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CK1: store i{{[0-9]+}}** [[ARG]], i{{[0-9]+}}*** [[ARGCADDR]],
// CK1: store i8*** [[ARGCADDR]], i8**** [[ARGCADDR_PTR]],
// CK1: [[ARGCADDR_PTR_REF:%.+]] = load i{{.+}}**, i{{.+}}*** [[ARGCADDR_PTR]],
// CK1: store i{{[0-9]+}}** null, i{{[0-9]+}}*** [[ARGCADDR_PTR_REF]],
@@ -97,15 +105,19 @@
// CK2: [[AADDR:%.+]] = alloca i{{[0-9]+}},
// CK2: [[BADDR:%.+]] = alloca i{{[0-9]+}},
// CK2: [[ARGCADDR:%.+]] = alloca i{{[0-9]+}},
-// CK2-NOT: {{%.+}} = call i32 @__kmpc_global_thread_num(
+// CK2: {{%.+}} = call i32 @__kmpc_global_thread_num(
// CK2: store i{{[0-9]+}} [[A_IN]], i{{[0-9]+}}* [[AADDR]],
// CK2: store i{{[0-9]+}} [[B_IN]], i{{[0-9]+}}* [[BADDR]],
// CK2: store i{{[0-9]+}} [[ARGC_IN]], i{{[0-9]+}}* [[ARGCADDR]],
// CK2-64: [[ACONV:%.+]] = bitcast i64* [[AADDR]] to i32*
// CK2-64: [[BCONV:%.+]] = bitcast i64* [[BADDR]] to i32*
// CK2-64: [[CONV:%.+]] = bitcast i64* [[ARGCADDR]] to i32*
-// CK2-64: store i{{[0-9]+}}* [[CONV]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
-// CK2-32: store i{{[0-9]+}}* [[ARGCADDR]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
+// CK2: call i8* @__kmpc_data_sharing_push_stack(i{{[0-9]+}} 4, i16 0)
+// CK2-64: [[ARG:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[CONV]]
+// CK2-32: [[ARG:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[ARGCADDR]]
+// CK2: [[ARGCADDR:%.+]] = getelementptr inbounds %struct.{{.*}}, %struct.{{.*}}* %{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CK2: store i{{[0-9]+}} [[ARG]], i{{[0-9]+}}* [[ARGCADDR]],
+// CK2: store i{{[0-9]+}}* [[ARGCADDR]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
// CK2: [[ARGCADDR_PTR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[ARGCADDR_PTR]],
// CK2: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[ARGCADDR_PTR_REF]],
// CK2-NOT: {{.+}} = call i32 @__kmpc_push_num_teams(
@@ -117,10 +129,14 @@
// CK2: [[AADDR:%.+]] = alloca i{{[0-9]+}},
// CK2: [[BADDR:%.+]] = alloca i{{[0-9]+}},
// CK2: [[ARGCADDR:%.+]] = alloca i{{[0-9]+}}**,
-// CK2-NOT: {{%.+}} = call i32 @__kmpc_global_thread_num(
+// CK2: {{%.+}} = call i32 @__kmpc_global_thread_num(
// CK2: store i{{[0-9]+}} [[A_IN]], i{{[0-9]+}}* [[AADDR]],
// CK2: store i{{[0-9]+}} [[B_IN]], i{{[0-9]+}}* [[BADDR]],
// CK2: store i{{[0-9]+}}** [[ARGC]], i{{[0-9]+}}*** [[ARGCADDR]],
+// CK2: call i8* @__kmpc_data_sharing_push_stack(i{{[0-9]+}} {{4|8}}, i16 0)
+// CK2: [[ARG:%.+]] = load i{{[0-9]+}}**, i{{[0-9]+}}*** [[ARGCADDR]]
+// CK2: [[ARGCADDR:%.+]] = getelementptr inbounds %struct.{{.*}}, %struct.{{.*}}* %{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CK2: store i{{[0-9]+}}** [[ARG]], i{{[0-9]+}}*** [[ARGCADDR]],
// CK2: store i{{[0-9]+}}*** [[ARGCADDR]], i{{[0-9]+}}**** [[ARGCADDR_PTR]],
// CK2: [[ARGCADDR_PTR_REF:%.+]] = load i{{[0-9]+}}***, i{{[0-9]+}}**** [[ARGCADDR_PTR]],
// CK2: store i{{[0-9]+}}** null, i{{[0-9]+}}*** [[ARGCADDR_PTR_REF]],
diff --git a/test/OpenMP/openmp_win_codegen.cpp b/test/OpenMP/openmp_win_codegen.cpp
index 249832b..00d424b 100644
--- a/test/OpenMP/openmp_win_codegen.cpp
+++ b/test/OpenMP/openmp_win_codegen.cpp
@@ -62,9 +62,9 @@
// CHECK-NEXT: call void @__kmpc_end_critical(%ident_t* {{.*}}@0, i32 [[GID]],
// CHECK-NEXT: cleanupret from {{.*}} unwind label %[[CATCHTERM:[^ ]+]]
// CHECK: cleanuppad within none []
-// CHECK-NEXT: call void @"\01?terminate@@YAXXZ"() #5 [ "funclet"(token %{{.*}}) ]
+// CHECK-NEXT: call void @"?terminate@@YAXXZ"() #5 [ "funclet"(token %{{.*}}) ]
// CHECK-NEXT: unreachable
// CHECK: [[CATCHTERM]]
// CHECK-NEXT: cleanuppad within [[CATCHPAD]] []
-// CHECK-NEXT: call void @"\01?terminate@@YAXXZ"() #5 [ "funclet"(token %{{.*}}) ]
+// CHECK-NEXT: call void @"?terminate@@YAXXZ"() #5 [ "funclet"(token %{{.*}}) ]
// CHECK-NEXT: unreachable
diff --git a/test/OpenMP/target_codegen.cpp b/test/OpenMP/target_codegen.cpp
index 2c0dfd8..e75ea73 100644
--- a/test/OpenMP/target_codegen.cpp
+++ b/test/OpenMP/target_codegen.cpp
@@ -72,15 +72,15 @@
// CHECK-DAG: @{{.*}} = private constant i8 0
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -91,7 +91,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_codegen_registration.cpp b/test/OpenMP/target_codegen_registration.cpp
index 80604ea..febfd7f 100644
--- a/test/OpenMP/target_codegen_registration.cpp
+++ b/test/OpenMP/target_codegen_registration.cpp
@@ -123,54 +123,54 @@
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: @.omp_offloading.entry.[[NAME1]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME1]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: @.omp_offloading.entry.[[NAME2]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME2]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: @.omp_offloading.entry.[[NAME3]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME3]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: @.omp_offloading.entry.[[NAME4]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME4]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: @.omp_offloading.entry.[[NAME5]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME5]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: @.omp_offloading.entry.[[NAME6]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME6]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: @.omp_offloading.entry.[[NAME7]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME7]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: @.omp_offloading.entry.[[NAME8]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME8]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: @.omp_offloading.entry.[[NAME9]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME9]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: @.omp_offloading.entry.[[NAME10]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME10]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: @.omp_offloading.entry.[[NAME11]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME11]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: @.omp_offloading.entry.[[NAME12]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: @.omp_offloading.entry.[[NAME12]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: @.omp_offloading.entry.[[NAME1]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME1]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: @.omp_offloading.entry.[[NAME2]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME2]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: @.omp_offloading.entry.[[NAME3]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME3]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: @.omp_offloading.entry.[[NAME4]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME4]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: @.omp_offloading.entry.[[NAME5]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME5]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: @.omp_offloading.entry.[[NAME6]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME6]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: @.omp_offloading.entry.[[NAME7]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME7]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: @.omp_offloading.entry.[[NAME8]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME8]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: @.omp_offloading.entry.[[NAME9]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME9]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: @.omp_offloading.entry.[[NAME10]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME10]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: @.omp_offloading.entry.[[NAME11]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME11]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: @.omp_offloading.entry.[[NAME12]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: @.omp_offloading.entry.[[NAME12]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -184,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -393,7 +393,7 @@
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
diff --git a/test/OpenMP/target_depend_codegen.cpp b/test/OpenMP/target_depend_codegen.cpp
index d7eb93d..7e6d5c2 100644
--- a/test/OpenMP/target_depend_codegen.cpp
+++ b/test/OpenMP/target_depend_codegen.cpp
@@ -51,9 +51,9 @@
// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288]
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -64,7 +64,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_parallel_codegen.cpp b/test/OpenMP/target_parallel_codegen.cpp
index 0cead45..887ce05 100644
--- a/test/OpenMP/target_parallel_codegen.cpp
+++ b/test/OpenMP/target_parallel_codegen.cpp
@@ -74,14 +74,14 @@
// CHECK-DAG: @{{.*}} = private constant i8 0
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -92,7 +92,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_parallel_codegen_registration.cpp b/test/OpenMP/target_parallel_codegen_registration.cpp
index 5b2af0f..4b28c6c 100644
--- a/test/OpenMP/target_parallel_codegen_registration.cpp
+++ b/test/OpenMP/target_parallel_codegen_registration.cpp
@@ -123,54 +123,54 @@
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -184,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -393,7 +393,7 @@
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
diff --git a/test/OpenMP/target_parallel_depend_codegen.cpp b/test/OpenMP/target_parallel_depend_codegen.cpp
index 108535a..3f2771a 100644
--- a/test/OpenMP/target_parallel_depend_codegen.cpp
+++ b/test/OpenMP/target_parallel_depend_codegen.cpp
@@ -51,9 +51,9 @@
// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288]
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -64,7 +64,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_parallel_for_codegen.cpp b/test/OpenMP/target_parallel_for_codegen.cpp
index 4b6254d..11a2460 100644
--- a/test/OpenMP/target_parallel_for_codegen.cpp
+++ b/test/OpenMP/target_parallel_for_codegen.cpp
@@ -74,14 +74,14 @@
// CHECK-DAG: @{{.*}} = private constant i8 0
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -92,7 +92,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_parallel_for_codegen_registration.cpp b/test/OpenMP/target_parallel_for_codegen_registration.cpp
index 6862a61..c074be8 100644
--- a/test/OpenMP/target_parallel_for_codegen_registration.cpp
+++ b/test/OpenMP/target_parallel_for_codegen_registration.cpp
@@ -123,54 +123,54 @@
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -184,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -402,7 +402,7 @@
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
diff --git a/test/OpenMP/target_parallel_for_depend_codegen.cpp b/test/OpenMP/target_parallel_for_depend_codegen.cpp
index 4845ed4..896963d 100644
--- a/test/OpenMP/target_parallel_for_depend_codegen.cpp
+++ b/test/OpenMP/target_parallel_for_depend_codegen.cpp
@@ -51,9 +51,9 @@
// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288]
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -64,7 +64,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_parallel_for_simd_codegen.cpp b/test/OpenMP/target_parallel_for_simd_codegen.cpp
index 39e10fe..44b5945 100644
--- a/test/OpenMP/target_parallel_for_simd_codegen.cpp
+++ b/test/OpenMP/target_parallel_for_simd_codegen.cpp
@@ -73,14 +73,14 @@
// CHECK-DAG: @{{.*}} = private constant i8 0
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -91,7 +91,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_parallel_for_simd_codegen_registration.cpp b/test/OpenMP/target_parallel_for_simd_codegen_registration.cpp
index 5a29222..226cd28 100644
--- a/test/OpenMP/target_parallel_for_simd_codegen_registration.cpp
+++ b/test/OpenMP/target_parallel_for_simd_codegen_registration.cpp
@@ -123,54 +123,54 @@
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -184,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -402,7 +402,7 @@
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
diff --git a/test/OpenMP/target_parallel_for_simd_depend_codegen.cpp b/test/OpenMP/target_parallel_for_simd_depend_codegen.cpp
index da51699..58be1a7 100644
--- a/test/OpenMP/target_parallel_for_simd_depend_codegen.cpp
+++ b/test/OpenMP/target_parallel_for_simd_depend_codegen.cpp
@@ -51,9 +51,9 @@
// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288]
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -64,7 +64,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_parallel_if_codegen.cpp b/test/OpenMP/target_parallel_if_codegen.cpp
index 04c052a..2146b29 100644
--- a/test/OpenMP/target_parallel_if_codegen.cpp
+++ b/test/OpenMP/target_parallel_if_codegen.cpp
@@ -60,12 +60,12 @@
// CHECK-DAG: @{{.*}} = private constant i8 0
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -76,7 +76,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx>
diff --git a/test/OpenMP/target_parallel_num_threads_codegen.cpp b/test/OpenMP/target_parallel_num_threads_codegen.cpp
index cc3f0d8..3c21858 100644
--- a/test/OpenMP/target_parallel_num_threads_codegen.cpp
+++ b/test/OpenMP/target_parallel_num_threads_codegen.cpp
@@ -60,12 +60,12 @@
// CHECK-DAG: @{{.*}} = private constant i8 0
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -76,7 +76,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx>
diff --git a/test/OpenMP/target_simd_codegen.cpp b/test/OpenMP/target_simd_codegen.cpp
index ad94def..2e58ccb 100644
--- a/test/OpenMP/target_simd_codegen.cpp
+++ b/test/OpenMP/target_simd_codegen.cpp
@@ -70,14 +70,14 @@
// CHECK-DAG: @{{.*}} = private constant i8 0
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -88,7 +88,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_simd_codegen_registration.cpp b/test/OpenMP/target_simd_codegen_registration.cpp
index 47185ce..1ca65b9 100644
--- a/test/OpenMP/target_simd_codegen_registration.cpp
+++ b/test/OpenMP/target_simd_codegen_registration.cpp
@@ -123,54 +123,54 @@
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -184,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -402,7 +402,7 @@
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
diff --git a/test/OpenMP/target_simd_depend_codegen.cpp b/test/OpenMP/target_simd_depend_codegen.cpp
index abbbc76..27a1077 100644
--- a/test/OpenMP/target_simd_depend_codegen.cpp
+++ b/test/OpenMP/target_simd_depend_codegen.cpp
@@ -51,9 +51,9 @@
// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288]
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -64,7 +64,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_teams_codegen.cpp b/test/OpenMP/target_teams_codegen.cpp
index f77c671..6d5b596 100644
--- a/test/OpenMP/target_teams_codegen.cpp
+++ b/test/OpenMP/target_teams_codegen.cpp
@@ -76,14 +76,14 @@
// CHECK-DAG: @{{.*}} = private constant i8 0
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -94,7 +94,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_teams_codegen_registration.cpp b/test/OpenMP/target_teams_codegen_registration.cpp
index 97ebbc6..3e6d6e6 100644
--- a/test/OpenMP/target_teams_codegen_registration.cpp
+++ b/test/OpenMP/target_teams_codegen_registration.cpp
@@ -123,54 +123,54 @@
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -184,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -393,7 +393,7 @@
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
diff --git a/test/OpenMP/target_teams_depend_codegen.cpp b/test/OpenMP/target_teams_depend_codegen.cpp
index 27734bc..983011d 100644
--- a/test/OpenMP/target_teams_depend_codegen.cpp
+++ b/test/OpenMP/target_teams_depend_codegen.cpp
@@ -51,9 +51,9 @@
// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288]
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -64,7 +64,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_teams_distribute_codegen.cpp b/test/OpenMP/target_teams_distribute_codegen.cpp
index 6605cbd..35083a6 100644
--- a/test/OpenMP/target_teams_distribute_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_codegen.cpp
@@ -76,14 +76,14 @@
// CHECK-DAG: @{{.*}} = private constant i8 0
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -94,7 +94,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_teams_distribute_codegen_registration.cpp b/test/OpenMP/target_teams_distribute_codegen_registration.cpp
index 2b8208c..1d053fd 100644
--- a/test/OpenMP/target_teams_distribute_codegen_registration.cpp
+++ b/test/OpenMP/target_teams_distribute_codegen_registration.cpp
@@ -123,54 +123,54 @@
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -184,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -402,7 +402,7 @@
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
diff --git a/test/OpenMP/target_teams_distribute_depend_codegen.cpp b/test/OpenMP/target_teams_distribute_depend_codegen.cpp
index ebd1f9e..084ac94 100644
--- a/test/OpenMP/target_teams_distribute_depend_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_depend_codegen.cpp
@@ -51,9 +51,9 @@
// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288]
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -64,7 +64,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_depend_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_depend_codegen.cpp
index ca4e6a6..2a05586 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_depend_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_depend_codegen.cpp
@@ -51,9 +51,9 @@
// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288]
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -64,7 +64,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration.cpp
index f03971b..81be36f 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration.cpp
@@ -123,54 +123,54 @@
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -184,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -402,7 +402,7 @@
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_codegen.cpp
index e8b4a93..19015b9 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_codegen.cpp
@@ -51,9 +51,9 @@
// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288]
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -64,7 +64,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_teams_distribute_simd_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_codegen.cpp
index fb33cc9..f8d2326 100644
--- a/test/OpenMP/target_teams_distribute_simd_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_codegen.cpp
@@ -76,14 +76,14 @@
// CHECK-DAG: @{{.*}} = private constant i8 0
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -94,7 +94,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp b/test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp
index 9e455b6..7bb8888 100644
--- a/test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp
@@ -123,54 +123,54 @@
// CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i
// CHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// CHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// CHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// CHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// CHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// CHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// CHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// CHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// CHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// CHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// CHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// CHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// CHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// CHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* @{{.*}}, i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR1:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME1:__omp_offloading_[0-9a-f]+_[0-9a-f]+__Z.+_l[0-9]+]]\00"
-// TCHECK-DAG: [[ENTRY1:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY1:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR1]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR2:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME2:.+]]\00"
-// TCHECK-DAG: [[ENTRY2:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY2:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR2]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR3:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME3:.+]]\00"
-// TCHECK-DAG: [[ENTRY3:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY3:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR3]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR4:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME4:.+]]\00"
-// TCHECK-DAG: [[ENTRY4:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY4:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR4]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR5:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME5:.+]]\00"
-// TCHECK-DAG: [[ENTRY5:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY5:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR5]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR6:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME6:.+]]\00"
-// TCHECK-DAG: [[ENTRY6:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY6:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR6]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR7:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME7:.+]]\00"
-// TCHECK-DAG: [[ENTRY7:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY7:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR7]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR8:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME8:.+]]\00"
-// TCHECK-DAG: [[ENTRY8:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY8:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR8]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR9:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME9:.+]]\00"
-// TCHECK-DAG: [[ENTRY9:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY9:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR9]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR10:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME10:.+]]\00"
-// TCHECK-DAG: [[ENTRY10:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY10:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR10]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR11:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME11:.+]]\00"
-// TCHECK-DAG: [[ENTRY11:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY11:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR11]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// TCHECK-DAG: [[NAMEPTR12:@.+]] = internal unnamed_addr constant [{{.*}} x i8] c"[[NAME12:.+]]\00"
-// TCHECK-DAG: [[ENTRY12:@.+]] = constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
+// TCHECK-DAG: [[ENTRY12:@.+]] = weak constant [[ENTTY]] { i8* bitcast (void (i[[SZ]])* @{{.*}} to i8*), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* [[NAMEPTR12]], i32 0, i32 0), i[[SZ]] 0, i32 0, i32 0 }, section ".omp_offloading.entries", align 1
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
@@ -184,7 +184,7 @@
// CHECK-SAME: { i32, void ()*, i8* } { i32 500, void ()* [[P500:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 501, void ()* [[P501:@[^,]+]], i8* null },
// CHECK-SAME: { i32, void ()*, i8* } { i32 65535, void ()* [[PMAX:@[^,]+]], i8* null },
-// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK-SAME: { i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
// CHECK-NTARGET: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
@@ -402,7 +402,7 @@
//CHECK: ret void
//CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
-//CHECK: define linkonce hidden void @[[REGFN]](i8*)
+//CHECK: define linkonce hidden void @[[REGFN]]()
//CHECK-SAME: comdat {
//CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
//CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
diff --git a/test/OpenMP/target_teams_distribute_simd_depend_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_depend_codegen.cpp
index a94da30..e189c0e 100644
--- a/test/OpenMP/target_teams_distribute_simd_depend_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_depend_codegen.cpp
@@ -51,9 +51,9 @@
// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288]
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]]
-// TCHECK-NOT: @{{.+}} = constant [[ENTTY]]
+// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -64,7 +64,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx, typename ty>
diff --git a/test/OpenMP/target_teams_num_teams_codegen.cpp b/test/OpenMP/target_teams_num_teams_codegen.cpp
index d5b83ac..685924a 100644
--- a/test/OpenMP/target_teams_num_teams_codegen.cpp
+++ b/test/OpenMP/target_teams_num_teams_codegen.cpp
@@ -60,12 +60,12 @@
// CHECK-DAG: @{{.*}} = private constant i8 0
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -76,7 +76,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx>
diff --git a/test/OpenMP/target_teams_thread_limit_codegen.cpp b/test/OpenMP/target_teams_thread_limit_codegen.cpp
index 01efd12..61f1a46 100644
--- a/test/OpenMP/target_teams_thread_limit_codegen.cpp
+++ b/test/OpenMP/target_teams_thread_limit_codegen.cpp
@@ -60,12 +60,12 @@
// CHECK-DAG: @{{.*}} = private constant i8 0
// CHECK-DAG: @{{.*}} = private constant i8 0
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
-// TCHECK: @{{.+}} = constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
@@ -76,7 +76,7 @@
// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 1, [[DEVTY]]* getelementptr inbounds ([1 x [[DEVTY]]], [1 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
// Check target registration is registered as a Ctor.
-// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* bitcast (void (i8*)* @[[REGFN]] to void ()*), i8* bitcast (void (i8*)* @[[REGFN]] to i8*) }]
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
template<typename tx>
diff --git a/test/OpenMP/task_in_reduction_codegen.cpp b/test/OpenMP/task_in_reduction_codegen.cpp
index 30ba9a1..3944857 100644
--- a/test/OpenMP/task_in_reduction_codegen.cpp
+++ b/test/OpenMP/task_in_reduction_codegen.cpp
@@ -78,9 +78,11 @@
// CHECK-NEXT: call i8* @__kmpc_task_reduction_get_th_data(i32 [[GTID]], i8* [[TD1]], i8* [[A_PTR]])
// CHECK: [[D_REF:%.+]] = getelementptr inbounds %
// CHECK-NEXT: [[D_ADDR:%.+]] = load i16*, i16** [[D_REF]],
+// CHECK: call i8* @__kmpc_threadprivate_cached(
// CHECK: [[TD2:%.+]] = load i8*, i8** [[TD2_ADDR]],
// CHECK-NEXT: [[D_PTR:%.+]] = bitcast i16* [[D_ADDR]] to i8*
// CHECK-NEXT: call i8* @__kmpc_task_reduction_get_th_data(i32 [[GTID]], i8* [[TD2]], i8* [[D_PTR]])
// CHECK: add nsw i32
// CHECK: store i32 %
+// CHECK-NOT: call i8* @__kmpc_threadprivate_cached(
#endif
diff --git a/test/OpenMP/taskloop_reduction_codegen.cpp b/test/OpenMP/taskloop_reduction_codegen.cpp
index 8abd017..fe261d4 100644
--- a/test/OpenMP/taskloop_reduction_codegen.cpp
+++ b/test/OpenMP/taskloop_reduction_codegen.cpp
@@ -164,7 +164,9 @@
// CHECK: define internal void @[[RED_INIT2]](i8*)
// CHECK: call i8* @__kmpc_threadprivate_cached(
-// CHECK: call i8* @__kmpc_threadprivate_cached(
+// CHECK: [[ORIG_PTR_ADDR:%.+]] = call i8* @__kmpc_threadprivate_cached(
+// CHECK: [[ORIG_PTR_REF:%.+]] = bitcast i8* [[ORIG_PTR_ADDR]] to i8**
+// CHECK: load i8*, i8** [[ORIG_PTR_REF]],
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(
// CHECK: ret void
@@ -199,6 +201,17 @@
// CHECK: store float %{{.+}}, float* %
// CHECK: ret void
+// CHECK-NOT: call i8* @__kmpc_threadprivate_cached(
+// CHECK: call i8* @__kmpc_task_reduction_get_th_data(
+// CHECK: call i8* @__kmpc_threadprivate_cached(
+// CHECK: call i8* @__kmpc_threadprivate_cached(
+// CHECK: call i8* @__kmpc_task_reduction_get_th_data(
+// CHECK-NOT: call i8* @__kmpc_threadprivate_cached(
+// CHECK: call i8* @__kmpc_task_reduction_get_th_data(
+// CHECK: call i8* @__kmpc_threadprivate_cached(
+// CHECK: call i8* @__kmpc_task_reduction_get_th_data(
+// CHECK-NOT: call i8* @__kmpc_threadprivate_cached(
+
// CHECK-DAG: distinct !DISubprogram(linkageName: "[[TASK]]", scope: !
// CHECK-DAG: !DISubprogram(linkageName: "[[RED_INIT1]]"
// CHECK-DAG: !DISubprogram(linkageName: "[[RED_COMB1]]"
diff --git a/test/PCH/chain-openmp-threadprivate.cpp b/test/PCH/chain-openmp-threadprivate.cpp
index c7f0f41..d719d4d 100644
--- a/test/PCH/chain-openmp-threadprivate.cpp
+++ b/test/PCH/chain-openmp-threadprivate.cpp
@@ -23,7 +23,7 @@
#else
// CHECK: call {{.*}} @__kmpc_threadprivate_register(
-// CHECK-TLS-1: @{{a|\"\\01\?a@@3PE?AHE?A\"}} = {{.*}}thread_local {{.*}}global {{.*}}i32*
+// CHECK-TLS-1: @{{a|\"\?a@@3PE?AHE?A\"}} = {{.*}}thread_local {{.*}}global {{.*}}i32*
// CHECK-LABEL: foo
// CHECK-TLS-LABEL: foo
@@ -31,9 +31,9 @@
return *a;
// CHECK: call {{.*}} @__kmpc_global_thread_num(
// CHECK: call {{.*}} @__kmpc_threadprivate_cached(
- // CHECK-TLS-1: call {{.*}} @{{_ZTW1a|\"\\01\?\?__Ea@@YAXXZ\"}}()
+ // CHECK-TLS-1: call {{.*}} @{{_ZTW1a|\"\?\?__Ea@@YAXXZ\"}}()
}
-// CHECK-TLS-2: define {{.*}} @{{_ZTW1a|\"\\01\?\?__Ea@@YAXXZ\"}}()
+// CHECK-TLS-2: define {{.*}} @{{_ZTW1a|\"\?\?__Ea@@YAXXZ\"}}()
#endif
diff --git a/test/PCH/dllexport-default-arg-closure.cpp b/test/PCH/dllexport-default-arg-closure.cpp
index a8da0c0..32e0a72 100644
--- a/test/PCH/dllexport-default-arg-closure.cpp
+++ b/test/PCH/dllexport-default-arg-closure.cpp
@@ -17,8 +17,8 @@
// Demangles as:
// void Foo::`default constructor closure'(void)
-// CHECK: define weak_odr dso_local dllexport void @"\01??_FFoo@@QEAAXXZ"(%struct.Foo*{{.*}})
-// CHECK: call %struct.Foo* @"\01??0Foo@@QEAA@W4E@0@@Z"(%struct.Foo* {{.*}}, i32 0)
+// CHECK: define weak_odr dso_local dllexport void @"??_FFoo@@QEAAXXZ"(%struct.Foo*{{.*}})
+// CHECK: call %struct.Foo* @"??0Foo@@QEAA@W4E@0@@Z"(%struct.Foo* {{.*}}, i32 0)
#else
diff --git a/test/PCH/late-parsed-instantiations.cpp b/test/PCH/late-parsed-instantiations.cpp
new file mode 100644
index 0000000..f1fe8bb
--- /dev/null
+++ b/test/PCH/late-parsed-instantiations.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fdelayed-template-parsing -std=c++14 -emit-pch %s -o %t.pch -verify
+// RUN: %clang_cc1 -fdelayed-template-parsing -std=c++14 -include-pch %t.pch %s -verify
+
+#ifndef HEADER_INCLUDED
+
+#define HEADER_INCLUDED
+
+// pr33561
+class ArrayBuffer;
+template <typename T> class Trans_NS_WTF_RefPtr {
+public:
+ ArrayBuffer *operator->() { return nullptr; }
+};
+Trans_NS_WTF_RefPtr<ArrayBuffer> get();
+template <typename _Visitor>
+constexpr void visit(_Visitor __visitor) {
+ __visitor(get()); // expected-note {{in instantiation}}
+}
+class ArrayBuffer {
+ char data() {
+ visit([](auto buffer) -> char { // expected-note {{in instantiation}}
+ buffer->data();
+ }); // expected-warning {{control reaches end of non-void lambda}}
+ } // expected-warning {{control reaches end of non-void function}}
+};
+
+#else
+
+// expected-no-diagnostics
+
+#endif
diff --git a/test/PCH/uses-seh.cpp b/test/PCH/uses-seh.cpp
index 50e2053..53ca1ef 100644
--- a/test/PCH/uses-seh.cpp
+++ b/test/PCH/uses-seh.cpp
@@ -19,8 +19,8 @@
}
int x = f();
-// CHECK: define linkonce_odr dso_local i32 @"\01?f@@YAHXZ"()
-// CHECK: define internal i32 @"\01?filt$0@0@f@@"({{.*}})
+// CHECK: define linkonce_odr dso_local i32 @"?f@@YAHXZ"()
+// CHECK: define internal i32 @"?filt$0@0@f@@"({{.*}})
#else
diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp
index 21635f0..8799f49 100644
--- a/test/Parser/MicrosoftExtensions.cpp
+++ b/test/Parser/MicrosoftExtensions.cpp
@@ -424,3 +424,10 @@
S(T);
} f([] {});
}
+
+namespace pr36638 {
+// Make sure we accept __unaligned method qualifiers on member function
+// pointers.
+struct A;
+void (A::*mp1)(int) __unaligned;
+}
diff --git a/test/Parser/cxx-extra-semi.cpp b/test/Parser/cxx-extra-semi.cpp
index 2aa18df..de14bc0 100644
--- a/test/Parser/cxx-extra-semi.cpp
+++ b/test/Parser/cxx-extra-semi.cpp
@@ -38,4 +38,7 @@
#if __cplusplus < 201103L
// expected-warning@-3{{extra ';' outside of a function is a C++11 extension}}
// expected-warning@-3{{extra ';' outside of a function is a C++11 extension}}
+#elif !defined(PEDANTIC)
+// expected-warning@-6{{extra ';' outside of a function is incompatible with C++98}}
+// expected-warning@-6{{extra ';' outside of a function is incompatible with C++98}}
#endif
diff --git a/test/Parser/cxx1z-class-template-argument-deduction.cpp b/test/Parser/cxx1z-class-template-argument-deduction.cpp
index bf1d004..532c893 100644
--- a/test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ b/test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -137,7 +137,6 @@
(void)A{n};
(void)new A(n);
(void)new A{n};
- // FIXME: We should diagnose the lack of an initializer here.
(void)new A;
}
}
@@ -150,7 +149,7 @@
auto k() -> A; // expected-error{{requires template arguments}}
- A a; // expected-error {{declaration of variable 'a' with deduced type 'A' requires an initializer}}
+ A a;
A b = 0;
const A c = 0;
A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}}
diff --git a/test/Parser/decomposed-condition.cpp b/test/Parser/decomposed-condition.cpp
index c41c822..4c635c4 100644
--- a/test/Parser/decomposed-condition.cpp
+++ b/test/Parser/decomposed-condition.cpp
@@ -1,5 +1,20 @@
// RUN: %clang_cc1 -std=c++1z %s -verify
+namespace std {
+ template<typename> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+struct Get {
+ template<int> int get() { return 0; }
+ operator bool() { return true; }
+};
+
+namespace std {
+ template<> struct tuple_size<Get> { static constexpr int value = 1; };
+ template<> struct tuple_element<0, Get> { using type = int; };
+}
+
struct Na {
bool flag;
float data;
@@ -17,29 +32,35 @@
Na g();
namespace CondInIf {
-void h() {
+int h() {
if (auto [ok, d] = f()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
;
if (auto [ok, d] = g()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'Na' is not contextually convertible to 'bool'}}
;
+ if (auto [value] = Get()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
+ return value;
}
} // namespace CondInIf
namespace CondInWhile {
-void h() {
+int h() {
while (auto [ok, d] = f()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
;
while (auto [ok, d] = g()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'Na' is not contextually convertible to 'bool'}}
;
+ while (auto [value] = Get()) // expected-warning{{ISO C++17 does not permit structured binding declaration in a condition}}
+ return value;
}
} // namespace CondInWhile
namespace CondInFor {
-void h() {
+int h() {
for (; auto [ok, d] = f();) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
;
for (; auto [ok, d] = g();) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'Na' is not contextually convertible to 'bool'}}
;
+ for (; auto [value] = Get();) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
+ return value;
}
} // namespace CondInFor
@@ -52,10 +73,15 @@
};
namespace CondInSwitch {
-void h(IntegerLike x) {
+int h(IntegerLike x) {
switch (auto [ok, d] = x) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
;
switch (auto [ok, d] = g()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{statement requires expression of integer type ('Na' invalid)}}
;
+ switch (auto [value] = Get()) {// expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
+ // expected-warning@-1{{switch condition has boolean value}}
+ case 1:
+ return value;
+ }
}
} // namespace CondInSwitch
diff --git a/test/Preprocessor/aarch64-target-features.c b/test/Preprocessor/aarch64-target-features.c
index 836d298..b554fd6 100644
--- a/test/Preprocessor/aarch64-target-features.c
+++ b/test/Preprocessor/aarch64-target-features.c
@@ -89,6 +89,18 @@
// RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE %s
// CHECK-SVE: __ARM_FEATURE_SVE 1
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP 0xE
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
+
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2a+fp16+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// CHECK-FULLFP16-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
+// CHECK-FULLFP16-SCALAR-NOT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
+// CHECK-FULLFP16-SCALAR: #define __ARM_FP 0xE
+// CHECK-FULLFP16-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
+
// ================== Check whether -mtune accepts mixed-case features.
// RUN: %clang -target aarch64 -mtune=CYCLONE -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MTUNE-CYCLONE %s
// CHECK-MTUNE-CYCLONE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+zcm" "-target-feature" "+zcz"
diff --git a/test/Preprocessor/arm-target-features.c b/test/Preprocessor/arm-target-features.c
index 82ab964..b8116b2 100644
--- a/test/Preprocessor/arm-target-features.c
+++ b/test/Preprocessor/arm-target-features.c
@@ -19,6 +19,18 @@
// CHECK-V8A-ALLOW-FP-INSTR: #define __ARM_FP16_ARGS 1
// CHECK-V8A-ALLOW-FP-INSTR: #define __ARM_FP16_FORMAT_IEEE 1
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP 0xe
+// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
+
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2a+fp16 -mfpu=vfp4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// CHECK-FULLFP16-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
+// CHECK-FULLFP16-SCALAR-NOT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
+// CHECK-FULLFP16-SCALAR: #define __ARM_FP 0xe
+// CHECK-FULLFP16-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
+
// RUN: %clang -target armv8r-none-linux-gnu -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V8R %s
// CHECK-V8R: #define __ARMEL__ 1
// CHECK-V8R: #define __ARM_ARCH 8
diff --git a/test/Preprocessor/has_include.c b/test/Preprocessor/has_include.c
index ad73293..af1f6b8 100644
--- a/test/Preprocessor/has_include.c
+++ b/test/Preprocessor/has_include.c
@@ -93,19 +93,19 @@
// Try as non-preprocessor directives
void foo( void ) {
- __has_include_next("stdint.h") // expected-warning {{#include_next in primary source file}} expected-error {{__has_include_next must be used within a preprocessing directive}}
- __has_include("stdint.h") // expected-error {{__has_include must be used within a preprocessing directive}}
+ __has_include_next("stdint.h") // expected-warning {{#include_next in primary source file}} expected-error {{'__has_include_next' must be used within a preprocessing directive}}
+ __has_include("stdint.h") // expected-error {{'__has_include' must be used within a preprocessing directive}}
}
-MACRO1 // expected-error {{__has_include must be used within a preprocessing directive}}
+MACRO1 // expected-error {{'__has_include' must be used within a preprocessing directive}}
#if 1
-MACRO1 // expected-error {{__has_include must be used within a preprocessing directive}}
+MACRO1 // expected-error {{'__has_include' must be used within a preprocessing directive}}
#endif
#if 0
#elif 1
-MACRO1 // expected-error {{__has_include must be used within a preprocessing directive}}
+MACRO1 // expected-error {{'__has_include' must be used within a preprocessing directive}}
#endif
#if 0
@@ -148,7 +148,7 @@
#if __has_include(stdint.h>)
#endif
-// expected-error@+1 {{__has_include must be used within a preprocessing directive}}
+// expected-error@+1 {{'__has_include' must be used within a preprocessing directive}}
__has_include
// expected-error@+1 {{missing ')' after '__has_include'}} // expected-error@+1 {{expected value in expression}} // expected-note@+1 {{to match this '('}}
diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c
index 2ed74dc..1b4f500 100644
--- a/test/Preprocessor/init.c
+++ b/test/Preprocessor/init.c
@@ -8965,6 +8965,9 @@
// PS4:#define __x86_64__ 1
// PS4:#define unix 1
//
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=x86_64-scei-ps4 < /dev/null | FileCheck -match-full-lines -check-prefix PS4-CXX %s
+// PS4-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 32UL
+//
// RUN: %clang_cc1 -E -dM -triple=x86_64-pc-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix X86-64-DECLSPEC %s
// RUN: %clang_cc1 -E -dM -fms-extensions -triple=x86_64-unknown-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix X86-64-DECLSPEC %s
// X86-64-DECLSPEC: #define __declspec{{.*}}
diff --git a/test/Preprocessor/pragma_microsoft.c b/test/Preprocessor/pragma_microsoft.c
index 5d08943..4105e41 100644
--- a/test/Preprocessor/pragma_microsoft.c
+++ b/test/Preprocessor/pragma_microsoft.c
@@ -190,3 +190,11 @@
#pragma intrinsic(asdf) // no-warning
#pragma clang diagnostic pop
#pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including <intrin.h>}}
+
+#pragma optimize // expected-warning{{missing '(' after '#pragma optimize'}}
+#pragma optimize( // expected-warning{{expected string literal in '#pragma optimize'}}
+#pragma optimize(a // expected-warning{{expected string literal in '#pragma optimize'}}
+#pragma optimize("g" // expected-warning{{expected ',' in '#pragma optimize'}}
+#pragma optimize("g", // expected-warning{{missing argument to '#pragma optimize'; expected 'on' or 'off'}}
+#pragma optimize("g",xyz // expected-warning{{unexpected argument 'xyz' to '#pragma optimize'; expected 'on' or 'off'}}
+#pragma optimize("g",on) // expected-warning{{#pragma optimize' is not supported}}
diff --git a/test/Sema/attr-nocf_check.c b/test/Sema/attr-nocf_check.c
new file mode 100644
index 0000000..aab4eac
--- /dev/null
+++ b/test/Sema/attr-nocf_check.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -verify -fcf-protection=branch -target-feature +ibt -fsyntax-only %s
+
+// Function pointer definition.
+typedef void (*FuncPointerWithNoCfCheck)(void) __attribute__((nocf_check)); // no-warning
+typedef void (*FuncPointer)(void);
+
+// Dont allow function declaration and definition mismatch.
+void __attribute__((nocf_check)) testNoCfCheck(); // expected-note {{previous declaration is here}}
+void testNoCfCheck(){}; // expected-error {{conflicting types for 'testNoCfCheck'}}
+
+// No variable or parameter declaration
+__attribute__((nocf_check)) int i; // expected-warning {{'nocf_check' attribute only applies to function}}
+void testNoCfCheckImpl(double __attribute__((nocf_check)) i) {} // expected-warning {{'nocf_check' attribute only applies to function}}
+
+// Allow attributed function pointers as well as casting between attributed
+// and non-attributed function pointers.
+void testNoCfCheckMismatch(FuncPointer f) {
+ FuncPointerWithNoCfCheck fNoCfCheck = f; // expected-warning {{incompatible function pointer types}}
+ (*fNoCfCheck)(); // no-warning
+}
+
+// 'nocf_check' Attribute has no parameters.
+int testNoCfCheckParams() __attribute__((nocf_check(1))); // expected-error {{'nocf_check' attribute takes no arguments}}
diff --git a/test/Sema/attr-nocf_check.cpp b/test/Sema/attr-nocf_check.cpp
new file mode 100644
index 0000000..b785f98
--- /dev/null
+++ b/test/Sema/attr-nocf_check.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple=i386-unknown-unknown -verify -fcf-protection=branch -target-feature +ibt -std=c++11 -fsyntax-only %s
+
+// Function pointer definition.
+[[gnu::nocf_check]] typedef void (*FuncPointerWithNoCfCheck)(void); // no-warning
+typedef void (*FuncPointer)(void);
+
+// Dont allow function declaration and definition mismatch.
+[[gnu::nocf_check]] void testNoCfCheck(); // expected-note {{previous declaration is here}}
+void testNoCfCheck(){}; // expected-error {{conflicting types for 'testNoCfCheck'}}
+
+// No variable or parameter declaration
+int [[gnu::nocf_check]] i; // expected-error {{'nocf_check' attribute cannot be applied to types}}
+void testNoCfCheckImpl(double i [[gnu::nocf_check]]) {} // expected-warning {{'nocf_check' attribute only applies to functions and function pointers}}
+
+// Allow attributed function pointers as well as casting between attributed
+// and non-attributed function pointers.
+void testNoCfCheckMismatch(FuncPointer f) {
+ FuncPointerWithNoCfCheck fNoCfCheck = f; // expected-error {{cannot initialize a variable of type}}
+ (*fNoCfCheck)(); // no-warning
+}
+
+// 'nocf_check' Attribute has no parameters.
+[[gnu::nocf_check(1)]] int testNoCfCheckParams(); // expected-error {{'nocf_check' attribute takes no arguments}}
diff --git a/test/Sema/conversion.c b/test/Sema/conversion.c
index e55e834..aa591c9 100644
--- a/test/Sema/conversion.c
+++ b/test/Sema/conversion.c
@@ -436,10 +436,15 @@
}
void double2float_test2(double a, float *b) {
- *b += a;
+ *b += a; // expected-warning {{implicit conversion when assigning computation result loses floating-point precision: 'double' to 'float'}}
}
float sinf (float x);
double double2float_test3(double a) {
return sinf(a); // expected-warning {{implicit conversion loses floating-point precision: 'double' to 'float'}}
}
+
+float double2float_test4(double a, float b) {
+ b -= a; // expected-warning {{implicit conversion when assigning computation result loses floating-point precision: 'double' to 'float'}}
+ return b;
+}
diff --git a/test/Sema/inline-asm-validate-amdgpu.cl b/test/Sema/inline-asm-validate-amdgpu.cl
index bc2580c..51009ec 100644
--- a/test/Sema/inline-asm-validate-amdgpu.cl
+++ b/test/Sema/inline-asm-validate-amdgpu.cl
@@ -74,3 +74,8 @@
c[i] = ci;
}
+
+void test_long(int arg0) {
+ long v15_16;
+ __asm volatile("v_lshlrev_b64 v[15:16], 0, %0" : "={v[15:16]}"(v15_16) : "v"(arg0));
+}
diff --git a/test/Sema/integer-overflow.c b/test/Sema/integer-overflow.c
index 44c2629..d66ce7f 100644
--- a/test/Sema/integer-overflow.c
+++ b/test/Sema/integer-overflow.c
@@ -158,6 +158,21 @@
return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024)));
}
+void check_integer_overflows_in_function_calls() {
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ (void)f0(4608 * 1024 * 1024);
+
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ uint64_t x = f0(4608 * 1024 * 1024);
+
+// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}}
+ uint64_t (*f0_ptr)(uint64_t) = &f0;
+ (void)(*f0_ptr)(4608 * 1024 * 1024);
+
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ (void)f2(0, f0(4608 * 1024 * 1024));
+}
+
struct s {
unsigned x;
unsigned y;
diff --git a/test/Sema/nocf_check_attr_not_allowed.c b/test/Sema/nocf_check_attr_not_allowed.c
new file mode 100644
index 0000000..2ba71d4
--- /dev/null
+++ b/test/Sema/nocf_check_attr_not_allowed.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fsyntax-only -verify -fcf-protection=branch %s
+// RUN: %clang_cc1 -triple arm-unknown-linux-gnu -fsyntax-only -verify -fcf-protection=branch %s
+// RUN: %clang_cc1 -triple arm-unknown-linux-gnu -fsyntax-only -verify %s
+
+void __attribute__((nocf_check)) foo(); // expected-warning-re{{{{((unknown attribute 'nocf_check' ignored)|('nocf_check' attribute ignored; use -fcf-protection to enable the attribute))}}}}
diff --git a/test/Sema/preserve-call-conv.c b/test/Sema/preserve-call-conv.c
index 6bd049f..6add309 100644
--- a/test/Sema/preserve-call-conv.c
+++ b/test/Sema/preserve-call-conv.c
@@ -2,6 +2,7 @@
// RUN: %clang_cc1 %s -fsyntax-only -triple arm64-unknown-unknown -verify
// RUN: %clang_cc1 %s -fsyntax-only -triple x86_64-unknown-windows-msvc -verify
// RUN: %clang_cc1 %s -fsyntax-only -triple aarch64-unknown-windows-msvc -verify
+// RUN: %clang_cc1 %s -fsyntax-only -triple thumbv7-unknown-windows-msvc -verify
typedef void typedef_fun_t(int);
diff --git a/test/Sema/redefine_extname.c b/test/Sema/redefine_extname.c
index 8202176..b1e8dab 100644
--- a/test/Sema/redefine_extname.c
+++ b/test/Sema/redefine_extname.c
@@ -4,3 +4,4 @@
#pragma redefine_extname foo_static bar_static
static int foo_static() { return 1; } // expected-warning {{#pragma redefine_extname is applicable to external C declarations only; not applied to function 'foo_static'}}
+unsigned __int128_t; // expected-error {{redefinition of '__int128_t' as different kind of symbol}}
diff --git a/test/Sema/warn-duplicate-enum.c b/test/Sema/warn-duplicate-enum.c
index f108b3a..84fdeb4 100644
--- a/test/Sema/warn-duplicate-enum.c
+++ b/test/Sema/warn-duplicate-enum.c
@@ -1,29 +1,29 @@
// RUN: %clang_cc1 %s -fsyntax-only -verify -Wduplicate-enum
// RUN: %clang_cc1 %s -x c++ -fsyntax-only -verify -Wduplicate-enum
enum A {
- A1 = 0, // expected-note {{element A1 also has value 0}}
+ A1 = 0, // expected-note {{element 'A1' also has value 0}}
A2 = -1,
- A3, // expected-warning {{element A3 has been implicitly assigned 0 which another element has been assigned}}
+ A3, // expected-warning {{element 'A3' has been implicitly assigned 0 which another element has been assigned}}
A4};
enum B {
- B1 = -1, // expected-note {{element B1 also has value -1}}
- B2, // expected-warning {{element B2 has been implicitly assigned 0 which another element has been assigned}}
+ B1 = -1, // expected-note {{element 'B1' also has value -1}}
+ B2, // expected-warning {{element 'B2' has been implicitly assigned 0 which another element has been assigned}}
B3,
B4 = -2,
- B5, // expected-warning {{element B5 has been implicitly assigned -1 which another element has been assigned}}
- B6 // expected-note {{element B6 also has value 0}}
+ B5, // expected-warning {{element 'B5' has been implicitly assigned -1 which another element has been assigned}}
+ B6 // expected-note {{element 'B6' also has value 0}}
};
-enum C { C1, C2 = -1, C3 }; // expected-warning{{element C1 has been implicitly assigned 0 which another element has been assigned}} \
- // expected-note {{element C3 also has value 0}}
+enum C { C1, C2 = -1, C3 }; // expected-warning{{element 'C1' has been implicitly assigned 0 which another element has been assigned}} \
+ // expected-note {{element 'C3' also has value 0}}
enum D {
D1,
D2,
- D3, // expected-warning{{element D3 has been implicitly assigned 2 which another element has been assigned}}
+ D3, // expected-warning{{element 'D3' has been implicitly assigned 2 which another element has been assigned}}
D4 = D2, // no warning
- D5 = 2 // expected-note {{element D5 also has value 2}}
+ D5 = 2 // expected-note {{element 'D5' also has value 2}}
};
enum E {
diff --git a/test/SemaCUDA/call-device-fn-from-host.cu b/test/SemaCUDA/call-device-fn-from-host.cu
index 3ea013f..26215d5 100644
--- a/test/SemaCUDA/call-device-fn-from-host.cu
+++ b/test/SemaCUDA/call-device-fn-from-host.cu
@@ -83,3 +83,10 @@
__host__ __device__ void fn_ptr_template() {
auto* ptr = &device_fn; // Not an error because the template isn't instantiated.
}
+
+// Launching a kernel from a host function does not result in code generation
+// for it, so calling HD function which calls a D function should not trigger
+// errors.
+static __host__ __device__ void hd_func() { device_fn(); }
+__global__ void kernel() { hd_func(); }
+void host_func(void) { kernel<<<1, 1>>>(); }
diff --git a/test/SemaCUDA/function-overload.cu b/test/SemaCUDA/function-overload.cu
index adf488b..1d78636 100644
--- a/test/SemaCUDA/function-overload.cu
+++ b/test/SemaCUDA/function-overload.cu
@@ -119,7 +119,7 @@
HostReturnTy ret_cdh = cdh();
GlobalFnPtr fp_g = g;
- g(); // expected-error {{call to global function g not configured}}
+ g(); // expected-error {{call to global function 'g' not configured}}
g<<<0, 0>>>();
}
@@ -202,7 +202,7 @@
#if defined (__CUDA_ARCH__)
// expected-error@-2 {{reference to __global__ function 'g' in __host__ __device__ function}}
#else
- // expected-error@-4 {{call to global function g not configured}}
+ // expected-error@-4 {{call to global function 'g' not configured}}
#endif
g<<<0,0>>>();
diff --git a/test/SemaCUDA/kernel-call.cu b/test/SemaCUDA/kernel-call.cu
index 47d7762..b2433c9 100644
--- a/test/SemaCUDA/kernel-call.cu
+++ b/test/SemaCUDA/kernel-call.cu
@@ -13,13 +13,13 @@
int main(void) {
g1<<<1, 1>>>(42);
- g1(42); // expected-error {{call to global function g1 not configured}}
+ g1(42); // expected-error {{call to global function 'g1' not configured}}
g1<<<1>>>(42); // expected-error {{too few execution configuration arguments to kernel function call}}
g1<<<1, 1, 0, 0, 0>>>(42); // expected-error {{too many execution configuration arguments to kernel function call}}
t1(1);
- h1<<<1, 1>>>(42); // expected-error {{kernel call to non-global function h1}}
+ h1<<<1, 1>>>(42); // expected-error {{kernel call to non-global function 'h1'}}
int (*fp)(int) = h2;
fp<<<1, 1>>>(42); // expected-error {{must have void return type}}
diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp
index c605dcb..55adb68 100644
--- a/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/test/SemaCXX/MicrosoftExtensions.cpp
@@ -489,7 +489,6 @@
namespace PR24246 {
template <typename TX> struct A {
template <bool> struct largest_type_select;
- // expected-warning@+1 {{explicit specialization of 'largest_type_select' within class scope is a Microsoft extension}}
template <> struct largest_type_select<false> {
blah x; // expected-error {{unknown type name 'blah'}}
};
diff --git a/test/SemaCXX/builtin-operator-new-delete.cpp b/test/SemaCXX/builtin-operator-new-delete.cpp
new file mode 100644
index 0000000..40d4732
--- /dev/null
+++ b/test/SemaCXX/builtin-operator-new-delete.cpp
@@ -0,0 +1,157 @@
+// RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++03 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++03 -faligned-allocation -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fsized-deallocation %s
+
+#if !__has_builtin(__builtin_operator_new) || !__has_builtin(__builtin_operator_delete)
+#error builtins should always be available
+#endif
+
+#if __has_builtin(__builtin_operator_new) != 201802L || \
+ __has_builtin(__builtin_operator_delete) != 201802L
+#error builtin should report updated value
+#endif
+
+typedef __SIZE_TYPE__ size_t;
+namespace std {
+ struct nothrow_t {};
+#if __cplusplus >= 201103L
+enum class align_val_t : size_t {};
+#else
+ enum align_val_t {
+ // We can't force an underlying type when targeting windows.
+# ifndef _WIN32
+ __zero = 0, __max = (size_t)-1
+# endif
+ };
+#endif
+}
+std::nothrow_t nothrow;
+
+void *operator new(size_t); // expected-note 1+ {{candidate function}}
+void operator delete(void *); // expected-note 1+ {{candidate function}}
+
+// Declare the reserved placement operators.
+void *operator new(size_t, void*) throw(); // expected-note 1+ {{candidate function}}
+void operator delete(void *, void *)throw(); // expected-note 1+ {{candidate function}}
+void *operator new[](size_t, void*) throw();
+void operator delete[](void*, void*) throw();
+
+// Declare the replaceable global allocation operators.
+void *operator new(size_t, const std::nothrow_t &) throw(); // expected-note 1+ {{candidate function}}
+void *operator new[](size_t, const std::nothrow_t &) throw();
+void operator delete(void *, const std::nothrow_t &)throw(); // expected-note 1+ {{candidate function}}
+void operator delete[](void *, const std::nothrow_t &) throw();
+
+// aligned allocation and deallocation functions.
+void* operator new ( size_t count, std::align_val_t al); // expected-note 1+ {{candidate function}}
+void operator delete(void *, std::align_val_t); // expected-note 1+ {{candidate}}
+#ifndef __cpp_aligned_new
+// expected-note@-3 1+ {{non-usual 'operator new' declared here}}
+// expected-note@-3 1+ {{non-usual 'operator delete' declared here}}
+#endif
+void *operator new[](size_t count, std::align_val_t al);
+void operator delete[](void*, std::align_val_t);
+
+void operator delete(void *, size_t); // expected-note 1+ {{candidate}}
+#ifndef __cpp_sized_deallocation
+// expected-note@-2 1+ {{non-usual 'operator delete' declared here}}
+#endif
+void operator delete[](void*, size_t);
+
+// Declare some other placemenet operators.
+void *operator new(size_t, void*, bool) throw(); // expected-note 1+ {{candidate function}}
+void *operator new[](size_t, void*, bool) throw();
+
+void *NP = 0;
+
+void test_typo_in_args() {
+ __builtin_operator_new(DNE); // expected-error {{undeclared identifier 'DNE'}}
+ __builtin_operator_new(DNE, DNE2); // expected-error {{undeclared identifier 'DNE'}} expected-error {{'DNE2'}}
+ __builtin_operator_delete(DNE); // expected-error {{'DNE'}}
+ __builtin_operator_delete(DNE, DNE2); // expected-error {{'DNE'}} expected-error {{'DNE2'}}
+}
+
+void test_arg_types() {
+ __builtin_operator_new(NP); // expected-error {{no matching function for call to 'operator new'}}
+ __builtin_operator_new(NP, std::align_val_t(0)); // expected-error {{no matching function for call to 'operator new'}}}
+}
+void test_return_type() {
+ int w = __builtin_operator_new(42); // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void *'}}
+ int y = __builtin_operator_delete(NP); // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void'}}
+}
+
+void test_aligned_new() {
+#ifdef __cpp_aligned_new
+ void *p = __builtin_operator_new(42, std::align_val_t(2));
+ __builtin_operator_delete(p, std::align_val_t(2));
+#else
+ // FIXME: We've manually declared the aligned new/delete overloads,
+ // but LangOpts::AlignedAllocation is false. Should our overloads be considered
+ // usual allocation/deallocation functions?
+ void *p = __builtin_operator_new(42, std::align_val_t(2)); // expected-error {{call to '__builtin_operator_new' selects non-usual allocation function}}
+ __builtin_operator_delete(p, std::align_val_t(2)); // expected-error {{call to '__builtin_operator_delete' selects non-usual deallocation function}}
+#endif
+}
+
+void test_sized_delete() {
+#ifdef __cpp_sized_deallocation
+ __builtin_operator_delete(NP, 4);
+#else
+ __builtin_operator_delete(NP, 4); // expected-error {{call to '__builtin_operator_delete' selects non-usual deallocation function}}
+#endif
+}
+
+void *operator new(size_t, bool); // expected-note 1+ {{candidate}}
+// expected-note@-1 {{non-usual 'operator new' declared here}}
+void operator delete(void *, bool); // expected-note 1+ {{candidate}}
+// expected-note@-1 {{non-usual 'operator delete' declared here}}
+
+void test_non_usual() {
+ __builtin_operator_new(42, true); // expected-error {{call to '__builtin_operator_new' selects non-usual allocation function}}
+ __builtin_operator_delete(NP, false); // expected-error {{call to '__builtin_operator_delete' selects non-usual deallocation function}}
+}
+
+template <int ID>
+struct Tag {};
+struct ConvertsToTypes {
+ operator std::align_val_t() const;
+ operator Tag<0>() const;
+};
+
+void *operator new(size_t, Tag<0>); // expected-note 0+ {{candidate}}
+void operator delete(void *, Tag<0>); // expected-note 0+ {{candidate}}
+
+void test_ambiguous() {
+#ifdef __cpp_aligned_new
+ ConvertsToTypes cvt;
+ __builtin_operator_new(42, cvt); // expected-error {{call to 'operator new' is ambiguous}}
+ __builtin_operator_delete(NP, cvt); // expected-error {{call to 'operator delete' is ambiguous}}
+#endif
+}
+
+void test_no_args() {
+ __builtin_operator_new(); // expected-error {{no matching function for call to 'operator new'}}
+ __builtin_operator_delete(); // expected-error {{no matching function for call to 'operator delete'}}
+}
+
+void test_no_matching_fn() {
+ Tag<1> tag;
+ __builtin_operator_new(42, tag); // expected-error {{no matching function for call to 'operator new'}}
+ __builtin_operator_delete(NP, tag); // expected-error {{no matching function for call to 'operator delete'}}
+}
+
+template <class Tp, class Up, class RetT>
+void test_dependent_call(Tp new_arg, Up delete_arg, RetT) {
+ RetT ret = __builtin_operator_new(new_arg);
+ __builtin_operator_delete(delete_arg);
+}
+template void test_dependent_call(int, int*, void*);
+
+void test_const_attribute() {
+ __builtin_operator_new(42); // expected-warning {{ignoring return value of function declared with const attribute}}
+#ifdef __cpp_aligned_new
+ __builtin_operator_new(42, std::align_val_t(8)); // expected-warning {{ignoring return value of function declared with const attribute}}
+#endif
+}
diff --git a/test/SemaCXX/constant-conversion.cpp b/test/SemaCXX/constant-conversion.cpp
new file mode 100644
index 0000000..80deabf
--- /dev/null
+++ b/test/SemaCXX/constant-conversion.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-apple-darwin %s
+
+// This file tests -Wconstant-conversion, a subcategory of -Wconversion
+// which is on by default.
+
+constexpr int nines() { return 99999; }
+
+void too_big_for_char(int param) {
+ char warn1 = false ? 0 : 99999;
+ // expected-warning@-1 {{implicit conversion from 'int' to 'char' changes value from 99999 to -97}}
+ char warn2 = false ? 0 : nines();
+ // expected-warning@-1 {{implicit conversion from 'int' to 'char' changes value from 99999 to -97}}
+
+ char warn3 = param > 0 ? 0 : 99999;
+ // expected-warning@-1 {{implicit conversion from 'int' to 'char' changes value from 99999 to -97}}
+ char warn4 = param > 0 ? 0 : nines();
+ // expected-warning@-1 {{implicit conversion from 'int' to 'char' changes value from 99999 to -97}}
+
+ char ok1 = true ? 0 : 99999;
+ char ok2 = true ? 0 : nines();
+
+ char ok3 = true ? 0 : 99999 + 1;
+ char ok4 = true ? 0 : nines() + 1;
+}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index 51dd619..fe4c54e 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -629,6 +629,10 @@
extern const int carr[]; // expected-note {{here}}
constexpr int n = carr[0]; // expected-error {{constant}} expected-note {{non-constexpr variable}}
+
+ constexpr int local_extern[] = {1, 2, 3};
+ void f() { extern const int local_extern[]; }
+ static_assert(local_extern[1] == 2, "");
}
namespace DependentValues {
diff --git a/test/SemaCXX/coroutine-source-location-crash.cpp b/test/SemaCXX/coroutine-source-location-crash.cpp
new file mode 100644
index 0000000..04fb1d4
--- /dev/null
+++ b/test/SemaCXX/coroutine-source-location-crash.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts \
+// RUN: -fsyntax-only -ast-dump | FileCheck %s
+#include "Inputs/std-coroutine.h"
+
+using namespace std::experimental;
+
+struct A {
+ bool await_ready();
+ void await_resume();
+ template <typename F>
+ void await_suspend(F);
+};
+
+struct coro_t {
+ struct promise_type {
+ coro_t get_return_object();
+ suspend_never initial_suspend();
+ suspend_never final_suspend();
+ void return_void();
+ static void unhandled_exception();
+ };
+};
+
+// {{0x[0-9a-fA-F]+}} <line:[[@LINE+1]]:1, col:36>
+// CHECK-LABEL: FunctionDecl {{.*}} f 'coro_t (int)'
+coro_t f(int n) {
+ A a{};
+ // CHECK: CoawaitExpr {{0x[0-9a-fA-F]+}} <col:3, col:12>
+ // CHECK-NEXT: DeclRefExpr {{0x[0-9a-fA-F]+}} <col:12>
+ // CHECK-NEXT: CXXMemberCallExpr {{0x[0-9a-fA-F]+}} <col:12>
+ // CHECK-NEXT: MemberExpr {{0x[0-9a-fA-F]+}} <col:12>
+ co_await a;
+}
diff --git a/test/SemaCXX/coroutines.cpp b/test/SemaCXX/coroutines.cpp
index 6ceeb86..ed8fd90 100644
--- a/test/SemaCXX/coroutines.cpp
+++ b/test/SemaCXX/coroutines.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions
+// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions -Wunused-result
void no_coroutine_traits_bad_arg_await() {
co_await a; // expected-error {{include <experimental/coroutine>}}
@@ -510,8 +510,7 @@
struct bad_promise_2 {
coro<bad_promise_2> get_return_object();
- // FIXME: We shouldn't offer a typo-correction here!
- suspend_always final_suspend(); // expected-note {{here}}
+ suspend_always final_suspend();
void unhandled_exception();
void return_void();
};
@@ -522,8 +521,7 @@
struct bad_promise_3 {
coro<bad_promise_3> get_return_object();
- // FIXME: We shouldn't offer a typo-correction here!
- suspend_always initial_suspend(); // expected-note {{here}}
+ suspend_always initial_suspend();
void unhandled_exception();
void return_void();
};
@@ -1337,3 +1335,63 @@
}
} // namespace CoroHandleMemberFunctionTest
+
+class awaitable_no_unused_warn {
+public:
+ using handle_type = std::experimental::coroutine_handle<>;
+ constexpr bool await_ready() { return false; }
+ void await_suspend(handle_type) noexcept {}
+ int await_resume() { return 1; }
+};
+
+
+class awaitable_unused_warn {
+public:
+ using handle_type = std::experimental::coroutine_handle<>;
+ constexpr bool await_ready() { return false; }
+ void await_suspend(handle_type) noexcept {}
+ [[nodiscard]]
+ int await_resume() { return 1; }
+};
+
+template <class Await>
+struct check_warning_promise {
+ coro<check_warning_promise> get_return_object();
+ Await initial_suspend();
+ Await final_suspend();
+ Await yield_value(int);
+ void return_void();
+ void unhandled_exception();
+};
+
+
+coro<check_warning_promise<awaitable_no_unused_warn>>
+test_no_unused_warning() {
+ co_await awaitable_no_unused_warn();
+ co_yield 42;
+}
+
+coro<check_warning_promise<awaitable_unused_warn>>
+test_unused_warning() {
+ co_await awaitable_unused_warn(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ co_yield 42; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+}
+
+struct missing_await_ready {
+ void await_suspend(std::experimental::coroutine_handle<>);
+ void await_resume();
+};
+struct missing_await_suspend {
+ bool await_ready();
+ void await_resume();
+};
+struct missing_await_resume {
+ bool await_ready();
+ void await_suspend(std::experimental::coroutine_handle<>);
+};
+
+void test_missing_awaitable_members() {
+ co_await missing_await_ready{}; // expected-error {{no member named 'await_ready' in 'missing_await_ready'}}
+ co_await missing_await_suspend{}; // expected-error {{no member named 'await_suspend' in 'missing_await_suspend'}}
+ co_await missing_await_resume{}; // expected-error {{no member named 'await_resume' in 'missing_await_resume'}}
+}
diff --git a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
index 66f0f10..04c4429 100644
--- a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -15,8 +15,8 @@
template<typename T> static CONST T right<T,int> = 5;
template<typename T> CONST int right<int,T>; // expected-error {{member 'right' declared as a template}}
template<typename T> CONST float right<float,T> = 5; // expected-error {{member 'right' declared as a template}}
- template<> static CONST int right<int,int> = 7; // expected-error {{explicit specialization of 'right' in class scope}}
- template<> static CONST float right<float,int>; // expected-error {{explicit specialization of 'right' in class scope}}
+ template<> static CONST int right<int,int> = 7;
+ template<> static CONST float right<float,int>;
template static CONST int right<int,int>; // expected-error {{expected '<' after 'template'}}
};
@@ -163,8 +163,8 @@
template<typename T> constexpr int right<int,T>; // expected-error {{member 'right' declared as a template}} \
// expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}}
template<typename T> constexpr float right<float,T> = 5; // expected-error {{non-static data member cannot be constexpr; did you intend to make it static?}}
- template<> static constexpr int right<int,int> = 7; // expected-error {{explicit specialization of 'right' in class scope}}
- template<> static constexpr float right<float,int>; // expected-error {{explicit specialization of 'right' in class scope}}
+ template<> static constexpr int right<int,int> = 7;
+ template<> static constexpr float right<float,int>; // expected-error {{requires an initializer}}
template static constexpr int right<int,int>; // expected-error {{expected '<' after 'template'}}
};
}
diff --git a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
index a78548b..ecd9593 100644
--- a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
+++ b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
@@ -409,7 +409,7 @@
#endif
float f1 = pi1a<float>;
- template<> double pi1a<double> = 5.2; // expected-error {{variable template specialization of 'pi1a' must originally be declared in namespace 'n1'}}
+ template<> double pi1a<double> = 5.2; // expected-error {{not in a namespace enclosing 'n1'}}
double d1 = pi1a<double>;
}
@@ -422,8 +422,7 @@
#endif
float f1 = n1::pi1b<float>;
- template<> double n1::pi1b<double> = 5.2; // expected-error {{cannot define or redeclare 'pi1b' here because namespace 'use_n1b' does not enclose namespace 'n1'}} \
- // expected-error {{variable template specialization of 'pi1b' must originally be declared in namespace 'n1'}}
+ template<> double n1::pi1b<double> = 5.2; // expected-error {{not in a namespace enclosing 'n1'}}
double d1 = n1::pi1b<double>;
}
}
diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp
index 4a9baf5..33516f7 100644
--- a/test/SemaCXX/cxx98-compat.cpp
+++ b/test/SemaCXX/cxx98-compat.cpp
@@ -185,9 +185,9 @@
}
namespace TemplateSpecOutOfScopeNs {
- template<typename T> struct S {}; // expected-note {{here}}
+ template<typename T> struct S {};
}
-template<> struct TemplateSpecOutOfScopeNs::S<char> {}; // expected-warning {{class template specialization of 'S' outside namespace 'TemplateSpecOutOfScopeNs' is incompatible with C++98}}
+template<> struct TemplateSpecOutOfScopeNs::S<char> {};
struct Typename {
template<typename T> struct Inner {};
diff --git a/test/SemaCXX/extra-semi.cpp b/test/SemaCXX/extra-semi.cpp
new file mode 100644
index 0000000..be7435a
--- /dev/null
+++ b/test/SemaCXX/extra-semi.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -verify -std=c++98 -Wextra-semi %s
+// RUN: %clang_cc1 -verify -std=c++03 -Wextra-semi %s
+// RUN: %clang_cc1 -verify -std=c++11 -Wextra-semi %s
+// RUN: %clang_cc1 -verify -std=c++17 -Wextra-semi %s
+// RUN: %clang_cc1 -verify -std=c++2a -Wextra-semi %s
+// RUN: %clang_cc1 -verify -Weverything -Wno-c++98-compat %s
+// RUN: %clang_cc1 -verify -Weverything -Wno-c++98-compat-pedantic -Wc++98-compat-extra-semi %s
+
+// Last RUN line checks that c++98-compat-extra-semi can still be re-enabled.
+
+void F();
+
+void F(){}
+;
+#if __cplusplus < 201103L
+// expected-warning@-2{{extra ';' outside of a function is a C++11 extension}}
+#else
+// expected-warning@-4{{extra ';' outside of a function is incompatible with C++98}}
+#endif
+
+namespace ns {
+class C {
+ void F() const;
+};
+}
+; // expected-warning {{extra ';' outside of a function is}}
+
+void ns::C::F() const {}
+; // expected-warning {{extra ';' outside of a function is}}
diff --git a/test/SemaCXX/integer-overflow.cpp b/test/SemaCXX/integer-overflow.cpp
index 6abc956..956ec15 100644
--- a/test/SemaCXX/integer-overflow.cpp
+++ b/test/SemaCXX/integer-overflow.cpp
@@ -169,3 +169,18 @@
// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024)));
}
+
+void check_integer_overflows_in_function_calls() {
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ (void)f0(4608 * 1024 * 1024);
+
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ uint64_t x = f0(4608 * 1024 * 1024);
+
+// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}}
+ uint64_t (*f0_ptr)(uint64_t) = &f0;
+ (void)(*f0_ptr)(4608 * 1024 * 1024);
+
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ (void)f2(0, f0(4608 * 1024 * 1024));
+}
diff --git a/test/SemaCXX/ms-interface.cpp b/test/SemaCXX/ms-interface.cpp
index 66ce376..c827f4c 100644
--- a/test/SemaCXX/ms-interface.cpp
+++ b/test/SemaCXX/ms-interface.cpp
@@ -47,7 +47,7 @@
void fn2() final;
};
-// expected-error@+1 {{interface type cannot inherit from non-public 'interface I1'}}
+// expected-error@+1 {{interface type cannot inherit from non-public interface 'I1'}}
__interface I5 : private I1 {
};
@@ -65,12 +65,12 @@
static_assert(!__is_interface_class(I), "oops");
static_assert(!__is_interface_class(U), "oops");
-// expected-error@55 {{interface type cannot inherit from 'struct S'}}
+// expected-error@55 {{interface type cannot inherit from struct 'S'}}
// expected-note@+1 {{in instantiation of template class 'I6<S>' requested here}}
struct S1 : I6<S> {
};
-// expected-error@55 {{interface type cannot inherit from 'class C'}}
+// expected-error@55 {{interface type cannot inherit from class 'C'}}
// expected-note@+1 {{in instantiation of template class 'I6<C>' requested here}}
class C1 : I6<C> {
};
diff --git a/test/SemaCXX/pr36536.cpp b/test/SemaCXX/pr36536.cpp
new file mode 100644
index 0000000..702b9cc
--- /dev/null
+++ b/test/SemaCXX/pr36536.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -std=c++11 %s -verify -fno-spell-checking
+
+// These test cases are constructed to make clang call ActOnStartOfFunctionDef
+// with nullptr.
+
+struct ImplicitDefaultCtor1 {};
+struct Foo {
+ typedef int NameInClass;
+ void f();
+};
+namespace bar {
+// FIXME: Improved our recovery to make this a redeclaration of Foo::f,
+// even though this is in the wrong namespace. That will allow name lookup to
+// find NameInClass below. Users are likely to hit this when they forget to
+// close namespaces.
+// expected-error@+1 {{cannot define or redeclare 'f' here}}
+void Foo::f() {
+ switch (0) { case 0: ImplicitDefaultCtor1 o; }
+ // expected-error@+1 {{unknown type name 'NameInClass'}}
+ NameInClass var;
+}
+} // namespace bar
+
+struct ImplicitDefaultCtor2 {};
+template <typename T> class TFoo { void f(); };
+// expected-error@+1 {{nested name specifier 'decltype(TFoo<T>())::'}}
+template <typename T> void decltype(TFoo<T>())::f() {
+ switch (0) { case 0: ImplicitDefaultCtor1 o; }
+}
+
+namespace tpl2 {
+struct ImplicitDefaultCtor3 {};
+template <class T1> class A {
+ template <class T2> class B {
+ void mf2();
+ };
+};
+template <class Y>
+template <>
+// expected-error@+1 {{nested name specifier 'A<Y>::B<double>::'}}
+void A<Y>::B<double>::mf2() {
+ switch (0) { case 0: ImplicitDefaultCtor3 o; }
+}
+}
diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp
index 2d78f06..ed845c3 100644
--- a/test/SemaCXX/typo-correction.cpp
+++ b/test/SemaCXX/typo-correction.cpp
@@ -647,7 +647,7 @@
namespace crash_has_include {
int has_include(int); // expected-note {{'has_include' declared here}}
-// expected-error@+1 {{__has_include must be used within a preprocessing directive}}
+// expected-error@+1 {{'__has_include' must be used within a preprocessing directive}}
int foo = __has_include(42); // expected-error {{use of undeclared identifier '__has_include'; did you mean 'has_include'?}}
}
diff --git a/test/SemaCXX/warn-infinite-recursion.cpp b/test/SemaCXX/warn-infinite-recursion.cpp
index e1b7c54..bbeff92 100644
--- a/test/SemaCXX/warn-infinite-recursion.cpp
+++ b/test/SemaCXX/warn-infinite-recursion.cpp
@@ -29,8 +29,7 @@
void e() { f(); }
void f() { e(); }
-// Don't warn on infinite loops
-void g() {
+void g() { // expected-warning{{call itself}}
while (true)
g();
@@ -54,6 +53,19 @@
return 5 + j();
}
+void k() { // expected-warning{{call itself}}
+ while(true) {
+ k();
+ }
+}
+
+// Don't warn on infinite loops
+void l() {
+ while (true) {}
+
+ l();
+}
+
class S {
static void a();
void b();
diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp
index 829e2e4..db1373d 100644
--- a/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -1933,7 +1933,7 @@
f1.mu_.Unlock();
bt.barTD(&f1); // \
- // expected-warning {{calling function 'barTD' requires holding mutex 'f1.mu_' exclusively}} \
+ // expected-warning {{calling function 'barTD<TestTemplateAttributeInstantiation::Foo1>' requires holding mutex 'f1.mu_' exclusively}} \
// expected-note {{found near match 'bt.fooBase.mu_'}}
bt.fooBase.mu_.Unlock();
@@ -2130,10 +2130,10 @@
myFoo.foo3(&myFoo); // \
// expected-warning {{calling function 'foo3' requires holding mutex 'myFoo.mu_' exclusively}}
myFoo.fooT1(dummy); // \
- // expected-warning {{calling function 'fooT1' requires holding mutex 'myFoo.mu_' exclusively}}
+ // expected-warning {{calling function 'fooT1<int>' requires holding mutex 'myFoo.mu_' exclusively}}
myFoo.fooT2(dummy); // \
- // expected-warning {{calling function 'fooT2' requires holding mutex 'myFoo.mu_' exclusively}}
+ // expected-warning {{calling function 'fooT2<int>' requires holding mutex 'myFoo.mu_' exclusively}}
fooF1(&myFoo); // \
// expected-warning {{calling function 'fooF1' requires holding mutex 'myFoo.mu_' exclusively}}
@@ -3565,7 +3565,7 @@
void Foo::test() {
Cell<int> cell;
elr(&cell); // \
- // expected-warning {{calling function 'elr' requires holding mutex 'cell.mu_' exclusively}}
+ // expected-warning {{calling function 'elr<int>' requires holding mutex 'cell.mu_' exclusively}}
}
@@ -3578,7 +3578,7 @@
void globalTest() {
Cell<int> cell;
globalELR(&cell); // \
- // expected-warning {{calling function 'globalELR' requires holding mutex 'cell.mu_' exclusively}}
+ // expected-warning {{calling function 'globalELR<int>' requires holding mutex 'cell.mu_' exclusively}}
}
@@ -3599,7 +3599,7 @@
void globalTest2() {
Cell<int> cell;
globalELR2(&cell); // \
- // expected-warning {{calling function 'globalELR2' requires holding mutex 'cell.mu_' exclusively}}
+ // expected-warning {{calling function 'globalELR2<int>' requires holding mutex 'cell.mu_' exclusively}}
}
diff --git a/test/SemaObjC/attr-deprecated-replacement-fixit.m b/test/SemaObjC/attr-deprecated-replacement-fixit.m
new file mode 100644
index 0000000..9d0fcf9
--- /dev/null
+++ b/test/SemaObjC/attr-deprecated-replacement-fixit.m
@@ -0,0 +1,177 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -verify -fsyntax-only %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck --implicit-check-not fix-it: %s
+// RUN: cp %s %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -DIGNORE_UNSUCCESSFUL_RENAMES -fixit -x objective-c %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -DIGNORE_UNSUCCESSFUL_RENAMES -Werror -x objective-c %t
+
+#if !__has_feature(attribute_deprecated_with_replacement)
+#error "Missing __has_feature"
+#endif
+
+#if !__has_feature(attribute_availability_with_replacement)
+#error "Missing __has_feature"
+#endif
+
+#define DEPRECATED(replacement) __attribute__((deprecated("message", replacement)))
+
+@protocol SuccessfulMultiParameterRenames
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)multi:(int)param1 parameter:(int)param2 replacement:(int)param3 DEPRECATED("multi_new:parameter_new:replace_new_ment:");
+- (void)multi_new:(int)param1 parameter_new:(int)param2 replace_new_ment:(int)param3;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)varArgs:(int)params, ... DEPRECATED("renameVarArgs:");
+- (void)renameVarArgs:(int)params, ...;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)leadingMinus:(int)param DEPRECATED("-leadingMinusRenamed:");
+- (void)leadingMinusRenamed:(int)param;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)leadingPlus:(int)param DEPRECATED("+leadingPlusRenamed:");
+- (void)leadingPlusRenamed:(int)param;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)sourceEmptyName:(int)param1 :(int)param2 DEPRECATED("renameEmptyName:toNonEmpty:");
+- (void)renameEmptyName:(int)param1 toNonEmpty:(int)param2;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)target:(int)param1 willBecomeEmpty:(int)param2 emptyName:(int)param3 DEPRECATED("target::emptyName:");
+- (void)target:(int)param1 :(int)param2 emptyName:(int)param3;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)extra:(int)param1 whiteSpace:(int)param2 DEPRECATED("renameExtra:whiteSpace:");
+- (void)renameExtra:(int)param1 whiteSpace:(int)param2;
+
+// Test renaming that was producing valid code earlier is still producing valid
+// code. The difference is that now we detect different number of parameters.
+//
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)singleArgumentRegression:(int)param DEPRECATED("renameSingleArgument");
+- (void)renameSingleArgument:(int)param;
+@end
+
+void successfulRenames(id<SuccessfulMultiParameterRenames> object) {
+ [object multi:0 parameter:1 replacement:2]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:16}:"multi_new"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:19-[[@LINE-2]]:28}:"parameter_new"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:31-[[@LINE-3]]:42}:"replace_new_ment"
+
+ [object varArgs:1, 2, 3, 0]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:18}:"renameVarArgs"
+
+ [object leadingMinus:0]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:23}:"leadingMinusRenamed"
+
+ [object leadingPlus:0]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:22}:"leadingPlusRenamed"
+
+ [object sourceEmptyName:0 :1]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:26}:"renameEmptyName"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:29-[[@LINE-2]]:29}:"toNonEmpty"
+
+ [object target:0 willBecomeEmpty:1 emptyName:2]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:17}:"target"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:20-[[@LINE-2]]:35}:""
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:38-[[@LINE-3]]:47}:"emptyName"
+
+ [object extra: 0 whiteSpace: 1]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:16}:"renameExtra"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:23-[[@LINE-2]]:33}:"whiteSpace"
+
+ [object singleArgumentRegression:0]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:35}:"renameSingleArgument"
+}
+
+#ifndef IGNORE_UNSUCCESSFUL_RENAMES
+@protocol UnsuccessfulMultiParameterRenames
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)differentNumberOfParameters:(int)param DEPRECATED("rename:hasMoreParameters:");
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)differentNumber:(int)param1 ofParameters:(int)param2 DEPRECATED("renameHasLessParameters:");
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)methodLike:(int)param1 replacement:(int)param2 DEPRECATED("noColon:atTheEnd");
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)freeFormText DEPRECATED("Use something else");
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)freeFormTextReplacementStartsAsMethod DEPRECATED("-Use something different");
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)replacementHasSingleSkipCharacter DEPRECATED("-");
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)replacementHasInvalid:(int)param1 slotName:(int)param2 DEPRECATED("renameWith:1nonIdentifier:");
+@end
+
+void unsuccessfulRenames(id<UnsuccessfulMultiParameterRenames> object) {
+ [object differentNumberOfParameters:0]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:38}:"rename:hasMoreParameters:"
+
+ [object differentNumber:0 ofParameters:1]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:26}:"renameHasLessParameters:"
+
+ [object methodLike:0 replacement:1]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:21}:"noColon:atTheEnd"
+
+ [object freeFormText]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:23}:"Use something else"
+
+ [object freeFormTextReplacementStartsAsMethod]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:48}:"-Use something different"
+
+ [object replacementHasSingleSkipCharacter]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:44}:"-"
+
+ [object replacementHasInvalid:0 slotName:1]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:32}:"renameWith:1nonIdentifier:"
+}
+#endif // IGNORE_UNSUCCESSFUL_RENAMES
+
+// Make sure classes are treated the same way as protocols.
+__attribute__((objc_root_class))
+@interface Interface
+// expected-note@+1 {{has been explicitly marked deprecated here}}
++ (void)classMethod:(int)param1 replacement:(int)param2 DEPRECATED("renameClassMethod:replace_new_ment:");
++ (void)renameClassMethod:(int)param1 replace_new_ment:(int)param2;
+
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)multi:(int)param1 parameter:(int)param2 replacement:(int)param3 DEPRECATED("multi_new:parameter_new:replace_new_ment:");
+- (void)multi_new:(int)param1 parameter_new:(int)param2 replace_new_ment:(int)param3;
+@end
+
+@implementation Interface
++ (void)classMethod:(int)param1 replacement:(int)param2 {}
++ (void)renameClassMethod:(int)param1 replace_new_ment:(int)param2 {}
+
+- (void)multi:(int)param1 parameter:(int)param2 replacement:(int)param3 {}
+- (void)multi_new:(int)param1 parameter_new:(int)param2 replace_new_ment:(int)param3 {}
+
+- (void)usage {
+ [Interface classMethod:0 replacement:1]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:25}:"renameClassMethod"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:28-[[@LINE-2]]:39}:"replace_new_ment"
+
+ [self multi:0 parameter:1 replacement:2]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:14}:"multi_new"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:26}:"parameter_new"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:29-[[@LINE-3]]:40}:"replace_new_ment"
+}
+@end
+
+// Make sure availability attribute is handled the same way as deprecation attribute.
+@protocol AvailabilityAttributeRenames
+// expected-note@+1 {{has been explicitly marked deprecated here}}
+- (void)multi:(int)param1 parameter:(int)param2 replacement:(int)param3 __attribute__((availability(macosx,deprecated=9.0,replacement="multi_new:parameter_new:replace_new_ment:")));
+- (void)multi_new:(int)param1 parameter_new:(int)param2 replace_new_ment:(int)param3;
+@end
+
+void availabilityAttributeRenames(id<AvailabilityAttributeRenames> object) {
+ [object multi:0 parameter:1 replacement:2]; // expected-warning {{is deprecated}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:16}:"multi_new"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:19-[[@LINE-2]]:28}:"parameter_new"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:31-[[@LINE-3]]:42}:"replace_new_ment"
+}
diff --git a/test/SemaObjC/comptypes-legal.m b/test/SemaObjC/comptypes-legal.m
index 05f1897..7ac4e14 100644
--- a/test/SemaObjC/comptypes-legal.m
+++ b/test/SemaObjC/comptypes-legal.m
@@ -42,7 +42,7 @@
- (void) Meth : (id <NSCopying>)aKey; // expected-note {{passing argument to parameter 'aKey' here}}
@end
-@class ForwarClass; // expected-note 3 {{conformance of forward class ForwarClass to protocol NSCopying can not be confirmed}}
+@class ForwarClass; // expected-note 3 {{conformance of forward class 'ForwarClass' to protocol 'NSCopying' can not be confirmed}}
ForwarClass *Test10751015 (I* pi, ForwarClass *ns_forward) {
diff --git a/test/SemaObjC/foreachtemplatized.mm b/test/SemaObjC/foreachtemplatized.mm
new file mode 100644
index 0000000..ab2770a
--- /dev/null
+++ b/test/SemaObjC/foreachtemplatized.mm
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -Wno-objc-root-class -std=c++11 -ast-dump %s | FileCheck %s
+
+// CHECK-NOT: ImplicitValueInitExpr
+
+@interface I
+@end
+
+template <typename T>
+void decode(I *p) {
+ for (I *k in p) {}
+}
+
+void decode(I *p) {
+ decode<int>(p);
+}
diff --git a/test/SemaObjC/integer-overflow.m b/test/SemaObjC/integer-overflow.m
new file mode 100644
index 0000000..6d82e29
--- /dev/null
+++ b/test/SemaObjC/integer-overflow.m
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -Wno-objc-root-class -fsyntax-only -verify %s
+
+@interface Foo
+@end
+
+@implementation Foo
+- (int)add:(int)a with:(int)b {
+ return a + b;
+}
+
+- (void)testIntegerOverflows {
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ (void)[self add:0 with:4608 * 1024 * 1024];
+
+// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+ (void)[self add:0 with:[self add:4608 * 1024 * 1024 with:0]];
+}
+@end
diff --git a/test/SemaObjC/non-trivial-struct-traits.m b/test/SemaObjC/non-trivial-struct-traits.m
new file mode 100644
index 0000000..db918d8
--- /dev/null
+++ b/test/SemaObjC/non-trivial-struct-traits.m
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -verify %s
+
+// expected-no-diagnostics
+
+struct Trivial {
+ int x;
+};
+
+struct NonTrivial {
+ id x;
+};
+
+int trivial_assign[__has_trivial_assign(struct Trivial) ? 1 : -1];
+int trivial_move_assign[__has_trivial_move_assign(struct Trivial) ? 1 : -1];
+int trivial_copy_constructor[__has_trivial_copy(struct Trivial) ? 1 : -1];
+int trivial_move_constructor[__has_trivial_move_constructor(struct Trivial) ? 1 : -1];
+int trivial_constructor[__has_trivial_constructor(struct Trivial) ? 1 : -1];
+int trivial_destructor[__has_trivial_destructor(struct Trivial) ? 1 : -1];
+
+int non_trivial_assign[__has_trivial_assign(struct NonTrivial) ? -1 : 1];
+int non_trivial_move_assign[__has_trivial_move_assign(struct NonTrivial) ? -1 : 1];
+int non_trivial_copy_constructor[__has_trivial_copy(struct NonTrivial) ? -1 : 1];
+int non_trivial_move_constructor[__has_trivial_move_constructor(struct NonTrivial) ? -1 : 1];
+int non_trivial_constructor[__has_trivial_constructor(struct NonTrivial) ? -1 : 1];
+int non_trivial_destructor[__has_trivial_destructor(struct NonTrivial) ? -1 : 1];
diff --git a/test/SemaObjC/protocol-expr-neg-1.m b/test/SemaObjC/protocol-expr-neg-1.m
index aed56c0..26cdac7 100644
--- a/test/SemaObjC/protocol-expr-neg-1.m
+++ b/test/SemaObjC/protocol-expr-neg-1.m
@@ -12,7 +12,7 @@
int main()
{
Protocol *proto = @protocol(p1);
- Protocol *fproto = @protocol(fproto); // expected-warning {{@protocol is using a forward protocol declaration of fproto}}
+ Protocol *fproto = @protocol(fproto); // expected-warning {{@protocol is using a forward protocol declaration of 'fproto'}}
Protocol *pp = @protocol(i); // expected-error {{cannot find protocol declaration for 'i'}}
Protocol *p1p = @protocol(cl); // expected-error {{cannot find protocol declaration for 'cl'}}
}
@@ -26,9 +26,9 @@
@end
int doesConform(id foo) {
- return [foo conformsToProtocol:@protocol(TestProtocol)]; // expected-warning {{@protocol is using a forward protocol declaration of TestProtocol}}
+ return [foo conformsToProtocol:@protocol(TestProtocol)]; // expected-warning {{@protocol is using a forward protocol declaration of 'TestProtocol'}}
}
int doesConformSuper(id foo) {
- return [foo conformsToProtocol:@protocol(SuperProtocol)]; // expected-warning {{@protocol is using a forward protocol declaration of SuperProtocol}}
+ return [foo conformsToProtocol:@protocol(SuperProtocol)]; // expected-warning {{@protocol is using a forward protocol declaration of 'SuperProtocol'}}
}
diff --git a/test/SemaObjC/undef-class-property-error.m b/test/SemaObjC/undef-class-property-error.m
new file mode 100644
index 0000000..e7e5db4
--- /dev/null
+++ b/test/SemaObjC/undef-class-property-error.m
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+@implementation I (C) // expected-error {{cannot find interface declaration for 'I'}}
+
++ (void)f {
+ self.m; // expected-error {{member reference base type 'Class' is not a structure or union}}
+}
+
+@end
diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp
index 00e03ef..d763944 100644
--- a/test/SemaTemplate/class-template-spec.cpp
+++ b/test/SemaTemplate/class-template-spec.cpp
@@ -78,9 +78,6 @@
namespace N {
template<typename T> struct B; // expected-note {{explicitly specialized}}
-#if __cplusplus <= 199711L
- // expected-note@-2 {{explicitly specialized}}
-#endif
template<> struct ::N::B<char>; // okay
template<> struct ::N::B<short>; // okay
@@ -92,9 +89,6 @@
template<> struct N::B<int> { }; // okay
template<> struct N::B<float> { };
-#if __cplusplus <= 199711L
-// expected-warning@-2 {{first declaration of class template specialization of 'B' outside namespace 'N' is a C++11 extension}}
-#endif
namespace M {
@@ -121,9 +115,9 @@
namespace rdar9676205 {
template<typename T>
- struct X {
+ struct X { // expected-note {{here}}
template<typename U>
- struct X<U*> { // expected-error{{explicit specialization of 'X' in class scope}}
+ struct X<U*> { // expected-error{{partial specialization of 'X' not in a namespace enclosing}}
};
};
diff --git a/test/SemaTemplate/ext_ms_template_spec.cpp b/test/SemaTemplate/ext_ms_template_spec.cpp
index fc2ed16..cb30321 100644
--- a/test/SemaTemplate/ext_ms_template_spec.cpp
+++ b/test/SemaTemplate/ext_ms_template_spec.cpp
@@ -18,16 +18,16 @@
namespace B {
template <>
-class A::ClassTemplate<int>; // expected-warning {{class template specialization of 'ClassTemplate' outside namespace enclosing 'A' is a Microsoft extension}}
+class A::ClassTemplate<int>; // expected-warning {{class template specialization of 'ClassTemplate' not in a namespace enclosing 'A' is a Microsoft extension}}
template <class T1>
-class A::ClassTemplatePartial<T1, T1 *> {}; // expected-warning {{class template partial specialization of 'ClassTemplatePartial' outside namespace enclosing 'A' is a Microsoft extension}}
+class A::ClassTemplatePartial<T1, T1 *> {}; // expected-warning {{class template partial specialization of 'ClassTemplatePartial' not in a namespace enclosing 'A' is a Microsoft extension}}
template <>
-struct A::X<int>::MemberClass; // expected-warning {{member class specialization of 'MemberClass' outside namespace enclosing 'A' is a Microsoft extension}}
+struct A::X<int>::MemberClass; // expected-warning {{member class specialization of 'MemberClass' not in class 'X' or an enclosing namespace is a Microsoft extension}}
template <>
-enum A::X<int>::MemberEnumeration; // expected-warning {{member enumeration specialization of 'MemberEnumeration' outside namespace enclosing 'A' is a Microsoft extension}} // expected-error {{ISO C++ forbids forward references to 'enum' types}}
+enum A::X<int>::MemberEnumeration; // expected-warning {{member enumeration specialization of 'MemberEnumeration' not in class 'X' or an enclosing namespace is a Microsoft extension}} // expected-error {{ISO C++ forbids forward references to 'enum' types}}
}
diff --git a/test/SemaTemplate/function-template-specialization.cpp b/test/SemaTemplate/function-template-specialization.cpp
index 6327ff6..a3669fd 100644
--- a/test/SemaTemplate/function-template-specialization.cpp
+++ b/test/SemaTemplate/function-template-specialization.cpp
@@ -54,5 +54,5 @@
// Don't crash here.
template<>
- static void Bar(const long& input) {} // expected-error{{explicit specialization of 'Bar' in class scope}}
+ static void Bar(const long& input) {} // expected-warning{{explicit specialization cannot have a storage class}}
};
diff --git a/test/SemaTemplate/instantiate-method.cpp b/test/SemaTemplate/instantiate-method.cpp
index 9618844..9cd668d 100644
--- a/test/SemaTemplate/instantiate-method.cpp
+++ b/test/SemaTemplate/instantiate-method.cpp
@@ -185,7 +185,7 @@
namespace PR22040 {
template <typename T> struct Foobar {
- template <> void bazqux(typename T::type) {} // expected-error {{cannot specialize a function 'bazqux' within class scope}} expected-error 2{{cannot be used prior to '::' because it has no members}}
+ template <> void bazqux(typename T::type) {} // expected-error 2{{cannot be used prior to '::' because it has no members}}
};
void test() {
diff --git a/test/SemaTemplate/late-parsing-eager-instantiation.cpp b/test/SemaTemplate/late-parsing-eager-instantiation.cpp
new file mode 100644
index 0000000..412f026
--- /dev/null
+++ b/test/SemaTemplate/late-parsing-eager-instantiation.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -std=c++14 -verify %s
+
+// pr33561
+class ArrayBuffer;
+template <typename T> class Trans_NS_WTF_RefPtr {
+public:
+ ArrayBuffer *operator->() { return nullptr; }
+};
+Trans_NS_WTF_RefPtr<ArrayBuffer> get();
+template <typename _Visitor>
+constexpr void visit(_Visitor __visitor) {
+ __visitor(get()); // expected-note {{in instantiation}}
+}
+class ArrayBuffer {
+ char data() {
+ visit([](auto buffer) -> char { // expected-note {{in instantiation}}
+ buffer->data();
+ }); // expected-warning {{control reaches end of non-void lambda}}
+ } // expected-warning {{control reaches end of non-void function}}
+};
+
+// pr34185
+template <typename Promise> struct coroutine_handle {
+ Promise &promise() const { return
+ *static_cast<Promise *>(nullptr); // expected-warning {{binding dereferenced null}}
+ }
+};
+
+template <typename Promise> auto GetCurrenPromise() {
+ struct Awaiter { // expected-note {{in instantiation}}
+ void await_suspend(coroutine_handle<Promise> h) {
+ h.promise(); // expected-note {{in instantiation}}
+ }
+ };
+ return Awaiter{};
+}
+
+void foo() {
+ auto &&p = GetCurrenPromise<int>(); // expected-note {{in instantiation}}
+}
diff --git a/test/SemaTemplate/ms-function-specialization-class-scope.cpp b/test/SemaTemplate/ms-function-specialization-class-scope.cpp
index 3c7111d..dcab9bf 100644
--- a/test/SemaTemplate/ms-function-specialization-class-scope.cpp
+++ b/test/SemaTemplate/ms-function-specialization-class-scope.cpp
@@ -1,18 +1,15 @@
// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -verify %s
+// expected-no-diagnostics
class A {
public:
template<class U> A(U p) {}
- template<> A(int p) {
- // expected-warning@-1 {{explicit specialization of 'A' within class scope is a Microsoft extension}}
- }
+ template<> A(int p) {}
template<class U> void f(U p) {}
- template<> void f(int p) {
- // expected-warning@-1 {{explicit specialization of 'f' within class scope is a Microsoft extension}}
- }
+ template<> void f(int p) {}
void f(int p) {}
};
@@ -28,14 +25,11 @@
template<class T> class B {
public:
template<class U> B(U p) {}
- template<> B(int p) {
- // expected-warning@-1 {{explicit specialization of 'B<T>' within class scope is a Microsoft extension}}
- }
+ template<> B(int p) {}
template<class U> void f(U p) { T y = 9; }
template<> void f(int p) {
- // expected-warning@-1 {{explicit specialization of 'f' within class scope is a Microsoft extension}}
T a = 3;
}
@@ -56,9 +50,7 @@
template<bool b> void specialized_member_template() {}
- template<> void specialized_member_template<false>() {
- // expected-warning@-1 {{explicit specialization of 'specialized_member_template' within class scope is a Microsoft extension}}
- }
+ template<> void specialized_member_template<false>() {}
};
void f() { TemplateClass<int> t; }
@@ -67,8 +59,8 @@
namespace Duplicates {
template<typename T> struct A {
template<typename U> void f();
- template<> void f<int>() {} // expected-warning {{Microsoft extension}}
- template<> void f<T>() {} // expected-warning {{Microsoft extension}}
+ template<> void f<int>() {}
+ template<> void f<T>() {}
};
// FIXME: We should diagnose the duplicate explicit specialization definitions
@@ -81,6 +73,6 @@
template <int>
int f(int = 0);
template <>
- int f<0>(int); // expected-warning {{Microsoft extension}}
+ int f<0>(int);
};
}
diff --git a/test/SemaTemplate/temp-param-subst-linear.cpp b/test/SemaTemplate/temp-param-subst-linear.cpp
new file mode 100644
index 0000000..fd93aa5
--- /dev/null
+++ b/test/SemaTemplate/temp-param-subst-linear.cpp
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -std=c++17 %s -verify
+// expected-no-diagnostics
+
+// This test attempts to ensure that the below template parameter pack
+// splitting technique executes in linear time in the number of template
+// parameters. The size of the list below is selected so as to execute
+// relatively quickly on a "good" compiler and to time out otherwise.
+
+template<typename...> struct TypeList;
+
+namespace detail {
+template<unsigned> using Unsigned = unsigned;
+template<typename T, T ...N> using ListOfNUnsignedsImpl = TypeList<Unsigned<N>...>;
+template<unsigned N> using ListOfNUnsigneds =
+ __make_integer_seq<ListOfNUnsignedsImpl, unsigned, N>;
+
+template<typename T> struct TypeWrapper {
+ template<unsigned> using AsTemplate = T;
+};
+
+template<typename ...N> struct Splitter {
+ template<template<N> class ...L,
+ template<unsigned> class ...R> struct Split {
+ using Left = TypeList<L<0>...>;
+ using Right = TypeList<R<0>...>;
+ };
+};
+}
+
+template<typename TypeList, unsigned N, typename = detail::ListOfNUnsigneds<N>>
+struct SplitAtIndex;
+
+template<typename ...T, unsigned N, typename ...NUnsigneds>
+struct SplitAtIndex<TypeList<T...>, N, TypeList<NUnsigneds...>> :
+ detail::Splitter<NUnsigneds...>::
+ template Split<detail::TypeWrapper<T>::template AsTemplate...> {};
+
+template<typename T, int N> struct Rep : Rep<typename Rep<T, N-1>::type, 1> {};
+template<typename ...T> struct Rep<TypeList<T...>, 1> { typedef TypeList<T..., T...> type; };
+
+using Ints = Rep<TypeList<int>, 14>::type;
+
+template<typename T> extern int Size;
+template<typename ...T> constexpr int Size<TypeList<T...>> = sizeof...(T);
+
+using Left = SplitAtIndex<Ints, Size<Ints> / 2>::Left;
+using Right = SplitAtIndex<Ints, Size<Ints> / 2>::Right;
+static_assert(Size<Left> == 8192);
+static_assert(Size<Right> == 8192);
+
+template<typename L, typename R> struct Concat;
+template<typename ...L, typename ...R> struct Concat<TypeList<L...>, TypeList<R...>> {
+ using type = TypeList<L..., R...>;
+};
+
+using Ints = Concat<Left, Right>::type;
diff --git a/test/SemaTemplate/temp_class_spec_neg.cpp b/test/SemaTemplate/temp_class_spec_neg.cpp
index 6366a52..7465e5e 100644
--- a/test/SemaTemplate/temp_class_spec_neg.cpp
+++ b/test/SemaTemplate/temp_class_spec_neg.cpp
@@ -7,17 +7,11 @@
namespace N {
namespace M {
template<typename T> struct A;
-#if __cplusplus <= 199711L // C++03 or earlier modes
- // expected-note@-2{{explicitly specialized declaration is here}}
-#endif
}
}
template<typename T>
struct N::M::A<T*> { };
-#if __cplusplus <= 199711L
-// expected-warning@-2{{first declaration of class template partial specialization of 'A' outside namespace 'M' is a C++11 extension}}
-#endif
// C++ [temp.class.spec]p9
// bullet 1, as amended by DR1315
diff --git a/test/SemaTemplate/warn-thread-safety-analysis.cpp b/test/SemaTemplate/warn-thread-safety-analysis.cpp
index 03bae7a..710f424 100644
--- a/test/SemaTemplate/warn-thread-safety-analysis.cpp
+++ b/test/SemaTemplate/warn-thread-safety-analysis.cpp
@@ -23,8 +23,8 @@
a.mu2.Lock();
a.bar<int>();
a.mu2.Unlock();
- a.bar<int>(); // expected-warning {{calling function 'bar' requires holding mutex 'a.mu2' exclusively}}
+ a.bar<int>(); // expected-warning {{calling function 'bar<int>' requires holding mutex 'a.mu2' exclusively}}
a.mu1.Unlock();
- a.bar<int>(); // expected-warning {{calling function 'bar' requires holding mutex 'a.mu1' exclusively}} \
- expected-warning {{calling function 'bar' requires holding mutex 'a.mu2' exclusively}}
+ a.bar<int>(); // expected-warning {{calling function 'bar<int>' requires holding mutex 'a.mu1' exclusively}} \
+ expected-warning {{calling function 'bar<int>' requires holding mutex 'a.mu2' exclusively}}
}
diff --git a/test/VFS/Inputs/MissingVFS/a.h b/test/VFS/Inputs/MissingVFS/a.h
new file mode 100644
index 0000000..892d837
--- /dev/null
+++ b/test/VFS/Inputs/MissingVFS/a.h
@@ -0,0 +1 @@
+// void funcA(void);
diff --git a/test/VFS/Inputs/MissingVFS/module.modulemap b/test/VFS/Inputs/MissingVFS/module.modulemap
new file mode 100644
index 0000000..bbd9d67
--- /dev/null
+++ b/test/VFS/Inputs/MissingVFS/module.modulemap
@@ -0,0 +1,3 @@
+module A {
+ header "a.h"
+}
diff --git a/test/VFS/Inputs/MissingVFS/vfsoverlay.yaml b/test/VFS/Inputs/MissingVFS/vfsoverlay.yaml
new file mode 100644
index 0000000..49517a1
--- /dev/null
+++ b/test/VFS/Inputs/MissingVFS/vfsoverlay.yaml
@@ -0,0 +1,13 @@
+{
+ 'version': 0,
+ 'ignore-non-existent-contents': false,
+ 'roots': [
+ { 'name': 'INPUT_DIR', 'type': 'directory',
+ 'contents': [
+ { 'name': 'a.h', 'type': 'file',
+ 'external-contents': 'OUT_DIR/a.h'
+ }
+ ]
+ }
+ ]
+}
diff --git a/test/VFS/module_missing_vfs.m b/test/VFS/module_missing_vfs.m
new file mode 100644
index 0000000..4c4ee4d
--- /dev/null
+++ b/test/VFS/module_missing_vfs.m
@@ -0,0 +1,16 @@
+// REQUIRES: shell
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: echo "void funcA(void);" >> %t/a.h
+
+// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/mcp -I %S/Inputs/MissingVFS %s -fsyntax-only -ivfsoverlay %t/vfs.yaml 2>&1 | FileCheck %s -check-prefix=ERROR
+// ERROR: virtual filesystem overlay file '{{.*}}' not found
+// RUN: find %t/mcp -name "A-*.pcm" | count 1
+
+// RUN: sed -e "s:INPUT_DIR:%S/Inputs:g" -e "s:OUT_DIR:%t:g" %S/Inputs/MissingVFS/vfsoverlay.yaml > %t/vfs.yaml
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/mcp -I %S/Inputs/MissingVFS %s -fsyntax-only -ivfsoverlay %t/vfs.yaml
+// RUN: find %t/mcp -name "A-*.pcm" | count 1
+
+@import A;
+void test(void) {
+ funcA();
+}
diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp
index 2718a72..2909cdd 100644
--- a/tools/clang-format/ClangFormat.cpp
+++ b/tools/clang-format/ClangFormat.cpp
@@ -22,6 +22,7 @@
#include "clang/Rewrite/Core/Rewriter.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
using namespace llvm;
@@ -339,11 +340,19 @@
int main(int argc, const char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+ SmallVector<const char *, 256> Args;
+ llvm::SpecificBumpPtrAllocator<char> ArgAllocator;
+ std::error_code EC = llvm::sys::Process::GetArgumentVector(
+ Args, llvm::makeArrayRef(argv, argc), ArgAllocator);
+ if (EC) {
+ llvm::errs() << "error: couldn't get arguments: " << EC.message() << '\n';
+ }
+
cl::HideUnrelatedOptions(ClangFormatCategory);
cl::SetVersionPrinter(PrintVersion);
cl::ParseCommandLineOptions(
- argc, argv,
+ Args.size(), &Args[0],
"A tool to format C/C++/Java/JavaScript/Objective-C/Protobuf code.\n\n"
"If no arguments are specified, it formats the code from standard input\n"
"and writes the result to the standard output.\n"
diff --git a/tools/clang-import-test/clang-import-test.cpp b/tools/clang-import-test/clang-import-test.cpp
index e2cf7d8..d218d41 100644
--- a/tools/clang-import-test/clang-import-test.cpp
+++ b/tools/clang-import-test/clang-import-test.cpp
@@ -245,7 +245,7 @@
ASTContext &getASTContext() { return CI->getASTContext(); }
FileManager &getFileManager() { return CI->getFileManager(); }
const OriginMap &getOriginMap() {
- static const OriginMap EmptyOriginMap;
+ static const OriginMap EmptyOriginMap{};
if (ExternalASTSource *Source = CI->getASTContext().getExternalSource())
return static_cast<ExternalASTMerger *>(Source)->GetOrigins();
return EmptyOriginMap;
diff --git a/tools/diagtool/DiagTool.cpp b/tools/diagtool/DiagTool.cpp
index 7582d51..d9086af 100644
--- a/tools/diagtool/DiagTool.cpp
+++ b/tools/diagtool/DiagTool.cpp
@@ -48,7 +48,7 @@
if (len > maxName)
maxName = len;
}
- std::sort(toolNames.begin(), toolNames.end());
+ llvm::sort(toolNames.begin(), toolNames.end());
for (std::vector<llvm::StringRef>::iterator it = toolNames.begin(),
ei = toolNames.end(); it != ei; ++it) {
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index 611bff2..72d56a7 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -212,20 +212,21 @@
// Put target and mode arguments at the start of argument list so that
// arguments specified in command line could override them. Avoid putting
// them at index 0, as an option like '-cc1' must remain the first.
- auto InsertionPoint = ArgVector.begin();
- if (InsertionPoint != ArgVector.end())
+ int InsertionPoint = 0;
+ if (ArgVector.size() > 0)
++InsertionPoint;
if (NameParts.DriverMode) {
// Add the mode flag to the arguments.
- ArgVector.insert(InsertionPoint,
+ ArgVector.insert(ArgVector.begin() + InsertionPoint,
GetStableCStr(SavedStrings, NameParts.DriverMode));
}
if (NameParts.TargetIsValid) {
const char *arr[] = {"-target", GetStableCStr(SavedStrings,
NameParts.TargetPrefix)};
- ArgVector.insert(InsertionPoint, std::begin(arr), std::end(arr));
+ ArgVector.insert(ArgVector.begin() + InsertionPoint,
+ std::begin(arr), std::end(arr));
}
}
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 791b475..d7f27d1 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -1039,8 +1039,8 @@
}
// Now sort the Decls so that they appear in lexical order.
- std::sort(DeclsInContainer.begin(), DeclsInContainer.end(),
- [&SM](Decl *A, Decl *B) {
+ llvm::sort(DeclsInContainer.begin(), DeclsInContainer.end(),
+ [&SM](Decl *A, Decl *B) {
SourceLocation L_A = A->getLocStart();
SourceLocation L_B = B->getLocStart();
return L_A != L_B ?
@@ -7573,10 +7573,10 @@
if (AvailabilityAttrs.empty())
return;
- std::sort(AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
- [](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
- return LHS->getPlatform()->getName() <
- RHS->getPlatform()->getName();
+ llvm::sort(AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+ [](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+ return LHS->getPlatform()->getName() <
+ RHS->getPlatform()->getName();
});
ASTContext &Ctx = D->getASTContext();
auto It = std::unique(
diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp
index dfc0152..25bbde0 100644
--- a/tools/libclang/CXType.cpp
+++ b/tools/libclang/CXType.cpp
@@ -626,6 +626,7 @@
TCALLINGCONV(PreserveAll);
case CC_SpirFunction: return CXCallingConv_Unexposed;
case CC_OpenCLKernel: return CXCallingConv_Unexposed;
+ case CC_CUDAKernel: return CXCallingConv_Unexposed;
break;
}
#undef TCALLINGCONV
diff --git a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 3e27948..ad90f75 100644
--- a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2139,5 +2139,20 @@
functionDecl(hasTrailingReturn())));
}
+TEST(IsAssignmentOperator, Basic) {
+ StatementMatcher BinAsgmtOperator = binaryOperator(isAssignmentOperator());
+ StatementMatcher CXXAsgmtOperator =
+ cxxOperatorCallExpr(isAssignmentOperator());
+
+ EXPECT_TRUE(matches("void x() { int a; a += 1; }", BinAsgmtOperator));
+ EXPECT_TRUE(matches("void x() { int a; a = 2; }", BinAsgmtOperator));
+ EXPECT_TRUE(matches("void x() { int a; a &= 3; }", BinAsgmtOperator));
+ EXPECT_TRUE(matches("struct S { S& operator=(const S&); };"
+ "void x() { S s1, s2; s1 = s2; }",
+ CXXAsgmtOperator));
+ EXPECT_TRUE(
+ notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator));
+}
+
} // namespace ast_matchers
} // namespace clang
diff --git a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index 59fadad..6298e87 100644
--- a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1565,11 +1565,22 @@
EXPECT_TRUE(matchesObjC(
Objc1String,
objcMessageExpr(anything())));
+ EXPECT_TRUE(matchesObjC(Objc1String,
+ objcMessageExpr(hasAnySelector({
+ "contents", "meth:"}))
+
+ ));
EXPECT_TRUE(matchesObjC(
Objc1String,
objcMessageExpr(hasSelector("contents"))));
EXPECT_TRUE(matchesObjC(
Objc1String,
+ objcMessageExpr(hasAnySelector("contents", "contentsA"))));
+ EXPECT_FALSE(matchesObjC(
+ Objc1String,
+ objcMessageExpr(hasAnySelector("contentsB", "contentsC"))));
+ EXPECT_TRUE(matchesObjC(
+ Objc1String,
objcMessageExpr(matchesSelector("cont*"))));
EXPECT_FALSE(matchesObjC(
Objc1String,
diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index e699e19..c9c70a5 100644
--- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -403,11 +403,18 @@
}
TEST(Matcher, AnyArgument) {
- StatementMatcher CallArgumentY = callExpr(
- hasAnyArgument(
- ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y")))))));
+ auto HasArgumentY = hasAnyArgument(
+ ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y"))))));
+ StatementMatcher CallArgumentY = callExpr(HasArgumentY);
+ StatementMatcher ObjCCallArgumentY = objcMessageExpr(HasArgumentY);
EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }", CallArgumentY));
EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY));
+ EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) y; @end "
+ "void x(I* i) { int y; [i f:y]; }",
+ ObjCCallArgumentY));
+ EXPECT_FALSE(matchesObjC("@interface I -(void)f:(int) z; @end "
+ "void x(I* i) { int z; [i f:z]; }",
+ ObjCCallArgumentY));
EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY));
StatementMatcher ImplicitCastedArgument = callExpr(
@@ -532,6 +539,8 @@
cxxMethodDecl(hasParameter(0, varDecl()))));
EXPECT_TRUE(notMatches("class X { void x(int) {} };",
cxxMethodDecl(hasParameter(0, hasName("x")))));
+ EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
+ objcMethodDecl(hasParameter(0, hasName("x")))));
}
TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {
@@ -561,6 +570,8 @@
EXPECT_TRUE(matches(
"class Y {}; class X { void x(Y y, X x) {} };",
cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
+ objcMethodDecl(hasAnyParameter(hasName("x")))));
}
TEST(Returns, MatchesReturnTypes) {
diff --git a/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
index 0c4c7df..d670e31 100644
--- a/unittests/ASTMatchers/Dynamic/ParserTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
@@ -186,8 +186,8 @@
Parser::NamedValueMap getTestNamedValues() {
Parser::NamedValueMap Values;
Values["nameX"] = llvm::StringRef("x");
- Values["hasParamA"] =
- VariantMatcher::SingleMatcher(hasParameter(0, hasName("a")));
+ Values["hasParamA"] = VariantMatcher::SingleMatcher(
+ functionDecl(hasParameter(0, hasName("a"))));
return Values;
}
@@ -236,6 +236,17 @@
Error.toStringFull());
}
+TEST(ParserTest, VariadicMatchTest) {
+ Diagnostics Error;
+ llvm::Optional<DynTypedMatcher> OM(Parser::parseMatcherExpression(
+ "stmt(objcMessageExpr(hasAnySelector(\"methodA\", \"methodB:\")))",
+ &Error));
+ EXPECT_EQ("", Error.toStringFull());
+ auto M = OM->unconditionalConvertTo<Stmt>();
+ EXPECT_TRUE(matchesObjC("@interface I @end "
+ "void foo(I* i) { [i methodA]; }", M));
+}
+
std::string ParseWithError(StringRef Code) {
Diagnostics Error;
VariantValue Value;
@@ -329,16 +340,17 @@
EXPECT_LT(0u, Comps.size());
// Can complete names and registry together.
- Code = "cxxMethodDecl(hasP";
+ Code = "functionDecl(hasP";
Comps = Parser::completeExpression(Code, Code.size(), nullptr, &NamedValues);
ASSERT_EQ(3u, Comps.size());
- EXPECT_EQ("aramA", Comps[0].TypedText);
- EXPECT_EQ("Matcher<FunctionDecl> hasParamA", Comps[0].MatcherDecl);
- EXPECT_EQ("arameter(", Comps[1].TypedText);
+ EXPECT_EQ("arameter(", Comps[0].TypedText);
EXPECT_EQ(
"Matcher<FunctionDecl> hasParameter(unsigned, Matcher<ParmVarDecl>)",
- Comps[1].MatcherDecl);
+ Comps[0].MatcherDecl);
+
+ EXPECT_EQ("aramA", Comps[1].TypedText);
+ EXPECT_EQ("Matcher<Decl> hasParamA", Comps[1].MatcherDecl);
EXPECT_EQ("arent(", Comps[2].TypedText);
EXPECT_EQ(
diff --git a/unittests/Basic/CharInfoTest.cpp b/unittests/Basic/CharInfoTest.cpp
index 348e6ff..7a9d17f 100644
--- a/unittests/Basic/CharInfoTest.cpp
+++ b/unittests/Basic/CharInfoTest.cpp
@@ -432,6 +432,7 @@
EXPECT_TRUE(isValidIdentifier("z"));
EXPECT_TRUE(isValidIdentifier("A"));
EXPECT_TRUE(isValidIdentifier("Z"));
+ EXPECT_TRUE(isValidIdentifier("$", /*AllowDollar=*/true));
// 2 characters, '_' suffix
EXPECT_FALSE(isValidIdentifier("._"));
@@ -448,6 +449,7 @@
EXPECT_TRUE(isValidIdentifier("z_"));
EXPECT_TRUE(isValidIdentifier("A_"));
EXPECT_TRUE(isValidIdentifier("Z_"));
+ EXPECT_TRUE(isValidIdentifier("$_", /*AllowDollar=*/true));
// 2 characters, '_' prefix
EXPECT_FALSE(isValidIdentifier("_."));
@@ -464,6 +466,7 @@
EXPECT_TRUE(isValidIdentifier("_z"));
EXPECT_TRUE(isValidIdentifier("_A"));
EXPECT_TRUE(isValidIdentifier("_Z"));
+ EXPECT_TRUE(isValidIdentifier("_$", /*AllowDollar=*/true));
// 3 characters, '__' prefix
EXPECT_FALSE(isValidIdentifier("__."));
@@ -480,6 +483,7 @@
EXPECT_TRUE(isValidIdentifier("__z"));
EXPECT_TRUE(isValidIdentifier("__A"));
EXPECT_TRUE(isValidIdentifier("__Z"));
+ EXPECT_TRUE(isValidIdentifier("__$", /*AllowDollar=*/true));
// 3 characters, '_' prefix and suffix
EXPECT_FALSE(isValidIdentifier("_._"));
@@ -496,4 +500,5 @@
EXPECT_TRUE(isValidIdentifier("_z_"));
EXPECT_TRUE(isValidIdentifier("_A_"));
EXPECT_TRUE(isValidIdentifier("_Z_"));
+ EXPECT_TRUE(isValidIdentifier("_$_", /*AllowDollar=*/true));
}
diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp
index f9efbea..13c246e 100644
--- a/unittests/Basic/VirtualFileSystemTest.cpp
+++ b/unittests/Basic/VirtualFileSystemTest.cpp
@@ -471,7 +471,7 @@
}
// Check sorted contents.
- std::sort(Contents.begin(), Contents.end());
+ llvm::sort(Contents.begin(), Contents.end());
EXPECT_EQ(Expected.size(), Contents.size());
EXPECT_TRUE(std::equal(Contents.begin(), Contents.end(), Expected.begin()));
}
@@ -488,8 +488,8 @@
for (DirIter E; !EC && I != E; I.increment(EC))
InputToCheck.push_back(I->getName());
- std::sort(InputToCheck.begin(), InputToCheck.end());
- std::sort(Expected.begin(), Expected.end());
+ llvm::sort(InputToCheck.begin(), InputToCheck.end());
+ llvm::sort(Expected.begin(), Expected.end());
EXPECT_EQ(InputToCheck.size(), Expected.size());
unsigned LastElt = std::min(InputToCheck.size(), Expected.size());
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index 75667d5..819ab3c 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -6067,6 +6067,16 @@
AfterType);
}
+TEST_F(FormatTest, UnderstandsSquareAttributes) {
+ verifyFormat("SomeType s [[unused]] (InitValue);");
+ verifyFormat("SomeType s [[gnu::unused]] (InitValue);");
+ verifyFormat("SomeType s [[using gnu: unused]] (InitValue);");
+ verifyFormat("[[gsl::suppress(\"clang-tidy-check-name\")]] void f() {}");
+ verifyFormat("void f() [[deprecated(\"so sorry\")]];");
+ verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " [[unused]] aaaaaaaaaaaaaaaaaaaaaaa(int i);");
+}
+
TEST_F(FormatTest, UnderstandsEllipsis) {
verifyFormat("int printf(const char *fmt, ...);");
verifyFormat("template <class... Ts> void Foo(Ts... ts) { Foo(ts...); }");
@@ -8084,6 +8094,9 @@
"multiline raw string literal xxxxxxxxxxxxxx\n"
")x\" + bbbbbb);",
getGoogleStyleWithColumns(20)));
+ EXPECT_EQ("fffffffffff(R\"(single line raw string)\" + bbbbbb);",
+ format("fffffffffff(\n"
+ " R\"(single line raw string)\" + bbbbbb);"));
}
TEST_F(FormatTest, SkipsUnknownStringLiterals) {
@@ -8805,6 +8818,7 @@
FormatStyle Spaces = getLLVMStyle();
Spaces.SpacesInParentheses = true;
+ verifyFormat("do_something( ::globalVar );", Spaces);
verifyFormat("call( x, y, z );", Spaces);
verifyFormat("call();", Spaces);
verifyFormat("std::function<void( int, int )> callback;", Spaces);
@@ -12086,31 +12100,71 @@
EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.h", "@interface Foo\n@end\n"));
EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo", ""));
EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo", "@interface Foo\n@end\n"));
-}
-
-TEST_F(FormatTest, GuessLanguageWithForIn) {
- EXPECT_EQ(FormatStyle::LK_Cpp,
- guessLanguage("foo.h", "for (Foo *x = 0; x != in; x++) {}"));
EXPECT_EQ(FormatStyle::LK_ObjC,
- guessLanguage("foo.h", "for (Foo *x in bar) {}"));
- EXPECT_EQ(FormatStyle::LK_ObjC,
- guessLanguage("foo.h", "for (Foo *x in [bar baz]) {}"));
- EXPECT_EQ(FormatStyle::LK_ObjC,
- guessLanguage("foo.h", "for (Foo *x in [bar baz:blech]) {}"));
+ guessLanguage("foo.h", "int DoStuff(CGRect rect);\n"));
EXPECT_EQ(
FormatStyle::LK_ObjC,
- guessLanguage("foo.h", "for (Foo *x in [bar baz:blech, 1, 2, 3, 0]) {}"));
+ guessLanguage("foo.h",
+ "#define MY_POINT_MAKE(x, y) CGPointMake((x), (y));\n"));
+}
+
+TEST_F(FormatTest, GuessLanguageWithCpp11AttributeSpecifiers) {
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "[[noreturn]];"));
EXPECT_EQ(FormatStyle::LK_ObjC,
- guessLanguage("foo.h", "for (Foo *x in [bar baz:^{[uh oh];}]) {}"));
+ guessLanguage("foo.h", "array[[calculator getIndex]];"));
EXPECT_EQ(FormatStyle::LK_Cpp,
- guessLanguage("foo.h", "Foo *x; for (x = 0; x != in; x++) {}"));
- EXPECT_EQ(FormatStyle::LK_ObjC,
- guessLanguage("foo.h", "Foo *x; for (x in y) {}"));
+ guessLanguage("foo.h", "[[noreturn, deprecated(\"so sorry\")]];"));
EXPECT_EQ(
FormatStyle::LK_Cpp,
- guessLanguage(
- "foo.h",
- "for (const Foo<Bar>& baz = in.value(); !baz.at_end(); ++baz) {}"));
+ guessLanguage("foo.h", "[[noreturn, deprecated(\"gone, sorry\")]];"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "[[noreturn foo] bar];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[clang::fallthrough]];"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "[[clang:fallthrough] foo];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[gsl::suppress(\"type\")]];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[using clang: fallthrough]];"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "[[abusing clang:fallthrough] bar];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[using gsl: suppress(\"type\")]];"));
+ EXPECT_EQ(
+ FormatStyle::LK_Cpp,
+ guessLanguage("foo.h",
+ "[[clang::callable_when(\"unconsumed\", \"unknown\")]]"));
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "[[foo::bar, ...]]"));
+}
+
+TEST_F(FormatTest, GuessLanguageWithCaret) {
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "FOO(^);"));
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "FOO(^, Bar);"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "int(^)(char, float);"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "int(^foo)(char, float);"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "int(^foo[10])(char, float);"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "int(^foo[kNumEntries])(char, float);"));
+ EXPECT_EQ(
+ FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "int(^foo[(kNumEntries + 10)])(char, float);"));
+}
+
+TEST_F(FormatTest, GuessLanguageWithChildLines) {
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "#define FOO ({ std::string s; })"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "#define FOO ({ NSString *s; })"));
+ EXPECT_EQ(
+ FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "#define FOO ({ foo(); ({ std::string s; }) })"));
+ EXPECT_EQ(
+ FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "#define FOO ({ foo(); ({ NSString *s; }) })"));
}
} // end namespace
diff --git a/unittests/Format/FormatTestObjC.cpp b/unittests/Format/FormatTestObjC.cpp
index 8773088..5c12911 100644
--- a/unittests/Format/FormatTestObjC.cpp
+++ b/unittests/Format/FormatTestObjC.cpp
@@ -514,6 +514,7 @@
" evenLongerKeyword:(float)theInterval\n"
" error:(NSError **)theError {\n"
"}");
+ verifyFormat("+ (instancetype)new;\n");
Style.ColumnLimit = 60;
verifyFormat("- (instancetype)initXxxxxx:(id<x>)x\n"
" y:(id<yyyyyyyyyyyyyyyyyyyy>)y\n"
@@ -536,6 +537,22 @@
" aShortf:(NSRect)theRect {\n"
"}");
+ // Make sure selectors with 0, 1, or more arguments are indented
+ // when IndentWrappedFunctionNames is true.
+ verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa;\n");
+ verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+ verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+ verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+ verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+
// Format pairs correctly.
Style.ColumnLimit = 80;
verifyFormat("- (void)drawRectOn:(id)surface\n"
@@ -618,6 +635,9 @@
verifyFormat("for (id foo in [self getStuffFor:bla]) {\n"
"}");
verifyFormat("[self aaaaa:MACRO(a, b:, c:)];");
+ verifyFormat("[self aaaaa:MACRO(a, b:c:, d:e:)];");
+ verifyFormat("[self aaaaa:MACRO(a, b:c:d:, e:f:g:)];");
+ verifyFormat("int XYMyFoo(int a, int b) NS_SWIFT_NAME(foo(self:scale:));");
verifyFormat("[self aaaaa:(1 + 2) bbbbb:3];");
verifyFormat("[self aaaaa:(Type)a bbbbb:3];");
@@ -845,6 +865,15 @@
verifyFormat("@ /*foo*/ interface");
}
+TEST_F(FormatTestObjC, ObjCBlockTypesAndVariables) {
+ verifyFormat("void DoStuffWithBlockType(int (^)(char));");
+ verifyFormat("int (^foo)(char, float);");
+ verifyFormat("int (^foo[10])(char, float);");
+ verifyFormat("int (^foo[kNumEntries])(char, float);");
+ verifyFormat("int (^foo[kNumEntries + 10])(char, float);");
+ verifyFormat("int (^foo[(kNumEntries + 10)])(char, float);");
+}
+
TEST_F(FormatTestObjC, ObjCSnippets) {
verifyFormat("@autoreleasepool {\n"
" foo();\n"
@@ -902,6 +931,17 @@
" }]) {\n}");
}
+TEST_F(FormatTestObjC, ObjCNew) {
+ verifyFormat("+ (instancetype)new {\n"
+ " return nil;\n"
+ "}\n");
+ verifyFormat("+ (instancetype)myNew {\n"
+ " return [self new];\n"
+ "}\n");
+ verifyFormat("SEL NewSelector(void) { return @selector(new); }\n");
+ verifyFormat("SEL MacroSelector(void) { return MACRO(new); }\n");
+}
+
TEST_F(FormatTestObjC, ObjCLiterals) {
verifyFormat("@\"String\"");
verifyFormat("@1");
@@ -976,6 +1016,21 @@
" (aaaaaaaa id)aaaaaaaaa : (aaaaaaaa id)aaaaaaaaaaaaaaaaaaaaaaaa,\n"
" (aaaaaaaa id)aaaaaaaaaaaaaa : (aaaaaaaa id)aaaaaaaaaaaaaa,\n"
"};");
+ Style.ColumnLimit = 40;
+ verifyFormat("int Foo() {\n"
+ " a12345 = @{a12345 : a12345};\n"
+ "}");
+ verifyFormat("int Foo() {\n"
+ " a12345 = @{(Foo *)a12345 : @(a12345)};\n"
+ "}");
+ Style.SpacesInContainerLiterals = false;
+ verifyFormat("int Foo() {\n"
+ " b12345 = @{b12345: b12345};\n"
+ "}");
+ verifyFormat("int Foo() {\n"
+ " b12345 = @{(Foo *)b12345: @(b12345)};\n"
+ "}");
+ Style.SpacesInContainerLiterals = true;
Style = getGoogleStyle(FormatStyle::LK_ObjC);
verifyFormat(
@@ -1031,6 +1086,21 @@
verifyFormat("[someFunction someLooooooooooooongParameter:@[\n"
" NSBundle.mainBundle.infoDictionary[@\"a\"]\n"
"]];");
+ Style.ColumnLimit = 40;
+ verifyFormat("int Foo() {\n"
+ " a12345 = @[ a12345, a12345 ];\n"
+ "}");
+ verifyFormat("int Foo() {\n"
+ " a123 = @[ (Foo *)a12345, @(a12345) ];\n"
+ "}");
+ Style.SpacesInContainerLiterals = false;
+ verifyFormat("int Foo() {\n"
+ " b12345 = @[b12345, b12345];\n"
+ "}");
+ verifyFormat("int Foo() {\n"
+ " b12345 = @[(Foo *)b12345, @(b12345)];\n"
+ "}");
+ Style.SpacesInContainerLiterals = true;
Style.ColumnLimit = 20;
// We can't break string literals inside NSArray literals
// (that raises -Wobjc-string-concatenation).
diff --git a/unittests/Format/FormatTestProto.cpp b/unittests/Format/FormatTestProto.cpp
index 6db44c7..66c5d37 100644
--- a/unittests/Format/FormatTestProto.cpp
+++ b/unittests/Format/FormatTestProto.cpp
@@ -158,9 +158,8 @@
" key: 'a' //\n"
" }\n"
"];");
- verifyFormat("optional string test = 1 [default =\n"
- " \"test\"\n"
- " \"test\"];");
+ verifyFormat("optional string test = 1 [default = \"test\"\n"
+ " \"test\"];");
verifyFormat("optional Aaaaaaaa aaaaaaaa = 12 [\n"
" (aaa) = aaaa,\n"
" (bbbbbbbbbbbbbbbbbbbbbbbbbb) = {\n"
diff --git a/unittests/Format/FormatTestRawStrings.cpp b/unittests/Format/FormatTestRawStrings.cpp
index 21bbc3f..f5a0c1e 100644
--- a/unittests/Format/FormatTestRawStrings.cpp
+++ b/unittests/Format/FormatTestRawStrings.cpp
@@ -164,6 +164,20 @@
getRawStringPbStyleWithColumns(40)));
}
+TEST_F(FormatTestRawStrings, RespectsClangFormatOff) {
+ expect_eq(R"test(
+// clang-format off
+s = R"pb(item: 1)pb";
+// clang-format on
+t = R"pb(item: 1)pb";)test",
+ format(R"test(
+// clang-format off
+s = R"pb(item: 1)pb";
+// clang-format on
+t = R"pb(item: 1)pb";)test",
+ getRawStringPbStyleWithColumns(40)));
+}
+
TEST_F(FormatTestRawStrings, ReformatsShortRawStringsOnSingleLine) {
expect_eq(
R"test(P p = TP(R"pb()pb");)test",
@@ -681,15 +695,14 @@
})test",
getRawStringPbStyleWithColumns(20)));
- // Align the suffix with the surrounding FirstIndent if the prefix is not on
+ // Align the suffix with the surrounding indent if the prefix is not on
// a line of its own.
expect_eq(R"test(
int s() {
- auto S = PTP(
- R"pb(
- item_1: 1,
- item_2: 2
- )pb");
+ auto S = PTP(R"pb(
+ item_1: 1,
+ item_2: 2
+ )pb");
})test",
format(R"test(
int s() {
@@ -781,6 +794,34 @@
format(R"test(a = R"pb(key:")proto")pb";)test", Style));
}
+TEST_F(FormatTestRawStrings, PenalizesPrefixExcessChars) {
+ FormatStyle Style = getRawStringPbStyleWithColumns(60);
+
+ // The '(' in R"pb is at column 60, no break.
+ expect_eq(R"test(
+xxxxxxxaaaaax wwwwwww = _Verxrrrrrrrr(PARSE_TEXT_PROTO(R"pb(
+ Category: aaaaaaaaaaaaaaaaaaaaaaaaaa
+)pb"));
+)test",
+ format(R"test(
+xxxxxxxaaaaax wwwwwww = _Verxrrrrrrrr(PARSE_TEXT_PROTO(R"pb(
+ Category: aaaaaaaaaaaaaaaaaaaaaaaaaa
+)pb"));
+)test", Style));
+ // The '(' in R"pb is at column 61, break.
+ expect_eq(R"test(
+xxxxxxxaaaaax wwwwwww =
+ _Verxrrrrrrrrr(PARSE_TEXT_PROTO(R"pb(
+ Category: aaaaaaaaaaaaaaaaaaaaaaaaaa
+ )pb"));
+)test",
+ format(R"test(
+xxxxxxxaaaaax wwwwwww = _Verxrrrrrrrrr(PARSE_TEXT_PROTO(R"pb(
+ Category: aaaaaaaaaaaaaaaaaaaaaaaaaa
+)pb"));
+)test", Style));
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
diff --git a/unittests/Format/FormatTestTextProto.cpp b/unittests/Format/FormatTestTextProto.cpp
index 1102055..f4e09cf 100644
--- a/unittests/Format/FormatTestTextProto.cpp
+++ b/unittests/Format/FormatTestTextProto.cpp
@@ -143,6 +143,23 @@
"}");
}
+TEST_F(FormatTestTextProto, ImplicitStringLiteralConcatenation) {
+ verifyFormat("field_a: 'aaaaa'\n"
+ " 'bbbbb'");
+ verifyFormat("field_a: \"aaaaa\"\n"
+ " \"bbbbb\"");
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
+ Style.AlwaysBreakBeforeMultilineStrings = true;
+ verifyFormat("field_a:\n"
+ " 'aaaaa'\n"
+ " 'bbbbb'",
+ Style);
+ verifyFormat("field_a:\n"
+ " \"aaaaa\"\n"
+ " \"bbbbb\"",
+ Style);
+}
+
TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) {
// Single-line tests
verifyFormat("msg_field <>");
@@ -375,10 +392,12 @@
" .long/longg.longlong] { key: value }");
verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/\n"
" bbbbbbbbbbbbbb] { key: value }");
- verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- "] { key: value }");
- verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- "] {\n"
+ // These go over the column limit intentionally, since the alternative
+ // [aa..a\n] is worse.
+ verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] {\n"
+ " key: value\n"
+ "}");
+ verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] {\n"
" [type.type] {\n"
" keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
" }\n"
@@ -452,5 +471,26 @@
" >\n"
">");
}
+
+TEST_F(FormatTestTextProto, BreaksConsecutiveStringLiterals) {
+ verifyFormat("ala: \"str1\"\n"
+ " \"str2\"\n");
+}
+
+TEST_F(FormatTestTextProto, PutsMultipleEntriesInExtensionsOnNewlines) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
+ verifyFormat("pppppppppp: {\n"
+ " ssssss: \"http://example.com/blahblahblah\"\n"
+ " ppppppp: \"sssss/MMMMMMMMMMMM\"\n"
+ " [ns.sssss.eeeeeeeee.eeeeeeeeeeeeeee] { begin: 24 end: 252 }\n"
+ " [ns.sssss.eeeeeeeee.eeeeeeeeeeeeeee] {\n"
+ " begin: 24\n"
+ " end: 252\n"
+ " key: value\n"
+ " key: value\n"
+ " }\n"
+ "}", Style);
+}
+
} // end namespace tooling
} // end namespace clang
diff --git a/unittests/Tooling/ToolingTest.cpp b/unittests/Tooling/ToolingTest.cpp
index 6dd0e53..bd57118 100644
--- a/unittests/Tooling/ToolingTest.cpp
+++ b/unittests/Tooling/ToolingTest.cpp
@@ -319,8 +319,8 @@
TEST(runToolOnCodeWithArgs, TestNoDepFile) {
llvm::SmallString<32> DepFilePath;
- ASSERT_FALSE(
- llvm::sys::fs::createTemporaryFile("depfile", "d", DepFilePath));
+ ASSERT_FALSE(llvm::sys::fs::getPotentiallyUniqueTempFileName("depfile", "d",
+ DepFilePath));
std::vector<std::string> Args;
Args.push_back("-MMD");
Args.push_back("-MT");
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index 263dcae..0f8bb18 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -104,6 +104,7 @@
.Case("Expr *", "Record.readExpr()")
.Case("IdentifierInfo *", "Record.getIdentifierInfo()")
.Case("StringRef", "Record.readString()")
+ .Case("ParamIdx", "ParamIdx::deserialize(Record.readInt())")
.Default("Record.readInt()");
}
@@ -122,6 +123,7 @@
.Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
.Case("IdentifierInfo *", "AddIdentifierRef(" + std::string(name) + ");\n")
.Case("StringRef", "AddString(" + std::string(name) + ");\n")
+ .Case("ParamIdx", "push_back(" + std::string(name) + ".serialize());\n")
.Default("push_back(" + std::string(name) + ");\n");
}
@@ -302,6 +304,8 @@
std::string getIsOmitted() const override {
if (type == "IdentifierInfo *")
return "!get" + getUpperName().str() + "()";
+ if (type == "ParamIdx")
+ return "!get" + getUpperName().str() + "().isValid()";
return "false";
}
@@ -316,6 +320,8 @@
<< "()->getName() : \"\") << \"";
else if (type == "TypeSourceInfo *")
OS << "\" << get" << getUpperName() << "().getAsString() << \"";
+ else if (type == "ParamIdx")
+ OS << "\" << get" << getUpperName() << "().getSourceIndex() << \"";
else
OS << "\" << get" << getUpperName() << "() << \"";
}
@@ -338,6 +344,11 @@
<< getUpperName() << "\";\n";
} else if (type == "int" || type == "unsigned") {
OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
+ } else if (type == "ParamIdx") {
+ if (isOptional())
+ OS << " if (SA->get" << getUpperName() << "().isValid())\n ";
+ OS << " OS << \" \" << SA->get" << getUpperName()
+ << "().getSourceIndex();\n";
} else {
llvm_unreachable("Unknown SimpleArgument type!");
}
@@ -615,6 +626,10 @@
virtual void writeValueImpl(raw_ostream &OS) const {
OS << " OS << Val;\n";
}
+ // Assumed to receive a parameter: raw_ostream OS.
+ virtual void writeDumpImpl(raw_ostream &OS) const {
+ OS << " OS << \" \" << Val;\n";
+ }
public:
VariadicArgument(const Record &Arg, StringRef Attr, std::string T)
@@ -741,7 +756,7 @@
void writeDump(raw_ostream &OS) const override {
OS << " for (const auto &Val : SA->" << RangeName << "())\n";
- OS << " OS << \" \" << Val;\n";
+ writeDumpImpl(OS);
}
};
@@ -751,129 +766,12 @@
: VariadicArgument(Arg, Attr, "ParamIdx") {}
public:
- void writeCtorBody(raw_ostream &OS) const override {
- VariadicArgument::writeCtorBody(OS);
- OS << " #ifndef NDEBUG\n"
- << " if (" << getLowerName() << "_size()) {\n"
- << " bool HasThis = " << getLowerName()
- << "_begin()->hasThis();\n"
- << " for (const auto Idx : " << getLowerName() << "()) {\n"
- << " assert(Idx.isValid() && \"ParamIdx must be valid\");\n"
- << " assert(HasThis == Idx.hasThis() && "
- << "\"HasThis must be consistent\");\n"
- << " }\n"
- << " }\n"
- << " #endif\n";
- }
-
- void writePCHReadDecls(raw_ostream &OS) const override {
- OS << " unsigned " << getUpperName() << "Size = Record.readInt();\n";
- OS << " bool " << getUpperName() << "HasThis = " << getUpperName()
- << "Size ? Record.readInt() : false;\n";
- OS << " SmallVector<ParamIdx, 4> " << getUpperName() << ";\n"
- << " " << getUpperName() << ".reserve(" << getUpperName()
- << "Size);\n"
- << " for (unsigned i = 0; i != " << getUpperName()
- << "Size; ++i) {\n"
- << " " << getUpperName()
- << ".push_back(ParamIdx(Record.readInt(), " << getUpperName()
- << "HasThis));\n"
- << " }\n";
- }
-
- void writePCHReadArgs(raw_ostream &OS) const override {
- OS << getUpperName() << ".data(), " << getUpperName() << "Size";
- }
-
- void writePCHWrite(raw_ostream &OS) const override {
- OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
- OS << " if (SA->" << getLowerName() << "_size())\n"
- << " Record.push_back(SA->" << getLowerName()
- << "_begin()->hasThis());\n";
- OS << " for (auto Idx : SA->" << getLowerName() << "())\n"
- << " Record.push_back(Idx.getSourceIndex());\n";
- }
-
void writeValueImpl(raw_ostream &OS) const override {
OS << " OS << Val.getSourceIndex();\n";
}
- void writeDump(raw_ostream &OS) const override {
- OS << " for (auto Idx : SA->" << getLowerName() << "())\n";
- OS << " OS << \" \" << Idx.getSourceIndex();\n";
- }
- };
-
- class ParamIdxArgument : public Argument {
- std::string IdxName;
-
- public:
- ParamIdxArgument(const Record &Arg, StringRef Attr)
- : Argument(Arg, Attr), IdxName(getUpperName()) {}
-
- void writeDeclarations(raw_ostream &OS) const override {
- OS << "ParamIdx " << IdxName << ";\n";
- }
-
- void writeAccessors(raw_ostream &OS) const override {
- OS << "\n"
- << " ParamIdx " << getLowerName() << "() const {"
- << " return " << IdxName << "; }\n";
- }
-
- void writeCtorParameters(raw_ostream &OS) const override {
- OS << "ParamIdx " << IdxName;
- }
-
- void writeCloneArgs(raw_ostream &OS) const override { OS << IdxName; }
-
- void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
- OS << "A->" << getLowerName() << "()";
- }
-
- void writeImplicitCtorArgs(raw_ostream &OS) const override {
- OS << IdxName;
- }
-
- void writeCtorInitializers(raw_ostream &OS) const override {
- OS << IdxName << "(" << IdxName << ")";
- }
-
- void writeCtorDefaultInitializers(raw_ostream &OS) const override {
- OS << IdxName << "()";
- }
-
- void writePCHReadDecls(raw_ostream &OS) const override {
- OS << " unsigned " << IdxName << "Src = Record.readInt();\n";
- OS << " bool " << IdxName << "HasThis = Record.readInt();\n";
- }
-
- void writePCHReadArgs(raw_ostream &OS) const override {
- OS << "ParamIdx(" << IdxName << "Src, " << IdxName << "HasThis)";
- }
-
- void writePCHWrite(raw_ostream &OS) const override {
- OS << " Record.push_back(SA->" << getLowerName()
- << "().isValid() ? SA->" << getLowerName()
- << "().getSourceIndex() : 0);\n";
- OS << " Record.push_back(SA->" << getLowerName()
- << "().isValid() ? SA->" << getLowerName()
- << "().hasThis() : false);\n";
- }
-
- std::string getIsOmitted() const override {
- return "!" + IdxName + ".isValid()";
- }
-
- void writeValue(raw_ostream &OS) const override {
- OS << "\" << " << IdxName << ".getSourceIndex() << \"";
- }
-
- void writeDump(raw_ostream &OS) const override {
- if (isOptional())
- OS << " if (SA->" << getLowerName() << "().isValid())\n ";
- OS << " OS << \" \" << SA->" << getLowerName()
- << "().getSourceIndex();\n";
+ void writeDumpImpl(raw_ostream &OS) const override {
+ OS << " OS << \" \" << Val.getSourceIndex();\n";
}
};
@@ -1379,7 +1277,7 @@
else if (ArgName == "VariadicParamIdxArgument")
Ptr = llvm::make_unique<VariadicParamIdxArgument>(Arg, Attr);
else if (ArgName == "ParamIdxArgument")
- Ptr = llvm::make_unique<ParamIdxArgument>(Arg, Attr);
+ Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "ParamIdx");
else if (ArgName == "VersionArgument")
Ptr = llvm::make_unique<VersionArgument>(Arg, Attr);
@@ -4010,9 +3908,9 @@
for (auto &I : SplitDocs) {
WriteCategoryHeader(I.first, OS);
- std::sort(I.second.begin(), I.second.end(),
- [](const DocumentationData &D1, const DocumentationData &D2) {
- return D1.Heading < D2.Heading;
+ llvm::sort(I.second.begin(), I.second.end(),
+ [](const DocumentationData &D1, const DocumentationData &D2) {
+ return D1.Heading < D2.Heading;
});
// Walk over each of the attributes in the category and write out their
diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp
index 4a2516f..a8a56df 100644
--- a/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -207,9 +207,9 @@
E = SortedGroups.end();
I != E; ++I) {
MutableArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
- std::sort(GroupDiags.begin(), GroupDiags.end(), beforeThanCompare);
+ llvm::sort(GroupDiags.begin(), GroupDiags.end(), beforeThanCompare);
}
- std::sort(SortedGroups.begin(), SortedGroups.end(), beforeThanCompareGroups);
+ llvm::sort(SortedGroups.begin(), SortedGroups.end(), beforeThanCompareGroups);
// Warn about the same group being used anonymously in multiple places.
for (SmallVectorImpl<GroupInfo *>::const_iterator I = SortedGroups.begin(),
@@ -863,9 +863,10 @@
Index.push_back(RecordIndexElement(R));
}
- std::sort(Index.begin(), Index.end(),
- [](const RecordIndexElement &Lhs,
- const RecordIndexElement &Rhs) { return Lhs.Name < Rhs.Name; });
+ llvm::sort(Index.begin(), Index.end(),
+ [](const RecordIndexElement &Lhs, const RecordIndexElement &Rhs) {
+ return Lhs.Name < Rhs.Name;
+ });
for (unsigned i = 0, e = Index.size(); i != e; ++i) {
const RecordIndexElement &R = Index[i];
@@ -1212,7 +1213,7 @@
Records.getAllDerivedDefinitions("Diagnostic");
std::vector<Record*> DiagGroups =
Records.getAllDerivedDefinitions("DiagGroup");
- std::sort(DiagGroups.begin(), DiagGroups.end(), diagGroupBeforeByName);
+ llvm::sort(DiagGroups.begin(), DiagGroups.end(), diagGroupBeforeByName);
DiagGroupParentMap DGParentMap(Records);
@@ -1231,10 +1232,10 @@
DiagsInPedanticSet.end());
RecordVec GroupsInPedantic(GroupsInPedanticSet.begin(),
GroupsInPedanticSet.end());
- std::sort(DiagsInPedantic.begin(), DiagsInPedantic.end(),
- beforeThanCompare);
- std::sort(GroupsInPedantic.begin(), GroupsInPedantic.end(),
- beforeThanCompare);
+ llvm::sort(DiagsInPedantic.begin(), DiagsInPedantic.end(),
+ beforeThanCompare);
+ llvm::sort(GroupsInPedantic.begin(), GroupsInPedantic.end(),
+ beforeThanCompare);
PedDiags.DiagsInGroup.insert(PedDiags.DiagsInGroup.end(),
DiagsInPedantic.begin(),
DiagsInPedantic.end());
@@ -1283,7 +1284,7 @@
OS << "Also controls ";
bool First = true;
- std::sort(GroupInfo.SubGroups.begin(), GroupInfo.SubGroups.end());
+ llvm::sort(GroupInfo.SubGroups.begin(), GroupInfo.SubGroups.end());
for (const auto &Name : GroupInfo.SubGroups) {
if (!First) OS << ", ";
OS << "`" << (IsRemarkGroup ? "-R" : "-W") << Name << "`_";
diff --git a/utils/TableGen/ClangOptionDocEmitter.cpp b/utils/TableGen/ClangOptionDocEmitter.cpp
index 734ff0b..7fe487e 100644
--- a/utils/TableGen/ClangOptionDocEmitter.cpp
+++ b/utils/TableGen/ClangOptionDocEmitter.cpp
@@ -111,7 +111,7 @@
auto DocumentationForOption = [&](Record *R) -> DocumentedOption {
auto &A = Aliases[R];
- std::sort(A.begin(), A.end(), CompareByName);
+ llvm::sort(A.begin(), A.end(), CompareByName);
return {R, std::move(A)};
};
@@ -120,7 +120,7 @@
Documentation D;
auto &Groups = GroupsInGroup[R];
- std::sort(Groups.begin(), Groups.end(), CompareByLocation);
+ llvm::sort(Groups.begin(), Groups.end(), CompareByLocation);
for (Record *G : Groups) {
D.Groups.emplace_back();
D.Groups.back().Group = G;
@@ -129,7 +129,7 @@
}
auto &Options = OptionsInGroup[R];
- std::sort(Options.begin(), Options.end(), CompareByName);
+ llvm::sort(Options.begin(), Options.end(), CompareByName);
for (Record *O : Options)
D.Options.push_back(DocumentationForOption(O));
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 1a95ca4..b9f0224 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -2007,7 +2007,7 @@
}
}
- std::sort(NewTypeSpecs.begin(), NewTypeSpecs.end());
+ llvm::sort(NewTypeSpecs.begin(), NewTypeSpecs.end());
NewTypeSpecs.erase(std::unique(NewTypeSpecs.begin(), NewTypeSpecs.end()),
NewTypeSpecs.end());
auto &Entry = IntrinsicMap[Name];
diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py
index 51e5f4e..8f765b9 100755
--- a/utils/analyzer/SATestBuild.py
+++ b/utils/analyzer/SATestBuild.py
@@ -180,7 +180,7 @@
"nullability"
])
-Verbose = 1
+Verbose = 0
#------------------------------------------------------------------------------
# Test harness logic.
diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html
index f9a8f59..c5a8ac8 100644
--- a/www/cxx_dr_status.html
+++ b/www/cxx_dr_status.html
@@ -303,7 +303,7 @@
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#44">44</a></td>
<td>CD1</td>
<td>Member specializations</td>
- <td class="full" align="center">Yes</td>
+ <td class="svn" align="center">Superseded by <a href="#727">727</a></td>
</tr>
<tr id="45">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45">45</a></td>
@@ -937,7 +937,7 @@
</tr>
<tr id="150">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#150">150</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Template template parameters and default arguments</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -1554,11 +1554,11 @@
<td>Looking up deallocation functions in virtual destructors</td>
<td class="full" align="center">Yes</td>
</tr>
- <tr class="open" id="253">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#253">253</a></td>
- <td>drafting</td>
+ <tr id="253">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#253">253</a></td>
+ <td>C++17</td>
<td>Why must empty or fully-initialized const objects be initialized?</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="254">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#254">254</a></td>
@@ -1921,11 +1921,11 @@
<td>Class with single conversion function to integral as array size in <TT>new</TT></td>
<td class="full" align="center">Duplicate of <a href="#299">299</a> (C++11 onwards)</td>
</tr>
- <tr class="open" id="314">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#314">314</a></td>
- <td>drafting</td>
+ <tr id="314">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#314">314</a></td>
+ <td>C++17</td>
<td><TT>template</TT> in base class specifier</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="315">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#315">315</a></td>
@@ -2095,11 +2095,11 @@
<td>Terminology: "indirection" versus "dereference"</td>
<td class="na" align="center">N/A</td>
</tr>
- <tr class="open" id="343">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#343">343</a></td>
- <td>drafting</td>
+ <tr id="343">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#343">343</a></td>
+ <td>C++17</td>
<td>Make <TT>template</TT> optional in contexts that require a type</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="344">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#344">344</a></td>
@@ -2285,7 +2285,7 @@
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#374">374</a></td>
<td>CD2</td>
<td>Can explicit specialization outside namespace use qualified name?</td>
- <td class="full" align="center">Yes (C++11 onwards)</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="375">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#375">375</a></td>
@@ -2593,11 +2593,11 @@
<td>Set of candidates for overloaded built-in operator with float operand</td>
<td class="full" align="center">Yes</td>
</tr>
- <tr class="open" id="426">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#426">426</a></td>
- <td>review</td>
+ <tr id="426">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#426">426</a></td>
+ <td>C++17</td>
<td>Identically-named variables, one internally and one externally linked, allowed?</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="427">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#427">427</a></td>
@@ -3615,11 +3615,11 @@
<td>Exception specifications in templates instantiated from class bodies</td>
<td class="full" align="center">Duplicate of <a href="#1330">1330</a></td>
</tr>
- <tr class="open" id="596">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#596">596</a></td>
- <td>open</td>
+ <tr id="596">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#596">596</a></td>
+ <td>NAD</td>
<td>Replacing an exception object</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="597">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#597">597</a></td>
@@ -3855,11 +3855,11 @@
<td>Names of constructors and destructors of templates</td>
<td class="full" align="center">Yes</td>
</tr>
- <tr class="open" id="636">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#636">636</a></td>
- <td>drafting</td>
+ <tr id="636">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#636">636</a></td>
+ <td>CD4</td>
<td>Dynamic type of objects and aliasing</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="637">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#637">637</a></td>
@@ -4383,11 +4383,11 @@
<td>Atomic and non-atomic objects in the memory model</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="727">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#727">727</a></td>
- <td>drafting</td>
+ <tr id="727">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#727">727</a></td>
+ <td>C++17</td>
<td>In-class explicit specializations</td>
- <td align="center">Not resolved</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr class="open" id="728">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#728">728</a></td>
@@ -5235,11 +5235,11 @@
<td>Explicit conversion functions in direct class initialization</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr id="900">
+ <tr class="open" id="900">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#900">900</a></td>
- <td>NAD</td>
+ <td>extension</td>
<td>Lifetime of temporaries in range-based <TT>for</TT></td>
- <td class="none" align="center">Unknown</td>
+ <td align="center">Not resolved</td>
</tr>
<tr class="open" id="901">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#901">901</a></td>
@@ -5469,11 +5469,11 @@
<td>Is <TT>this</TT> an entity?</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="943">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#943">943</a></td>
- <td>open</td>
+ <tr id="943">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#943">943</a></td>
+ <td>DRWP</td>
<td>Is <TT>T()</TT> a temporary?</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="944">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#944">944</a></td>
@@ -6267,11 +6267,11 @@
<td>Grammar does not allow template alias in <I>type-name</I></td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1076">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1076">1076</a></td>
- <td>open</td>
+ <tr id="1076">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1076">1076</a></td>
+ <td>DRWP</td>
<td>Value categories and lvalue temporaries</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1077">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1077">1077</a></td>
@@ -7605,11 +7605,11 @@
<td>Incorrect example in overload resolution</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1299">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1299">1299</a></td>
- <td>drafting</td>
+ <tr id="1299">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1299">1299</a></td>
+ <td>DRWP</td>
<td>“Temporary objects” vs “temporary expressions”</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1300">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1300">1300</a></td>
@@ -7871,7 +7871,7 @@
</tr>
<tr id="1343">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1343">1343</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Sequencing of non-class initialization</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -8183,7 +8183,7 @@
</tr>
<tr id="1395">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1395">1395</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Partial ordering of variadic templates reconsidered</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -8949,11 +8949,11 @@
<td>Access checking for <TT>initializer_list</TT> array initialization</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1523">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1523">1523</a></td>
- <td>drafting</td>
+ <tr id="1523">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1523">1523</a></td>
+ <td>DRWP</td>
<td>Point of declaration in range-based <TT>for</TT></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1524">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1524">1524</a></td>
@@ -9544,8 +9544,8 @@
<td align="center">Not resolved</td>
</tr>
<tr id="1622">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1622">1622</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1622">1622</a></td>
+ <td>C++17</td>
<td>Empty aggregate initializer for union</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -9874,8 +9874,8 @@
<td align="center">Not resolved</td>
</tr>
<tr id="1677">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677">1677</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1677">1677</a></td>
+ <td>C++17</td>
<td>Constant initialization via aggregate initialization</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -10035,11 +10035,11 @@
<td>Language linkage of names of functions with internal linkage</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1704">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1704">1704</a></td>
- <td>drafting</td>
+ <tr id="1704">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1704">1704</a></td>
+ <td>DRWP</td>
<td>Type checking in explicit instantiation of variable templates</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1705">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1705">1705</a></td>
@@ -10071,11 +10071,11 @@
<td>Stringizing raw string literals containing newline</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="1710">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1710">1710</a></td>
- <td>drafting</td>
+ <tr id="1710">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1710">1710</a></td>
+ <td>C++17</td>
<td>Missing <TT>template</TT> keyword in <I>class-or-decltype</I></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1711">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1711">1711</a></td>
@@ -10179,11 +10179,11 @@
<td>Type of a specialization of a variable template</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1728">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1728">1728</a></td>
- <td>drafting</td>
+ <tr id="1728">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1728">1728</a></td>
+ <td>DRWP</td>
<td>Type of an explicit instantiation of a variable template</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1729">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1729">1729</a></td>
@@ -10515,17 +10515,17 @@
<td>Why are virtual destructors non-trivial?</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1784">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1784">1784</a></td>
- <td>concurrency</td>
+ <tr id="1784">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1784">1784</a></td>
+ <td>C++17</td>
<td>Concurrent execution during static local initialization</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1785">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1785">1785</a></td>
- <td>drafting</td>
+ <tr id="1785">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1785">1785</a></td>
+ <td>NAD</td>
<td>Conflicting diagnostic requirements for template definitions</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1786">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1786">1786</a></td>
@@ -10575,11 +10575,11 @@
<td><TT>thread_local</TT> in explicit specializations</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1794">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1794">1794</a></td>
- <td>drafting</td>
+ <tr id="1794">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1794">1794</a></td>
+ <td>C++17</td>
<td><TT>template</TT> keyword and alias templates</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1795">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1795">1795</a></td>
@@ -10683,11 +10683,11 @@
<td>Lookup of deallocation function in a virtual destructor definition</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1812">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1812">1812</a></td>
- <td>drafting</td>
+ <tr id="1812">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1812">1812</a></td>
+ <td>C++17</td>
<td>Omission of <TT>template</TT> in a <I>typename-specifier</I></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1813">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1813">1813</a></td>
@@ -10763,7 +10763,7 @@
</tr>
<tr id="1825">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1825">1825</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Partial ordering between variadic and non-variadic function templates</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -10827,11 +10827,11 @@
<td>Dependent member lookup before <TT><</TT></td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="1836">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1836">1836</a></td>
- <td>drafting</td>
+ <tr id="1836">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1836">1836</a></td>
+ <td>DRWP</td>
<td>Use of class type being defined in <I>trailing-return-type</I></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1837">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1837">1837</a></td>
@@ -10972,8 +10972,8 @@
<td align="center">Not resolved</td>
</tr>
<tr id="1860">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1860">1860</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1860">1860</a></td>
+ <td>C++17</td>
<td>What is a “direct member?”</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -10983,11 +10983,11 @@
<td>Values of a bit-field</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1862">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1862">1862</a></td>
- <td>drafting</td>
+ <tr id="1862">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1862">1862</a></td>
+ <td>DR</td>
<td>Determining “corresponding members” for friendship</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1863">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1863">1863</a></td>
@@ -11169,11 +11169,11 @@
<td>Use of <TT>auto</TT> in function type</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1893">
+ <tr id="1893">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1893">1893</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Function-style cast with <I>braced-init-list</I>s and empty pack expansions</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1894">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1894">1894</a></td>
@@ -11249,7 +11249,7 @@
</tr>
<tr class="open" id="1906">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1906">1906</a></td>
- <td>drafting</td>
+ <td>review</td>
<td>Name lookup in member <TT>friend</TT> declaration</td>
<td align="center">Not resolved</td>
</tr>
@@ -11271,11 +11271,11 @@
<td>Member class template with the same name as the class</td>
<td class="full" align="center">Yes</td>
</tr>
- <tr class="open" id="1910">
+ <tr id="1910">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1910">1910</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>“Shall” requirement applied to runtime behavior</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1911">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1911">1911</a></td>
@@ -11579,7 +11579,7 @@
</tr>
<tr id="1961">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1961">1961</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Potentially-concurrent actions within a signal handler</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11709,11 +11709,11 @@
<td>Deduction extending parameter pack</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1983">
+ <tr id="1983">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1983">1983</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Inappropriate use of <I>virt-specifier</I></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1984">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1984">1984</a></td>
@@ -11877,11 +11877,11 @@
<td><I>exception-specification</I>s and conversion operators</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2011">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2011">2011</a></td>
- <td>drafting</td>
+ <tr id="2011">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2011">2011</a></td>
+ <td>C++17</td>
<td>Unclear effect of reference capture of reference</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2012">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2012">2012</a></td>
@@ -12087,11 +12087,11 @@
<td>“Identical” template parameter lists</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2046">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2046">2046</a></td>
- <td>concurrency</td>
+ <tr id="2046">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2046">2046</a></td>
+ <td>C++17</td>
<td>Incomplete thread specifications</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2047">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2047">2047</a></td>
@@ -12165,11 +12165,11 @@
<td>More errors from internal-linkage namespaces</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2059">
+ <tr id="2059">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2059">2059</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Linkage and deduced return types</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2060">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2060">2060</a></td>
@@ -12297,11 +12297,11 @@
<td>Example with empty anonymous union member</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2081">
+ <tr id="2081">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2081">2081</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Deduced return type in redeclaration or specialization of function template</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2082">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2082">2082</a></td>
@@ -12339,11 +12339,11 @@
<td>Left shift of negative value by zero bits</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2088">
+ <tr id="2088">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2088">2088</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Late tiebreakers in partial ordering</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2089">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2089">2089</a></td>
@@ -12363,11 +12363,11 @@
<td>Deducing reference non-type template arguments</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2092">
+ <tr id="2092">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2092">2092</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Deduction failure and overload resolution</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2093">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2093">2093</a></td>
@@ -12377,7 +12377,7 @@
</tr>
<tr id="2094">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2094">2094</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Trivial copy/move constructor for class with volatile member</td>
<td class="full" align="center">Clang 5</td>
</tr>
@@ -12413,7 +12413,7 @@
</tr>
<tr id="2100">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2100">2100</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Value-dependent address of static data member of class template</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12671,7 +12671,7 @@
</tr>
<tr id="2143">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2143">2143</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Value-dependency via injected-class-name</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12743,7 +12743,7 @@
</tr>
<tr id="2155">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2155">2155</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Defining classes and enumerations via <I>using-declaration</I>s</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12765,11 +12765,11 @@
<td>Polymorphic behavior during destruction</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2159">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2159">2159</a></td>
- <td>concurrency</td>
+ <tr id="2159">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2159">2159</a></td>
+ <td>NAD</td>
<td>Lambda capture and local <TT>thread_local</TT> variables</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2160">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2160">2160</a></td>
@@ -12795,11 +12795,11 @@
<td>Labels in <TT>constexpr</TT> functions</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2164">
+ <tr id="2164">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2164">2164</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Name hiding and <I>using-directive</I>s</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2165">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2165">2165</a></td>
@@ -12856,8 +12856,8 @@
<td align="center">Not resolved</td>
</tr>
<tr id="2174">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2174">2174</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2174">2174</a></td>
+ <td>C++17</td>
<td>Unclear rules for friend definitions in templates</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12873,11 +12873,11 @@
<td>Destroying the returned object when a destructor throws</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2177">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2177">2177</a></td>
- <td>drafting</td>
+ <tr id="2177">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2177">2177</a></td>
+ <td>DR</td>
<td>Placement <TT>operator delete</TT> and parameter copies</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2178">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2178">2178</a></td>
@@ -12909,11 +12909,11 @@
<td>Pointer arithmetic in array-like containers</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2183">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2183">2183</a></td>
- <td>review</td>
+ <tr id="2183">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2183">2183</a></td>
+ <td>NAD</td>
<td>Problems in description of potential exceptions</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2184">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2184">2184</a></td>
@@ -12958,8 +12958,8 @@
<td align="center">Not resolved</td>
</tr>
<tr id="2191">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2191">2191</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2191">2191</a></td>
+ <td>C++17</td>
<td>Incorrect result for <TT>noexcept(typeid(v))</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12969,57 +12969,57 @@
<td>Constant expressions and order-of-eval undefined behavior</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2193">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2193">2193</a></td>
- <td>open</td>
+ <tr id="2193">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2193">2193</a></td>
+ <td>NAD</td>
<td><TT>numeric_limits<int>::radix</TT> and <TT>digits</TT></td>
- <td align="center">Not resolved</td>
- </tr>
- <tr id="2194">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2194">2194</a></td>
- <td>tentatively ready</td>
- <td>Impossible case in list initialization</td>
<td class="none" align="center">Unknown</td>
</tr>
+ <tr class="open" id="2194">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2194">2194</a></td>
+ <td>review</td>
+ <td>Impossible case in list initialization</td>
+ <td align="center">Not resolved</td>
+ </tr>
<tr class="open" id="2195">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2195">2195</a></td>
<td>open</td>
<td>Unsolicited reading of trailing volatile members</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2196">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2196">2196</a></td>
- <td>open</td>
+ <tr id="2196">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2196">2196</a></td>
+ <td>C++17</td>
<td>Zero-initialization with virtual base classes</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2197">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2197">2197</a></td>
- <td>open</td>
+ <td>review</td>
<td>Overload resolution and deleted special member functions</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2198">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2198">2198</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2198">2198</a></td>
+ <td>C++17</td>
<td>Linkage of enumerators</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2199">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2199">2199</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Typedefs and tags</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2200">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2200">2200</a></td>
- <td>open</td>
+ <tr id="2200">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2200">2200</a></td>
+ <td>NAD</td>
<td>Conversions in template argument deduction</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2201">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2201">2201</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2201">2201</a></td>
+ <td>C++17</td>
<td>Cv-qualification of array types</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -13031,31 +13031,31 @@
</tr>
<tr class="open" id="2203">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2203">2203</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Defaulted copy/move constructors and UDCs</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2204">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2204">2204</a></td>
- <td>open</td>
+ <tr id="2204">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2204">2204</a></td>
+ <td>NAD</td>
<td>Naming delegated constructors</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2205">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2205">2205</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2205">2205</a></td>
+ <td>C++17</td>
<td>Restrictions on use of <TT>alignas</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2206">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2206">2206</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2206">2206</a></td>
+ <td>C++17</td>
<td>Composite type of object and function pointers</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2207">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2207">2207</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Alignment of allocation function return value</td>
<td align="center">Not resolved</td>
</tr>
@@ -13077,11 +13077,11 @@
<td>Principal/target constructor confusion</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2211">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2211">2211</a></td>
- <td>open</td>
+ <tr id="2211">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2211">2211</a></td>
+ <td>C++17</td>
<td>Hiding by lambda captures and parameters</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2212">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2212">2212</a></td>
@@ -13091,37 +13091,37 @@
</tr>
<tr class="open" id="2213">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2213">2213</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Forward declaration of partial specializations</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2214">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2214">2214</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2214">2214</a></td>
+ <td>C++17</td>
<td>Missing requirement on representation of integer values</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2215">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2215">2215</a></td>
- <td>open</td>
+ <td>review</td>
<td>Redundant description of language linkage in function call</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2216">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2216">2216</a></td>
- <td>open</td>
+ <tr id="2216">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2216">2216</a></td>
+ <td>NAD</td>
<td>Exception specifications in unevaluated contexts</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2217">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2217">2217</a></td>
- <td>open</td>
+ <tr id="2217">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2217">2217</a></td>
+ <td>NAD</td>
<td><TT>constexpr</TT> constructors for non-literal types</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2218">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2218">2218</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2218">2218</a></td>
+ <td>C++17</td>
<td>Ambiguity and namespace aliases</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -13132,76 +13132,76 @@
<td align="center">Not resolved</td>
</tr>
<tr id="2220">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2220">2220</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2220">2220</a></td>
+ <td>C++17</td>
<td>Hiding index variable in range-based <TT>for</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2221">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2221">2221</a></td>
- <td>open</td>
+ <td>review</td>
<td>Copying volatile objects</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2222">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2222">2222</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Additional contexts where instantiation is not required</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2223">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2223">2223</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Multiple <TT>alignas</TT> specifiers</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2224">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2224">2224</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2224">2224</a></td>
+ <td>C++17</td>
<td>Member subobjects and base-class casts</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2225">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2225">2225</a></td>
- <td>open</td>
+ <tr id="2225">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2225">2225</a></td>
+ <td>NAD</td>
<td><TT>reinterpret_cast</TT> to same floating-point type</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2226">
+ <tr id="2226">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2226">2226</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Xvalues vs lvalues in conditional expressions</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2227">
+ <tr id="2227">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2227">2227</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Destructor access and default member initializers</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2228">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2228">2228</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Ambiguity resolution for cast to function type</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2229">
+ <tr id="2229">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2229">2229</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Volatile unnamed bit-fields</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2230">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2230">2230</a></td>
- <td>open</td>
+ <tr id="2230">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2230">2230</a></td>
+ <td>NAD</td>
<td>Linkage of <TT>extern "C"</TT> function in unnamed namespace</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2231">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2231">2231</a></td>
- <td>open</td>
+ <tr id="2231">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2231">2231</a></td>
+ <td>NAD</td>
<td>Class member access to static data member template</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2232">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2232">2232</a></td>
@@ -13209,47 +13209,47 @@
<td><TT>thread_local</TT> anonymous unions</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2233">
+ <tr id="2233">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2233">2233</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Function parameter packs following default arguments</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2234">
+ <tr id="2234">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2234">2234</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Missing rules for <I>simple-template-id</I> as <I>class-name</I></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2235">
+ <tr id="2235">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2235">2235</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Partial ordering and non-dependent types</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2236">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2236">2236</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>When is an alias template specialization dependent?</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2237">
+ <tr id="2237">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2237">2237</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Can a <I>template-id</I> name a constructor?</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2238">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2238">2238</a></td>
- <td>open</td>
+ <tr id="2238">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2238">2238</a></td>
+ <td>NAD</td>
<td>Contradictory alignment requirements for allocation</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2239">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2239">2239</a></td>
- <td>open</td>
+ <tr id="2239">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2239">2239</a></td>
+ <td>NAD</td>
<td>Sized deallocation with a trivial destructor</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2240">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2240">2240</a></td>
@@ -13271,7 +13271,7 @@
</tr>
<tr class="open" id="2243">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2243">2243</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Incorrect use of implicit conversion sequence</td>
<td align="center">Not resolved</td>
</tr>
@@ -13293,23 +13293,23 @@
<td>Access of indirect virtual base class constructors</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2247">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2247">2247</a></td>
- <td>open</td>
+ <tr id="2247">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2247">2247</a></td>
+ <td>C++17</td>
<td>Lambda capture and variable argument list</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2248">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2248">2248</a></td>
- <td>review</td>
+ <tr id="2248">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2248">2248</a></td>
+ <td>C++17</td>
<td>Problems with sized delete</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2249">
+ <tr id="2249">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2249">2249</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td><I>identifier</I>s and <I>id-expression</I>s</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2250">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2250">2250</a></td>
@@ -13317,11 +13317,11 @@
<td>Implicit instantiation, destruction, and TUs</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2251">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2251">2251</a></td>
- <td>review</td>
+ <tr id="2251">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2251">2251</a></td>
+ <td>C++17</td>
<td>Unreachable enumeration list-initialization</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2252">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2252">2252</a></td>
@@ -13329,23 +13329,23 @@
<td>Enumeration list-initialization from the same type</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2253">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2253">2253</a></td>
- <td>open</td>
+ <tr id="2253">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2253">2253</a></td>
+ <td>DRWP</td>
<td>Unnamed bit-fields and zero-initialization</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2254">
+ <tr id="2254">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2254">2254</a></td>
- <td>open</td>
- <td>Standard-layout classes and unnamed bit-fields</td>
- <td align="center">Not resolved</td>
+ <td>tentatively ready</td>
+ <td>Standard-layout classes and bit-fields</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2255">
+ <tr id="2255">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2255">2255</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Instantiated static data member templates</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2256">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2256">2256</a></td>
@@ -13366,16 +13366,16 @@
<td align="center">Not resolved</td>
</tr>
<tr id="2259">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2259">2259</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2259">2259</a></td>
+ <td>C++17</td>
<td>Unclear context describing ambiguity</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2260">
+ <tr id="2260">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2260">2260</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Explicit specializations of deleted member functions</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2261">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2261">2261</a></td>
@@ -13384,8 +13384,8 @@
<td align="center">Not resolved</td>
</tr>
<tr id="2262">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2262">2262</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2262">2262</a></td>
+ <td>C++17</td>
<td>Attributes for <I>asm-definition</I></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -13419,66 +13419,540 @@
<td>Copy-initialization of temporary in reference direct-initialization</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2268">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2268">2268</a></td>
- <td>open</td>
+ <tr id="2268">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2268">2268</a></td>
+ <td>C++17</td>
<td>Unions with mutable members in constant expressions revisited</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2269">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2269">2269</a></td>
- <td>open</td>
+ <tr id="2269">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2269">2269</a></td>
+ <td>dup</td>
<td>Additional recursive references in aggregate DMIs</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2270">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2270">2270</a></td>
- <td>open</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2270">2270</a></td>
+ <td>extension</td>
<td>Non-inline functions and explicit instantiation declarations</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2271">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2271">2271</a></td>
- <td>DR</td>
+ <td>C++17</td>
<td>Aliasing <TT>this</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2272">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2272">2272</a></td>
- <td>open</td>
+ <tr id="2272">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2272">2272</a></td>
+ <td>C++17</td>
<td>Implicit initialization of aggregate members of reference type</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2273">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2273">2273</a></td>
- <td>open</td>
+ <tr id="2273">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2273">2273</a></td>
+ <td>DRWP</td>
<td>Inheriting constructors vs implicit default constructor</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2274">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2274">2274</a></td>
- <td>open</td>
+ <tr id="2274">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2274">2274</a></td>
+ <td>NAD</td>
<td>Generic lambda capture vs constexpr if</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2275">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2275">2275</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Type-dependence of function template</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2276">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2276">2276</a></td>
- <td>open</td>
+ <tr id="2276">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2276">2276</a></td>
+ <td>C++17</td>
<td>Dependent <TT>noexcept</TT> and function type-dependence</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2277">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2277">2277</a></td>
+ <td>DRWP</td>
+ <td>Ambiguity inheriting constructors with default arguments</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2278">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2278">2278</a></td>
+ <td>open</td>
+ <td>Copy elision in constant expressions reconsidered</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2277">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2277">2277</a></td>
- <td>open</td>
- <td>Ambiguity inheriting constructors with default arguments</td>
+ <tr id="2279">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2279">2279</a></td>
+ <td>NAD</td>
+ <td>Multiple <I>attribute-specifier</I>s in one <I>attribute-list</I></td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2280">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2280">2280</a></td>
+ <td>review</td>
+ <td>Matching a usual deallocation function with placement new</td>
<td align="center">Not resolved</td>
</tr>
+ <tr class="open" id="2281">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2281">2281</a></td>
+ <td>open</td>
+ <td>Consistency of aligned <TT>operator delete</TT> replacement</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2282">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2282">2282</a></td>
+ <td>drafting</td>
+ <td>Consistency with mismatched aligned/non-over-aligned allocation/deallocation functions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2283">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2283">2283</a></td>
+ <td>drafting</td>
+ <td>Missing complete type requirements</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2284">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2284">2284</a></td>
+ <td>open</td>
+ <td>Sequencing of <I>braced-init-list</I> arguments</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2285">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2285">2285</a></td>
+ <td>tentatively ready</td>
+ <td>Issues with structured bindings</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2286">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2286">2286</a></td>
+ <td>NAD</td>
+ <td>Assignment evaluation order</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2287">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2287">2287</a></td>
+ <td>DRWP</td>
+ <td>Pointer-interconvertibility in non-standard-layout unions</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2288">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2288">2288</a></td>
+ <td>NAD</td>
+ <td>Contradictory optionality in <I>simple-declaration</I></td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2289">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2289">2289</a></td>
+ <td>drafting</td>
+ <td>Uniqueness of decomposition declaration names</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2290">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2290">2290</a></td>
+ <td>DRWP</td>
+ <td>Unclear specification for overload resolution and deleted special member functions</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2291">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2291">2291</a></td>
+ <td>dup</td>
+ <td>Implicit conversion sequences in non-call contexts</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2292">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2292">2292</a></td>
+ <td>drafting</td>
+ <td><I>simple-template-id</I> is ambiguous between <I>class-name</I> and <I>type-name</I></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2293">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2293">2293</a></td>
+ <td>drafting</td>
+ <td>Requirements for <I>simple-template-id</I> used as a <I>class-name</I></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2294">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2294">2294</a></td>
+ <td>drafting</td>
+ <td>Dependent <TT>auto</TT> static data members</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2295">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2295">2295</a></td>
+ <td>extension</td>
+ <td>Aggregates with deleted defaulted constructors</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2296">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2296">2296</a></td>
+ <td>extension</td>
+ <td>Are default argument instantiation failures in the “immediate context”?</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2297">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2297">2297</a></td>
+ <td>review</td>
+ <td>Unclear specification of atomic operations</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2298">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2298">2298</a></td>
+ <td>concurrency</td>
+ <td>Actions and expression evaluation</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2299">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2299">2299</a></td>
+ <td>tentatively ready</td>
+ <td><TT>constexpr</TT> vararg functions</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2300">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2300">2300</a></td>
+ <td>drafting</td>
+ <td>Lambdas in multiple definitions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2301">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2301">2301</a></td>
+ <td>open</td>
+ <td>Value-initialization and constexpr constructor evaluation</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2302">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2302">2302</a></td>
+ <td>NAD</td>
+ <td>Address comparison between different member subobjects</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2303">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2303">2303</a></td>
+ <td>open</td>
+ <td>Partial ordering and recursive variadic inheritance</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2304">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2304">2304</a></td>
+ <td>NAD</td>
+ <td>Incomplete type vs overload resolution</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2305">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2305">2305</a></td>
+ <td>DR</td>
+ <td>Explicit instantiation of constexpr or inline variable template</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2306">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2306">2306</a></td>
+ <td>open</td>
+ <td>Nested friend templates of class templates</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2307">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2307">2307</a></td>
+ <td>DR</td>
+ <td>Unclear definition of “equivalent to a nontype template parameter”</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2308">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2308">2308</a></td>
+ <td>open</td>
+ <td>Structured bindings and lambda capture</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2309">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2309">2309</a></td>
+ <td>drafting</td>
+ <td>Restrictions on nested statements within <TT>constexpr</TT> functions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2310">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2310">2310</a></td>
+ <td>open</td>
+ <td>Type completeness and derived-to-base pointer conversions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2311">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2311">2311</a></td>
+ <td>open</td>
+ <td>Missed case for guaranteed copy elision</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2312">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2312">2312</a></td>
+ <td>drafting</td>
+ <td>Structured bindings and <TT>mutable</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2313">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2313">2313</a></td>
+ <td>DR</td>
+ <td>Redeclaration of structured binding reference variables</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2314">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2314">2314</a></td>
+ <td>dup</td>
+ <td>Structured bindings and lambda capture</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2315">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2315">2315</a></td>
+ <td>DR</td>
+ <td>What is the “corresponding special member” of a variant member?</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2316">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2316">2316</a></td>
+ <td>drafting</td>
+ <td>Simplifying class conversions in conditional expressions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2317">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2317">2317</a></td>
+ <td>open</td>
+ <td>Self-referential default member initializers</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2318">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2318">2318</a></td>
+ <td>drafting</td>
+ <td>Nondeduced contexts in deduction from a <I>braced-init-list</I></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2319">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2319">2319</a></td>
+ <td>drafting</td>
+ <td>Nested brace initialization from same type</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2320">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2320">2320</a></td>
+ <td>extension</td>
+ <td><TT>constexpr if</TT> and boolean conversions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2321">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2321">2321</a></td>
+ <td>drafting</td>
+ <td>Conditional operator and cv-qualified class prvalues</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2322">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2322">2322</a></td>
+ <td>drafting</td>
+ <td>Substitution failure and lexical order</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2323">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2323">2323</a></td>
+ <td>drafting</td>
+ <td>Expunge POD</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2324">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2324">2324</a></td>
+ <td>drafting</td>
+ <td>Size of base class subobject</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2325">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2325">2325</a></td>
+ <td>drafting</td>
+ <td><TT>std::launder</TT> and reuse of character buffers</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2326">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2326">2326</a></td>
+ <td>dup</td>
+ <td>Type deduction with initializer list containing ambiguous functions</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2327">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2327">2327</a></td>
+ <td>drafting</td>
+ <td>Copy elision for direct-initialization with a conversion function</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2328">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2328">2328</a></td>
+ <td>open</td>
+ <td>Unclear presentation style of template argument deduction rules</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2329">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2329">2329</a></td>
+ <td>drafting</td>
+ <td>Virtual base classes and generated assignment operators</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2330">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2330">2330</a></td>
+ <td>drafting</td>
+ <td>Missing references to variable templates</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2331">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2331">2331</a></td>
+ <td>drafting</td>
+ <td>Redundancy in description of class scope</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2332">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2332">2332</a></td>
+ <td>drafting</td>
+ <td><I>template-name</I> as <I>simple-type-name</I> vs injected-class-name</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2333">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2333">2333</a></td>
+ <td>drafting</td>
+ <td>Escape sequences in UTF-8 character literals</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2334">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2334">2334</a></td>
+ <td>open</td>
+ <td>Creation of objects by <TT>typeid</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2335">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2335">2335</a></td>
+ <td>open</td>
+ <td>Deduced return types vs member types</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2336">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2336">2336</a></td>
+ <td>drafting</td>
+ <td>Destructor characteristics vs potentially-constructed subobjects</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2337">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2337">2337</a></td>
+ <td>open</td>
+ <td>Incorrect implication of logic ladder for conversion sequence tiebreakers</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2338">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2338">2338</a></td>
+ <td>DR</td>
+ <td>Undefined behavior converting to short enums with fixed underlying types</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2339">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2339">2339</a></td>
+ <td>drafting</td>
+ <td>Underspecified template arguments in structured bindings</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2340">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2340">2340</a></td>
+ <td>open</td>
+ <td>Reference collapsing and structured bindings</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2341">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2341">2341</a></td>
+ <td>extension</td>
+ <td>Structured bindings with static storage duration</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2342">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2342">2342</a></td>
+ <td>DR</td>
+ <td>Reference <TT>reinterpret_cast</TT> and pointer-interconvertibility</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2343">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2343">2343</a></td>
+ <td>open</td>
+ <td><TT>void*</TT> non-type template parameters</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2344">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2344">2344</a></td>
+ <td>open</td>
+ <td>Redeclaration of names in <I>init-statement</I>s</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2345">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2345">2345</a></td>
+ <td>open</td>
+ <td>Jumping across initializers in <I>init-statement</I>s and <I>condition</I>s</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2346">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2346">2346</a></td>
+ <td>open</td>
+ <td>Local variables in default arguments</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2347">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2347">2347</a></td>
+ <td>open</td>
+ <td>Passing short scoped enumerations to ellipsis</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2348">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2348">2348</a></td>
+ <td>open</td>
+ <td>Non-templated <TT>constexpr if</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2349">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2349">2349</a></td>
+ <td>open</td>
+ <td>Class/enumeration names vs conditions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2350">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2350">2350</a></td>
+ <td>open</td>
+ <td>Forwarding references and deduction guides</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2351">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2351">2351</a></td>
+ <td>open</td>
+ <td><TT>void{}</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2352">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2352">2352</a></td>
+ <td>open</td>
+ <td>Similar types and reference binding</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2353">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2353">2353</a></td>
+ <td>open</td>
+ <td>Potential results of a member access expression for a static data member</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2354">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2354">2354</a></td>
+ <td>open</td>
+ <td>Extended alignment and object representation</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2355">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2355">2355</a></td>
+ <td>open</td>
+ <td>Deducing <I>noexcept-specifier</I>s</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2356">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2356">2356</a></td>
+ <td>tentatively ready</td>
+ <td>Base class copy and move constructors should not be inherited</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
</table>
</div>
diff --git a/www/cxx_status.html b/www/cxx_status.html
index 10a4cda..8861638 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -56,7 +56,7 @@
<h2 id="cxx11">C++11 implementation status</h2>
<p>Clang 3.3 and later implement all of the <a
- href="http://www.iso.org/iso/catalogue_detail.htm?csnumber=50372">ISO
+ href="http://www.iso.org/standard/50372.html">ISO
C++ 2011 standard</a>.
<p>By default, Clang builds C++ code according to the C++98 standard, with many
@@ -134,10 +134,15 @@
<td class="full" align="center">Clang 2.9</td>
</tr>
<tr>
- <td>Lambda expressions</td>
+ <td rowspan="2">Lambda expressions</td>
<td><a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2927.pdf">N2927</a></td>
<td class="full" align="center">Clang 3.1</td>
</tr>
+ <tr>
+ <!-- from Albuquerque 2017 -->
+ <td><a href="http://wg21.link/p0588r1">P0588R1</a> (<a href="#dr">DR</a>)</td>
+ <td class="none" align="center">No</td>
+ </tr>
<tr>
<td>Declared type of an expression</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf">N2343</a></td>
@@ -195,10 +200,15 @@
<td class="full" align="center">Clang 3.3 <a href="#n2761">(1)</a></td>
</tr>
<tr>
- <td>Generalized constant expressions</td>
+ <td rowspan="2">Generalized constant expressions</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf">N2235</a></td>
<td class="full" align="center">Clang 3.1</td>
</tr>
+ <tr>
+ <!-- from Albuquerque 2017 -->
+ <td><a href="http://wg21.link/p0859r0">P0859R0</a> (<a href="#dr">DR</a>)</td>
+ <td class="none" align="center">No</td>
+ </tr>
<tr>
<td>Alignment support</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf">N2341</a></td>
@@ -220,10 +230,15 @@
<td class="full" align="center">Clang 3.0</td>
</tr>
<tr>
- <td>Inheriting constructors</td>
+ <td rowspan="2">Inheriting constructors</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm">N2540</a></td>
<td class="full" align="center">Clang 3.3</td>
</tr>
+ <tr>
+ <!-- from Kona 2015 -->
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html">P0136R1</a> (<a href="#dr">DR</a>)</td>
+ <td class="full" align="center">Clang 3.9</td>
+ </tr>
<tr>
<td>Explicit conversion operators</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf">N2437</a></td>
@@ -296,10 +311,15 @@
<td class="full" align="center">Clang 2.9</td>
</tr>
<tr>
- <td>Range-based for</td>
+ <td rowspan="2">Range-based for</td>
<td><a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2930.html">N2930</a></td>
<td class="full" align="center">Clang 3.0</td>
</tr>
+ <tr>
+ <!-- from Jacksonville 2018 -->
+ <td><a href="http://wg21.link/p0962r1">P0962R1</a> (<a href="#dr">DR</a>)</td>
+ <td class="none" align="center">No</td>
+ </tr>
<tr>
<td>Explicit virtual overrides</td>
<td><a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm">N2928</a>
@@ -427,7 +447,7 @@
<h2 id="cxx14">C++14 implementation status</h2>
<p>Clang 3.4 and later implement all of the <a
- href="http://www.iso.org/iso/catalogue_detail.htm?csnumber=64029">ISO
+ href="http://www.iso.org/standard/64029.html">ISO
C++ 2014 standard</a>.
<p>You can use Clang in C++14 mode with the <code>-std=c++14</code> option
@@ -521,8 +541,8 @@
<h2 id="cxx17">C++17 implementation status</h2>
-<p>Clang 5 and later implement all the features
-of the C++ 2017 Draft International Standard.
+<p>Clang 5 and later implement all the features of the
+<a href="https://www.iso.org/standard/68564.html">ISO C++ 2017 standard</a>.
<p>You can use Clang in C++17 mode with the <code>-std=c++17</code> option
(use <code>-std=c++1z</code> in Clang 4 and earlier).</p>
@@ -619,11 +639,6 @@
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0061.html">P0061R1</a></td>
<td class="full" align="center">Yes</td>
</tr>
- <tr>
- <td>New specification for inheriting constructors (<a href="cxx_dr_status.html#1941">DR1941</a> et al)</td>
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html">P0136R1</a></td>
- <td class="full" align="center">Clang 3.9 <a href="#p0136">(9)</a></td>
- </tr>
<!-- Jacksonville papers -->
<tr>
<td><tt>[[fallthrough]]</tt> attribute</td>
@@ -682,13 +697,18 @@
<td class="full" align="center">Clang 4</td>
</tr>
<tr>
- <td rowspan="2">Template argument deduction for class templates</td>
+ <td rowspan="3">Template argument deduction for class templates</td>
<td><a href="http://wg21.link/p0091r3">P0091R3</a></td>
<td rowspan="2" class="full" align="center">Clang 5</td>
</tr>
<tr> <!-- from Issaquah -->
<td><a href="http://wg21.link/p0512r0">P0512R0</a></td>
</tr>
+ <tr>
+ <!-- from Toronto 2017 -->
+ <td><a href="http://wg21.link/p0702r1">P0702R1</a> (<a href="#dr">DR</a>)</td>
+ <td class="svn" align="center">Clang 6</td>
+ </tr>
<tr>
<td>Non-type template parameters with <tt>auto</tt> type</td>
<td><a href="http://wg21.link/p0127r2">P0127R2</a></td>
@@ -702,7 +722,7 @@
<tr>
<td rowspan=2>Stricter expression evaluation order</td>
<td><a href="http://wg21.link/p0145r3">P0145R3</a></td>
- <td class="full" align="center" rowspan=2>Clang 4 <a href="#p0145">(10)</a></td>
+ <td class="full" align="center" rowspan=2>Clang 4 <a href="#p0145">(9)</a></td>
</tr>
<tr>
<td><a href="http://wg21.link/p0400r0">P0400R0</a></td>
@@ -723,10 +743,20 @@
<td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
- <td>Structured bindings</td>
+ <td rowspan="3">Structured bindings</td>
<td><a href="http://wg21.link/p0217r3">P0217R3</a></td>
<td class="full" align="center">Clang 4</td>
</tr>
+ <tr>
+ <!-- from Jacksonville 2018 -->
+ <td><a href="http://wg21.link/p0961r1">P0961R1</a> (<a href="#dr">DR</a>)</td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <!-- from Jacksonville 2018 -->
+ <td><a href="http://wg21.link/p0969r0">P0969R0</a> (<a href="#dr">DR</a>)</td>
+ <td class="none" align="center">No</td>
+ </tr>
<tr>
<td>Separate variable and condition for <tt>if</tt> and <tt>switch</tt></td>
<td><a href="http://wg21.link/p0305r1">P0305R1</a></td>
@@ -736,7 +766,7 @@
<tr>
<td>Matching template template parameters to compatible arguments</td>
<td><a href="http://wg21.link/p0522r0">P0522R0</a></td>
- <td class="partial" align="center">Partial <a href="#p0522">(12)</a></td>
+ <td class="partial" align="center">Partial <a href="#p0522">(10)</a></td>
</tr>
<tr>
<td>Removing deprecated dynamic exception specifications</td>
@@ -756,17 +786,14 @@
(per the request of the C++ committee).
In Clang 3.7, a warning is emitted for all cases that would change meaning.
</span><br>
-<span id="p0136">(9): This is the resolution to a Defect Report, so is applied
-to all language versions supporting inheriting constructors.
-</span><br>
-<span id="p0145">(10): Under the MS ABI, function parameters are destroyed from
+<span id="p0145">(9): Under the MS ABI, function parameters are destroyed from
left to right in the callee. As a result, function parameters in calls to
<tt>operator<<</tt>, <tt>operator>></tt>, <tt>operator->*</tt>,
<tt>operator&&</tt>, <tt>operator||</tt>, and <tt>operator,</tt>
functions using expression syntax are no longer guaranteed to be destroyed in
reverse construction order in that ABI.
</span><br>
-<span id="p0522">(12): Despite being the resolution to a Defect Report, this
+<span id="p0522">(10): Despite being the resolution to a Defect Report, this
feature is disabled by default in all language versions, and can be enabled
explicitly with the flag <tt>-frelaxed-template-template-args</tt> in Clang 4
onwards.
@@ -826,11 +853,6 @@
<td><a href="http://wg21.link/p0428r2">P0428R2</a></td>
<td class="none" align="center">No</td>
</tr>
- <tr>
- <td>Initializer list constructors in class template argument deduction</td>
- <td><a href="http://wg21.link/p0702r1">P0702R1</a></td>
- <td class="svn" align="center">Clang 6 <a href="#p0702">(13)</a></td>
- </tr>
<tr id="p0734">
<td rowspan="2">Concepts</td>
<td><a href="http://wg21.link/p0734r0">P0734R0</a></td>
@@ -846,11 +868,6 @@
<td class="none" align="center">No</td>
</tr>
<tr>
- <td>Simplifying implicit lambda capture</td>
- <td><a href="http://wg21.link/p0588r1">P0588R1</a></td>
- <td class="none" align="center">No <a href="#p0588">(14)</a></td>
- </tr>
- <tr>
<td>ADL and function templates that are not visible</td>
<td><a href="http://wg21.link/p0846r0">P0846R0</a></td>
<td class="none" align="center">No</td>
@@ -861,15 +878,13 @@
<td class="none" align="center">No</td>
</tr>
<tr>
- <td>Less eager instantiation of <tt>constexpr</tt> functions</td>
- <td><a href="http://wg21.link/p0859r0">P0859R0</a></td>
- <td class="none" align="center">No <a href="#p0859">(15)</a></td>
- </tr>
- <tr>
- <td>Consistent comparison (<tt>operator<=></tt>)</td>
+ <td rowspan="2">Consistent comparison (<tt>operator<=></tt>)</td>
<td><a href="http://wg21.link/p0515r3">P0515R3</a></td>
- <td class="none" align="center">No</td>
+ <td rowspan="2" class="none" align="center">No</td>
</tr>
+ <tr> <!-- from Jacksonville -->
+ <td><a href="http://wg21.link/p0905r1">P0905R1</a></td>
+ </tr>
<tr>
<td>Access checking on specializations</td>
<td><a href="http://wg21.link/p0692r1">P0692R1</a></td>
@@ -885,20 +900,43 @@
<td><a href="http://wg21.link/p0315r4">P0315R4</a></td>
<td class="none" align="center">No</td>
</tr>
+ <!-- Jacksonville papers -->
+ <tr>
+ <td><tt>[[no_unique_address]]</tt> attribute</td>
+ <td><a href="http://wg21.link/p0840r2">P0840R2</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td><tt>[[likely]]</tt> and <tt>[[unlikely]]</tt> attributes</td>
+ <td><a href="http://wg21.link/p0479r5">P0479R5</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td><tt>typename</tt> optional in more contexts</td>
+ <td><a href="http://wg21.link/p0634r3">P0634R3</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td>Pack expansion in lambda <i>init-capture</i></td>
+ <td><a href="http://wg21.link/p0780r2">P0780R2</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
</table>
</details>
-<p>
-<span id="p0702">(13): This is the resolution to a Defect Report, so is applied
-to all language versions supporting class template argument deduction.
-</span><br>
-<span id="p0588">(14): This is the resolution to a Defect Report, so will be applied
-to all language versions supporting lamba expressions.
-</span><br>
-<span id="p0859">(15): This is the resolution to a Defect Report, so will be applied
-to all language versions supporting <tt>constexpr</tt>.
-</span>
-</p>
+<h2 id="dr">Defect reports</h2>
+
+<p>Clang generally aims to implement resolutions to Defect Reports (bug fixes
+against prior standards) retroactively, in all prior standard versions where
+the fix is meaningful. Significant Defect Report changes to language features
+after the publication of the relevant standard are marked (DR) in the above
+table.</p>
+
+<p>Clang also has a test suite for conformance to resolutions for issues on the
+<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_toc.html">C++ core issues list</a>,
+most of which are considered Defect Reports.
+<a href="cxx_dr_status.html">Implementation status for C++ core issues</a> based on
+that test suite is tracked on a separate page.</p>
<h2 id="ts">Technical specifications and standing documents</h2>
@@ -959,6 +997,7 @@
<td class="na" align="center">Superseded by <a href="#p0734">P0734R0</a></td>
</tr>
<tr>
+ <!-- track unimplemented Coroutines features: p0913r1 p0914r1 -->
<td>[DRAFT TS] Coroutines</td>
<td><a href="https://isocpp.org/files/papers/N4663.pdf">N4663</a></td>
<td><tt>-fcoroutines-ts<br>-stdlib=libc++</tt></td>
@@ -983,6 +1022,12 @@
<td class="none" align="center">WIP</td>
</tr>
<tr>
+ <td>[DRAFT TS] Reflection</td>
+ <td><a href="http://wg21.link/p0194r6">P0194R6</a></td>
+ <td></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
<td>[TS] Transactional Memory</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4514.pdf">N4514</a></td>
<td></td>
diff --git a/www/hacking.html b/www/hacking.html
index 96eb7f6..f2f98f4 100644
--- a/www/hacking.html
+++ b/www/hacking.html
@@ -180,7 +180,7 @@
<p>Note that the test runner is based on
Python, which must be installed. Find Python at:
<a href="http://www.python.org/download/">http://www.python.org/download/</a>.
- Download the latest stable version (2.6.2 at the time of this writing).</p>
+ Download the latest stable version.</p>
<p>The GnuWin32 tools are also necessary for running the tests.
Get them from <a href="http://getgnuwin32.sourceforge.net/">
diff --git a/www/make_cxx_dr_status b/www/make_cxx_dr_status
index 164ae99..3b0e09d 100755
--- a/www/make_cxx_dr_status
+++ b/www/make_cxx_dr_status
@@ -111,9 +111,6 @@
elif status == '7':
avail = 'SVN'
avail_style = ' class="svn"'
- elif status == '6':
- avail = 'Clang 6'
- avail_style = ' class="svn"'
elif re.match('^[0-9]+\.?[0-9]*', status):
avail = 'Clang %s' % status
avail_style = ' class="full"'