aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-24 01:00:23 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-24 01:00:23 +0000
commit6252156da5066bd47f63f8bd40404d1f89909d32 (patch)
tree743d1b59945b071890dc19b6bf5e9d3ff0d1399b
parent461a67fa15370a9ec88f8f8a240bf7c123bb2029 (diff)
downloadsrc-vendor/clang/clang-trunk-r321414.tar.gz
src-vendor/clang/clang-trunk-r321414.zip
Vendor import of clang trunk r321414:vendor/clang/clang-trunk-r321414
-rw-r--r--cmake/caches/Fuchsia-stage2.cmake1
-rw-r--r--cmake/caches/Fuchsia.cmake1
-rw-r--r--docs/HardwareAssistedAddressSanitizerDesign.rst34
-rw-r--r--docs/Modules.rst29
-rw-r--r--docs/UndefinedBehaviorSanitizer.rst4
-rw-r--r--include/clang/AST/Decl.h14
-rw-r--r--include/clang/AST/ODRHash.h4
-rw-r--r--include/clang/AST/Type.h14
-rw-r--r--include/clang/Basic/Attr.td30
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td5
-rw-r--r--include/clang/Basic/DiagnosticIDs.h2
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td12
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--include/clang/Basic/DiagnosticSerializationKinds.td23
-rw-r--r--include/clang/Basic/arm_neon.td185
-rw-r--r--include/clang/Frontend/PrecompiledPreamble.h11
-rw-r--r--include/clang/Index/IndexSymbol.h10
-rw-r--r--include/clang/Parse/Parser.h8
-rw-r--r--include/clang/Sema/Sema.h6
-rw-r--r--include/clang/Serialization/ASTReader.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h2
-rw-r--r--lib/AST/ASTDumper.cpp48
-rw-r--r--lib/AST/ASTImporter.cpp126
-rw-r--r--lib/AST/Decl.cpp25
-rw-r--r--lib/AST/Expr.cpp3
-rw-r--r--lib/AST/ExprCXX.cpp4
-rw-r--r--lib/AST/ExprConstant.cpp16
-rw-r--r--lib/AST/ItaniumMangle.cpp2
-rw-r--r--lib/AST/ODRHash.cpp34
-rw-r--r--lib/AST/TypeLoc.cpp2
-rw-r--r--lib/AST/TypePrinter.cpp12
-rw-r--r--lib/Basic/Diagnostic.cpp2
-rw-r--r--lib/Basic/DiagnosticIDs.cpp2
-rw-r--r--lib/Basic/SourceManager.cpp7
-rw-r--r--lib/Basic/Targets/AArch64.cpp3
-rw-r--r--lib/Basic/Targets/X86.cpp12
-rw-r--r--lib/CodeGen/BackendUtil.cpp6
-rw-r--r--lib/CodeGen/CGAtomic.cpp26
-rw-r--r--lib/CodeGen/CGBuiltin.cpp261
-rw-r--r--lib/CodeGen/CGCall.cpp23
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp1
-rw-r--r--lib/CodeGen/CGException.cpp2
-rw-r--r--lib/CodeGen/CGExpr.cpp17
-rw-r--r--lib/CodeGen/CGExprAgg.cpp2
-rw-r--r--lib/CodeGen/CGExprCXX.cpp7
-rw-r--r--lib/CodeGen/CGExprComplex.cpp37
-rw-r--r--lib/CodeGen/CodeGenFunction.h25
-rw-r--r--lib/CodeGen/CodeGenModule.cpp7
-rw-r--r--lib/CodeGen/CodeGenTBAA.cpp21
-rw-r--r--lib/CodeGen/CodeGenTypeCache.h2
-rw-r--r--lib/Driver/SanitizerArgs.cpp3
-rw-r--r--lib/Driver/ToolChains/Clang.cpp1
-rw-r--r--lib/Driver/ToolChains/CommonArgs.cpp6
-rw-r--r--lib/Driver/ToolChains/Darwin.cpp154
-rw-r--r--lib/Driver/ToolChains/Fuchsia.cpp1
-rw-r--r--lib/Driver/ToolChains/Myriad.cpp9
-rw-r--r--lib/Frontend/CompilerInstance.cpp38
-rw-r--r--lib/Frontend/PrecompiledPreamble.cpp29
-rw-r--r--lib/Headers/__clang_cuda_intrinsics.h77
-rw-r--r--lib/Headers/cpuid.h19
-rw-r--r--lib/Headers/xmmintrin.h11
-rw-r--r--lib/Index/IndexSymbol.cpp65
-rw-r--r--lib/Lex/HeaderSearch.cpp13
-rw-r--r--lib/Lex/ModuleMap.cpp98
-rw-r--r--lib/Lex/Preprocessor.cpp7
-rw-r--r--lib/Parse/ParseTemplate.cpp14
-rw-r--r--lib/Rewrite/HTMLRewrite.cpp1
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp2
-rw-r--r--lib/Sema/JumpDiagnostics.cpp2
-rw-r--r--lib/Sema/SemaChecking.cpp6
-rw-r--r--lib/Sema/SemaCodeComplete.cpp6
-rw-r--r--lib/Sema/SemaDecl.cpp8
-rw-r--r--lib/Sema/SemaDeclAttr.cpp6
-rw-r--r--lib/Sema/SemaDeclCXX.cpp4
-rw-r--r--lib/Sema/SemaExpr.cpp6
-rw-r--r--lib/Sema/SemaExprMember.cpp2
-rw-r--r--lib/Sema/SemaExprObjC.cpp1
-rw-r--r--lib/Sema/SemaInit.cpp4
-rw-r--r--lib/Sema/SemaOpenMP.cpp51
-rw-r--r--lib/Sema/SemaOverload.cpp10
-rw-r--r--lib/Sema/SemaTemplate.cpp60
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp3
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp37
-rw-r--r--lib/Sema/SemaType.cpp38
-rw-r--r--lib/Serialization/ASTReader.cpp244
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp3
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp3
-rw-r--r--lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp16
-rw-r--r--lib/StaticAnalyzer/Checkers/PaddingChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp12
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp13
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp18
-rw-r--r--lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp95
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp7
-rw-r--r--test/Analysis/arc-zero-init.m46
-rw-r--r--test/Analysis/initializer.cpp40
-rw-r--r--test/Analysis/inlining/false-positive-suppression.m7
-rw-r--r--test/Analysis/inlining/inline-defensive-checks.c51
-rw-r--r--test/Analysis/inlining/path-notes.m390
-rw-r--r--test/Analysis/nullptr.cpp5
-rw-r--r--test/Analysis/uninit-const.cpp2
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp112
-rw-r--r--test/CXX/temp/temp.param/p2.cpp31
-rw-r--r--test/CodeGen/aarch64-neon-intrinsics.c230
-rw-r--r--test/CodeGen/aarch64-neon-ldst-one.c228
-rw-r--r--test/CodeGen/aarch64-v8.2a-neon-intrinsics.c1633
-rw-r--r--test/CodeGen/complex-math.c139
-rw-r--r--test/CodeGen/tbaa-array.cpp34
-rw-r--r--test/CodeGen/tbaa.cpp83
-rw-r--r--test/CodeGen/ubsan-noreturn.c7
-rw-r--r--test/CodeGenCXX/ubsan-unreachable.cpp81
-rw-r--r--test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/crtbegin.o (renamed from test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/crtbegin.o)0
-rw-r--r--test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/crtend.o (renamed from test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/crtend.o)0
-rw-r--r--test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/crti.o (renamed from test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/crti.o)0
-rw-r--r--test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/crtn.o (renamed from test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/crtn.o)0
-rw-r--r--test/Driver/Inputs/basic_myriad_tree/sparc-myriad-rtems/include/c++/6.3.0/.keep (renamed from test/Driver/Inputs/basic_myriad_tree/sparc-myriad-elf/include/c++/4.8.2/.keep)0
-rw-r--r--test/Driver/Inputs/basic_myriad_tree/sparc-myriad-rtems/lib/crt0.o (renamed from test/Driver/Inputs/basic_myriad_tree/sparc-myriad-elf/lib/crt0.o)0
-rw-r--r--test/Driver/darwin-version.c162
-rw-r--r--test/Driver/fsanitize.c1
-rw-r--r--test/Driver/fuchsia.c17
-rw-r--r--test/Driver/myriad-toolchain.c16
-rw-r--r--test/Driver/objc-weak.m24
-rw-r--r--test/Driver/opt-record.c3
-rw-r--r--test/Driver/pic.c14
-rw-r--r--test/Driver/unavailable_aligned_allocation.cpp12
-rw-r--r--test/Frontend/float16.cpp16
-rw-r--r--test/Index/skipped-bodies-templates.cpp27
-rw-r--r--test/Misc/ast-dump-attr.cpp422
-rw-r--r--test/Misc/ast-dump-color.cpp38
-rw-r--r--test/Misc/ast-dump-decl.cpp1078
-rw-r--r--test/Misc/ast-dump-invalid.cpp2
-rw-r--r--test/Modules/Inputs/implicit-private-canonical/A.framework/Headers/a.h1
-rw-r--r--test/Modules/Inputs/implicit-private-canonical/A.framework/Headers/aprivate.h (renamed from test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/aprivate.h)0
-rw-r--r--test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.modulemap4
-rw-r--r--test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.private.modulemap4
-rw-r--r--test/Modules/Inputs/implicit-private-canonical/A.framework/PrivateHeaders/aprivate.h1
-rw-r--r--test/Modules/Inputs/implicit-private-with-different-name/A.framework/PrivateHeaders/aprivate.h1
-rw-r--r--test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/a.h1
-rw-r--r--test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/aprivate.h1
-rw-r--r--test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.modulemap4
-rw-r--r--test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap4
-rw-r--r--test/Modules/Inputs/implicit-private-with-submodule/A.framework/PrivateHeaders/aprivate.h1
-rw-r--r--test/Modules/add-remove-private.m4
-rw-r--r--test/Modules/auto-module-import.m6
-rw-r--r--test/Modules/global_index.m6
-rw-r--r--test/Modules/implicit-map-dot-private.m12
-rw-r--r--test/Modules/implicit-private-canonical.m35
-rw-r--r--test/Modules/implicit-private-with-different-name.m12
-rw-r--r--test/Modules/implicit-private-with-submodule.m36
-rw-r--r--test/Modules/modulemap-locations.m2
-rw-r--r--test/Modules/odr.cpp2
-rw-r--r--test/Modules/odr_hash.cpp160
-rw-r--r--test/Modules/prune.m10
-rw-r--r--test/Modules/redefinition-c-tagtypes.m4
-rw-r--r--test/Modules/requires-coroutines.mm4
-rw-r--r--test/Modules/requires.m2
-rw-r--r--test/Modules/requires.mm2
-rw-r--r--test/Modules/subframework-from-intermediate-path.m2
-rw-r--r--test/Modules/subframeworks.m4
-rw-r--r--test/OpenMP/dump.cpp4
-rw-r--r--test/OpenMP/parallel_for_codegen.cpp8
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp8
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp8
-rw-r--r--test/Parser/cxx-decl.cpp43
-rw-r--r--test/Parser/objc-default-ctor-init.mm42
-rw-r--r--test/Preprocessor/predefined-arch-macros.c26
-rw-r--r--test/Sema/attr-ifunc.c2
-rw-r--r--test/Sema/builtin-object-size.c19
-rw-r--r--test/SemaCXX/compound-literal.cpp196
-rw-r--r--test/SemaCXX/decl-expr-ambiguity.cpp17
-rw-r--r--test/SemaCXX/return-noreturn.cpp2
-rw-r--r--test/SemaCXX/sourceranges.cpp104
-rw-r--r--test/SemaCXX/warn-redundant-move.cpp2
-rw-r--r--test/SemaObjCXX/block-cleanup.mm32
-rw-r--r--test/SemaTemplate/default-expr-arguments-2.cpp4
-rw-r--r--test/SemaTemplate/default-expr-arguments-3.cpp22
-rw-r--r--test/SemaTemplate/nested-deduction-guides.cpp13
-rw-r--r--test/SemaTemplate/temp_arg_enum_printing.cpp4
-rw-r--r--test/SemaTemplate/temp_arg_enum_printing_more.cpp26
-rw-r--r--tools/libclang/CXIndexDataConsumer.cpp6
-rw-r--r--unittests/AST/ASTImporterTest.cpp799
-rw-r--r--unittests/AST/NamedDeclPrinterTest.cpp4
-rw-r--r--unittests/CodeGen/CMakeLists.txt1
-rw-r--r--unittests/CodeGen/IRMatchers.h453
-rw-r--r--unittests/CodeGen/TBAAMetadataTest.cpp1299
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp82
-rw-r--r--utils/TableGen/NeonEmitter.cpp12
187 files changed, 8280 insertions, 2578 deletions
diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake
index 52512e94e2c3..7ad2d9c60765 100644
--- a/cmake/caches/Fuchsia-stage2.cmake
+++ b/cmake/caches/Fuchsia-stage2.cmake
@@ -23,6 +23,7 @@ if(APPLE)
set(LLDB_CODESIGN_IDENTITY "" CACHE STRING "")
endif()
+set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "")
diff --git a/cmake/caches/Fuchsia.cmake b/cmake/caches/Fuchsia.cmake
index 05a28d6c0947..0d8159294e27 100644
--- a/cmake/caches/Fuchsia.cmake
+++ b/cmake/caches/Fuchsia.cmake
@@ -13,6 +13,7 @@ set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "")
set(LLVM_ENABLE_ZLIB OFF CACHE BOOL "")
set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
+set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
set(CMAKE_BUILD_TYPE Release CACHE STRING "")
set(BOOTSTRAP_LLVM_ENABLE_LTO ON CACHE BOOL "")
diff --git a/docs/HardwareAssistedAddressSanitizerDesign.rst b/docs/HardwareAssistedAddressSanitizerDesign.rst
index 00777ce88280..5904cceaead2 100644
--- a/docs/HardwareAssistedAddressSanitizerDesign.rst
+++ b/docs/HardwareAssistedAddressSanitizerDesign.rst
@@ -21,7 +21,7 @@ The redzones, the quarantine, and, to a less extent, the shadow, are the
sources of AddressSanitizer's memory overhead.
See the `AddressSanitizer paper`_ for details.
-AArch64 has the `Address Tagging`_, a hardware feature that allows
+AArch64 has the `Address Tagging`_ (or top-byte-ignore, TBI), a hardware feature that allows
software to use 8 most significant bits of a 64-bit pointer as
a tag. HWASAN uses `Address Tagging`_
to implement a memory safety tool, similar to :doc:`AddressSanitizer`,
@@ -31,7 +31,7 @@ accuracy guarantees.
Algorithm
=========
* Every heap/stack/global memory object is forcibly aligned by `N` bytes
- (`N` is e.g. 16 or 64)
+ (`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)
* The pointer to the object is tagged with `T`.
* The memory for the object is also tagged with `T`
@@ -44,19 +44,35 @@ Instrumentation
Memory Accesses
---------------
-All memory accesses are prefixed with a call to a run-time function.
-The function encodes the type and the size of access in its name;
-it receives the address as a parameter, e.g. `__hwasan_load4(void *ptr)`;
-it loads the memory tag, compares it with the
-pointer tag, and executes `__builtin_trap` (or calls `__hwasan_error_load4(void *ptr)`) on mismatch.
+All memory accesses are prefixed with an inline instruction sequence that
+verifies the tags. Currently, the following sequence is used:
-It's possible to inline this callback too.
+
+.. code-block:: asm
+
+ // int foo(int *a) { return *a; }
+ // clang -O2 --target=aarch64-linux -fsanitize=hwaddress -c load.c
+ foo:
+ 0: 08 dc 44 d3 ubfx x8, x0, #4, #52 // shadow address
+ 4: 08 01 40 39 ldrb w8, [x8] // load shadow
+ 8: 09 fc 78 d3 lsr x9, x0, #56 // address tag
+ 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
+ 20: 00 00 40 b9 ldr w0, [x0] // original load
+ 24: c0 03 5f d6 ret
+
+
+Alternatively, memory accesses are prefixed with a function call.
Heap
----
Tagging the heap memory/pointers is done by `malloc`.
This can be based on any malloc that forces all objects to be N-aligned.
+`free` tags the memory with a different tag.
Stack
-----
@@ -75,7 +91,7 @@ TODO: details.
Error reporting
---------------
-Errors are generated by `__builtin_trap` and are handled by a signal handler.
+Errors are generated by the `HLT` instruction and are handled by a signal handler.
Attribute
---------
diff --git a/docs/Modules.rst b/docs/Modules.rst
index 757be6191390..2fa38be6f493 100644
--- a/docs/Modules.rst
+++ b/docs/Modules.rst
@@ -859,10 +859,12 @@ express this with a single module map file in the library:
module Foo {
header "Foo.h"
-
- explicit module Private {
- header "Foo_Private.h"
- }
+ ...
+ }
+
+ module Foo_Private {
+ header "Foo_Private.h"
+ ...
}
@@ -873,7 +875,7 @@ build machinery.
Private module map files, which are named ``module.private.modulemap``
(or, for backward compatibility, ``module_private.map``), allow one to
-augment the primary module map file with an additional submodule. For
+augment the primary module map file with an additional modules. For
example, we would split the module map file above into two module map
files:
@@ -883,9 +885,9 @@ files:
module Foo {
header "Foo.h"
}
-
+
/* module.private.modulemap */
- explicit module Foo.Private {
+ module Foo_Private {
header "Foo_Private.h"
}
@@ -899,13 +901,12 @@ boundaries.
When writing a private module as part of a *framework*, it's recommended that:
-* Headers for this module are present in the ``PrivateHeaders``
- framework subdirectory.
-* The private module is defined as a *submodule* of the public framework (if
- there's one), similar to how ``Foo.Private`` is defined in the example above.
-* The ``explicit`` keyword should be used to guarantee that its content will
- only be available when the submodule itself is explicitly named (through a
- ``@import`` for example).
+* Headers for this module are present in the ``PrivateHeaders`` framework
+ subdirectory.
+* The private module is defined as a *top level module* with the name of the
+ public framework prefixed, like ``Foo_Private`` above. Clang has extra logic
+ to work with this naming, using ``FooPrivate`` or ``Foo.Private`` (submodule)
+ trigger warnings and might not work as expected.
Modularizing a Platform
=======================
diff --git a/docs/UndefinedBehaviorSanitizer.rst b/docs/UndefinedBehaviorSanitizer.rst
index 0a08a41e2d9b..e9f85c24dde0 100644
--- a/docs/UndefinedBehaviorSanitizer.rst
+++ b/docs/UndefinedBehaviorSanitizer.rst
@@ -124,8 +124,8 @@ Available checks are:
- ``-fsanitize=signed-integer-overflow``: Signed integer overflow,
including all the checks added by ``-ftrapv``, and checking for
overflow in signed division (``INT_MIN / -1``).
- - ``-fsanitize=unreachable``: If control flow reaches
- ``__builtin_unreachable``.
+ - ``-fsanitize=unreachable``: If control flow reaches an unreachable
+ program point.
- ``-fsanitize=unsigned-integer-overflow``: Unsigned integer
overflows. Note that unlike signed integer overflow, unsigned integer
is not undefined behavior. However, while it has well-defined semantics,
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 4db0b1ef949b..04a832e552a4 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -1759,6 +1759,11 @@ protected:
unsigned IsCopyDeductionCandidate : 1;
private:
+
+ /// Store the ODRHash after first calculation.
+ unsigned HasODRHash : 1;
+ unsigned ODRHash;
+
/// \brief End part of this FunctionDecl's source range.
///
/// We could compute the full range in getSourceRange(). However, when we're
@@ -1841,8 +1846,9 @@ protected:
IsExplicitlyDefaulted(false), HasImplicitReturnZero(false),
IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified),
InstantiationIsPending(false), UsesSEHTry(false), HasSkippedBody(false),
- WillHaveBody(false), IsCopyDeductionCandidate(false),
- EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {}
+ WillHaveBody(false), IsCopyDeductionCandidate(false), HasODRHash(false),
+ ODRHash(0), EndRangeLoc(NameInfo.getEndLoc()),
+ DNLoc(NameInfo.getInfo()) {}
using redeclarable_base = Redeclarable<FunctionDecl>;
@@ -2439,6 +2445,10 @@ public:
/// returns 0.
unsigned getMemoryFunctionKind() const;
+ /// \brief Returns ODRHash of the function. This value is calculated and
+ /// stored on first call, then the stored value returned on the other calls.
+ unsigned getODRHash();
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) {
diff --git a/include/clang/AST/ODRHash.h b/include/clang/AST/ODRHash.h
index e4cc12d35891..ed648bb8afb1 100644
--- a/include/clang/AST/ODRHash.h
+++ b/include/clang/AST/ODRHash.h
@@ -53,6 +53,10 @@ public:
// more information than the AddDecl class.
void AddCXXRecordDecl(const CXXRecordDecl *Record);
+ // Use this for ODR checking functions between modules. This method compares
+ // more information than the AddDecl class.
+ void AddFunctionDecl(const FunctionDecl *Function);
+
// Process SubDecls of the main Decl. This method calls the DeclVisitor
// while AddDecl does not.
void AddSubDecl(const Decl *D);
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 7247838947a2..882878bb7e1e 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -976,16 +976,14 @@ public:
return LHS.Value != RHS.Value;
}
- std::string getAsString() const {
- return getAsString(split());
+ static std::string getAsString(SplitQualType split,
+ const PrintingPolicy &Policy) {
+ return getAsString(split.Ty, split.Quals, Policy);
}
+ static std::string getAsString(const Type *ty, Qualifiers qs,
+ const PrintingPolicy &Policy);
- static std::string getAsString(SplitQualType split) {
- return getAsString(split.Ty, split.Quals);
- }
-
- static std::string getAsString(const Type *ty, Qualifiers qs);
-
+ std::string getAsString() const;
std::string getAsString(const PrintingPolicy &Policy) const;
void print(raw_ostream &OS, const PrintingPolicy &Policy,
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index d926fdde4eee..8b84c4b8b50d 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -267,13 +267,24 @@ def RenderScript : LangOpt<"RenderScript">;
def ObjC : LangOpt<"ObjC1">;
def BlocksSupported : LangOpt<"Blocks">;
-// Defines targets for target-specific attributes. The list of strings should
-// specify architectures for which the target applies, based off the ArchType
-// enumeration in Triple.h.
-class TargetArch<list<string> arches> {
- list<string> Arches = arches;
+// Defines targets for target-specific attributes. Empty lists are unchecked.
+class TargetSpec {
+ // Specifies Architectures for which the target applies, based off the
+ // ArchType enumeration in Triple.h.
+ list<string> Arches = [];
+ // Specifies Operating Systems for which the target applies, based off the
+ // OSType enumeration in Triple.h
list<string> OSes;
+ // Specifies the C++ ABIs for which the target applies, based off the
+ // TargetCXXABI::Kind in TargetCXXABI.h.
list<string> CXXABIs;
+ // Specifies Object Formats for which the target applies, based off the
+ // ObjectFormatType enumeration in Triple.h
+ list<string> ObjectFormats;
+}
+
+class TargetArch<list<string> arches> : TargetSpec {
+ let Arches = arches;
}
def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>;
def TargetAVR : TargetArch<["avr"]>;
@@ -288,6 +299,9 @@ def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> {
def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> {
let CXXABIs = ["Microsoft"];
}
+def TargetELF : TargetSpec {
+ let ObjectFormats = ["ELF"];
+}
// Attribute subject match rules that are used for #pragma clang attribute.
//
@@ -465,8 +479,8 @@ class InheritableAttr : Attr;
/// A target-specific attribute. This class is meant to be used as a mixin
/// with InheritableAttr or Attr depending on the attribute's needs.
-class TargetSpecificAttr<TargetArch target> {
- TargetArch Target = target;
+class TargetSpecificAttr<TargetSpec target> {
+ TargetSpec Target = target;
// Attributes are generally required to have unique spellings for their names
// so that the parser can determine what kind of attribute it has parsed.
// However, target-specific attributes are special in that the attribute only
@@ -1121,7 +1135,7 @@ def IBOutletCollection : InheritableAttr {
let Documentation = [Undocumented];
}
-def IFunc : Attr {
+def IFunc : Attr, TargetSpecificAttr<TargetELF> {
let Spellings = [GCC<"ifunc">];
let Args = [StringArgument<"Resolver">];
let Subjects = SubjectList<[Function]>;
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index 392a340a3bb7..b25181f25658 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -198,6 +198,11 @@ def err_missing_module : Error<
def err_no_submodule : Error<"no submodule named %0 in module '%1'">;
def err_no_submodule_suggest : Error<
"no submodule named %0 in module '%1'; did you mean '%2'?">;
+def warn_no_priv_submodule_use_toplevel : Warning<
+ "no submodule named %0 in module '%1'; using top level '%2'">,
+ InGroup<PrivateModule>;
+def note_private_top_level_defined : Note<
+ "module defined here">;
def warn_missing_submodule : Warning<"missing submodule '%0'">,
InGroup<IncompleteUmbrella>;
def note_module_import_here : Note<"module imported here">;
diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h
index 43183a120bb9..b4ea85ba853c 100644
--- a/include/clang/Basic/DiagnosticIDs.h
+++ b/include/clang/Basic/DiagnosticIDs.h
@@ -297,7 +297,7 @@ public:
/// \brief Get the set of all diagnostic IDs.
static void getAllDiagnostics(diag::Flavor Flavor,
- SmallVectorImpl<diag::kind> &Diags);
+ std::vector<diag::kind> &Diags);
/// \brief Get the diagnostic option with the closest edit distance to the
/// given group name.
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index c664281ffcd4..c391470cb1c8 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -691,11 +691,15 @@ def err_mmap_expected_feature : Error<"expected a feature name">;
def err_mmap_expected_attribute : Error<"expected an attribute name">;
def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">,
InGroup<IgnoredAttributes>;
-def warn_mmap_mismatched_top_level_private : Warning<
- "top-level module '%0' in private module map, expected a submodule of '%1'">,
+def warn_mmap_mismatched_private_submodule : Warning<
+ "private submodule '%0' in private module map, expected top-level module">,
InGroup<PrivateModule>;
-def note_mmap_rename_top_level_private_as_submodule : Note<
- "make '%0' a submodule of '%1' to ensure it can be found by name">;
+def warn_mmap_mismatched_private_module_name : Warning<
+ "expected canonical name for private module '%0'">,
+ InGroup<PrivateModule>;
+def note_mmap_rename_top_level_private_module : Note<
+ "rename '%0' to ensure it can be found by name">;
+
def err_mmap_duplicate_header_attribute : Error<
"header attribute '%0' specified multiple times">;
def err_mmap_invalid_header_attribute_value : Error<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 29236eab5446..01e819942f68 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3911,6 +3911,9 @@ def err_template_param_different_kind : Error<
"%select{|template parameter }0redeclaration">;
def note_template_param_different_kind : Note<
"template parameter has a different kind in template argument">;
+
+def err_invalid_decl_specifier_in_nontype_parm : Error<
+ "invalid declaration specifier in template non-type parameter">;
def err_template_nontype_parm_different_type : Error<
"template non-type parameter has a different type %0 in template "
diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td
index 3949bc2146f6..250b49f2cac4 100644
--- a/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -270,6 +270,29 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
"friend function %2|"
"}1">;
+def err_module_odr_violation_function : Error<
+ "%q0 has different definitions in different modules; "
+ "%select{definition in module '%2'|defined here}1 "
+ "first difference is "
+ "%select{"
+ "return type is %4|"
+ "%ordinal4 parameter with name %5|"
+ "%ordinal4 parameter with type %5%select{| decayed from %7}6|"
+ "%ordinal4 parameter with%select{out|}5 a default argument|"
+ "%ordinal4 parameter with a default argument|"
+ "function body"
+ "}3">;
+
+def note_module_odr_violation_function : Note<"but in '%0' found "
+ "%select{"
+ "different return type %2|"
+ "%ordinal2 parameter with name %3|"
+ "%ordinal2 parameter with type %3%select{| decayed from %5}4|"
+ "%ordinal2 parameter with%select{out|}3 a default argument|"
+ "%ordinal2 parameter with a different default argument|"
+ "a different body"
+ "}1">;
+
def err_module_odr_violation_mismatch_decl_unknown : Error<
"%q0 %select{with definition in module '%2'|defined here}1 has different "
"definitions in different modules; first difference is this "
diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td
index ad8d679a1664..d5c16a91a34f 100644
--- a/include/clang/Basic/arm_neon.td
+++ b/include/clang/Basic/arm_neon.td
@@ -227,6 +227,7 @@ def OP_UNAVAILABLE : Operation {
// u: unsigned integer (int/float args)
// f: float (int args)
// F: double (int args)
+// H: half (int args)
// d: default
// g: default, ignore 'Q' size modifier.
// j: default, force 'Q' size modifier.
@@ -345,6 +346,7 @@ def OP_MLSLHi : Op<(call "vmlsl", $p0, (call "vget_high", $p1),
(call "vget_high", $p2))>;
def OP_MLSLHi_N : Op<(call "vmlsl_n", $p0, (call "vget_high", $p1), $p2)>;
def OP_MUL_N : Op<(op "*", $p0, (dup $p1))>;
+def OP_MULX_N : Op<(call "vmulx", $p0, (dup $p1))>;
def OP_MLA_N : Op<(op "+", $p0, (op "*", $p1, (dup $p2)))>;
def OP_MLS_N : Op<(op "-", $p0, (op "*", $p1, (dup $p2)))>;
def OP_FMLA_N : Op<(call "vfma", $p0, $p1, (dup $p2))>;
@@ -1661,3 +1663,186 @@ def SCALAR_SQRDMLSH_LANEQ : SOpInst<"vqrdmlsh_laneq", "sssji", "SsSi", OP_SCALAR
def SCALAR_VDUP_LANE : IInst<"vdup_lane", "sdi", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
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 one-operand vector intrinsics.
+
+ // Comparison
+ def CMEQH : SInst<"vceqz", "ud", "hQh">;
+ def CMGEH : SInst<"vcgez", "ud", "hQh">;
+ def CMGTH : SInst<"vcgtz", "ud", "hQh">;
+ def CMLEH : SInst<"vclez", "ud", "hQh">;
+ def CMLTH : SInst<"vcltz", "ud", "hQh">;
+
+ // Vector conversion
+ def VCVT_F16 : SInst<"vcvt_f16", "Hd", "sUsQsQUs">;
+ def VCVT_S16 : SInst<"vcvt_s16", "xd", "hQh">;
+ def VCVT_U16 : SInst<"vcvt_u16", "ud", "hQh">;
+ def VCVTA_S16 : SInst<"vcvta_s16", "xd", "hQh">;
+ def VCVTA_U16 : SInst<"vcvta_u16", "ud", "hQh">;
+ def VCVTM_S16 : SInst<"vcvtm_s16", "xd", "hQh">;
+ def VCVTM_U16 : SInst<"vcvtm_u16", "ud", "hQh">;
+ def VCVTN_S16 : SInst<"vcvtn_s16", "xd", "hQh">;
+ def VCVTN_U16 : SInst<"vcvtn_u16", "ud", "hQh">;
+ def VCVTP_S16 : SInst<"vcvtp_s16", "xd", "hQh">;
+ def VCVTP_U16 : SInst<"vcvtp_u16", "ud", "hQh">;
+
+ // Vector rounding
+ def FRINTZH : SInst<"vrnd", "dd", "hQh">;
+ def FRINTNH : SInst<"vrndn", "dd", "hQh">;
+ def FRINTAH : SInst<"vrnda", "dd", "hQh">;
+ 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.
+
+ // Misc.
+ def VADDH : SOpInst<"vadd", "ddd", "hQh", OP_ADD>;
+ def VABDH : SInst<"vabd", "ddd", "hQh">;
+ def VSUBH : SOpInst<"vsub", "ddd", "hQh", OP_SUB>;
+
+ // Comparison
+ let InstName = "vacge" in {
+ def VCAGEH : SInst<"vcage", "udd", "hQh">;
+ def VCALEH : SInst<"vcale", "udd", "hQh">;
+ }
+ let InstName = "vacgt" in {
+ def VCAGTH : SInst<"vcagt", "udd", "hQh">;
+ def VCALTH : SInst<"vcalt", "udd", "hQh">;
+ }
+ def VCEQH : SOpInst<"vceq", "udd", "hQh", OP_EQ>;
+ def VCGEH : SOpInst<"vcge", "udd", "hQh", OP_GE>;
+ def VCGTH : SOpInst<"vcgt", "udd", "hQh", OP_GT>;
+ let InstName = "vcge" in
+ def VCLEH : SOpInst<"vcle", "udd", "hQh", OP_LE>;
+ let InstName = "vcgt" in
+ def VCLTH : SOpInst<"vclt", "udd", "hQh", OP_LT>;
+
+ // Vector conversion
+ let isVCVT_N = 1 in {
+ def VCVT_N_F16 : SInst<"vcvt_n_f16", "Hdi", "sUsQsQUs">;
+ def VCVT_N_S16 : SInst<"vcvt_n_s16", "xdi", "hQh">;
+ def VCVT_N_U16 : SInst<"vcvt_n_u16", "udi", "hQh">;
+ }
+
+ // Max/Min
+ def VMAXH : SInst<"vmax", "ddd", "hQh">;
+ def VMINH : SInst<"vmin", "ddd", "hQh">;
+ def FMAXNMH : SInst<"vmaxnm", "ddd", "hQh">;
+ def FMINNMH : SInst<"vminnm", "ddd", "hQh">;
+
+ // 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">;
+
+ // 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">;
+
+ // Reciprocal/Sqrt
+ def VRECPSH : SInst<"vrecps", "ddd", "hQh">;
+ def VRSQRTSH : SInst<"vrsqrts", "ddd", "hQh">;
+
+ // ARMv8.2-A FP16 three-operands vector intrinsics.
+
+ // Vector fused multiply-add operations
+ def VFMAH : SInst<"vfma", "dddd", "hQh">;
+ def VFMSH : SOpInst<"vfms", "dddd", "hQh", OP_FMLS>;
+
+ // 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">;
+
+ // FMA lane with scalar argument
+ def FMLA_NH : SOpInst<"vfma_n", "ddds", "hQh", OP_FMLA_N>;
+ // Scalar floating point fused multiply-add (scalar, by element)
+ def SCALAR_FMLA_LANEH : IInst<"vfma_lane", "sssdi", "Sh">;
+ def SCALAR_FMLA_LANEQH : IInst<"vfma_laneq", "sssji", "Sh">;
+
+ // FMS lane
+ def VFMS_LANEH : IOpInst<"vfms_lane", "dddgi", "hQh", OP_FMS_LN>;
+ def VFMS_LANEQH : IOpInst<"vfms_laneq", "dddji", "hQh", OP_FMS_LNQ>;
+ // FMS lane with scalar argument
+ def FMLS_NH : SOpInst<"vfms_n", "ddds", "hQh", OP_FMLS_N>;
+ // Scalar floating foint fused multiply-subtract (scalar, by element)
+ def SCALAR_FMLS_LANEH : IOpInst<"vfms_lane", "sssdi", "Sh", OP_FMS_LN>;
+ 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>;
+
+ // Mulx lane
+ 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>;
+
+ // ARMv8.2-A FP16 reduction vector intrinsics.
+ def VMAXVH : SInst<"vmaxv", "sd", "hQh">;
+ def VMINVH : SInst<"vminv", "sd", "hQh">;
+ 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>;
+ def VUZP1H : SOpInst<"vuzp1", "ddd", "hQh", OP_UZP1>;
+ def VTRN2H : SOpInst<"vtrn2", "ddd", "hQh", OP_TRN2>;
+ def VZIP2H : SOpInst<"vzip2", "ddd", "hQh", OP_ZIP2>;
+ def VUZP2H : SOpInst<"vuzp2", "ddd", "hQh", OP_UZP2>;
+
+ def SCALAR_VDUP_LANEH : IInst<"vdup_lane", "sdi", "Sh">;
+ def SCALAR_VDUP_LANEQH : IInst<"vdup_laneq", "sji", "Sh">;
+}
diff --git a/include/clang/Frontend/PrecompiledPreamble.h b/include/clang/Frontend/PrecompiledPreamble.h
index 64342b1dffa8..130fe60704a7 100644
--- a/include/clang/Frontend/PrecompiledPreamble.h
+++ b/include/clang/Frontend/PrecompiledPreamble.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/MD5.h"
+#include <cstddef>
#include <memory>
#include <system_error>
#include <type_traits>
@@ -89,6 +90,11 @@ public:
/// PreambleBounds used to build the preamble.
PreambleBounds getBounds() const;
+ /// Returns the size, in bytes, that preamble takes on disk or in memory.
+ /// For on-disk preambles returns 0 if filesystem operations fail. Intended to
+ /// be used for logging and debugging purposes only.
+ std::size_t getSize() const;
+
/// Check whether PrecompiledPreamble can be reused for the new contents(\p
/// MainFileBuffer) of the main file.
bool CanReuse(const CompilerInvocation &Invocation,
@@ -244,6 +250,11 @@ class PreambleCallbacks {
public:
virtual ~PreambleCallbacks() = default;
+ /// Called before FrontendAction::BeginSourceFile.
+ /// Can be used to store references to various CompilerInstance fields
+ /// (e.g. SourceManager) that may be interesting to the consumers of other
+ /// callbacks.
+ virtual void BeforeExecute(CompilerInstance &CI);
/// Called after FrontendAction::Execute(), but before
/// FrontendAction::EndSourceFile(). Can be used to transfer ownership of
/// various CompilerInstance fields before they are destroyed.
diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h
index ae591364f229..08f2839f37e8 100644
--- a/include/clang/Index/IndexSymbol.h
+++ b/include/clang/Index/IndexSymbol.h
@@ -56,7 +56,7 @@ enum class SymbolKind : uint8_t {
Using,
};
-enum class SymbolLanguage {
+enum class SymbolLanguage : uint8_t {
C,
ObjC,
CXX,
@@ -64,7 +64,7 @@ enum class SymbolLanguage {
};
/// Language specific sub-kinds.
-enum class SymbolSubKind {
+enum class SymbolSubKind : uint8_t {
None,
CXXCopyConstructor,
CXXMoveConstructor,
@@ -74,8 +74,9 @@ enum class SymbolSubKind {
UsingValue,
};
+typedef uint8_t SymbolPropertySet;
/// Set of properties that provide additional info about a symbol.
-enum class SymbolProperty : uint8_t {
+enum class SymbolProperty : SymbolPropertySet {
Generic = 1 << 0,
TemplatePartialSpecialization = 1 << 1,
TemplateSpecialization = 1 << 2,
@@ -86,7 +87,6 @@ enum class SymbolProperty : uint8_t {
Local = 1 << 7,
};
static const unsigned SymbolPropertyBitNum = 8;
-typedef unsigned SymbolPropertySet;
/// Set of roles that are attributed to symbol occurrences.
enum class SymbolRole : uint32_t {
@@ -127,8 +127,8 @@ struct SymbolRelation {
struct SymbolInfo {
SymbolKind Kind;
SymbolSubKind SubKind;
- SymbolPropertySet Properties;
SymbolLanguage Lang;
+ SymbolPropertySet Properties;
};
SymbolInfo getSymbolInfo(const Decl *D);
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 396b5a9aa394..8f5b20c2bd71 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -2748,10 +2748,10 @@ private:
bool ParseTemplateParameterList(unsigned Depth,
SmallVectorImpl<NamedDecl*> &TemplateParams);
bool isStartOfTemplateTypeParameter();
- Decl *ParseTemplateParameter(unsigned Depth, unsigned Position);
- Decl *ParseTypeParameter(unsigned Depth, unsigned Position);
- Decl *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
- Decl *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
+ NamedDecl *ParseTemplateParameter(unsigned Depth, unsigned Position);
+ NamedDecl *ParseTypeParameter(unsigned Depth, unsigned Position);
+ NamedDecl *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
+ NamedDecl *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
void DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc,
SourceLocation CorrectLoc,
bool AlreadyHasEllipsis,
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 47cea3029bd9..9cbe8e5cd63e 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -6064,7 +6064,7 @@ public:
void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
- Decl *ActOnTypeParameter(Scope *S, bool Typename,
+ NamedDecl *ActOnTypeParameter(Scope *S, bool Typename,
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
@@ -6077,12 +6077,12 @@ public:
SourceLocation Loc);
QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
- Decl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+ NamedDecl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
unsigned Depth,
unsigned Position,
SourceLocation EqualLoc,
Expr *DefaultArg);
- Decl *ActOnTemplateTemplateParameter(Scope *S,
+ NamedDecl *ActOnTemplateTemplateParameter(Scope *S,
SourceLocation TmpLoc,
TemplateParameterList *Params,
SourceLocation EllipsisLoc,
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 7b71fee95de2..37920fc143ea 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -1092,6 +1092,10 @@ private:
llvm::SmallDenseMap<CXXRecordDecl *, llvm::SmallVector<DataPointers, 2>, 2>
PendingOdrMergeFailures;
+ /// \brief Function definitions in which we found an ODR violation.
+ llvm::SmallDenseMap<FunctionDecl *, llvm::SmallVector<FunctionDecl *, 2>, 2>
+ PendingFunctionOdrMergeFailures;
+
/// \brief DeclContexts in which we have diagnosed an ODR violation.
llvm::SmallPtrSet<DeclContext*, 2> DiagnosedOdrMergeFailures;
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index a07cd88950d8..f31ab2cd81cd 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -334,7 +334,7 @@ public:
// Path "pieces" for path-sensitive diagnostics.
//===----------------------------------------------------------------------===//
-class PathDiagnosticPiece {
+class PathDiagnosticPiece: public llvm::FoldingSetNode {
public:
enum Kind { ControlFlow, Event, Macro, Call, Note };
enum DisplayHint { Above, Below };
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 157b29fd84b6..92be6d95e898 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -99,6 +99,9 @@ namespace {
const CommandTraits *Traits;
const SourceManager *SM;
+ /// The policy to use for printing; can be defaulted.
+ PrintingPolicy PrintPolicy;
+
/// Pending[i] is an action to dump an entity at level i.
llvm::SmallVector<std::function<void(bool isLastChild)>, 32> Pending;
@@ -207,12 +210,17 @@ namespace {
public:
ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
const SourceManager *SM)
- : OS(OS), Traits(Traits), SM(SM),
- ShowColors(SM && SM->getDiagnostics().getShowColors()) { }
+ : ASTDumper(OS, Traits, SM,
+ SM && SM->getDiagnostics().getShowColors()) {}
ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
const SourceManager *SM, bool ShowColors)
- : OS(OS), Traits(Traits), SM(SM), ShowColors(ShowColors) {}
+ : ASTDumper(OS, Traits, SM, ShowColors, LangOptions()) {}
+ ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
+ const SourceManager *SM, bool ShowColors,
+ const PrintingPolicy &PrintPolicy)
+ : OS(OS), Traits(Traits), SM(SM), PrintPolicy(PrintPolicy),
+ ShowColors(ShowColors) {}
void setDeserialize(bool D) { Deserialize = D; }
@@ -646,13 +654,13 @@ void ASTDumper::dumpBareType(QualType T, bool Desugar) {
ColorScope Color(*this, TypeColor);
SplitQualType T_split = T.split();
- OS << "'" << QualType::getAsString(T_split) << "'";
+ OS << "'" << QualType::getAsString(T_split, PrintPolicy) << "'";
if (Desugar && !T.isNull()) {
// If the type is sugared, also dump a (shallow) desugared type.
SplitQualType D_split = T.getSplitDesugaredType();
if (T_split != D_split)
- OS << ":'" << QualType::getAsString(D_split) << "'";
+ OS << ":'" << QualType::getAsString(D_split, PrintPolicy) << "'";
}
}
@@ -1187,12 +1195,12 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
if (MD->size_overridden_methods() != 0) {
- auto dumpOverride =
- [=](const CXXMethodDecl *D) {
- SplitQualType T_split = D->getType().split();
- OS << D << " " << D->getParent()->getName() << "::"
- << D->getNameAsString() << " '" << QualType::getAsString(T_split) << "'";
- };
+ auto dumpOverride = [=](const CXXMethodDecl *D) {
+ SplitQualType T_split = D->getType().split();
+ OS << D << " " << D->getParent()->getName()
+ << "::" << D->getNameAsString() << " '"
+ << QualType::getAsString(T_split, PrintPolicy) << "'";
+ };
dumpChild([=] {
auto Overrides = MD->overridden_methods();
@@ -1537,7 +1545,7 @@ void ASTDumper::VisitTemplateDeclSpecialization(const SpecializationDecl *D,
case TSK_ExplicitInstantiationDefinition:
if (!DumpExplicitInst)
break;
- // Fall through.
+ LLVM_FALLTHROUGH;
case TSK_Undeclared:
case TSK_ImplicitInstantiation:
if (DumpRefOnly)
@@ -2682,15 +2690,19 @@ LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS) const {
LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }
LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize) const {
- ASTDumper P(OS, &getASTContext().getCommentCommandTraits(),
- &getASTContext().getSourceManager());
+ const ASTContext &Ctx = getASTContext();
+ const SourceManager &SM = Ctx.getSourceManager();
+ ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &SM,
+ SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy());
P.setDeserialize(Deserialize);
P.dumpDecl(this);
}
LLVM_DUMP_METHOD void Decl::dumpColor() const {
- ASTDumper P(llvm::errs(), &getASTContext().getCommentCommandTraits(),
- &getASTContext().getSourceManager(), /*ShowColors*/true);
+ const ASTContext &Ctx = getASTContext();
+ ASTDumper P(llvm::errs(), &Ctx.getCommentCommandTraits(),
+ &Ctx.getSourceManager(), /*ShowColors*/ true,
+ Ctx.getPrintingPolicy());
P.dumpDecl(this);
}
@@ -2705,7 +2717,9 @@ LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
while (!DC->isTranslationUnit())
DC = DC->getParent();
ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
- ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager());
+ const SourceManager &SM = Ctx.getSourceManager();
+ ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager(),
+ SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy());
P.setDeserialize(Deserialize);
P.dumpLookups(this, DumpDecls);
}
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 84b0d7ecff93..0e627f9737ce 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -134,17 +134,12 @@ namespace clang {
bool ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs);
- template <typename InContainerTy>
- bool ImportTemplateArgumentListInfo(const InContainerTy &Container,
- TemplateArgumentListInfo &ToTAInfo);
bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord,
bool Complain = true);
bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar,
bool Complain = true);
bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord);
bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC);
- bool IsStructuralMatch(FunctionTemplateDecl *From,
- FunctionTemplateDecl *To);
bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To);
bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To);
Decl *VisitDecl(Decl *D);
@@ -200,7 +195,6 @@ namespace clang {
ClassTemplateSpecializationDecl *D);
Decl *VisitVarTemplateDecl(VarTemplateDecl *D);
Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
- Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
// Importing statements
DeclGroupRef ImportDeclGroup(DeclGroupRef DG);
@@ -286,7 +280,6 @@ namespace clang {
Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E);
Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
- Expr *VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
Expr *VisitExprWithCleanups(ExprWithCleanups *EWC);
Expr *VisitCXXThisExpr(CXXThisExpr *E);
Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
@@ -1254,18 +1247,6 @@ bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
return false;
}
-template <typename InContainerTy>
-bool ASTNodeImporter::ImportTemplateArgumentListInfo(
- const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) {
- for (const auto &FromLoc : Container) {
- if (auto ToLoc = ImportTemplateArgumentLoc(FromLoc))
- ToTAInfo.addArgument(*ToLoc);
- else
- return true;
- }
- return false;
-}
-
bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
RecordDecl *ToRecord, bool Complain) {
// Eliminate a potential failure point where we attempt to re-import
@@ -1299,14 +1280,6 @@ bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) {
return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum);
}
-bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From,
- FunctionTemplateDecl *To) {
- StructuralEquivalenceContext Ctx(
- Importer.getFromContext(), Importer.getToContext(),
- Importer.getNonEquivalentDecls(), false, false);
- return Ctx.IsStructurallyEquivalent(From, To);
-}
-
bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC,
EnumConstantDecl *ToEC)
{
@@ -4224,64 +4197,6 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
return D2;
}
-Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
- DeclContext *DC, *LexicalDC;
- DeclarationName Name;
- SourceLocation Loc;
- NamedDecl *ToD;
-
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
-
- if (ToD)
- return ToD;
-
- // Try to find a function in our own ("to") context with the same name, same
- // type, and in the same context as the function we're importing.
- if (!LexicalDC->isFunctionOrMethod()) {
- unsigned IDNS = Decl::IDNS_Ordinary;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
- for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
- if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
- continue;
-
- if (FunctionTemplateDecl *FoundFunction =
- dyn_cast<FunctionTemplateDecl>(FoundDecls[I])) {
- if (FoundFunction->hasExternalFormalLinkage() &&
- D->hasExternalFormalLinkage()) {
- if (IsStructuralMatch(D, FoundFunction)) {
- Importer.Imported(D, FoundFunction);
- // FIXME: Actually try to merge the body and other attributes.
- return FoundFunction;
- }
- }
- }
- }
- }
-
- TemplateParameterList *Params =
- ImportTemplateParameterList(D->getTemplateParameters());
- if (!Params)
- return nullptr;
-
- FunctionDecl *TemplatedFD =
- cast_or_null<FunctionDecl>(Importer.Import(D->getTemplatedDecl()));
- if (!TemplatedFD)
- return nullptr;
-
- FunctionTemplateDecl *ToFunc = FunctionTemplateDecl::Create(
- Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD);
-
- TemplatedFD->setDescribedFunctionTemplate(ToFunc);
- ToFunc->setAccess(D->getAccess());
- ToFunc->setLexicalDeclContext(LexicalDC);
- Importer.Imported(D, ToFunc);
-
- LexicalDC->addDeclInternal(ToFunc);
- return ToFunc;
-}
-
//----------------------------------------------------------------------------
// Import Statements
//----------------------------------------------------------------------------
@@ -5844,47 +5759,6 @@ Expr *ASTNodeImporter::VisitCXXPseudoDestructorExpr(
Importer.Import(E->getTildeLoc()), Storage);
}
-Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
- CXXDependentScopeMemberExpr *E) {
- Expr *Base = nullptr;
- if (!E->isImplicitAccess()) {
- Base = Importer.Import(E->getBase());
- if (!Base)
- return nullptr;
- }
-
- QualType BaseType = Importer.Import(E->getBaseType());
- if (BaseType.isNull())
- return nullptr;
-
- TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()),
- Importer.Import(E->getRAngleLoc()));
- TemplateArgumentListInfo *ResInfo = nullptr;
- if (E->hasExplicitTemplateArgs()) {
- if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
- return nullptr;
- ResInfo = &ToTAInfo;
- }
-
- DeclarationName Name = Importer.Import(E->getMember());
- if (!E->getMember().isEmpty() && Name.isEmpty())
- return nullptr;
-
- DeclarationNameInfo MemberNameInfo(Name, Importer.Import(E->getMemberLoc()));
- // Import additional name location/type info.
- ImportDeclarationNameLoc(E->getMemberNameInfo(), MemberNameInfo);
- auto ToFQ = Importer.Import(E->getFirstQualifierFoundInScope());
- if (!ToFQ && E->getFirstQualifierFoundInScope())
- return nullptr;
-
- return CXXDependentScopeMemberExpr::Create(
- Importer.getToContext(), Base, BaseType, E->isArrow(),
- Importer.Import(E->getOperatorLoc()),
- Importer.Import(E->getQualifierLoc()),
- Importer.Import(E->getTemplateKeywordLoc()),
- cast_or_null<NamedDecl>(ToFQ), MemberNameInfo, ResInfo);
-}
-
Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 2f51ec31a7bd..629037b1755c 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -26,6 +26,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/ODRHash.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Stmt.h"
@@ -1548,7 +1549,10 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
// enumerator is declared in the scope that immediately contains
// the enum-specifier. Each scoped enumerator is declared in the
// scope of the enumeration.
- if (ED->isScoped() || ED->getIdentifier())
+ // For the case of unscoped enumerator, do not include in the qualified
+ // name any information about its enum enclosing scope, as is visibility
+ // is global.
+ if (ED->isScoped())
OS << *ED;
else
continue;
@@ -3601,6 +3605,25 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
return 0;
}
+unsigned FunctionDecl::getODRHash() {
+ if (HasODRHash)
+ return ODRHash;
+
+ if (FunctionDecl *Definition = getDefinition()) {
+ if (Definition != this) {
+ HasODRHash = true;
+ ODRHash = Definition->getODRHash();
+ return ODRHash;
+ }
+ }
+
+ class ODRHash Hash;
+ Hash.AddFunctionDecl(this);
+ HasODRHash = true;
+ ODRHash = Hash.CalculateHash();
+ return ODRHash;
+}
+
//===----------------------------------------------------------------------===//
// FieldDecl Implementation
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 55061aa462e5..7ddab9356b54 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -3116,7 +3116,8 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
if (DCE->getTypeAsWritten()->isReferenceType() &&
DCE->getCastKind() == CK_Dynamic)
return true;
- } // Fall through.
+ }
+ LLVM_FALLTHROUGH;
case ImplicitCastExprClass:
case CStyleCastExprClass:
case CXXStaticCastExprClass:
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 262a1e3ff9d5..a0d611381123 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -857,7 +857,7 @@ LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit,
switch (Kind) {
case LCK_StarThis:
Bits |= Capture_ByCopy;
- // Fall through
+ LLVM_FALLTHROUGH;
case LCK_This:
assert(!Var && "'this' capture cannot have a variable!");
Bits |= Capture_This;
@@ -865,7 +865,7 @@ LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit,
case LCK_ByCopy:
Bits |= Capture_ByCopy;
- // Fall through
+ LLVM_FALLTHROUGH;
case LCK_ByRef:
assert(Var && "capture must have a variable!");
break;
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 9c9eeb79b40a..8d9b3c3bebc0 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -5913,7 +5913,7 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
<< (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
else
Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
- // Fall through.
+ LLVM_FALLTHROUGH;
case Builtin::BI__builtin_strchr:
case Builtin::BI__builtin_wcschr:
case Builtin::BI__builtin_memchr:
@@ -5952,7 +5952,7 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
Desired))
return ZeroInitialization(E);
StopAtNull = true;
- // Fall through.
+ LLVM_FALLTHROUGH;
case Builtin::BImemchr:
case Builtin::BI__builtin_memchr:
case Builtin::BI__builtin_char_memchr:
@@ -5965,7 +5965,7 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
case Builtin::BIwcschr:
case Builtin::BI__builtin_wcschr:
StopAtNull = true;
- // Fall through.
+ LLVM_FALLTHROUGH;
case Builtin::BIwmemchr:
case Builtin::BI__builtin_wmemchr:
// wcschr and wmemchr are given a wchar_t to look for. Just use it.
@@ -7209,6 +7209,7 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E,
case BuiltinType::Dependent:
llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
};
+ break;
case Type::Enum:
return LangOpts.CPlusPlus ? enumeral_type_class : integer_type_class;
@@ -7419,7 +7420,10 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
// If we don't know the array bound, conservatively assume we're looking at
// the final array element.
++I;
- BaseType = BaseType->castAs<PointerType>()->getPointeeType();
+ if (BaseType->isIncompleteArrayType())
+ BaseType = Ctx.getAsArrayType(BaseType)->getElementType();
+ else
+ BaseType = BaseType->castAs<PointerType>()->getPointeeType();
}
for (unsigned E = LVal.Designator.Entries.size(); I != E; ++I) {
@@ -7821,7 +7825,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
<< (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
else
Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
- // Fall through.
+ LLVM_FALLTHROUGH;
case Builtin::BI__builtin_strlen:
case Builtin::BI__builtin_wcslen: {
// As an extension, we support __builtin_strlen() as a constant expression,
@@ -7881,7 +7885,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
<< (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
else
Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
- // Fall through.
+ LLVM_FALLTHROUGH;
case Builtin::BI__builtin_strcmp:
case Builtin::BI__builtin_wcscmp:
case Builtin::BI__builtin_strncmp:
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index f95dc8458e8a..3c7e26d41370 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -1468,7 +1468,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
if (!MD->isStatic())
Arity++;
}
- // FALLTHROUGH
+ LLVM_FALLTHROUGH;
case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXLiteralOperatorName:
mangleOperatorName(Name, Arity);
diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp
index 17c95f2a0af7..088d8bedd453 100644
--- a/lib/AST/ODRHash.cpp
+++ b/lib/AST/ODRHash.cpp
@@ -466,8 +466,42 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) {
}
}
+void ODRHash::AddFunctionDecl(const FunctionDecl *Function) {
+ assert(Function && "Expecting non-null pointer.");
+
+ // Skip hashing these kinds of function.
+ if (Function->isImplicit()) return;
+ if (Function->isDefaulted()) return;
+ if (Function->isDeleted()) return;
+ if (!Function->hasBody()) return;
+ if (!Function->getBody()) return;
+
+ // TODO: Fix hashing for class methods.
+ if (isa<CXXMethodDecl>(Function)) return;
+
+ // Skip functions that are specializations or in specialization context.
+ const DeclContext *DC = Function;
+ while (DC) {
+ if (isa<ClassTemplateSpecializationDecl>(DC)) return;
+ if (auto *F = dyn_cast<FunctionDecl>(DC))
+ if (F->isFunctionTemplateSpecialization()) return;
+ DC = DC->getParent();
+ }
+
+ AddDecl(Function);
+
+ AddQualType(Function->getReturnType());
+
+ ID.AddInteger(Function->param_size());
+ for (auto Param : Function->parameters())
+ AddSubDecl(Param);
+
+ AddStmt(Function->getBody());
+}
+
void ODRHash::AddDecl(const Decl *D) {
assert(D && "Expecting non-null pointer.");
+ D = D->getCanonicalDecl();
auto Result = DeclMap.insert(std::make_pair(D, DeclMap.size()));
ID.AddInteger(Result.first->second);
// On first encounter of a Decl pointer, process it. Every time afterwards,
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index b05c5fc68096..0ac50b31acec 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -201,7 +201,7 @@ SourceLocation TypeLoc::getBeginLoc() const {
LeftMost = Cur;
break;
}
- /* Fall through */
+ LLVM_FALLTHROUGH;
case FunctionNoProto:
case ConstantArray:
case DependentSizedArray:
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 35e0b75f3c22..c28ada7dcb8b 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -213,7 +213,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::VariableArray:
case Type::DependentSizedArray:
NeedARCStrongQualifier = true;
- // Fall through
+ LLVM_FALLTHROUGH;
case Type::Adjusted:
case Type::Decayed:
@@ -1712,16 +1712,20 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
OS << ' ';
}
+std::string QualType::getAsString() const {
+ return getAsString(split(), LangOptions());
+}
+
std::string QualType::getAsString(const PrintingPolicy &Policy) const {
std::string S;
getAsStringInternal(S, Policy);
return S;
}
-std::string QualType::getAsString(const Type *ty, Qualifiers qs) {
+std::string QualType::getAsString(const Type *ty, Qualifiers qs,
+ const PrintingPolicy &Policy) {
std::string buffer;
- LangOptions options;
- getAsStringInternal(ty, qs, buffer, PrintingPolicy(options));
+ getAsStringInternal(ty, qs, buffer, Policy);
return buffer;
}
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 640b42c1ca2e..26baa838f8c6 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -363,7 +363,7 @@ void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor,
diag::Severity Map,
SourceLocation Loc) {
// Get all the diagnostics.
- SmallVector<diag::kind, 64> AllDiags;
+ std::vector<diag::kind> AllDiags;
DiagnosticIDs::getAllDiagnostics(Flavor, AllDiags);
// Set the mapping.
diff --git a/lib/Basic/DiagnosticIDs.cpp b/lib/Basic/DiagnosticIDs.cpp
index 5c53f35aa68f..c4c425d9eb1d 100644
--- a/lib/Basic/DiagnosticIDs.cpp
+++ b/lib/Basic/DiagnosticIDs.cpp
@@ -583,7 +583,7 @@ DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
}
void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor,
- SmallVectorImpl<diag::kind> &Diags) {
+ std::vector<diag::kind> &Diags) {
for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
if (StaticDiagInfo[i].getFlavor() == Flavor)
Diags.push_back(StaticDiagInfo[i].DiagID);
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index e664879639f3..0a51985614c8 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -125,11 +125,12 @@ llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
// possible.
if (!BufferOrError) {
StringRef FillStr("<<<MISSING SOURCE FILE>>>\n");
- Buffer.setPointer(MemoryBuffer::getNewUninitMemBuffer(
- ContentsEntry->getSize(), "<invalid>").release());
- char *Ptr = const_cast<char*>(Buffer.getPointer()->getBufferStart());
+ auto BackupBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
+ ContentsEntry->getSize(), "<invalid>");
+ char *Ptr = BackupBuffer->getBufferStart();
for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i)
Ptr[i] = FillStr[i % FillStr.size()];
+ Buffer.setPointer(BackupBuffer.release());
if (Diag.isDiagnosticInFlight())
Diag.SetDelayedDiagnostic(diag::err_cannot_open_file,
diff --git a/lib/Basic/Targets/AArch64.cpp b/lib/Basic/Targets/AArch64.cpp
index 62990dc23821..6080cefac744 100644
--- a/lib/Basic/Targets/AArch64.cpp
+++ b/lib/Basic/Targets/AArch64.cpp
@@ -181,6 +181,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
if (Unaligned)
Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
+ if ((FPU & NeonMode) && HasFullFP16)
+ Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
+
switch (ArchKind) {
default:
break;
diff --git a/lib/Basic/Targets/X86.cpp b/lib/Basic/Targets/X86.cpp
index 7fd9fd047818..bdf5cdb9407b 100644
--- a/lib/Basic/Targets/X86.cpp
+++ b/lib/Basic/Targets/X86.cpp
@@ -159,6 +159,7 @@ bool X86TargetInfo::initFeatureMap(
case CK_Broadwell:
setFeatureEnabledImpl(Features, "rdseed", true);
setFeatureEnabledImpl(Features, "adx", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
LLVM_FALLTHROUGH;
case CK_Haswell:
setFeatureEnabledImpl(Features, "avx2", true);
@@ -224,6 +225,7 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "aes", true);
setFeatureEnabledImpl(Features, "pclmul", true);
setFeatureEnabledImpl(Features, "sse4.2", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
LLVM_FALLTHROUGH;
case CK_Bonnell:
setFeatureEnabledImpl(Features, "movbe", true);
@@ -241,6 +243,7 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "avx512cd", true);
setFeatureEnabledImpl(Features, "avx512er", true);
setFeatureEnabledImpl(Features, "avx512pf", true);
+ setFeatureEnabledImpl(Features, "prfchw", true);
setFeatureEnabledImpl(Features, "prefetchwt1", true);
setFeatureEnabledImpl(Features, "fxsr", true);
setFeatureEnabledImpl(Features, "rdseed", true);
@@ -1131,6 +1134,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
return llvm::StringSwitch<bool>(Name)
.Case("3dnow", true)
.Case("3dnowa", true)
+ .Case("adx", true)
.Case("aes", true)
.Case("avx", true)
.Case("avx2", true)
@@ -1160,6 +1164,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
.Case("mmx", true)
.Case("movbe", true)
.Case("mpx", true)
+ .Case("mwaitx", true)
.Case("pclmul", true)
.Case("pku", true)
.Case("popcnt", true)
@@ -1170,6 +1175,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
.Case("rtm", true)
.Case("sgx", true)
.Case("sha", true)
+ .Case("shstk", true)
.Case("sse", true)
.Case("sse2", true)
.Case("sse3", true)
@@ -1190,6 +1196,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
bool X86TargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
+ .Case("adx", HasADX)
.Case("aes", HasAES)
.Case("avx", SSELevel >= AVX)
.Case("avx2", SSELevel >= AVX2)
@@ -1214,6 +1221,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("fma4", XOPLevel >= FMA4)
.Case("fsgsbase", HasFSGSBASE)
.Case("fxsr", HasFXSR)
+ .Case("ibt", HasIBT)
.Case("lwp", HasLWP)
.Case("lzcnt", HasLZCNT)
.Case("mm3dnow", MMX3DNowLevel >= AMD3DNow)
@@ -1221,8 +1229,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("mmx", MMX3DNowLevel >= MMX)
.Case("movbe", HasMOVBE)
.Case("mpx", HasMPX)
- .Case("shstk", HasSHSTK)
- .Case("ibt", HasIBT)
+ .Case("mwaitx", HasMWAITX)
.Case("pclmul", HasPCLMUL)
.Case("pku", HasPKU)
.Case("popcnt", HasPOPCNT)
@@ -1233,6 +1240,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("rtm", HasRTM)
.Case("sgx", HasSGX)
.Case("sha", HasSHA)
+ .Case("shstk", HasSHSTK)
.Case("sse", SSELevel >= SSE1)
.Case("sse2", SSELevel >= SSE2)
.Case("sse3", SSELevel >= SSE3)
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index 2c033e0f7c02..e2349da5f0a4 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -239,7 +239,11 @@ static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) {
- PM.add(createHWAddressSanitizerPass());
+ const PassManagerBuilderWrapper &BuilderWrapper =
+ static_cast<const PassManagerBuilderWrapper &>(Builder);
+ const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
+ bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::HWAddress);
+ PM.add(createHWAddressSanitizerPass(Recover));
}
static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp
index d90c3a53a635..6862fd811186 100644
--- a/lib/CodeGen/CGAtomic.cpp
+++ b/lib/CodeGen/CGAtomic.cpp
@@ -573,7 +573,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
case AtomicExpr::AO__atomic_add_fetch:
PostOp = llvm::Instruction::Add;
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_add:
case AtomicExpr::AO__opencl_atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_add:
@@ -582,7 +582,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
case AtomicExpr::AO__atomic_sub_fetch:
PostOp = llvm::Instruction::Sub;
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_sub:
case AtomicExpr::AO__opencl_atomic_fetch_sub:
case AtomicExpr::AO__atomic_fetch_sub:
@@ -601,7 +601,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
case AtomicExpr::AO__atomic_and_fetch:
PostOp = llvm::Instruction::And;
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__opencl_atomic_fetch_and:
case AtomicExpr::AO__atomic_fetch_and:
@@ -610,7 +610,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
case AtomicExpr::AO__atomic_or_fetch:
PostOp = llvm::Instruction::Or;
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__opencl_atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_or:
@@ -619,7 +619,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
case AtomicExpr::AO__atomic_xor_fetch:
PostOp = llvm::Instruction::Xor;
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_xor:
case AtomicExpr::AO__opencl_atomic_fetch_xor:
case AtomicExpr::AO__atomic_fetch_xor:
@@ -628,7 +628,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
case AtomicExpr::AO__atomic_nand_fetch:
PostOp = llvm::Instruction::And; // the NOT is special cased below
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__atomic_fetch_nand:
Op = llvm::AtomicRMWInst::Nand;
break;
@@ -828,7 +828,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
EmitStoreOfScalar(Val1Scalar, MakeAddrLValue(Temp, Val1Ty));
break;
}
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_sub:
case AtomicExpr::AO__atomic_add_fetch:
@@ -1035,7 +1035,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// T __atomic_fetch_add_N(T *mem, T val, int order)
case AtomicExpr::AO__atomic_add_fetch:
PostOp = llvm::Instruction::Add;
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_add:
case AtomicExpr::AO__opencl_atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_add:
@@ -1047,7 +1047,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// T __atomic_fetch_and_N(T *mem, T val, int order)
case AtomicExpr::AO__atomic_and_fetch:
PostOp = llvm::Instruction::And;
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__opencl_atomic_fetch_and:
case AtomicExpr::AO__atomic_fetch_and:
@@ -1059,7 +1059,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// T __atomic_fetch_or_N(T *mem, T val, int order)
case AtomicExpr::AO__atomic_or_fetch:
PostOp = llvm::Instruction::Or;
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__opencl_atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_or:
@@ -1071,7 +1071,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// T __atomic_fetch_sub_N(T *mem, T val, int order)
case AtomicExpr::AO__atomic_sub_fetch:
PostOp = llvm::Instruction::Sub;
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_sub:
case AtomicExpr::AO__opencl_atomic_fetch_sub:
case AtomicExpr::AO__atomic_fetch_sub:
@@ -1083,7 +1083,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// T __atomic_fetch_xor_N(T *mem, T val, int order)
case AtomicExpr::AO__atomic_xor_fetch:
PostOp = llvm::Instruction::Xor;
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_xor:
case AtomicExpr::AO__opencl_atomic_fetch_xor:
case AtomicExpr::AO__atomic_fetch_xor:
@@ -1109,7 +1109,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// T __atomic_fetch_nand_N(T *mem, T val, int order)
case AtomicExpr::AO__atomic_nand_fetch:
PostOp = llvm::Instruction::And; // the NOT is special cased below
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__atomic_fetch_nand:
LibCallName = "__atomic_fetch_nand";
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 3ecd1c6697d7..609987c4fa4c 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -1432,14 +1432,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__debugbreak:
return RValue::get(EmitTrapCall(Intrinsic::debugtrap));
case Builtin::BI__builtin_unreachable: {
- if (SanOpts.has(SanitizerKind::Unreachable)) {
- SanitizerScope SanScope(this);
- EmitCheck(std::make_pair(static_cast<llvm::Value *>(Builder.getFalse()),
- SanitizerKind::Unreachable),
- SanitizerHandler::BuiltinUnreachable,
- EmitCheckSourceLocation(E->getExprLoc()), None);
- } else
- Builder.CreateUnreachable();
+ EmitUnreachable(E->getExprLoc());
// We do need to preserve an insertion point.
EmitBlock(createBasicBlock("unreachable.cont"));
@@ -3341,10 +3334,10 @@ static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF,
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
- return CGF->EmitARMBuiltinExpr(BuiltinID, E);
+ return CGF->EmitARMBuiltinExpr(BuiltinID, E, Arch);
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
- return CGF->EmitAArch64BuiltinExpr(BuiltinID, E);
+ return CGF->EmitAArch64BuiltinExpr(BuiltinID, E, Arch);
case llvm::Triple::x86:
case llvm::Triple::x86_64:
return CGF->EmitX86BuiltinExpr(BuiltinID, E);
@@ -3385,6 +3378,7 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
static llvm::VectorType *GetNeonType(CodeGenFunction *CGF,
NeonTypeFlags TypeFlags,
+ llvm::Triple::ArchType Arch,
bool V1Ty=false) {
int IsQuad = TypeFlags.isQuad();
switch (TypeFlags.getEltType()) {
@@ -3393,8 +3387,14 @@ static llvm::VectorType *GetNeonType(CodeGenFunction *CGF,
return llvm::VectorType::get(CGF->Int8Ty, V1Ty ? 1 : (8 << IsQuad));
case NeonTypeFlags::Int16:
case NeonTypeFlags::Poly16:
- case NeonTypeFlags::Float16:
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)
+ return llvm::VectorType::get(CGF->HalfTy, V1Ty ? 1 : (4 << IsQuad));
+ else
+ return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
case NeonTypeFlags::Int32:
return llvm::VectorType::get(CGF->Int32Ty, V1Ty ? 1 : (2 << IsQuad));
case NeonTypeFlags::Int64:
@@ -3417,6 +3417,8 @@ static llvm::VectorType *GetFloatNeonType(CodeGenFunction *CGF,
NeonTypeFlags IntTypeFlags) {
int IsQuad = IntTypeFlags.isQuad();
switch (IntTypeFlags.getEltType()) {
+ case NeonTypeFlags::Int16:
+ return llvm::VectorType::get(CGF->HalfTy, (4 << IsQuad));
case NeonTypeFlags::Int32:
return llvm::VectorType::get(CGF->FloatTy, (2 << IsQuad));
case NeonTypeFlags::Int64:
@@ -3564,55 +3566,80 @@ static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP1(vcvt_f16_f32, arm_neon_vcvtfp2hf, 0),
NEONMAP1(vcvt_f32_f16, arm_neon_vcvthf2fp, 0),
NEONMAP0(vcvt_f32_v),
+ NEONMAP2(vcvt_n_f16_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvt_n_f32_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
+ NEONMAP1(vcvt_n_s16_v, arm_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvt_n_s32_v, arm_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvt_n_s64_v, arm_neon_vcvtfp2fxs, 0),
+ NEONMAP1(vcvt_n_u16_v, arm_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvt_n_u32_v, arm_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvt_n_u64_v, arm_neon_vcvtfp2fxu, 0),
+ NEONMAP0(vcvt_s16_v),
NEONMAP0(vcvt_s32_v),
NEONMAP0(vcvt_s64_v),
+ NEONMAP0(vcvt_u16_v),
NEONMAP0(vcvt_u32_v),
NEONMAP0(vcvt_u64_v),
+ NEONMAP1(vcvta_s16_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvta_s32_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvta_s64_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvta_u32_v, arm_neon_vcvtau, 0),
NEONMAP1(vcvta_u64_v, arm_neon_vcvtau, 0),
+ NEONMAP1(vcvtaq_s16_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvtaq_s32_v, arm_neon_vcvtas, 0),
NEONMAP1(vcvtaq_s64_v, arm_neon_vcvtas, 0),
+ NEONMAP1(vcvtaq_u16_v, arm_neon_vcvtau, 0),
NEONMAP1(vcvtaq_u32_v, arm_neon_vcvtau, 0),
NEONMAP1(vcvtaq_u64_v, arm_neon_vcvtau, 0),
+ NEONMAP1(vcvtm_s16_v, arm_neon_vcvtms, 0),
NEONMAP1(vcvtm_s32_v, arm_neon_vcvtms, 0),
NEONMAP1(vcvtm_s64_v, arm_neon_vcvtms, 0),
+ NEONMAP1(vcvtm_u16_v, arm_neon_vcvtmu, 0),
NEONMAP1(vcvtm_u32_v, arm_neon_vcvtmu, 0),
NEONMAP1(vcvtm_u64_v, arm_neon_vcvtmu, 0),
+ NEONMAP1(vcvtmq_s16_v, arm_neon_vcvtms, 0),
NEONMAP1(vcvtmq_s32_v, arm_neon_vcvtms, 0),
NEONMAP1(vcvtmq_s64_v, arm_neon_vcvtms, 0),
+ NEONMAP1(vcvtmq_u16_v, arm_neon_vcvtmu, 0),
NEONMAP1(vcvtmq_u32_v, arm_neon_vcvtmu, 0),
NEONMAP1(vcvtmq_u64_v, arm_neon_vcvtmu, 0),
+ NEONMAP1(vcvtn_s16_v, arm_neon_vcvtns, 0),
NEONMAP1(vcvtn_s32_v, arm_neon_vcvtns, 0),
NEONMAP1(vcvtn_s64_v, arm_neon_vcvtns, 0),
+ NEONMAP1(vcvtn_u16_v, arm_neon_vcvtnu, 0),
NEONMAP1(vcvtn_u32_v, arm_neon_vcvtnu, 0),
NEONMAP1(vcvtn_u64_v, arm_neon_vcvtnu, 0),
+ NEONMAP1(vcvtnq_s16_v, arm_neon_vcvtns, 0),
NEONMAP1(vcvtnq_s32_v, arm_neon_vcvtns, 0),
NEONMAP1(vcvtnq_s64_v, arm_neon_vcvtns, 0),
+ NEONMAP1(vcvtnq_u16_v, arm_neon_vcvtnu, 0),
NEONMAP1(vcvtnq_u32_v, arm_neon_vcvtnu, 0),
NEONMAP1(vcvtnq_u64_v, arm_neon_vcvtnu, 0),
+ NEONMAP1(vcvtp_s16_v, arm_neon_vcvtps, 0),
NEONMAP1(vcvtp_s32_v, arm_neon_vcvtps, 0),
NEONMAP1(vcvtp_s64_v, arm_neon_vcvtps, 0),
+ NEONMAP1(vcvtp_u16_v, arm_neon_vcvtpu, 0),
NEONMAP1(vcvtp_u32_v, arm_neon_vcvtpu, 0),
NEONMAP1(vcvtp_u64_v, arm_neon_vcvtpu, 0),
+ NEONMAP1(vcvtpq_s16_v, arm_neon_vcvtps, 0),
NEONMAP1(vcvtpq_s32_v, arm_neon_vcvtps, 0),
NEONMAP1(vcvtpq_s64_v, arm_neon_vcvtps, 0),
+ 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_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),
+ NEONMAP1(vcvtq_n_s16_v, arm_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvtq_n_s32_v, arm_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvtq_n_s64_v, arm_neon_vcvtfp2fxs, 0),
+ NEONMAP1(vcvtq_n_u16_v, arm_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvtq_n_u32_v, arm_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvtq_n_u64_v, arm_neon_vcvtfp2fxu, 0),
+ NEONMAP0(vcvtq_s16_v),
NEONMAP0(vcvtq_s32_v),
NEONMAP0(vcvtq_s64_v),
+ NEONMAP0(vcvtq_u16_v),
NEONMAP0(vcvtq_u32_v),
NEONMAP0(vcvtq_u64_v),
NEONMAP0(vext_v),
@@ -3775,19 +3802,27 @@ static const NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
NEONMAP1(vcnt_v, ctpop, Add1ArgType),
NEONMAP1(vcntq_v, ctpop, Add1ArgType),
NEONMAP1(vcvt_f16_f32, aarch64_neon_vcvtfp2hf, 0),
+ NEONMAP0(vcvt_f16_v),
NEONMAP1(vcvt_f32_f16, aarch64_neon_vcvthf2fp, 0),
NEONMAP0(vcvt_f32_v),
+ NEONMAP2(vcvt_n_f16_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvt_n_f32_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvt_n_f64_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
+ NEONMAP1(vcvt_n_s16_v, aarch64_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvt_n_s32_v, aarch64_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvt_n_s64_v, aarch64_neon_vcvtfp2fxs, 0),
+ NEONMAP1(vcvt_n_u16_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvt_n_u32_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvt_n_u64_v, aarch64_neon_vcvtfp2fxu, 0),
+ NEONMAP0(vcvtq_f16_v),
NEONMAP0(vcvtq_f32_v),
+ NEONMAP2(vcvtq_n_f16_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvtq_n_f32_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
NEONMAP2(vcvtq_n_f64_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
+ NEONMAP1(vcvtq_n_s16_v, aarch64_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvtq_n_s32_v, aarch64_neon_vcvtfp2fxs, 0),
NEONMAP1(vcvtq_n_s64_v, aarch64_neon_vcvtfp2fxs, 0),
+ NEONMAP1(vcvtq_n_u16_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvtq_n_u32_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvtq_n_u64_v, aarch64_neon_vcvtfp2fxu, 0),
NEONMAP1(vcvtx_f32_v, aarch64_neon_fcvtxn, AddRetType | Add1ArgType),
@@ -4197,7 +4232,8 @@ static Value *EmitCommonNeonSISDBuiltinExpr(CodeGenFunction &CGF,
Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
unsigned BuiltinID, unsigned LLVMIntrinsic, unsigned AltLLVMIntrinsic,
const char *NameHint, unsigned Modifier, const CallExpr *E,
- SmallVectorImpl<llvm::Value *> &Ops, Address PtrOp0, Address PtrOp1) {
+ SmallVectorImpl<llvm::Value *> &Ops, Address PtrOp0, Address PtrOp1,
+ llvm::Triple::ArchType Arch) {
// Get the last argument, which specifies the vector type.
llvm::APSInt NeonTypeConst;
const Expr *Arg = E->getArg(E->getNumArgs() - 1);
@@ -4209,7 +4245,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
bool Usgn = Type.isUnsigned();
bool Quad = Type.isQuad();
- llvm::VectorType *VTy = GetNeonType(this, Type);
+ llvm::VectorType *VTy = GetNeonType(this, Type, Arch);
llvm::Type *Ty = VTy;
if (!Ty)
return nullptr;
@@ -4256,9 +4292,20 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vcageq_v:
case NEON::BI__builtin_neon_vcagt_v:
case NEON::BI__builtin_neon_vcagtq_v: {
- llvm::Type *VecFlt = llvm::VectorType::get(
- VTy->getScalarSizeInBits() == 32 ? FloatTy : DoubleTy,
- VTy->getNumElements());
+ llvm::Type *Ty;
+ switch (VTy->getScalarSizeInBits()) {
+ default: llvm_unreachable("unexpected type");
+ case 32:
+ Ty = FloatTy;
+ break;
+ case 64:
+ Ty = DoubleTy;
+ break;
+ case 16:
+ Ty = HalfTy;
+ break;
+ }
+ llvm::Type *VecFlt = llvm::VectorType::get(Ty, VTy->getNumElements());
llvm::Type *Tys[] = { VTy, VecFlt };
Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
return EmitNeonCall(F, Ops, NameHint);
@@ -4272,11 +4319,19 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
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));
+ Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, Quad), Arch);
+ 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);
return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
+ case NEON::BI__builtin_neon_vcvt_n_f16_v:
case NEON::BI__builtin_neon_vcvt_n_f32_v:
case NEON::BI__builtin_neon_vcvt_n_f64_v:
+ case NEON::BI__builtin_neon_vcvtq_n_f16_v:
case NEON::BI__builtin_neon_vcvtq_n_f32_v:
case NEON::BI__builtin_neon_vcvtq_n_f64_v: {
llvm::Type *Tys[2] = { GetFloatNeonType(this, Type), Ty };
@@ -4284,11 +4339,15 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Function *F = CGM.getIntrinsic(Int, Tys);
return EmitNeonCall(F, Ops, "vcvt_n");
}
+ case NEON::BI__builtin_neon_vcvt_n_s16_v:
case NEON::BI__builtin_neon_vcvt_n_s32_v:
+ case NEON::BI__builtin_neon_vcvt_n_u16_v:
case NEON::BI__builtin_neon_vcvt_n_u32_v:
case NEON::BI__builtin_neon_vcvt_n_s64_v:
case NEON::BI__builtin_neon_vcvt_n_u64_v:
+ case NEON::BI__builtin_neon_vcvtq_n_s16_v:
case NEON::BI__builtin_neon_vcvtq_n_s32_v:
+ case NEON::BI__builtin_neon_vcvtq_n_u16_v:
case NEON::BI__builtin_neon_vcvtq_n_u32_v:
case NEON::BI__builtin_neon_vcvtq_n_s64_v:
case NEON::BI__builtin_neon_vcvtq_n_u64_v: {
@@ -4300,44 +4359,63 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vcvt_u32_v:
case NEON::BI__builtin_neon_vcvt_s64_v:
case NEON::BI__builtin_neon_vcvt_u64_v:
+ case NEON::BI__builtin_neon_vcvt_s16_v:
+ case NEON::BI__builtin_neon_vcvt_u16_v:
case NEON::BI__builtin_neon_vcvtq_s32_v:
case NEON::BI__builtin_neon_vcvtq_u32_v:
case NEON::BI__builtin_neon_vcvtq_s64_v:
- case NEON::BI__builtin_neon_vcvtq_u64_v: {
+ case NEON::BI__builtin_neon_vcvtq_u64_v:
+ case NEON::BI__builtin_neon_vcvtq_s16_v:
+ case NEON::BI__builtin_neon_vcvtq_u16_v: {
Ops[0] = Builder.CreateBitCast(Ops[0], GetFloatNeonType(this, Type));
return Usgn ? Builder.CreateFPToUI(Ops[0], Ty, "vcvt")
: Builder.CreateFPToSI(Ops[0], Ty, "vcvt");
}
+ case NEON::BI__builtin_neon_vcvta_s16_v:
case NEON::BI__builtin_neon_vcvta_s32_v:
case NEON::BI__builtin_neon_vcvta_s64_v:
case NEON::BI__builtin_neon_vcvta_u32_v:
case NEON::BI__builtin_neon_vcvta_u64_v:
+ case NEON::BI__builtin_neon_vcvtaq_s16_v:
case NEON::BI__builtin_neon_vcvtaq_s32_v:
case NEON::BI__builtin_neon_vcvtaq_s64_v:
+ case NEON::BI__builtin_neon_vcvtaq_u16_v:
case NEON::BI__builtin_neon_vcvtaq_u32_v:
case NEON::BI__builtin_neon_vcvtaq_u64_v:
+ case NEON::BI__builtin_neon_vcvtn_s16_v:
case NEON::BI__builtin_neon_vcvtn_s32_v:
case NEON::BI__builtin_neon_vcvtn_s64_v:
+ case NEON::BI__builtin_neon_vcvtn_u16_v:
case NEON::BI__builtin_neon_vcvtn_u32_v:
case NEON::BI__builtin_neon_vcvtn_u64_v:
+ case NEON::BI__builtin_neon_vcvtnq_s16_v:
case NEON::BI__builtin_neon_vcvtnq_s32_v:
case NEON::BI__builtin_neon_vcvtnq_s64_v:
+ case NEON::BI__builtin_neon_vcvtnq_u16_v:
case NEON::BI__builtin_neon_vcvtnq_u32_v:
case NEON::BI__builtin_neon_vcvtnq_u64_v:
+ case NEON::BI__builtin_neon_vcvtp_s16_v:
case NEON::BI__builtin_neon_vcvtp_s32_v:
case NEON::BI__builtin_neon_vcvtp_s64_v:
+ case NEON::BI__builtin_neon_vcvtp_u16_v:
case NEON::BI__builtin_neon_vcvtp_u32_v:
case NEON::BI__builtin_neon_vcvtp_u64_v:
+ case NEON::BI__builtin_neon_vcvtpq_s16_v:
case NEON::BI__builtin_neon_vcvtpq_s32_v:
case NEON::BI__builtin_neon_vcvtpq_s64_v:
+ case NEON::BI__builtin_neon_vcvtpq_u16_v:
case NEON::BI__builtin_neon_vcvtpq_u32_v:
case NEON::BI__builtin_neon_vcvtpq_u64_v:
+ case NEON::BI__builtin_neon_vcvtm_s16_v:
case NEON::BI__builtin_neon_vcvtm_s32_v:
case NEON::BI__builtin_neon_vcvtm_s64_v:
+ case NEON::BI__builtin_neon_vcvtm_u16_v:
case NEON::BI__builtin_neon_vcvtm_u32_v:
case NEON::BI__builtin_neon_vcvtm_u64_v:
+ case NEON::BI__builtin_neon_vcvtmq_s16_v:
case NEON::BI__builtin_neon_vcvtmq_s32_v:
case NEON::BI__builtin_neon_vcvtmq_s64_v:
+ case NEON::BI__builtin_neon_vcvtmq_u16_v:
case NEON::BI__builtin_neon_vcvtmq_u32_v:
case NEON::BI__builtin_neon_vcvtmq_u64_v: {
llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
@@ -4816,7 +4894,8 @@ static bool HasExtraNeonArgument(unsigned BuiltinID) {
}
Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
- const CallExpr *E) {
+ const CallExpr *E,
+ llvm::Triple::ArchType Arch) {
if (auto Hint = GetValueForARMHint(BuiltinID))
return Hint;
@@ -5355,7 +5434,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
bool usgn = Type.isUnsigned();
bool rightShift = false;
- llvm::VectorType *VTy = GetNeonType(this, Type);
+ llvm::VectorType *VTy = GetNeonType(this, Type, Arch);
llvm::Type *Ty = VTy;
if (!Ty)
return nullptr;
@@ -5368,7 +5447,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
if (Builtin)
return EmitCommonNeonBuiltinExpr(
Builtin->BuiltinID, Builtin->LLVMIntrinsic, Builtin->AltLLVMIntrinsic,
- Builtin->NameHint, Builtin->TypeModifier, E, Ops, PtrOp0, PtrOp1);
+ Builtin->NameHint, Builtin->TypeModifier, E, Ops, PtrOp0, PtrOp1, Arch);
unsigned Int;
switch (BuiltinID) {
@@ -5393,7 +5472,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
SV = llvm::ConstantDataVector::get(getLLVMContext(), Indices);
return Builder.CreateShuffleVector(Ops[1], Ld, SV, "vld1q_lane");
}
- // fall through
+ LLVM_FALLTHROUGH;
case NEON::BI__builtin_neon_vld1_lane_v: {
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
PtrOp0 = Builder.CreateElementBitCast(PtrOp0, VTy->getElementType());
@@ -5518,7 +5597,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst1,
Tys), Ops);
}
- // fall through
+ LLVM_FALLTHROUGH;
case NEON::BI__builtin_neon_vst1_lane_v: {
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]);
@@ -5555,7 +5634,8 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID,
const CallExpr *E,
- SmallVectorImpl<Value *> &Ops) {
+ SmallVectorImpl<Value *> &Ops,
+ llvm::Triple::ArchType Arch) {
unsigned int Int = 0;
const char *s = nullptr;
@@ -5600,7 +5680,7 @@ static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID
// Determine the type of this overloaded NEON intrinsic.
NeonTypeFlags Type(Result.getZExtValue());
- llvm::VectorType *Ty = GetNeonType(&CGF, Type);
+ llvm::VectorType *Ty = GetNeonType(&CGF, Type, Arch);
if (!Ty)
return nullptr;
@@ -5710,7 +5790,8 @@ Value *CodeGenFunction::vectorWrapScalar16(Value *Op) {
}
Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
- const CallExpr *E) {
+ const CallExpr *E,
+ llvm::Triple::ArchType Arch) {
unsigned HintID = static_cast<unsigned>(-1);
switch (BuiltinID) {
default: break;
@@ -6011,7 +6092,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcvts_u32_f32:
case NEON::BI__builtin_neon_vcvtd_u64_f64:
usgn = true;
- // FALL THROUGH
+ LLVM_FALLTHROUGH;
case NEON::BI__builtin_neon_vcvts_s32_f32:
case NEON::BI__builtin_neon_vcvtd_s64_f64: {
Ops.push_back(EmitScalarExpr(E->getArg(0)));
@@ -6026,7 +6107,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcvts_f32_u32:
case NEON::BI__builtin_neon_vcvtd_f64_u64:
usgn = true;
- // FALL THROUGH
+ LLVM_FALLTHROUGH;
case NEON::BI__builtin_neon_vcvts_f32_s32:
case NEON::BI__builtin_neon_vcvtd_f64_s64: {
Ops.push_back(EmitScalarExpr(E->getArg(0)));
@@ -6453,7 +6534,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
}
- llvm::VectorType *VTy = GetNeonType(this, Type);
+ llvm::VectorType *VTy = GetNeonType(this, Type, Arch);
llvm::Type *Ty = VTy;
if (!Ty)
return nullptr;
@@ -6467,9 +6548,9 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
return EmitCommonNeonBuiltinExpr(
Builtin->BuiltinID, Builtin->LLVMIntrinsic, Builtin->AltLLVMIntrinsic,
Builtin->NameHint, Builtin->TypeModifier, E, Ops,
- /*never use addresses*/ Address::invalid(), Address::invalid());
+ /*never use addresses*/ Address::invalid(), Address::invalid(), Arch);
- if (Value *V = EmitAArch64TblBuiltinExpr(*this, BuiltinID, E, Ops))
+ if (Value *V = EmitAArch64TblBuiltinExpr(*this, BuiltinID, E, Ops, Arch))
return V;
unsigned Int;
@@ -6518,7 +6599,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy);
llvm::Type *VTy = GetNeonType(this,
- NeonTypeFlags(NeonTypeFlags::Float64, false, true));
+ NeonTypeFlags(NeonTypeFlags::Float64, false, true), Arch);
Ops[2] = Builder.CreateBitCast(Ops[2], VTy);
Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
Value *F = CGM.getIntrinsic(Intrinsic::fma, DoubleTy);
@@ -6547,7 +6628,9 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[2] = EmitNeonSplat(Ops[2], cast<ConstantInt>(Ops[3]));
return Builder.CreateCall(F, {Ops[2], Ops[1], Ops[0]});
}
+ case NEON::BI__builtin_neon_vfmah_lane_f16:
case NEON::BI__builtin_neon_vfmas_lane_f32:
+ case NEON::BI__builtin_neon_vfmah_laneq_f16:
case NEON::BI__builtin_neon_vfmas_laneq_f32:
case NEON::BI__builtin_neon_vfmad_lane_f64:
case NEON::BI__builtin_neon_vfmad_laneq_f64: {
@@ -6699,14 +6782,14 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
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));
+ Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad), Arch);
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));
+ Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag, Arch));
return Builder.CreateFPExt(Ops[0], Ty, "vcvt");
}
@@ -6714,7 +6797,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
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));
+ Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(this, SrcFlag, Arch));
return Builder.CreateFPTrunc(Ops[0], Ty, "vcvt");
}
@@ -6722,18 +6805,25 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcvt_u32_v:
case NEON::BI__builtin_neon_vcvt_s64_v:
case NEON::BI__builtin_neon_vcvt_u64_v:
+ case NEON::BI__builtin_neon_vcvt_s16_v:
+ case NEON::BI__builtin_neon_vcvt_u16_v:
case NEON::BI__builtin_neon_vcvtq_s32_v:
case NEON::BI__builtin_neon_vcvtq_u32_v:
case NEON::BI__builtin_neon_vcvtq_s64_v:
- case NEON::BI__builtin_neon_vcvtq_u64_v: {
+ case NEON::BI__builtin_neon_vcvtq_u64_v:
+ case NEON::BI__builtin_neon_vcvtq_s16_v:
+ case NEON::BI__builtin_neon_vcvtq_u16_v: {
Ops[0] = Builder.CreateBitCast(Ops[0], GetFloatNeonType(this, Type));
if (usgn)
return Builder.CreateFPToUI(Ops[0], Ty);
return Builder.CreateFPToSI(Ops[0], Ty);
}
+ case NEON::BI__builtin_neon_vcvta_s16_v:
case NEON::BI__builtin_neon_vcvta_s32_v:
+ case NEON::BI__builtin_neon_vcvtaq_s16_v:
case NEON::BI__builtin_neon_vcvtaq_s32_v:
case NEON::BI__builtin_neon_vcvta_u32_v:
+ case NEON::BI__builtin_neon_vcvtaq_u16_v:
case NEON::BI__builtin_neon_vcvtaq_u32_v:
case NEON::BI__builtin_neon_vcvta_s64_v:
case NEON::BI__builtin_neon_vcvtaq_s64_v:
@@ -6743,9 +6833,13 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvta");
}
+ case NEON::BI__builtin_neon_vcvtm_s16_v:
case NEON::BI__builtin_neon_vcvtm_s32_v:
+ case NEON::BI__builtin_neon_vcvtmq_s16_v:
case NEON::BI__builtin_neon_vcvtmq_s32_v:
+ case NEON::BI__builtin_neon_vcvtm_u16_v:
case NEON::BI__builtin_neon_vcvtm_u32_v:
+ case NEON::BI__builtin_neon_vcvtmq_u16_v:
case NEON::BI__builtin_neon_vcvtmq_u32_v:
case NEON::BI__builtin_neon_vcvtm_s64_v:
case NEON::BI__builtin_neon_vcvtmq_s64_v:
@@ -6755,9 +6849,13 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtm");
}
+ case NEON::BI__builtin_neon_vcvtn_s16_v:
case NEON::BI__builtin_neon_vcvtn_s32_v:
+ case NEON::BI__builtin_neon_vcvtnq_s16_v:
case NEON::BI__builtin_neon_vcvtnq_s32_v:
+ case NEON::BI__builtin_neon_vcvtn_u16_v:
case NEON::BI__builtin_neon_vcvtn_u32_v:
+ case NEON::BI__builtin_neon_vcvtnq_u16_v:
case NEON::BI__builtin_neon_vcvtnq_u32_v:
case NEON::BI__builtin_neon_vcvtn_s64_v:
case NEON::BI__builtin_neon_vcvtnq_s64_v:
@@ -6767,9 +6865,13 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtn");
}
+ case NEON::BI__builtin_neon_vcvtp_s16_v:
case NEON::BI__builtin_neon_vcvtp_s32_v:
+ case NEON::BI__builtin_neon_vcvtpq_s16_v:
case NEON::BI__builtin_neon_vcvtpq_s32_v:
+ case NEON::BI__builtin_neon_vcvtp_u16_v:
case NEON::BI__builtin_neon_vcvtp_u32_v:
+ case NEON::BI__builtin_neon_vcvtpq_u16_v:
case NEON::BI__builtin_neon_vcvtpq_u32_v:
case NEON::BI__builtin_neon_vcvtp_s64_v:
case NEON::BI__builtin_neon_vcvtpq_s64_v:
@@ -6792,7 +6894,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Quad = true;
Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
llvm::Type *VTy = GetNeonType(this,
- NeonTypeFlags(NeonTypeFlags::Float64, false, Quad));
+ NeonTypeFlags(NeonTypeFlags::Float64, false, Quad), Arch);
Ops[1] = Builder.CreateBitCast(Ops[1], VTy);
Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract");
Value *Result = Builder.CreateFMul(Ops[0], Ops[1]);
@@ -6824,7 +6926,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vaddv_u8:
// FIXME: These are handled by the AArch64 scalar code.
usgn = true;
- // FALLTHROUGH
+ LLVM_FALLTHROUGH;
case NEON::BI__builtin_neon_vaddv_s8: {
Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv;
Ty = Int32Ty;
@@ -6836,7 +6938,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
case NEON::BI__builtin_neon_vaddv_u16:
usgn = true;
- // FALLTHROUGH
+ LLVM_FALLTHROUGH;
case NEON::BI__builtin_neon_vaddv_s16: {
Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv;
Ty = Int32Ty;
@@ -6848,7 +6950,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
case NEON::BI__builtin_neon_vaddvq_u8:
usgn = true;
- // FALLTHROUGH
+ LLVM_FALLTHROUGH;
case NEON::BI__builtin_neon_vaddvq_s8: {
Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv;
Ty = Int32Ty;
@@ -6860,7 +6962,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
case NEON::BI__builtin_neon_vaddvq_u16:
usgn = true;
- // FALLTHROUGH
+ LLVM_FALLTHROUGH;
case NEON::BI__builtin_neon_vaddvq_s16: {
Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv;
Ty = Int32Ty;
@@ -6942,6 +7044,24 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
return Builder.CreateTrunc(Ops[0], Int16Ty);
}
+ case NEON::BI__builtin_neon_vmaxv_f16: {
+ Int = Intrinsic::aarch64_neon_fmaxv;
+ Ty = HalfTy;
+ VTy = llvm::VectorType::get(HalfTy, 4);
+ llvm::Type *Tys[2] = { Ty, VTy };
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
+ return Builder.CreateTrunc(Ops[0], HalfTy);
+ }
+ case NEON::BI__builtin_neon_vmaxvq_f16: {
+ Int = Intrinsic::aarch64_neon_fmaxv;
+ Ty = HalfTy;
+ VTy = llvm::VectorType::get(HalfTy, 8);
+ llvm::Type *Tys[2] = { Ty, VTy };
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
+ return Builder.CreateTrunc(Ops[0], HalfTy);
+ }
case NEON::BI__builtin_neon_vminv_u8: {
Int = Intrinsic::aarch64_neon_uminv;
Ty = Int32Ty;
@@ -7014,6 +7134,60 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
return Builder.CreateTrunc(Ops[0], Int16Ty);
}
+ case NEON::BI__builtin_neon_vminv_f16: {
+ Int = Intrinsic::aarch64_neon_fminv;
+ Ty = HalfTy;
+ VTy = llvm::VectorType::get(HalfTy, 4);
+ llvm::Type *Tys[2] = { Ty, VTy };
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
+ return Builder.CreateTrunc(Ops[0], HalfTy);
+ }
+ case NEON::BI__builtin_neon_vminvq_f16: {
+ Int = Intrinsic::aarch64_neon_fminv;
+ Ty = HalfTy;
+ VTy = llvm::VectorType::get(HalfTy, 8);
+ llvm::Type *Tys[2] = { Ty, VTy };
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
+ return Builder.CreateTrunc(Ops[0], HalfTy);
+ }
+ case NEON::BI__builtin_neon_vmaxnmv_f16: {
+ Int = Intrinsic::aarch64_neon_fmaxnmv;
+ Ty = HalfTy;
+ VTy = llvm::VectorType::get(HalfTy, 4);
+ llvm::Type *Tys[2] = { Ty, VTy };
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxnmv");
+ return Builder.CreateTrunc(Ops[0], HalfTy);
+ }
+ case NEON::BI__builtin_neon_vmaxnmvq_f16: {
+ Int = Intrinsic::aarch64_neon_fmaxnmv;
+ Ty = HalfTy;
+ VTy = llvm::VectorType::get(HalfTy, 8);
+ llvm::Type *Tys[2] = { Ty, VTy };
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxnmv");
+ return Builder.CreateTrunc(Ops[0], HalfTy);
+ }
+ case NEON::BI__builtin_neon_vminnmv_f16: {
+ Int = Intrinsic::aarch64_neon_fminnmv;
+ Ty = HalfTy;
+ VTy = llvm::VectorType::get(HalfTy, 4);
+ llvm::Type *Tys[2] = { Ty, VTy };
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminnmv");
+ return Builder.CreateTrunc(Ops[0], HalfTy);
+ }
+ case NEON::BI__builtin_neon_vminnmvq_f16: {
+ Int = Intrinsic::aarch64_neon_fminnmv;
+ Ty = HalfTy;
+ VTy = llvm::VectorType::get(HalfTy, 8);
+ llvm::Type *Tys[2] = { Ty, VTy };
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminnmv");
+ return Builder.CreateTrunc(Ops[0], HalfTy);
+ }
case NEON::BI__builtin_neon_vmul_n_f64: {
Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
Value *RHS = Builder.CreateBitCast(EmitScalarExpr(E->getArg(1)), DoubleTy);
@@ -7848,8 +8022,9 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
default: return nullptr;
case X86::BI_mm_prefetch: {
Value *Address = Ops[0];
- Value *RW = ConstantInt::get(Int32Ty, 0);
- Value *Locality = Ops[1];
+ ConstantInt *C = cast<ConstantInt>(Ops[1]);
+ Value *RW = ConstantInt::get(Int32Ty, (C->getZExtValue() >> 2) & 0x1);
+ Value *Locality = ConstantInt::get(Int32Ty, C->getZExtValue() & 0x3);
Value *Data = ConstantInt::get(Int32Ty, 1);
Value *F = CGM.getIntrinsic(Intrinsic::prefetch);
return Builder.CreateCall(F, {Address, RW, Locality, Data});
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index c3709bf2e447..38d7344572d3 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -1929,7 +1929,7 @@ void CodeGenModule::ConstructAttributeList(
RetAttrs.addAttribute(llvm::Attribute::SExt);
else if (RetTy->hasUnsignedIntegerRepresentation())
RetAttrs.addAttribute(llvm::Attribute::ZExt);
- // FALL THROUGH
+ LLVM_FALLTHROUGH;
case ABIArgInfo::Direct:
if (RetAI.getInReg())
RetAttrs.addAttribute(llvm::Attribute::InReg);
@@ -2014,7 +2014,7 @@ void CodeGenModule::ConstructAttributeList(
else
Attrs.addAttribute(llvm::Attribute::ZExt);
}
- // FALL THROUGH
+ LLVM_FALLTHROUGH;
case ABIArgInfo::Direct:
if (ArgNo == 0 && FI.isChainCall())
Attrs.addAttribute(llvm::Attribute::Nest);
@@ -2758,6 +2758,12 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) {
void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
bool EmitRetDbgLoc,
SourceLocation EndLoc) {
+ if (FI.isNoReturn()) {
+ // Noreturn functions don't return.
+ EmitUnreachable(EndLoc);
+ return;
+ }
+
if (CurCodeDecl && CurCodeDecl->hasAttr<NakedAttr>()) {
// Naked functions don't have epilogues.
Builder.CreateUnreachable();
@@ -3718,7 +3724,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
const CGCallee &Callee,
ReturnValueSlot ReturnValue,
const CallArgList &CallArgs,
- llvm::Instruction **callOrInvoke) {
+ llvm::Instruction **callOrInvoke,
+ SourceLocation Loc) {
// FIXME: We no longer need the types from CallArgs; lift up and simplify.
assert(Callee.isOrdinary());
@@ -4241,7 +4248,15 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
SRetPtr.getPointer());
- Builder.CreateUnreachable();
+ // Strip away the noreturn attribute to better diagnose unreachable UB.
+ if (SanOpts.has(SanitizerKind::Unreachable)) {
+ if (auto *F = CS.getCalledFunction())
+ F->removeFnAttr(llvm::Attribute::NoReturn);
+ CS.removeAttribute(llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::NoReturn);
+ }
+
+ EmitUnreachable(Loc);
Builder.ClearInsertionPoint();
// FIXME: For now, emit a dummy basic block because expr emitters in
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index caea41ec0e03..aeed4d658a4e 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -2653,7 +2653,6 @@ llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) {
// file where the type's definition is located, so it might be
// best to make this behavior a command line or debugger tuning
// option.
- FullSourceLoc Loc(D->getLocation(), CGM.getContext().getSourceManager());
if (Module *M = D->getOwningModule()) {
// This is a (sub-)module.
auto Info = ExternalASTSource::ASTSourceDescriptor(*M);
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 6c9d9f170ace..1ec084ff3f5b 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -133,7 +133,7 @@ static const EHPersonality &getObjCPersonality(const llvm::Triple &T,
case ObjCRuntime::GNUstep:
if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
return EHPersonality::GNUstep_ObjC;
- // fallthrough
+ LLVM_FALLTHROUGH;
case ObjCRuntime::GCC:
case ObjCRuntime::ObjFW:
if (L.SjLjExceptions)
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 98740e8f9aab..90eeddf5cc0b 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -3076,6 +3076,17 @@ void CodeGenFunction::EmitCfiCheckFail() {
CGM.addUsedGlobal(F);
}
+void CodeGenFunction::EmitUnreachable(SourceLocation Loc) {
+ if (SanOpts.has(SanitizerKind::Unreachable)) {
+ SanitizerScope SanScope(this);
+ EmitCheck(std::make_pair(static_cast<llvm::Value *>(Builder.getFalse()),
+ SanitizerKind::Unreachable),
+ SanitizerHandler::BuiltinUnreachable,
+ EmitCheckSourceLocation(Loc), None);
+ }
+ Builder.CreateUnreachable();
+}
+
void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) {
llvm::BasicBlock *Cont = createBasicBlock("cont");
@@ -3790,8 +3801,10 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
FieldTBAAInfo.Offset +=
Layout.getFieldOffset(field->getFieldIndex()) / CharWidth;
- // Update the final access type.
+ // Update the final access type and size.
FieldTBAAInfo.AccessType = CGM.getTBAATypeInfo(FieldType);
+ FieldTBAAInfo.Size =
+ getContext().getTypeSizeInChars(FieldType).getQuantity();
}
Address addr = base.getAddress();
@@ -4616,7 +4629,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
Callee.setFunctionPointer(CalleePtr);
}
- return EmitCall(FnInfo, Callee, ReturnValue, Args);
+ return EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr, E->getExprLoc());
}
LValue CodeGenFunction::
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 1ab8433864c4..0f05cab66d7e 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -692,7 +692,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
return Visit(E->getSubExpr());
}
- // fallthrough
+ LLVM_FALLTHROUGH;
case CK_NoOp:
case CK_UserDefinedConversion:
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 41bb199ffde7..0749b0ac46a7 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -89,7 +89,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
*this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs);
auto &FnInfo = CGM.getTypes().arrangeCXXMethodCall(
Args, FPT, CallInfo.ReqArgs, CallInfo.PrefixSize);
- return EmitCall(FnInfo, Callee, ReturnValue, Args);
+ return EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr,
+ CE ? CE->getExprLoc() : SourceLocation());
}
RValue CodeGenFunction::EmitCXXDestructorCall(
@@ -446,7 +447,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
EmitCallArgs(Args, FPT, E->arguments());
return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required,
/*PrefixSize=*/0),
- Callee, ReturnValue, Args);
+ Callee, ReturnValue, Args, nullptr, E->getExprLoc());
}
RValue
@@ -613,7 +614,7 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
case CXXConstructExpr::CK_VirtualBase:
ForVirtualBase = true;
- // fall-through
+ LLVM_FALLTHROUGH;
case CXXConstructExpr::CK_NonVirtualBase:
Type = Ctor_Base;
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index e860b3045f0e..9094d3f8a91c 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -761,15 +761,16 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second;
llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second;
-
llvm::Value *DSTr, *DSTi;
if (LHSr->getType()->isFloatingPointTy()) {
- // If we have a complex operand on the RHS, we delegate to a libcall to
- // handle all of the complexities and minimize underflow/overflow cases.
+ // If we have a complex operand on the RHS and FastMath is not allowed, we
+ // delegate to a libcall to handle all of the complexities and minimize
+ // underflow/overflow cases. When FastMath is allowed we construct the
+ // divide inline using the same algorithm as for integer operands.
//
// FIXME: We would be able to avoid the libcall in many places if we
// supported imaginary types in addition to complex types.
- if (RHSi) {
+ if (RHSi && !CGF.getLangOpts().FastMath) {
BinOpInfo LibCallOp = Op;
// If LHS was a real, supply a null imaginary part.
if (!LHSi)
@@ -791,11 +792,31 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
case llvm::Type::FP128TyID:
return EmitComplexBinOpLibCall("__divtc3", LibCallOp);
}
- }
- assert(LHSi && "Can have at most one non-complex operand!");
+ } else if (RHSi) {
+ if (!LHSi)
+ LHSi = llvm::Constant::getNullValue(RHSi->getType());
+
+ // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
+ llvm::Value *AC = Builder.CreateFMul(LHSr, RHSr); // a*c
+ llvm::Value *BD = Builder.CreateFMul(LHSi, RHSi); // b*d
+ llvm::Value *ACpBD = Builder.CreateFAdd(AC, BD); // ac+bd
+
+ llvm::Value *CC = Builder.CreateFMul(RHSr, RHSr); // c*c
+ llvm::Value *DD = Builder.CreateFMul(RHSi, RHSi); // d*d
+ llvm::Value *CCpDD = Builder.CreateFAdd(CC, DD); // cc+dd
- DSTr = Builder.CreateFDiv(LHSr, RHSr);
- DSTi = Builder.CreateFDiv(LHSi, RHSr);
+ llvm::Value *BC = Builder.CreateFMul(LHSi, RHSr); // b*c
+ llvm::Value *AD = Builder.CreateFMul(LHSr, RHSi); // a*d
+ llvm::Value *BCmAD = Builder.CreateFSub(BC, AD); // bc-ad
+
+ DSTr = Builder.CreateFDiv(ACpBD, CCpDD);
+ DSTi = Builder.CreateFDiv(BCmAD, CCpDD);
+ } else {
+ assert(LHSi && "Can have at most one non-complex operand!");
+
+ DSTr = Builder.CreateFDiv(LHSr, RHSr);
+ DSTi = Builder.CreateFDiv(LHSi, RHSr);
+ }
} else {
assert(Op.LHS.second && Op.RHS.second &&
"Both operands of integer complex operators must be complex!");
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index ab5bbc03db95..cd62d00dfb53 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -3288,11 +3288,15 @@ public:
/// LLVM arguments and the types they were derived from.
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee,
ReturnValueSlot ReturnValue, const CallArgList &Args,
- llvm::Instruction **callOrInvoke = nullptr);
-
+ llvm::Instruction **callOrInvoke, SourceLocation Loc);
+ RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee,
+ ReturnValueSlot ReturnValue, const CallArgList &Args,
+ llvm::Instruction **callOrInvoke = nullptr) {
+ return EmitCall(CallInfo, Callee, ReturnValue, Args, callOrInvoke,
+ SourceLocation());
+ }
RValue EmitCall(QualType FnType, const CGCallee &Callee, const CallExpr *E,
- ReturnValueSlot ReturnValue,
- llvm::Value *Chain = nullptr);
+ ReturnValueSlot ReturnValue, llvm::Value *Chain = nullptr);
RValue EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue = ReturnValueSlot());
RValue EmitSimpleCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue);
@@ -3391,7 +3395,8 @@ public:
const llvm::CmpInst::Predicate Fp,
const llvm::CmpInst::Predicate Ip,
const llvm::Twine &Name = "");
- llvm::Value *EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E,
+ llvm::Triple::ArchType Arch);
llvm::Value *EmitCommonNeonBuiltinExpr(unsigned BuiltinID,
unsigned LLVMIntrinsic,
@@ -3400,7 +3405,8 @@ public:
unsigned Modifier,
const CallExpr *E,
SmallVectorImpl<llvm::Value *> &Ops,
- Address PtrOp0, Address PtrOp1);
+ Address PtrOp0, Address PtrOp1,
+ llvm::Triple::ArchType Arch);
llvm::Function *LookupNeonLLVMIntrinsic(unsigned IntrinsicID,
unsigned Modifier, llvm::Type *ArgTy,
const CallExpr *E);
@@ -3414,7 +3420,8 @@ public:
llvm::Value *EmitNeonRShiftImm(llvm::Value *Vec, llvm::Value *Amt,
llvm::Type *Ty, bool usgn, const char *name);
llvm::Value *vectorWrapScalar16(llvm::Value *Op);
- llvm::Value *EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E,
+ llvm::Triple::ArchType Arch);
llvm::Value *BuildVector(ArrayRef<llvm::Value*> Ops);
llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
@@ -3747,6 +3754,10 @@ public:
llvm::ConstantInt *TypeId, llvm::Value *Ptr,
ArrayRef<llvm::Constant *> StaticArgs);
+ /// Emit a reached-unreachable diagnostic if \p Loc is valid and runtime
+ /// checking is enabled. Otherwise, just emit an unreachable instruction.
+ void EmitUnreachable(SourceLocation Loc);
+
/// \brief Create a basic block that will call the trap intrinsic, and emit a
/// conditional branch to it, for the -ftrapv checks.
void EmitTrapCheck(llvm::Value *Checked);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index c59dc71da596..5bdf81aaf66e 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -103,6 +103,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
Int16Ty = llvm::Type::getInt16Ty(LLVMContext);
Int32Ty = llvm::Type::getInt32Ty(LLVMContext);
Int64Ty = llvm::Type::getInt64Ty(LLVMContext);
+ HalfTy = llvm::Type::getHalfTy(LLVMContext);
FloatTy = llvm::Type::getFloatTy(LLVMContext);
DoubleTy = llvm::Type::getDoubleTy(LLVMContext);
PointerWidthInBits = C.getTargetInfo().getPointerWidth(0);
@@ -4289,7 +4290,11 @@ void CodeGenModule::ClearUnusedCoverageMapping(const Decl *D) {
}
void CodeGenModule::EmitDeferredUnusedCoverageMappings() {
- for (const auto &Entry : DeferredEmptyCoverageMappingDecls) {
+ // We call takeVector() here to avoid use-after-free.
+ // FIXME: DeferredEmptyCoverageMappingDecls is getting mutated because
+ // we deserialize function bodies to emit coverage info for them, and that
+ // deserializes more declarations. How should we handle that case?
+ for (const auto &Entry : DeferredEmptyCoverageMappingDecls.takeVector()) {
if (!Entry.second)
continue;
const Decl *D = Entry.first;
diff --git a/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp
index f394ea288d46..ad473032db17 100644
--- a/lib/CodeGen/CodeGenTBAA.cpp
+++ b/lib/CodeGen/CodeGenTBAA.cpp
@@ -59,7 +59,10 @@ llvm::MDNode *CodeGenTBAA::getRoot() {
llvm::MDNode *CodeGenTBAA::createScalarTypeNode(StringRef Name,
llvm::MDNode *Parent,
uint64_t Size) {
- (void)Size; // TODO: Support generation of size-aware type nodes.
+ if (CodeGenOpts.NewStructPathTBAA) {
+ llvm::Metadata *Id = MDHelper.createString(Name);
+ return MDHelper.createTBAATypeNode(Parent, Size, Id);
+ }
return MDHelper.createTBAAScalarTypeNode(Name, Parent);
}
@@ -158,6 +161,10 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
if (Ty->isPointerType() || Ty->isReferenceType())
return createScalarTypeNode("any pointer", getChar(), Size);
+ // Accesses to arrays are accesses to objects of their element types.
+ if (CodeGenOpts.NewStructPathTBAA && Ty->isArrayType())
+ return getTypeInfo(cast<ArrayType>(Ty)->getElementType());
+
// Enum types are distinct types. In C++ they have "underlying types",
// however they aren't related for TBAA.
if (const EnumType *ETy = dyn_cast<EnumType>(Ty)) {
@@ -300,8 +307,12 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
OutName = RD->getName();
}
- // TODO: Support size-aware type nodes and create one here for the
- // given aggregate type.
+ if (CodeGenOpts.NewStructPathTBAA) {
+ llvm::MDNode *Parent = getChar();
+ uint64_t Size = Context.getTypeSizeInChars(Ty).getQuantity();
+ llvm::Metadata *Id = MDHelper.createString(OutName);
+ return MDHelper.createTBAATypeNode(Parent, Size, Id, Fields);
+ }
// Create the struct type node with a vector of pairs (offset, type).
SmallVector<std::pair<llvm::MDNode*, uint64_t>, 4> OffsetsAndTypes;
@@ -348,6 +359,10 @@ llvm::MDNode *CodeGenTBAA::getAccessTagInfo(TBAAAccessInfo Info) {
Info.BaseType = Info.AccessType;
assert(!Info.Offset && "Nonzero offset for an access with no base type!");
}
+ if (CodeGenOpts.NewStructPathTBAA) {
+ return N = MDHelper.createTBAAAccessTag(Info.BaseType, Info.AccessType,
+ Info.Offset, Info.Size);
+ }
return N = MDHelper.createTBAAStructTagNode(Info.BaseType, Info.AccessType,
Info.Offset);
}
diff --git a/lib/CodeGen/CodeGenTypeCache.h b/lib/CodeGen/CodeGenTypeCache.h
index 2af7b30eafb4..fb096ac89987 100644
--- a/lib/CodeGen/CodeGenTypeCache.h
+++ b/lib/CodeGen/CodeGenTypeCache.h
@@ -37,7 +37,7 @@ struct CodeGenTypeCache {
/// i8, i16, i32, and i64
llvm::IntegerType *Int8Ty, *Int16Ty, *Int32Ty, *Int64Ty;
/// float, double
- llvm::Type *FloatTy, *DoubleTy;
+ llvm::Type *HalfTy, *FloatTy, *DoubleTy;
/// int
llvm::IntegerType *IntTy;
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index f617d8b4551e..6ba8892f3501 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -440,6 +440,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
RecoverableKinds &= ~Unrecoverable;
TrappingKinds &= Kinds;
+ RecoverableKinds &= ~TrappingKinds;
// Setup blacklist files.
// Add default blacklist from resource directory.
@@ -683,6 +684,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
Sanitizers.Mask |= Kinds;
RecoverableSanitizers.Mask |= RecoverableKinds;
TrapSanitizers.Mask |= TrappingKinds;
+ assert(!(RecoverableKinds & TrappingKinds) &&
+ "Overlap between recoverable and trapping sanitizers");
}
static std::string toString(const clang::SanitizerSet &Sanitizers) {
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index 0a89ff96d3c8..7b3f4bc9d872 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -4389,6 +4389,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fapple-pragma-pack");
if (Args.hasFlag(options::OPT_fsave_optimization_record,
+ options::OPT_foptimization_record_file_EQ,
options::OPT_fno_save_optimization_record, false)) {
CmdArgs.push_back("-opt-record-file");
diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp
index ab51a8c3cc90..60f96d03c9c8 100644
--- a/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/lib/Driver/ToolChains/CommonArgs.cpp
@@ -549,6 +549,12 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
TC.getTriple().getOS() != llvm::Triple::NetBSD &&
TC.getTriple().getOS() != llvm::Triple::RTEMS)
CmdArgs.push_back("-ldl");
+ // Required for forkpty on some OSes
+ if (TC.getTriple().getOS() == llvm::Triple::NetBSD)
+ CmdArgs.push_back("-lutil");
+ // Required for backtrace on some OSes
+ if (TC.getTriple().getOS() == llvm::Triple::NetBSD)
+ CmdArgs.push_back("-lexecinfo");
}
static void
diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp
index 28efa86538ed..289f4ed92f6c 100644
--- a/lib/Driver/ToolChains/Darwin.cpp
+++ b/lib/Driver/ToolChains/Darwin.cpp
@@ -1181,9 +1181,12 @@ struct DarwinPlatform {
};
using DarwinPlatformKind = Darwin::DarwinPlatformKind;
+ using DarwinEnvironmentKind = Darwin::DarwinEnvironmentKind;
DarwinPlatformKind getPlatform() const { return Platform; }
+ DarwinEnvironmentKind getEnvironment() const { return Environment; }
+
StringRef getOSVersion() const {
if (Kind == OSVersionArg)
return Argument->getValue();
@@ -1233,6 +1236,19 @@ struct DarwinPlatform {
llvm_unreachable("Unsupported Darwin Source Kind");
}
+ static DarwinPlatform createFromTarget(llvm::Triple::OSType OS,
+ StringRef OSVersion, Arg *A,
+ llvm::Triple::EnvironmentType Env) {
+ DarwinPlatform Result(TargetArg, getPlatformFromOS(OS), OSVersion, A);
+ switch (Env) {
+ case llvm::Triple::Simulator:
+ Result.Environment = DarwinEnvironmentKind::Simulator;
+ break;
+ default:
+ break;
+ }
+ return Result;
+ }
static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform,
Arg *A) {
return DarwinPlatform(OSVersionArg, Platform, A);
@@ -1250,35 +1266,35 @@ struct DarwinPlatform {
}
static DarwinPlatform createFromArch(llvm::Triple::OSType OS,
StringRef Value) {
- DarwinPlatformKind Platform;
+ return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value);
+ }
+
+private:
+ DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
+ : Kind(Kind), Platform(Platform), Argument(Argument) {}
+ DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value,
+ Arg *Argument = nullptr)
+ : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(Argument) {}
+
+ static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) {
switch (OS) {
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
- Platform = DarwinPlatformKind::MacOS;
- break;
+ return DarwinPlatformKind::MacOS;
case llvm::Triple::IOS:
- Platform = DarwinPlatformKind::IPhoneOS;
- break;
+ return DarwinPlatformKind::IPhoneOS;
case llvm::Triple::TvOS:
- Platform = DarwinPlatformKind::TvOS;
- break;
+ return DarwinPlatformKind::TvOS;
case llvm::Triple::WatchOS:
- Platform = DarwinPlatformKind::WatchOS;
- break;
+ return DarwinPlatformKind::WatchOS;
default:
llvm_unreachable("Unable to infer Darwin variant");
}
- return DarwinPlatform(InferredFromArch, Platform, Value);
}
-private:
- DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
- : Kind(Kind), Platform(Platform), Argument(Argument) {}
- DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value)
- : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(nullptr) {}
-
SourceKind Kind;
DarwinPlatformKind Platform;
+ DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
std::string OSVersion;
Arg *Argument;
StringRef EnvVarName;
@@ -1449,20 +1465,15 @@ inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
const Driver &TheDriver) {
llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
- // Set the OSTy based on -target if -arch isn't present.
- if (Args.hasArg(options::OPT_target) && !Args.hasArg(options::OPT_arch)) {
- OSTy = Triple.getOS();
- } else {
- StringRef MachOArchName = Toolchain.getMachOArchName(Args);
- if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
- MachOArchName == "arm64")
- OSTy = llvm::Triple::IOS;
- else if (MachOArchName == "armv7k")
- OSTy = llvm::Triple::WatchOS;
- else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
- MachOArchName != "armv7em")
- OSTy = llvm::Triple::MacOSX;
- }
+ StringRef MachOArchName = Toolchain.getMachOArchName(Args);
+ if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
+ MachOArchName == "arm64")
+ OSTy = llvm::Triple::IOS;
+ else if (MachOArchName == "armv7k")
+ OSTy = llvm::Triple::WatchOS;
+ else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
+ MachOArchName != "armv7em")
+ OSTy = llvm::Triple::MacOSX;
if (OSTy == llvm::Triple::UnknownOS)
return None;
@@ -1470,6 +1481,20 @@ inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
getOSVersion(OSTy, Triple, TheDriver));
}
+/// Returns the deployment target that's specified using the -target option.
+Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
+ DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver) {
+ if (!Args.hasArg(options::OPT_target))
+ return None;
+ if (Triple.getOS() == llvm::Triple::Darwin ||
+ Triple.getOS() == llvm::Triple::UnknownOS)
+ return None;
+ std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
+ return DarwinPlatform::createFromTarget(Triple.getOS(), OSVersion,
+ Args.getLastArg(options::OPT_target),
+ Triple.getEnvironment());
+}
+
} // namespace
void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
@@ -1494,24 +1519,52 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
}
}
- // The OS target can be specified using the -m<os>version-min argument.
+ // The OS and the version can be specified using the -target argument.
Optional<DarwinPlatform> OSTarget =
- getDeploymentTargetFromOSVersionArg(Args, getDriver());
- // If no deployment target was specified on the command line, check for
- // environment defines.
- if (!OSTarget)
- OSTarget =
- getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
- // If there is no command-line argument to specify the Target version and
- // no environment variable defined, see if we can set the default based
- // on -isysroot.
- if (!OSTarget)
- OSTarget = inferDeploymentTargetFromSDK(Args);
- // If no OS targets have been specified, try to guess platform from -target
- // or arch name and compute the version from the triple.
- if (!OSTarget)
- OSTarget =
- inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver());
+ getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver());
+ if (OSTarget) {
+ Optional<DarwinPlatform> OSVersionArgTarget =
+ getDeploymentTargetFromOSVersionArg(Args, getDriver());
+ if (OSVersionArgTarget) {
+ unsigned TargetMajor, TargetMinor, TargetMicro;
+ bool TargetExtra;
+ unsigned ArgMajor, ArgMinor, ArgMicro;
+ bool ArgExtra;
+ if (OSTarget->getPlatform() != OSVersionArgTarget->getPlatform() ||
+ (Driver::GetReleaseVersion(OSTarget->getOSVersion(), TargetMajor,
+ TargetMinor, TargetMicro, TargetExtra) &&
+ Driver::GetReleaseVersion(OSVersionArgTarget->getOSVersion(),
+ ArgMajor, ArgMinor, ArgMicro, ArgExtra) &&
+ (VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=
+ VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||
+ TargetExtra != ArgExtra))) {
+ // Warn about -m<os>-version-min that doesn't match the OS version
+ // that's specified in the target.
+ std::string OSVersionArg = OSVersionArgTarget->getAsString(Args, Opts);
+ std::string TargetArg = OSTarget->getAsString(Args, Opts);
+ getDriver().Diag(clang::diag::warn_drv_overriding_flag_option)
+ << OSVersionArg << TargetArg;
+ }
+ }
+ } else {
+ // The OS target can be specified using the -m<os>version-min argument.
+ OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());
+ // If no deployment target was specified on the command line, check for
+ // environment defines.
+ if (!OSTarget)
+ OSTarget =
+ getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
+ // If there is no command-line argument to specify the Target version and
+ // no environment variable defined, see if we can set the default based
+ // on -isysroot.
+ if (!OSTarget)
+ OSTarget = inferDeploymentTargetFromSDK(Args);
+ // If no OS targets have been specified, try to guess platform from -target
+ // or arch name and compute the version from the triple.
+ if (!OSTarget)
+ OSTarget =
+ inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver());
+ }
assert(OSTarget && "Unable to infer Darwin variant");
OSTarget->addOSVersionMinArgument(Args, Opts);
@@ -1562,10 +1615,11 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
} else
llvm_unreachable("unknown kind of Darwin platform");
- DarwinEnvironmentKind Environment = NativeEnvironment;
+ DarwinEnvironmentKind Environment = OSTarget->getEnvironment();
// Recognize iOS targets with an x86 architecture as the iOS simulator.
- if (Platform != MacOS && (getTriple().getArch() == llvm::Triple::x86 ||
- getTriple().getArch() == llvm::Triple::x86_64))
+ if (Environment == NativeEnvironment && Platform != MacOS &&
+ (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64))
Environment = Simulator;
setTarget(Platform, Environment, Major, Minor, Micro);
diff --git a/lib/Driver/ToolChains/Fuchsia.cpp b/lib/Driver/ToolChains/Fuchsia.cpp
index 10ee7b7829be..269d34d18f1e 100644
--- a/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/lib/Driver/ToolChains/Fuchsia.cpp
@@ -280,5 +280,6 @@ SanitizerMask Fuchsia::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::SafeStack;
Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::Scudo;
return Res;
}
diff --git a/lib/Driver/ToolChains/Myriad.cpp b/lib/Driver/ToolChains/Myriad.cpp
index 6fdb5a2248dd..06079b109dd1 100644
--- a/lib/Driver/ToolChains/Myriad.cpp
+++ b/lib/Driver/ToolChains/Myriad.cpp
@@ -199,7 +199,7 @@ void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
std::string Exec =
- Args.MakeArgString(TC.GetProgramPath("sparc-myriad-elf-ld"));
+ Args.MakeArgString(TC.GetProgramPath("sparc-myriad-rtems-ld"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
CmdArgs, Inputs));
}
@@ -218,10 +218,11 @@ MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
D.Diag(clang::diag::err_target_unsupported_arch)
<< Triple.getArchName() << "myriad";
LLVM_FALLTHROUGH;
+ case llvm::Triple::shave:
+ return;
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
- case llvm::Triple::shave:
- GCCInstallation.init(Triple, Args, {"sparc-myriad-elf"});
+ GCCInstallation.init(Triple, Args, {"sparc-myriad-rtems"});
}
if (GCCInstallation.isValid()) {
@@ -231,7 +232,7 @@ MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
addPathIfExists(D, CompilerSupportDir, getFilePaths());
}
// libstd++ and libc++ must both be found in this one place.
- addPathIfExists(D, D.Dir + "/../sparc-myriad-elf/lib", getFilePaths());
+ addPathIfExists(D, D.Dir + "/../sparc-myriad-rtems/lib", getFilePaths());
}
MyriadToolChain::~MyriadToolChain() {}
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 32f1232bbe24..7208177aa012 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -1854,6 +1854,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// Verify that the rest of the module path actually corresponds to
// a submodule.
+ bool MapPrivateSubModToTopLevel = false;
if (!getLangOpts().ModulesTS && Path.size() > 1) {
for (unsigned I = 1, N = Path.size(); I != N; ++I) {
StringRef Name = Path[I].first->getName();
@@ -1892,7 +1893,40 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
Sub = Module->findSubmodule(Best[0]);
}
}
-
+
+ // If the user is requesting Foo.Private and it doesn't exist, try to
+ // match Foo_Private and emit a warning asking for the user to write
+ // @import Foo_Private instead. FIXME: remove this when existing clients
+ // migrate off of Foo.Private syntax.
+ if (!Sub && PP->getLangOpts().ImplicitModules && Name == "Private" &&
+ Module == Module->getTopLevelModule()) {
+ SmallString<128> PrivateModule(Module->Name);
+ PrivateModule.append("_Private");
+
+ SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> PrivPath;
+ auto &II = PP->getIdentifierTable().get(
+ PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
+ PrivPath.push_back(std::make_pair(&II, Path[0].second));
+
+ if (PP->getHeaderSearchInfo().lookupModule(PrivateModule))
+ Sub =
+ loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective);
+ if (Sub) {
+ MapPrivateSubModToTopLevel = true;
+ if (!getDiagnostics().isIgnored(
+ diag::warn_no_priv_submodule_use_toplevel, ImportLoc)) {
+ getDiagnostics().Report(Path[I].second,
+ diag::warn_no_priv_submodule_use_toplevel)
+ << Path[I].first << Module->getFullModuleName() << PrivateModule
+ << SourceRange(Path[0].second, Path[I].second)
+ << FixItHint::CreateReplacement(SourceRange(Path[0].second),
+ PrivateModule);
+ getDiagnostics().Report(Sub->DefinitionLoc,
+ diag::note_private_top_level_defined);
+ }
+ }
+ }
+
if (!Sub) {
// No submodule by this name. Complain, and don't look for further
// submodules.
@@ -1909,7 +1943,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// Make the named module visible, if it's not already part of the module
// we are parsing.
if (ModuleName != getLangOpts().CurrentModule) {
- if (!Module->IsFromModuleFile) {
+ if (!Module->IsFromModuleFile && !MapPrivateSubModToTopLevel) {
// We have an umbrella header or directory that doesn't actually include
// all of the headers within the directory it covers. Complain about
// this missing submodule and recover by forgetting that we ever saw
diff --git a/lib/Frontend/PrecompiledPreamble.cpp b/lib/Frontend/PrecompiledPreamble.cpp
index f6964d02b237..7e1323fd83bb 100644
--- a/lib/Frontend/PrecompiledPreamble.cpp
+++ b/lib/Frontend/PrecompiledPreamble.cpp
@@ -30,7 +30,7 @@
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/Process.h"
-
+#include <limits>
#include <utility>
using namespace clang;
@@ -333,6 +333,7 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
std::unique_ptr<PrecompilePreambleAction> Act;
Act.reset(new PrecompilePreambleAction(
StoreInMemory ? &Storage.asMemory().Data : nullptr, Callbacks));
+ Callbacks.BeforeExecute(*Clang);
if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
return BuildPreambleError::BeginSourceFileFailed;
@@ -380,6 +381,27 @@ PreambleBounds PrecompiledPreamble::getBounds() const {
return PreambleBounds(PreambleBytes.size(), PreambleEndsAtStartOfLine);
}
+std::size_t PrecompiledPreamble::getSize() const {
+ switch (Storage.getKind()) {
+ case PCHStorage::Kind::Empty:
+ assert(false && "Calling getSize() on invalid PrecompiledPreamble. "
+ "Was it std::moved?");
+ return 0;
+ case PCHStorage::Kind::InMemory:
+ return Storage.asMemory().Data.size();
+ case PCHStorage::Kind::TempFile: {
+ uint64_t Result;
+ if (llvm::sys::fs::file_size(Storage.asFile().getFilePath(), Result))
+ return 0;
+
+ assert(Result <= std::numeric_limits<std::size_t>::max() &&
+ "file size did not fit into size_t");
+ return Result;
+ }
+ }
+ llvm_unreachable("Unhandled storage kind");
+}
+
bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation,
const llvm::MemoryBuffer *MainFileBuffer,
PreambleBounds Bounds,
@@ -505,8 +527,8 @@ PrecompiledPreamble::TempPCHFile::createInSystemTempDir(const Twine &Prefix,
StringRef Suffix) {
llvm::SmallString<64> File;
// Using a version of createTemporaryFile with a file descriptor guarantees
- // that we would never get a race condition in a multi-threaded setting (i.e.,
- // multiple threads getting the same temporary path).
+ // that we would never get a race condition in a multi-threaded setting
+ // (i.e., multiple threads getting the same temporary path).
int FD;
auto EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, FD, File);
if (EC)
@@ -694,6 +716,7 @@ void PrecompiledPreamble::setupPreambleStorage(
}
}
+void PreambleCallbacks::BeforeExecute(CompilerInstance &CI) {}
void PreambleCallbacks::AfterExecute(CompilerInstance &CI) {}
void PreambleCallbacks::AfterPCHEmitted(ASTWriter &Writer) {}
void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {}
diff --git a/lib/Headers/__clang_cuda_intrinsics.h b/lib/Headers/__clang_cuda_intrinsics.h
index 02d68a2e618e..1794eb3dc1d6 100644
--- a/lib/Headers/__clang_cuda_intrinsics.h
+++ b/lib/Headers/__clang_cuda_intrinsics.h
@@ -34,23 +34,24 @@
#if !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 300
#pragma push_macro("__MAKE_SHUFFLES")
-#define __MAKE_SHUFFLES(__FnName, __IntIntrinsic, __FloatIntrinsic, __Mask) \
- inline __device__ int __FnName(int __val, int __offset, \
+#define __MAKE_SHUFFLES(__FnName, __IntIntrinsic, __FloatIntrinsic, __Mask, \
+ __Type) \
+ inline __device__ int __FnName(int __val, __Type __offset, \
int __width = warpSize) { \
return __IntIntrinsic(__val, __offset, \
((warpSize - __width) << 8) | (__Mask)); \
} \
- inline __device__ float __FnName(float __val, int __offset, \
+ inline __device__ float __FnName(float __val, __Type __offset, \
int __width = warpSize) { \
return __FloatIntrinsic(__val, __offset, \
((warpSize - __width) << 8) | (__Mask)); \
} \
- inline __device__ unsigned int __FnName(unsigned int __val, int __offset, \
+ inline __device__ unsigned int __FnName(unsigned int __val, __Type __offset, \
int __width = warpSize) { \
return static_cast<unsigned int>( \
::__FnName(static_cast<int>(__val), __offset, __width)); \
} \
- inline __device__ long long __FnName(long long __val, int __offset, \
+ inline __device__ long long __FnName(long long __val, __Type __offset, \
int __width = warpSize) { \
struct __Bits { \
int __a, __b; \
@@ -65,12 +66,29 @@
memcpy(&__ret, &__tmp, sizeof(__tmp)); \
return __ret; \
} \
+ inline __device__ long __FnName(long __val, __Type __offset, \
+ int __width = warpSize) { \
+ _Static_assert(sizeof(long) == sizeof(long long) || \
+ sizeof(long) == sizeof(int)); \
+ if (sizeof(long) == sizeof(long long)) { \
+ return static_cast<long>( \
+ ::__FnName(static_cast<long long>(__val), __offset, __width)); \
+ } else if (sizeof(long) == sizeof(int)) { \
+ return static_cast<long>( \
+ ::__FnName(static_cast<int>(__val), __offset, __width)); \
+ } \
+ } \
+ inline __device__ unsigned long __FnName( \
+ unsigned long __val, __Type __offset, int __width = warpSize) { \
+ return static_cast<unsigned long>( \
+ ::__FnName(static_cast<long>(__val), __offset, __width)); \
+ } \
inline __device__ unsigned long long __FnName( \
- unsigned long long __val, int __offset, int __width = warpSize) { \
+ unsigned long long __val, __Type __offset, int __width = warpSize) { \
return static_cast<unsigned long long>(::__FnName( \
static_cast<unsigned long long>(__val), __offset, __width)); \
} \
- inline __device__ double __FnName(double __val, int __offset, \
+ inline __device__ double __FnName(double __val, __Type __offset, \
int __width = warpSize) { \
long long __tmp; \
_Static_assert(sizeof(__tmp) == sizeof(__val)); \
@@ -81,13 +99,15 @@
return __ret; \
}
-__MAKE_SHUFFLES(__shfl, __nvvm_shfl_idx_i32, __nvvm_shfl_idx_f32, 0x1f);
+__MAKE_SHUFFLES(__shfl, __nvvm_shfl_idx_i32, __nvvm_shfl_idx_f32, 0x1f, int);
// We use 0 rather than 31 as our mask, because shfl.up applies to lanes >=
// maxLane.
-__MAKE_SHUFFLES(__shfl_up, __nvvm_shfl_up_i32, __nvvm_shfl_up_f32, 0);
-__MAKE_SHUFFLES(__shfl_down, __nvvm_shfl_down_i32, __nvvm_shfl_down_f32, 0x1f);
-__MAKE_SHUFFLES(__shfl_xor, __nvvm_shfl_bfly_i32, __nvvm_shfl_bfly_f32, 0x1f);
-
+__MAKE_SHUFFLES(__shfl_up, __nvvm_shfl_up_i32, __nvvm_shfl_up_f32, 0,
+ unsigned int);
+__MAKE_SHUFFLES(__shfl_down, __nvvm_shfl_down_i32, __nvvm_shfl_down_f32, 0x1f,
+ unsigned int);
+__MAKE_SHUFFLES(__shfl_xor, __nvvm_shfl_bfly_i32, __nvvm_shfl_bfly_f32, 0x1f,
+ int);
#pragma pop_macro("__MAKE_SHUFFLES")
#endif // !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 300
@@ -97,25 +117,26 @@ __MAKE_SHUFFLES(__shfl_xor, __nvvm_shfl_bfly_i32, __nvvm_shfl_bfly_f32, 0x1f);
// __shfl_sync_* variants available in CUDA-9
#pragma push_macro("__MAKE_SYNC_SHUFFLES")
#define __MAKE_SYNC_SHUFFLES(__FnName, __IntIntrinsic, __FloatIntrinsic, \
- __Mask) \
- inline __device__ int __FnName(unsigned int __mask, int __val, int __offset, \
- int __width = warpSize) { \
+ __Mask, __Type) \
+ inline __device__ int __FnName(unsigned int __mask, int __val, \
+ __Type __offset, int __width = warpSize) { \
return __IntIntrinsic(__mask, __val, __offset, \
((warpSize - __width) << 8) | (__Mask)); \
} \
inline __device__ float __FnName(unsigned int __mask, float __val, \
- int __offset, int __width = warpSize) { \
+ __Type __offset, int __width = warpSize) { \
return __FloatIntrinsic(__mask, __val, __offset, \
((warpSize - __width) << 8) | (__Mask)); \
} \
inline __device__ unsigned int __FnName(unsigned int __mask, \
- unsigned int __val, int __offset, \
+ unsigned int __val, __Type __offset, \
int __width = warpSize) { \
return static_cast<unsigned int>( \
::__FnName(__mask, static_cast<int>(__val), __offset, __width)); \
} \
inline __device__ long long __FnName(unsigned int __mask, long long __val, \
- int __offset, int __width = warpSize) { \
+ __Type __offset, \
+ int __width = warpSize) { \
struct __Bits { \
int __a, __b; \
}; \
@@ -130,13 +151,13 @@ __MAKE_SHUFFLES(__shfl_xor, __nvvm_shfl_bfly_i32, __nvvm_shfl_bfly_f32, 0x1f);
return __ret; \
} \
inline __device__ unsigned long long __FnName( \
- unsigned int __mask, unsigned long long __val, int __offset, \
+ unsigned int __mask, unsigned long long __val, __Type __offset, \
int __width = warpSize) { \
return static_cast<unsigned long long>(::__FnName( \
__mask, static_cast<unsigned long long>(__val), __offset, __width)); \
} \
inline __device__ long __FnName(unsigned int __mask, long __val, \
- int __offset, int __width = warpSize) { \
+ __Type __offset, int __width = warpSize) { \
_Static_assert(sizeof(long) == sizeof(long long) || \
sizeof(long) == sizeof(int)); \
if (sizeof(long) == sizeof(long long)) { \
@@ -147,14 +168,14 @@ __MAKE_SHUFFLES(__shfl_xor, __nvvm_shfl_bfly_i32, __nvvm_shfl_bfly_f32, 0x1f);
::__FnName(__mask, static_cast<int>(__val), __offset, __width)); \
} \
} \
- inline __device__ unsigned long __FnName(unsigned int __mask, \
- unsigned long __val, int __offset, \
- int __width = warpSize) { \
+ inline __device__ unsigned long __FnName( \
+ unsigned int __mask, unsigned long __val, __Type __offset, \
+ int __width = warpSize) { \
return static_cast<unsigned long>( \
::__FnName(__mask, static_cast<long>(__val), __offset, __width)); \
} \
inline __device__ double __FnName(unsigned int __mask, double __val, \
- int __offset, int __width = warpSize) { \
+ __Type __offset, int __width = warpSize) { \
long long __tmp; \
_Static_assert(sizeof(__tmp) == sizeof(__val)); \
memcpy(&__tmp, &__val, sizeof(__val)); \
@@ -164,15 +185,15 @@ __MAKE_SHUFFLES(__shfl_xor, __nvvm_shfl_bfly_i32, __nvvm_shfl_bfly_f32, 0x1f);
return __ret; \
}
__MAKE_SYNC_SHUFFLES(__shfl_sync, __nvvm_shfl_sync_idx_i32,
- __nvvm_shfl_sync_idx_f32, 0x1f);
+ __nvvm_shfl_sync_idx_f32, 0x1f, int);
// We use 0 rather than 31 as our mask, because shfl.up applies to lanes >=
// maxLane.
__MAKE_SYNC_SHUFFLES(__shfl_up_sync, __nvvm_shfl_sync_up_i32,
- __nvvm_shfl_sync_up_f32, 0);
+ __nvvm_shfl_sync_up_f32, 0, unsigned int);
__MAKE_SYNC_SHUFFLES(__shfl_down_sync, __nvvm_shfl_sync_down_i32,
- __nvvm_shfl_sync_down_f32, 0x1f);
+ __nvvm_shfl_sync_down_f32, 0x1f, unsigned int);
__MAKE_SYNC_SHUFFLES(__shfl_xor_sync, __nvvm_shfl_sync_bfly_i32,
- __nvvm_shfl_sync_bfly_f32, 0x1f);
+ __nvvm_shfl_sync_bfly_f32, 0x1f, int);
#pragma pop_macro("__MAKE_SYNC_SHUFFLES")
inline __device__ void __syncwarp(unsigned int mask = 0xffffffff) {
diff --git a/lib/Headers/cpuid.h b/lib/Headers/cpuid.h
index 2dd0add236b8..3ae90de0b91f 100644
--- a/lib/Headers/cpuid.h
+++ b/lib/Headers/cpuid.h
@@ -173,16 +173,24 @@
#define bit_AVX512VL 0x80000000
/* Features in %ecx for leaf 7 sub-leaf 0 */
-#define bit_PREFTCHWT1 0x00000001
-#define bit_AVX512VBMI 0x00000002
-#define bit_PKU 0x00000004
-#define bit_OSPKE 0x00000010
+#define bit_PREFTCHWT1 0x00000001
+#define bit_AVX512VBMI 0x00000002
+#define bit_PKU 0x00000004
+#define bit_OSPKE 0x00000010
+#define bit_AVX512VBMI2 0x00000040
+#define bit_SHSTK 0x00000080
+#define bit_GFNI 0x00000100
+#define bit_VAES 0x00000200
+#define bit_VPCLMULQDQ 0x00000400
+#define bit_AVX512VNNI 0x00000800
+#define bit_AVX512BITALG 0x00001000
#define bit_AVX512VPOPCNTDQ 0x00004000
-#define bit_RDPID 0x00400000
+#define bit_RDPID 0x00400000
/* Features in %edx for leaf 7 sub-leaf 0 */
#define bit_AVX5124VNNIW 0x00000004
#define bit_AVX5124FMAPS 0x00000008
+#define bit_IBT 0x00100000
/* Features in %eax for leaf 13 sub-leaf 1 */
#define bit_XSAVEOPT 0x00000001
@@ -192,6 +200,7 @@
/* Features in %ecx for leaf 0x80000001 */
#define bit_LAHF_LM 0x00000001
#define bit_ABM 0x00000020
+#define bit_LZCNT bit_ABM /* for gcc compat */
#define bit_SSE4a 0x00000040
#define bit_PRFCHW 0x00000100
#define bit_XOP 0x00000800
diff --git a/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h
index bbc2117b4ea1..279c0275d93f 100644
--- a/lib/Headers/xmmintrin.h
+++ b/lib/Headers/xmmintrin.h
@@ -2035,9 +2035,11 @@ _mm_storer_ps(float *__p, __m128 __a)
_mm_store_ps(__p, __a);
}
-#define _MM_HINT_T0 3
-#define _MM_HINT_T1 2
-#define _MM_HINT_T2 1
+#define _MM_HINT_ET0 7
+#define _MM_HINT_ET1 6
+#define _MM_HINT_T0 3
+#define _MM_HINT_T1 2
+#define _MM_HINT_T2 1
#define _MM_HINT_NTA 0
#ifndef _MSC_VER
@@ -2068,7 +2070,8 @@ _mm_storer_ps(float *__p, __m128 __a)
/// be generated. \n
/// _MM_HINT_T2: Move data using the T2 hint. The PREFETCHT2 instruction will
/// be generated.
-#define _mm_prefetch(a, sel) (__builtin_prefetch((void *)(a), 0, (sel)))
+#define _mm_prefetch(a, sel) (__builtin_prefetch((void *)(a), \
+ ((sel) >> 2) & 1, (sel) & 0x3))
#endif
/// \brief Stores a 64-bit integer in the specified aligned memory location. To
diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp
index 03db0cd53f7a..733d4dbc2f94 100644
--- a/lib/Index/IndexSymbol.cpp
+++ b/lib/Index/IndexSymbol.cpp
@@ -42,10 +42,10 @@ static bool isUnitTest(const ObjCMethodDecl *D) {
static void checkForIBOutlets(const Decl *D, SymbolPropertySet &PropSet) {
if (D->hasAttr<IBOutletAttr>()) {
- PropSet |= (unsigned)SymbolProperty::IBAnnotated;
+ PropSet |= (SymbolPropertySet)SymbolProperty::IBAnnotated;
} else if (D->hasAttr<IBOutletCollectionAttr>()) {
- PropSet |= (unsigned)SymbolProperty::IBAnnotated;
- PropSet |= (unsigned)SymbolProperty::IBOutletCollection;
+ PropSet |= (SymbolPropertySet)SymbolProperty::IBAnnotated;
+ PropSet |= (SymbolPropertySet)SymbolProperty::IBOutletCollection;
}
}
@@ -93,7 +93,7 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
Info.Lang = SymbolLanguage::C;
if (isFunctionLocalSymbol(D)) {
- Info.Properties |= (unsigned)SymbolProperty::Local;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Local;
}
if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
@@ -118,17 +118,19 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
if (!CXXRec->isCLike()) {
Info.Lang = SymbolLanguage::CXX;
if (CXXRec->getDescribedClassTemplate()) {
- Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
}
}
}
if (isa<ClassTemplatePartialSpecializationDecl>(D)) {
- Info.Properties |= (unsigned)SymbolProperty::Generic;
- Info.Properties |= (unsigned)SymbolProperty::TemplatePartialSpecialization;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
+ Info.Properties |=
+ (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization;
} else if (isa<ClassTemplateSpecializationDecl>(D)) {
- Info.Properties |= (unsigned)SymbolProperty::Generic;
- Info.Properties |= (unsigned)SymbolProperty::TemplateSpecialization;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
+ Info.Properties |=
+ (SymbolPropertySet)SymbolProperty::TemplateSpecialization;
}
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
@@ -142,15 +144,17 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
if (isa<VarTemplatePartialSpecializationDecl>(D)) {
Info.Lang = SymbolLanguage::CXX;
- Info.Properties |= (unsigned)SymbolProperty::Generic;
- Info.Properties |= (unsigned)SymbolProperty::TemplatePartialSpecialization;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
+ Info.Properties |=
+ (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization;
} else if (isa<VarTemplateSpecializationDecl>(D)) {
Info.Lang = SymbolLanguage::CXX;
- Info.Properties |= (unsigned)SymbolProperty::Generic;
- Info.Properties |= (unsigned)SymbolProperty::TemplateSpecialization;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
+ Info.Properties |=
+ (SymbolPropertySet)SymbolProperty::TemplateSpecialization;
} else if (VD->getDescribedVarTemplate()) {
Info.Lang = SymbolLanguage::CXX;
- Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
}
} else {
@@ -181,7 +185,7 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
if (!ClsD)
ClsD = cast<ObjCImplementationDecl>(D)->getClassInterface();
if (isUnitTestCase(ClsD))
- Info.Properties |= (unsigned)SymbolProperty::UnitTest;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest;
break;
}
case Decl::ObjCProtocol:
@@ -198,7 +202,7 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
else
ClsD = cast<ObjCCategoryImplDecl>(D)->getClassInterface();
if (isUnitTestCase(ClsD))
- Info.Properties |= (unsigned)SymbolProperty::UnitTest;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest;
break;
}
case Decl::ObjCMethod: {
@@ -212,9 +216,9 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
}
Info.Lang = SymbolLanguage::ObjC;
if (isUnitTest(MD))
- Info.Properties |= (unsigned)SymbolProperty::UnitTest;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest;
if (D->hasAttr<IBActionAttr>())
- Info.Properties |= (unsigned)SymbolProperty::IBAnnotated;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::IBAnnotated;
break;
}
case Decl::ObjCProperty:
@@ -223,7 +227,7 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
checkForIBOutlets(D, Info.Properties);
if (auto *Annot = D->getAttr<AnnotateAttr>()) {
if (Annot->getAnnotation() == "gk_inspectable")
- Info.Properties |= (unsigned)SymbolProperty::GKInspectable;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::GKInspectable;
}
break;
case Decl::ObjCIvar:
@@ -268,12 +272,12 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
}
case Decl::ClassTemplate:
Info.Kind = SymbolKind::Class;
- Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
Info.Lang = SymbolLanguage::CXX;
break;
case Decl::FunctionTemplate:
Info.Kind = SymbolKind::Function;
- Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
Info.Lang = SymbolLanguage::CXX;
if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
@@ -294,7 +298,7 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
case Decl::TypeAliasTemplate:
Info.Kind = SymbolKind::TypeAlias;
Info.Lang = SymbolLanguage::CXX;
- Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
break;
case Decl::TypeAlias:
Info.Kind = SymbolKind::TypeAlias;
@@ -304,13 +308,13 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
Info.Kind = SymbolKind::Using;
Info.SubKind = SymbolSubKind::UsingTypename;
Info.Lang = SymbolLanguage::CXX;
- Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
break;
case Decl::UnresolvedUsingValue:
Info.Kind = SymbolKind::Using;
Info.SubKind = SymbolSubKind::UsingValue;
Info.Lang = SymbolLanguage::CXX;
- Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
break;
case Decl::Binding:
Info.Kind = SymbolKind::Variable;
@@ -327,12 +331,13 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->getTemplatedKind() ==
FunctionDecl::TK_FunctionTemplateSpecialization) {
- Info.Properties |= (unsigned)SymbolProperty::Generic;
- Info.Properties |= (unsigned)SymbolProperty::TemplateSpecialization;
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
+ Info.Properties |=
+ (SymbolPropertySet)SymbolProperty::TemplateSpecialization;
}
}
- if (Info.Properties & (unsigned)SymbolProperty::Generic)
+ if (Info.Properties & (SymbolPropertySet)SymbolProperty::Generic)
Info.Lang = SymbolLanguage::CXX;
if (auto *attr = D->getExternalSourceSymbolAttr()) {
@@ -490,9 +495,9 @@ StringRef index::getSymbolLanguageString(SymbolLanguage K) {
void index::applyForEachSymbolProperty(SymbolPropertySet Props,
llvm::function_ref<void(SymbolProperty)> Fn) {
-#define APPLY_FOR_PROPERTY(K) \
- if (Props & (unsigned)SymbolProperty::K) \
- Fn(SymbolProperty::K)
+#define APPLY_FOR_PROPERTY(K) \
+ if (Props & (SymbolPropertySet)SymbolProperty::K) \
+ Fn(SymbolProperty::K)
APPLY_FOR_PROPERTY(Generic);
APPLY_FOR_PROPERTY(TemplatePartialSpecialization);
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index aa2588659ddf..6976294a2eaf 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -209,11 +209,14 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) {
// The facility for "private modules" -- adjacent, optional module maps named
// module.private.modulemap that are supposed to define private submodules --
- // is sometimes misused by frameworks that name their associated private
- // module FooPrivate, rather than as a submodule named Foo.Private as
- // intended. Here we compensate for such cases by looking in directories named
- // Foo.framework, when we previously looked and failed to find a
- // FooPrivate.framework.
+ // may have different flavors of names: FooPrivate, Foo_Private and Foo.Private.
+ //
+ // Foo.Private is now depracated in favor of Foo_Private. Users of FooPrivate
+ // should also rename to Foo_Private. Representing private as submodules
+ // could force building unwanted dependencies into the parent module and cause
+ // dependency cycles.
+ if (!Module && SearchName.consume_back("_Private"))
+ Module = lookupModule(ModuleName, SearchName);
if (!Module && SearchName.consume_back("Private"))
Module = lookupModule(ModuleName, SearchName);
return Module;
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index fbbae7a09520..b3ac10c5c5ae 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -1608,6 +1608,54 @@ namespace {
} // namespace
+/// Private modules are canonicalized as Foo_Private. Clang provides extra
+/// module map search logic to find the appropriate private module when PCH
+/// is used with implicit module maps. Warn when private modules are written
+/// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
+static void diagnosePrivateModules(const ModuleMap &Map,
+ DiagnosticsEngine &Diags,
+ const Module *ActiveModule) {
+
+ auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
+ const Module *M) {
+ auto D = Diags.Report(ActiveModule->DefinitionLoc,
+ diag::note_mmap_rename_top_level_private_module);
+ D << BadName << M->Name;
+ D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, Canonical);
+ };
+
+ for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
+ auto const *M = E->getValue();
+ if (M->Directory != ActiveModule->Directory)
+ continue;
+
+ SmallString<128> FullName(ActiveModule->getFullModuleName());
+ if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
+ continue;
+ SmallString<128> Canonical(M->Name);
+ Canonical.append("_Private");
+
+ // Foo.Private -> Foo_Private
+ if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
+ M->Name == ActiveModule->Parent->Name) {
+ Diags.Report(ActiveModule->DefinitionLoc,
+ diag::warn_mmap_mismatched_private_submodule)
+ << FullName;
+ GenNoteAndFixIt(FullName, Canonical, M);
+ continue;
+ }
+
+ // FooPrivate and whatnots -> Foo_Private
+ if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
+ ActiveModule->Name != Canonical) {
+ Diags.Report(ActiveModule->DefinitionLoc,
+ diag::warn_mmap_mismatched_private_module_name)
+ << ActiveModule->Name;
+ GenNoteAndFixIt(ActiveModule->Name, Canonical, M);
+ }
+ }
+}
+
/// \brief Parse a module declaration.
///
/// module-declaration:
@@ -1791,41 +1839,21 @@ void ModuleMapParser::parseModuleDecl() {
ActiveModule->NoUndeclaredIncludes = true;
ActiveModule->Directory = Directory;
- if (!ActiveModule->Parent) {
- StringRef MapFileName(ModuleMapFile->getName());
- if (MapFileName.endswith("module.private.modulemap") ||
- MapFileName.endswith("module_private.map")) {
- // Adding a top-level module from a private modulemap is likely a
- // user error; we check to see if there's another top-level module
- // defined in the non-private map in the same dir, and if so emit a
- // warning.
- for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
- auto const *M = E->getValue();
- if (!M->Parent &&
- M->Directory == ActiveModule->Directory &&
- M->Name != ActiveModule->Name) {
- Diags.Report(ActiveModule->DefinitionLoc,
- diag::warn_mmap_mismatched_top_level_private)
- << ActiveModule->Name << M->Name;
- // The pattern we're defending against here is typically due to
- // a module named FooPrivate which is supposed to be a submodule
- // called Foo.Private. Emit a fixit in that case.
- auto D =
- Diags.Report(ActiveModule->DefinitionLoc,
- diag::note_mmap_rename_top_level_private_as_submodule);
- D << ActiveModule->Name << M->Name;
- StringRef Bad(ActiveModule->Name);
- if (Bad.consume_back("Private")) {
- SmallString<128> Fixed = Bad;
- Fixed.append(".Private");
- D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc,
- Fixed);
- }
- break;
- }
- }
- }
- }
+
+ // Private modules named as FooPrivate, Foo.Private or similar are likely a
+ // user error; provide warnings, notes and fixits to direct users to use
+ // Foo_Private instead.
+ SourceLocation StartLoc =
+ SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+ StringRef MapFileName(ModuleMapFile->getName());
+ if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
+ !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
+ StartLoc) &&
+ !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
+ StartLoc) &&
+ (MapFileName.endswith("module.private.modulemap") ||
+ MapFileName.endswith("module_private.map")))
+ diagnosePrivateModules(Map, Diags, ActiveModule);
bool Done = false;
do {
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index c291a4b99d10..7d789e780113 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -420,10 +420,9 @@ bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File,
CodeCompletionFile = File;
CodeCompletionOffset = Position - Buffer->getBufferStart();
- std::unique_ptr<MemoryBuffer> NewBuffer =
- MemoryBuffer::getNewUninitMemBuffer(Buffer->getBufferSize() + 1,
- Buffer->getBufferIdentifier());
- char *NewBuf = const_cast<char*>(NewBuffer->getBufferStart());
+ auto NewBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
+ Buffer->getBufferSize() + 1, Buffer->getBufferIdentifier());
+ char *NewBuf = NewBuffer->getBufferStart();
char *NewPos = std::copy(Buffer->getBufferStart(), Position, NewBuf);
*NewPos = '\0';
std::copy(Position, Buffer->getBufferEnd(), NewPos+1);
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 6df9df804fd7..56a16b9e0271 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -372,10 +372,10 @@ bool
Parser::ParseTemplateParameterList(unsigned Depth,
SmallVectorImpl<NamedDecl*> &TemplateParams) {
while (1) {
- // FIXME: ParseTemplateParameter should probably just return a NamedDecl.
- if (Decl *TmpParam
+
+ if (NamedDecl *TmpParam
= ParseTemplateParameter(Depth, TemplateParams.size())) {
- TemplateParams.push_back(dyn_cast<NamedDecl>(TmpParam));
+ TemplateParams.push_back(TmpParam);
} else {
// If we failed to parse a template parameter, skip until we find
// a comma or closing brace.
@@ -480,7 +480,7 @@ bool Parser::isStartOfTemplateTypeParameter() {
/// 'class' ...[opt] identifier[opt]
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
/// = id-expression
-Decl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
+NamedDecl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
if (isStartOfTemplateTypeParameter())
return ParseTypeParameter(Depth, Position);
@@ -502,7 +502,7 @@ Decl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
/// 'class' identifier[opt] '=' type-id
/// 'typename' ...[opt][C++0x] identifier[opt]
/// 'typename' identifier[opt] '=' type-id
-Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
+NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
assert(Tok.isOneOf(tok::kw_class, tok::kw_typename) &&
"A type-parameter starts with 'class' or 'typename'");
@@ -564,7 +564,7 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
/// type-parameter-key:
/// 'class'
/// 'typename' [C++1z]
-Decl *
+NamedDecl *
Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
@@ -669,7 +669,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
/// template-parameter:
/// ...
/// parameter-declaration
-Decl *
+NamedDecl *
Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
// Parse the declaration-specifiers (i.e., the type).
// FIXME: The type should probably be restricted in some way... Not all
diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp
index 23d1895e31b4..618c0179f100 100644
--- a/lib/Rewrite/HTMLRewrite.cpp
+++ b/lib/Rewrite/HTMLRewrite.cpp
@@ -342,6 +342,7 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter &R, FileID FID,
" .CodeInsertionHint { font-weight: bold; background-color: #10dd10 }\n"
" .CodeRemovalHint { background-color:#de1010 }\n"
" .CodeRemovalHint { border-bottom:1px solid #6F9DBE }\n"
+ " .selected{ background-color:orange !important; }\n"
" table.simpletable {\n"
" padding: 5px;\n"
" font-size:12pt;\n"
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 542b65327b7d..3431ddcf70a2 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -562,7 +562,7 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
// Do nothing: Patterns can come with cursor kinds!
break;
}
- // Fall through
+ LLVM_FALLTHROUGH;
case RK_Declaration: {
// Set the availability based on attributes.
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index 865aea9e2284..64fa2c34b238 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -323,7 +323,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
BuildScopeInformation(Var, ParentScope);
++StmtsToSkip;
}
- // Fall through
+ LLVM_FALLTHROUGH;
case Stmt::GotoStmtClass:
// Remember both what scope a goto is in as well as the fact that we have
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 94070bb9c9aa..803f87b3c568 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -2278,7 +2278,7 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
default:
return false;
case X86::BI_mm_prefetch:
- i = 1; l = 0; u = 3;
+ i = 1; l = 0; u = 7;
break;
case X86::BI__builtin_ia32_sha1rnds4:
case X86::BI__builtin_ia32_shuf_f32x4_256_mask:
@@ -3020,7 +3020,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
case AtomicExpr::AO__atomic_add_fetch:
case AtomicExpr::AO__atomic_sub_fetch:
IsAddSub = true;
- // Fall through.
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__c11_atomic_fetch_xor:
@@ -8487,7 +8487,7 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) {
return IntRange(R.Width, /*NonNegative*/ true);
}
}
- // fallthrough
+ LLVM_FALLTHROUGH;
case BO_ShlAssign:
return IntRange::forValueOfType(C, GetExprType(E));
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 834e149d1af4..9aed178763dc 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -1420,7 +1420,7 @@ static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Results.AddResult(Result("mutable"));
Results.AddResult(Result("virtual"));
}
- // Fall through
+ LLVM_FALLTHROUGH;
case Sema::PCC_ObjCInterface:
case Sema::PCC_ObjCImplementation:
@@ -1638,7 +1638,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
AddObjCTopLevelResults(Results, true);
AddTypedefResult(Results);
- // Fall through
+ LLVM_FALLTHROUGH;
case Sema::PCC_Class:
if (SemaRef.getLangOpts().CPlusPlus) {
@@ -1688,7 +1688,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Results.AddResult(Result(Builder.TakeString()));
}
}
- // Fall through
+ LLVM_FALLTHROUGH;
case Sema::PCC_Template:
case Sema::PCC_MemberTemplate:
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index ec5ca6973568..a1fc725f8df4 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -10671,7 +10671,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
// that has an in-class initializer, so we type-check this like
// a declaration.
//
- // Fall through
+ LLVM_FALLTHROUGH;
case VarDecl::DeclarationOnly:
// It's only a declaration.
@@ -12179,9 +12179,11 @@ bool Sema::canSkipFunctionBody(Decl *D) {
}
Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) {
- if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Decl))
+ if (!Decl)
+ return nullptr;
+ if (FunctionDecl *FD = Decl->getAsFunction())
FD->setHasSkippedBody();
- else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(Decl))
+ else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Decl))
MD->setHasSkippedBody();
return Decl;
}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 676d00357c96..21fe46ad9dd1 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1844,12 +1844,6 @@ static void handleIFuncAttr(Sema &S, Decl *D, const AttributeList &Attr) {
S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << FD << 1;
return;
}
- // FIXME: it should be handled as a target specific attribute.
- if (S.Context.getTargetInfo().getTriple().getObjectFormat() !=
- llvm::Triple::ELF) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
- return;
- }
D->addAttr(::new (S.Context) IFuncAttr(Attr.getRange(), S.Context, Str,
Attr.getAttributeSpellingListIndex()));
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 96472a0a70fe..f2fb95c39163 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -8157,7 +8157,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
PastFunctionChunk = true;
break;
}
- // Fall through.
+ LLVM_FALLTHROUGH;
case DeclaratorChunk::Array:
NeedsTypedef = true;
extendRight(After, Chunk.getSourceRange());
@@ -12352,7 +12352,7 @@ static bool hasOneRealArgument(MultiExprArg Args) {
if (!Args[1]->isDefaultArgument())
return false;
- // fall through
+ LLVM_FALLTHROUGH;
case 1:
return !Args[0]->isDefaultArgument();
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 929806ac6bfa..4746355e9800 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -817,7 +817,7 @@ void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) {
E->getLocStart(), nullptr,
PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg)
<< Ty << CT);
- // Fall through.
+ LLVM_FALLTHROUGH;
case VAK_Valid:
if (Ty->isRecordType()) {
// This is unlikely to be what the user intended. If the class has a
@@ -2881,7 +2881,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
valueKind = VK_RValue;
break;
}
- // fallthrough
+ LLVM_FALLTHROUGH;
case Decl::ImplicitParam:
case Decl::ParmVar: {
@@ -2978,7 +2978,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
valueKind = VK_LValue;
break;
}
- // fallthrough
+ LLVM_FALLTHROUGH;
case Decl::CXXConversion:
case Decl::CXXDestructor:
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index 03ddcc0a3eca..dd516ea3b428 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -251,7 +251,7 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
case IMA_Field_Uneval_Context:
Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
<< R.getLookupNameInfo().getName();
- // Fall through.
+ LLVM_FALLTHROUGH;
case IMA_Static:
case IMA_Abstract:
case IMA_Mixed_StaticContext:
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 6ed5047c35da..cd0c2c47ae4c 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -2981,6 +2981,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
case OMF_init:
if (Method)
checkInitMethod(Method, ReceiverType);
+ break;
case OMF_None:
case OMF_alloc:
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index e4789cdf53bf..011051da58e5 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -6212,7 +6212,7 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
if (Entity->getParent())
return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
Entity);
- // Fall through.
+ LLVM_FALLTHROUGH;
case InitializedEntity::EK_Delegating:
// We can reach this case for aggregate initialization in a constructor:
// struct A { int &&r; };
@@ -7656,7 +7656,7 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->getSourceRange();
break;
}
- // Intentional fallthrough
+ LLVM_FALLTHROUGH;
case FK_NonConstLValueReferenceBindingToUnrelated:
S.Diag(Kind.getLocation(),
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index b34bb3388d71..0880b2d79060 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -1290,9 +1290,14 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) {
}
if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
- IsByRef = !DSAStack->hasExplicitDSA(
- D, [](OpenMPClauseKind K) -> bool { return K == OMPC_firstprivate; },
- Level, /*NotLastprivate=*/true);
+ IsByRef =
+ !DSAStack->hasExplicitDSA(
+ D,
+ [](OpenMPClauseKind K) -> bool { return K == OMPC_firstprivate; },
+ Level, /*NotLastprivate=*/true) &&
+ // If the variable is artificial and must be captured by value - try to
+ // capture by value.
+ !(isa<OMPCapturedExprDecl>(D) && D->hasAttr<OMPCaptureKindAttr>());
}
// When passing data by copy, we need to make sure it fits the uintptr size
@@ -2321,10 +2326,11 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
ASTContext &C = S.getASTContext();
Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
QualType Ty = Init->getType();
+ Attr *OMPCaptureKind = nullptr;
if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
- if (S.getLangOpts().CPlusPlus)
+ if (S.getLangOpts().CPlusPlus) {
Ty = C.getLValueReferenceType(Ty);
- else {
+ } else {
Ty = C.getPointerType(Ty);
ExprResult Res =
S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
@@ -2333,11 +2339,16 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
Init = Res.get();
}
WithInit = true;
+ } else if (AsExpression) {
+ // This variable must be captured by value.
+ OMPCaptureKind = OMPCaptureKindAttr::CreateImplicit(C, OMPC_unknown);
}
auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty,
CaptureExpr->getLocStart());
if (!WithInit)
CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C, SourceRange()));
+ if (OMPCaptureKind)
+ CED->addAttr(OMPCaptureKind);
S.CurContext->addHiddenDecl(CED);
S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
return CED;
@@ -2346,31 +2357,34 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
bool WithInit) {
OMPCapturedExprDecl *CD;
- if (auto *VD = S.IsOpenMPCapturedDecl(D))
+ if (auto *VD = S.IsOpenMPCapturedDecl(D)) {
CD = cast<OMPCapturedExprDecl>(VD);
- else
+ } else {
CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
/*AsExpression=*/false);
+ }
return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
CaptureExpr->getExprLoc());
}
static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref) {
+ CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
if (!Ref) {
- auto *CD =
- buildCaptureDecl(S, &S.getASTContext().Idents.get(".capture_expr."),
- CaptureExpr, /*WithInit=*/true, /*AsExpression=*/true);
+ OMPCapturedExprDecl *CD = buildCaptureDecl(
+ S, &S.getASTContext().Idents.get(".capture_expr."), CaptureExpr,
+ /*WithInit=*/true, /*AsExpression=*/true);
Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
CaptureExpr->getExprLoc());
}
ExprResult Res = Ref;
if (!S.getLangOpts().CPlusPlus &&
CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
- Ref->getType()->isPointerType())
+ Ref->getType()->isPointerType()) {
Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
- if (!Res.isUsable())
- return ExprError();
- return CaptureExpr->isGLValue() ? Res : S.DefaultLvalueConversion(Res.get());
+ if (!Res.isUsable())
+ return ExprError();
+ }
+ return S.DefaultLvalueConversion(Res.get());
}
namespace {
@@ -8117,12 +8131,13 @@ OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
if (Val.isInvalid())
return nullptr;
- ValExpr = MakeFullExpr(Val.get()).get();
+ ValExpr = Val.get();
OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
CaptureRegion =
getOpenMPCaptureRegionForClause(DKind, OMPC_if, NameModifier);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
+ ValExpr = MakeFullExpr(ValExpr).get();
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
@@ -8239,6 +8254,7 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
OpenMPDirectiveKind CaptureRegion =
getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
+ ValExpr = MakeFullExpr(ValExpr).get();
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
@@ -8666,6 +8682,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(
DSAStack->getCurrentDirective(), OMPC_schedule) !=
OMPD_unknown &&
!CurContext->isDependentContext()) {
+ ValExpr = MakeFullExpr(ValExpr).get();
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
@@ -11355,6 +11372,7 @@ OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
OpenMPDirectiveKind CaptureRegion =
getOpenMPCaptureRegionForClause(DKind, OMPC_device);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
+ ValExpr = MakeFullExpr(ValExpr).get();
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
@@ -12378,6 +12396,7 @@ OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
OpenMPDirectiveKind CaptureRegion =
getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
+ ValExpr = MakeFullExpr(ValExpr).get();
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
@@ -12404,6 +12423,7 @@ OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
OpenMPDirectiveKind CaptureRegion =
getOpenMPCaptureRegionForClause(DKind, OMPC_thread_limit);
if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
+ ValExpr = MakeFullExpr(ValExpr).get();
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
@@ -12514,6 +12534,7 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause(
DSAStack->getCurrentDirective(), OMPC_dist_schedule) !=
OMPD_unknown &&
!CurContext->isDependentContext()) {
+ ValExpr = MakeFullExpr(ValExpr).get();
llvm::MapVector<Expr *, DeclRefExpr *> Captures;
ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
HelperValStmt = buildPreInits(Context, Captures);
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 268be9430a56..2144845f4dd3 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -5790,7 +5790,7 @@ ExprResult Sema::PerformContextualImplicitConversion(
HadMultipleCandidates,
ExplicitConversions))
return ExprError();
- // fall through 'OR_Deleted' case.
+ LLVM_FALLTHROUGH;
case OR_Deleted:
// We'll complain below about a non-integral condition type.
break;
@@ -8651,7 +8651,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
case OO_Plus: // '+' is either unary or binary
if (Args.size() == 1)
OpBuilder.addUnaryPlusPointerOverloads();
- // Fall through.
+ LLVM_FALLTHROUGH;
case OO_Minus: // '-' is either unary or binary
if (Args.size() == 1) {
@@ -8682,7 +8682,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
case OO_EqualEqual:
case OO_ExclaimEqual:
OpBuilder.addEqualEqualOrNotEqualMemberPointerOrNullptrOverloads();
- // Fall through.
+ LLVM_FALLTHROUGH;
case OO_Less:
case OO_Greater:
@@ -8719,12 +8719,12 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
case OO_Equal:
OpBuilder.addAssignmentMemberPointerOrEnumeralOverloads();
- // Fall through.
+ LLVM_FALLTHROUGH;
case OO_PlusEqual:
case OO_MinusEqual:
OpBuilder.addAssignmentPointerOverloads(Op == OO_Equal);
- // Fall through.
+ LLVM_FALLTHROUGH;
case OO_StarEqual:
case OO_SlashEqual:
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index c70a8ba8f126..d94cb0d0f485 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -792,7 +792,7 @@ static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S,
/// ParamNameLoc is the location of the parameter name (if any).
/// If the type parameter has a default argument, it will be added
/// later via ActOnTypeParameterDefault.
-Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
+NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
@@ -922,13 +922,67 @@ QualType Sema::CheckNonTypeTemplateParameterType(QualType T,
return QualType();
}
-Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
unsigned Depth,
unsigned Position,
SourceLocation EqualLoc,
Expr *Default) {
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ // Check that we have valid decl-specifiers specified.
+ auto CheckValidDeclSpecifiers = [this, &D] {
+ // C++ [temp.param]
+ // p1
+ // template-parameter:
+ // ...
+ // parameter-declaration
+ // p2
+ // ... A storage class shall not be specified in a template-parameter
+ // declaration.
+ // [dcl.typedef]p1:
+ // The typedef specifier [...] shall not be used in the decl-specifier-seq
+ // of a parameter-declaration
+ const DeclSpec &DS = D.getDeclSpec();
+ auto EmitDiag = [this](SourceLocation Loc) {
+ Diag(Loc, diag::err_invalid_decl_specifier_in_nontype_parm)
+ << FixItHint::CreateRemoval(Loc);
+ };
+ if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified)
+ EmitDiag(DS.getStorageClassSpecLoc());
+
+ if (DS.getThreadStorageClassSpec() != TSCS_unspecified)
+ EmitDiag(DS.getThreadStorageClassSpecLoc());
+
+ // [dcl.inline]p1:
+ // The inline specifier can be applied only to the declaration or
+ // definition of a variable or function.
+
+ if (DS.isInlineSpecified())
+ EmitDiag(DS.getInlineSpecLoc());
+
+ // [dcl.constexpr]p1:
+ // The constexpr specifier shall be applied only to the definition of a
+ // variable or variable template or the declaration of a function or
+ // function template.
+
+ if (DS.isConstexprSpecified())
+ EmitDiag(DS.getConstexprSpecLoc());
+
+ // [dcl.fct.spec]p1:
+ // Function-specifiers can be used only in function declarations.
+
+ if (DS.isVirtualSpecified())
+ EmitDiag(DS.getVirtualSpecLoc());
+
+ if (DS.isExplicitSpecified())
+ EmitDiag(DS.getExplicitSpecLoc());
+
+ if (DS.isNoreturnSpecified())
+ EmitDiag(DS.getNoreturnSpecLoc());
+ };
+
+ CheckValidDeclSpecifiers();
+
if (TInfo->getType()->isUndeducedType()) {
Diag(D.getIdentifierLoc(),
diag::warn_cxx14_compat_template_nontype_parm_auto_type)
@@ -999,7 +1053,7 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
/// ActOnTemplateTemplateParameter - Called when a C++ template template
/// parameter (e.g. T in template <template \<typename> class T> class array)
/// has been parsed. S is the current scope.
-Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
+NamedDecl *Sema::ActOnTemplateTemplateParameter(Scope* S,
SourceLocation TmpLoc,
TemplateParameterList *Params,
SourceLocation EllipsisLoc,
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 564692b03020..f8ee60251698 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -5324,7 +5324,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
case Type::InjectedClassName:
T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType();
- // fall through
+ LLVM_FALLTHROUGH;
case Type::TemplateSpecialization: {
const TemplateSpecializationType *Spec
@@ -5431,6 +5431,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
MarkUsedTemplateParameters(Ctx,
cast<DeducedType>(T)->getDeducedType(),
OnlyDeduced, Depth, Used);
+ break;
// None of these types have any template parameters in them.
case Type::Builtin:
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index f627f6017f38..1deb8638756b 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1587,9 +1587,10 @@ static QualType adjustFunctionTypeForInstantiation(ASTContext &Context,
}
/// Normal class members are of more specific types and therefore
-/// don't make it here. This function serves two purposes:
+/// don't make it here. This function serves three purposes:
/// 1) instantiating function templates
/// 2) substituting friend declarations
+/// 3) substituting deduction guide declarations for nested class templates
Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
TemplateParameterList *TemplateParams) {
// Check whether there is already a function template specialization for
@@ -1650,16 +1651,19 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
TemplateArgs);
}
+ DeclarationNameInfo NameInfo
+ = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
+
FunctionDecl *Function;
if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) {
Function = CXXDeductionGuideDecl::Create(
SemaRef.Context, DC, D->getInnerLocStart(), DGuide->isExplicit(),
- D->getNameInfo(), T, TInfo, D->getSourceRange().getEnd());
+ NameInfo, T, TInfo, D->getSourceRange().getEnd());
if (DGuide->isCopyDeductionCandidate())
cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate();
} else {
Function = FunctionDecl::Create(
- SemaRef.Context, DC, D->getInnerLocStart(), D->getNameInfo(), T, TInfo,
+ SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo,
D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(),
D->hasWrittenPrototype(), D->isConstexpr());
Function->setRangeEnd(D->getSourceRange().getEnd());
@@ -3855,7 +3859,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
}
// Note, we should never try to instantiate a deleted function template.
- assert((Pattern || PatternDecl->isDefaulted()) &&
+ assert((Pattern || PatternDecl->isDefaulted() ||
+ PatternDecl->hasSkippedBody()) &&
"unexpected kind of function template definition");
// C++1y [temp.explicit]p10:
@@ -3940,16 +3945,20 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
}
}
- // Instantiate the function body.
- StmtResult Body = SubstStmt(Pattern, TemplateArgs);
+ if (PatternDecl->hasSkippedBody()) {
+ ActOnSkippedFunctionBody(Function);
+ } else {
+ // Instantiate the function body.
+ StmtResult Body = SubstStmt(Pattern, TemplateArgs);
- if (Body.isInvalid())
- Function->setInvalidDecl();
+ 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);
@@ -5195,7 +5204,9 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
case TSK_ExplicitInstantiationDefinition:
// We only need an instantiation if the pending instantiation *is* the
// explicit instantiation.
- if (Var != Var->getMostRecentDecl()) continue;
+ if (Var != Var->getMostRecentDecl())
+ continue;
+ break;
case TSK_ImplicitInstantiation:
break;
}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 2fffe8e17970..2530b766f5f7 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -367,7 +367,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
if (onlyBlockPointers)
continue;
- // fallthrough
+ LLVM_FALLTHROUGH;
case DeclaratorChunk::BlockPointer:
result = &ptrChunk;
@@ -1340,7 +1340,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
}
- // FALL THROUGH.
+ LLVM_FALLTHROUGH;
case DeclSpec::TST_int: {
if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
switch (DS.getTypeSpecWidth()) {
@@ -3137,10 +3137,15 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
(T->isRecordType() || T->isDependentType()) &&
D.getDeclSpec().getTypeQualifiers() == 0 && D.isFirstDeclarator();
+ bool StartsWithDeclaratorId = true;
for (auto &C : D.type_objects()) {
switch (C.Kind) {
- case DeclaratorChunk::Pointer:
case DeclaratorChunk::Paren:
+ if (&C == &Paren)
+ continue;
+ LLVM_FALLTHROUGH;
+ case DeclaratorChunk::Pointer:
+ StartsWithDeclaratorId = false;
continue;
case DeclaratorChunk::Array:
@@ -3154,18 +3159,25 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
// We assume that something like 'T (&x) = y;' is highly likely to not
// be intended to be a temporary object.
CouldBeTemporaryObject = false;
+ StartsWithDeclaratorId = false;
continue;
case DeclaratorChunk::Function:
// In a new-type-id, function chunks require parentheses.
if (D.getContext() == Declarator::CXXNewContext)
return;
- LLVM_FALLTHROUGH;
+ // FIXME: "A(f())" deserves a vexing-parse warning, not just a
+ // redundant-parens warning, but we don't know whether the function
+ // chunk was syntactically valid as an expression here.
+ CouldBeTemporaryObject = false;
+ continue;
+
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Pipe:
// These cannot appear in expressions.
CouldBeTemporaryObject = false;
+ StartsWithDeclaratorId = false;
continue;
}
}
@@ -3186,6 +3198,18 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
SourceRange ParenRange(Paren.Loc, Paren.EndLoc);
if (!CouldBeTemporaryObject) {
+ // If we have A (::B), the parentheses affect the meaning of the program.
+ // Suppress the warning in that case. Don't bother looking at the DeclSpec
+ // here: even (e.g.) "int ::x" is visually ambiguous even though it's
+ // formally unambiguous.
+ if (StartsWithDeclaratorId && D.getCXXScopeSpec().isValid()) {
+ for (NestedNameSpecifier *NNS = D.getCXXScopeSpec().getScopeRep(); NNS;
+ NNS = NNS->getPrefix()) {
+ if (NNS->getKind() == NestedNameSpecifier::Global)
+ return;
+ }
+ }
+
S.Diag(Paren.Loc, diag::warn_redundant_parens_around_declarator)
<< ParenRange << FixItHint::CreateRemoval(Paren.Loc)
<< FixItHint::CreateRemoval(Paren.EndLoc);
@@ -3890,7 +3914,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case Declarator::PrototypeContext:
case Declarator::TrailingReturnContext:
isFunctionOrMethod = true;
- // fallthrough
+ LLVM_FALLTHROUGH;
case Declarator::MemberContext:
if (state.getDeclarator().isObjCIvar() && !isFunctionOrMethod) {
@@ -3904,7 +3928,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
}
- // fallthrough
+ LLVM_FALLTHROUGH;
case Declarator::FileContext:
case Declarator::KNRTypeListContext: {
@@ -4063,7 +4087,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case CAMN_InnerPointers:
if (NumPointersRemaining == 0)
break;
- // Fallthrough.
+ LLVM_FALLTHROUGH;
case CAMN_Yes:
checkNullabilityConsistency(S, pointerKind, pointerLoc, pointerEndLoc);
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 111ac4fcdaa4..4ed822e04f6c 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -9235,8 +9235,16 @@ void ASTReader::finishPendingActions() {
const FunctionDecl *Defn = nullptr;
if (!getContext().getLangOpts().Modules || !FD->hasBody(Defn)) {
FD->setLazyBody(PB->second);
- } else
- mergeDefinitionVisibility(const_cast<FunctionDecl*>(Defn), FD);
+ } else {
+ auto *NonConstDefn = const_cast<FunctionDecl*>(Defn);
+ mergeDefinitionVisibility(NonConstDefn, FD);
+
+ if (!FD->isLateTemplateParsed() &&
+ !NonConstDefn->isLateTemplateParsed() &&
+ FD->getODRHash() != NonConstDefn->getODRHash()) {
+ PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn);
+ }
+ }
continue;
}
@@ -9253,7 +9261,8 @@ void ASTReader::finishPendingActions() {
}
void ASTReader::diagnoseOdrViolations() {
- if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty())
+ if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty() &&
+ PendingFunctionOdrMergeFailures.empty())
return;
// Trigger the import of the full definition of each class that had any
@@ -9275,6 +9284,20 @@ void ASTReader::diagnoseOdrViolations() {
}
}
+ // Trigger the import of functions.
+ auto FunctionOdrMergeFailures = std::move(PendingFunctionOdrMergeFailures);
+ PendingFunctionOdrMergeFailures.clear();
+ for (auto &Merge : FunctionOdrMergeFailures) {
+ Merge.first->buildLookup();
+ Merge.first->decls_begin();
+ Merge.first->getBody();
+ for (auto &FD : Merge.second) {
+ FD->buildLookup();
+ FD->decls_begin();
+ FD->getBody();
+ }
+ }
+
// For each declaration from a merged context, check that the canonical
// definition of that context also contains a declaration of the same
// entity.
@@ -9357,13 +9380,35 @@ void ASTReader::diagnoseOdrViolations() {
}
}
- if (OdrMergeFailures.empty())
+ if (OdrMergeFailures.empty() && FunctionOdrMergeFailures.empty())
return;
// Ensure we don't accidentally recursively enter deserialization while
// we're producing our diagnostics.
Deserializing RecursionGuard(this);
+ // Common code for hashing helpers.
+ ODRHash Hash;
+ auto ComputeQualTypeODRHash = [&Hash](QualType Ty) {
+ Hash.clear();
+ Hash.AddQualType(Ty);
+ return Hash.CalculateHash();
+ };
+
+ auto ComputeODRHash = [&Hash](const Stmt *S) {
+ assert(S);
+ Hash.clear();
+ Hash.AddStmt(S);
+ return Hash.CalculateHash();
+ };
+
+ auto ComputeSubDeclODRHash = [&Hash](const Decl *D) {
+ assert(D);
+ Hash.clear();
+ Hash.AddSubDecl(D);
+ return Hash.CalculateHash();
+ };
+
// Issue any pending ODR-failure diagnostics.
for (auto &Merge : OdrMergeFailures) {
// If we've already pointed out a specific problem with this class, don't
@@ -9411,13 +9456,6 @@ void ASTReader::diagnoseOdrViolations() {
<< SecondModule << Range << DiffType;
};
- ODRHash Hash;
- auto ComputeQualTypeODRHash = [&Hash](QualType Ty) {
- Hash.clear();
- Hash.AddQualType(Ty);
- return Hash.CalculateHash();
- };
-
unsigned FirstNumBases = FirstDD->NumBases;
unsigned FirstNumVBases = FirstDD->NumVBases;
unsigned SecondNumBases = SecondDD->NumBases;
@@ -9520,14 +9558,12 @@ void ASTReader::diagnoseOdrViolations() {
if (FirstTemplate && SecondTemplate) {
DeclHashes FirstTemplateHashes;
DeclHashes SecondTemplateHashes;
- ODRHash Hash;
auto PopulateTemplateParameterHashs =
- [&Hash](DeclHashes &Hashes, const ClassTemplateDecl *TD) {
+ [&ComputeSubDeclODRHash](DeclHashes &Hashes,
+ const ClassTemplateDecl *TD) {
for (auto *D : TD->getTemplateParameters()->asArray()) {
- Hash.clear();
- Hash.AddSubDecl(D);
- Hashes.emplace_back(D, Hash.CalculateHash());
+ Hashes.emplace_back(D, ComputeSubDeclODRHash(D));
}
};
@@ -9696,18 +9732,15 @@ void ASTReader::diagnoseOdrViolations() {
DeclHashes FirstHashes;
DeclHashes SecondHashes;
- ODRHash Hash;
- auto PopulateHashes = [&Hash, FirstRecord](DeclHashes &Hashes,
- CXXRecordDecl *Record) {
+ auto PopulateHashes = [&ComputeSubDeclODRHash, FirstRecord](
+ DeclHashes &Hashes, CXXRecordDecl *Record) {
for (auto *D : Record->decls()) {
// Due to decl merging, the first CXXRecordDecl is the parent of
// Decls in both records.
if (!ODRHash::isWhitelistedDecl(D, FirstRecord))
continue;
- Hash.clear();
- Hash.AddSubDecl(D);
- Hashes.emplace_back(D, Hash.CalculateHash());
+ Hashes.emplace_back(D, ComputeSubDeclODRHash(D));
}
};
PopulateHashes(FirstHashes, FirstRecord);
@@ -9901,19 +9934,6 @@ void ASTReader::diagnoseOdrViolations() {
<< SecondModule << Range << DiffType;
};
- auto ComputeODRHash = [&Hash](const Stmt* S) {
- assert(S);
- Hash.clear();
- Hash.AddStmt(S);
- return Hash.CalculateHash();
- };
-
- auto ComputeQualTypeODRHash = [&Hash](QualType Ty) {
- Hash.clear();
- Hash.AddQualType(Ty);
- return Hash.CalculateHash();
- };
-
switch (FirstDiffType) {
case Other:
case EndOfClass:
@@ -10488,6 +10508,160 @@ void ASTReader::diagnoseOdrViolations() {
<< Merge.first;
}
}
+
+ // Issue ODR failures diagnostics for functions.
+ for (auto &Merge : FunctionOdrMergeFailures) {
+ enum ODRFunctionDifference {
+ ReturnType,
+ ParameterName,
+ ParameterType,
+ ParameterSingleDefaultArgument,
+ ParameterDifferentDefaultArgument,
+ FunctionBody,
+ };
+
+ FunctionDecl *FirstFunction = Merge.first;
+ std::string FirstModule = getOwningModuleNameForDiagnostic(FirstFunction);
+
+ bool Diagnosed = false;
+ for (auto &SecondFunction : Merge.second) {
+
+ if (FirstFunction == SecondFunction)
+ continue;
+
+ std::string SecondModule =
+ getOwningModuleNameForDiagnostic(SecondFunction);
+
+ auto ODRDiagError = [FirstFunction, &FirstModule,
+ this](SourceLocation Loc, SourceRange Range,
+ ODRFunctionDifference DiffType) {
+ return Diag(Loc, diag::err_module_odr_violation_function)
+ << FirstFunction << FirstModule.empty() << FirstModule << Range
+ << DiffType;
+ };
+ auto ODRDiagNote = [&SecondModule, this](SourceLocation Loc,
+ SourceRange Range,
+ ODRFunctionDifference DiffType) {
+ return Diag(Loc, diag::note_module_odr_violation_function)
+ << SecondModule << Range << DiffType;
+ };
+
+ if (ComputeQualTypeODRHash(FirstFunction->getReturnType()) !=
+ ComputeQualTypeODRHash(SecondFunction->getReturnType())) {
+ ODRDiagError(FirstFunction->getReturnTypeSourceRange().getBegin(),
+ FirstFunction->getReturnTypeSourceRange(), ReturnType)
+ << FirstFunction->getReturnType();
+ ODRDiagNote(SecondFunction->getReturnTypeSourceRange().getBegin(),
+ SecondFunction->getReturnTypeSourceRange(), ReturnType)
+ << SecondFunction->getReturnType();
+ Diagnosed = true;
+ break;
+ }
+
+ assert(FirstFunction->param_size() == SecondFunction->param_size() &&
+ "Merged functions with different number of parameters");
+
+ auto ParamSize = FirstFunction->param_size();
+ bool ParameterMismatch = false;
+ for (unsigned I = 0; I < ParamSize; ++I) {
+ auto *FirstParam = FirstFunction->getParamDecl(I);
+ auto *SecondParam = SecondFunction->getParamDecl(I);
+
+ assert(getContext().hasSameType(FirstParam->getType(),
+ SecondParam->getType()) &&
+ "Merged function has different parameter types.");
+
+ if (FirstParam->getDeclName() != SecondParam->getDeclName()) {
+ ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
+ ParameterName)
+ << I + 1 << FirstParam->getDeclName();
+ ODRDiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
+ ParameterName)
+ << I + 1 << SecondParam->getDeclName();
+ ParameterMismatch = true;
+ break;
+ };
+
+ QualType FirstParamType = FirstParam->getType();
+ QualType SecondParamType = SecondParam->getType();
+ if (FirstParamType != SecondParamType &&
+ ComputeQualTypeODRHash(FirstParamType) !=
+ ComputeQualTypeODRHash(SecondParamType)) {
+ if (const DecayedType *ParamDecayedType =
+ FirstParamType->getAs<DecayedType>()) {
+ ODRDiagError(FirstParam->getLocation(),
+ FirstParam->getSourceRange(), ParameterType)
+ << (I + 1) << FirstParamType << true
+ << ParamDecayedType->getOriginalType();
+ } else {
+ ODRDiagError(FirstParam->getLocation(),
+ FirstParam->getSourceRange(), ParameterType)
+ << (I + 1) << FirstParamType << false;
+ }
+
+ if (const DecayedType *ParamDecayedType =
+ SecondParamType->getAs<DecayedType>()) {
+ ODRDiagNote(SecondParam->getLocation(),
+ SecondParam->getSourceRange(), ParameterType)
+ << (I + 1) << SecondParamType << true
+ << ParamDecayedType->getOriginalType();
+ } else {
+ ODRDiagNote(SecondParam->getLocation(),
+ SecondParam->getSourceRange(), ParameterType)
+ << (I + 1) << SecondParamType << false;
+ }
+ ParameterMismatch = true;
+ break;
+ }
+
+ const Expr *FirstInit = FirstParam->getInit();
+ const Expr *SecondInit = SecondParam->getInit();
+ if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
+ ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
+ ParameterSingleDefaultArgument)
+ << (I + 1) << (FirstInit == nullptr)
+ << (FirstInit ? FirstInit->getSourceRange() : SourceRange());
+ ODRDiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
+ ParameterSingleDefaultArgument)
+ << (I + 1) << (SecondInit == nullptr)
+ << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
+ ParameterMismatch = true;
+ break;
+ }
+
+ if (FirstInit && SecondInit &&
+ ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
+ ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
+ ParameterDifferentDefaultArgument)
+ << (I + 1) << FirstInit->getSourceRange();
+ ODRDiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
+ ParameterDifferentDefaultArgument)
+ << (I + 1) << SecondInit->getSourceRange();
+ ParameterMismatch = true;
+ break;
+ }
+
+ assert(ComputeSubDeclODRHash(FirstParam) ==
+ ComputeSubDeclODRHash(SecondParam) &&
+ "Undiagnosed parameter difference.");
+ }
+
+ if (ParameterMismatch) {
+ Diagnosed = true;
+ break;
+ }
+
+ // If no error has been generated before now, assume the problem is in
+ // the body and generate a message.
+ ODRDiagError(FirstFunction->getLocation(),
+ FirstFunction->getSourceRange(), FunctionBody);
+ ODRDiagNote(SecondFunction->getLocation(),
+ SecondFunction->getSourceRange(), FunctionBody);
+ Diagnosed = true;
+ break;
+ }
+ assert(Diagnosed && "Unable to emit ODR diagnostic.");
+ }
}
void ASTReader::StartedDeserializing() {
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index a3bf0d971267..efbaf92a849a 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -796,6 +796,9 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setCachedLinkage(Linkage(Record.readInt()));
FD->EndRangeLoc = ReadSourceLocation();
+ FD->ODRHash = Record.readInt();
+ FD->HasODRHash = true;
+
switch ((FunctionDecl::TemplatedKind)Record.readInt()) {
case FunctionDecl::TK_NonTemplate:
mergeRedeclarable(FD, Redecl);
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 3dac3a48297a..bb72a3b383ea 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -538,6 +538,8 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Record.push_back(D->getLinkageInternal());
Record.AddSourceLocation(D->getLocEnd());
+ Record.push_back(D->getODRHash());
+
Record.push_back(D->getTemplatedKind());
switch (D->getTemplatedKind()) {
case FunctionDecl::TK_NonTemplate:
@@ -2072,6 +2074,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind
// This Array slurps the rest of the record. Fortunately we want to encode
// (nearly) all the remaining (variable number of) fields in the same way.
diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
index 23b43759a34b..db9179e018a1 100644
--- a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -22,6 +22,7 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/AST/ParentMap.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -262,8 +263,19 @@ void DynamicTypePropagation::checkPostCall(const CallEvent &Call,
if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) {
// We just finished a base constructor. Now we can use the subclass's
// type when resolving virtual calls.
- const Decl *D = C.getLocationContext()->getDecl();
- recordFixedType(Target, cast<CXXConstructorDecl>(D), C);
+ const LocationContext *LCtx = C.getLocationContext();
+
+ // FIXME: In C++17 classes with non-virtual bases may be treated as
+ // aggregates, and in such case no top-frame constructor will be called.
+ // Figure out if we need to do anything in this case.
+ // FIXME: Instead of relying on the ParentMap, we should have the
+ // trigger-statement (InitListExpr in this case) available in this
+ // callback, ideally as part of CallEvent.
+ if (dyn_cast_or_null<InitListExpr>(
+ LCtx->getParentMap().getParent(Ctor->getOriginExpr())))
+ return;
+
+ recordFixedType(Target, cast<CXXConstructorDecl>(LCtx->getDecl()), C);
}
return;
}
diff --git a/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
index a51dda6fe858..6c0c53dd64cb 100644
--- a/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -293,7 +293,9 @@ public:
SmallString<100> Buf;
llvm::raw_svector_ostream Os(Buf);
Os << "Excessive padding in '";
- Os << QualType::getAsString(RD->getTypeForDecl(), Qualifiers()) << "'";
+ Os << QualType::getAsString(RD->getTypeForDecl(), Qualifiers(),
+ LangOptions())
+ << "'";
if (auto *TSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
// TODO: make this show up better in the console output and in
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 4a5d25fc5634..dc284888eb03 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -885,8 +885,12 @@ static bool GenerateMinimalPathDiagnostic(
if (NextNode) {
// Add diagnostic pieces from custom visitors.
BugReport *R = PDB.getBugReport();
+ llvm::FoldingSet<PathDiagnosticPiece> DeduplicationSet;
for (auto &V : visitors) {
if (auto p = V->VisitNode(N, NextNode, PDB, *R)) {
+ if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get())
+ continue;
+
updateStackPiecesWithMessage(*p, CallStack);
PD.getActivePath().push_front(std::move(p));
}
@@ -1584,8 +1588,12 @@ static bool GenerateExtensivePathDiagnostic(
// Add pieces from custom visitors.
BugReport *R = PDB.getBugReport();
+ llvm::FoldingSet<PathDiagnosticPiece> DeduplicationSet;
for (auto &V : visitors) {
if (auto p = V->VisitNode(N, NextNode, PDB, *R)) {
+ if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get())
+ continue;
+
const PathDiagnosticLocation &Loc = p->getLocation();
EB.addEdge(Loc, true);
updateStackPiecesWithMessage(*p, CallStack);
@@ -1879,8 +1887,12 @@ static bool GenerateAlternateExtensivePathDiagnostic(
continue;
// Add pieces from custom visitors.
+ llvm::FoldingSet<PathDiagnosticPiece> DeduplicationSet;
for (auto &V : visitors) {
if (auto p = V->VisitNode(N, NextNode, PDB, *report)) {
+ if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get())
+ continue;
+
addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);
updateStackPiecesWithMessage(*p, CallStack);
PD.getActivePath().push_front(std::move(p));
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 7304d789431e..972f4c5f3da2 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -985,12 +985,8 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
if (!S || !N)
return false;
- if (const Expr *Ex = dyn_cast<Expr>(S)) {
- Ex = Ex->IgnoreParenCasts();
- const Expr *PeeledEx = peelOffOuterExpr(Ex, N);
- if (Ex != PeeledEx)
- S = PeeledEx;
- }
+ if (const Expr *Ex = dyn_cast<Expr>(S))
+ S = peelOffOuterExpr(Ex, N);
const Expr *Inner = nullptr;
if (const Expr *Ex = dyn_cast<Expr>(S)) {
@@ -1142,9 +1138,12 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
else
RVal = state->getSVal(L->getRegion());
- const MemRegion *RegionRVal = RVal.getAsRegion();
report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
+ if (Optional<KnownSVal> KV = RVal.getAs<KnownSVal>())
+ report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
+ *KV, L->getRegion(), EnableNullFPSuppression));
+ const MemRegion *RegionRVal = RVal.getAsRegion();
if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
report.markInteresting(RegionRVal);
report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 03e0095d0e83..dad93111966f 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/AST/ParentMap.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
@@ -267,6 +268,23 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
}
// FALLTHROUGH
case CXXConstructExpr::CK_NonVirtualBase:
+ // In C++17, classes with non-virtual bases may be aggregates, so they would
+ // be initialized as aggregates without a constructor call, so we may have
+ // a base class constructed directly into an initializer list without
+ // having the derived-class constructor call on the previous stack frame.
+ // Initializer lists may be nested into more initializer lists that
+ // correspond to surrounding aggregate initializations.
+ // FIXME: For now this code essentially bails out. We need to find the
+ // correct target region and set it.
+ // FIXME: Instead of relying on the ParentMap, we should have the
+ // trigger-statement (InitListExpr in this case) passed down from CFG or
+ // otherwise always available during construction.
+ if (dyn_cast_or_null<InitListExpr>(LCtx->getParentMap().getParent(CE))) {
+ MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
+ Target = MRMgr.getCXXTempObjectRegion(CE, LCtx);
+ break;
+ }
+ // FALLTHROUGH
case CXXConstructExpr::CK_Delegating: {
const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
diff --git a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index 9b820e81e374..ebf1487d4bfc 100644
--- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -91,6 +91,9 @@ public:
// Rewrite the file specified by FID with HTML formatting.
void RewriteFile(Rewriter &R, const SourceManager& SMgr,
const PathPieces& path, FileID FID);
+
+ /// \return Javascript for navigating the HTML report using j/k keys.
+ std::string generateKeyboardNavigationJavascript();
};
} // end anonymous namespace
@@ -337,6 +340,9 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
int LineNumber = path.back()->getLocation().asLocation().getExpansionLineNumber();
int ColumnNumber = path.back()->getLocation().asLocation().getExpansionColumnNumber();
+ R.InsertTextBefore(SMgr.getLocForStartOfFile(FID),
+ generateKeyboardNavigationJavascript());
+
// Add the name of the file as an <h1> tag.
{
std::string s;
@@ -378,8 +384,14 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
os << "<tr><td></td><td>" << html::EscapeText(*I) << "</td></tr>\n";
}
- os << "</table>\n<!-- REPORTSUMMARYEXTRA -->\n"
- "<h3>Annotated Source Code</h3>\n";
+ os << R"<<<(
+</table>
+<!-- REPORTSUMMARYEXTRA -->
+<h3>Annotated Source Code</h3>
+<p><span class='macro'>[?]
+ <span class='expansion'>Use j/k keys for keyboard navigation</span>
+</span></p>
+)<<<";
R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
}
@@ -777,3 +789,82 @@ void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID,
html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd);
}
+
+std::string HTMLDiagnostics::generateKeyboardNavigationJavascript() {
+ return R"<<<(
+<script type='text/javascript'>
+var digitMatcher = new RegExp("[0-9]+");
+
+document.addEventListener("DOMContentLoaded", function() {
+ document.querySelectorAll(".PathNav > a").forEach(
+ function(currentValue, currentIndex) {
+ var hrefValue = currentValue.getAttribute("href");
+ currentValue.onclick = function() {
+ scrollTo(document.querySelector(hrefValue));
+ return false;
+ };
+ });
+});
+
+var findNum = function() {
+ var s = document.querySelector(".selected");
+ if (!s || s.id == "EndPath") {
+ return 0;
+ }
+ var out = parseInt(digitMatcher.exec(s.id)[0]);
+ return out;
+};
+
+var scrollTo = function(el) {
+ document.querySelectorAll(".selected").forEach(function(s) {
+ s.classList.remove("selected");
+ });
+ el.classList.add("selected");
+ window.scrollBy(0, el.getBoundingClientRect().top -
+ (window.innerHeight / 2));
+}
+
+var move = function(num, up, numItems) {
+ if (num == 1 && up || num == numItems - 1 && !up) {
+ return 0;
+ } else if (num == 0 && up) {
+ return numItems - 1;
+ } else if (num == 0 && !up) {
+ return 1 % numItems;
+ }
+ return up ? num - 1 : num + 1;
+}
+
+var numToId = function(num) {
+ if (num == 0) {
+ return document.getElementById("EndPath")
+ }
+ return document.getElementById("Path" + num);
+};
+
+var navigateTo = function(up) {
+ var numItems = document.querySelectorAll(".line > .msg").length;
+ var currentSelected = findNum();
+ var newSelected = move(currentSelected, up, numItems);
+ var newEl = numToId(newSelected, numItems);
+
+ // Scroll element into center.
+ scrollTo(newEl);
+};
+
+window.addEventListener("keydown", function (event) {
+ if (event.defaultPrevented) {
+ return;
+ }
+ if (event.key == "j") {
+ navigateTo(/*up=*/false);
+ } else if (event.key == "k") {
+ navigateTo(/*up=*/true);
+ } else {
+ return;
+ }
+ event.preventDefault();
+}, true);
+</script>
+ )<<<";
+}
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index 7f2a481c6b0d..e2e69bb28ec2 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -2132,9 +2132,10 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B,
NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
}
- // If the init list is shorter than the array length, set the
- // array default value.
- if (Size.hasValue() && i < Size.getValue())
+ // If the init list is shorter than the array length (or the array has
+ // variable length), set the array default value. Values that are already set
+ // are not overwritten.
+ if (!Size.hasValue() || i < Size.getValue())
NewB = setImplicitDefaultValue(NewB, R, ElementTy);
return NewB;
diff --git a/test/Analysis/arc-zero-init.m b/test/Analysis/arc-zero-init.m
new file mode 100644
index 000000000000..de1e978cd0d8
--- /dev/null
+++ b/test/Analysis/arc-zero-init.m
@@ -0,0 +1,46 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify -fobjc-arc %s
+
+#if __has_feature(objc_arc)
+// expected-no-diagnostics
+#endif
+
+@interface SomeClass
+@end
+
+void simpleStrongPointerValue() {
+ SomeClass *x;
+ if (x) {}
+#if !__has_feature(objc_arc)
+// expected-warning@-2{{Branch condition evaluates to a garbage value}}
+#endif
+}
+
+void simpleArray() {
+ SomeClass *vlaArray[5];
+
+ if (vlaArray[0]) {}
+#if !__has_feature(objc_arc)
+// expected-warning@-2{{Branch condition evaluates to a garbage value}}
+#endif
+}
+
+void variableLengthArray() {
+ int count = 1;
+ SomeClass * vlaArray[count];
+
+ if (vlaArray[0]) {}
+#if !__has_feature(objc_arc)
+ // expected-warning@-2{{Branch condition evaluates to a garbage value}}
+#endif
+}
+
+void variableLengthArrayWithExplicitStrongAttribute() {
+ int count = 1;
+ __attribute__((objc_ownership(strong))) SomeClass * vlaArray[count];
+
+ if (vlaArray[0]) {}
+#if !__has_feature(objc_arc)
+ // expected-warning@-2{{Branch condition evaluates to a garbage value}}
+#endif
+}
diff --git a/test/Analysis/initializer.cpp b/test/Analysis/initializer.cpp
index 6359b93d0a29..55f0a8950287 100644
--- a/test/Analysis/initializer.cpp
+++ b/test/Analysis/initializer.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++17 -DCPLUSPLUS17 -verify %s
void clang_analyzer_eval(bool);
@@ -224,3 +225,42 @@ void testPassListsWithExplicitConstructors() {
(void)(std::initializer_list<int>){12}; // no-crash
}
}
+
+namespace CXX17_aggregate_construction {
+struct A {
+ A();
+};
+
+struct B: public A {
+};
+
+struct C: public B {
+};
+
+struct D: public virtual A {
+};
+
+// In C++17, classes B and C are aggregates, so they will be constructed
+// without actually calling their trivial constructor. Used to crash.
+void foo() {
+ B b = {}; // no-crash
+ const B &bl = {}; // no-crash
+ B &&br = {}; // no-crash
+
+ C c = {}; // no-crash
+ const C &cl = {}; // no-crash
+ C &&cr = {}; // no-crash
+
+ D d = {}; // no-crash
+
+#ifdef CPLUSPLUS17
+ C cd = {{}}; // no-crash
+ const C &cdl = {{}}; // no-crash
+ C &&cdr = {{}}; // no-crash
+
+ const B &bll = {{}}; // no-crash
+ const B &bcl = C({{}}); // no-crash
+ B &&bcr = C({{}}); // no-crash
+#endif
+}
+}
diff --git a/test/Analysis/inlining/false-positive-suppression.m b/test/Analysis/inlining/false-positive-suppression.m
index f3532e5d6640..25fe40fc8555 100644
--- a/test/Analysis/inlining/false-positive-suppression.m
+++ b/test/Analysis/inlining/false-positive-suppression.m
@@ -5,7 +5,7 @@
#define ARC __has_feature(objc_arc)
-#if defined(SUPPRESSED) && !ARC
+#ifdef SUPPRESSED
// expected-no-diagnostics
#endif
@@ -27,9 +27,8 @@ void testNilReceiverHelperA(int *x) {
void testNilReceiverHelperB(int *x) {
*x = 1;
-// FIXME: Suppression for this case isn't working under ARC. It should.
-#if !defined(SUPPRESSED) || (defined(SUPPRESSED) && ARC)
- // expected-warning@-3 {{Dereference of null pointer}}
+#if !defined(SUPPRESSED)
+ // expected-warning@-2 {{Dereference of null pointer}}
#endif
}
diff --git a/test/Analysis/inlining/inline-defensive-checks.c b/test/Analysis/inlining/inline-defensive-checks.c
index 9f211b502bc0..ca61395fc0d4 100644
--- a/test/Analysis/inlining/inline-defensive-checks.c
+++ b/test/Analysis/inlining/inline-defensive-checks.c
@@ -190,3 +190,54 @@ void idcTrackZeroValueThroughUnaryPointerOperatorsWithArrayField(struct S2 *s) {
idc(s);
*(&(s->a[0])) = 7; // no-warning
}
+
+void idcTrackConstraintThroughSymbolicRegion(int **x) {
+ idc(*x);
+ // FIXME: Should not warn.
+ **x = 7; // expected-warning{{Dereference of null pointer}}
+}
+
+void idcTrackConstraintThroughSymbolicRegionAndParens(int **x) {
+ idc(*x);
+ // FIXME: Should not warn.
+ *(*x) = 7; // expected-warning{{Dereference of null pointer}}
+}
+
+int *idcPlainNull(int coin) {
+ if (coin)
+ return 0;
+ static int X;
+ return &X;
+}
+
+void idcTrackZeroValueThroughSymbolicRegion(int coin, int **x) {
+ *x = idcPlainNull(coin);
+ **x = 7; // no-warning
+}
+
+void idcTrackZeroValueThroughSymbolicRegionAndParens(int coin, int **x) {
+ *x = idcPlainNull(coin);
+ *(*x) = 7; // no-warning
+}
+
+struct WithInt {
+ int i;
+};
+
+struct WithArray {
+ struct WithInt arr[1];
+};
+
+struct WithArray *idcPlainNullWithArray(int coin) {
+ if (coin)
+ return 0;
+ static struct WithArray S;
+ return &S;
+}
+
+void idcTrackZeroValueThroughSymbolicRegionWithArray(int coin, struct WithArray **s) {
+ *s = idcPlainNullWithArray(coin);
+ (*s)->arr[0].i = 1; // no-warning
+ // Same thing.
+ (*s)->arr->i = 1; // no-warning
+}
diff --git a/test/Analysis/inlining/path-notes.m b/test/Analysis/inlining/path-notes.m
index 7f60ff8e3200..5bfd41d95a75 100644
--- a/test/Analysis/inlining/path-notes.m
+++ b/test/Analysis/inlining/path-notes.m
@@ -136,11 +136,19 @@ void testNilReceiverHelper(int *x) {
// expected-note@-1 {{Dereference of null pointer (loaded from variable 'x')}}
}
-void testNilReceiver(id *x) {
- if (*x) { // expected-note {{Assuming the condition is false}}
+void testNilReceiver(id *x, id *y, id *z) {
+ // FIXME: Should say "Assuming pointer value is null" instead.
+ // For some reason we're displaying different notes for
+ // tracked and untracked pointers.
+ if (*y) {} // expected-note {{Assuming the condition is false}}
+ // expected-note@-1 {{Taking false branch}}
+ if (*x) { // expected-note {{Assuming pointer value is null}}
// expected-note@-1 {{Taking false branch}}
return;
}
+ // FIXME: Should say "Assuming pointer value is null" instead.
+ if (*z) {} // expected-note {{Assuming the condition is false}}
+ // expected-note@-1 {{Taking false branch}}
testNilReceiverHelper([*x getPtr]);
// expected-note@-1 {{'getPtr' not called because the receiver is nil}}
// expected-note@-2 {{Passing null pointer value via 1st parameter 'x'}}
@@ -1158,12 +1166,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1171,12 +1179,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1188,7 +1196,7 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1196,12 +1204,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1221,12 +1229,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
+// CHECK-NEXT: <key>line</key><integer>143</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1234,12 +1242,206 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>145</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>145</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>145</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>145</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>145</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>145</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>145</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>145</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>145</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming pointer value is null</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming pointer value is null</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>145</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>145</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>150</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>150</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>150</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>150</integer>
+// CHECK-NEXT: <key>col</key><integer>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>150</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>150</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>150</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>150</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>150</integer>
+// CHECK-NEXT: <key>col</key><integer>8</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>150</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>150</integer>
+// CHECK-NEXT: <key>col</key><integer>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
+// CHECK-NEXT: <key>col</key><integer>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>23</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1255,12 +1457,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>23</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1268,12 +1470,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1285,7 +1487,7 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1293,12 +1495,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>27</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1318,12 +1520,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1331,12 +1533,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>25</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>25</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1348,7 +1550,7 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>25</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1356,12 +1558,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>25</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>35</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1377,7 +1579,7 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1385,12 +1587,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
+// CHECK-NEXT: <key>line</key><integer>152</integer>
// CHECK-NEXT: <key>col</key><integer>36</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1541,12 +1743,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>line</key><integer>159</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>line</key><integer>159</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1554,12 +1756,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>line</key><integer>159</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>line</key><integer>159</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1571,7 +1773,7 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>line</key><integer>159</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1579,12 +1781,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>line</key><integer>159</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>line</key><integer>159</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1604,12 +1806,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>line</key><integer>159</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
+// CHECK-NEXT: <key>line</key><integer>159</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1617,12 +1819,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>line</key><integer>161</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>line</key><integer>161</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1638,12 +1840,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>line</key><integer>161</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>line</key><integer>161</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1651,12 +1853,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>line</key><integer>161</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>line</key><integer>161</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1668,7 +1870,7 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>line</key><integer>161</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1676,12 +1878,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>line</key><integer>161</integer>
// CHECK-NEXT: <key>col</key><integer>19</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>line</key><integer>161</integer>
// CHECK-NEXT: <key>col</key><integer>23</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1705,7 +1907,7 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
+// CHECK-NEXT: <key>line</key><integer>161</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1721,12 +1923,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
+// CHECK-NEXT: <key>line</key><integer>167</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
+// CHECK-NEXT: <key>line</key><integer>167</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1734,12 +1936,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
+// CHECK-NEXT: <key>line</key><integer>168</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
+// CHECK-NEXT: <key>line</key><integer>168</integer>
// CHECK-NEXT: <key>col</key><integer>15</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1755,12 +1957,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
+// CHECK-NEXT: <key>line</key><integer>168</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
+// CHECK-NEXT: <key>line</key><integer>168</integer>
// CHECK-NEXT: <key>col</key><integer>15</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1768,12 +1970,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1789,12 +1991,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>4</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1802,12 +2004,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1819,7 +2021,7 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1827,12 +2029,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>34</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1852,12 +2054,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1865,12 +2067,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1882,7 +2084,7 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1890,24 +2092,24 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>47</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>12</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>34</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1927,12 +2129,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1940,12 +2142,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1957,7 +2159,7 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1965,24 +2167,24 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>60</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>11</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>47</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2002,12 +2204,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
+// CHECK-NEXT: <key>line</key><integer>170</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2015,12 +2217,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>167</integer>
+// CHECK-NEXT: <key>line</key><integer>175</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>167</integer>
+// CHECK-NEXT: <key>line</key><integer>175</integer>
// CHECK-NEXT: <key>col</key><integer>15</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2036,12 +2238,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>167</integer>
+// CHECK-NEXT: <key>line</key><integer>175</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>167</integer>
+// CHECK-NEXT: <key>line</key><integer>175</integer>
// CHECK-NEXT: <key>col</key><integer>15</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2049,12 +2251,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>169</integer>
+// CHECK-NEXT: <key>line</key><integer>177</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>169</integer>
+// CHECK-NEXT: <key>line</key><integer>177</integer>
// CHECK-NEXT: <key>col</key><integer>8</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2066,7 +2268,7 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>169</integer>
+// CHECK-NEXT: <key>line</key><integer>177</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2074,12 +2276,12 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>169</integer>
+// CHECK-NEXT: <key>line</key><integer>177</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>169</integer>
+// CHECK-NEXT: <key>line</key><integer>177</integer>
// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -2103,7 +2305,7 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: <key>issue_hash_function_offset</key><string>11</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>169</integer>
+// CHECK-NEXT: <key>line</key><integer>177</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
diff --git a/test/Analysis/nullptr.cpp b/test/Analysis/nullptr.cpp
index b3e61c9defb9..38e099b7fbdf 100644
--- a/test/Analysis/nullptr.cpp
+++ b/test/Analysis/nullptr.cpp
@@ -142,8 +142,9 @@ void shouldNotCrash() {
// expected-note@-1{{Passing null pointer value via 1st parameter 'x'}}
if (getSymbol()) { // expected-note {{Assuming the condition is true}}
// expected-note@-1{{Taking true branch}}
- X *x = Type().x; // expected-note{{'x' initialized to a null pointer value}}
- x->f(); // expected-warning{{Called C++ object pointer is null}}
+ X *xx = Type().x; // expected-note {{Null pointer value stored to field 'x'}}
+ // expected-note@-1{{'xx' initialized to a null pointer value}}
+ xx->f(); // expected-warning{{Called C++ object pointer is null}}
// expected-note@-1{{Called C++ object pointer is null}}
}
}
diff --git a/test/Analysis/uninit-const.cpp b/test/Analysis/uninit-const.cpp
index db969bfb67d6..2ffc71bcbd66 100644
--- a/test/Analysis/uninit-const.cpp
+++ b/test/Analysis/uninit-const.cpp
@@ -52,7 +52,7 @@ int& f6_1_sub(int &p) {
}
void f6_1(void) {
- int t;
+ int t; // expected-note{{'t' declared without an initial value}}
int p = f6_1_sub(t); //expected-warning {{Assigned value is garbage or undefined}}
//expected-note@-1 {{Calling 'f6_1_sub'}}
//expected-note@-2 {{Returning from 'f6_1_sub'}}
diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp
index 052349c8e2e0..46593b7e2adb 100644
--- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp
+++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp
@@ -1,56 +1,56 @@
-// RUN: %clang_cc1 -ast-dump %s 2>&1 | FileCheck %s
-
-// CHECK-LABEL: example0
-void example0() {
- double d = 2.0;
- // CHECK: VarDecl{{.*}}rd 'double &'
- // CHECK-NEXT: DeclRefExpr
- double &rd = d;
- // CHECK: VarDecl{{.*}}rcd 'const double &'
- // CHECK-NEXT: ImplicitCastExpr{{.*}}'const double' lvalue <NoOp>
- const double &rcd = d;
-}
-
-struct A { };
-struct B : A { } b;
-
-// CHECK-LABEL: example1
-void example1() {
- // CHECK: VarDecl{{.*}}ra 'struct A &'
- // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)>
- A &ra = b;
- // CHECK: VarDecl{{.*}}rca 'const struct A &'
- // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <DerivedToBase (A)>
- // CHECK-NOT: MaterializeTemporaryExpr
- // CHECK: ImplicitCastExpr{{.*}}'const struct B' lvalue <NoOp>
- const A& rca = b;
-}
-
-extern B f();
-
-struct X {
- operator B();
-} x;
-
-// CHECK-LABEL: example2
-void example2() {
- // CHECK: VarDecl{{.*}}rca 'const struct A &'
- // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <DerivedToBase (A)>
- // CHECK: MaterializeTemporaryExpr{{.*}}'const struct B'
- // CHECK: ImplicitCastExpr{{.*}}'const struct B' <NoOp>
- // CHECK: CallExpr{{.*}}B
- const A &rca = f();
- // CHECK: VarDecl{{.*}}r 'const struct A &'
- // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <DerivedToBase (A)>
- // CHECK: MaterializeTemporaryExpr{{.*}}'const struct B'
- // CHECK: ImplicitCastExpr{{.*}}'const struct B' <NoOp>
- // CHECK: CXXMemberCallExpr{{.*}}'struct B'
- const A& r = x;
-}
-
-// CHECK-LABEL: example3
-void example3() {
- // CHECK: VarDecl{{.*}}rcd2 'const double &'
- // CHECK: ImplicitCastExpr{{.*}} <IntegralToFloating>
- const double& rcd2 = 2;
-}
+// RUN: %clang_cc1 -ast-dump %s 2>&1 | FileCheck %s
+
+// CHECK-LABEL: example0
+void example0() {
+ double d = 2.0;
+ // CHECK: VarDecl{{.*}}rd 'double &'
+ // CHECK-NEXT: DeclRefExpr
+ double &rd = d;
+ // CHECK: VarDecl{{.*}}rcd 'const double &'
+ // CHECK-NEXT: ImplicitCastExpr{{.*}}'const double' lvalue <NoOp>
+ const double &rcd = d;
+}
+
+struct A { };
+struct B : A { } b;
+
+// CHECK-LABEL: example1
+void example1() {
+ // CHECK: VarDecl{{.*}}ra 'A &'
+ // CHECK: ImplicitCastExpr{{.*}}'A' lvalue <DerivedToBase (A)>
+ A &ra = b;
+ // CHECK: VarDecl{{.*}}rca 'const A &'
+ // CHECK: ImplicitCastExpr{{.*}}'const A' lvalue <DerivedToBase (A)>
+ // CHECK-NOT: MaterializeTemporaryExpr
+ // CHECK: ImplicitCastExpr{{.*}}'const B' lvalue <NoOp>
+ const A& rca = b;
+}
+
+extern B f();
+
+struct X {
+ operator B();
+} x;
+
+// CHECK-LABEL: example2
+void example2() {
+ // CHECK: VarDecl{{.*}}rca 'const A &'
+ // CHECK: ImplicitCastExpr{{.*}}'const A' lvalue <DerivedToBase (A)>
+ // CHECK: MaterializeTemporaryExpr{{.*}}'const B'
+ // CHECK: ImplicitCastExpr{{.*}}'const B' <NoOp>
+ // CHECK: CallExpr{{.*}}B
+ const A &rca = f();
+ // CHECK: VarDecl{{.*}}r 'const A &'
+ // CHECK: ImplicitCastExpr{{.*}}'const A' lvalue <DerivedToBase (A)>
+ // CHECK: MaterializeTemporaryExpr{{.*}}'const B'
+ // CHECK: ImplicitCastExpr{{.*}}'const B' <NoOp>
+ // CHECK: CXXMemberCallExpr{{.*}}'B'
+ const A& r = x;
+}
+
+// CHECK-LABEL: example3
+void example3() {
+ // CHECK: VarDecl{{.*}}rcd2 'const double &'
+ // CHECK: ImplicitCastExpr{{.*}} <IntegralToFloating>
+ const double& rcd2 = 2;
+}
diff --git a/test/CXX/temp/temp.param/p2.cpp b/test/CXX/temp/temp.param/p2.cpp
index 4eca05774ab5..20e0b8ef35f8 100644
--- a/test/CXX/temp/temp.param/p2.cpp
+++ b/test/CXX/temp/temp.param/p2.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -DCPP11
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s -DCPP17
// There is no semantic difference between class and typename in a
// template-parameter. typename followed by an unqualified-id names a
@@ -13,7 +14,31 @@ template<typename T, typename T::type Value> struct Y0;
template<typename T, typename X<T>::type Value> struct Y1;
// A storage class shall not be specified in a template-parameter declaration.
-template<static int Value> struct Z; // FIXME: expect an error
+template<static int Value> struct Z; //expected-error{{invalid declaration specifier}}
+template<typedef int Value> struct Z0; //expected-error{{invalid declaration specifier}}
+template<extern inline int Value> struct Z0; //expected-error2{{invalid declaration specifier}}
+template<virtual int Value> struct Z0; //expected-error{{invalid declaration specifier}}
+template<explicit int Value> struct Z0; //expected-error{{invalid declaration specifier}}
+template<inline int Value> struct Z0; //expected-error{{invalid declaration specifier}}
+template<extern int> struct Z0; //expected-error{{invalid declaration specifier}}
+template<static int> struct Z0; //expected-error{{invalid declaration specifier}}
+template<explicit int Value> struct Z0; //expected-error{{invalid declaration specifier}}
+template<mutable int> struct Z0; //expected-error{{invalid declaration specifier}}
+
+template<const int> struct Z0; // OK
+template<volatile int> struct Z0; // OK
+
+
+
+#ifdef CPP11
+template<thread_local int> struct Z0; //expected-error{{invalid declaration specifier}}
+template<constexpr int> struct Z0; //expected-error{{invalid declaration specifier}}
+
+#endif
+
+#ifdef CPP17
+template<auto> struct Z1; // OK
+#endif
// Make sure that we properly disambiguate non-type template parameters that
// start with 'class'.
diff --git a/test/CodeGen/aarch64-neon-intrinsics.c b/test/CodeGen/aarch64-neon-intrinsics.c
index bcb680c4b518..cbc2e72fcbac 100644
--- a/test/CodeGen/aarch64-neon-intrinsics.c
+++ b/test/CodeGen/aarch64-neon-intrinsics.c
@@ -9037,10 +9037,9 @@ int64x2_t test_vld1q_s64(int64_t const *a) {
// CHECK-LABEL: @test_vld1q_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
-// CHECK: [[TMP2:%.*]] = load <8 x i16>, <8 x i16>* [[TMP1]]
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i16> [[TMP2]] to <8 x half>
-// CHECK: ret <8 x half> [[TMP3]]
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x half>*
+// CHECK: [[TMP2:%.*]] = load <8 x half>, <8 x half>* [[TMP1]]
+// CHECK: ret <8 x half> [[TMP2]]
float16x8_t test_vld1q_f16(float16_t const *a) {
return vld1q_f16(a);
}
@@ -9152,10 +9151,9 @@ int64x1_t test_vld1_s64(int64_t const *a) {
// CHECK-LABEL: @test_vld1_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
-// CHECK: [[TMP2:%.*]] = load <4 x i16>, <4 x i16>* [[TMP1]]
-// CHECK: [[TMP3:%.*]] = bitcast <4 x i16> [[TMP2]] to <4 x half>
-// CHECK: ret <4 x half> [[TMP3]]
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x half>*
+// CHECK: [[TMP2:%.*]] = load <4 x half>, <4 x half>* [[TMP1]]
+// CHECK: ret <4 x half> [[TMP2]]
float16x4_t test_vld1_f16(float16_t const *a) {
return vld1_f16(a);
}
@@ -9342,10 +9340,10 @@ int64x2x2_t test_vld2q_s64(int64_t const *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <8 x i16>*
-// CHECK: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2.v8i16.p0v8i16(<8 x i16>* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <8 x half>*
+// CHECK: [[VLD2:%.*]] = call { <8 x half>, <8 x half> } @llvm.aarch64.neon.ld2.v8f16.p0v8f16(<8 x half>* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half> }*
+// CHECK: store { <8 x half>, <8 x half> } [[VLD2]], { <8 x half>, <8 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
@@ -9573,10 +9571,10 @@ int64x1x2_t test_vld2_s64(int64_t const *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <4 x i16>*
-// CHECK: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2.v4i16.p0v4i16(<4 x i16>* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <4 x half>*
+// CHECK: [[VLD2:%.*]] = call { <4 x half>, <4 x half> } @llvm.aarch64.neon.ld2.v4f16.p0v4f16(<4 x half>* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half> }*
+// CHECK: store { <4 x half>, <4 x half> } [[VLD2]], { <4 x half>, <4 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
@@ -9804,10 +9802,10 @@ int64x2x3_t test_vld3q_s64(int64_t const *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <8 x i16>*
-// CHECK: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3.v8i16.p0v8i16(<8 x i16>* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <8 x half>*
+// CHECK: [[VLD3:%.*]] = call { <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld3.v8f16.p0v8f16(<8 x half>* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half>, <8 x half> }*
+// CHECK: store { <8 x half>, <8 x half>, <8 x half> } [[VLD3]], { <8 x half>, <8 x half>, <8 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
@@ -10035,10 +10033,10 @@ int64x1x3_t test_vld3_s64(int64_t const *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <4 x i16>*
-// CHECK: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3.v4i16.p0v4i16(<4 x i16>* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <4 x half>*
+// CHECK: [[VLD3:%.*]] = call { <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld3.v4f16.p0v4f16(<4 x half>* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half>, <4 x half> }*
+// CHECK: store { <4 x half>, <4 x half>, <4 x half> } [[VLD3]], { <4 x half>, <4 x half>, <4 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
@@ -10266,10 +10264,10 @@ int64x2x4_t test_vld4q_s64(int64_t const *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <8 x i16>*
-// CHECK: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4.v8i16.p0v8i16(<8 x i16>* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <8 x half>*
+// CHECK: [[VLD4:%.*]] = call { <8 x half>, <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld4.v8f16.p0v8f16(<8 x half>* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half>, <8 x half>, <8 x half> }*
+// CHECK: store { <8 x half>, <8 x half>, <8 x half>, <8 x half> } [[VLD4]], { <8 x half>, <8 x half>, <8 x half>, <8 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
@@ -10497,10 +10495,10 @@ int64x1x4_t test_vld4_s64(int64_t const *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <4 x i16>*
-// CHECK: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4.v4i16.p0v4i16(<4 x i16>* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <4 x half>*
+// CHECK: [[VLD4:%.*]] = call { <4 x half>, <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld4.v4f16.p0v4f16(<4 x half>* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half>, <4 x half>, <4 x half> }*
+// CHECK: store { <4 x half>, <4 x half>, <4 x half>, <4 x half> } [[VLD4]], { <4 x half>, <4 x half>, <4 x half>, <4 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
@@ -10666,9 +10664,9 @@ void test_vst1q_s64(int64_t *a, int64x2_t b) {
// CHECK-LABEL: @test_vst1q_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: store <8 x i16> [[TMP3]], <8 x i16>* [[TMP2]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <8 x half>*
+// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK: store <8 x half> [[TMP3]], <8 x half>* [[TMP2]]
// CHECK: ret void
void test_vst1q_f16(float16_t *a, float16x8_t b) {
vst1q_f16(a, b);
@@ -10800,9 +10798,9 @@ void test_vst1_s64(int64_t *a, int64x1_t b) {
// CHECK-LABEL: @test_vst1_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: store <4 x i16> [[TMP3]], <4 x i16>* [[TMP2]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <4 x half>*
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK: store <4 x half> [[TMP3]], <4 x half>* [[TMP2]]
// CHECK: ret void
void test_vst1_f16(float16_t *a, float16x4_t b) {
vst1_f16(a, b);
@@ -11056,9 +11054,9 @@ void test_vst2q_s64(int64_t *a, int64x2x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], i64 0, i64 1
// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16
// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: call void @llvm.aarch64.neon.st2.v8i16.p0i8(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i8* [[TMP2]])
+// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half>
+// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
+// CHECK: call void @llvm.aarch64.neon.st2.v8f16.p0i8(<8 x half> [[TMP7]], <8 x half> [[TMP8]], i8* [[TMP2]])
// CHECK: ret void
void test_vst2q_f16(float16_t *a, float16x8x2_t b) {
vst2q_f16(a, b);
@@ -11366,9 +11364,9 @@ void test_vst2_s64(int64_t *a, int64x1x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL1]], i64 0, i64 1
// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: call void @llvm.aarch64.neon.st2.v4i16.p0i8(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i8* [[TMP2]])
+// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half>
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
+// CHECK: call void @llvm.aarch64.neon.st2.v4f16.p0i8(<4 x half> [[TMP7]], <4 x half> [[TMP8]], i8* [[TMP2]])
// CHECK: ret void
void test_vst2_f16(float16_t *a, float16x4x2_t b) {
vst2_f16(a, b);
@@ -11716,10 +11714,10 @@ void test_vst3q_s64(int64_t *a, int64x2x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], i64 0, i64 2
// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16
// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: call void @llvm.aarch64.neon.st3.v8i16.p0i8(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i8* [[TMP2]])
+// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half>
+// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
+// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half>
+// CHECK: call void @llvm.aarch64.neon.st3.v8f16.p0i8(<8 x half> [[TMP9]], <8 x half> [[TMP10]], <8 x half> [[TMP11]], i8* [[TMP2]])
// CHECK: ret void
void test_vst3q_f16(float16_t *a, float16x8x3_t b) {
vst3q_f16(a, b);
@@ -12085,10 +12083,10 @@ void test_vst3_s64(int64_t *a, int64x1x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL3]], i64 0, i64 2
// CHECK: [[TMP7:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8
// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: call void @llvm.aarch64.neon.st3.v4i16.p0i8(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i8* [[TMP2]])
+// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half>
+// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
+// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half>
+// CHECK: call void @llvm.aarch64.neon.st3.v4f16.p0i8(<4 x half> [[TMP9]], <4 x half> [[TMP10]], <4 x half> [[TMP11]], i8* [[TMP2]])
// CHECK: ret void
void test_vst3_f16(float16_t *a, float16x4x3_t b) {
vst3_f16(a, b);
@@ -12494,11 +12492,11 @@ void test_vst4q_s64(int64_t *a, int64x2x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], i64 0, i64 3
// CHECK: [[TMP9:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 16
// CHECK: [[TMP10:%.*]] = bitcast <8 x half> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
-// CHECK: call void @llvm.aarch64.neon.st4.v8i16.p0i8(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i8* [[TMP2]])
+// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x half>
+// CHECK: call void @llvm.aarch64.neon.st4.v8f16.p0i8(<8 x half> [[TMP11]], <8 x half> [[TMP12]], <8 x half> [[TMP13]], <8 x half> [[TMP14]], i8* [[TMP2]])
// CHECK: ret void
void test_vst4q_f16(float16_t *a, float16x8x4_t b) {
vst4q_f16(a, b);
@@ -12922,11 +12920,11 @@ void test_vst4_s64(int64_t *a, int64x1x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL5]], i64 0, i64 3
// CHECK: [[TMP9:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX6]], align 8
// CHECK: [[TMP10:%.*]] = bitcast <4 x half> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
-// CHECK: call void @llvm.aarch64.neon.st4.v4i16.p0i8(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i8* [[TMP2]])
+// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x half>
+// CHECK: call void @llvm.aarch64.neon.st4.v4f16.p0i8(<4 x half> [[TMP11]], <4 x half> [[TMP12]], <4 x half> [[TMP13]], <4 x half> [[TMP14]], i8* [[TMP2]])
// CHECK: ret void
void test_vst4_f16(float16_t *a, float16x4x4_t b) {
vst4_f16(a, b);
@@ -13208,10 +13206,10 @@ int64x2x2_t test_vld1q_s64_x2(int64_t const *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld1x2.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x half>, <8 x half> } @llvm.aarch64.neon.ld1x2.v8f16.p0f16(half* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half> }*
+// CHECK: store { <8 x half>, <8 x half> } [[VLD1XN]], { <8 x half>, <8 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
@@ -13454,10 +13452,10 @@ int64x1x2_t test_vld1_s64_x2(int64_t const *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld1x2.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x half>, <4 x half> } @llvm.aarch64.neon.ld1x2.v4f16.p0f16(half* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half> }*
+// CHECK: store { <4 x half>, <4 x half> } [[VLD1XN]], { <4 x half>, <4 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
@@ -13700,10 +13698,10 @@ int64x2x3_t test_vld1q_s64_x3(int64_t const *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld1x3.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld1x3.v8f16.p0f16(half* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half>, <8 x half> }*
+// CHECK: store { <8 x half>, <8 x half>, <8 x half> } [[VLD1XN]], { <8 x half>, <8 x half>, <8 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
@@ -13946,10 +13944,10 @@ int64x1x3_t test_vld1_s64_x3(int64_t const *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld1x3.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld1x3.v4f16.p0f16(half* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half>, <4 x half> }*
+// CHECK: store { <4 x half>, <4 x half>, <4 x half> } [[VLD1XN]], { <4 x half>, <4 x half>, <4 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
@@ -14192,10 +14190,10 @@ int64x2x4_t test_vld1q_s64_x4(int64_t const *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld1x4.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK: [[VLD1XN:%.*]] = call { <8 x half>, <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld1x4.v8f16.p0f16(half* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half>, <8 x half>, <8 x half> }*
+// CHECK: store { <8 x half>, <8 x half>, <8 x half>, <8 x half> } [[VLD1XN]], { <8 x half>, <8 x half>, <8 x half>, <8 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
@@ -14438,10 +14436,10 @@ int64x1x4_t test_vld1_s64_x4(int64_t const *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld1x4.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK: [[VLD1XN:%.*]] = call { <4 x half>, <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld1x4.v4f16.p0f16(half* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half>, <4 x half>, <4 x half> }*
+// CHECK: store { <4 x half>, <4 x half>, <4 x half>, <4 x half> } [[VLD1XN]], { <4 x half>, <4 x half>, <4 x half>, <4 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
@@ -14752,10 +14750,10 @@ void test_vst1q_s64_x2(int64_t *a, int64x2x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], i64 0, i64 1
// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16
// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]])
+// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half>
+// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
+// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to half*
+// CHECK: call void @llvm.aarch64.neon.st1x2.v8f16.p0f16(<8 x half> [[TMP7]], <8 x half> [[TMP8]], half* [[TMP9]])
// CHECK: ret void
void test_vst1q_f16_x2(float16_t *a, float16x8x2_t b) {
vst1q_f16_x2(a, b);
@@ -15098,10 +15096,10 @@ void test_vst1_s64_x2(int64_t *a, int64x1x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL1]], i64 0, i64 1
// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]])
+// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half>
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
+// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to half*
+// CHECK: call void @llvm.aarch64.neon.st1x2.v4f16.p0f16(<4 x half> [[TMP7]], <4 x half> [[TMP8]], half* [[TMP9]])
// CHECK: ret void
void test_vst1_f16_x2(float16_t *a, float16x4x2_t b) {
vst1_f16_x2(a, b);
@@ -15484,11 +15482,11 @@ void test_vst1q_s64_x3(int64_t *a, int64x2x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], i64 0, i64 2
// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16
// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]])
+// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half>
+// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
+// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half>
+// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to half*
+// CHECK: call void @llvm.aarch64.neon.st1x3.v8f16.p0f16(<8 x half> [[TMP9]], <8 x half> [[TMP10]], <8 x half> [[TMP11]], half* [[TMP12]])
// CHECK: ret void
void test_vst1q_f16_x3(float16_t *a, float16x8x3_t b) {
vst1q_f16_x3(a, b);
@@ -15894,11 +15892,11 @@ void test_vst1_s64_x3(int64_t *a, int64x1x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL3]], i64 0, i64 2
// CHECK: [[TMP7:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8
// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]])
+// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half>
+// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
+// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half>
+// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to half*
+// CHECK: call void @llvm.aarch64.neon.st1x3.v4f16.p0f16(<4 x half> [[TMP9]], <4 x half> [[TMP10]], <4 x half> [[TMP11]], half* [[TMP12]])
// CHECK: ret void
void test_vst1_f16_x3(float16_t *a, float16x4x3_t b) {
vst1_f16_x3(a, b);
@@ -16344,12 +16342,12 @@ void test_vst1q_s64_x4(int64_t *a, int64x2x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], i64 0, i64 3
// CHECK: [[TMP9:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 16
// CHECK: [[TMP10:%.*]] = bitcast <8 x half> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]])
+// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x half>
+// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to half*
+// CHECK: call void @llvm.aarch64.neon.st1x4.v8f16.p0f16(<8 x half> [[TMP11]], <8 x half> [[TMP12]], <8 x half> [[TMP13]], <8 x half> [[TMP14]], half* [[TMP15]])
// CHECK: ret void
void test_vst1q_f16_x4(float16_t *a, float16x8x4_t b) {
vst1q_f16_x4(a, b);
@@ -16818,12 +16816,12 @@ void test_vst1_s64_x4(int64_t *a, int64x1x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL5]], i64 0, i64 3
// CHECK: [[TMP9:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX6]], align 8
// CHECK: [[TMP10:%.*]] = bitcast <4 x half> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16*
-// CHECK: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]])
+// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x half>
+// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to half*
+// CHECK: call void @llvm.aarch64.neon.st1x4.v4f16.p0f16(<4 x half> [[TMP11]], <4 x half> [[TMP12]], <4 x half> [[TMP13]], <4 x half> [[TMP14]], half* [[TMP15]])
// CHECK: ret void
void test_vst1_f16_x4(float16_t *a, float16x4x4_t b) {
vst1_f16_x4(a, b);
diff --git a/test/CodeGen/aarch64-neon-ldst-one.c b/test/CodeGen/aarch64-neon-ldst-one.c
index 9bd9ab1cb61b..a3c5b140a0d2 100644
--- a/test/CodeGen/aarch64-neon-ldst-one.c
+++ b/test/CodeGen/aarch64-neon-ldst-one.c
@@ -90,12 +90,11 @@ int64x2_t test_vld1q_dup_s64(int64_t *a) {
// CHECK-LABEL: define <8 x half> @test_vld1q_dup_f16(half* %a) #0 {
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
-// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]]
-// CHECK: [[TMP3:%.*]] = insertelement <8 x i16> undef, i16 [[TMP2]], i32 0
-// CHECK: [[LANE:%.*]] = shufflevector <8 x i16> [[TMP3]], <8 x i16> [[TMP3]], <8 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[LANE]] to <8 x half>
-// CHECK: ret <8 x half> [[TMP4]]
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to half*
+// CHECK: [[TMP2:%.*]] = load half, half* [[TMP1]]
+// CHECK: [[TMP3:%.*]] = insertelement <8 x half> undef, half [[TMP2]], i32 0
+// CHECK: [[LANE:%.*]] = shufflevector <8 x half> [[TMP3]], <8 x half> [[TMP3]], <8 x i32> zeroinitializer
+// CHECK: ret <8 x half> [[LANE]]
float16x8_t test_vld1q_dup_f16(float16_t *a) {
return vld1q_dup_f16(a);
}
@@ -239,12 +238,11 @@ int64x1_t test_vld1_dup_s64(int64_t *a) {
// CHECK-LABEL: define <4 x half> @test_vld1_dup_f16(half* %a) #0 {
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
-// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]]
-// CHECK: [[TMP3:%.*]] = insertelement <4 x i16> undef, i16 [[TMP2]], i32 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP3]], <4 x i16> [[TMP3]], <4 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[LANE]] to <4 x half>
-// CHECK: ret <4 x half> [[TMP4]]
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to half*
+// CHECK: [[TMP2:%.*]] = load half, half* [[TMP1]]
+// CHECK: [[TMP3:%.*]] = insertelement <4 x half> undef, half [[TMP2]], i32 0
+// CHECK: [[LANE:%.*]] = shufflevector <4 x half> [[TMP3]], <4 x half> [[TMP3]], <4 x i32> zeroinitializer
+// CHECK: ret <4 x half> [[LANE]]
float16x4_t test_vld1_dup_f16(float16_t *a) {
return vld1_dup_f16(a);
}
@@ -447,10 +445,10 @@ int64x2x2_t test_vld2q_dup_s64(int64_t *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK: [[VLD2:%.*]] = call { <8 x half>, <8 x half> } @llvm.aarch64.neon.ld2r.v8f16.p0f16(half* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half> }*
+// CHECK: store { <8 x half>, <8 x half> } [[VLD2]], { <8 x half>, <8 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 16, i1 false)
@@ -693,10 +691,10 @@ int64x1x2_t test_vld2_dup_s64(int64_t *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK: [[VLD2:%.*]] = call { <4 x half>, <4 x half> } @llvm.aarch64.neon.ld2r.v4f16.p0f16(half* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half> }*
+// CHECK: store { <4 x half>, <4 x half> } [[VLD2]], { <4 x half>, <4 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 16, i32 8, i1 false)
@@ -947,10 +945,10 @@ int64x2x3_t test_vld3q_dup_s64(int64_t *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK: [[VLD3:%.*]] = call { <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld3r.v8f16.p0f16(half* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half>, <8 x half> }*
+// CHECK: store { <8 x half>, <8 x half>, <8 x half> } [[VLD3]], { <8 x half>, <8 x half>, <8 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 48, i32 16, i1 false)
@@ -1207,10 +1205,10 @@ int64x1x3_t test_vld3_dup_s64(int64_t *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK: [[VLD3:%.*]] = call { <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld3r.v4f16.p0f16(half* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half>, <4 x half> }*
+// CHECK: store { <4 x half>, <4 x half>, <4 x half> } [[VLD3]], { <4 x half>, <4 x half>, <4 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 24, i32 8, i1 false)
@@ -1459,10 +1457,10 @@ int64x2x4_t test_vld4q_dup_s64(int64_t *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK: [[VLD4:%.*]] = call { <8 x half>, <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld4r.v8f16.p0f16(half* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half>, <8 x half>, <8 x half> }*
+// CHECK: store { <8 x half>, <8 x half>, <8 x half>, <8 x half> } [[VLD4]], { <8 x half>, <8 x half>, <8 x half>, <8 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 64, i32 16, i1 false)
@@ -1705,10 +1703,10 @@ int64x1x4_t test_vld4_dup_s64(int64_t *a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16*
-// CHECK: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]])
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]]
+// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half*
+// CHECK: [[VLD4:%.*]] = call { <4 x half>, <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld4r.v4f16.p0f16(half* [[TMP2]])
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half>, <4 x half>, <4 x half> }*
+// CHECK: store { <4 x half>, <4 x half>, <4 x half>, <4 x half> } [[VLD4]], { <4 x half>, <4 x half>, <4 x half>, <4 x half> }* [[TMP3]]
// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP4]], i8* [[TMP5]], i64 32, i32 8, i1 false)
@@ -1897,12 +1895,11 @@ int64x2_t test_vld1q_lane_s64(int64_t *a, int64x2_t b) {
// CHECK-LABEL: define <8 x half> @test_vld1q_lane_f16(half* %a, <8 x half> %b) #0 {
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to i16*
-// CHECK: [[TMP4:%.*]] = load i16, i16* [[TMP3]]
-// CHECK: [[VLD1_LANE:%.*]] = insertelement <8 x i16> [[TMP2]], i16 [[TMP4]], i32 7
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[VLD1_LANE]] to <8 x half>
-// CHECK: ret <8 x half> [[TMP5]]
+// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to half*
+// CHECK: [[TMP4:%.*]] = load half, half* [[TMP3]]
+// CHECK: [[VLD1_LANE:%.*]] = insertelement <8 x half> [[TMP2]], half [[TMP4]], i32 7
+// CHECK: ret <8 x half> [[VLD1_LANE]]
float16x8_t test_vld1q_lane_f16(float16_t *a, float16x8_t b) {
return vld1q_lane_f16(a, b, 7);
}
@@ -2054,12 +2051,11 @@ int64x1_t test_vld1_lane_s64(int64_t *a, int64x1_t b) {
// CHECK-LABEL: define <4 x half> @test_vld1_lane_f16(half* %a, <4 x half> %b) #0 {
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to i16*
-// CHECK: [[TMP4:%.*]] = load i16, i16* [[TMP3]]
-// CHECK: [[VLD1_LANE:%.*]] = insertelement <4 x i16> [[TMP2]], i16 [[TMP4]], i32 3
-// CHECK: [[TMP5:%.*]] = bitcast <4 x i16> [[VLD1_LANE]] to <4 x half>
-// CHECK: ret <4 x half> [[TMP5]]
+// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to half*
+// CHECK: [[TMP4:%.*]] = load half, half* [[TMP3]]
+// CHECK: [[VLD1_LANE:%.*]] = insertelement <4 x half> [[TMP2]], half [[TMP4]], i32 3
+// CHECK: ret <4 x half> [[VLD1_LANE]]
float16x4_t test_vld1_lane_f16(float16_t *a, float16x4_t b) {
return vld1_lane_f16(a, b, 3);
}
@@ -2495,11 +2491,11 @@ int64x2x2_t test_vld2q_lane_s64(int64_t *a, int64x2x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], i64 0, i64 1
// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16
// CHECK: [[TMP7:%.*]] = bitcast <8 x half> [[TMP6]] to <16 x i8>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16>
-// CHECK: [[VLD2_LANE:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2lane.v8i16.p0i8(<8 x i16> [[TMP8]], <8 x i16> [[TMP9]], i64 7, i8* [[TMP3]])
-// CHECK: [[TMP10:%.*]] = bitcast i8* [[TMP2]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2_LANE]], { <8 x i16>, <8 x i16> }* [[TMP10]]
+// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x half>
+// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x half>
+// CHECK: [[VLD2_LANE:%.*]] = call { <8 x half>, <8 x half> } @llvm.aarch64.neon.ld2lane.v8f16.p0i8(<8 x half> [[TMP8]], <8 x half> [[TMP9]], i64 7, i8* [[TMP3]])
+// CHECK: [[TMP10:%.*]] = bitcast i8* [[TMP2]] to { <8 x half>, <8 x half> }*
+// CHECK: store { <8 x half>, <8 x half> } [[VLD2_LANE]], { <8 x half>, <8 x half> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 32, i32 16, i1 false)
@@ -2927,11 +2923,11 @@ int64x1x2_t test_vld2_lane_s64(int64_t *a, int64x1x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL1]], i64 0, i64 1
// CHECK: [[TMP6:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
// CHECK: [[TMP7:%.*]] = bitcast <4 x half> [[TMP6]] to <8 x i8>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x i16>
-// CHECK: [[VLD2_LANE:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2lane.v4i16.p0i8(<4 x i16> [[TMP8]], <4 x i16> [[TMP9]], i64 3, i8* [[TMP3]])
-// CHECK: [[TMP10:%.*]] = bitcast i8* [[TMP2]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2_LANE]], { <4 x i16>, <4 x i16> }* [[TMP10]]
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x half>
+// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x half>
+// CHECK: [[VLD2_LANE:%.*]] = call { <4 x half>, <4 x half> } @llvm.aarch64.neon.ld2lane.v4f16.p0i8(<4 x half> [[TMP8]], <4 x half> [[TMP9]], i64 3, i8* [[TMP3]])
+// CHECK: [[TMP10:%.*]] = bitcast i8* [[TMP2]] to { <4 x half>, <4 x half> }*
+// CHECK: store { <4 x half>, <4 x half> } [[VLD2_LANE]], { <4 x half>, <4 x half> }* [[TMP10]]
// CHECK: [[TMP11:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8*
// CHECK: [[TMP12:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP11]], i8* [[TMP12]], i64 16, i32 8, i1 false)
@@ -3364,12 +3360,12 @@ int64x2x3_t test_vld3q_lane_s64(int64_t *a, int64x2x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], i64 0, i64 2
// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16
// CHECK: [[TMP9:%.*]] = bitcast <8 x half> [[TMP8]] to <16 x i8>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP9]] to <8 x i16>
-// CHECK: [[VLD3_LANE:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3lane.v8i16.p0i8(<8 x i16> [[TMP10]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], i64 7, i8* [[TMP3]])
-// CHECK: [[TMP13:%.*]] = bitcast i8* [[TMP2]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3_LANE]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP13]]
+// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x half>
+// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP9]] to <8 x half>
+// CHECK: [[VLD3_LANE:%.*]] = call { <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld3lane.v8f16.p0i8(<8 x half> [[TMP10]], <8 x half> [[TMP11]], <8 x half> [[TMP12]], i64 7, i8* [[TMP3]])
+// CHECK: [[TMP13:%.*]] = bitcast i8* [[TMP2]] to { <8 x half>, <8 x half>, <8 x half> }*
+// CHECK: store { <8 x half>, <8 x half>, <8 x half> } [[VLD3_LANE]], { <8 x half>, <8 x half>, <8 x half> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.float16x8x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 48, i32 16, i1 false)
@@ -3889,12 +3885,12 @@ int64x1x3_t test_vld3_lane_s64(int64_t *a, int64x1x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL3]], i64 0, i64 2
// CHECK: [[TMP8:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8
// CHECK: [[TMP9:%.*]] = bitcast <4 x half> [[TMP8]] to <8 x i8>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP9]] to <4 x i16>
-// CHECK: [[VLD3_LANE:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3lane.v4i16.p0i8(<4 x i16> [[TMP10]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], i64 3, i8* [[TMP3]])
-// CHECK: [[TMP13:%.*]] = bitcast i8* [[TMP2]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3_LANE]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP13]]
+// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x half>
+// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP9]] to <4 x half>
+// CHECK: [[VLD3_LANE:%.*]] = call { <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld3lane.v4f16.p0i8(<4 x half> [[TMP10]], <4 x half> [[TMP11]], <4 x half> [[TMP12]], i64 3, i8* [[TMP3]])
+// CHECK: [[TMP13:%.*]] = bitcast i8* [[TMP2]] to { <4 x half>, <4 x half>, <4 x half> }*
+// CHECK: store { <4 x half>, <4 x half>, <4 x half> } [[VLD3_LANE]], { <4 x half>, <4 x half>, <4 x half> }* [[TMP13]]
// CHECK: [[TMP14:%.*]] = bitcast %struct.float16x4x3_t* [[RETVAL]] to i8*
// CHECK: [[TMP15:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP14]], i8* [[TMP15]], i64 24, i32 8, i1 false)
@@ -4454,13 +4450,13 @@ int64x2x4_t test_vld4q_lane_s64(int64_t *a, int64x2x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], i64 0, i64 3
// CHECK: [[TMP10:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 16
// CHECK: [[TMP11:%.*]] = bitcast <8 x half> [[TMP10]] to <16 x i8>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP9]] to <8 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP11]] to <8 x i16>
-// CHECK: [[VLD4_LANE:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4lane.v8i16.p0i8(<8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], <8 x i16> [[TMP15]], i64 7, i8* [[TMP3]])
-// CHECK: [[TMP16:%.*]] = bitcast i8* [[TMP2]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4_LANE]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP16]]
+// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP9]] to <8 x half>
+// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP11]] to <8 x half>
+// CHECK: [[VLD4_LANE:%.*]] = call { <8 x half>, <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld4lane.v8f16.p0i8(<8 x half> [[TMP12]], <8 x half> [[TMP13]], <8 x half> [[TMP14]], <8 x half> [[TMP15]], i64 7, i8* [[TMP3]])
+// CHECK: [[TMP16:%.*]] = bitcast i8* [[TMP2]] to { <8 x half>, <8 x half>, <8 x half>, <8 x half> }*
+// CHECK: store { <8 x half>, <8 x half>, <8 x half>, <8 x half> } [[VLD4_LANE]], { <8 x half>, <8 x half>, <8 x half>, <8 x half> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.float16x8x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 64, i32 16, i1 false)
@@ -5043,13 +5039,13 @@ int64x1x4_t test_vld4_lane_s64(int64_t *a, int64x1x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL5]], i64 0, i64 3
// CHECK: [[TMP10:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX6]], align 8
// CHECK: [[TMP11:%.*]] = bitcast <4 x half> [[TMP10]] to <8 x i8>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP9]] to <4 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP11]] to <4 x i16>
-// CHECK: [[VLD4_LANE:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4lane.v4i16.p0i8(<4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], <4 x i16> [[TMP15]], i64 3, i8* [[TMP3]])
-// CHECK: [[TMP16:%.*]] = bitcast i8* [[TMP2]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4_LANE]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP16]]
+// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP9]] to <4 x half>
+// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP11]] to <4 x half>
+// CHECK: [[VLD4_LANE:%.*]] = call { <4 x half>, <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld4lane.v4f16.p0i8(<4 x half> [[TMP12]], <4 x half> [[TMP13]], <4 x half> [[TMP14]], <4 x half> [[TMP15]], i64 3, i8* [[TMP3]])
+// CHECK: [[TMP16:%.*]] = bitcast i8* [[TMP2]] to { <4 x half>, <4 x half>, <4 x half>, <4 x half> }*
+// CHECK: store { <4 x half>, <4 x half>, <4 x half>, <4 x half> } [[VLD4_LANE]], { <4 x half>, <4 x half>, <4 x half>, <4 x half> }* [[TMP16]]
// CHECK: [[TMP17:%.*]] = bitcast %struct.float16x4x4_t* [[RETVAL]] to i8*
// CHECK: [[TMP18:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP17]], i8* [[TMP18]], i64 32, i32 8, i1 false)
@@ -5361,10 +5357,10 @@ void test_vst1q_lane_s64(int64_t *a, int64x2_t b) {
// CHECK-LABEL: define void @test_vst1q_lane_f16(half* %a, <8 x half> %b) #0 {
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = extractelement <8 x i16> [[TMP2]], i32 7
-// CHECK: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to i16*
-// CHECK: store i16 [[TMP3]], i16* [[TMP4]]
+// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK: [[TMP3:%.*]] = extractelement <8 x half> [[TMP2]], i32 7
+// CHECK: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to half*
+// CHECK: store half [[TMP3]], half* [[TMP4]]
// CHECK: ret void
void test_vst1q_lane_f16(float16_t *a, float16x8_t b) {
vst1q_lane_f16(a, b, 7);
@@ -5517,10 +5513,10 @@ void test_vst1_lane_s64(int64_t *a, int64x1_t b) {
// CHECK-LABEL: define void @test_vst1_lane_f16(half* %a, <4 x half> %b) #0 {
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = extractelement <4 x i16> [[TMP2]], i32 3
-// CHECK: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to i16*
-// CHECK: store i16 [[TMP3]], i16* [[TMP4]]
+// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK: [[TMP3:%.*]] = extractelement <4 x half> [[TMP2]], i32 3
+// CHECK: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to half*
+// CHECK: store half [[TMP3]], half* [[TMP4]]
// CHECK: ret void
void test_vst1_lane_f16(float16_t *a, float16x4_t b) {
vst1_lane_f16(a, b, 3);
@@ -5789,9 +5785,9 @@ void test_vst2q_lane_s64(int64_t *a, int64x2x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], i64 0, i64 1
// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16
// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: call void @llvm.aarch64.neon.st2lane.v8i16.p0i8(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i64 7, i8* [[TMP2]])
+// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half>
+// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
+// CHECK: call void @llvm.aarch64.neon.st2lane.v8f16.p0i8(<8 x half> [[TMP7]], <8 x half> [[TMP8]], i64 7, i8* [[TMP2]])
// CHECK: ret void
void test_vst2q_lane_f16(float16_t *a, float16x8x2_t b) {
vst2q_lane_f16(a, b, 7);
@@ -6124,9 +6120,9 @@ void test_vst2_lane_s64(int64_t *a, int64x1x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL1]], i64 0, i64 1
// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8>
-// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: call void @llvm.aarch64.neon.st2lane.v4i16.p0i8(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i64 3, i8* [[TMP2]])
+// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half>
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
+// CHECK: call void @llvm.aarch64.neon.st2lane.v4f16.p0i8(<4 x half> [[TMP7]], <4 x half> [[TMP8]], i64 3, i8* [[TMP2]])
// CHECK: ret void
void test_vst2_lane_f16(float16_t *a, float16x4x2_t b) {
vst2_lane_f16(a, b, 3);
@@ -6499,10 +6495,10 @@ void test_vst3q_lane_s64(int64_t *a, int64x2x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], i64 0, i64 2
// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16
// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: call void @llvm.aarch64.neon.st3lane.v8i16.p0i8(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i64 7, i8* [[TMP2]])
+// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half>
+// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
+// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half>
+// CHECK: call void @llvm.aarch64.neon.st3lane.v8f16.p0i8(<8 x half> [[TMP9]], <8 x half> [[TMP10]], <8 x half> [[TMP11]], i64 7, i8* [[TMP2]])
// CHECK: ret void
void test_vst3q_lane_f16(float16_t *a, float16x8x3_t b) {
vst3q_lane_f16(a, b, 7);
@@ -6898,10 +6894,10 @@ void test_vst3_lane_s64(int64_t *a, int64x1x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL3]], i64 0, i64 2
// CHECK: [[TMP7:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8
// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: call void @llvm.aarch64.neon.st3lane.v4i16.p0i8(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i64 3, i8* [[TMP2]])
+// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half>
+// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
+// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half>
+// CHECK: call void @llvm.aarch64.neon.st3lane.v4f16.p0i8(<4 x half> [[TMP9]], <4 x half> [[TMP10]], <4 x half> [[TMP11]], i64 3, i8* [[TMP2]])
// CHECK: ret void
void test_vst3_lane_f16(float16_t *a, float16x4x3_t b) {
vst3_lane_f16(a, b, 3);
@@ -7337,11 +7333,11 @@ void test_vst4q_lane_s64(int64_t *a, int64x2x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], i64 0, i64 3
// CHECK: [[TMP9:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 16
// CHECK: [[TMP10:%.*]] = bitcast <8 x half> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
-// CHECK: call void @llvm.aarch64.neon.st4lane.v8i16.p0i8(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i64 7, i8* [[TMP2]])
+// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x half>
+// CHECK: call void @llvm.aarch64.neon.st4lane.v8f16.p0i8(<8 x half> [[TMP11]], <8 x half> [[TMP12]], <8 x half> [[TMP13]], <8 x half> [[TMP14]], i64 7, i8* [[TMP2]])
// CHECK: ret void
void test_vst4q_lane_f16(float16_t *a, float16x8x4_t b) {
vst4q_lane_f16(a, b, 7);
@@ -7800,11 +7796,11 @@ void test_vst4_lane_s64(int64_t *a, int64x1x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL5]], i64 0, i64 3
// CHECK: [[TMP9:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX6]], align 8
// CHECK: [[TMP10:%.*]] = bitcast <4 x half> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
-// CHECK: call void @llvm.aarch64.neon.st4lane.v4i16.p0i8(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i64 3, i8* [[TMP2]])
+// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x half>
+// CHECK: call void @llvm.aarch64.neon.st4lane.v4f16.p0i8(<4 x half> [[TMP11]], <4 x half> [[TMP12]], <4 x half> [[TMP13]], <4 x half> [[TMP14]], i64 3, i8* [[TMP2]])
// CHECK: ret void
void test_vst4_lane_f16(float16_t *a, float16x4x4_t b) {
vst4_lane_f16(a, b, 3);
diff --git a/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c b/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c
new file mode 100644
index 000000000000..3f61238b64fb
--- /dev/null
+++ b/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c
@@ -0,0 +1,1633 @@
+// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -target-feature +fullfp16 -target-feature +v8.2a\
+// RUN: -fallow-half-arguments-and-returns -S -disable-O0-optnone -emit-llvm -o - %s \
+// RUN: | opt -S -mem2reg \
+// RUN: | FileCheck %s
+
+// REQUIRES: aarch64-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.aarch64.neon.fcvtas.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.aarch64.neon.fcvtas.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.aarch64.neon.fcvtms.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.aarch64.neon.fcvtms.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.aarch64.neon.fcvtmu.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.aarch64.neon.fcvtmu.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.aarch64.neon.fcvtns.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.aarch64.neon.fcvtns.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.aarch64.neon.fcvtnu.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.aarch64.neon.fcvtnu.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.aarch64.neon.fcvtps.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.aarch64.neon.fcvtps.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.aarch64.neon.fcvtpu.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.aarch64.neon.fcvtpu.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.aarch64.neon.frecpe.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.aarch64.neon.frecpe.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.trunc.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.trunc.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.round.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.round.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_vrndi_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.nearbyint.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[RND]]
+float16x4_t test_vrndi_f16(float16x4_t a) {
+ return vrndi_f16(a);
+}
+
+// CHECK-LABEL: test_vrndiq_f16
+// CHECK: [[RND:%.*]] = call <8 x half> @llvm.nearbyint.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[RND]]
+float16x8_t test_vrndiq_f16(float16x8_t a) {
+ return vrndiq_f16(a);
+}
+
+// CHECK-LABEL: test_vrndm_f16
+// CHECK: [[RND:%.*]] = call <4 x half> @llvm.floor.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.floor.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.aarch64.neon.frintn.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.aarch64.neon.frintn.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.ceil.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.ceil.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.rint.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.rint.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.aarch64.neon.frsqrte.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.aarch64.neon.frsqrte.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_vsqrt_f16
+// CHECK: [[SQR:%.*]] = call <4 x half> @llvm.sqrt.v4f16(<4 x half> %a)
+// CHECK: ret <4 x half> [[SQR]]
+float16x4_t test_vsqrt_f16(float16x4_t a) {
+ return vsqrt_f16(a);
+}
+
+// CHECK-LABEL: test_vsqrtq_f16
+// CHECK: [[SQR:%.*]] = call <8 x half> @llvm.sqrt.v8f16(<8 x half> %a)
+// CHECK: ret <8 x half> [[SQR]]
+float16x8_t test_vsqrtq_f16(float16x8_t a) {
+ return vsqrtq_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.aarch64.neon.fabd.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.aarch64.neon.fabd.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.aarch64.neon.facge.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.aarch64.neon.facge.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.aarch64.neon.facgt.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.aarch64.neon.facgt.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.aarch64.neon.facge.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.aarch64.neon.facge.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.aarch64.neon.facgt.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.aarch64.neon.facgt.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.aarch64.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.aarch64.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.aarch64.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.aarch64.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.aarch64.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.aarch64.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.aarch64.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.aarch64.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_vdiv_f16
+// CHECK: [[DIV:%.*]] = fdiv <4 x half> %a, %b
+// CHECK: ret <4 x half> [[DIV]]
+float16x4_t test_vdiv_f16(float16x4_t a, float16x4_t b) {
+ return vdiv_f16(a, b);
+}
+
+// CHECK-LABEL: test_vdivq_f16
+// CHECK: [[DIV:%.*]] = fdiv <8 x half> %a, %b
+// CHECK: ret <8 x half> [[DIV]]
+float16x8_t test_vdivq_f16(float16x8_t a, float16x8_t b) {
+ return vdivq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmax_f16
+// CHECK: [[MAX:%.*]] = call <4 x half> @llvm.aarch64.neon.fmax.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.aarch64.neon.fmax.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.aarch64.neon.fmaxnm.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.aarch64.neon.fmaxnm.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.aarch64.neon.fmin.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.aarch64.neon.fmin.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.aarch64.neon.fminnm.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.aarch64.neon.fminnm.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_vmulx_f16
+// CHECK: [[MUL:%.*]] = call <4 x half> @llvm.aarch64.neon.fmulx.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MUL]]
+float16x4_t test_vmulx_f16(float16x4_t a, float16x4_t b) {
+ return vmulx_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmulxq_f16
+// CHECK: [[MUL:%.*]] = call <8 x half> @llvm.aarch64.neon.fmulx.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MUL]]
+float16x8_t test_vmulxq_f16(float16x8_t a, float16x8_t b) {
+ return vmulxq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpadd_f16
+// CHECK: [[ADD:%.*]] = call <4 x half> @llvm.aarch64.neon.addp.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_vpaddq_f16
+// CHECK: [[ADD:%.*]] = call <8 x half> @llvm.aarch64.neon.addp.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[ADD]]
+float16x8_t test_vpaddq_f16(float16x8_t a, float16x8_t b) {
+ return vpaddq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpmax_f16
+// CHECK: [[MAX:%.*]] = call <4 x half> @llvm.aarch64.neon.fmaxp.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_vpmaxq_f16
+// CHECK: [[MAX:%.*]] = call <8 x half> @llvm.aarch64.neon.fmaxp.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MAX]]
+float16x8_t test_vpmaxq_f16(float16x8_t a, float16x8_t b) {
+ return vpmaxq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpmaxnm_f16
+// CHECK: [[MAX:%.*]] = call <4 x half> @llvm.aarch64.neon.fmaxnmp.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MAX]]
+float16x4_t test_vpmaxnm_f16(float16x4_t a, float16x4_t b) {
+ return vpmaxnm_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpmaxnmq_f16
+// CHECK: [[MAX:%.*]] = call <8 x half> @llvm.aarch64.neon.fmaxnmp.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MAX]]
+float16x8_t test_vpmaxnmq_f16(float16x8_t a, float16x8_t b) {
+ return vpmaxnmq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpmin_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.aarch64.neon.fminp.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_vpminq_f16
+// CHECK: [[MIN:%.*]] = call <8 x half> @llvm.aarch64.neon.fminp.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MIN]]
+float16x8_t test_vpminq_f16(float16x8_t a, float16x8_t b) {
+ return vpminq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpminnm_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.aarch64.neon.fminnmp.v4f16(<4 x half> %a, <4 x half> %b)
+// CHECK: ret <4 x half> [[MIN]]
+float16x4_t test_vpminnm_f16(float16x4_t a, float16x4_t b) {
+ return vpminnm_f16(a, b);
+}
+
+// CHECK-LABEL: test_vpminnmq_f16
+// CHECK: [[MIN:%.*]] = call <8 x half> @llvm.aarch64.neon.fminnmp.v8f16(<8 x half> %a, <8 x half> %b)
+// CHECK: ret <8 x half> [[MIN]]
+float16x8_t test_vpminnmq_f16(float16x8_t a, float16x8_t b) {
+ return vpminnmq_f16(a, b);
+}
+
+// CHECK-LABEL: test_vrecps_f16
+// CHECK: [[MIN:%.*]] = call <4 x half> @llvm.aarch64.neon.frecps.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.aarch64.neon.frecps.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.aarch64.neon.frsqrts.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.aarch64.neon.frsqrts.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_vfma_lane_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 <4 x half> %c to <8 x i8>
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x half>
+// CHECK: [[LANE:%.*]] = shufflevector <4 x half> [[TMP3]], <4 x half> [[TMP3]], <4 x i32> <i32 3, i32 3, i32 3, i32 3>
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK: [[FMLA:%.*]] = call <4 x half> @llvm.fma.v4f16(<4 x half> [[TMP4]], <4 x half> [[LANE]], <4 x half> [[TMP5]])
+// CHECK: ret <4 x half> [[FMLA]]
+float16x4_t test_vfma_lane_f16(float16x4_t a, float16x4_t b, float16x4_t c) {
+ return vfma_lane_f16(a, b, c, 3);
+}
+
+// CHECK-LABEL: test_vfmaq_lane_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 <4 x half> %c to <8 x i8>
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x half>
+// CHECK: [[LANE:%.*]] = shufflevector <4 x half> [[TMP3]], <4 x half> [[TMP3]], <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
+// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK: [[FMLA:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> [[TMP4]], <8 x half> [[LANE]], <8 x half> [[TMP5]])
+// CHECK: ret <8 x half> [[FMLA]]
+float16x8_t test_vfmaq_lane_f16(float16x8_t a, float16x8_t b, float16x4_t c) {
+ return vfmaq_lane_f16(a, b, c, 3);
+}
+
+// CHECK-LABEL: test_vfma_laneq_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 half> %c to <16 x i8>
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x half>
+// CHECK: [[LANE:%.*]] = shufflevector <8 x half> [[TMP5]], <8 x half> [[TMP5]], <4 x i32> <i32 7, i32 7, i32 7, i32 7>
+// CHECK: [[FMLA:%.*]] = call <4 x half> @llvm.fma.v4f16(<4 x half> [[LANE]], <4 x half> [[TMP4]], <4 x half> [[TMP3]])
+// CHECK: ret <4 x half> [[FMLA]]
+float16x4_t test_vfma_laneq_f16(float16x4_t a, float16x4_t b, float16x8_t c) {
+ return vfma_laneq_f16(a, b, c, 7);
+}
+
+// CHECK-LABEL: test_vfmaq_laneq_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 <8 x half> %c to <16 x i8>
+// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x half>
+// CHECK: [[LANE:%.*]] = shufflevector <8 x half> [[TMP5]], <8 x half> [[TMP5]], <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+// CHECK: [[FMLA:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> [[LANE]], <8 x half> [[TMP4]], <8 x half> [[TMP3]])
+// CHECK: ret <8 x half> [[FMLA]]
+float16x8_t test_vfmaq_laneq_f16(float16x8_t a, float16x8_t b, float16x8_t c) {
+ return vfmaq_laneq_f16(a, b, c, 7);
+}
+
+// CHECK-LABEL: test_vfma_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <4 x half> undef, half %c, i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half %c, i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half %c, i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half %c, i32 3
+// CHECK: [[FMA:%.*]] = call <4 x half> @llvm.fma.v4f16(<4 x half> %b, <4 x half> [[TMP3]], <4 x half> %a)
+// CHECK: ret <4 x half> [[FMA]]
+float16x4_t test_vfma_n_f16(float16x4_t a, float16x4_t b, float16_t c) {
+ return vfma_n_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vfmaq_n_f16
+// CHECK: [[TMP0:%.*]] = insertelement <8 x half> undef, half %c, i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half %c, i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half %c, i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half %c, i32 3
+// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half %c, i32 4
+// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half %c, i32 5
+// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half %c, i32 6
+// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half %c, i32 7
+// CHECK: [[FMA:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> %b, <8 x half> [[TMP7]], <8 x half> %a)
+// CHECK: ret <8 x half> [[FMA]]
+float16x8_t test_vfmaq_n_f16(float16x8_t a, float16x8_t b, float16_t c) {
+ return vfmaq_n_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vfmah_lane_f16
+// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %c 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: [[FMA:%.*]] = call half @llvm.fma.f16(half %b, half [[EXTR]], half %a)
+// CHECK: ret half [[FMA]]
+float16_t test_vfmah_lane_f16(float16_t a, float16_t b, float16x4_t c) {
+ return vfmah_lane_f16(a, b, c, 3);
+}
+
+// CHECK-LABEL: test_vfmah_laneq_f16
+// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %c 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: [[FMA:%.*]] = call half @llvm.fma.f16(half %b, half [[EXTR]], half %a)
+// CHECK: ret half [[FMA]]
+float16_t test_vfmah_laneq_f16(float16_t a, float16_t b, float16x8_t c) {
+ return vfmah_laneq_f16(a, b, c, 7);
+}
+
+// CHECK-LABEL: test_vfms_lane_f16
+// CHECK: [[SUB:%.*]] = fsub <4 x half> <half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000>, %b
+// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x half> [[SUB]] to <8 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <4 x half> %c to <8 x i8>
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x half>
+// CHECK: [[LANE:%.*]] = shufflevector <4 x half> [[TMP3]], <4 x half> [[TMP3]], <4 x i32> <i32 3, i32 3, i32 3, i32 3>
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK: [[FMA:%.*]] = call <4 x half> @llvm.fma.v4f16(<4 x half> [[TMP4]], <4 x half> [[LANE]], <4 x half> [[TMP5]])
+// CHECK: ret <4 x half> [[FMA]]
+float16x4_t test_vfms_lane_f16(float16x4_t a, float16x4_t b, float16x4_t c) {
+ return vfms_lane_f16(a, b, c, 3);
+}
+
+// CHECK-LABEL: test_vfmsq_lane_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: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x half> [[SUB]] to <16 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <4 x half> %c to <8 x i8>
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x half>
+// CHECK: [[LANE:%.*]] = shufflevector <4 x half> [[TMP3]], <4 x half> [[TMP3]], <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
+// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK: [[FMLA:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> [[TMP4]], <8 x half> [[LANE]], <8 x half> [[TMP5]])
+// CHECK: ret <8 x half> [[FMLA]]
+float16x8_t test_vfmsq_lane_f16(float16x8_t a, float16x8_t b, float16x4_t c) {
+ return vfmsq_lane_f16(a, b, c, 3);
+}
+
+// CHECK-LABEL: test_vfms_laneq_f16
+// CHECK: [[SUB:%.*]] = fsub <4 x half> <half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000>, %b
+// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x half> [[SUB]] to <8 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <8 x half> %c to <16 x i8>
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x half>
+// CHECK: [[LANE:%.*]] = shufflevector <8 x half> [[TMP5]], <8 x half> [[TMP5]], <4 x i32> <i32 7, i32 7, i32 7, i32 7>
+// CHECK: [[FMLA:%.*]] = call <4 x half> @llvm.fma.v4f16(<4 x half> [[LANE]], <4 x half> [[TMP4]], <4 x half> [[TMP3]])
+// CHECK: ret <4 x half> [[FMLA]]
+float16x4_t test_vfms_laneq_f16(float16x4_t a, float16x4_t b, float16x8_t c) {
+ return vfms_laneq_f16(a, b, c, 7);
+}
+
+// CHECK-LABEL: test_vfmsq_laneq_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: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x half> [[SUB]] to <16 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <8 x half> %c to <16 x i8>
+// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x half>
+// CHECK: [[LANE:%.*]] = shufflevector <8 x half> [[TMP5]], <8 x half> [[TMP5]], <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+// CHECK: [[FMLA:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> [[LANE]], <8 x half> [[TMP4]], <8 x half> [[TMP3]])
+// CHECK: ret <8 x half> [[FMLA]]
+float16x8_t test_vfmsq_laneq_f16(float16x8_t a, float16x8_t b, float16x8_t c) {
+ return vfmsq_laneq_f16(a, b, c, 7);
+}
+
+// CHECK-LABEL: test_vfms_n_f16
+// CHECK: [[SUB:%.*]] = fsub <4 x half> <half 0xH8000, half 0xH8000, half 0xH8000, half 0xH8000>, %b
+// CHECK: [[TMP0:%.*]] = insertelement <4 x half> undef, half %c, i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half %c, i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half %c, i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half %c, i32 3
+// CHECK: [[FMA:%.*]] = call <4 x half> @llvm.fma.v4f16(<4 x half> [[SUB]], <4 x half> [[TMP3]], <4 x half> %a)
+// CHECK: ret <4 x half> [[FMA]]
+float16x4_t test_vfms_n_f16(float16x4_t a, float16x4_t b, float16_t c) {
+ return vfms_n_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vfmsq_n_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: [[TMP0:%.*]] = insertelement <8 x half> undef, half %c, i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half %c, i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half %c, i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half %c, i32 3
+// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half %c, i32 4
+// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half %c, i32 5
+// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half %c, i32 6
+// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half %c, i32 7
+// CHECK: [[FMA:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> [[SUB]], <8 x half> [[TMP7]], <8 x half> %a)
+// CHECK: ret <8 x half> [[FMA]]
+float16x8_t test_vfmsq_n_f16(float16x8_t a, float16x8_t b, float16_t c) {
+ return vfmsq_n_f16(a, b, c);
+}
+
+// CHECK-LABEL: test_vfmsh_lane_f16
+// CHECK: [[TMP0:%.*]] = fpext half %b to float
+// CHECK: [[TMP1:%.*]] = fsub float -0.000000e+00, [[TMP0]]
+// CHECK: [[SUB:%.*]] = fptrunc float [[TMP1]] to half
+// CHECK: [[TMP2:%.*]] = bitcast <4 x half> %c to <8 x i8>
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x half>
+// CHECK: [[EXTR:%.*]] = extractelement <4 x half> [[TMP3]], i32 3
+// CHECK: [[FMA:%.*]] = call half @llvm.fma.f16(half [[SUB]], half [[EXTR]], half %a)
+// CHECK: ret half [[FMA]]
+float16_t test_vfmsh_lane_f16(float16_t a, float16_t b, float16x4_t c) {
+ return vfmsh_lane_f16(a, b, c, 3);
+}
+
+// CHECK-LABEL: test_vfmsh_laneq_f16
+// CHECK: [[TMP0:%.*]] = fpext half %b to float
+// CHECK: [[TMP1:%.*]] = fsub float -0.000000e+00, [[TMP0]]
+// CHECK: [[SUB:%.*]] = fptrunc float [[TMP1]] to half
+// CHECK: [[TMP2:%.*]] = bitcast <8 x half> %c to <16 x i8>
+// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x half>
+// CHECK: [[EXTR:%.*]] = extractelement <8 x half> [[TMP3]], i32 7
+// CHECK: [[FMA:%.*]] = call half @llvm.fma.f16(half [[SUB]], half [[EXTR]], half %a)
+// CHECK: ret half [[FMA]]
+float16_t test_vfmsh_laneq_f16(float16_t a, float16_t b, float16x8_t c) {
+ return vfmsh_laneq_f16(a, b, c, 7);
+}
+
+// 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_laneq_f16
+// CHECK: [[TMP0:%.*]] = shufflevector <8 x half> %b, <8 x half> %b, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
+// CHECK: [[MUL:%.*]] = fmul <4 x half> %a, [[TMP0]]
+// CHECK: ret <4 x half> [[MUL]]
+float16x4_t test_vmul_laneq_f16(float16x4_t a, float16x8_t b) {
+ return vmul_laneq_f16(a, b, 7);
+}
+
+// CHECK-LABEL: test_vmulq_laneq_f16
+// CHECK: [[TMP0:%.*]] = shufflevector <8 x half> %b, <8 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_laneq_f16(float16x8_t a, float16x8_t b) {
+ return vmulq_laneq_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);
+}
+
+// FIXME: Fix it when fp16 non-storage-only type becomes available.
+// CHECK-LABEL: test_vmulh_lane_f16
+// CHECK: [[CONV0:%.*]] = fpext half %a to float
+// CHECK: [[CONV1:%.*]] = fpext half %{{.*}} to float
+// CHECK: [[MUL:%.*]] = fmul float [[CONV0:%.*]], [[CONV0:%.*]]
+// CHECK: [[CONV3:%.*]] = fptrunc float %mul to half
+// CHECK: ret half [[CONV3:%.*]]
+float16_t test_vmulh_lane_f16(float16_t a, float16x4_t b) {
+ return vmulh_lane_f16(a, b, 3);
+}
+
+// CHECK-LABEL: test_vmulh_laneq_f16
+// CHECK: [[CONV0:%.*]] = fpext half %a to float
+// CHECK: [[CONV1:%.*]] = fpext half %{{.*}} to float
+// CHECK: [[MUL:%.*]] = fmul float [[CONV0:%.*]], [[CONV0:%.*]]
+// CHECK: [[CONV3:%.*]] = fptrunc float %mul to half
+// CHECK: ret half [[CONV3:%.*]]
+float16_t test_vmulh_laneq_f16(float16_t a, float16x8_t b) {
+ return vmulh_laneq_f16(a, b, 7);
+}
+
+// CHECK-LABEL: test_vmulx_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:%.*]] = call <4 x half> @llvm.aarch64.neon.fmulx.v4f16(<4 x half> %a, <4 x half> [[TMP0]])
+// CHECK: ret <4 x half> [[MUL]]
+float16x4_t test_vmulx_lane_f16(float16x4_t a, float16x4_t b) {
+ return vmulx_lane_f16(a, b, 3);
+}
+
+// CHECK-LABEL: test_vmulxq_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:%.*]] = call <8 x half> @llvm.aarch64.neon.fmulx.v8f16(<8 x half> %a, <8 x half> [[TMP0]])
+// CHECK: ret <8 x half> [[MUL]]
+float16x8_t test_vmulxq_lane_f16(float16x8_t a, float16x4_t b) {
+ return vmulxq_lane_f16(a, b, 7);
+}
+
+// CHECK-LABEL: test_vmulx_laneq_f16
+// CHECK: [[TMP0:%.*]] = shufflevector <8 x half> %b, <8 x half> %b, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
+// CHECK: [[MUL:%.*]] = call <4 x half> @llvm.aarch64.neon.fmulx.v4f16(<4 x half> %a, <4 x half> [[TMP0]])
+// CHECK: ret <4 x half> [[MUL]]
+float16x4_t test_vmulx_laneq_f16(float16x4_t a, float16x8_t b) {
+ return vmulx_laneq_f16(a, b, 7);
+}
+
+// CHECK-LABEL: test_vmulxq_laneq_f16
+// CHECK: [[TMP0:%.*]] = shufflevector <8 x half> %b, <8 x half> %b, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+// CHECK: [[MUL:%.*]] = call <8 x half> @llvm.aarch64.neon.fmulx.v8f16(<8 x half> %a, <8 x half> [[TMP0]])
+// CHECK: ret <8 x half> [[MUL]]
+float16x8_t test_vmulxq_laneq_f16(float16x8_t a, float16x8_t b) {
+ return vmulxq_laneq_f16(a, b, 7);
+}
+
+// CHECK-LABEL: test_vmulx_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:%.*]] = call <4 x half> @llvm.aarch64.neon.fmulx.v4f16(<4 x half> %a, <4 x half> [[TMP3]])
+// CHECK: ret <4 x half> [[MUL]]
+float16x4_t test_vmulx_n_f16(float16x4_t a, float16_t b) {
+ return vmulx_n_f16(a, b);
+}
+
+// CHECK-LABEL: test_vmulxq_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:%.*]] = call <8 x half> @llvm.aarch64.neon.fmulx.v8f16(<8 x half> %a, <8 x half> [[TMP7]])
+// CHECK: ret <8 x half> [[MUL]]
+float16x8_t test_vmulxq_n_f16(float16x8_t a, float16_t b) {
+ 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:%.*]]
+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:%.*]]
+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>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK: [[MAX:%.*]] = call half @llvm.aarch64.neon.fmaxv.f16.v4f16(<4 x half> [[TMP1]])
+// CHECK: ret half [[MAX]]
+float16_t test_vmaxv_f16(float16x4_t a) {
+ return vmaxv_f16(a);
+}
+
+// CHECK-LABEL: test_vmaxvq_f16
+// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK: [[MAX:%.*]] = call half @llvm.aarch64.neon.fmaxv.f16.v8f16(<8 x half> [[TMP1]])
+// CHECK: ret half [[MAX]]
+float16_t test_vmaxvq_f16(float16x8_t a) {
+ return vmaxvq_f16(a);
+}
+
+// CHECK-LABEL: test_vminv_f16
+// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK: [[MAX:%.*]] = call half @llvm.aarch64.neon.fminv.f16.v4f16(<4 x half> [[TMP1]])
+// CHECK: ret half [[MAX]]
+float16_t test_vminv_f16(float16x4_t a) {
+ return vminv_f16(a);
+}
+
+// CHECK-LABEL: test_vminvq_f16
+// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK: [[MAX:%.*]] = call half @llvm.aarch64.neon.fminv.f16.v8f16(<8 x half> [[TMP1]])
+// CHECK: ret half [[MAX]]
+float16_t test_vminvq_f16(float16x8_t a) {
+ return vminvq_f16(a);
+}
+
+// CHECK-LABEL: test_vmaxnmv_f16
+// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK: [[MAX:%.*]] = call half @llvm.aarch64.neon.fmaxnmv.f16.v4f16(<4 x half> [[TMP1]])
+// CHECK: ret half [[MAX]]
+float16_t test_vmaxnmv_f16(float16x4_t a) {
+ return vmaxnmv_f16(a);
+}
+
+// CHECK-LABEL: test_vmaxnmvq_f16
+// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK: [[MAX:%.*]] = call half @llvm.aarch64.neon.fmaxnmv.f16.v8f16(<8 x half> [[TMP1]])
+// CHECK: ret half [[MAX]]
+float16_t test_vmaxnmvq_f16(float16x8_t a) {
+ return vmaxnmvq_f16(a);
+}
+
+// CHECK-LABEL: test_vminnmv_f16
+// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
+// CHECK: [[MAX:%.*]] = call half @llvm.aarch64.neon.fminnmv.f16.v4f16(<4 x half> [[TMP1]])
+// CHECK: ret half [[MAX]]
+float16_t test_vminnmv_f16(float16x4_t a) {
+ return vminnmv_f16(a);
+}
+
+// CHECK-LABEL: test_vminnmvq_f16
+// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
+// CHECK: [[MAX:%.*]] = call half @llvm.aarch64.neon.fminnmv.f16.v8f16(<8 x half> [[TMP1]])
+// CHECK: ret half [[MAX]]
+float16_t test_vminnmvq_f16(float16x8_t a) {
+ return vminnmvq_f16(a);
+}
+
+// CHECK-LABEL: test_vbsl_f16
+// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %b to <8 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %c to <8 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
+// CHECK: [[TMP4:%.*]] = and <4 x i16> %a, [[TMP2]]
+// CHECK: [[TMP5:%.*]] = xor <4 x i16> %a, <i16 -1, i16 -1, i16 -1, i16 -1>
+// CHECK: [[TMP6:%.*]] = and <4 x i16> [[TMP5]], [[TMP3]]
+// CHECK: [[TMP7:%.*]] = or <4 x i16> [[TMP4]], [[TMP6]]
+// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <4 x half>
+// CHECK: ret <4 x half> [[TMP8]]
+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 half> %b to <16 x i8>
+// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %c to <16 x i8>
+// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
+// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
+// CHECK: [[TMP4:%.*]] = and <8 x i16> %a, [[TMP2]]
+// CHECK: [[TMP5:%.*]] = xor <8 x i16> %a, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
+// CHECK: [[TMP6:%.*]] = and <8 x i16> [[TMP5]], [[TMP3]]
+// CHECK: [[TMP7:%.*]] = or <8 x i16> [[TMP4]], [[TMP6]]
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <8 x half>
+// CHECK: ret <8 x half> [[TMP8]]
+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: [[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: [[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* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false)
+float16x4x2_t test_vzip_f16(float16x4_t a, float16x4_t b) {
+ return vzip_f16(a, b);
+}
+
+// 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: [[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* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false)
+float16x8x2_t test_vzipq_f16(float16x8_t a, float16x8_t b) {
+ return vzipq_f16(a, b);
+}
+
+// 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: [[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* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false)
+float16x4x2_t test_vuzp_f16(float16x4_t a, float16x4_t b) {
+ return vuzp_f16(a, b);
+}
+
+// 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: [[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* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false)
+float16x8x2_t test_vuzpq_f16(float16x8_t a, float16x8_t b) {
+ return vuzpq_f16(a, b);
+}
+
+// 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: [[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* [[TMP5]], i8* [[TMP6]], i64 16, i32 8, i1 false)
+float16x4x2_t test_vtrn_f16(float16x4_t a, float16x4_t b) {
+ return vtrn_f16(a, b);
+}
+
+// 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: [[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* [[TMP5]], i8* [[TMP6]], i64 32, i32 16, i1 false)
+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 %a, i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half %a, i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half %a, i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half %a, 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 %a, i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half %a, i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half %a, i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half %a, i32 3
+// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half %a, i32 4
+// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half %a, i32 5
+// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half %a, i32 6
+// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half %a, 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 %a, i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half %a, i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half %a, i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half %a, 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 %a, i32 0
+// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half %a, i32 1
+// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half %a, i32 2
+// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half %a, i32 3
+// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half %a, i32 4
+// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half %a, i32 5
+// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half %a, i32 6
+// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half %a, 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);
+}
+
+// CHECK-LABEL: @test_vzip1_f16(
+// CHECK: [[SHFL:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// CHECK: ret <4 x half> [[SHFL]]
+float16x4_t test_vzip1_f16(float16x4_t a, float16x4_t b) {
+ return vzip1_f16(a, b);
+}
+
+// CHECK-LABEL: @test_vzip1q_f16(
+// CHECK: [[SHFL:%.*]] = 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: ret <8 x half> [[SHFL]]
+float16x8_t test_vzip1q_f16(float16x8_t a, float16x8_t b) {
+ return vzip1q_f16(a, b);
+}
+
+// CHECK-LABEL: @test_vzip2_f16(
+// CHECK: [[SHFL:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
+// CHECK: ret <4 x half> [[SHFL]]
+float16x4_t test_vzip2_f16(float16x4_t a, float16x4_t b) {
+ return vzip2_f16(a, b);
+}
+
+// CHECK-LABEL: @test_vzip2q_f16(
+// CHECK: [[SHFL:%.*]] = 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: ret <8 x half> [[SHFL]]
+float16x8_t test_vzip2q_f16(float16x8_t a, float16x8_t b) {
+ return vzip2q_f16(a, b);
+}
+
+// CHECK-LABEL: @test_vuzp1_f16(
+// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// CHECK: ret <4 x half> [[SHUFFLE_I]]
+float16x4_t test_vuzp1_f16(float16x4_t a, float16x4_t b) {
+ return vuzp1_f16(a, b);
+}
+
+// CHECK-LABEL: @test_vuzp1q_f16(
+// CHECK: [[SHUFFLE_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: ret <8 x half> [[SHUFFLE_I]]
+float16x8_t test_vuzp1q_f16(float16x8_t a, float16x8_t b) {
+ return vuzp1q_f16(a, b);
+}
+
+// CHECK-LABEL: @test_vuzp2_f16(
+// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+// CHECK: ret <4 x half> [[SHUFFLE_I]]
+float16x4_t test_vuzp2_f16(float16x4_t a, float16x4_t b) {
+ return vuzp2_f16(a, b);
+}
+
+// CHECK-LABEL: @test_vuzp2q_f16(
+// CHECK: [[SHUFFLE_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: ret <8 x half> [[SHUFFLE_I]]
+float16x8_t test_vuzp2q_f16(float16x8_t a, float16x8_t b) {
+ return vuzp2q_f16(a, b);
+}
+
+// CHECK-LABEL: @test_vtrn1_f16(
+// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// CHECK: ret <4 x half> [[SHUFFLE_I]]
+float16x4_t test_vtrn1_f16(float16x4_t a, float16x4_t b) {
+ return vtrn1_f16(a, b);
+}
+
+// CHECK-LABEL: @test_vtrn1q_f16(
+// CHECK: [[SHUFFLE_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: ret <8 x half> [[SHUFFLE_I]]
+float16x8_t test_vtrn1q_f16(float16x8_t a, float16x8_t b) {
+ return vtrn1q_f16(a, b);
+}
+
+// CHECK-LABEL: @test_vtrn2_f16(
+// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+// CHECK: ret <4 x half> [[SHUFFLE_I]]
+float16x4_t test_vtrn2_f16(float16x4_t a, float16x4_t b) {
+ return vtrn2_f16(a, b);
+}
+
+// CHECK-LABEL: @test_vtrn2q_f16(
+// CHECK: [[SHUFFLE_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: ret <8 x half> [[SHUFFLE_I]]
+float16x8_t test_vtrn2q_f16(float16x8_t a, float16x8_t b) {
+ return vtrn2q_f16(a, b);
+}
+
diff --git a/test/CodeGen/complex-math.c b/test/CodeGen/complex-math.c
index 8792ca14b9d8..5fd25d009226 100644
--- a/test/CodeGen/complex-math.c
+++ b/test/CodeGen/complex-math.c
@@ -5,6 +5,7 @@
// RUN %clang_cc1 %s -O1 -emit-llvm -triple armv7-none-linux-gnueabi -o - | FileCheck %s --check-prefix=ARM
// RUN: %clang_cc1 %s -O1 -emit-llvm -triple armv7-none-linux-gnueabihf -o - | FileCheck %s --check-prefix=ARMHF
// RUN: %clang_cc1 %s -O1 -emit-llvm -triple thumbv7k-apple-watchos2.0 -o - -target-abi aapcs16 | FileCheck %s --check-prefix=ARM7K
+// RUN: %clang_cc1 %s -O1 -emit-llvm -triple aarch64-unknown-unknown -ffast-math -o - | FileCheck %s --check-prefix=AARCH64-FASTMATH
float _Complex add_float_rr(float a, float b) {
// X86-LABEL: @add_float_rr(
@@ -128,6 +129,29 @@ float _Complex div_float_rc(float a, float _Complex b) {
// X86-NOT: fdiv
// X86: call {{.*}} @__divsc3(
// X86: ret
+
+ // a / b = (A+iB) / (C+iD) = ((AC+BD)/(CC+DD)) + i((BC-AD)/(CC+DD))
+ // AARCH64-FASTMATH-LABEL: @div_float_rc(float %a, [2 x float] %b.coerce)
+ // A = a
+ // B = 0
+ // AARCH64-FASTMATH: [[C:%.*]] = extractvalue [2 x float] %b.coerce, 0
+ // AARCH64-FASTMATH: [[D:%.*]] = extractvalue [2 x float] %b.coerce, 1
+ //
+ // AARCH64-FASTMATH: [[AC:%.*]] = fmul fast float [[C]], %a
+ // BD = 0
+ // ACpBD = AC
+ //
+ // AARCH64-FASTMATH: [[CC:%.*]] = fmul fast float [[C]], [[C]]
+ // AARCH64-FASTMATH: [[DD:%.*]] = fmul fast float [[D]], [[D]]
+ // AARCH64-FASTMATH: [[CCpDD:%.*]] = fadd fast float [[CC]], [[DD]]
+ //
+ // BC = 0
+ // AARCH64-FASTMATH: [[AD:%.*]] = fmul fast float [[D]], %a
+ // AARCH64-FASTMATH: [[BCmAD:%.*]] = fsub fast float -0.000000e+00, [[AD]]
+ //
+ // AARCH64-FASTMATH: fdiv fast float [[AC]], [[CCpDD]]
+ // AARCH64-FASTMATH: fdiv fast float [[BCmAD]], [[CCpDD]]
+ // AARCH64-FASTMATH: ret
return a / b;
}
float _Complex div_float_cc(float _Complex a, float _Complex b) {
@@ -135,6 +159,29 @@ float _Complex div_float_cc(float _Complex a, float _Complex b) {
// X86-NOT: fdiv
// X86: call {{.*}} @__divsc3(
// X86: ret
+
+ // a / b = (A+iB) / (C+iD) = ((AC+BD)/(CC+DD)) + i((BC-AD)/(CC+DD))
+ // AARCH64-FASTMATH-LABEL: @div_float_cc([2 x float] %a.coerce, [2 x float] %b.coerce)
+ // AARCH64-FASTMATH: [[A:%.*]] = extractvalue [2 x float] %a.coerce, 0
+ // AARCH64-FASTMATH: [[B:%.*]] = extractvalue [2 x float] %a.coerce, 1
+ // AARCH64-FASTMATH: [[C:%.*]] = extractvalue [2 x float] %b.coerce, 0
+ // AARCH64-FASTMATH: [[D:%.*]] = extractvalue [2 x float] %b.coerce, 1
+ //
+ // AARCH64-FASTMATH: [[AC:%.*]] = fmul fast float [[C]], [[A]]
+ // AARCH64-FASTMATH: [[BD:%.*]] = fmul fast float [[D]], [[B]]
+ // AARCH64-FASTMATH: [[ACpBD:%.*]] = fadd fast float [[AC]], [[BD]]
+ //
+ // AARCH64-FASTMATH: [[CC:%.*]] = fmul fast float [[C]], [[C]]
+ // AARCH64-FASTMATH: [[DD:%.*]] = fmul fast float [[D]], [[D]]
+ // AARCH64-FASTMATH: [[CCpDD:%.*]] = fadd fast float [[CC]], [[DD]]
+ //
+ // AARCH64-FASTMATH: [[BC:%.*]] = fmul fast float [[C]], [[B]]
+ // AARCH64-FASTMATH: [[AD:%.*]] = fmul fast float [[D]], [[A]]
+ // AARCH64-FASTMATH: [[BCmAD:%.*]] = fsub fast float [[BC]], [[AD]]
+ //
+ // AARCH64-FASTMATH: fdiv fast float [[ACpBD]], [[CCpDD]]
+ // AARCH64-FASTMATH: fdiv fast float [[BCmAD]], [[CCpDD]]
+ // AARCH64-FASTMATH: ret
return a / b;
}
@@ -260,6 +307,29 @@ double _Complex div_double_rc(double a, double _Complex b) {
// X86-NOT: fdiv
// X86: call {{.*}} @__divdc3(
// X86: ret
+
+ // a / b = (A+iB) / (C+iD) = ((AC+BD)/(CC+DD)) + i((BC-AD)/(CC+DD))
+ // AARCH64-FASTMATH-LABEL: @div_double_rc(double %a, [2 x double] %b.coerce)
+ // A = a
+ // B = 0
+ // AARCH64-FASTMATH: [[C:%.*]] = extractvalue [2 x double] %b.coerce, 0
+ // AARCH64-FASTMATH: [[D:%.*]] = extractvalue [2 x double] %b.coerce, 1
+ //
+ // AARCH64-FASTMATH: [[AC:%.*]] = fmul fast double [[C]], %a
+ // BD = 0
+ // ACpBD = AC
+ //
+ // AARCH64-FASTMATH: [[CC:%.*]] = fmul fast double [[C]], [[C]]
+ // AARCH64-FASTMATH: [[DD:%.*]] = fmul fast double [[D]], [[D]]
+ // AARCH64-FASTMATH: [[CCpDD:%.*]] = fadd fast double [[CC]], [[DD]]
+ //
+ // BC = 0
+ // AARCH64-FASTMATH: [[AD:%.*]] = fmul fast double [[D]], %a
+ // AARCH64-FASTMATH: [[BCmAD:%.*]] = fsub fast double -0.000000e+00, [[AD]]
+ //
+ // AARCH64-FASTMATH: fdiv fast double [[AC]], [[CCpDD]]
+ // AARCH64-FASTMATH: fdiv fast double [[BCmAD]], [[CCpDD]]
+ // AARCH64-FASTMATH: ret
return a / b;
}
double _Complex div_double_cc(double _Complex a, double _Complex b) {
@@ -267,6 +337,29 @@ double _Complex div_double_cc(double _Complex a, double _Complex b) {
// X86-NOT: fdiv
// X86: call {{.*}} @__divdc3(
// X86: ret
+
+ // a / b = (A+iB) / (C+iD) = ((AC+BD)/(CC+DD)) + i((BC-AD)/(CC+DD))
+ // AARCH64-FASTMATH-LABEL: @div_double_cc([2 x double] %a.coerce, [2 x double] %b.coerce)
+ // AARCH64-FASTMATH: [[A:%.*]] = extractvalue [2 x double] %a.coerce, 0
+ // AARCH64-FASTMATH: [[B:%.*]] = extractvalue [2 x double] %a.coerce, 1
+ // AARCH64-FASTMATH: [[C:%.*]] = extractvalue [2 x double] %b.coerce, 0
+ // AARCH64-FASTMATH: [[D:%.*]] = extractvalue [2 x double] %b.coerce, 1
+ //
+ // AARCH64-FASTMATH: [[AC:%.*]] = fmul fast double [[C]], [[A]]
+ // AARCH64-FASTMATH: [[BD:%.*]] = fmul fast double [[D]], [[B]]
+ // AARCH64-FASTMATH: [[ACpBD:%.*]] = fadd fast double [[AC]], [[BD]]
+ //
+ // AARCH64-FASTMATH: [[CC:%.*]] = fmul fast double [[C]], [[C]]
+ // AARCH64-FASTMATH: [[DD:%.*]] = fmul fast double [[D]], [[D]]
+ // AARCH64-FASTMATH: [[CCpDD:%.*]] = fadd fast double [[CC]], [[DD]]
+ //
+ // AARCH64-FASTMATH: [[BC:%.*]] = fmul fast double [[C]], [[B]]
+ // AARCH64-FASTMATH: [[AD:%.*]] = fmul fast double [[D]], [[A]]
+ // AARCH64-FASTMATH: [[BCmAD:%.*]] = fsub fast double [[BC]], [[AD]]
+ //
+ // AARCH64-FASTMATH: fdiv fast double [[ACpBD]], [[CCpDD]]
+ // AARCH64-FASTMATH: fdiv fast double [[BCmAD]], [[CCpDD]]
+ // AARCH64-FASTMATH: ret
return a / b;
}
@@ -410,6 +503,29 @@ long double _Complex div_long_double_rc(long double a, long double _Complex b) {
// PPC-NOT: fdiv
// PPC: call {{.*}} @__divtc3(
// PPC: ret
+
+ // a / b = (A+iB) / (C+iD) = ((AC+BD)/(CC+DD)) + i((BC-AD)/(CC+DD))
+ // AARCH64-FASTMATH-LABEL: @div_long_double_rc(fp128 %a, [2 x fp128] %b.coerce)
+ // A = a
+ // B = 0
+ // AARCH64-FASTMATH: [[C:%.*]] = extractvalue [2 x fp128] %b.coerce, 0
+ // AARCH64-FASTMATH: [[D:%.*]] = extractvalue [2 x fp128] %b.coerce, 1
+ //
+ // AARCH64-FASTMATH: [[AC:%.*]] = fmul fast fp128 [[C]], %a
+ // BD = 0
+ // ACpBD = AC
+ //
+ // AARCH64-FASTMATH: [[CC:%.*]] = fmul fast fp128 [[C]], [[C]]
+ // AARCH64-FASTMATH: [[DD:%.*]] = fmul fast fp128 [[D]], [[D]]
+ // AARCH64-FASTMATH: [[CCpDD:%.*]] = fadd fast fp128 [[CC]], [[DD]]
+ //
+ // BC = 0
+ // AARCH64-FASTMATH: [[AD:%.*]] = fmul fast fp128 [[D]], %a
+ // AARCH64-FASTMATH: [[BCmAD:%.*]] = fsub fast fp128 0xL00000000000000008000000000000000, [[AD]]
+ //
+ // AARCH64-FASTMATH: fdiv fast fp128 [[AC]], [[CCpDD]]
+ // AARCH64-FASTMATH: fdiv fast fp128 [[BCmAD]], [[CCpDD]]
+ // AARCH64-FASTMATH: ret
return a / b;
}
long double _Complex div_long_double_cc(long double _Complex a, long double _Complex b) {
@@ -421,6 +537,29 @@ long double _Complex div_long_double_cc(long double _Complex a, long double _Com
// PPC-NOT: fdiv
// PPC: call {{.*}} @__divtc3(
// PPC: ret
+
+ // a / b = (A+iB) / (C+iD) = ((AC+BD)/(CC+DD)) + i((BC-AD)/(CC+DD))
+ // AARCH64-FASTMATH-LABEL: @div_long_double_cc([2 x fp128] %a.coerce, [2 x fp128] %b.coerce)
+ // AARCH64-FASTMATH: [[A:%.*]] = extractvalue [2 x fp128] %a.coerce, 0
+ // AARCH64-FASTMATH: [[B:%.*]] = extractvalue [2 x fp128] %a.coerce, 1
+ // AARCH64-FASTMATH: [[C:%.*]] = extractvalue [2 x fp128] %b.coerce, 0
+ // AARCH64-FASTMATH: [[D:%.*]] = extractvalue [2 x fp128] %b.coerce, 1
+ //
+ // AARCH64-FASTMATH: [[AC:%.*]] = fmul fast fp128 [[C]], [[A]]
+ // AARCH64-FASTMATH: [[BD:%.*]] = fmul fast fp128 [[D]], [[B]]
+ // AARCH64-FASTMATH: [[ACpBD:%.*]] = fadd fast fp128 [[AC]], [[BD]]
+ //
+ // AARCH64-FASTMATH: [[CC:%.*]] = fmul fast fp128 [[C]], [[C]]
+ // AARCH64-FASTMATH: [[DD:%.*]] = fmul fast fp128 [[D]], [[D]]
+ // AARCH64-FASTMATH: [[CCpDD:%.*]] = fadd fast fp128 [[CC]], [[DD]]
+ //
+ // AARCH64-FASTMATH: [[BC:%.*]] = fmul fast fp128 [[C]], [[B]]
+ // AARCH64-FASTMATH: [[AD:%.*]] = fmul fast fp128 [[D]], [[A]]
+ // AARCH64-FASTMATH: [[BCmAD:%.*]] = fsub fast fp128 [[BC]], [[AD]]
+ //
+ // AARCH64-FASTMATH: fdiv fast fp128 [[ACpBD]], [[CCpDD]]
+ // AARCH64-FASTMATH: fdiv fast fp128 [[BCmAD]], [[CCpDD]]
+ // AARCH64-FASTMATH: ret
return a / b;
}
diff --git a/test/CodeGen/tbaa-array.cpp b/test/CodeGen/tbaa-array.cpp
index 86ca5ccb40dc..4a6576e2eeb7 100644
--- a/test/CodeGen/tbaa-array.cpp
+++ b/test/CodeGen/tbaa-array.cpp
@@ -1,18 +1,52 @@
// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s \
// RUN: -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s \
+// RUN: -new-struct-path-tbaa -emit-llvm -o - | \
+// RUN: FileCheck -check-prefix=CHECK-NEW %s
//
// Check that we generate correct TBAA information for accesses to array
// elements.
struct A { int i; };
struct B { A a[1]; };
+struct C { int i; int x[3]; };
int foo(B *b) {
// CHECK-LABEL: _Z3fooP1B
// CHECK: load i32, {{.*}}, !tbaa [[TAG_A_i:!.*]]
+// CHECK-NEW-LABEL: _Z3fooP1B
+// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_A_i:!.*]]
return b->a->i;
}
+// Check that members of array types are represented correctly.
+int bar(C *c) {
+// CHECK-NEW-LABEL: _Z3barP1C
+// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_C_i:!.*]]
+ return c->i;
+}
+
+int bar2(C *c) {
+// CHECK-NEW-LABEL: _Z4bar2P1C
+// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
+ return c->x[2];
+}
+
+int bar3(C *c, int j) {
+// CHECK-NEW-LABEL: _Z4bar3P1Ci
+// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
+ return c->x[j];
+}
+
// CHECK-DAG: [[TAG_A_i]] = !{[[TYPE_A:!.*]], [[TYPE_int:!.*]], i64 0}
// CHECK-DAG: [[TYPE_A]] = !{!"_ZTS1A", !{{.*}}, i64 0}
// CHECK-DAG: [[TYPE_int]] = !{!"int", !{{.*}}, i64 0}
+
+// CHECK-NEW-DAG: [[TYPE_char:!.*]] = !{{{.*}}, i64 1, !"omnipotent char"}
+// CHECK-NEW-DAG: [[TYPE_int:!.*]] = !{[[TYPE_char]], i64 4, !"int"}
+// CHECK-NEW-DAG: [[TAG_int]] = !{[[TYPE_int]], [[TYPE_int]], i64 0, i64 4}
+// CHECK-NEW-DAG: [[TYPE_pointer:!.*]] = !{[[TYPE_char]], i64 8, !"any pointer"}
+// CHECK-NEW-DAG: [[TYPE_A:!.*]] = !{[[TYPE_char]], i64 4, !"_ZTS1A", [[TYPE_int]], i64 0, i64 4}
+// CHECK-NEW-DAG: [[TAG_A_i]] = !{[[TYPE_A]], [[TYPE_int]], i64 0, i64 4}
+// CHECK-NEW-DAG: [[TYPE_C:!.*]] = !{[[TYPE_char]], i64 16, !"_ZTS1C", [[TYPE_int]], i64 0, i64 4, [[TYPE_int]], i64 4, i64 12}
+// CHECK-NEW-DAG: [[TAG_C_i]] = !{[[TYPE_C:!.*]], [[TYPE_int:!.*]], i64 0, i64 4}
diff --git a/test/CodeGen/tbaa.cpp b/test/CodeGen/tbaa.cpp
index 10e64875476c..c8a9e69d92b9 100644
--- a/test/CodeGen/tbaa.cpp
+++ b/test/CodeGen/tbaa.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -no-struct-path-tbaa -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefix=PATH
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefixes=PATH,OLD-PATH
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -new-struct-path-tbaa -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefixes=PATH,NEW-PATH
// RUN: %clang_cc1 -triple x86_64-apple-darwin -O0 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefix=NO-TBAA
// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -relaxed-aliasing -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefix=NO-TBAA
// Test TBAA metadata generated by front-end.
@@ -248,29 +249,57 @@ uint32_t g15(StructS *S, StructS3 *S3, uint64_t count) {
// CHECK: [[TYPE_i16]] = !{!"short", [[TYPE_char]],
// CHECK: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0}
-// PATH: [[TYPE_CHAR:!.*]] = !{!"omnipotent char", !
-// PATH: [[TAG_i32]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0}
-// PATH: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR]]
-// PATH: [[TAG_A_f32]] = !{[[TYPE_A:!.*]], [[TYPE_INT]], i64 4}
-// PATH: [[TYPE_A]] = !{!"_ZTS7StructA", [[TYPE_SHORT:!.*]], i64 0, [[TYPE_INT]], i64 4, [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12}
-// PATH: [[TYPE_SHORT:!.*]] = !{!"short", [[TYPE_CHAR]]
-// PATH: [[TAG_A_f16]] = !{[[TYPE_A]], [[TYPE_SHORT]], i64 0}
-// PATH: [[TAG_B_a_f32]] = !{[[TYPE_B:!.*]], [[TYPE_INT]], i64 8}
-// PATH: [[TYPE_B]] = !{!"_ZTS7StructB", [[TYPE_SHORT]], i64 0, [[TYPE_A]], i64 4, [[TYPE_INT]], i64 20}
-// PATH: [[TAG_B_a_f16]] = !{[[TYPE_B]], [[TYPE_SHORT]], i64 4}
-// PATH: [[TAG_B_f32]] = !{[[TYPE_B]], [[TYPE_INT]], i64 20}
-// PATH: [[TAG_B_a_f32_2]] = !{[[TYPE_B]], [[TYPE_INT]], i64 16}
-// PATH: [[TAG_S_f32]] = !{[[TYPE_S:!.*]], [[TYPE_INT]], i64 4}
-// PATH: [[TYPE_S]] = !{!"_ZTS7StructS", [[TYPE_SHORT]], i64 0, [[TYPE_INT]], i64 4}
-// PATH: [[TAG_S_f16]] = !{[[TYPE_S]], [[TYPE_SHORT]], i64 0}
-// PATH: [[TAG_S2_f32]] = !{[[TYPE_S2:!.*]], [[TYPE_INT]], i64 4}
-// PATH: [[TYPE_S2]] = !{!"_ZTS8StructS2", [[TYPE_SHORT]], i64 0, [[TYPE_INT]], i64 4}
-// PATH: [[TAG_S2_f16]] = !{[[TYPE_S2]], [[TYPE_SHORT]], i64 0}
-// PATH: [[TAG_C_b_a_f32]] = !{[[TYPE_C:!.*]], [[TYPE_INT]], i64 12}
-// PATH: [[TYPE_C]] = !{!"_ZTS7StructC", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28}
-// PATH: [[TAG_D_b_a_f32]] = !{[[TYPE_D:!.*]], [[TYPE_INT]], i64 12}
-// PATH: [[TYPE_D]] = !{!"_ZTS7StructD", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28, [[TYPE_CHAR]], i64 32}
-// PATH: [[TAG_five_b]] = !{[[TYPE_five:!.*]], [[TYPE_CHAR]], i64 1}
-// PATH: [[TYPE_five]] = !{!"_ZTS4five", [[TYPE_CHAR]], i64 0, [[TYPE_INT]], i64 1, [[TYPE_CHAR]], i64 1, [[TYPE_CHAR]], i64 2}
-// PATH: [[TAG_six_b]] = !{[[TYPE_six:!.*]], [[TYPE_CHAR]], i64 4}
-// PATH: [[TYPE_six]] = !{!"_ZTS3six", [[TYPE_CHAR]], i64 0, [[TYPE_INT]], i64 4, [[TYPE_CHAR]], i64 4, [[TYPE_CHAR]], i64 5}
+// OLD-PATH: [[TYPE_CHAR:!.*]] = !{!"omnipotent char", !
+// OLD-PATH: [[TAG_i32]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0}
+// OLD-PATH: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR]]
+// OLD-PATH: [[TAG_A_f32]] = !{[[TYPE_A:!.*]], [[TYPE_INT]], i64 4}
+// OLD-PATH: [[TYPE_A]] = !{!"_ZTS7StructA", [[TYPE_SHORT:!.*]], i64 0, [[TYPE_INT]], i64 4, [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12}
+// OLD-PATH: [[TYPE_SHORT:!.*]] = !{!"short", [[TYPE_CHAR]]
+// OLD-PATH: [[TAG_A_f16]] = !{[[TYPE_A]], [[TYPE_SHORT]], i64 0}
+// OLD-PATH: [[TAG_B_a_f32]] = !{[[TYPE_B:!.*]], [[TYPE_INT]], i64 8}
+// OLD-PATH: [[TYPE_B]] = !{!"_ZTS7StructB", [[TYPE_SHORT]], i64 0, [[TYPE_A]], i64 4, [[TYPE_INT]], i64 20}
+// OLD-PATH: [[TAG_B_a_f16]] = !{[[TYPE_B]], [[TYPE_SHORT]], i64 4}
+// OLD-PATH: [[TAG_B_f32]] = !{[[TYPE_B]], [[TYPE_INT]], i64 20}
+// OLD-PATH: [[TAG_B_a_f32_2]] = !{[[TYPE_B]], [[TYPE_INT]], i64 16}
+// OLD-PATH: [[TAG_S_f32]] = !{[[TYPE_S:!.*]], [[TYPE_INT]], i64 4}
+// OLD-PATH: [[TYPE_S]] = !{!"_ZTS7StructS", [[TYPE_SHORT]], i64 0, [[TYPE_INT]], i64 4}
+// OLD-PATH: [[TAG_S_f16]] = !{[[TYPE_S]], [[TYPE_SHORT]], i64 0}
+// OLD-PATH: [[TAG_S2_f32]] = !{[[TYPE_S2:!.*]], [[TYPE_INT]], i64 4}
+// OLD-PATH: [[TYPE_S2]] = !{!"_ZTS8StructS2", [[TYPE_SHORT]], i64 0, [[TYPE_INT]], i64 4}
+// OLD-PATH: [[TAG_S2_f16]] = !{[[TYPE_S2]], [[TYPE_SHORT]], i64 0}
+// OLD-PATH: [[TAG_C_b_a_f32]] = !{[[TYPE_C:!.*]], [[TYPE_INT]], i64 12}
+// OLD-PATH: [[TYPE_C]] = !{!"_ZTS7StructC", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28}
+// OLD-PATH: [[TAG_D_b_a_f32]] = !{[[TYPE_D:!.*]], [[TYPE_INT]], i64 12}
+// OLD-PATH: [[TYPE_D]] = !{!"_ZTS7StructD", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28, [[TYPE_CHAR]], i64 32}
+// OLD-PATH: [[TAG_five_b]] = !{[[TYPE_five:!.*]], [[TYPE_CHAR]], i64 1}
+// OLD-PATH: [[TYPE_five]] = !{!"_ZTS4five", [[TYPE_CHAR]], i64 0, [[TYPE_INT]], i64 1, [[TYPE_CHAR]], i64 1, [[TYPE_CHAR]], i64 2}
+// OLD-PATH: [[TAG_six_b]] = !{[[TYPE_six:!.*]], [[TYPE_CHAR]], i64 4}
+// OLD-PATH: [[TYPE_six]] = !{!"_ZTS3six", [[TYPE_CHAR]], i64 0, [[TYPE_INT]], i64 4, [[TYPE_CHAR]], i64 4, [[TYPE_CHAR]], i64 5}
+
+// NEW-PATH-DAG: [[ROOT:!.*]] = !{!"Simple C++ TBAA"}
+// NEW-PATH-DAG: [[TYPE_char:!.*]] = !{[[ROOT]], i64 1, !"omnipotent char"}
+// NEW-PATH-DAG: [[TYPE_short:!.*]] = !{[[TYPE_char]], i64 2, !"short"}
+// NEW-PATH-DAG: [[TYPE_int:!.*]] = !{[[TYPE_char]], i64 4, !"int"}
+// NEW-PATH-DAG: [[TAG_i32:!.*]] = !{[[TYPE_int]], [[TYPE_int]], i64 0, i64 4}
+// NEW-PATH-DAG: [[TYPE_A:!.*]] = !{[[TYPE_char]], i64 16, !"_ZTS7StructA", [[TYPE_short]], i64 0, i64 2, [[TYPE_int]], i64 4, i64 4, !12, i64 8, i64 2, [[TYPE_int]], i64 12, i64 4}
+// NEW-PATH-DAG: [[TAG_A_f16]] = !{[[TYPE_A]], [[TYPE_short]], i64 0, i64 2}
+// NEW-PATH-DAG: [[TAG_A_f32]] = !{[[TYPE_A]], [[TYPE_int]], i64 4, i64 4}
+// NEW-PATH-DAG: [[TYPE_B:!.*]] = !{[[TYPE_char]], i64 24, !"_ZTS7StructB", [[TYPE_short]], i64 0, i64 2, [[TYPE_A]], i64 4, i64 16, [[TYPE_int]], i64 20, i64 4}
+// NEW-PATH-DAG: [[TAG_B_a_f16]] = !{[[TYPE_B]], [[TYPE_short]], i64 4, i64 2}
+// NEW-PATH-DAG: [[TAG_B_a_f32]] = !{[[TYPE_B]], [[TYPE_int]], i64 8, i64 4}
+// NEW-PATH-DAG: [[TAG_B_f32]] = !{[[TYPE_B]], [[TYPE_int]], i64 20, i64 4}
+// NEW-PATH-DAG: [[TAG_B_a_f32_2]] = !{[[TYPE_B]], [[TYPE_int]], i64 16, i64 4}
+// NEW-PATH-DAG: [[TYPE_S:!.*]] = !{[[TYPE_char]], i64 8, !"_ZTS7StructS", [[TYPE_short]], i64 0, i64 2, [[TYPE_int]], i64 4, i64 4}
+// NEW-PATH-DAG: [[TAG_S_f16]] = !{[[TYPE_S]], [[TYPE_short]], i64 0, i64 2}
+// NEW-PATH-DAG: [[TAG_S_f32]] = !{[[TYPE_S]], [[TYPE_int]], i64 4, i64 4}
+// NEW-PATH-DAG: [[TYPE_S2:!.*]] = !{[[TYPE_char]], i64 8, !"_ZTS8StructS2", [[TYPE_short]], i64 0, i64 2, [[TYPE_int]], i64 4, i64 4}
+// NEW-PATH-DAG: [[TAG_S2_f16]] = !{[[TYPE_S2]], [[TYPE_short]], i64 0, i64 2}
+// NEW-PATH-DAG: [[TAG_S2_f32]] = !{[[TYPE_S2]], [[TYPE_int]], i64 4, i64 4}
+// NEW-PATH-DAG: [[TYPE_C:!.*]] = !{[[TYPE_char]], i64 32, !"_ZTS7StructC", [[TYPE_short]], i64 0, i64 2, [[TYPE_B]], i64 4, i64 24, [[TYPE_int]], i64 28, i64 4}
+// NEW-PATH-DAG: [[TAG_C_b_a_f32]] = !{[[TYPE_C]], [[TYPE_int]], i64 12, i64 4}
+// NEW-PATH-DAG: [[TYPE_D:!.*]] = !{[[TYPE_char]], i64 36, !"_ZTS7StructD", [[TYPE_short]], i64 0, i64 2, [[TYPE_B]], i64 4, i64 24, [[TYPE_int]], i64 28, i64 4, [[TYPE_char]], i64 32, i64 1}
+// NEW-PATH-DAG: [[TAG_D_b_a_f32]] = !{[[TYPE_D]], [[TYPE_int]], i64 12, i64 4}
+// NEW-PATH-DAG: [[TYPE_five:!.*]] = !{[[TYPE_char]], i64 3, !"_ZTS4five", [[TYPE_char]], i64 0, i64 1, [[TYPE_int]], i64 1, i64 4, [[TYPE_char]], i64 1, i64 1, [[TYPE_char]], i64 2, i64 1}
+// NEW-PATH-DAG: [[TAG_five_b]] = !{[[TYPE_five]], [[TYPE_char]], i64 1, i64 1}
+// NEW-PATH-DAG: [[TYPE_six:!.*]] = !{[[TYPE_char]], i64 6, !"_ZTS3six", [[TYPE_char]], i64 0, i64 1, [[TYPE_int]], i64 4, i64 4, [[TYPE_char]], i64 4, i64 1, [[TYPE_char]], i64 5, i64 1}
+// NEW-PATH-DAG: [[TAG_six_b]] = !{[[TYPE_six]], [[TYPE_char]], i64 4, i64 1}
diff --git a/test/CodeGen/ubsan-noreturn.c b/test/CodeGen/ubsan-noreturn.c
new file mode 100644
index 000000000000..7de24e016920
--- /dev/null
+++ b/test/CodeGen/ubsan-noreturn.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 %s -emit-llvm -fsanitize=unreachable -o - | FileCheck %s
+
+// CHECK-LABEL: @f(
+void __attribute__((noreturn)) f() {
+ // CHECK: __ubsan_handle_builtin_unreachable
+ // CHECK: unreachable
+}
diff --git a/test/CodeGenCXX/ubsan-unreachable.cpp b/test/CodeGenCXX/ubsan-unreachable.cpp
new file mode 100644
index 000000000000..32a78048cfd6
--- /dev/null
+++ b/test/CodeGenCXX/ubsan-unreachable.cpp
@@ -0,0 +1,81 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=unreachable | FileCheck %s
+
+extern void __attribute__((noreturn)) abort();
+
+// CHECK-LABEL: define void @_Z14calls_noreturnv
+void calls_noreturn() {
+ abort();
+
+ // Check that there are no attributes on the call site.
+ // CHECK-NOT: call void @_Z5abortv{{.*}}#
+
+ // CHECK: __ubsan_handle_builtin_unreachable
+ // CHECK: unreachable
+}
+
+struct A {
+ // CHECK: declare void @_Z5abortv{{.*}} [[ABORT_ATTR:#[0-9]+]]
+
+ // CHECK-LABEL: define linkonce_odr void @_ZN1A5call1Ev
+ void call1() {
+ // CHECK-NOT: call void @_ZN1A16does_not_return2Ev{{.*}}#
+ does_not_return2();
+
+ // CHECK: __ubsan_handle_builtin_unreachable
+ // CHECK: unreachable
+ }
+
+ // Test static members.
+ static void __attribute__((noreturn)) does_not_return1() {
+ // CHECK-NOT: call void @_Z5abortv{{.*}}#
+ abort();
+ }
+
+ // CHECK-LABEL: define linkonce_odr void @_ZN1A5call2Ev
+ void call2() {
+ // CHECK-NOT: call void @_ZN1A16does_not_return1Ev{{.*}}#
+ does_not_return1();
+
+ // CHECK: __ubsan_handle_builtin_unreachable
+ // CHECK: unreachable
+ }
+
+ // Test calls through pointers to non-static member functions.
+ typedef void __attribute__((noreturn)) (A::*MemFn)();
+
+ // CHECK-LABEL: define linkonce_odr void @_ZN1A5call3Ev
+ void call3() {
+ MemFn MF = &A::does_not_return2;
+ (this->*MF)();
+
+ // CHECK-NOT: call void %{{.*}}#
+ // CHECK: __ubsan_handle_builtin_unreachable
+ // CHECK: unreachable
+ }
+
+ // Test regular members.
+ // CHECK-LABEL: define linkonce_odr void @_ZN1A16does_not_return2Ev({{.*}})
+ // CHECK-SAME: [[DOES_NOT_RETURN_ATTR:#[0-9]+]]
+ void __attribute__((noreturn)) does_not_return2() {
+ // CHECK-NOT: call void @_Z5abortv(){{.*}}#
+ abort();
+
+ // CHECK: call void @__ubsan_handle_builtin_unreachable
+ // CHECK: unreachable
+
+ // CHECK: call void @__ubsan_handle_builtin_unreachable
+ // CHECK: unreachable
+ }
+};
+
+// CHECK: define linkonce_odr void @_ZN1A16does_not_return1Ev() [[DOES_NOT_RETURN_ATTR]]
+
+void force_irgen() {
+ A a;
+ a.call1();
+ a.call2();
+ a.call3();
+}
+
+// CHECK-NOT: [[ABORT_ATTR]] = {{[^}]+}}noreturn
+// CHECK-NOT: [[DOES_NOT_RETURN_ATTR]] = {{[^}]+}}noreturn
diff --git a/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/crtbegin.o b/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/crtbegin.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/crtbegin.o
+++ b/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/crtbegin.o
diff --git a/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/crtend.o b/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/crtend.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/crtend.o
+++ b/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/crtend.o
diff --git a/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/crti.o b/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/crti.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/crti.o
+++ b/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/crti.o
diff --git a/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/crtn.o b/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/crtn.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/crtn.o
+++ b/test/Driver/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/crtn.o
diff --git a/test/Driver/Inputs/basic_myriad_tree/sparc-myriad-elf/include/c++/4.8.2/.keep b/test/Driver/Inputs/basic_myriad_tree/sparc-myriad-rtems/include/c++/6.3.0/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_myriad_tree/sparc-myriad-elf/include/c++/4.8.2/.keep
+++ b/test/Driver/Inputs/basic_myriad_tree/sparc-myriad-rtems/include/c++/6.3.0/.keep
diff --git a/test/Driver/Inputs/basic_myriad_tree/sparc-myriad-elf/lib/crt0.o b/test/Driver/Inputs/basic_myriad_tree/sparc-myriad-rtems/lib/crt0.o
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_myriad_tree/sparc-myriad-elf/lib/crt0.o
+++ b/test/Driver/Inputs/basic_myriad_tree/sparc-myriad-rtems/lib/crt0.o
diff --git a/test/Driver/darwin-version.c b/test/Driver/darwin-version.c
index 9fddb1abcfa6..4a9cdf9e5f52 100644
--- a/test/Driver/darwin-version.c
+++ b/test/Driver/darwin-version.c
@@ -12,11 +12,15 @@
// CHECK-VERSION-IOS3: "armv6k-apple-ios3.0.0"
// RUN: env IPHONEOS_DEPLOYMENT_TARGET=11.0 \
-// RUN: %clang -target armv7-apple-ios9.0 -c -### %s 2> %t.err
+// RUN: %clang -target armv7-apple-darwin -c -### %s 2> %t.err
// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-VERSION-IOS4 %s
// CHECK-VERSION-IOS4: invalid iOS deployment version 'IPHONEOS_DEPLOYMENT_TARGET=11.0'
-// RUN: %clang -target armv7-apple-ios9.0 -miphoneos-version-min=11.0 -c -### %s 2> %t.err
+// RUN: %clang -target armv7-apple-ios11.0 -c -### %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-VERSION-IOS41 %s
+// CHECK-VERSION-IOS41: invalid iOS deployment version '--target=armv7-apple-ios11.0'
+
+// RUN: %clang -target armv7-apple-darwin -miphoneos-version-min=11.0 -c -### %s 2> %t.err
// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-VERSION-IOS5 %s
// CHECK-VERSION-IOS5: invalid iOS deployment version '-miphoneos-version-min=11.0'
@@ -25,13 +29,14 @@
// CHECK-VERSION-IOS6: invalid iOS deployment version '-mios-simulator-version-min=11.0'
// RUN: %clang -target armv7-apple-ios11.1 -c -### %s 2>&1 | \
-// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS7 %s
-// RUN: %clang -target armv7-apple-ios9 -Wno-missing-sysroot -isysroot SDKs/iPhoneOS11.0.sdk -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS71 %s
+// CHECK-VERSION-IOS71: invalid iOS deployment version
+// RUN: %clang -target armv7-apple-darwin -Wno-missing-sysroot -isysroot SDKs/iPhoneOS11.0.sdk -c -### %s 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS7 %s
// CHECK-VERSION-IOS7: thumbv7-apple-ios10.99.99
// RUN: env IPHONEOS_DEPLOYMENT_TARGET=11.0 \
-// RUN: %clang -target arm64-apple-ios11.0 -c -### %s 2>&1 | \
+// RUN: %clang -target arm64-apple-darwin -c -### %s 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS8 %s
// CHECK-VERSION-IOS8: arm64-apple-ios11.0.0
@@ -49,7 +54,7 @@
// RUN: %clang -target armv7-apple-ios9.0 -miphoneos-version-min=11.0 -c -Wno-invalid-ios-deployment-target -### %s 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-IOS12 %s
-// CHECK-VERSION-IOS12: thumbv7-apple-ios11.0.0
+// CHECK-VERSION-IOS12: thumbv7-apple-ios9.0.0
// RUN: %clang -target i686-apple-darwin8 -c %s -### 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-OSX4 %s
@@ -68,14 +73,14 @@
// CHECK-VERSION-OSX6: "i386-apple-macosx10.6.0"
// RUN: %clang -target x86_64-apple-darwin14 -c %s -### 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-OSX10 %s
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.10 -c %s -### 2>&1 | \
+// RUN: %clang -target x86_64-apple-darwin -mmacosx-version-min=10.10 -c %s -### 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-OSX10 %s
-// RUN: %clang -target x86_64-apple-macosx -mmacos-version-min=10.10 -c %s -### 2>&1 | \
+// RUN: %clang -target x86_64-apple-darwin -mmacos-version-min=10.10 -c %s -### 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-OSX10 %s
// CHECK-VERSION-OSX10: "x86_64-apple-macosx10.10.0"
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min= -c %s -### 2>&1 | \
+// RUN: %clang -target x86_64-apple-darwin -mmacosx-version-min= -c %s -### 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-MISSING %s
-// RUN: %clang -target x86_64-apple-macosx -mmacos-version-min= -c %s -### 2>&1 | \
+// RUN: %clang -target x86_64-apple-darwin -mmacos-version-min= -c %s -### 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-MISSING %s
// CHECK-VERSION-MISSING: invalid version number
// RUN: %clang -target armv7k-apple-darwin -mwatchos-version-min=2.0 -c %s -### 2>&1 | \
@@ -144,3 +149,140 @@
// RUN: %clang -target x86_64-apple-darwin -c %s -### 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-VERSION-INVALID-ENV %s
// CHECK-VERSION-INVALID-ENV: invalid version number in 'MACOSX_DEPLOYMENT_TARGET=1000.1000'
+
+
+
+// Target can specify the OS version:
+
+// RUN: %clang -target x86_64-apple-macos10.11.2 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TMAC2 %s
+// CHECK-VERSION-TMAC2: "x86_64-apple-macosx10.11.2"
+
+// RUN: %clang -target arm64-apple-ios11.1 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TIOS1 %s
+// CHECK-VERSION-TIOS1: "arm64-apple-ios11.1.0"
+
+// RUN: %clang -target arm64-apple-tvos10.3 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TTVOS1 %s
+// CHECK-VERSION-TTVOS1: "arm64-apple-tvos10.3.0"
+
+// RUN: %clang -target armv7k-apple-watchos4.1 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TWATCHOS1 %s
+// CHECK-VERSION-TWATCHOS1: "thumbv7k-apple-watchos4.1.0"
+
+// "darwin" always back to the -m<os>version-min and environment:
+
+// RUN: %clang -target x86_64-apple-darwin14 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TDARWIN-FALL1 %s
+// CHECK-VERSION-TDARWIN-FALL1: "x86_64-apple-macosx10.10.0"
+
+// RUN: %clang -target x86_64-apple-darwin14 -miphoneos-version-min=10.1 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TDARWIN-FALL2 %s
+// CHECK-VERSION-TDARWIN-FALL2: "x86_64-apple-ios10.1.0-simulator"
+
+// RUN: env IPHONEOS_DEPLOYMENT_TARGET=9.1 \
+// RUN: %clang -target arm64-apple-darwin14 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TDARWIN-FALL3 %s
+// CHECK-VERSION-TDARWIN-FALL3: "arm64-apple-ios9.1.0"
+
+// RUN: %clang -target arm64-apple-darwin14 -isysroot SDKs/iPhoneOS11.0.sdk -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TDARWIN-FALL4 %s
+// CHECK-VERSION-TDARWIN-FALL4: "arm64-apple-ios11.0.0"
+
+// RUN: %clang -target unknown-apple-darwin12 -arch armv7 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TDARWIN-FALL5 %s
+// CHECK-VERSION-TDARWIN-FALL5: "thumbv7-apple-ios5.0.0"
+
+// Warn about -m<os>-version-min when it's used with target:
+
+// RUN: %clang -target x86_64-apple-macos10.11.2 -mmacos-version-min=10.6 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TNO-OSV1 %s
+// CHECK-VERSION-TNO-OSV1: overriding '-mmacosx-version-min=10.6' option with '--target=x86_64-apple-macos10.11.2'
+
+// RUN: %clang -target x86_64-apple-macos -miphoneos-version-min=9.1 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TNO-OSV2 %s
+// CHECK-VERSION-TNO-OSV2: overriding '-miphoneos-version-min=9.1' option with '--target=x86_64-apple-macos'
+
+// RUN: %clang -target x86_64-apple-ios -miphonesimulator-version-min=10.0 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TNO-OSV3 %s
+// CHECK-VERSION-TNO-OSV3: overriding '-mios-simulator-version-min=10.0' option with '--target=x86_64-apple-ios'
+// CHECK-VERSION-TNO-OSV3-NOT: argument unused during compilation
+
+// RUN: %clang -target arm64-apple-ios10.1.0 -miphoneos-version-min=10.1.0.1 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TNO-OSV4 %s
+// CHECK-VERSION-TNO-OSV4: overriding '-miphoneos-version-min=10.1.0.1' option with '--target=arm64-apple-ios10.1.0'
+
+// RUN: %clang -target x86_64-apple-macos10.6 -mmacos-version-min=10.6 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TNO-SAME %s
+// CHECK-VERSION-TNO-SAME-NOT: overriding
+// CHECK-VERSION-TNO-SAME-NOT: argument unused during compilation
+
+// Target with OS version is not overriden by -m<os>-version-min variables:
+
+// RUN: %clang -target x86_64-apple-macos10.11.2 -mmacos-version-min=10.6 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TIGNORE-OSV1 %s
+// CHECK-VERSION-TIGNORE-OSV1: "x86_64-apple-macosx10.11.2"
+
+// RUN: %clang -target arm64-apple-ios11.0 -mios-version-min=9.0 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TIGNORE-OSV2 %s
+// CHECK-VERSION-TIGNORE-OSV2: "arm64-apple-ios11.0.0"
+
+// RUN: %clang -target arm64-apple-tvos11.0 -mtvos-version-min=9.0 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TIGNORE-OSV3 %s
+// CHECK-VERSION-TIGNORE-OSV3: "arm64-apple-tvos11.0.0"
+
+// RUN: %clang -target armv7k-apple-watchos3 -mwatchos-version-min=4 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TIGNORE-OSV4 %s
+// CHECK-VERSION-TIGNORE-OSV4: "thumbv7k-apple-watchos3.0.0"
+
+// Target with OS version is not overriden by environment variables:
+
+// RUN: env MACOSX_DEPLOYMENT_TARGET=10.1 \
+// RUN: %clang -target i386-apple-macos10.5 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TMACOS-CMD %s
+// CHECK-VERSION-TMACOS-CMD: "i386-apple-macosx10.5.0"
+
+// RUN: env IPHONEOS_DEPLOYMENT_TARGET=10.1 \
+// RUN: %clang -target arm64-apple-ios11 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TIOS-CMD %s
+// CHECK-VERSION-TIOS-CMD: "arm64-apple-ios11.0.0"
+
+// RUN: env TVOS_DEPLOYMENT_TARGET=8.3.1 \
+// RUN: %clang -target arm64-apple-tvos9 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TTVOS-CMD %s
+// CHECK-VERSION-TTVOS-CMD: "arm64-apple-tvos9.0.0"
+
+// RUN: env WATCHOS_DEPLOYMENT_TARGET=2 \
+// RUN: %clang -target armv7k-apple-watchos3 -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TWATCHOS-CMD %s
+// CHECK-VERSION-TWATCHOS-CMD: "thumbv7k-apple-watchos3.0.0"
+
+// Target with OS version is not overriden by the SDK:
+
+// RUN: %clang -target armv7-apple-ios9 -Wno-missing-sysroot -isysroot SDKs/iPhoneOS11.0.sdk -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TIOS-SDK %s
+// CHECK-VERSION-TIOS-SDK: thumbv7-apple-ios9
+
+// RUN: %clang -target armv7k-apple-watchos4 -Wno-missing-sysroot -isysroot SDKs/WatchOS3.0.sdk -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TWATCHOS-SDK %s
+// CHECK-VERSION-TWATCHOS-SDK: thumbv7k-apple-watchos4
+
+// RUN: %clang -target armv7-apple-tvos9 -Wno-missing-sysroot -isysroot SDKs/AppleTVOS11.0.sdk -c -### %s 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TTVOS-SDK %s
+// CHECK-VERSION-TTVOS-SDK: thumbv7-apple-tvos9
+
+// Target with OS version is not overriden by arch:
+
+// RUN: %clang -target uknown-apple-macos10.11.2 -arch=armv7k -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TIGNORE-ARCH1 %s
+// CHECK-VERSION-TIGNORE-ARCH1: "unknown-apple-macosx10.11.2"
+
+// Target can be used to specify the environment:
+
+// RUN: %clang -target x86_64-apple-ios11-simulator -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TENV-SIM1 %s
+// CHECK-VERSION-TENV-SIM1: "x86_64-apple-ios11.0.0-simulator"
+
+// RUN: %clang -target armv7k-apple-ios10.1-simulator -c %s -### 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-VERSION-TENV-SIM2 %s
+// CHECK-VERSION-TENV-SIM2: "thumbv7k-apple-ios10.1.0-simulator"
diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c
index eb8eab574cb1..7870f724b6c3 100644
--- a/test/Driver/fsanitize.c
+++ b/test/Driver/fsanitize.c
@@ -3,6 +3,7 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
// RUN: %clang -target x86_64-linux-gnu -fsanitize-undefined-trap-on-error -fsanitize=undefined-trap %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
+// CHECK-UNDEFINED-TRAP-NOT: -fsanitize-recover
// CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute|function),?){19}"}}
// CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound"
// CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound"
diff --git a/test/Driver/fuchsia.c b/test/Driver/fuchsia.c
index eb413b7509be..b6946ef40664 100644
--- a/test/Driver/fuchsia.c
+++ b/test/Driver/fuchsia.c
@@ -79,3 +79,20 @@
// CHECK-ASAN-SHARED: "-fsanitize-address-globals-dead-stripping"
// CHECK-ASAN-SHARED: "{{.*[/\\]}}libclang_rt.asan-x86_64.so"
// CHECK-ASAN-SHARED-NOT: "{{.*[/\\]}}libclang_rt.asan-preinit-x86_64.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: "-pie"
+
+// 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: "-pie"
+
+// 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"
diff --git a/test/Driver/myriad-toolchain.c b/test/Driver/myriad-toolchain.c
index 7bd215bf1a48..26b02387093a 100644
--- a/test/Driver/myriad-toolchain.c
+++ b/test/Driver/myriad-toolchain.c
@@ -1,19 +1,19 @@
-// RUN: %clang -no-canonical-prefixes -### -target sparc-myriad-rtems-elf %s \
+// RUN: %clang -no-canonical-prefixes -### -target sparc-myriad-rtems %s \
// RUN: -ccc-install-dir %S/Inputs/basic_myriad_tree/bin \
// RUN: --gcc-toolchain=%S/Inputs/basic_myriad_tree 2>&1 | FileCheck %s -check-prefix=LINK_WITH_RTEMS
// LINK_WITH_RTEMS: Inputs{{.*}}crti.o
// LINK_WITH_RTEMS: Inputs{{.*}}crtbegin.o
-// LINK_WITH_RTEMS: "-L{{.*}}Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2"
-// LINK_WITH_RTEMS: "-L{{.*}}Inputs/basic_myriad_tree/bin/../sparc-myriad-elf/lib"
+// LINK_WITH_RTEMS: "-L{{.*}}Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0"
+// LINK_WITH_RTEMS: "-L{{.*}}Inputs/basic_myriad_tree/bin/../sparc-myriad-rtems/lib"
// LINK_WITH_RTEMS: "--start-group" "-lc" "-lgcc" "-lrtemscpu" "-lrtemsbsp" "--end-group"
// LINK_WITH_RTEMS: Inputs{{.*}}crtend.o
// LINK_WITH_RTEMS: Inputs{{.*}}crtn.o
-// RUN: %clang -c -no-canonical-prefixes -### -target sparc-myriad-rtems-elf -x c++ %s \
+// RUN: %clang -c -no-canonical-prefixes -### -target sparc-myriad-rtems -x c++ %s \
// RUN: -stdlib=libstdc++ --gcc-toolchain=%S/Inputs/basic_myriad_tree 2>&1 | FileCheck %s -check-prefix=COMPILE_CXX
-// COMPILE_CXX: "-internal-isystem" "{{.*}}/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/../../../../sparc-myriad-elf/include/c++/4.8.2"
-// COMPILE_CXX: "-internal-isystem" "{{.*}}/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/../../../../sparc-myriad-elf/include/c++/4.8.2/sparc-myriad-elf"
-// COMPILE_CXX: "-internal-isystem" "{{.*}}/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/../../../../sparc-myriad-elf/include/c++/4.8.2/backward"
+// COMPILE_CXX: "-internal-isystem" "{{.*}}/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/../../../../sparc-myriad-rtems/include/c++/6.3.0"
+// COMPILE_CXX: "-internal-isystem" "{{.*}}/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/../../../../sparc-myriad-rtems/include/c++/6.3.0/sparc-myriad-rtems"
+// COMPILE_CXX: "-internal-isystem" "{{.*}}/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-rtems/6.3.0/../../../../sparc-myriad-rtems/include/c++/6.3.0/backward"
// RUN: %clang -### -E -target sparc-myriad --sysroot=/yow %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=SLASH_INCLUDE
@@ -85,6 +85,6 @@
// RUN: %clang -### -c -g %s -target sparc-myriad 2>&1 | FileCheck -check-prefix=G_SPARC %s
// G_SPARC: "-debug-info-kind=limited" "-dwarf-version=2"
-// RUN: %clang -### -c %s -target sparc-myriad-elf -fuse-init-array 2>&1 \
+// RUN: %clang -### -c %s -target sparc-myriad-rtems -fuse-init-array 2>&1 \
// RUN: | FileCheck -check-prefix=USE-INIT-ARRAY %s
// USE-INIT-ARRAY-NOT: argument unused
diff --git a/test/Driver/objc-weak.m b/test/Driver/objc-weak.m
index 68ae26e1bcbc..85cfcd825495 100644
--- a/test/Driver/objc-weak.m
+++ b/test/Driver/objc-weak.m
@@ -1,27 +1,27 @@
// Check miscellaneous Objective-C options.
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.7 -S -### %s -fobjc-arc -fobjc-weak 2>&1 | FileCheck %s --check-prefix ARC-WEAK
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.7 -S -### %s -fno-objc-weak -fobjc-weak -fobjc-arc 2>&1 | FileCheck %s --check-prefix ARC-WEAK
+// RUN: %clang -target x86_64-apple-macosx10.7 -S -### %s -fobjc-arc -fobjc-weak 2>&1 | FileCheck %s --check-prefix ARC-WEAK
+// RUN: %clang -target x86_64-apple-macosx10.7 -S -### %s -fno-objc-weak -fobjc-weak -fobjc-arc 2>&1 | FileCheck %s --check-prefix ARC-WEAK
// ARC-WEAK: -fobjc-arc
// ARC-WEAK: -fobjc-weak
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.7 -S -### %s -fobjc-arc -fno-objc-weak 2>&1 | FileCheck %s --check-prefix ARC-NO-WEAK
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.7 -S -### %s -fobjc-weak -fno-objc-weak -fobjc-arc 2>&1 | FileCheck %s --check-prefix ARC-NO-WEAK
+// RUN: %clang -target x86_64-apple-macos10.7 -S -### %s -fobjc-arc -fno-objc-weak 2>&1 | FileCheck %s --check-prefix ARC-NO-WEAK
+// RUN: %clang -target x86_64-apple-macos10.7 -S -### %s -fobjc-weak -fno-objc-weak -fobjc-arc 2>&1 | FileCheck %s --check-prefix ARC-NO-WEAK
// ARC-NO-WEAK: -fobjc-arc
// ARC-NO-WEAK: -fno-objc-weak
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.5 -S -### %s -fobjc-arc -fobjc-weak 2>&1 | FileCheck %s --check-prefix ARC-WEAK-NOTSUPPORTED
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.5 -S -### %s -fno-objc-weak -fobjc-weak -fobjc-arc 2>&1 | FileCheck %s --check-prefix ARC-WEAK-NOTSUPPORTED
+// RUN: %clang -target x86_64-apple-macosx10.5 -S -### %s -fobjc-arc -fobjc-weak 2>&1 | FileCheck %s --check-prefix ARC-WEAK-NOTSUPPORTED
+// RUN: %clang -target x86_64-apple-macosx10.5 -S -### %s -fno-objc-weak -fobjc-weak -fobjc-arc 2>&1 | FileCheck %s --check-prefix ARC-WEAK-NOTSUPPORTED
// ARC-WEAK-NOTSUPPORTED: error: -fobjc-weak is not supported on the current deployment target
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.7 -S -### %s -fobjc-weak 2>&1 | FileCheck %s --check-prefix MRC-WEAK
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.7 -S -### %s -fno-objc-weak -fobjc-weak 2>&1 | FileCheck %s --check-prefix MRC-WEAK
+// RUN: %clang -target x86_64-apple-macos10.7 -S -### %s -fobjc-weak 2>&1 | FileCheck %s --check-prefix MRC-WEAK
+// RUN: %clang -target x86_64-apple-macos10.7 -S -### %s -fno-objc-weak -fobjc-weak 2>&1 | FileCheck %s --check-prefix MRC-WEAK
// MRC-WEAK: -fobjc-weak
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.7 -S -### %s -fno-objc-weak 2>&1 | FileCheck %s --check-prefix MRC-NO-WEAK
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.7 -S -### %s -fobjc-weak -fno-objc-weak 2>&1 | FileCheck %s --check-prefix MRC-NO-WEAK
+// RUN: %clang -target x86_64-apple-macosx10.7 -S -### %s -fno-objc-weak 2>&1 | FileCheck %s --check-prefix MRC-NO-WEAK
+// RUN: %clang -target x86_64-apple-macosx10.7 -S -### %s -fobjc-weak -fno-objc-weak 2>&1 | FileCheck %s --check-prefix MRC-NO-WEAK
// MRC-NO-WEAK: -fno-objc-weak
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.5 -S -### %s -fobjc-weak 2>&1 | FileCheck %s --check-prefix MRC-WEAK-NOTSUPPORTED
-// RUN: %clang -target x86_64-apple-macosx -mmacosx-version-min=10.5 -S -### %s -fno-objc-weak -fobjc-weak 2>&1 | FileCheck %s --check-prefix MRC-WEAK-NOTSUPPORTED
+// RUN: %clang -target x86_64-apple-macosx10.5 -S -### %s -fobjc-weak 2>&1 | FileCheck %s --check-prefix MRC-WEAK-NOTSUPPORTED
+// RUN: %clang -target x86_64-apple-macosx10.5 -S -### %s -fno-objc-weak -fobjc-weak 2>&1 | FileCheck %s --check-prefix MRC-WEAK-NOTSUPPORTED
// MRC-WEAK-NOTSUPPORTED: error: -fobjc-weak is not supported on the current deployment target
diff --git a/test/Driver/opt-record.c b/test/Driver/opt-record.c
index 5e8a28f5f8cc..7b4ec48632e2 100644
--- a/test/Driver/opt-record.c
+++ b/test/Driver/opt-record.c
@@ -9,6 +9,8 @@
// RUN: %clang -### -S -fsave-optimization-record -x cuda -nocudainc -nocudalib %s 2>&1 | FileCheck %s -check-prefix=CHECK-NO-O -check-prefix=CHECK-CUDA-DEV
// RUN: %clang -### -fsave-optimization-record -x cuda -nocudainc -nocudalib %s 2>&1 | FileCheck %s -check-prefix=CHECK-NO-O -check-prefix=CHECK-CUDA-DEV
// RUN: %clang -### -S -o FOO -fsave-optimization-record -foptimization-record-file=BAR.txt %s 2>&1 | FileCheck %s -check-prefix=CHECK-EQ
+// RUN: %clang -### -S -o FOO -foptimization-record-file=BAR.txt %s 2>&1 | FileCheck %s -check-prefix=CHECK-EQ
+// RUN: %clang -### -S -o FOO -foptimization-record-file=BAR.txt -fno-save-optimization-record %s 2>&1 | FileCheck %s --check-prefix=CHECK-FOPT-DISABLE
// CHECK: "-cc1"
// CHECK: "-opt-record-file" "FOO.opt.yaml"
@@ -20,3 +22,4 @@
// CHECK-EQ: "-cc1"
// CHECK-EQ: "-opt-record-file" "BAR.txt"
+// CHECK-FOPT-DISABLE-NOT: "-fno-save-optimization-record"
diff --git a/test/Driver/pic.c b/test/Driver/pic.c
index 9b3aa0e77135..1b4257c28bb5 100644
--- a/test/Driver/pic.c
+++ b/test/Driver/pic.c
@@ -221,19 +221,19 @@
//
// Checks for ARM+Apple+IOS including -fapple-kext, -mkernel, and iphoneos
// version boundaries.
-// RUN: %clang -c %s -target armv7-apple-ios -fapple-kext -miphoneos-version-min=6.0.0 -### 2>&1 \
+// RUN: %clang -c %s -target armv7-apple-ios6 -fapple-kext -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-PIC2
-// RUN: %clang -c %s -target armv7-apple-ios -mkernel -miphoneos-version-min=6.0.0 -### 2>&1 \
+// RUN: %clang -c %s -target armv7-apple-ios6 -mkernel -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-PIC2
-// RUN: %clang -c %s -target arm64-apple-ios -mkernel -miphoneos-version-min=7.0.0 -### 2>&1 \
+// RUN: %clang -c %s -target arm64-apple-ios7 -mkernel -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-PIC2
-// RUN: %clang -x assembler -c %s -target arm64-apple-ios -mkernel -miphoneos-version-min=7.0.0 -no-integrated-as -### 2>&1 \
+// RUN: %clang -x assembler -c %s -target arm64-apple-ios7 -mkernel -no-integrated-as -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-NO-STATIC
-// RUN: %clang -c %s -target armv7k-apple-watchos -fapple-kext -mwatchos-version-min=1.0.0 -### 2>&1 \
+// RUN: %clang -c %s -target armv7k-apple-watchos1 -fapple-kext -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-PIC2
-// RUN: %clang -c %s -target armv7-apple-ios -fapple-kext -miphoneos-version-min=5.0.0 -### 2>&1 \
+// RUN: %clang -c %s -target armv7-apple-ios5 -fapple-kext -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-NO-PIC
-// RUN: %clang -c %s -target armv7-apple-ios -fapple-kext -miphoneos-version-min=6.0.0 -static -### 2>&1 \
+// RUN: %clang -c %s -target armv7-apple-ios6 -fapple-kext -static -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-NO-PIC
// RUN: %clang -c %s -target armv7-apple-unknown-macho -static -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-NO-PIC
diff --git a/test/Driver/unavailable_aligned_allocation.cpp b/test/Driver/unavailable_aligned_allocation.cpp
index cd75c08165d7..d5820b0665c1 100644
--- a/test/Driver/unavailable_aligned_allocation.cpp
+++ b/test/Driver/unavailable_aligned_allocation.cpp
@@ -10,15 +10,15 @@
// RUN: %clang -target thumbv7-apple-watchos3 -c -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=UNAVAILABLE
//
-// RUN: %clang -target x86_64-apple-macosx10.13 -mios-simulator-version-min=10 \
+// RUN: %clang -target x86_64-apple-darwin -mios-simulator-version-min=10 \
// RUN: -c -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=UNAVAILABLE
//
-// RUN: %clang -target x86_64-apple-macosx10.13 -mtvos-simulator-version-min=10 \
+// RUN: %clang -target x86_64-apple-darwin -mtvos-simulator-version-min=10 \
// RUN: -c -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=UNAVAILABLE
//
-// RUN: %clang -target x86_64-apple-macosx10.13 -mwatchos-simulator-version-min=3 \
+// RUN: %clang -target x86_64-apple-darwin -mwatchos-simulator-version-min=3 \
// RUN: -c -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=UNAVAILABLE
//
@@ -39,15 +39,15 @@
// RUN: %clang -target x86_64-unknown-linux-gnu -c -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AVAILABLE
//
-// RUN: %clang -target x86_64-apple-macosx10.12 -mios-simulator-version-min=11 \
+// RUN: %clang -target x86_64-apple-darwin -mios-simulator-version-min=11 \
// RUN: -c -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AVAILABLE
//
-// RUN: %clang -target x86_64-apple-macosx10.12 -mtvos-simulator-version-min=11 \
+// RUN: %clang -target x86_64-apple-darwin -mtvos-simulator-version-min=11 \
// RUN: -c -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AVAILABLE
//
-// RUN: %clang -target x86_64-apple-macosx10.12 -mwatchos-simulator-version-min=4 \
+// RUN: %clang -target x86_64-apple-darwin -mwatchos-simulator-version-min=4 \
// RUN: -c -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AVAILABLE
//
diff --git a/test/Frontend/float16.cpp b/test/Frontend/float16.cpp
index febd6b8e36a0..fa00eae75360 100644
--- a/test/Frontend/float16.cpp
+++ b/test/Frontend/float16.cpp
@@ -132,7 +132,7 @@ public:
//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '+'
//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue ->f1c 0x{{.*}}
-//CHECK-NEXT: | | | `-CXXThisExpr {{.*}} 'class C1 *' this
+//CHECK-NEXT: | | | `-CXXThisExpr {{.*}} 'C1 *' this
//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func2c '_Float16 (_Float16)' static
@@ -208,14 +208,14 @@ int main(void) {
//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000977e+00
C1 c1(f1l);
-//CHECK: | `-VarDecl{{.*}} used c1 'class C1' callinit
-//CHECK-NEXT: | `-CXXConstructExpr {{.*}} 'class C1' 'void (_Float16)
+//CHECK: | `-VarDecl{{.*}} used c1 'C1' callinit
+//CHECK-NEXT: | `-CXXConstructExpr {{.*}} 'C1' 'void (_Float16)
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var 0x{{.*}} 'f1l' '_Float16'
S1<_Float16> s1 = { 132.f16 };
-//CHECK: | `-VarDecl {{.*}} used s1 'S1<_Float16>':'struct S1<_Float16>' cinit
-//CHECK-NEXT: | `-InitListExpr {{.*}} 'S1<_Float16>':'struct S1<_Float16>'
+//CHECK: | `-VarDecl {{.*}} used s1 'S1<_Float16>':'S1<_Float16>' cinit
+//CHECK-NEXT: | `-InitListExpr {{.*}} 'S1<_Float16>':'S1<_Float16>'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.320000e+02
_Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) +
@@ -240,13 +240,13 @@ int main(void) {
//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16'
//CHECK-NEXT: | | | | | | `-CXXMemberCallExpr {{.*}} '_Float16'
//CHECK-NEXT: | | | | | | |-MemberExpr {{.*}} '<bound member function type>' .func1c {{.*}}
-//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} 'class C1' lvalue Var {{.*}} 'c1' 'class C1'
+//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} 'C1' lvalue Var {{.*}} 'c1' 'C1'
//CHECK-NEXT: | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16'
//CHECK-NEXT: | | | | | `-CallExpr {{.*}} '_Float16'
//CHECK-NEXT: | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
//CHECK-NEXT: | | | | | | `-MemberExpr {{.*}} '_Float16 (_Float16)' lvalue .func2c {{.*}}
-//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} 'class C1' lvalue Var {{.*}} 'c1' 'class C1'
+//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} 'C1' lvalue Var {{.*}} 'c1' 'C1'
//CHECK-NEXT: | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
//CHECK-NEXT: | | | | `-CallExpr {{.*}} '_Float16':'_Float16'
@@ -256,7 +256,7 @@ int main(void) {
//CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue .mem2 {{.*}}
-//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'S1<_Float16>':'struct S1<_Float16>' lvalue Var {{.*}} 's1' 'S1<_Float16>':'struct S1<_Float16>'
+//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'S1<_Float16>':'S1<_Float16>' lvalue Var {{.*}} 's1' 'S1<_Float16>':'S1<_Float16>'
//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1n' '_Float16'
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
diff --git a/test/Index/skipped-bodies-templates.cpp b/test/Index/skipped-bodies-templates.cpp
new file mode 100644
index 000000000000..d8fbc28ebc2f
--- /dev/null
+++ b/test/Index/skipped-bodies-templates.cpp
@@ -0,0 +1,27 @@
+// RUN: env CINDEXTEST_SKIP_FUNCTION_BODIES=1 c-index-test -test-load-source all %s 2>&1 \
+// RUN: | FileCheck %s
+
+
+template <class T>
+struct Foo {
+ inline int with_body() {
+ return 100;
+ }
+
+ inline int without_body();
+};
+
+
+int bar = Foo<int>().with_body() + Foo<int>().without_body();
+// CHECK-NOT: warning: inline function 'Foo<int>::with_body' is not defined
+// CHECK: warning: inline function 'Foo<int>::without_body' is not defined
+
+template <class T>
+inline int with_body() { return 10; }
+
+template <class T>
+inline int without_body();
+
+int baz = with_body<int>() + without_body<int>();
+// CHECK-NOT: warning: inline function 'with_body<int>' is not defined
+// CHECK: warning: inline function 'without_body<int>' is not defined
diff --git a/test/Misc/ast-dump-attr.cpp b/test/Misc/ast-dump-attr.cpp
index bf942959a85c..9e6f257a920e 100644
--- a/test/Misc/ast-dump-attr.cpp
+++ b/test/Misc/ast-dump-attr.cpp
@@ -1,211 +1,211 @@
-// RUN: %clang_cc1 -triple x86_64-pc-linux -std=c++11 -Wno-deprecated-declarations -ast-dump -ast-dump-filter Test %s | FileCheck --strict-whitespace %s
-
-int TestLocation
-__attribute__((unused));
-// CHECK: VarDecl{{.*}}TestLocation
-// CHECK-NEXT: UnusedAttr 0x{{[^ ]*}} <line:[[@LINE-2]]:16>
-
-int TestIndent
-__attribute__((unused));
-// CHECK: {{^}}VarDecl{{.*TestIndent[^()]*$}}
-// CHECK-NEXT: {{^}}`-UnusedAttr{{[^()]*$}}
-
-void TestAttributedStmt() {
- switch (1) {
- case 1:
- [[clang::fallthrough]];
- case 2:
- ;
- }
-}
-// CHECK: FunctionDecl{{.*}}TestAttributedStmt
-// CHECK: AttributedStmt
-// CHECK-NEXT: FallThroughAttr
-// CHECK-NEXT: NullStmt
-
-[[clang::warn_unused_result]] int TestCXX11DeclAttr();
-// CHECK: FunctionDecl{{.*}}TestCXX11DeclAttr
-// CHECK-NEXT: WarnUnusedResultAttr
-
-int TestAlignedNull __attribute__((aligned));
-// CHECK: VarDecl{{.*}}TestAlignedNull
-// CHECK-NEXT: AlignedAttr {{.*}} aligned
-// CHECK-NEXT: <<<NULL>>>
-
-int TestAlignedExpr __attribute__((aligned(4)));
-// CHECK: VarDecl{{.*}}TestAlignedExpr
-// CHECK-NEXT: AlignedAttr {{.*}} aligned
-// CHECK-NEXT: IntegerLiteral
-
-int TestEnum __attribute__((visibility("default")));
-// CHECK: VarDecl{{.*}}TestEnum
-// CHECK-NEXT: VisibilityAttr{{.*}} Default
-
-class __attribute__((lockable)) Mutex {
-} mu1, mu2;
-int TestExpr __attribute__((guarded_by(mu1)));
-// CHECK: VarDecl{{.*}}TestExpr
-// CHECK-NEXT: GuardedByAttr
-// CHECK-NEXT: DeclRefExpr{{.*}}mu1
-
-class Mutex TestVariadicExpr __attribute__((acquired_after(mu1, mu2)));
-// CHECK: VarDecl{{.*}}TestVariadicExpr
-// CHECK: AcquiredAfterAttr
-// CHECK-NEXT: DeclRefExpr{{.*}}mu1
-// CHECK-NEXT: DeclRefExpr{{.*}}mu2
-
-void function1(void *) {
- int TestFunction __attribute__((cleanup(function1)));
-}
-// CHECK: VarDecl{{.*}}TestFunction
-// CHECK-NEXT: CleanupAttr{{.*}} Function{{.*}}function1
-
-void TestIdentifier(void *, int)
-__attribute__((pointer_with_type_tag(ident1,1,2)));
-// CHECK: FunctionDecl{{.*}}TestIdentifier
-// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag ident1
-
-void TestBool(void *, int)
-__attribute__((pointer_with_type_tag(bool1,1,2)));
-// CHECK: FunctionDecl{{.*}}TestBool
-// CHECK: ArgumentWithTypeTagAttr{{.*}}pointer_with_type_tag bool1 0 1 IsPointer
-
-void TestUnsigned(void *, int)
-__attribute__((pointer_with_type_tag(unsigned1,1,2)));
-// CHECK: FunctionDecl{{.*}}TestUnsigned
-// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag unsigned1 0 1
-
-void TestInt(void) __attribute__((constructor(123)));
-// CHECK: FunctionDecl{{.*}}TestInt
-// CHECK-NEXT: ConstructorAttr{{.*}} 123
-
-static int TestString __attribute__((alias("alias1")));
-// CHECK: VarDecl{{.*}}TestString
-// CHECK-NEXT: AliasAttr{{.*}} "alias1"
-
-extern struct s1 TestType
-__attribute__((type_tag_for_datatype(ident1,int)));
-// CHECK: VarDecl{{.*}}TestType
-// CHECK-NEXT: TypeTagForDatatypeAttr{{.*}} int
-
-void TestLabel() {
-L: __attribute__((unused)) int i;
-// CHECK: LabelStmt{{.*}}'L'
-// CHECK: VarDecl{{.*}}i 'int'
-// CHECK-NEXT: UnusedAttr{{.*}}
-
-M: __attribute(()) int j;
-// CHECK: LabelStmt {{.*}} 'M'
-// CHECK-NEXT: DeclStmt
-// CHECK-NEXT: VarDecl {{.*}} j 'int'
-
-N: __attribute(()) ;
-// CHECK: LabelStmt {{.*}} 'N'
-// CHECK-NEXT: NullStmt
-}
-
-namespace Test {
-extern "C" int printf(const char *format, ...);
-// CHECK: FunctionDecl{{.*}}printf
-// CHECK-NEXT: ParmVarDecl{{.*}}format{{.*}}'const char *'
-// CHECK-NEXT: FormatAttr{{.*}}Implicit printf 1 2
-
-alignas(8) extern int x;
-extern int x;
-// CHECK: VarDecl{{.*}} x 'int'
-// CHECK: VarDecl{{.*}} x 'int'
-// CHECK-NEXT: AlignedAttr{{.*}} Inherited
-}
-
-int __attribute__((cdecl)) TestOne(void), TestTwo(void);
-// CHECK: FunctionDecl{{.*}}TestOne{{.*}}__attribute__((cdecl))
-// CHECK: FunctionDecl{{.*}}TestTwo{{.*}}__attribute__((cdecl))
-
-void func() {
- auto Test = []() __attribute__((no_thread_safety_analysis)) {};
- // CHECK: CXXMethodDecl{{.*}}operator() 'void (void) const'
- // CHECK: NoThreadSafetyAnalysisAttr
-
- // Because GNU's noreturn applies to the function type, and this lambda does
- // not have a capture list, the call operator and the function pointer
- // conversion should both be noreturn, but the method should not contain a
- // NoReturnAttr because the attribute applied to the type.
- auto Test2 = []() __attribute__((noreturn)) { while(1); };
- // CHECK: CXXMethodDecl{{.*}}operator() 'void (void) __attribute__((noreturn)) const'
- // CHECK-NOT: NoReturnAttr
- // CHECK: CXXConversionDecl{{.*}}operator void (*)() __attribute__((noreturn))
-}
-
-namespace PR20930 {
-struct S {
- struct { int Test __attribute__((deprecated)); };
- // CHECK: FieldDecl{{.*}}Test 'int'
- // CHECK-NEXT: DeprecatedAttr
-};
-
-void f() {
- S s;
- s.Test = 1;
- // CHECK: IndirectFieldDecl{{.*}}Test 'int'
- // CHECK: DeprecatedAttr
-}
-}
-
-struct __attribute__((objc_bridge_related(NSParagraphStyle,,))) TestBridgedRef;
-// CHECK: CXXRecordDecl{{.*}} struct TestBridgedRef
-// CHECK-NEXT: ObjCBridgeRelatedAttr{{.*}} NSParagraphStyle
-
-void TestExternalSourceSymbolAttr1()
-__attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration)));
-// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr1
-// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration
-
-void TestExternalSourceSymbolAttr2()
-__attribute__((external_source_symbol(defined_in="module", language="Swift")));
-// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr2
-// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module"{{$}}
-
-void TestExternalSourceSymbolAttr3()
-__attribute__((external_source_symbol(generated_declaration, language="Objective-C++", defined_in="module")));
-// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr3
-// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Objective-C++" "module" GeneratedDeclaration
-
-void TestExternalSourceSymbolAttr4()
-__attribute__((external_source_symbol(defined_in="Some external file.cs", generated_declaration, language="C Sharp")));
-// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr4
-// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "C Sharp" "Some external file.cs" GeneratedDeclaration
-
-void TestExternalSourceSymbolAttr5()
-__attribute__((external_source_symbol(generated_declaration, defined_in="module", language="Swift")));
-// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr5
-// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration
-
-namespace TestNoEscape {
- void noescapeFunc(int *p0, __attribute__((noescape)) int *p1) {}
- // CHECK: `-FunctionDecl{{.*}} noescapeFunc 'void (int *, __attribute__((noescape)) int *)'
- // CHECK-NEXT: ParmVarDecl
- // CHECK-NEXT: ParmVarDecl
- // CHECK-NEXT: NoEscapeAttr
-}
-
-namespace TestSuppress {
- [[gsl::suppress("at-namespace")]];
- // CHECK: NamespaceDecl{{.*}} TestSuppress
- // CHECK-NEXT: EmptyDecl{{.*}}
- // CHECK-NEXT: SuppressAttr{{.*}} at-namespace
- [[gsl::suppress("on-decl")]]
- void TestSuppressFunction();
- // CHECK: FunctionDecl{{.*}} TestSuppressFunction
- // CHECK-NEXT SuppressAttr{{.*}} on-decl
-
- void f() {
- int *i;
-
- [[gsl::suppress("on-stmt")]] {
- // CHECK: AttributedStmt
- // CHECK-NEXT: SuppressAttr{{.*}} on-stmt
- // CHECK-NEXT: CompoundStmt
- i = reinterpret_cast<int*>(7);
- }
- }
-}
+// RUN: %clang_cc1 -triple x86_64-pc-linux -std=c++11 -Wno-deprecated-declarations -ast-dump -ast-dump-filter Test %s | FileCheck --strict-whitespace %s
+
+int TestLocation
+__attribute__((unused));
+// CHECK: VarDecl{{.*}}TestLocation
+// CHECK-NEXT: UnusedAttr 0x{{[^ ]*}} <line:[[@LINE-2]]:16>
+
+int TestIndent
+__attribute__((unused));
+// CHECK: {{^}}VarDecl{{.*TestIndent[^()]*$}}
+// CHECK-NEXT: {{^}}`-UnusedAttr{{[^()]*$}}
+
+void TestAttributedStmt() {
+ switch (1) {
+ case 1:
+ [[clang::fallthrough]];
+ case 2:
+ ;
+ }
+}
+// CHECK: FunctionDecl{{.*}}TestAttributedStmt
+// CHECK: AttributedStmt
+// CHECK-NEXT: FallThroughAttr
+// CHECK-NEXT: NullStmt
+
+[[clang::warn_unused_result]] int TestCXX11DeclAttr();
+// CHECK: FunctionDecl{{.*}}TestCXX11DeclAttr
+// CHECK-NEXT: WarnUnusedResultAttr
+
+int TestAlignedNull __attribute__((aligned));
+// CHECK: VarDecl{{.*}}TestAlignedNull
+// CHECK-NEXT: AlignedAttr {{.*}} aligned
+// CHECK-NEXT: <<<NULL>>>
+
+int TestAlignedExpr __attribute__((aligned(4)));
+// CHECK: VarDecl{{.*}}TestAlignedExpr
+// CHECK-NEXT: AlignedAttr {{.*}} aligned
+// CHECK-NEXT: IntegerLiteral
+
+int TestEnum __attribute__((visibility("default")));
+// CHECK: VarDecl{{.*}}TestEnum
+// CHECK-NEXT: VisibilityAttr{{.*}} Default
+
+class __attribute__((lockable)) Mutex {
+} mu1, mu2;
+int TestExpr __attribute__((guarded_by(mu1)));
+// CHECK: VarDecl{{.*}}TestExpr
+// CHECK-NEXT: GuardedByAttr
+// CHECK-NEXT: DeclRefExpr{{.*}}mu1
+
+class Mutex TestVariadicExpr __attribute__((acquired_after(mu1, mu2)));
+// CHECK: VarDecl{{.*}}TestVariadicExpr
+// CHECK: AcquiredAfterAttr
+// CHECK-NEXT: DeclRefExpr{{.*}}mu1
+// CHECK-NEXT: DeclRefExpr{{.*}}mu2
+
+void function1(void *) {
+ int TestFunction __attribute__((cleanup(function1)));
+}
+// CHECK: VarDecl{{.*}}TestFunction
+// CHECK-NEXT: CleanupAttr{{.*}} Function{{.*}}function1
+
+void TestIdentifier(void *, int)
+__attribute__((pointer_with_type_tag(ident1,1,2)));
+// CHECK: FunctionDecl{{.*}}TestIdentifier
+// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag ident1
+
+void TestBool(void *, int)
+__attribute__((pointer_with_type_tag(bool1,1,2)));
+// CHECK: FunctionDecl{{.*}}TestBool
+// CHECK: ArgumentWithTypeTagAttr{{.*}}pointer_with_type_tag bool1 0 1 IsPointer
+
+void TestUnsigned(void *, int)
+__attribute__((pointer_with_type_tag(unsigned1,1,2)));
+// CHECK: FunctionDecl{{.*}}TestUnsigned
+// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag unsigned1 0 1
+
+void TestInt(void) __attribute__((constructor(123)));
+// CHECK: FunctionDecl{{.*}}TestInt
+// CHECK-NEXT: ConstructorAttr{{.*}} 123
+
+static int TestString __attribute__((alias("alias1")));
+// CHECK: VarDecl{{.*}}TestString
+// CHECK-NEXT: AliasAttr{{.*}} "alias1"
+
+extern struct s1 TestType
+__attribute__((type_tag_for_datatype(ident1,int)));
+// CHECK: VarDecl{{.*}}TestType
+// CHECK-NEXT: TypeTagForDatatypeAttr{{.*}} int
+
+void TestLabel() {
+L: __attribute__((unused)) int i;
+// CHECK: LabelStmt{{.*}}'L'
+// CHECK: VarDecl{{.*}}i 'int'
+// CHECK-NEXT: UnusedAttr{{.*}}
+
+M: __attribute(()) int j;
+// CHECK: LabelStmt {{.*}} 'M'
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl {{.*}} j 'int'
+
+N: __attribute(()) ;
+// CHECK: LabelStmt {{.*}} 'N'
+// CHECK-NEXT: NullStmt
+}
+
+namespace Test {
+extern "C" int printf(const char *format, ...);
+// CHECK: FunctionDecl{{.*}}printf
+// CHECK-NEXT: ParmVarDecl{{.*}}format{{.*}}'const char *'
+// CHECK-NEXT: FormatAttr{{.*}}Implicit printf 1 2
+
+alignas(8) extern int x;
+extern int x;
+// CHECK: VarDecl{{.*}} x 'int'
+// CHECK: VarDecl{{.*}} x 'int'
+// CHECK-NEXT: AlignedAttr{{.*}} Inherited
+}
+
+int __attribute__((cdecl)) TestOne(void), TestTwo(void);
+// CHECK: FunctionDecl{{.*}}TestOne{{.*}}__attribute__((cdecl))
+// CHECK: FunctionDecl{{.*}}TestTwo{{.*}}__attribute__((cdecl))
+
+void func() {
+ auto Test = []() __attribute__((no_thread_safety_analysis)) {};
+ // CHECK: CXXMethodDecl{{.*}}operator() 'void () const'
+ // CHECK: NoThreadSafetyAnalysisAttr
+
+ // Because GNU's noreturn applies to the function type, and this lambda does
+ // not have a capture list, the call operator and the function pointer
+ // conversion should both be noreturn, but the method should not contain a
+ // NoReturnAttr because the attribute applied to the type.
+ auto Test2 = []() __attribute__((noreturn)) { while(1); };
+ // CHECK: CXXMethodDecl{{.*}}operator() 'void () __attribute__((noreturn)) const'
+ // CHECK-NOT: NoReturnAttr
+ // CHECK: CXXConversionDecl{{.*}}operator void (*)() __attribute__((noreturn))
+}
+
+namespace PR20930 {
+struct S {
+ struct { int Test __attribute__((deprecated)); };
+ // CHECK: FieldDecl{{.*}}Test 'int'
+ // CHECK-NEXT: DeprecatedAttr
+};
+
+void f() {
+ S s;
+ s.Test = 1;
+ // CHECK: IndirectFieldDecl{{.*}}Test 'int'
+ // CHECK: DeprecatedAttr
+}
+}
+
+struct __attribute__((objc_bridge_related(NSParagraphStyle,,))) TestBridgedRef;
+// CHECK: CXXRecordDecl{{.*}} struct TestBridgedRef
+// CHECK-NEXT: ObjCBridgeRelatedAttr{{.*}} NSParagraphStyle
+
+void TestExternalSourceSymbolAttr1()
+__attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration)));
+// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr1
+// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration
+
+void TestExternalSourceSymbolAttr2()
+__attribute__((external_source_symbol(defined_in="module", language="Swift")));
+// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr2
+// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module"{{$}}
+
+void TestExternalSourceSymbolAttr3()
+__attribute__((external_source_symbol(generated_declaration, language="Objective-C++", defined_in="module")));
+// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr3
+// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Objective-C++" "module" GeneratedDeclaration
+
+void TestExternalSourceSymbolAttr4()
+__attribute__((external_source_symbol(defined_in="Some external file.cs", generated_declaration, language="C Sharp")));
+// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr4
+// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "C Sharp" "Some external file.cs" GeneratedDeclaration
+
+void TestExternalSourceSymbolAttr5()
+__attribute__((external_source_symbol(generated_declaration, defined_in="module", language="Swift")));
+// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr5
+// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration
+
+namespace TestNoEscape {
+ void noescapeFunc(int *p0, __attribute__((noescape)) int *p1) {}
+ // CHECK: `-FunctionDecl{{.*}} noescapeFunc 'void (int *, __attribute__((noescape)) int *)'
+ // CHECK-NEXT: ParmVarDecl
+ // CHECK-NEXT: ParmVarDecl
+ // CHECK-NEXT: NoEscapeAttr
+}
+
+namespace TestSuppress {
+ [[gsl::suppress("at-namespace")]];
+ // CHECK: NamespaceDecl{{.*}} TestSuppress
+ // CHECK-NEXT: EmptyDecl{{.*}}
+ // CHECK-NEXT: SuppressAttr{{.*}} at-namespace
+ [[gsl::suppress("on-decl")]]
+ void TestSuppressFunction();
+ // CHECK: FunctionDecl{{.*}} TestSuppressFunction
+ // CHECK-NEXT SuppressAttr{{.*}} on-decl
+
+ void f() {
+ int *i;
+
+ [[gsl::suppress("on-stmt")]] {
+ // CHECK: AttributedStmt
+ // CHECK-NEXT: SuppressAttr{{.*}} on-stmt
+ // CHECK-NEXT: CompoundStmt
+ i = reinterpret_cast<int*>(7);
+ }
+ }
+}
diff --git a/test/Misc/ast-dump-color.cpp b/test/Misc/ast-dump-color.cpp
index bc01d4932f77..ad7ea3023a86 100644
--- a/test/Misc/ast-dump-color.cpp
+++ b/test/Misc/ast-dump-color.cpp
@@ -32,7 +32,7 @@ struct Invalid {
//CHECK: {{^}}[[GREEN:.\[0;1;32m]]TranslationUnitDecl[[RESET:.\[0m]][[Yellow:.\[0;33m]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]<invalid sloc>[[RESET]]> [[Yellow]]<invalid sloc>[[RESET]]{{$}}
//CHECK: {{^}}[[Blue:.\[0;34m]]|-[[RESET]][[GREEN]]TypedefDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]<invalid sloc>[[RESET]]> [[Yellow]]<invalid sloc>[[RESET]] implicit[[CYAN:.\[0;1;36m]] __int128_t[[RESET]] [[Green:.\[0;32m]]'__int128'[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]TypedefDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]<invalid sloc>[[RESET]]> [[Yellow]]<invalid sloc>[[RESET]] implicit[[CYAN]] __uint128_t[[RESET]] [[Green]]'unsigned __int128'[[RESET]]{{$}}
-//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]TypedefDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]<invalid sloc>[[RESET]]> [[Yellow]]<invalid sloc>[[RESET]] implicit[[CYAN]] __builtin_va_list[[RESET]] [[Green]]'struct __va_list_tag [1]'[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]TypedefDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]<invalid sloc>[[RESET]]> [[Yellow]]<invalid sloc>[[RESET]] implicit[[CYAN]] __builtin_va_list[[RESET]] [[Green]]'__va_list_tag [1]'[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]{{.*}}ast-dump-color.cpp:6:1[[RESET]], [[Yellow]]col:5[[RESET]]> [[Yellow]]col:5[[RESET]][[CYAN]] Test[[RESET]] [[Green]]'int'[[RESET]]
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[BLUE:.\[0;1;34m]]UnusedAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:25[[RESET]]> unused{{$}}
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[Blue]]FullComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:4:4[[RESET]], [[Yellow]]line:5:8[[RESET]]>{{$}}
@@ -43,7 +43,7 @@ struct Invalid {
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[Blue]]HTMLEndTagComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:13[[RESET]], [[Yellow]]col:16[[RESET]]> Name="a"{{$}}
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[Blue]]TextComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:5:4[[RESET]]> Text=" "{{$}}
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[Blue]]HTMLStartTagComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:5[[RESET]], [[Yellow]]col:8[[RESET]]> Name="br" SelfClosing{{$}}
-//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]FunctionDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:9:1[[RESET]], [[Yellow]]line:16:1[[RESET]]> [[Yellow]]line:9:6[[RESET]][[CYAN]] TestAttributedStmt[[RESET]] [[Green]]'void (void)'[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]FunctionDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:9:1[[RESET]], [[Yellow]]line:16:1[[RESET]]> [[Yellow]]line:9:6[[RESET]][[CYAN]] TestAttributedStmt[[RESET]] [[Green]]'void ()'[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[MAGENTA:.\[0;1;35m]]CompoundStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:27[[RESET]], [[Yellow]]line:16:1[[RESET]]>{{$}}
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[MAGENTA]]SwitchStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:10:3[[RESET]], [[Yellow]]line:15:3[[RESET]]>{{$}}
//CHECK: {{^}}[[Blue]]| | |-[[RESET]][[Blue:.\[0;34m]]<<<NULL>>>[[RESET]]{{$}}
@@ -75,29 +75,29 @@ struct Invalid {
//CHECK: {{^}}[[Blue]]| | | `-[[RESET]][[Blue]]TextComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:6[[RESET]], [[Yellow]]col:22[[RESET]]> Text=" Another variable"{{$}}
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[Blue]]ParagraphComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:23:6[[RESET]], [[Yellow]]col:44[[RESET]]>{{$}}
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[Blue]]TextComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:6[[RESET]], [[Yellow]]col:44[[RESET]]> Text=" Like the other variable, but different"{{$}}
-//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:18:33[[RESET]]> [[Yellow]]col:33[[RESET]] implicit used[[CYAN]] Mutex[[RESET]] [[Green]]'void (void) noexcept'[[RESET]] inline{{.*$}}
+//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:18:33[[RESET]]> [[Yellow]]col:33[[RESET]] implicit used[[CYAN]] Mutex[[RESET]] [[Green]]'void () noexcept'[[RESET]] inline{{.*$}}
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[MAGENTA]]CompoundStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]>{{$}}
-//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] implicit constexpr[[CYAN]] Mutex[[RESET]] [[Green]]'void (const class Mutex &)'[[RESET]] inline{{ .*$}}
-//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] [[Green]]'const class Mutex &'[[RESET]]{{$}}
-//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] implicit constexpr[[CYAN]] Mutex[[RESET]] [[Green]]'void (class Mutex &&)'[[RESET]] inline{{ .*$}}
-//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] [[Green]]'class Mutex &&'[[RESET]]{{$}}
-//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:25:3[[RESET]]> [[Yellow]]col:3[[RESET]] referenced[[CYAN]] mu1[[RESET]] [[Green]]'class Mutex':'class Mutex'[[RESET]]
-//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:3[[RESET]]> [[Green]]'class Mutex':'class Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void (void) noexcept'[[RESET]]{{$}}
-//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:18:1[[RESET]], [[Yellow]]line:25:8[[RESET]]> [[Yellow]]col:8[[RESET]][[CYAN]] mu2[[RESET]] [[Green]]'class Mutex':'class Mutex'[[RESET]]
-//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'class Mutex':'class Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void (void) noexcept'[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] implicit constexpr[[CYAN]] Mutex[[RESET]] [[Green]]'void (const Mutex &)'[[RESET]] inline{{ .*$}}
+//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] [[Green]]'const Mutex &'[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] implicit constexpr[[CYAN]] Mutex[[RESET]] [[Green]]'void (Mutex &&)'[[RESET]] inline{{ .*$}}
+//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] [[Green]]'Mutex &&'[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:25:3[[RESET]]> [[Yellow]]col:3[[RESET]] referenced[[CYAN]] mu1[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]]
+//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:3[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:18:1[[RESET]], [[Yellow]]line:25:8[[RESET]]> [[Yellow]]col:8[[RESET]][[CYAN]] mu2[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]]
+//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:26:1[[RESET]], [[Yellow]]col:5[[RESET]]> [[Yellow]]col:5[[RESET]][[CYAN]] TestExpr[[RESET]] [[Green]]'int'[[RESET]]
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[BLUE]]GuardedByAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:29[[RESET]], [[Yellow]]col:43[[RESET]]>{{$}}
-//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]DeclRefExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:40[[RESET]]> [[Green]]'class Mutex':'class Mutex'[[RESET]][[Cyan]] lvalue[[RESET]][[Cyan]][[RESET]] [[GREEN]]Var[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]][[CYAN]] 'mu1'[[RESET]] [[Green]]'class Mutex':'class Mutex'[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]DeclRefExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:40[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]] lvalue[[RESET]][[Cyan]][[RESET]] [[GREEN]]Var[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]][[CYAN]] 'mu1'[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]CXXRecordDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:28:1[[RESET]], [[Yellow]]line:30:1[[RESET]]> [[Yellow]]line:28:8[[RESET]] struct[[CYAN]] Invalid[[RESET]] definition
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXRecordDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit referenced struct[[CYAN]] Invalid[[RESET]]
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:29:3[[RESET]], [[Yellow]]col:42[[RESET]]> [[Yellow]]col:29[[RESET]] invalid[[CYAN]] Invalid[[RESET]] [[Green]]'void (int)'[[RESET]]
//CHECK: {{^}}[[Blue]]| | |-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:37[[RESET]], [[Yellow]]<invalid sloc>[[RESET]]> [[Yellow]]col:42[[RESET]] invalid [[Green]]'int'[[RESET]]
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[BLUE]]NoInlineAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:18[[RESET]]>
-//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:28:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit used constexpr[[CYAN]] Invalid[[RESET]] [[Green]]'void (void) noexcept'[[RESET]] inline
+//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:28:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit used constexpr[[CYAN]] Invalid[[RESET]] [[Green]]'void () noexcept'[[RESET]] inline
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[MAGENTA]]CompoundStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]>
-//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit constexpr[[CYAN]] Invalid[[RESET]] [[Green]]'void (const struct Invalid &)'[[RESET]] inline default trivial noexcept-unevaluated 0x{{[0-9a-fA-F]*}}
-//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] [[Green]]'const struct Invalid &'[[RESET]]
-//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit constexpr[[CYAN]] Invalid[[RESET]] [[Green]]'void (struct Invalid &&)'[[RESET]] inline default trivial noexcept-unevaluated 0x{{[0-9a-fA-F]*}}
-//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] [[Green]]'struct Invalid &&'[[RESET]]
-//CHECK: {{^}}[[Blue]]`-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:30:3[[RESET]]> [[Yellow]]col:3[[RESET]][[CYAN]] Invalid[[RESET]] [[Green]]'struct Invalid':'struct Invalid'[[RESET]]
-//CHECK: {{^}}[[Blue]] `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:3[[RESET]]> [[Green]]'struct Invalid':'struct Invalid'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void (void) noexcept'[[RESET]]
+//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit constexpr[[CYAN]] Invalid[[RESET]] [[Green]]'void (const Invalid &)'[[RESET]] inline default trivial noexcept-unevaluated 0x{{[0-9a-fA-F]*}}
+//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] [[Green]]'const Invalid &'[[RESET]]
+//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit constexpr[[CYAN]] Invalid[[RESET]] [[Green]]'void (Invalid &&)'[[RESET]] inline default trivial noexcept-unevaluated 0x{{[0-9a-fA-F]*}}
+//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] [[Green]]'Invalid &&'[[RESET]]
+//CHECK: {{^}}[[Blue]]`-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:30:3[[RESET]]> [[Yellow]]col:3[[RESET]][[CYAN]] Invalid[[RESET]] [[Green]]'struct Invalid':'Invalid'[[RESET]]
+//CHECK: {{^}}[[Blue]] `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:3[[RESET]]> [[Green]]'struct Invalid':'Invalid'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]]
diff --git a/test/Misc/ast-dump-decl.cpp b/test/Misc/ast-dump-decl.cpp
index 0df8a5a2b8fb..c689149af06b 100644
--- a/test/Misc/ast-dump-decl.cpp
+++ b/test/Misc/ast-dump-decl.cpp
@@ -1,539 +1,539 @@
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -strict-whitespace %s
-
-class testEnumDecl {
- enum class TestEnumDeclScoped;
- enum TestEnumDeclFixed : int;
-};
-// CHECK: EnumDecl{{.*}} class TestEnumDeclScoped 'int'
-// CHECK: EnumDecl{{.*}} TestEnumDeclFixed 'int'
-
-class testFieldDecl {
- int TestFieldDeclInit = 0;
-};
-// CHECK: FieldDecl{{.*}} TestFieldDeclInit 'int'
-// CHECK-NEXT: IntegerLiteral
-
-namespace testVarDeclNRVO {
- class A { };
- A foo() {
- A TestVarDeclNRVO;
- return TestVarDeclNRVO;
- }
-}
-// CHECK: VarDecl{{.*}} TestVarDeclNRVO 'class testVarDeclNRVO::A' nrvo
-
-void testParmVarDeclInit(int TestParmVarDeclInit = 0);
-// CHECK: ParmVarDecl{{.*}} TestParmVarDeclInit 'int'
-// CHECK-NEXT: IntegerLiteral{{.*}}
-
-namespace TestNamespaceDecl {
- int i;
-}
-// CHECK: NamespaceDecl{{.*}} TestNamespaceDecl
-// CHECK-NEXT: VarDecl
-
-namespace TestNamespaceDecl {
- int j;
-}
-// CHECK: NamespaceDecl{{.*}} TestNamespaceDecl
-// CHECK-NEXT: original Namespace
-// CHECK-NEXT: VarDecl
-
-inline namespace TestNamespaceDeclInline {
-}
-// CHECK: NamespaceDecl{{.*}} TestNamespaceDeclInline inline
-
-namespace testUsingDirectiveDecl {
- namespace A {
- }
-}
-namespace TestUsingDirectiveDecl {
- using namespace testUsingDirectiveDecl::A;
-}
-// CHECK: NamespaceDecl{{.*}} TestUsingDirectiveDecl
-// CHECK-NEXT: UsingDirectiveDecl{{.*}} Namespace{{.*}} 'A'
-
-namespace testNamespaceAlias {
- namespace A {
- }
-}
-namespace TestNamespaceAlias = testNamespaceAlias::A;
-// CHECK: NamespaceAliasDecl{{.*}} TestNamespaceAlias
-// CHECK-NEXT: Namespace{{.*}} 'A'
-
-using TestTypeAliasDecl = int;
-// CHECK: TypeAliasDecl{{.*}} TestTypeAliasDecl 'int'
-
-namespace testTypeAliasTemplateDecl {
- template<typename T> class A;
- template<typename T> using TestTypeAliasTemplateDecl = A<T>;
-}
-// CHECK: TypeAliasTemplateDecl{{.*}} TestTypeAliasTemplateDecl
-// CHECK-NEXT: TemplateTypeParmDecl
-// CHECK-NEXT: TypeAliasDecl{{.*}} TestTypeAliasTemplateDecl 'A<T>'
-
-namespace testCXXRecordDecl {
- class TestEmpty {};
-// CHECK: CXXRecordDecl{{.*}} class TestEmpty
-// CHECK-NEXT: DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
-// CHECK-NEXT: DefaultConstructor exists trivial constexpr
-// CHECK-NEXT: CopyConstructor simple trivial has_const_param
-// CHECK-NEXT: MoveConstructor exists simple trivial
-// CHECK-NEXT: CopyAssignment trivial has_const_param
-// CHECK-NEXT: MoveAssignment exists simple trivial
-// CHECK-NEXT: Destructor simple irrelevant trivial
-
- class A { };
- class B { };
- class TestCXXRecordDecl : virtual A, public B {
- int i;
- };
-}
-// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDecl
-// CHECK-NEXT: DefinitionData{{$}}
-// CHECK-NEXT: DefaultConstructor exists non_trivial
-// CHECK-NEXT: CopyConstructor simple non_trivial has_const_param
-// CHECK-NEXT: MoveConstructor exists simple non_trivial
-// CHECK-NEXT: CopyAssignment non_trivial has_const_param
-// CHECK-NEXT: MoveAssignment exists simple non_trivial
-// CHECK-NEXT: Destructor simple irrelevant trivial
-// CHECK-NEXT: virtual private 'class testCXXRecordDecl::A'
-// CHECK-NEXT: public 'class testCXXRecordDecl::B'
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDecl
-// CHECK-NEXT: FieldDecl
-
-template<class...T>
-class TestCXXRecordDeclPack : public T... {
-};
-// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDeclPack
-// CHECK: public 'T'...
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDeclPack
-
-thread_local int TestThreadLocalInt;
-// CHECK: TestThreadLocalInt {{.*}} tls_dynamic
-
-class testCXXMethodDecl {
- virtual void TestCXXMethodDeclPure() = 0;
- void TestCXXMethodDeclDelete() = delete;
- void TestCXXMethodDeclThrow() throw();
- void TestCXXMethodDeclThrowType() throw(int);
-};
-// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclPure 'void (void)' virtual pure
-// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclDelete 'void (void)' delete
-// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrow 'void (void) throw()'
-// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrowType 'void (void) throw(int)'
-
-namespace testCXXConstructorDecl {
- class A { };
- class TestCXXConstructorDecl : public A {
- int I;
- TestCXXConstructorDecl(A &a, int i) : A(a), I(i) { }
- TestCXXConstructorDecl(A &a) : TestCXXConstructorDecl(a, 0) { }
- };
-}
-// CHECK: CXXConstructorDecl{{.*}} TestCXXConstructorDecl 'void {{.*}}'
-// CHECK-NEXT: ParmVarDecl{{.*}} a
-// CHECK-NEXT: ParmVarDecl{{.*}} i
-// CHECK-NEXT: CXXCtorInitializer{{.*}}A
-// CHECK-NEXT: Expr
-// CHECK: CXXCtorInitializer{{.*}}I
-// CHECK-NEXT: Expr
-// CHECK: CompoundStmt
-// CHECK: CXXConstructorDecl{{.*}} TestCXXConstructorDecl 'void {{.*}}'
-// CHECK-NEXT: ParmVarDecl{{.*}} a
-// CHECK-NEXT: CXXCtorInitializer{{.*}}TestCXXConstructorDecl
-// CHECK-NEXT: CXXConstructExpr{{.*}}TestCXXConstructorDecl
-
-class TestCXXDestructorDecl {
- ~TestCXXDestructorDecl() { }
-};
-// CHECK: CXXDestructorDecl{{.*}} ~TestCXXDestructorDecl 'void (void) noexcept'
-// CHECK-NEXT: CompoundStmt
-
-// Test that the range of a defaulted members is computed correctly.
-class TestMemberRanges {
-public:
- TestMemberRanges() = default;
- TestMemberRanges(const TestMemberRanges &Other) = default;
- TestMemberRanges(TestMemberRanges &&Other) = default;
- ~TestMemberRanges() = default;
- TestMemberRanges &operator=(const TestMemberRanges &Other) = default;
- TestMemberRanges &operator=(TestMemberRanges &&Other) = default;
-};
-void SomeFunction() {
- TestMemberRanges A;
- TestMemberRanges B(A);
- B = A;
- A = static_cast<TestMemberRanges &&>(B);
- TestMemberRanges C(static_cast<TestMemberRanges &&>(A));
-}
-// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:30>
-// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:59>
-// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:54>
-// CHECK: CXXDestructorDecl{{.*}} <line:{{.*}}:3, col:31>
-// CHECK: CXXMethodDecl{{.*}} <line:{{.*}}:3, col:70>
-// CHECK: CXXMethodDecl{{.*}} <line:{{.*}}:3, col:65>
-
-class TestCXXConversionDecl {
- operator int() { return 0; }
-};
-// CHECK: CXXConversionDecl{{.*}} operator int 'int (void)'
-// CHECK-NEXT: CompoundStmt
-
-namespace TestStaticAssertDecl {
- static_assert(true, "msg");
-}
-// CHECK: NamespaceDecl{{.*}} TestStaticAssertDecl
-// CHECK-NEXT: StaticAssertDecl{{.*> .*$}}
-// CHECK-NEXT: CXXBoolLiteralExpr
-// CHECK-NEXT: StringLiteral
-
-namespace testFunctionTemplateDecl {
- class A { };
- class B { };
- class C { };
- class D { };
- template<typename T> void TestFunctionTemplate(T) { }
-
- // implicit instantiation
- void bar(A a) { TestFunctionTemplate(a); }
-
- // explicit specialization
- template<> void TestFunctionTemplate(B);
-
- // explicit instantiation declaration
- extern template void TestFunctionTemplate(C);
-
- // explicit instantiation definition
- template void TestFunctionTemplate(D);
-}
-// CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate
-// CHECK-NEXT: TemplateTypeParmDecl
-// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'
-// CHECK-NEXT: ParmVarDecl{{.*}} 'T'
-// CHECK-NEXT: CompoundStmt
-// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}A
-// CHECK-NEXT: TemplateArgument
-// CHECK-NEXT: ParmVarDecl
-// CHECK-NEXT: CompoundStmt
-// CHECK-NEXT: Function{{.*}} 'TestFunctionTemplate' {{.*}}B
-// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}C
-// CHECK-NEXT: TemplateArgument
-// CHECK-NEXT: ParmVarDecl
-// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}D
-// CHECK-NEXT: TemplateArgument
-// CHECK-NEXT: ParmVarDecl
-// CHECK-NEXT: CompoundStmt
-// CHECK: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}B
-// CHECK-NEXT: TemplateArgument
-// CHECK-NEXT: ParmVarDecl
-
-namespace testClassTemplateDecl {
- class A { };
- class B { };
- class C { };
- class D { };
-
- template<typename T> class TestClassTemplate {
- public:
- TestClassTemplate();
- ~TestClassTemplate();
- int j();
- int i;
- };
-
- // implicit instantiation
- TestClassTemplate<A> a;
-
- // explicit specialization
- template<> class TestClassTemplate<B> {
- int j;
- };
-
- // explicit instantiation declaration
- extern template class TestClassTemplate<C>;
-
- // explicit instantiation definition
- template class TestClassTemplate<D>;
-
- // partial explicit specialization
- template<typename T1, typename T2> class TestClassTemplatePartial {
- int i;
- };
- template<typename T1> class TestClassTemplatePartial<T1, A> {
- int j;
- };
-}
-// CHECK: ClassTemplateDecl{{.*}} TestClassTemplate
-// CHECK-NEXT: TemplateTypeParmDecl
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
-// CHECK: CXXRecordDecl{{.*}} class TestClassTemplate
-// CHECK-NEXT: AccessSpecDecl{{.*}} public
-// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
-// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
-// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
-// CHECK-NEXT: FieldDecl{{.*}} i
-// CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
-// CHECK: TemplateArgument{{.*}}A
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
-// CHECK-NEXT: AccessSpecDecl{{.*}} public
-// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
-// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
-// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
-// CHECK-NEXT: FieldDecl{{.*}} i
-// CHECK: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
-// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
-// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
-
-// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
-// CHECK-NEXT: DefinitionData
-// CHECK: TemplateArgument{{.*}}B
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
-// CHECK-NEXT: FieldDecl{{.*}} j
-
-// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
-// CHECK: TemplateArgument{{.*}}C
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
-// CHECK-NEXT: AccessSpecDecl{{.*}} public
-// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
-// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
-// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
-// CHECK-NEXT: FieldDecl{{.*}} i
-
-// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
-// CHECK: TemplateArgument{{.*}}D
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
-// CHECK-NEXT: AccessSpecDecl{{.*}} public
-// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
-// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
-// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
-// CHECK-NEXT: FieldDecl{{.*}} i
-
-// CHECK: ClassTemplatePartialSpecializationDecl{{.*}} class TestClassTemplatePartial
-// CHECK: TemplateArgument
-// CHECK-NEXT: TemplateArgument{{.*}}A
-// CHECK-NEXT: TemplateTypeParmDecl
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplatePartial
-// CHECK-NEXT: FieldDecl{{.*}} j
-
-// PR15220 dump instantiation only once
-namespace testCanonicalTemplate {
- class A {};
-
- template<typename T> void TestFunctionTemplate(T);
- template<typename T> void TestFunctionTemplate(T);
- void bar(A a) { TestFunctionTemplate(a); }
- // CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate
- // CHECK-NEXT: TemplateTypeParmDecl
- // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'
- // CHECK-NEXT: ParmVarDecl{{.*}} 'T'
- // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}A
- // CHECK-NEXT: TemplateArgument
- // CHECK-NEXT: ParmVarDecl
- // CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate
- // CHECK-NEXT: TemplateTypeParmDecl
- // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'
- // CHECK-NEXT: ParmVarDecl{{.*}} 'T'
- // CHECK-NEXT: Function{{.*}} 'TestFunctionTemplate'
- // CHECK-NOT: TemplateArgument
-
- template<typename T1> class TestClassTemplate {
- template<typename T2> friend class TestClassTemplate;
- };
- TestClassTemplate<A> a;
- // CHECK: ClassTemplateDecl{{.*}} TestClassTemplate
- // CHECK-NEXT: TemplateTypeParmDecl
- // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
- // CHECK: CXXRecordDecl{{.*}} class TestClassTemplate
- // CHECK-NEXT: FriendDecl
- // CHECK-NEXT: ClassTemplateDecl{{.*}} TestClassTemplate
- // CHECK-NEXT: TemplateTypeParmDecl
- // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
- // CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
- // CHECK: TemplateArgument{{.*}}A
- // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
-}
-
-template <class T>
-class TestClassScopeFunctionSpecialization {
- template<class U> void foo(U a) { }
- template<> void foo<int>(int a) { }
-};
-// CHECK: ClassScopeFunctionSpecializationDecl
-// CHECK-NEXT: CXXMethod{{.*}} 'foo' 'void (int)'
-// CHECK-NEXT: TemplateArgument{{.*}} 'int'
-
-namespace TestTemplateTypeParmDecl {
- template<typename ... T, class U = int> void foo();
-}
-// CHECK: NamespaceDecl{{.*}} TestTemplateTypeParmDecl
-// CHECK-NEXT: FunctionTemplateDecl
-// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename depth 0 index 0 ... T
-// CHECK-NEXT: TemplateTypeParmDecl{{.*}} class depth 0 index 1 U
-// CHECK-NEXT: TemplateArgument type 'int'
-
-namespace TestNonTypeTemplateParmDecl {
- template<int I = 1, int ... J> void foo();
-}
-// CHECK: NamespaceDecl{{.*}} TestNonTypeTemplateParmDecl
-// CHECK-NEXT: FunctionTemplateDecl
-// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 0 I
-// CHECK-NEXT: TemplateArgument expr
-// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
-// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 1 ... J
-
-namespace TestTemplateTemplateParmDecl {
- template<typename T> class A;
- template <template <typename> class T = A, template <typename> class ... U> void foo();
-}
-// CHECK: NamespaceDecl{{.*}} TestTemplateTemplateParmDecl
-// CHECK: FunctionTemplateDecl
-// CHECK-NEXT: TemplateTemplateParmDecl{{.*}} T
-// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename
-// CHECK-NEXT: TemplateArgument{{.*}} template A
-// CHECK-NEXT: TemplateTemplateParmDecl{{.*}} ... U
-// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename
-
-namespace TestTemplateArgument {
- template<typename> class A { };
- template<template<typename> class ...> class B { };
- int foo();
-
- template<typename> class testType { };
- template class testType<int>;
- // CHECK: ClassTemplateSpecializationDecl{{.*}} class testType
- // CHECK: TemplateArgument{{.*}} type 'int'
-
- template<int fp(void)> class testDecl { };
- template class testDecl<foo>;
- // CHECK: ClassTemplateSpecializationDecl{{.*}} class testDecl
- // CHECK: TemplateArgument{{.*}} decl
- // CHECK-NEXT: Function{{.*}}foo
-
- template class testDecl<nullptr>;
- // CHECK: ClassTemplateSpecializationDecl{{.*}} class testDecl
- // CHECK: TemplateArgument{{.*}} nullptr
-
- template<int> class testIntegral { };
- template class testIntegral<1>;
- // CHECK: ClassTemplateSpecializationDecl{{.*}} class testIntegral
- // CHECK: TemplateArgument{{.*}} integral 1
-
- template<template<typename> class> class testTemplate { };
- template class testTemplate<A>;
- // CHECK: ClassTemplateSpecializationDecl{{.*}} class testTemplate
- // CHECK: TemplateArgument{{.*}} A
-
- template<template<typename> class ...T> class C {
- B<T...> testTemplateExpansion;
- };
- // FIXME: Need TemplateSpecializationType dumping to test TemplateExpansion.
-
- template<int, int = 0> class testExpr;
- template<int I> class testExpr<I> { };
- // CHECK: ClassTemplatePartialSpecializationDecl{{.*}} class testExpr
- // CHECK: TemplateArgument{{.*}} expr
- // CHECK-NEXT: DeclRefExpr{{.*}}I
-
- template<int, int ...> class testPack { };
- template class testPack<0, 1, 2>;
- // CHECK: ClassTemplateSpecializationDecl{{.*}} class testPack
- // CHECK: TemplateArgument{{.*}} integral 0
- // CHECK-NEXT: TemplateArgument{{.*}} pack
- // CHECK-NEXT: TemplateArgument{{.*}} integral 1
- // CHECK-NEXT: TemplateArgument{{.*}} integral 2
-}
-
-namespace testUsingDecl {
- int i;
-}
-namespace TestUsingDecl {
- using testUsingDecl::i;
-}
-// CHECK: NamespaceDecl{{.*}} TestUsingDecl
-// CHECK-NEXT: UsingDecl{{.*}} testUsingDecl::i
-// CHECK-NEXT: UsingShadowDecl{{.*}} Var{{.*}} 'i' 'int'
-
-namespace testUnresolvedUsing {
- class A { };
- template<class T> class B {
- public:
- A a;
- };
- template<class T> class TestUnresolvedUsing : public B<T> {
- using typename B<T>::a;
- using B<T>::a;
- };
-}
-// CHECK: CXXRecordDecl{{.*}} TestUnresolvedUsing
-// CHECK: UnresolvedUsingTypenameDecl{{.*}} B<T>::a
-// CHECK: UnresolvedUsingValueDecl{{.*}} B<T>::a
-
-namespace TestLinkageSpecDecl {
- extern "C" void test1();
- extern "C++" void test2();
-}
-// CHECK: NamespaceDecl{{.*}} TestLinkageSpecDecl
-// CHECK-NEXT: LinkageSpecDecl{{.*}} C
-// CHECK-NEXT: FunctionDecl
-// CHECK-NEXT: LinkageSpecDecl{{.*}} C++
-// CHECK-NEXT: FunctionDecl
-
-class TestAccessSpecDecl {
-public:
-private:
-protected:
-};
-// CHECK: CXXRecordDecl{{.*}} class TestAccessSpecDecl
-// CHECK: CXXRecordDecl{{.*}} class TestAccessSpecDecl
-// CHECK-NEXT: AccessSpecDecl{{.*}} public
-// CHECK-NEXT: AccessSpecDecl{{.*}} private
-// CHECK-NEXT: AccessSpecDecl{{.*}} protected
-
-template<typename T> class TestFriendDecl {
- friend int foo();
- friend class A;
- friend T;
-};
-// CHECK: CXXRecord{{.*}} TestFriendDecl
-// CHECK: CXXRecord{{.*}} TestFriendDecl
-// CHECK-NEXT: FriendDecl
-// CHECK-NEXT: FunctionDecl{{.*}} foo
-// CHECK-NEXT: FriendDecl{{.*}} 'class A':'class A'
-// CHECK-NEXT: FriendDecl{{.*}} 'T'
-
-namespace TestFileScopeAsmDecl {
- asm("ret");
-}
-// CHECK: NamespaceDecl{{.*}} TestFileScopeAsmDecl{{$}}
-// CHECK: FileScopeAsmDecl{{.*> .*$}}
-// CHECK-NEXT: StringLiteral
-
-namespace TestFriendDecl2 {
- void f();
- struct S {
- friend void f();
- };
-}
-// CHECK: NamespaceDecl [[TestFriendDecl2:0x.*]] <{{.*}}> {{.*}} TestFriendDecl2
-// CHECK: |-FunctionDecl [[TestFriendDecl2_f:0x.*]] <{{.*}}> {{.*}} f 'void (void)'
-// CHECK: `-CXXRecordDecl {{.*}} struct S
-// CHECK: |-CXXRecordDecl {{.*}} struct S
-// CHECK: `-FriendDecl
-// CHECK: `-FunctionDecl {{.*}} parent [[TestFriendDecl2]] prev [[TestFriendDecl2_f]] <{{.*}}> {{.*}} f 'void (void)'
-
-namespace Comment {
- extern int Test;
- /// Something here.
- extern int Test;
- extern int Test;
-}
-
-// CHECK: VarDecl {{.*}} Test 'int' extern
-// CHECK-NOT: FullComment
-// CHECK: VarDecl {{.*}} Test 'int' extern
-// CHECK: `-FullComment
-// CHECK: `-ParagraphComment
-// CHECK: `-TextComment
-// CHECK: VarDecl {{.*}} Test 'int' extern
-// CHECK-NOT: FullComment
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -strict-whitespace %s
+
+class testEnumDecl {
+ enum class TestEnumDeclScoped;
+ enum TestEnumDeclFixed : int;
+};
+// CHECK: EnumDecl{{.*}} class TestEnumDeclScoped 'int'
+// CHECK: EnumDecl{{.*}} TestEnumDeclFixed 'int'
+
+class testFieldDecl {
+ int TestFieldDeclInit = 0;
+};
+// CHECK: FieldDecl{{.*}} TestFieldDeclInit 'int'
+// CHECK-NEXT: IntegerLiteral
+
+namespace testVarDeclNRVO {
+ class A { };
+ A foo() {
+ A TestVarDeclNRVO;
+ return TestVarDeclNRVO;
+ }
+}
+// CHECK: VarDecl{{.*}} TestVarDeclNRVO 'testVarDeclNRVO::A' nrvo
+
+void testParmVarDeclInit(int TestParmVarDeclInit = 0);
+// CHECK: ParmVarDecl{{.*}} TestParmVarDeclInit 'int'
+// CHECK-NEXT: IntegerLiteral{{.*}}
+
+namespace TestNamespaceDecl {
+ int i;
+}
+// CHECK: NamespaceDecl{{.*}} TestNamespaceDecl
+// CHECK-NEXT: VarDecl
+
+namespace TestNamespaceDecl {
+ int j;
+}
+// CHECK: NamespaceDecl{{.*}} TestNamespaceDecl
+// CHECK-NEXT: original Namespace
+// CHECK-NEXT: VarDecl
+
+inline namespace TestNamespaceDeclInline {
+}
+// CHECK: NamespaceDecl{{.*}} TestNamespaceDeclInline inline
+
+namespace testUsingDirectiveDecl {
+ namespace A {
+ }
+}
+namespace TestUsingDirectiveDecl {
+ using namespace testUsingDirectiveDecl::A;
+}
+// CHECK: NamespaceDecl{{.*}} TestUsingDirectiveDecl
+// CHECK-NEXT: UsingDirectiveDecl{{.*}} Namespace{{.*}} 'A'
+
+namespace testNamespaceAlias {
+ namespace A {
+ }
+}
+namespace TestNamespaceAlias = testNamespaceAlias::A;
+// CHECK: NamespaceAliasDecl{{.*}} TestNamespaceAlias
+// CHECK-NEXT: Namespace{{.*}} 'A'
+
+using TestTypeAliasDecl = int;
+// CHECK: TypeAliasDecl{{.*}} TestTypeAliasDecl 'int'
+
+namespace testTypeAliasTemplateDecl {
+ template<typename T> class A;
+ template<typename T> using TestTypeAliasTemplateDecl = A<T>;
+}
+// CHECK: TypeAliasTemplateDecl{{.*}} TestTypeAliasTemplateDecl
+// CHECK-NEXT: TemplateTypeParmDecl
+// CHECK-NEXT: TypeAliasDecl{{.*}} TestTypeAliasTemplateDecl 'A<T>'
+
+namespace testCXXRecordDecl {
+ class TestEmpty {};
+// CHECK: CXXRecordDecl{{.*}} class TestEmpty
+// CHECK-NEXT: DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
+// CHECK-NEXT: DefaultConstructor exists trivial constexpr
+// CHECK-NEXT: CopyConstructor simple trivial has_const_param
+// CHECK-NEXT: MoveConstructor exists simple trivial
+// CHECK-NEXT: CopyAssignment trivial has_const_param
+// CHECK-NEXT: MoveAssignment exists simple trivial
+// CHECK-NEXT: Destructor simple irrelevant trivial
+
+ class A { };
+ class B { };
+ class TestCXXRecordDecl : virtual A, public B {
+ int i;
+ };
+}
+// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDecl
+// CHECK-NEXT: DefinitionData{{$}}
+// CHECK-NEXT: DefaultConstructor exists non_trivial
+// CHECK-NEXT: CopyConstructor simple non_trivial has_const_param
+// CHECK-NEXT: MoveConstructor exists simple non_trivial
+// CHECK-NEXT: CopyAssignment non_trivial has_const_param
+// CHECK-NEXT: MoveAssignment exists simple non_trivial
+// CHECK-NEXT: Destructor simple irrelevant trivial
+// CHECK-NEXT: virtual private 'testCXXRecordDecl::A'
+// CHECK-NEXT: public 'testCXXRecordDecl::B'
+// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDecl
+// CHECK-NEXT: FieldDecl
+
+template<class...T>
+class TestCXXRecordDeclPack : public T... {
+};
+// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDeclPack
+// CHECK: public 'T'...
+// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDeclPack
+
+thread_local int TestThreadLocalInt;
+// CHECK: TestThreadLocalInt {{.*}} tls_dynamic
+
+class testCXXMethodDecl {
+ virtual void TestCXXMethodDeclPure() = 0;
+ void TestCXXMethodDeclDelete() = delete;
+ void TestCXXMethodDeclThrow() throw();
+ void TestCXXMethodDeclThrowType() throw(int);
+};
+// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclPure 'void ()' virtual pure
+// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclDelete 'void ()' delete
+// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrow 'void () throw()'
+// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrowType 'void () throw(int)'
+
+namespace testCXXConstructorDecl {
+ class A { };
+ class TestCXXConstructorDecl : public A {
+ int I;
+ TestCXXConstructorDecl(A &a, int i) : A(a), I(i) { }
+ TestCXXConstructorDecl(A &a) : TestCXXConstructorDecl(a, 0) { }
+ };
+}
+// CHECK: CXXConstructorDecl{{.*}} TestCXXConstructorDecl 'void {{.*}}'
+// CHECK-NEXT: ParmVarDecl{{.*}} a
+// CHECK-NEXT: ParmVarDecl{{.*}} i
+// CHECK-NEXT: CXXCtorInitializer{{.*}}A
+// CHECK-NEXT: Expr
+// CHECK: CXXCtorInitializer{{.*}}I
+// CHECK-NEXT: Expr
+// CHECK: CompoundStmt
+// CHECK: CXXConstructorDecl{{.*}} TestCXXConstructorDecl 'void {{.*}}'
+// CHECK-NEXT: ParmVarDecl{{.*}} a
+// CHECK-NEXT: CXXCtorInitializer{{.*}}TestCXXConstructorDecl
+// CHECK-NEXT: CXXConstructExpr{{.*}}TestCXXConstructorDecl
+
+class TestCXXDestructorDecl {
+ ~TestCXXDestructorDecl() { }
+};
+// CHECK: CXXDestructorDecl{{.*}} ~TestCXXDestructorDecl 'void () noexcept'
+// CHECK-NEXT: CompoundStmt
+
+// Test that the range of a defaulted members is computed correctly.
+class TestMemberRanges {
+public:
+ TestMemberRanges() = default;
+ TestMemberRanges(const TestMemberRanges &Other) = default;
+ TestMemberRanges(TestMemberRanges &&Other) = default;
+ ~TestMemberRanges() = default;
+ TestMemberRanges &operator=(const TestMemberRanges &Other) = default;
+ TestMemberRanges &operator=(TestMemberRanges &&Other) = default;
+};
+void SomeFunction() {
+ TestMemberRanges A;
+ TestMemberRanges B(A);
+ B = A;
+ A = static_cast<TestMemberRanges &&>(B);
+ TestMemberRanges C(static_cast<TestMemberRanges &&>(A));
+}
+// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:30>
+// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:59>
+// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:54>
+// CHECK: CXXDestructorDecl{{.*}} <line:{{.*}}:3, col:31>
+// CHECK: CXXMethodDecl{{.*}} <line:{{.*}}:3, col:70>
+// CHECK: CXXMethodDecl{{.*}} <line:{{.*}}:3, col:65>
+
+class TestCXXConversionDecl {
+ operator int() { return 0; }
+};
+// CHECK: CXXConversionDecl{{.*}} operator int 'int ()'
+// CHECK-NEXT: CompoundStmt
+
+namespace TestStaticAssertDecl {
+ static_assert(true, "msg");
+}
+// CHECK: NamespaceDecl{{.*}} TestStaticAssertDecl
+// CHECK-NEXT: StaticAssertDecl{{.*> .*$}}
+// CHECK-NEXT: CXXBoolLiteralExpr
+// CHECK-NEXT: StringLiteral
+
+namespace testFunctionTemplateDecl {
+ class A { };
+ class B { };
+ class C { };
+ class D { };
+ template<typename T> void TestFunctionTemplate(T) { }
+
+ // implicit instantiation
+ void bar(A a) { TestFunctionTemplate(a); }
+
+ // explicit specialization
+ template<> void TestFunctionTemplate(B);
+
+ // explicit instantiation declaration
+ extern template void TestFunctionTemplate(C);
+
+ // explicit instantiation definition
+ template void TestFunctionTemplate(D);
+}
+// CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate
+// CHECK-NEXT: TemplateTypeParmDecl
+// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'
+// CHECK-NEXT: ParmVarDecl{{.*}} 'T'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}A
+// CHECK-NEXT: TemplateArgument
+// CHECK-NEXT: ParmVarDecl
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: Function{{.*}} 'TestFunctionTemplate' {{.*}}B
+// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}C
+// CHECK-NEXT: TemplateArgument
+// CHECK-NEXT: ParmVarDecl
+// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}D
+// CHECK-NEXT: TemplateArgument
+// CHECK-NEXT: ParmVarDecl
+// CHECK-NEXT: CompoundStmt
+// CHECK: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}B
+// CHECK-NEXT: TemplateArgument
+// CHECK-NEXT: ParmVarDecl
+
+namespace testClassTemplateDecl {
+ class A { };
+ class B { };
+ class C { };
+ class D { };
+
+ template<typename T> class TestClassTemplate {
+ public:
+ TestClassTemplate();
+ ~TestClassTemplate();
+ int j();
+ int i;
+ };
+
+ // implicit instantiation
+ TestClassTemplate<A> a;
+
+ // explicit specialization
+ template<> class TestClassTemplate<B> {
+ int j;
+ };
+
+ // explicit instantiation declaration
+ extern template class TestClassTemplate<C>;
+
+ // explicit instantiation definition
+ template class TestClassTemplate<D>;
+
+ // partial explicit specialization
+ template<typename T1, typename T2> class TestClassTemplatePartial {
+ int i;
+ };
+ template<typename T1> class TestClassTemplatePartial<T1, A> {
+ int j;
+ };
+}
+// CHECK: ClassTemplateDecl{{.*}} TestClassTemplate
+// CHECK-NEXT: TemplateTypeParmDecl
+// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
+// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
+// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
+// CHECK-NEXT: FieldDecl{{.*}} i
+// CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
+// CHECK: TemplateArgument{{.*}}A
+// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
+// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
+// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
+// CHECK-NEXT: FieldDecl{{.*}} i
+// CHECK: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
+// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
+// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
+
+// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: DefinitionData
+// CHECK: TemplateArgument{{.*}}B
+// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: FieldDecl{{.*}} j
+
+// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
+// CHECK: TemplateArgument{{.*}}C
+// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
+// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
+// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
+// CHECK-NEXT: FieldDecl{{.*}} i
+
+// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
+// CHECK: TemplateArgument{{.*}}D
+// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
+// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
+// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
+// CHECK-NEXT: FieldDecl{{.*}} i
+
+// CHECK: ClassTemplatePartialSpecializationDecl{{.*}} class TestClassTemplatePartial
+// CHECK: TemplateArgument
+// CHECK-NEXT: TemplateArgument{{.*}}A
+// CHECK-NEXT: TemplateTypeParmDecl
+// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplatePartial
+// CHECK-NEXT: FieldDecl{{.*}} j
+
+// PR15220 dump instantiation only once
+namespace testCanonicalTemplate {
+ class A {};
+
+ template<typename T> void TestFunctionTemplate(T);
+ template<typename T> void TestFunctionTemplate(T);
+ void bar(A a) { TestFunctionTemplate(a); }
+ // CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate
+ // CHECK-NEXT: TemplateTypeParmDecl
+ // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'
+ // CHECK-NEXT: ParmVarDecl{{.*}} 'T'
+ // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}A
+ // CHECK-NEXT: TemplateArgument
+ // CHECK-NEXT: ParmVarDecl
+ // CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate
+ // CHECK-NEXT: TemplateTypeParmDecl
+ // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'
+ // CHECK-NEXT: ParmVarDecl{{.*}} 'T'
+ // CHECK-NEXT: Function{{.*}} 'TestFunctionTemplate'
+ // CHECK-NOT: TemplateArgument
+
+ template<typename T1> class TestClassTemplate {
+ template<typename T2> friend class TestClassTemplate;
+ };
+ TestClassTemplate<A> a;
+ // CHECK: ClassTemplateDecl{{.*}} TestClassTemplate
+ // CHECK-NEXT: TemplateTypeParmDecl
+ // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+ // CHECK: CXXRecordDecl{{.*}} class TestClassTemplate
+ // CHECK-NEXT: FriendDecl
+ // CHECK-NEXT: ClassTemplateDecl{{.*}} TestClassTemplate
+ // CHECK-NEXT: TemplateTypeParmDecl
+ // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+ // CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
+ // CHECK: TemplateArgument{{.*}}A
+ // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+}
+
+template <class T>
+class TestClassScopeFunctionSpecialization {
+ template<class U> void foo(U a) { }
+ template<> void foo<int>(int a) { }
+};
+// CHECK: ClassScopeFunctionSpecializationDecl
+// CHECK-NEXT: CXXMethod{{.*}} 'foo' 'void (int)'
+// CHECK-NEXT: TemplateArgument{{.*}} 'int'
+
+namespace TestTemplateTypeParmDecl {
+ template<typename ... T, class U = int> void foo();
+}
+// CHECK: NamespaceDecl{{.*}} TestTemplateTypeParmDecl
+// CHECK-NEXT: FunctionTemplateDecl
+// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename depth 0 index 0 ... T
+// CHECK-NEXT: TemplateTypeParmDecl{{.*}} class depth 0 index 1 U
+// CHECK-NEXT: TemplateArgument type 'int'
+
+namespace TestNonTypeTemplateParmDecl {
+ template<int I = 1, int ... J> void foo();
+}
+// CHECK: NamespaceDecl{{.*}} TestNonTypeTemplateParmDecl
+// CHECK-NEXT: FunctionTemplateDecl
+// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 0 I
+// CHECK-NEXT: TemplateArgument expr
+// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
+// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 1 ... J
+
+namespace TestTemplateTemplateParmDecl {
+ template<typename T> class A;
+ template <template <typename> class T = A, template <typename> class ... U> void foo();
+}
+// CHECK: NamespaceDecl{{.*}} TestTemplateTemplateParmDecl
+// CHECK: FunctionTemplateDecl
+// CHECK-NEXT: TemplateTemplateParmDecl{{.*}} T
+// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename
+// CHECK-NEXT: TemplateArgument{{.*}} template A
+// CHECK-NEXT: TemplateTemplateParmDecl{{.*}} ... U
+// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename
+
+namespace TestTemplateArgument {
+ template<typename> class A { };
+ template<template<typename> class ...> class B { };
+ int foo();
+
+ template<typename> class testType { };
+ template class testType<int>;
+ // CHECK: ClassTemplateSpecializationDecl{{.*}} class testType
+ // CHECK: TemplateArgument{{.*}} type 'int'
+
+ template<int fp(void)> class testDecl { };
+ template class testDecl<foo>;
+ // CHECK: ClassTemplateSpecializationDecl{{.*}} class testDecl
+ // CHECK: TemplateArgument{{.*}} decl
+ // CHECK-NEXT: Function{{.*}}foo
+
+ template class testDecl<nullptr>;
+ // CHECK: ClassTemplateSpecializationDecl{{.*}} class testDecl
+ // CHECK: TemplateArgument{{.*}} nullptr
+
+ template<int> class testIntegral { };
+ template class testIntegral<1>;
+ // CHECK: ClassTemplateSpecializationDecl{{.*}} class testIntegral
+ // CHECK: TemplateArgument{{.*}} integral 1
+
+ template<template<typename> class> class testTemplate { };
+ template class testTemplate<A>;
+ // CHECK: ClassTemplateSpecializationDecl{{.*}} class testTemplate
+ // CHECK: TemplateArgument{{.*}} A
+
+ template<template<typename> class ...T> class C {
+ B<T...> testTemplateExpansion;
+ };
+ // FIXME: Need TemplateSpecializationType dumping to test TemplateExpansion.
+
+ template<int, int = 0> class testExpr;
+ template<int I> class testExpr<I> { };
+ // CHECK: ClassTemplatePartialSpecializationDecl{{.*}} class testExpr
+ // CHECK: TemplateArgument{{.*}} expr
+ // CHECK-NEXT: DeclRefExpr{{.*}}I
+
+ template<int, int ...> class testPack { };
+ template class testPack<0, 1, 2>;
+ // CHECK: ClassTemplateSpecializationDecl{{.*}} class testPack
+ // CHECK: TemplateArgument{{.*}} integral 0
+ // CHECK-NEXT: TemplateArgument{{.*}} pack
+ // CHECK-NEXT: TemplateArgument{{.*}} integral 1
+ // CHECK-NEXT: TemplateArgument{{.*}} integral 2
+}
+
+namespace testUsingDecl {
+ int i;
+}
+namespace TestUsingDecl {
+ using testUsingDecl::i;
+}
+// CHECK: NamespaceDecl{{.*}} TestUsingDecl
+// CHECK-NEXT: UsingDecl{{.*}} testUsingDecl::i
+// CHECK-NEXT: UsingShadowDecl{{.*}} Var{{.*}} 'i' 'int'
+
+namespace testUnresolvedUsing {
+ class A { };
+ template<class T> class B {
+ public:
+ A a;
+ };
+ template<class T> class TestUnresolvedUsing : public B<T> {
+ using typename B<T>::a;
+ using B<T>::a;
+ };
+}
+// CHECK: CXXRecordDecl{{.*}} TestUnresolvedUsing
+// CHECK: UnresolvedUsingTypenameDecl{{.*}} B<T>::a
+// CHECK: UnresolvedUsingValueDecl{{.*}} B<T>::a
+
+namespace TestLinkageSpecDecl {
+ extern "C" void test1();
+ extern "C++" void test2();
+}
+// CHECK: NamespaceDecl{{.*}} TestLinkageSpecDecl
+// CHECK-NEXT: LinkageSpecDecl{{.*}} C
+// CHECK-NEXT: FunctionDecl
+// CHECK-NEXT: LinkageSpecDecl{{.*}} C++
+// CHECK-NEXT: FunctionDecl
+
+class TestAccessSpecDecl {
+public:
+private:
+protected:
+};
+// CHECK: CXXRecordDecl{{.*}} class TestAccessSpecDecl
+// CHECK: CXXRecordDecl{{.*}} class TestAccessSpecDecl
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: AccessSpecDecl{{.*}} private
+// CHECK-NEXT: AccessSpecDecl{{.*}} protected
+
+template<typename T> class TestFriendDecl {
+ friend int foo();
+ friend class A;
+ friend T;
+};
+// CHECK: CXXRecord{{.*}} TestFriendDecl
+// CHECK: CXXRecord{{.*}} TestFriendDecl
+// CHECK-NEXT: FriendDecl
+// CHECK-NEXT: FunctionDecl{{.*}} foo
+// CHECK-NEXT: FriendDecl{{.*}} 'class A':'A'
+// CHECK-NEXT: FriendDecl{{.*}} 'T'
+
+namespace TestFileScopeAsmDecl {
+ asm("ret");
+}
+// CHECK: NamespaceDecl{{.*}} TestFileScopeAsmDecl{{$}}
+// CHECK: FileScopeAsmDecl{{.*> .*$}}
+// CHECK-NEXT: StringLiteral
+
+namespace TestFriendDecl2 {
+ void f();
+ struct S {
+ friend void f();
+ };
+}
+// CHECK: NamespaceDecl [[TestFriendDecl2:0x.*]] <{{.*}}> {{.*}} TestFriendDecl2
+// CHECK: |-FunctionDecl [[TestFriendDecl2_f:0x.*]] <{{.*}}> {{.*}} f 'void ()'
+// CHECK: `-CXXRecordDecl {{.*}} struct S
+// CHECK: |-CXXRecordDecl {{.*}} struct S
+// CHECK: `-FriendDecl
+// CHECK: `-FunctionDecl {{.*}} parent [[TestFriendDecl2]] prev [[TestFriendDecl2_f]] <{{.*}}> {{.*}} f 'void ()'
+
+namespace Comment {
+ extern int Test;
+ /// Something here.
+ extern int Test;
+ extern int Test;
+}
+
+// CHECK: VarDecl {{.*}} Test 'int' extern
+// CHECK-NOT: FullComment
+// CHECK: VarDecl {{.*}} Test 'int' extern
+// CHECK: `-FullComment
+// CHECK: `-ParagraphComment
+// CHECK: `-TextComment
+// CHECK: VarDecl {{.*}} Test 'int' extern
+// CHECK-NOT: FullComment
diff --git a/test/Misc/ast-dump-invalid.cpp b/test/Misc/ast-dump-invalid.cpp
index 842b057a4a54..1f7442155e33 100644
--- a/test/Misc/ast-dump-invalid.cpp
+++ b/test/Misc/ast-dump-invalid.cpp
@@ -35,7 +35,7 @@ int g(int i) {
// CHECK-NEXT: `-IfStmt {{.*}} <line:25:3, line:28:12>
// CHECK-NEXT: |-<<<NULL>>>
// CHECK-NEXT: |-<<<NULL>>>
-// CHECK-NEXT: |-OpaqueValueExpr {{.*}} <<invalid sloc>> '_Bool'
+// CHECK-NEXT: |-OpaqueValueExpr {{.*}} <<invalid sloc>> 'bool'
// CHECK-NEXT: |-ReturnStmt {{.*}} <line:26:5, col:12>
// CHECK-NEXT: | `-IntegerLiteral {{.*}} <col:12> 'int' 4
// CHECK-NEXT: `-ReturnStmt {{.*}} <line:28:5, col:12>
diff --git a/test/Modules/Inputs/implicit-private-canonical/A.framework/Headers/a.h b/test/Modules/Inputs/implicit-private-canonical/A.framework/Headers/a.h
new file mode 100644
index 000000000000..8b4b1987450a
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-canonical/A.framework/Headers/a.h
@@ -0,0 +1 @@
+extern int APUBLIC;
diff --git a/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/aprivate.h b/test/Modules/Inputs/implicit-private-canonical/A.framework/Headers/aprivate.h
index 760d901aa366..760d901aa366 100644
--- a/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/aprivate.h
+++ b/test/Modules/Inputs/implicit-private-canonical/A.framework/Headers/aprivate.h
diff --git a/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.modulemap b/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..95eabf90a968
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.modulemap
@@ -0,0 +1,4 @@
+framework module A {
+ header "a.h"
+ export *
+}
diff --git a/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.private.modulemap b/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.private.modulemap
new file mode 100644
index 000000000000..a7606f9c14b8
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.private.modulemap
@@ -0,0 +1,4 @@
+framework module A_Private {
+ header "aprivate.h"
+ export *
+}
diff --git a/test/Modules/Inputs/implicit-private-canonical/A.framework/PrivateHeaders/aprivate.h b/test/Modules/Inputs/implicit-private-canonical/A.framework/PrivateHeaders/aprivate.h
new file mode 100644
index 000000000000..760d901aa366
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-canonical/A.framework/PrivateHeaders/aprivate.h
@@ -0,0 +1 @@
+extern int APRIVATE;
diff --git a/test/Modules/Inputs/implicit-private-with-different-name/A.framework/PrivateHeaders/aprivate.h b/test/Modules/Inputs/implicit-private-with-different-name/A.framework/PrivateHeaders/aprivate.h
new file mode 100644
index 000000000000..760d901aa366
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-with-different-name/A.framework/PrivateHeaders/aprivate.h
@@ -0,0 +1 @@
+extern int APRIVATE;
diff --git a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/a.h b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/a.h
new file mode 100644
index 000000000000..8b4b1987450a
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/a.h
@@ -0,0 +1 @@
+extern int APUBLIC;
diff --git a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/aprivate.h b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/aprivate.h
new file mode 100644
index 000000000000..760d901aa366
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/aprivate.h
@@ -0,0 +1 @@
+extern int APRIVATE;
diff --git a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.modulemap b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..95eabf90a968
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.modulemap
@@ -0,0 +1,4 @@
+framework module A {
+ header "a.h"
+ export *
+}
diff --git a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap
new file mode 100644
index 000000000000..40182969f4c7
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap
@@ -0,0 +1,4 @@
+framework module A.Private {
+ header "aprivate.h"
+ export *
+}
diff --git a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/PrivateHeaders/aprivate.h b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/PrivateHeaders/aprivate.h
new file mode 100644
index 000000000000..760d901aa366
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/PrivateHeaders/aprivate.h
@@ -0,0 +1 @@
+extern int APRIVATE;
diff --git a/test/Modules/add-remove-private.m b/test/Modules/add-remove-private.m
index dc73a096c807..5e7a5a966a4d 100644
--- a/test/Modules/add-remove-private.m
+++ b/test/Modules/add-remove-private.m
@@ -4,7 +4,7 @@
// RUN: cp -r %S/Inputs/AddRemovePrivate.framework %t/AddRemovePrivate.framework
// Build with module.private.modulemap
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -fdisable-module-hash -F %t %s -verify -DP
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -fdisable-module-hash -F %t %s -verify -DP -Wno-private-module
// RUN: cp %t.mcp/AddRemovePrivate.pcm %t/with.pcm
// Build without module.private.modulemap
@@ -17,7 +17,7 @@
// Build with module.private.modulemap (again)
// RUN: cp %S/Inputs/AddRemovePrivate.framework/Modules/module.private.modulemap %t/AddRemovePrivate.framework/Modules/module.private.modulemap
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -fdisable-module-hash -F %t %s -verify -DP
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -fdisable-module-hash -F %t %s -verify -DP -Wno-private-module
// RUN: not diff %t.mcp/AddRemovePrivate.pcm %t/without.pcm
// expected-no-diagnostics
diff --git a/test/Modules/auto-module-import.m b/test/Modules/auto-module-import.m
index 9a34c92eab2f..f6127adcbd89 100644
--- a/test/Modules/auto-module-import.m
+++ b/test/Modules/auto-module-import.m
@@ -1,7 +1,7 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -DERRORS
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -xobjective-c++ %s -verify
+// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -DERRORS
+// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify
+// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -xobjective-c++ %s -verify
//
// Test both with and without the declarations that refer to unimported
// entities. For error recovery, those cases implicitly trigger an import.
diff --git a/test/Modules/global_index.m b/test/Modules/global_index.m
index 64a70f2a43ff..e94c69ac3c1c 100644
--- a/test/Modules/global_index.m
+++ b/test/Modules/global_index.m
@@ -1,12 +1,12 @@
// RUN: rm -rf %t
// Run without global module index
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fdisable-module-hash -fmodules -fimplicit-module-maps -fno-modules-global-index -F %S/Inputs %s -verify
+// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fdisable-module-hash -fmodules -fimplicit-module-maps -fno-modules-global-index -F %S/Inputs %s -verify
// RUN: ls %t|not grep modules.idx
// Run and create the global module index
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fdisable-module-hash -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify
+// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fdisable-module-hash -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify
// RUN: ls %t|grep modules.idx
// Run and use the global module index
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fdisable-module-hash -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -print-stats 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fdisable-module-hash -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -print-stats 2>&1 | FileCheck %s
// expected-no-diagnostics
@import DependsOnModule;
diff --git a/test/Modules/implicit-map-dot-private.m b/test/Modules/implicit-map-dot-private.m
new file mode 100644
index 000000000000..9fd8677f9e70
--- /dev/null
+++ b/test/Modules/implicit-map-dot-private.m
@@ -0,0 +1,12 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -emit-pch -o %t-A.pch %s -Wprivate-module
+
+#ifndef HEADER
+#define HEADER
+
+@import A.Private; // expected-warning {{no submodule named 'Private' in module 'A'; using top level 'A_Private'}}
+// expected-note@Inputs/implicit-private-canonical/A.framework/Modules/module.private.modulemap:1{{module defined here}}
+
+const int *y = &APRIVATE;
+
+#endif
diff --git a/test/Modules/implicit-private-canonical.m b/test/Modules/implicit-private-canonical.m
new file mode 100644
index 000000000000..96b6c4a3464d
--- /dev/null
+++ b/test/Modules/implicit-private-canonical.m
@@ -0,0 +1,35 @@
+// RUN: rm -rf %t
+// Build PCH using A, with adjacent private module APrivate, which winds up being implicitly referenced
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -emit-pch -o %t-A.pch %s -Wprivate-module -DNO_AT_IMPORT
+// Use the PCH with no explicit way to resolve APrivate, still pick it up by automatic second-chance search for "A" with "Private" appended
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -include-pch %t-A.pch %s -fsyntax-only -Wprivate-module -DNO_AT_IMPORT
+
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -emit-pch -o %t-A.pch %s -Wprivate-module -DUSE_AT_IMPORT_PRIV
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -include-pch %t-A.pch %s -fsyntax-only -Wprivate-module -DUSE_AT_IMPORT_PRIV
+
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -emit-pch -o %t-A.pch %s -Wprivate-module -DUSE_AT_IMPORT_BOTH
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -include-pch %t-A.pch %s -fsyntax-only -Wprivate-module -DUSE_AT_IMPORT_BOTH
+
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+#ifdef NO_AT_IMPORT
+#import "A/aprivate.h"
+#endif
+
+#ifdef USE_AT_IMPORT_PRIV
+@import A_Private;
+#endif
+
+#ifdef USE_AT_IMPORT_BOTH
+@import A;
+@import A_Private;
+#endif
+
+const int *y = &APRIVATE;
+
+#endif
diff --git a/test/Modules/implicit-private-with-different-name.m b/test/Modules/implicit-private-with-different-name.m
index c09d3979c3e1..7ee84539bf3a 100644
--- a/test/Modules/implicit-private-with-different-name.m
+++ b/test/Modules/implicit-private-with-different-name.m
@@ -1,17 +1,17 @@
// RUN: rm -rf %t
// Build PCH using A, with adjacent private module APrivate, which winds up being implicitly referenced
-// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -emit-pch -o %t-A.pch %s
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -emit-pch -o %t-A.pch %s -Wprivate-module
// Use the PCH with no explicit way to resolve APrivate, still pick it up by automatic second-chance search for "A" with "Private" appended
-// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -include-pch %t-A.pch %s -fsyntax-only
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -include-pch %t-A.pch %s -fsyntax-only -Wprivate-module
// Check the fixit
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -include-pch %t-A.pch %s -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -include-pch %t-A.pch %s -fsyntax-only -fdiagnostics-parseable-fixits -Wprivate-module %s 2>&1 | FileCheck %s
-// expected-warning@Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap:1{{top-level module 'APrivate' in private module map, expected a submodule of 'A'}}
-// expected-note@Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap:1{{make 'APrivate' a submodule of 'A' to ensure it can be found by name}}
-// CHECK: fix-it:"{{.*}}module.private.modulemap":{1:18-1:26}:"A.Private"
+// expected-warning@Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap:1{{expected canonical name for private module 'APrivate'}}
+// expected-note@Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap:1{{rename 'APrivate' to ensure it can be found by name}}
+// CHECK: fix-it:"{{.*}}module.private.modulemap":{1:18-1:26}:"A_Private"
#ifndef HEADER
#define HEADER
diff --git a/test/Modules/implicit-private-with-submodule.m b/test/Modules/implicit-private-with-submodule.m
new file mode 100644
index 000000000000..1779341a5f6b
--- /dev/null
+++ b/test/Modules/implicit-private-with-submodule.m
@@ -0,0 +1,36 @@
+// RUN: rm -rf %t
+// Build PCH using A, with private submodule A.Private
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-submodule -emit-pch -o %t-A.pch %s -DNO_AT_IMPORT
+
+// RUN: rm -rf %t
+// Build PCH using A, with private submodule A.Private, check the fixit
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-submodule -emit-pch -o %t-A.pch %s -fdiagnostics-parseable-fixits -DNO_AT_IMPORT 2>&1 | FileCheck %s
+
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-submodule -emit-pch -o %t-A.pch %s -DUSE_AT_IMPORT_PRIV
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-submodule -emit-pch -o %t-A.pch %s -DUSE_AT_IMPORT_BOTH
+
+// 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"
+
+#ifndef HEADER
+#define HEADER
+
+#ifdef NO_AT_IMPORT
+#import "A/aprivate.h"
+#endif
+
+#ifdef USE_AT_IMPORT_PRIV
+@import A.Private;
+#endif
+
+#ifdef USE_AT_IMPORT_BOTH
+@import A;
+@import A.Private;
+#endif
+
+const int *y = &APRIVATE;
+
+#endif
diff --git a/test/Modules/modulemap-locations.m b/test/Modules/modulemap-locations.m
index 3c80db582d1d..c99bb14dc718 100644
--- a/test/Modules/modulemap-locations.m
+++ b/test/Modules/modulemap-locations.m
@@ -1,5 +1,5 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/ModuleMapLocations/Module_ModuleMap -I %S/Inputs/ModuleMapLocations/Both -F %S/Inputs/ModuleMapLocations -I %S/Inputs/ModuleMapLocations -F %S/Inputs -x objective-c -fsyntax-only %s -verify
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/ModuleMapLocations/Module_ModuleMap -I %S/Inputs/ModuleMapLocations/Both -F %S/Inputs/ModuleMapLocations -I %S/Inputs/ModuleMapLocations -F %S/Inputs -x objective-c -fsyntax-only %s -verify -Wno-private-module
// regular
@import module_modulemap;
diff --git a/test/Modules/odr.cpp b/test/Modules/odr.cpp
index 9cdbb4f0806d..c4700110af44 100644
--- a/test/Modules/odr.cpp
+++ b/test/Modules/odr.cpp
@@ -18,6 +18,6 @@ int x = f() + g();
// expected-note@a.h:3 {{declaration of 'f' does not match}}
// expected-note@a.h:1 {{definition has no member 'm'}}
-// expected-error@b.h:5 {{'E::e2' from module 'b' is not present in definition of 'E' in module 'a'}}
+// expected-error@b.h:5 {{'e2' from module 'b' is not present in definition of 'E' in module 'a'}}
// expected-error@b.h:3 {{'Y::f' from module 'b' is not present in definition of 'Y' in module 'a'}}
// expected-error@b.h:2 {{'Y::m' from module 'b' is not present in definition of 'Y' in module 'a'}}
diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp
index b672695dce15..054e41a9eaea 100644
--- a/test/Modules/odr_hash.cpp
+++ b/test/Modules/odr_hash.cpp
@@ -557,11 +557,11 @@ S10 s10;
#if defined(FIRST)
struct S11 {
- void A(int x) {}
+ void A(int x);
};
#elif defined(SECOND)
struct S11 {
- void A(int y) {}
+ void A(int y);
};
#else
S11 s11;
@@ -571,11 +571,11 @@ S11 s11;
#if defined(FIRST)
struct S12 {
- void A(int x) {}
+ void A(int x);
};
#elif defined(SECOND)
struct S12 {
- void A(int x = 1) {}
+ void A(int x = 1);
};
#else
S12 s12;
@@ -585,11 +585,11 @@ S12 s12;
#if defined(FIRST)
struct S13 {
- void A(int x = 1 + 0) {}
+ void A(int x = 1 + 0);
};
#elif defined(SECOND)
struct S13 {
- void A(int x = 1) {}
+ void A(int x = 1);
};
#else
S13 s13;
@@ -599,11 +599,11 @@ S13 s13;
#if defined(FIRST)
struct S14 {
- void A(int x[2]) {}
+ void A(int x[2]);
};
#elif defined(SECOND)
struct S14 {
- void A(int x[3]) {}
+ void A(int x[3]);
};
#else
S14 s14;
@@ -2751,14 +2751,14 @@ namespace DefaultArguments {
template <typename T>
struct S {
struct R {
- void foo(T x = 0) {}
+ void foo(T x = 0);
};
};
#elif defined(SECOND)
template <typename T>
struct S {
struct R {
- void foo(T x = 1) {}
+ void foo(T x = 1);
};
};
#else
@@ -2771,13 +2771,13 @@ void run() {
#if defined(FIRST)
template <typename alpha> struct Bravo {
- void charlie(bool delta = false) {}
+ void charlie(bool delta = false);
};
typedef Bravo<char> echo;
echo foxtrot;
#elif defined(SECOND)
template <typename alpha> struct Bravo {
- void charlie(bool delta = (false)) {}
+ void charlie(bool delta = (false));
};
typedef Bravo<char> echo;
echo foxtrot;
@@ -2788,6 +2788,142 @@ Bravo<char> golf;
#endif
} // namespace DefaultArguments
+namespace FunctionDecl {
+#if defined(FIRST)
+struct S1 {};
+S1 s1a;
+#elif defined(SECOND)
+struct S1 {};
+#else
+S1 s1;
+#endif
+
+#if defined(FIRST)
+struct S2 {
+ S2() = default;
+};
+S2 s2a = S2();
+#elif defined(SECOND)
+struct S2 {
+ S2() = default;
+};
+#else
+S2 s2;
+#endif
+
+#if defined(FIRST)
+struct S3 {
+ S3() = delete;
+};
+S3* s3c;
+#elif defined(SECOND)
+struct S3 {
+ S3() = delete;
+};
+#else
+S3* s3;
+#endif
+
+#if defined(FIRST) || defined(SECOND)
+int F1(int x, float y = 2.7) { return 1; }
+#else
+int I1 = F1(1);
+#endif
+
+#if defined(FIRST)
+int F2() { return 1; }
+#elif defined(SECOND)
+double F2() { return 1; }
+#else
+int I2 = F2();
+// expected-error@-1 {{call to 'F2' is ambiguous}}
+// expected-note@first.h:* {{candidate function}}
+// expected-note@second.h:* {{candidate function}}
+#endif
+
+#if defined(FIRST)
+int F3(float) { return 1; }
+#elif defined(SECOND)
+int F3(double) { return 1; }
+#else
+int I3 = F3(1);
+// expected-error@-1 {{call to 'F3' is ambiguous}}
+// expected-note@first.h:* {{candidate function}}
+// expected-note@second.h:* {{candidate function}}
+#endif
+
+#if defined(FIRST)
+int F4(int x) { return 1; }
+#elif defined(SECOND)
+int F4(int y) { return 1; }
+#else
+int I4 = F4(1);
+// expected-error@second.h:* {{'FunctionDecl::F4' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st parameter with name 'y'}}
+// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter with name 'x'}}
+#endif
+
+#if defined(FIRST)
+int F5(int x) { return 1; }
+#elif defined(SECOND)
+int F5(int x = 1) { return 1; }
+#else
+int I5 = F6(1);
+// expected-error@second.h:* {{'FunctionDecl::F5' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st parameter without a default argument}}
+// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter with a default argument}}
+#endif
+
+#if defined(FIRST)
+int F6(int x = 2) { return 1; }
+#elif defined(SECOND)
+int F6(int x = 1) { return 1; }
+#else
+int I6 = F6(1);
+// expected-error@second.h:* {{'FunctionDecl::F6' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st parameter with a default argument}}
+// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter with a different default argument}}
+#endif
+
+using I = int;
+#if defined(FIRST)
+I F7() { return 0; }
+#elif defined(SECOND)
+int F7() { return 0; }
+#else
+int I7 = F7();
+// expected-error@second.h:* {{'FunctionDecl::F7' has different definitions in different modules; definition in module 'SecondModule' first difference is return type is 'int'}}
+// expected-note@first.h:* {{but in 'FirstModule' found different return type 'FunctionDecl::I' (aka 'int')}}
+#endif
+
+#if defined(FIRST)
+int F8(int) { return 0; }
+#elif defined(SECOND)
+int F8(I) { return 0; }
+#else
+int I8 = F8(1);
+// expected-error@second.h:* {{'FunctionDecl::F8' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st parameter with type 'FunctionDecl::I' (aka 'int')}}
+// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter with type 'int'}}
+#endif
+
+#if defined(FIRST)
+int F9(int[1]) { return 0; }
+#elif defined(SECOND)
+int F9(int[2]) { return 0; }
+#else
+int I9 = F9(nullptr);
+// expected-error@second.h:* {{'FunctionDecl::F9' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st parameter with type 'int *' decayed from 'int [2]'}}
+// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter with type 'int *' decayed from 'int [1]'}}
+#endif
+
+#if defined(FIRST)
+int F10() { return 1; }
+#elif defined(SECOND)
+int F10() { return 2; }
+#else
+int I10 = F10();
+#endif
+// expected-error@second.h:* {{'FunctionDecl::F10' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+} // namespace FunctionDecl
+
// Keep macros contained to one file.
#ifdef FIRST
#undef FIRST
diff --git a/test/Modules/prune.m b/test/Modules/prune.m
index 58992f9c006d..97a2fd7d0dcc 100644
--- a/test/Modules/prune.m
+++ b/test/Modules/prune.m
@@ -8,8 +8,8 @@
// Clear out the module cache
// RUN: rm -rf %t
// Run Clang twice so we end up creating the timestamp file (the second time).
-// RUN: %clang_cc1 -DIMPORT_DEPENDS_ON_MODULE -fmodules-ignore-macro=DIMPORT_DEPENDS_ON_MODULE -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t %s -verify
-// RUN: %clang_cc1 -DIMPORT_DEPENDS_ON_MODULE -fmodules-ignore-macro=DIMPORT_DEPENDS_ON_MODULE -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t %s -verify
+// RUN: %clang_cc1 -DIMPORT_DEPENDS_ON_MODULE -Wno-private-module -fmodules-ignore-macro=DIMPORT_DEPENDS_ON_MODULE -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t %s -verify
+// RUN: %clang_cc1 -DIMPORT_DEPENDS_ON_MODULE -Wno-private-module -fmodules-ignore-macro=DIMPORT_DEPENDS_ON_MODULE -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t %s -verify
// RUN: ls %t | grep modules.timestamp
// RUN: ls -R %t | grep ^Module.*pcm
// RUN: ls -R %t | grep DependsOnModule.*pcm
@@ -17,7 +17,7 @@
// Set the timestamp back more than two days. We should try to prune,
// but nothing gets pruned because the module files are new enough.
// RUN: touch -m -a -t 201101010000 %t/modules.timestamp
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -Wno-private-module -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify
// RUN: ls %t | grep modules.timestamp
// RUN: ls -R %t | grep ^Module.*pcm
// RUN: ls -R %t | grep DependsOnModule.*pcm
@@ -26,7 +26,7 @@
// This shouldn't prune anything, because the timestamp has been updated, so
// the pruning mechanism won't fire.
// RUN: find %t -name DependsOnModule*.pcm | sed -e 's/\\/\//g' | xargs touch -a -t 201101010000
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -F %S/Inputs -Wno-private-module -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify
// RUN: ls %t | grep modules.timestamp
// RUN: ls -R %t | grep ^Module.*pcm
// RUN: ls -R %t | grep DependsOnModule.*pcm
@@ -35,7 +35,7 @@
// This should trigger pruning, which will remove DependsOnModule but not Module.
// RUN: touch -m -a -t 201101010000 %t/modules.timestamp
// RUN: find %t -name DependsOnModule*.pcm | sed -e 's/\\/\//g' | xargs touch -a -t 201101010000
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -F %S/Inputs -Wno-private-module -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify
// RUN: ls %t | grep modules.timestamp
// RUN: ls -R %t | grep ^Module.*pcm
// RUN: ls -R %t | not grep DependsOnModule.*pcm
diff --git a/test/Modules/redefinition-c-tagtypes.m b/test/Modules/redefinition-c-tagtypes.m
index a01f11bd74c8..eb469e00e16f 100644
--- a/test/Modules/redefinition-c-tagtypes.m
+++ b/test/Modules/redefinition-c-tagtypes.m
@@ -1,8 +1,8 @@
// RUN: rm -rf %t.cache
// RUN: %clang_cc1 -fsyntax-only %s -fmodules -fmodules-cache-path=%t.cache \
-// RUN: -fimplicit-module-maps -F%S/Inputs -verify
+// RUN: -fimplicit-module-maps -Wno-private-module -F%S/Inputs -verify
// RUN: %clang_cc1 -fsyntax-only %s -fmodules -fmodules-cache-path=%t.cache \
-// RUN: -fimplicit-module-maps -F%S/Inputs -DCHANGE_TAGS -verify
+// RUN: -fimplicit-module-maps -Wno-private-module -F%S/Inputs -DCHANGE_TAGS -verify
#include "F/F.h"
#ifndef CHANGE_TAGS
diff --git a/test/Modules/requires-coroutines.mm b/test/Modules/requires-coroutines.mm
index 8e25a3c57521..4e9c9d19cd80 100644
--- a/test/Modules/requires-coroutines.mm
+++ b/test/Modules/requires-coroutines.mm
@@ -1,6 +1,6 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify
-// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify -fcoroutines-ts -DCOROUTINES
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -Wno-private-module -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -Wno-private-module -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify -fcoroutines-ts -DCOROUTINES
#ifdef COROUTINES
@import DependsOnModule.Coroutines;
diff --git a/test/Modules/requires.m b/test/Modules/requires.m
index d61de6bd48d0..4a83d0c2b0ec 100644
--- a/test/Modules/requires.m
+++ b/test/Modules/requires.m
@@ -1,5 +1,5 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs %s -verify -fmodule-feature custom_req1
+// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs %s -verify -fmodule-feature custom_req1
// expected-error@DependsOnModule.framework/module.map:7 {{module 'DependsOnModule.CXX' requires feature 'cplusplus'}}
@import DependsOnModule.CXX; // expected-note {{module imported here}}
diff --git a/test/Modules/requires.mm b/test/Modules/requires.mm
index f90622ece842..b4237cbd7874 100644
--- a/test/Modules/requires.mm
+++ b/test/Modules/requires.mm
@@ -1,5 +1,5 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify
+// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify
@import DependsOnModule.CXX;
// expected-error@module.map:11 {{module 'DependsOnModule.NotCXX' is incompatible with feature 'cplusplus'}}
diff --git a/test/Modules/subframework-from-intermediate-path.m b/test/Modules/subframework-from-intermediate-path.m
index 394cc45f2f60..1543861ec4c8 100644
--- a/test/Modules/subframework-from-intermediate-path.m
+++ b/test/Modules/subframework-from-intermediate-path.m
@@ -1,5 +1,5 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -F %S/Inputs/DependsOnModule.framework/Frameworks %s -verify
+// RUN: %clang_cc1 -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -F %S/Inputs/DependsOnModule.framework/Frameworks %s -verify
@import DependsOnModule;
@import SubFramework; // expected-error{{module 'SubFramework' not found}}
diff --git a/test/Modules/subframeworks.m b/test/Modules/subframeworks.m
index 21081843d78c..ce35415717d2 100644
--- a/test/Modules/subframeworks.m
+++ b/test/Modules/subframeworks.m
@@ -1,6 +1,6 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -F %S/Inputs/DependsOnModule.framework/Frameworks %s -verify
-// RUN: %clang_cc1 -x objective-c++ -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -F %S/Inputs/DependsOnModule.framework/Frameworks %s -verify
+// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -F %S/Inputs/DependsOnModule.framework/Frameworks %s -verify
+// RUN: %clang_cc1 -x objective-c++ -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -F %S/Inputs/DependsOnModule.framework/Frameworks %s -verify
@import DependsOnModule;
diff --git a/test/OpenMP/dump.cpp b/test/OpenMP/dump.cpp
index 5ec202cc3040..222c83d5ce08 100644
--- a/test/OpenMP/dump.cpp
+++ b/test/OpenMP/dump.cpp
@@ -48,7 +48,7 @@ struct S {
// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:48> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &'
// CHECK-NEXT: | |-OMPSharedClause {{.+}} <col:51, col:61>
// CHECK-NEXT: | | `-MemberExpr {{.+}} <col:58> 'int' lvalue ->b
-// CHECK-NEXT: | | `-CXXThisExpr {{.+}} <col:58> 'struct S *' this
+// CHECK-NEXT: | | `-CXXThisExpr {{.+}} <col:58> 'S *' this
// CHECK-NEXT: | |-OMPScheduleClause {{.+}} <col:61, col:79>
// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:78> 'int' <LValueToRValue>
// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:78> 'int' lvalue OMPCapturedExpr {{.+}} '.capture_expr.' 'int'
@@ -62,7 +62,7 @@ struct S {
#pragma omp declare simd inbranch
void foo();
-// CHECK: `-FunctionDecl {{.+}} <line:63:1, col:10> col:6 foo 'void (void)'
+// CHECK: `-FunctionDecl {{.+}} <line:63:1, col:10> col:6 foo 'void ()'
// CHECK-NEXT: |-OMPDeclareSimdDeclAttr {{.+}} <line:62:9, col:34> Implicit BS_Inbranch
// CHECK: `-OMPDeclareSimdDeclAttr {{.+}} <line:61:9, col:25> Implicit BS_Undefined
diff --git a/test/OpenMP/parallel_for_codegen.cpp b/test/OpenMP/parallel_for_codegen.cpp
index 1773619bce20..db3a2de580d8 100644
--- a/test/OpenMP/parallel_for_codegen.cpp
+++ b/test/OpenMP/parallel_for_codegen.cpp
@@ -15,10 +15,12 @@ void with_var_schedule() {
double a = 5;
// CHECK: [[CHUNK_SIZE:%.+]] = fptosi double %{{.+}}to i8
// CHECK: store i8 %{{.+}}, i8* [[CHUNK:%.+]],
-// CHECK: call void {{.+}} @__kmpc_fork_call({{.+}}, i8* [[CHUNK]])
+// CHECK: [[VAL:%.+]] = load i8, i8* [[CHUNK]],
+// CHECK: store i8 [[VAL]], i8*
+// CHECK: [[CHUNK:%.+]] = load i64, i64* %
+// CHECK: call void {{.+}} @__kmpc_fork_call({{.+}}, i64 [[CHUNK]])
-// CHECK: [[CHUNK:%.+]] = load i8*, i8** %
-// CHECK: [[CHUNK_VAL:%.+]] = load i8, i8* [[CHUNK]],
+// CHECK: [[CHUNK_VAL:%.+]] = load i8, i8* %
// CHECK: [[CHUNK_SIZE:%.+]] = sext i8 [[CHUNK_VAL]] to i64
// CHECK: call void @__kmpc_for_static_init_8u([[IDENT_T_TY]]* [[LOOP_LOC]], i32 [[GTID:%[^,]+]], i32 33, i32* [[IS_LAST:%[^,]+]], i64* [[OMP_LB:%[^,]+]], i64* [[OMP_UB:%[^,]+]], i64* [[OMP_ST:%[^,]+]], i64 1, i64 [[CHUNK_SIZE]])
// CHECK: call void @__kmpc_for_static_fini([[IDENT_T_TY]]* [[LOOP_LOC]], i32 [[GTID]])
diff --git a/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
index 7c0ac461220d..304cc8b3f4aa 100644
--- a/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
@@ -60,8 +60,8 @@ int main() {
#pragma omp teams distribute parallel for num_threads(a)
for (int i = 0; i < 100; i++) {
// CHECK: define{{.+}} void [[OMP_TEAMS_OUTLINED_1]](
- // CHECK-DAG: [[A_ADDR:%.+]] = alloca i8*,
- // CHECK-DAG: [[A_REF:%.+]] = load i8*, i8** [[A_ADDR]],
+ // CHECK-DAG: [[A_ADDR:%.+]] = alloca i64,
+ // CHECK-DAG: [[A_REF:%.+]] = bitcast i64* [[A_ADDR]] to i8*
// CHECK-DAG: [[A_VAL:%.+]] = load i8, i8* [[A_REF]],
// CHECK-DAG: [[A_EXT:%.+]] = sext i8 [[A_VAL]] to {{.+}}
// CHECK: call {{.*}}void @__kmpc_push_num_threads([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 {{.+}}, i32 [[A_EXT]])
@@ -110,9 +110,9 @@ int main() {
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}}* [[T_OMP_TEAMS_OUTLINED_3:@.+]] to {{.+}})
// CHECK: define{{.+}} void [[T_OMP_TEAMS_OUTLINED_3]]({{.+}}, {{.+}}, {{.+}} [[NUM_TH_CPT_IN:%.+]])
-// CHECK: [[NUM_TH_CPT:%.+]] = alloca i8*,
+// CHECK: [[NUM_TH_CPT:%.+]] = alloca i64,
// CHECK: store {{.+}} [[NUM_TH_CPT_IN]], {{.+}} [[NUM_TH_CPT]],
-// CHECK: [[NUM_TH_REF:%.+]] = load{{.+}}, {{.+}} [[NUM_TH_CPT]],
+// CHECK: [[NUM_TH_REF:%.+]] = bitcast i64* [[NUM_TH_CPT]] to i8*
// CHECK-DAG: [[NUM_TH_VAL:%.+]] = load {{.+}}, {{.+}} [[NUM_TH_REF]],
// CHECK-DAG: [[NUM_TH_SEXT:%.+]] = sext i8 [[NUM_TH_VAL]] to {{.+}}
// CHECK: call {{.*}}void @__kmpc_push_num_threads([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 {{.+}}, i32 [[NUM_TH_SEXT]])
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
index 93051af6161b..2576241725ca 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
@@ -60,8 +60,8 @@ int main() {
#pragma omp teams distribute parallel for simd num_threads(a)
for (int i = 0; i < 100; i++) {
// CHECK: define{{.+}} void [[OMP_TEAMS_OUTLINED_1]](
- // CHECK-DAG: [[A_ADDR:%.+]] = alloca i8*,
- // CHECK-DAG: [[A_REF:%.+]] = load i8*, i8** [[A_ADDR]],
+ // CHECK-DAG: [[A_ADDR:%.+]] = alloca i64,
+ // CHECK-DAG: [[A_REF:%.+]] = bitcast i64* [[A_ADDR]] to i8*
// CHECK-DAG: [[A_VAL:%.+]] = load i8, i8* [[A_REF]],
// CHECK-DAG: [[A_EXT:%.+]] = sext i8 [[A_VAL]] to {{.+}}
// CHECK: call {{.*}}void @__kmpc_push_num_threads([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 {{.+}}, i32 [[A_EXT]])
@@ -110,9 +110,9 @@ int main() {
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 {{.+}}, {{.+}}* [[T_OMP_TEAMS_OUTLINED_3:@.+]] to {{.+}})
// CHECK: define{{.+}} void [[T_OMP_TEAMS_OUTLINED_3]]({{.+}}, {{.+}}, {{.+}} [[NUM_TH_CPT_IN:%.+]])
-// CHECK: [[NUM_TH_CPT:%.+]] = alloca i8*,
+// CHECK: [[NUM_TH_CPT:%.+]] = alloca i64,
// CHECK: store {{.+}} [[NUM_TH_CPT_IN]], {{.+}} [[NUM_TH_CPT]],
-// CHECK: [[NUM_TH_REF:%.+]] = load{{.+}}, {{.+}} [[NUM_TH_CPT]],
+// CHECK: [[NUM_TH_REF:%.+]] = bitcast i64* [[NUM_TH_CPT]] to i8*
// CHECK-DAG: [[NUM_TH_VAL:%.+]] = load {{.+}}, {{.+}} [[NUM_TH_REF]],
// CHECK-DAG: [[NUM_TH_SEXT:%.+]] = sext i8 [[NUM_TH_VAL]] to {{.+}}
// CHECK: call {{.*}}void @__kmpc_push_num_threads([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 {{.+}}, i32 [[NUM_TH_SEXT]])
diff --git a/test/Parser/cxx-decl.cpp b/test/Parser/cxx-decl.cpp
index 8a7a38860539..58ad08079c1d 100644
--- a/test/Parser/cxx-decl.cpp
+++ b/test/Parser/cxx-decl.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -pedantic-errors -fcxx-exceptions -fexceptions %s
-// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -pedantic-errors -fcxx-exceptions -fexceptions -std=c++98 %s
-// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -pedantic-errors -fcxx-exceptions -fexceptions -std=c++11 %s
+// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -Wredundant-parens -pedantic-errors -fcxx-exceptions -fexceptions %s
+// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -Wredundant-parens -pedantic-errors -fcxx-exceptions -fexceptions -std=c++98 %s
+// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -Wredundant-parens -pedantic-errors -fcxx-exceptions -fexceptions -std=c++11 %s
const char const *x10; // expected-error {{duplicate 'const' declaration specifier}}
@@ -83,7 +83,7 @@ namespace Commas {
int global1,
__attribute__(()) global2,
- (global5),
+ (global5), // expected-warning {{redundant parentheses surrounding declarator}}
*global6,
&global7 = global1,
&&global8 = static_cast<int&&>(global1),
@@ -263,6 +263,41 @@ namespace DuplicateFriend {
};
}
+namespace NNS {
+ struct A {};
+ namespace B { extern A C1, C2, *C3, C4[], C5; }
+ // Do not produce a redundant parentheses warning here; removing these parens
+ // changes the meaning of the program.
+ A (::NNS::B::C1);
+ A (NNS::B::C2); // expected-warning {{redundant parentheses surrounding declarator}}
+ A (*::NNS::B::C3); // expected-warning {{redundant parentheses surrounding declarator}}
+ A (::NNS::B::C4[2]);
+ // Removing one of these sets of parentheses would be reasonable.
+ A ((::NNS::B::C5)); // expected-warning {{redundant parentheses surrounding declarator}}
+
+ void f() {
+ // FIXME: A vexing-parse warning here would be useful.
+ A(::NNS::B::C1); // expected-error {{definition or redeclaration}}
+ A(NNS::B::C1); // expected-warning {{redundant paren}} expected-error {{definition or redeclaration}}
+ }
+}
+
+inline namespace ParensAroundFriend { // expected-error 0-1{{C++11}}
+ struct A {};
+ struct B {
+ static A C();
+ };
+ namespace X {
+ struct B {};
+ struct D {
+ // No warning here: while this could be written as
+ // friend (::B::C)();
+ // we do need parentheses *somewhere* here.
+ friend A (::B::C());
+ };
+ }
+}
+
// PR8380
extern "" // expected-error {{unknown linkage language}}
test6a { ;// expected-error {{C++ requires a type specifier for all declarations}}
diff --git a/test/Parser/objc-default-ctor-init.mm b/test/Parser/objc-default-ctor-init.mm
index ea4c064d7791..a14a243a31cc 100644
--- a/test/Parser/objc-default-ctor-init.mm
+++ b/test/Parser/objc-default-ctor-init.mm
@@ -1,21 +1,21 @@
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -std=c++11 -ast-dump %s | FileCheck %s
-// CHECK: CXXCtorInitializer Field {{.*}} 'ptr' 'void *'
-// CHECK: CXXCtorInitializer Field {{.*}} 'q' 'struct Q'
-
-@interface NSObject
-@end
-
-@interface I : NSObject
-@end
-
-struct Q { Q(); };
-
-struct S {
- S();
- void *ptr = nullptr;
- Q q;
-};
-
-@implementation I
-S::S() {}
-@end
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -std=c++11 -ast-dump %s | FileCheck %s
+// CHECK: CXXCtorInitializer Field {{.*}} 'ptr' 'void *'
+// CHECK: CXXCtorInitializer Field {{.*}} 'q' 'Q'
+
+@interface NSObject
+@end
+
+@interface I : NSObject
+@end
+
+struct Q { Q(); };
+
+struct S {
+ S();
+ void *ptr = nullptr;
+ Q q;
+};
+
+@implementation I
+S::S() {}
+@end
diff --git a/test/Preprocessor/predefined-arch-macros.c b/test/Preprocessor/predefined-arch-macros.c
index 892e2783942e..f370f3e5f077 100644
--- a/test/Preprocessor/predefined-arch-macros.c
+++ b/test/Preprocessor/predefined-arch-macros.c
@@ -589,6 +589,7 @@
// CHECK_BROADWELL_M32: #define __MMX__ 1
// CHECK_BROADWELL_M32: #define __PCLMUL__ 1
// CHECK_BROADWELL_M32: #define __POPCNT__ 1
+// CHECK_BROADWELL_M32: #define __PRFCHW__ 1
// CHECK_BROADWELL_M32: #define __RDRND__ 1
// CHECK_BROADWELL_M32: #define __RDSEED__ 1
// CHECK_BROADWELL_M32: #define __SSE2__ 1
@@ -620,6 +621,7 @@
// CHECK_BROADWELL_M64: #define __MMX__ 1
// CHECK_BROADWELL_M64: #define __PCLMUL__ 1
// CHECK_BROADWELL_M64: #define __POPCNT__ 1
+// CHECK_BROADWELL_M64: #define __PRFCHW__ 1
// CHECK_BROADWELL_M64: #define __RDRND__ 1
// CHECK_BROADWELL_M64: #define __RDSEED__ 1
// CHECK_BROADWELL_M64: #define __SSE2_MATH__ 1
@@ -657,6 +659,7 @@
// CHECK_SKL_M32: #define __MPX__ 1
// CHECK_SKL_M32: #define __PCLMUL__ 1
// CHECK_SKL_M32: #define __POPCNT__ 1
+// CHECK_SKL_M32: #define __PRFCHW__ 1
// CHECK_SKL_M32: #define __RDRND__ 1
// CHECK_SKL_M32: #define __RDSEED__ 1
// CHECK_SKL_M32: #define __RTM__ 1
@@ -690,6 +693,7 @@
// CHECK_SKL_M64: #define __MPX__ 1
// CHECK_SKL_M64: #define __PCLMUL__ 1
// CHECK_SKL_M64: #define __POPCNT__ 1
+// CHECK_SKL_M64: #define __PRFCHW__ 1
// CHECK_SKL_M64: #define __RDRND__ 1
// CHECK_SKL_M64: #define __RDSEED__ 1
// CHECK_SKL_M64: #define __RTM__ 1
@@ -730,6 +734,7 @@
// CHECK_KNL_M32: #define __PCLMUL__ 1
// CHECK_KNL_M32: #define __POPCNT__ 1
// CHECK_KNL_M32: #define __PREFETCHWT1__ 1
+// CHECK_KNL_M32: #define __PRFCHW__ 1
// CHECK_KNL_M32: #define __RDRND__ 1
// CHECK_KNL_M32: #define __RTM__ 1
// CHECK_KNL_M32: #define __SSE2__ 1
@@ -766,6 +771,7 @@
// CHECK_KNL_M64: #define __PCLMUL__ 1
// CHECK_KNL_M64: #define __POPCNT__ 1
// CHECK_KNL_M64: #define __PREFETCHWT1__ 1
+// CHECK_KNL_M64: #define __PRFCHW__ 1
// CHECK_KNL_M64: #define __RDRND__ 1
// CHECK_KNL_M64: #define __RTM__ 1
// CHECK_KNL_M64: #define __SSE2_MATH__ 1
@@ -806,6 +812,7 @@
// CHECK_KNM_M32: #define __PCLMUL__ 1
// CHECK_KNM_M32: #define __POPCNT__ 1
// CHECK_KNM_M32: #define __PREFETCHWT1__ 1
+// CHECK_KNM_M32: #define __PRFCHW__ 1
// CHECK_KNM_M32: #define __RDRND__ 1
// CHECK_KNM_M32: #define __RTM__ 1
// CHECK_KNM_M32: #define __SSE2__ 1
@@ -840,6 +847,7 @@
// CHECK_KNM_M64: #define __PCLMUL__ 1
// CHECK_KNM_M64: #define __POPCNT__ 1
// CHECK_KNM_M64: #define __PREFETCHWT1__ 1
+// CHECK_KNM_M64: #define __PRFCHW__ 1
// CHECK_KNM_M64: #define __RDRND__ 1
// CHECK_KNM_M64: #define __RTM__ 1
// CHECK_KNM_M64: #define __SSE2_MATH__ 1
@@ -879,6 +887,7 @@
// CHECK_SKX_M32: #define __MPX__ 1
// CHECK_SKX_M32: #define __PCLMUL__ 1
// CHECK_SKX_M32: #define __POPCNT__ 1
+// CHECK_SKX_M32: #define __PRFCHW__ 1
// CHECK_SKX_M32: #define __RDRND__ 1
// CHECK_SKX_M32: #define __RTM__ 1
// CHECK_SKX_M32: #define __SGX__ 1
@@ -921,6 +930,7 @@
// CHECK_SKX_M64: #define __MPX__ 1
// CHECK_SKX_M64: #define __PCLMUL__ 1
// CHECK_SKX_M64: #define __POPCNT__ 1
+// CHECK_SKX_M64: #define __PRFCHW__ 1
// CHECK_SKX_M64: #define __RDRND__ 1
// CHECK_SKX_M64: #define __RTM__ 1
// CHECK_SKX_M64: #define __SGX__ 1
@@ -967,6 +977,7 @@
// CHECK_CNL_M32: #define __MPX__ 1
// CHECK_CNL_M32: #define __PCLMUL__ 1
// CHECK_CNL_M32: #define __POPCNT__ 1
+// CHECK_CNL_M32: #define __PRFCHW__ 1
// CHECK_CNL_M32: #define __RDRND__ 1
// CHECK_CNL_M32: #define __RTM__ 1
// CHECK_CNL_M32: #define __SGX__ 1
@@ -1011,6 +1022,7 @@
// CHECK_CNL_M64: #define __MPX__ 1
// CHECK_CNL_M64: #define __PCLMUL__ 1
// CHECK_CNL_M64: #define __POPCNT__ 1
+// CHECK_CNL_M64: #define __PRFCHW__ 1
// CHECK_CNL_M64: #define __RDRND__ 1
// CHECK_CNL_M64: #define __RTM__ 1
// CHECK_CNL_M64: #define __SGX__ 1
@@ -1056,6 +1068,7 @@
// CHECK_ICL_M32: #define __MPX__ 1
// CHECK_ICL_M32: #define __PCLMUL__ 1
// CHECK_ICL_M32: #define __POPCNT__ 1
+// CHECK_ICL_M32: #define __PRFCHW__ 1
// CHECK_ICL_M32: #define __RDRND__ 1
// CHECK_ICL_M32: #define __RTM__ 1
// CHECK_ICL_M32: #define __SGX__ 1
@@ -1100,6 +1113,7 @@
// CHECK_ICL_M64: #define __MPX__ 1
// CHECK_ICL_M64: #define __PCLMUL__ 1
// CHECK_ICL_M64: #define __POPCNT__ 1
+// CHECK_ICL_M64: #define __PRFCHW__ 1
// CHECK_ICL_M64: #define __RDRND__ 1
// CHECK_ICL_M64: #define __RTM__ 1
// CHECK_ICL_M64: #define __SGX__ 1
@@ -1165,6 +1179,7 @@
// CHECK_GLM_M32: #define __MPX__ 1
// CHECK_GLM_M32: #define __PCLMUL__ 1
// CHECK_GLM_M32: #define __POPCNT__ 1
+// CHECK_GLM_M32: #define __PRFCHW__ 1
// CHECK_GLM_M32: #define __RDRND__ 1
// CHECK_GLM_M32: #define __RDSEED__ 1
// CHECK_GLM_M32: #define __SHA__ 1
@@ -1197,6 +1212,7 @@
// CHECK_GLM_M64: #define __MPX__ 1
// CHECK_GLM_M64: #define __PCLMUL__ 1
// CHECK_GLM_M64: #define __POPCNT__ 1
+// CHECK_GLM_M64: #define __PRFCHW__ 1
// CHECK_GLM_M64: #define __RDRND__ 1
// CHECK_GLM_M64: #define __RDSEED__ 1
// CHECK_GLM_M64: #define __SSE2__ 1
@@ -1218,7 +1234,12 @@
// RUN: %clang -march=slm -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SLM_M32
+// CHECK_SLM_M32: #define __AES__ 1
+// CHECK_SLM_M32: #define __FXSR__ 1
// CHECK_SLM_M32: #define __MMX__ 1
+// CHECK_SLM_M32: #define __PCLMUL__ 1
+// CHECK_SLM_M32: #define __POPCNT__ 1
+// CHECK_SLM_M32: #define __PRFCHW__ 1
// CHECK_SLM_M32: #define __SSE2__ 1
// CHECK_SLM_M32: #define __SSE3__ 1
// CHECK_SLM_M32: #define __SSE4_1__ 1
@@ -1234,7 +1255,12 @@
// RUN: %clang -march=slm -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SLM_M64
+// CHECK_SLM_M64: #define __AES__ 1
+// CHECK_SLM_M64: #define __FXSR__ 1
// CHECK_SLM_M64: #define __MMX__ 1
+// CHECK_SLM_M64: #define __PCLMUL__ 1
+// CHECK_SLM_M64: #define __POPCNT__ 1
+// CHECK_SLM_M64: #define __PRFCHW__ 1
// CHECK_SLM_M64: #define __SSE2_MATH__ 1
// CHECK_SLM_M64: #define __SSE2__ 1
// CHECK_SLM_M64: #define __SSE3__ 1
diff --git a/test/Sema/attr-ifunc.c b/test/Sema/attr-ifunc.c
index 8f9c22f84927..16fd0dfc9820 100644
--- a/test/Sema/attr-ifunc.c
+++ b/test/Sema/attr-ifunc.c
@@ -5,7 +5,7 @@
#if defined(_WIN32)
void foo() {}
void bar() __attribute__((ifunc("foo")));
-//expected-warning@-1 {{'ifunc' attribute ignored}}
+//expected-warning@-1 {{unknown attribute 'ifunc' ignored}}
#else
#if defined(CHECK_ALIASES)
diff --git a/test/Sema/builtin-object-size.c b/test/Sema/builtin-object-size.c
index 300c739bbd14..096882a088c0 100644
--- a/test/Sema/builtin-object-size.c
+++ b/test/Sema/builtin-object-size.c
@@ -91,3 +91,22 @@ int pr31843() {
return n;
}
+
+typedef struct {
+ char string[512];
+} NestedArrayStruct;
+
+typedef struct {
+ int x;
+ NestedArrayStruct session[];
+} IncompleteArrayStruct;
+
+void rd36094951_IAS_builtin_object_size_assertion(IncompleteArrayStruct *p) {
+#define rd36094951_CHECK(mode) \
+ __builtin___strlcpy_chk(p->session[0].string, "ab", 2, \
+ __builtin_object_size(p->session[0].string, mode))
+ rd36094951_CHECK(0);
+ rd36094951_CHECK(1);
+ rd36094951_CHECK(2);
+ rd36094951_CHECK(3);
+}
diff --git a/test/SemaCXX/compound-literal.cpp b/test/SemaCXX/compound-literal.cpp
index 5480b1fef44d..be9ebee00c2f 100644
--- a/test/SemaCXX/compound-literal.cpp
+++ b/test/SemaCXX/compound-literal.cpp
@@ -1,98 +1,98 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c++03 -verify -ast-dump %s > %t-03
-// RUN: FileCheck --input-file=%t-03 %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -ast-dump %s > %t-11
-// RUN: FileCheck --input-file=%t-11 %s
-// RUN: FileCheck --input-file=%t-11 %s --check-prefix=CHECK-CXX11
-
-// http://llvm.org/PR7905
-namespace PR7905 {
-struct S; // expected-note {{forward declaration}}
-void foo1() {
- (void)(S[]) {{3}}; // expected-error {{array has incomplete element type}}
-}
-
-template <typename T> struct M { T m; };
-void foo2() {
- (void)(M<short> []) {{3}};
-}
-}
-
-// Check compound literals mixed with C++11 list-initialization.
-namespace brace_initializers {
- struct POD {
- int x, y;
- };
- struct HasCtor {
- HasCtor(int x, int y);
- };
- struct HasDtor {
- int x, y;
- ~HasDtor();
- };
- struct HasCtorDtor {
- HasCtorDtor(int x, int y);
- ~HasCtorDtor();
- };
-
- void test() {
- (void)(POD){1, 2};
- // CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::POD'
- // CHECK: CompoundLiteralExpr {{.*}} 'struct brace_initializers::POD'
- // CHECK-NEXT: InitListExpr {{.*}} 'struct brace_initializers::POD'
- // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
- // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
-
- (void)(HasDtor){1, 2};
- // CHECK: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::HasDtor'
- // CHECK-NEXT: CompoundLiteralExpr {{.*}} 'struct brace_initializers::HasDtor'
- // CHECK-NEXT: InitListExpr {{.*}} 'struct brace_initializers::HasDtor'
- // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
- // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
-
-#if __cplusplus >= 201103L
- (void)(HasCtor){1, 2};
- // CHECK-CXX11-NOT: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::HasCtor'
- // CHECK-CXX11: CompoundLiteralExpr {{.*}} 'struct brace_initializers::HasCtor'
- // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'struct brace_initializers::HasCtor'
- // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
- // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}
-
- (void)(HasCtorDtor){1, 2};
- // CHECK-CXX11: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::HasCtorDtor'
- // CHECK-CXX11-NEXT: CompoundLiteralExpr {{.*}} 'struct brace_initializers::HasCtorDtor'
- // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'struct brace_initializers::HasCtorDtor'
- // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
- // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}
-#endif
- }
-
- struct PrivateDtor {
- int x, y;
- private:
- ~PrivateDtor(); // expected-note {{declared private here}}
- };
-
- void testPrivateDtor() {
- (void)(PrivateDtor){1, 2}; // expected-error {{temporary of type 'brace_initializers::PrivateDtor' has private destructor}}
- }
-}
-
-// This doesn't necessarily need to be an error, but CodeGen can't handle it
-// at the moment.
-int PR17415 = (int){PR17415}; // expected-error {{initializer element is not a compile-time constant}}
-
-// Make sure we accept this. (Not sure if we actually should... but we do
-// at the moment.)
-template<unsigned> struct Value { };
-template<typename T>
-int &check_narrowed(Value<sizeof((T){1.1})>);
-
-#if __cplusplus >= 201103L
-// Compound literals in global lambdas have automatic storage duration
-// and are not subject to the constant-initialization rules.
-int computed_with_lambda = [] {
- int x = 5;
- int result = ((int[]) { x, x + 2, x + 4, x + 6 })[0];
- return result;
-}();
-#endif
+// RUN: %clang_cc1 -fsyntax-only -std=c++03 -verify -ast-dump %s > %t-03
+// RUN: FileCheck --input-file=%t-03 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -ast-dump %s > %t-11
+// RUN: FileCheck --input-file=%t-11 %s
+// RUN: FileCheck --input-file=%t-11 %s --check-prefix=CHECK-CXX11
+
+// http://llvm.org/PR7905
+namespace PR7905 {
+struct S; // expected-note {{forward declaration}}
+void foo1() {
+ (void)(S[]) {{3}}; // expected-error {{array has incomplete element type}}
+}
+
+template <typename T> struct M { T m; };
+void foo2() {
+ (void)(M<short> []) {{3}};
+}
+}
+
+// Check compound literals mixed with C++11 list-initialization.
+namespace brace_initializers {
+ struct POD {
+ int x, y;
+ };
+ struct HasCtor {
+ HasCtor(int x, int y);
+ };
+ struct HasDtor {
+ int x, y;
+ ~HasDtor();
+ };
+ struct HasCtorDtor {
+ HasCtorDtor(int x, int y);
+ ~HasCtorDtor();
+ };
+
+ void test() {
+ (void)(POD){1, 2};
+ // CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::POD'
+ // CHECK: CompoundLiteralExpr {{.*}} 'brace_initializers::POD'
+ // CHECK-NEXT: InitListExpr {{.*}} 'brace_initializers::POD'
+ // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
+
+ (void)(HasDtor){1, 2};
+ // CHECK: CXXBindTemporaryExpr {{.*}} 'brace_initializers::HasDtor'
+ // CHECK-NEXT: CompoundLiteralExpr {{.*}} 'brace_initializers::HasDtor'
+ // CHECK-NEXT: InitListExpr {{.*}} 'brace_initializers::HasDtor'
+ // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
+
+#if __cplusplus >= 201103L
+ (void)(HasCtor){1, 2};
+ // CHECK-CXX11-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::HasCtor'
+ // CHECK-CXX11: CompoundLiteralExpr {{.*}} 'brace_initializers::HasCtor'
+ // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'brace_initializers::HasCtor'
+ // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}
+
+ (void)(HasCtorDtor){1, 2};
+ // CHECK-CXX11: CXXBindTemporaryExpr {{.*}} 'brace_initializers::HasCtorDtor'
+ // CHECK-CXX11-NEXT: CompoundLiteralExpr {{.*}} 'brace_initializers::HasCtorDtor'
+ // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'brace_initializers::HasCtorDtor'
+ // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}
+#endif
+ }
+
+ struct PrivateDtor {
+ int x, y;
+ private:
+ ~PrivateDtor(); // expected-note {{declared private here}}
+ };
+
+ void testPrivateDtor() {
+ (void)(PrivateDtor){1, 2}; // expected-error {{temporary of type 'brace_initializers::PrivateDtor' has private destructor}}
+ }
+}
+
+// This doesn't necessarily need to be an error, but CodeGen can't handle it
+// at the moment.
+int PR17415 = (int){PR17415}; // expected-error {{initializer element is not a compile-time constant}}
+
+// Make sure we accept this. (Not sure if we actually should... but we do
+// at the moment.)
+template<unsigned> struct Value { };
+template<typename T>
+int &check_narrowed(Value<sizeof((T){1.1})>);
+
+#if __cplusplus >= 201103L
+// Compound literals in global lambdas have automatic storage duration
+// and are not subject to the constant-initialization rules.
+int computed_with_lambda = [] {
+ int x = 5;
+ int result = ((int[]) { x, x + 2, x + 4, x + 6 })[0];
+ return result;
+}();
+#endif
diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp
index 1e31d701d0c1..b77e226b5d01 100644
--- a/test/SemaCXX/decl-expr-ambiguity.cpp
+++ b/test/SemaCXX/decl-expr-ambiguity.cpp
@@ -125,3 +125,20 @@ void fizbin() {
baz b3; // expected-error {{must use 'class' tag to refer to type 'baz' in this scope}}
}
}
+
+namespace TemporaryFromFunctionCall {
+ struct A {
+ A(int);
+ };
+ int f();
+ int g(int);
+ namespace N {
+ void x() {
+ // FIXME: For the first and second of these (but not the third), we
+ // should produce a vexing-parse warning.
+ A(f());
+ A(g(int()));
+ A(g(int));
+ }
+ }
+}
diff --git a/test/SemaCXX/return-noreturn.cpp b/test/SemaCXX/return-noreturn.cpp
index cdd96e6a9ec4..cfeddffb664e 100644
--- a/test/SemaCXX/return-noreturn.cpp
+++ b/test/SemaCXX/return-noreturn.cpp
@@ -143,7 +143,7 @@ template <PR9412_MatchType type> int PR9412_t() {
} // expected-warning {{control reaches end of non-void function}}
void PR9412_f() {
- PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<PR9412_MatchType::PR9412_Exact>' requested here}}
+ PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<PR9412_Exact>' requested here}}
}
struct NoReturn {
diff --git a/test/SemaCXX/sourceranges.cpp b/test/SemaCXX/sourceranges.cpp
index 2f8eb2f2b96c..287925f7ffd7 100644
--- a/test/SemaCXX/sourceranges.cpp
+++ b/test/SemaCXX/sourceranges.cpp
@@ -1,52 +1,52 @@
-// RUN: %clang_cc1 -triple i686-mingw32 -ast-dump %s | FileCheck %s
-
-template<class T>
-class P {
- public:
- P(T* t) {}
-};
-
-namespace foo {
-class A { public: A(int = 0) {} };
-enum B {};
-typedef int C;
-}
-
-// CHECK: VarDecl {{0x[0-9a-fA-F]+}} <line:16:1, col:36> col:15 ImplicitConstrArray 'foo::A [2]'
-static foo::A ImplicitConstrArray[2];
-
-int main() {
- // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::A *'
- P<foo::A> p14 = new foo::A;
- // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::B *'
- P<foo::B> p24 = new foo::B;
- // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::C *'
- P<foo::C> pr4 = new foo::C;
-}
-
-foo::A getName() {
- // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:10, col:17> 'foo::A'
- return foo::A();
-}
-
-void destruct(foo::A *a1, foo::A *a2, P<int> *p1) {
- // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:8> '<bound member function type>' ->~A
- a1->~A();
- // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:16> '<bound member function type>' ->~A
- a2->foo::A::~A();
- // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:13> '<bound member function type>' ->~P
- p1->~P<int>();
-}
-
-struct D {
- D(int);
- ~D();
-};
-
-void construct() {
- using namespace foo;
- A a = A(12);
- // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:9, col:13> 'class foo::A' 'void (int){{( __attribute__\(\(thiscall\)\))?}}'
- D d = D(12);
- // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:9, col:13> 'struct D' 'void (int){{( __attribute__\(\(thiscall\)\))?}}'
-}
+// RUN: %clang_cc1 -triple i686-mingw32 -ast-dump %s | FileCheck %s
+
+template<class T>
+class P {
+ public:
+ P(T* t) {}
+};
+
+namespace foo {
+class A { public: A(int = 0) {} };
+enum B {};
+typedef int C;
+}
+
+// CHECK: VarDecl {{0x[0-9a-fA-F]+}} <line:16:1, col:36> col:15 ImplicitConstrArray 'foo::A [2]'
+static foo::A ImplicitConstrArray[2];
+
+int main() {
+ // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::A *'
+ P<foo::A> p14 = new foo::A;
+ // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::B *'
+ P<foo::B> p24 = new foo::B;
+ // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::C *'
+ P<foo::C> pr4 = new foo::C;
+}
+
+foo::A getName() {
+ // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:10, col:17> 'foo::A'
+ return foo::A();
+}
+
+void destruct(foo::A *a1, foo::A *a2, P<int> *p1) {
+ // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:8> '<bound member function type>' ->~A
+ a1->~A();
+ // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:16> '<bound member function type>' ->~A
+ a2->foo::A::~A();
+ // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:13> '<bound member function type>' ->~P
+ p1->~P<int>();
+}
+
+struct D {
+ D(int);
+ ~D();
+};
+
+void construct() {
+ using namespace foo;
+ A a = A(12);
+ // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:9, col:13> 'foo::A' 'void (int){{( __attribute__\(\(thiscall\)\))?}}'
+ D d = D(12);
+ // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:9, col:13> 'D' 'void (int){{( __attribute__\(\(thiscall\)\))?}}'
+}
diff --git a/test/SemaCXX/warn-redundant-move.cpp b/test/SemaCXX/warn-redundant-move.cpp
index abfb001fa8e6..97f4a7c37baa 100644
--- a/test/SemaCXX/warn-redundant-move.cpp
+++ b/test/SemaCXX/warn-redundant-move.cpp
@@ -75,7 +75,7 @@ D test5(D d) {
return d;
// Verify the implicit move from the AST dump
// CHECK-AST: ReturnStmt{{.*}}line:[[@LINE-2]]
- // CHECK-AST-NEXT: CXXConstructExpr{{.*}}struct D{{.*}}void (struct D &&)
+ // CHECK-AST-NEXT: CXXConstructExpr{{.*}}D{{.*}}void (D &&)
// CHECK-AST-NEXT: ImplicitCastExpr
// CHECK-AST-NEXT: DeclRefExpr{{.*}}ParmVar{{.*}}'d'
diff --git a/test/SemaObjCXX/block-cleanup.mm b/test/SemaObjCXX/block-cleanup.mm
index 0c6a6d8c26fa..53b2c224ab5e 100644
--- a/test/SemaObjCXX/block-cleanup.mm
+++ b/test/SemaObjCXX/block-cleanup.mm
@@ -1,16 +1,16 @@
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.11.0 -std=gnu++11 -o /dev/null -x objective-c++ -fblocks -ast-dump %s 2>&1 | FileCheck %s
-
-// CHECK: -FunctionDecl {{.*}} test 'id (void)'
-// CHECK-NEXT: -CompoundStmt
-// CHECK-NEXT: -ReturnStmt
-// CHECK-NEXT: -ExprWithCleanups
-// CHECK-NEXT: -cleanup Block
-// CHECK-NEXT: -cleanup Block
-
-@interface NSDictionary
-+ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
-@end
-
-id test() {
- return @{@"a": [](){}, @"b": [](){}};
-}
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.11.0 -std=gnu++11 -o /dev/null -x objective-c++ -fblocks -ast-dump %s 2>&1 | FileCheck %s
+
+// CHECK: -FunctionDecl {{.*}} test 'id ()'
+// CHECK-NEXT: -CompoundStmt
+// CHECK-NEXT: -ReturnStmt
+// CHECK-NEXT: -ExprWithCleanups
+// CHECK-NEXT: -cleanup Block
+// CHECK-NEXT: -cleanup Block
+
+@interface NSDictionary
++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
+@end
+
+id test() {
+ return @{@"a": [](){}, @"b": [](){}};
+}
diff --git a/test/SemaTemplate/default-expr-arguments-2.cpp b/test/SemaTemplate/default-expr-arguments-2.cpp
index 037949455f53..bfe87a931b95 100644
--- a/test/SemaTemplate/default-expr-arguments-2.cpp
+++ b/test/SemaTemplate/default-expr-arguments-2.cpp
@@ -9,8 +9,8 @@ namespace PR6733 {
public: enum { kSomeConst = 128 };
bar(int x = kSomeConst) {}
};
-
- // CHECK: FunctionDecl{{.*}}f 'void (void)'
+
+ // CHECK: FunctionDecl{{.*}}f 'void ()'
void f() {
// CHECK: VarDecl{{.*}}tmp 'bar<int>'
// CHECK: CXXDefaultArgExpr{{.*}}'int'
diff --git a/test/SemaTemplate/default-expr-arguments-3.cpp b/test/SemaTemplate/default-expr-arguments-3.cpp
index 4449eb7100aa..09fb7b290a1a 100644
--- a/test/SemaTemplate/default-expr-arguments-3.cpp
+++ b/test/SemaTemplate/default-expr-arguments-3.cpp
@@ -1,11 +1,11 @@
// RUN: %clang_cc1 -std=c++14 -verify -ast-dump %s | FileCheck %s
// expected-no-diagnostics
-// CHECK: FunctionDecl {{.*}} used func 'void (void)'
+// CHECK: FunctionDecl {{.*}} used func 'void ()'
// CHECK-NEXT: TemplateArgument type 'int'
-// CHECK: LambdaExpr {{.*}} 'class (lambda at
-// CHECK: ParmVarDecl {{.*}} used f 'enum foo' cinit
-// CHECK-NEXT: DeclRefExpr {{.*}} 'enum foo' EnumConstant {{.*}} 'a' 'enum foo'
+// CHECK: LambdaExpr {{.*}} '(lambda at
+// CHECK: ParmVarDecl {{.*}} used f 'foo' cinit
+// CHECK-NEXT: DeclRefExpr {{.*}} 'foo' EnumConstant {{.*}} 'a' 'foo'
namespace PR28795 {
template<typename T>
@@ -22,9 +22,9 @@ namespace PR28795 {
// CHECK: ClassTemplateSpecializationDecl {{.*}} struct class2 definition
// CHECK: TemplateArgument type 'int'
-// CHECK: LambdaExpr {{.*}} 'class (lambda at
-// CHECK: ParmVarDecl {{.*}} used f 'enum foo' cinit
-// CHECK-NEXT: DeclRefExpr {{.*}} 'enum foo' EnumConstant {{.*}} 'a' 'enum foo'
+// CHECK: LambdaExpr {{.*}} '(lambda at
+// CHECK: ParmVarDecl {{.*}} used f 'foo' cinit
+// CHECK-NEXT: DeclRefExpr {{.*}} 'foo' EnumConstant {{.*}} 'a' 'foo'
// Template struct case:
template <class T> struct class2 {
@@ -38,11 +38,11 @@ template struct class2<int>;
// CHECK: FunctionTemplateDecl {{.*}} f1
// CHECK-NEXT: TemplateTypeParmDecl {{.*}} typename depth 0 index 0 T
-// CHECK-NEXT: FunctionDecl {{.*}} f1 'void (void)'
-// CHECK: FunctionDecl {{.*}} f1 'void (void)'
+// CHECK-NEXT: FunctionDecl {{.*}} f1 'void ()'
+// CHECK: FunctionDecl {{.*}} f1 'void ()'
// CHECK-NEXT: TemplateArgument type 'int'
-// CHECK: ParmVarDecl {{.*}} n 'enum foo' cinit
-// CHECK-NEXT: DeclRefExpr {{.*}} 'enum foo' EnumConstant {{.*}} 'a' 'enum foo'
+// CHECK: ParmVarDecl {{.*}} n 'foo' cinit
+// CHECK-NEXT: DeclRefExpr {{.*}} 'foo' EnumConstant {{.*}} 'a' 'foo'
template<typename T>
void f1() {
diff --git a/test/SemaTemplate/nested-deduction-guides.cpp b/test/SemaTemplate/nested-deduction-guides.cpp
new file mode 100644
index 000000000000..2c5dda456a13
--- /dev/null
+++ b/test/SemaTemplate/nested-deduction-guides.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++17 -verify %s
+// expected-no-diagnostics
+
+template<typename T> struct A {
+ template<typename U> struct B {
+ B(...);
+ };
+ template<typename U> B(U) -> B<U>;
+};
+A<void>::B b = 123;
+
+using T = decltype(b);
+using T = A<void>::B<int>;
diff --git a/test/SemaTemplate/temp_arg_enum_printing.cpp b/test/SemaTemplate/temp_arg_enum_printing.cpp
index bdf277d308c3..dbb4db81f67a 100644
--- a/test/SemaTemplate/temp_arg_enum_printing.cpp
+++ b/test/SemaTemplate/temp_arg_enum_printing.cpp
@@ -13,9 +13,9 @@ template <NamedEnum E>
void foo();
void test() {
- // CHECK: template<> void foo<NamedEnumNS::NamedEnum::Val0>()
+ // CHECK: template<> void foo<NamedEnumNS::Val0>()
NamedEnumNS::foo<Val0>();
- // CHECK: template<> void foo<NamedEnumNS::NamedEnum::Val1>()
+ // CHECK: template<> void foo<NamedEnumNS::Val1>()
NamedEnumNS::foo<(NamedEnum)1>();
// CHECK: template<> void foo<2>()
NamedEnumNS::foo<(NamedEnum)2>();
diff --git a/test/SemaTemplate/temp_arg_enum_printing_more.cpp b/test/SemaTemplate/temp_arg_enum_printing_more.cpp
new file mode 100644
index 000000000000..a3a7158412e4
--- /dev/null
+++ b/test/SemaTemplate/temp_arg_enum_printing_more.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -ast-print %s -std=c++11 | FileCheck %s
+
+// Make sure that for template value arguments that are unscoped enumerators,
+// no qualified enum information is included in their name, as their visibility
+// is global. In the case of scoped enumerators, they must include information
+// about their enum enclosing scope.
+
+enum E1 { e1 };
+template<E1 v> struct tmpl_1 {};
+// CHECK: template<> struct tmpl_1<e1>
+tmpl_1<E1::e1> TMPL_1; // Name must be 'e1'.
+
+namespace nsp_1 { enum E2 { e2 }; }
+template<nsp_1::E2 v> struct tmpl_2 {};
+// CHECK: template<> struct tmpl_2<nsp_1::e2>
+tmpl_2<nsp_1::E2::e2> TMPL_2; // Name must be 'nsp_1::e2'.
+
+enum class E3 { e3 };
+template<E3 v> struct tmpl_3 {};
+// CHECK: template<> struct tmpl_3<E3::e3>
+tmpl_3<E3::e3> TMPL_3; // Name must be 'E3::e3'.
+
+namespace nsp_2 { enum class E4 { e4 }; }
+template<nsp_2::E4 v> struct tmpl_4 {};
+// CHECK: template<> struct tmpl_4<nsp_2::E4::e4>
+tmpl_4<nsp_2::E4::e4> TMPL_4; // Name must be 'nsp_2::E4::e4'.
diff --git a/tools/libclang/CXIndexDataConsumer.cpp b/tools/libclang/CXIndexDataConsumer.cpp
index ffe5c486ddda..89ac23be7344 100644
--- a/tools/libclang/CXIndexDataConsumer.cpp
+++ b/tools/libclang/CXIndexDataConsumer.cpp
@@ -1304,11 +1304,11 @@ static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage
static CXIdxEntityCXXTemplateKind
getEntityKindFromSymbolProperties(SymbolPropertySet K) {
- if (K & (unsigned)SymbolProperty::TemplatePartialSpecialization)
+ if (K & (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization)
return CXIdxEntity_TemplatePartialSpecialization;
- if (K & (unsigned)SymbolProperty::TemplateSpecialization)
+ if (K & (SymbolPropertySet)SymbolProperty::TemplateSpecialization)
return CXIdxEntity_TemplateSpecialization;
- if (K & (unsigned)SymbolProperty::Generic)
+ if (K & (SymbolPropertySet)SymbolProperty::Generic)
return CXIdxEntity_Template;
return CXIdxEntity_NonTemplate;
}
diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp
index 099d5412a7df..83556572f724 100644
--- a/unittests/AST/ASTImporterTest.cpp
+++ b/unittests/AST/ASTImporterTest.cpp
@@ -22,38 +22,50 @@
namespace clang {
namespace ast_matchers {
-typedef std::vector<std::string> StringVector;
+typedef std::vector<std::string> ArgVector;
+typedef std::vector<ArgVector> RunOptions;
-void getLangArgs(Language Lang, StringVector &Args) {
+static bool isCXX(Language Lang) {
+ return Lang == Lang_CXX || Lang == Lang_CXX11;
+}
+
+static RunOptions getRunOptionsForLanguage(Language Lang) {
+ ArgVector BasicArgs;
+ // Test with basic arguments.
switch (Lang) {
case Lang_C:
- Args.insert(Args.end(), { "-x", "c", "-std=c99" });
+ BasicArgs = {"-x", "c", "-std=c99"};
break;
case Lang_C89:
- Args.insert(Args.end(), { "-x", "c", "-std=c89" });
+ BasicArgs = {"-x", "c", "-std=c89"};
break;
case Lang_CXX:
- Args.push_back("-std=c++98");
+ BasicArgs = {"-std=c++98"};
break;
case Lang_CXX11:
- Args.push_back("-std=c++11");
+ BasicArgs = {"-std=c++11"};
break;
case Lang_OpenCL:
case Lang_OBJCXX:
- break;
+ llvm_unreachable("Not implemented yet!");
+ }
+
+ // For C++, test with "-fdelayed-template-parsing" enabled to handle MSVC
+ // default behaviour.
+ if (isCXX(Lang)) {
+ ArgVector ArgsForDelayedTemplateParse = BasicArgs;
+ ArgsForDelayedTemplateParse.emplace_back("-fdelayed-template-parsing");
+ return {BasicArgs, ArgsForDelayedTemplateParse};
}
+
+ return {BasicArgs};
}
template<typename NodeType, typename MatcherType>
testing::AssertionResult
-testImport(const std::string &FromCode, Language FromLang,
- const std::string &ToCode, Language ToLang,
- MatchVerifier<NodeType> &Verifier,
- const MatcherType &AMatcher) {
- StringVector FromArgs, ToArgs;
- getLangArgs(FromLang, FromArgs);
- getLangArgs(ToLang, ToArgs);
-
+testImport(const std::string &FromCode, const ArgVector &FromArgs,
+ const std::string &ToCode, const ArgVector &ToArgs,
+ MatchVerifier<NodeType> &Verifier, const MatcherType &AMatcher) {
const char *const InputFileName = "input.cc";
const char *const OutputFileName = "output.cc";
@@ -92,7 +104,7 @@ testImport(const std::string &FromCode, Language FromLang,
return testing::AssertionFailure() << "Import failed, nullptr returned!";
// This should dump source locations and assert if some source locations
- // were not imported
+ // were not imported.
SmallString<1024> ImportChecker;
llvm::raw_svector_ostream ToNothing(ImportChecker);
ToCtx.getTranslationUnitDecl()->print(ToNothing);
@@ -104,148 +116,154 @@ testImport(const std::string &FromCode, Language FromLang,
return Verifier.match(Imported, AMatcher);
}
+template<typename NodeType, typename MatcherType>
+void testImport(const std::string &FromCode, Language FromLang,
+ const std::string &ToCode, Language ToLang,
+ MatchVerifier<NodeType> &Verifier,
+ const MatcherType &AMatcher) {
+ auto RunOptsFrom = getRunOptionsForLanguage(FromLang);
+ auto RunOptsTo = getRunOptionsForLanguage(ToLang);
+ for (const auto &FromArgs : RunOptsFrom)
+ for (const auto &ToArgs : RunOptsTo)
+ EXPECT_TRUE(testImport(FromCode, FromArgs, ToCode, ToArgs,
+ Verifier, AMatcher));
+}
+
+
TEST(ImportExpr, ImportStringLiteral) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport("void declToImport() { \"foo\"; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- stringLiteral(
- hasType(
- asString("const char [4]")))))))));
- EXPECT_TRUE(testImport("void declToImport() { L\"foo\"; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- stringLiteral(
- hasType(
- asString("const wchar_t [4]")))))))));
- EXPECT_TRUE(testImport("void declToImport() { \"foo\" \"bar\"; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- stringLiteral(
- hasType(
- asString("const char [7]")))))))));
+ testImport("void declToImport() { \"foo\"; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ stringLiteral(
+ hasType(
+ asString("const char [4]"))))))));
+ testImport("void declToImport() { L\"foo\"; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ stringLiteral(
+ hasType(
+ asString("const wchar_t [4]"))))))));
+ testImport("void declToImport() { \"foo\" \"bar\"; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ stringLiteral(
+ hasType(
+ asString("const char [7]"))))))));
}
TEST(ImportExpr, ImportGNUNullExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport("void declToImport() { __null; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- gnuNullExpr(
- hasType(isInteger()))))))));
+ testImport("void declToImport() { __null; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ gnuNullExpr(
+ hasType(isInteger())))))));
}
TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport("void declToImport() { nullptr; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- cxxNullPtrLiteralExpr()))))));
+ testImport("void declToImport() { nullptr; }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ cxxNullPtrLiteralExpr())))));
}
TEST(ImportExpr, ImportFloatinglLiteralExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport("void declToImport() { 1.0; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- floatLiteral(
- equals(1.0),
- hasType(asString("double")))))))));
- EXPECT_TRUE(testImport("void declToImport() { 1.0e-5f; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- floatLiteral(
- equals(1.0e-5f),
- hasType(asString("float")))))))));
+ testImport("void declToImport() { 1.0; }",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ floatLiteral(
+ equals(1.0),
+ hasType(asString("double"))))))));
+ testImport("void declToImport() { 1.0e-5f; }",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ floatLiteral(
+ equals(1.0e-5f),
+ hasType(asString("float"))))))));
}
TEST(ImportExpr, ImportCompoundLiteralExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- testImport(
- "void declToImport() {"
- " struct s { int x; long y; unsigned z; }; "
- " (struct s){ 42, 0L, 1U }; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- compoundLiteralExpr(
- hasType(asString("struct s")),
- has(initListExpr(
- hasType(asString("struct s")),
- has(integerLiteral(
- equals(42), hasType(asString("int")))),
- has(integerLiteral(
- equals(0), hasType(asString("long")))),
- has(integerLiteral(
- equals(1),
- hasType(asString("unsigned int"))))
- )))))))));
+ testImport("void declToImport() {"
+ " struct s { int x; long y; unsigned z; }; "
+ " (struct s){ 42, 0L, 1U }; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ compoundLiteralExpr(
+ hasType(asString("struct s")),
+ has(initListExpr(
+ hasType(asString("struct s")),
+ has(integerLiteral(
+ equals(42), hasType(asString("int")))),
+ has(integerLiteral(
+ equals(0), hasType(asString("long")))),
+ has(integerLiteral(
+ equals(1),
+ hasType(asString("unsigned int"))))
+ ))))))));
}
TEST(ImportExpr, ImportCXXThisExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- testImport("class declToImport { void f() { this; } };",
- Lang_CXX, "", Lang_CXX, Verifier,
- cxxRecordDecl(
- hasMethod(
- hasBody(
- compoundStmt(
- has(
- cxxThisExpr(
- hasType(
- asString("class declToImport *"))))))))));
+ testImport("class declToImport { void f() { this; } };",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ cxxRecordDecl(
+ hasMethod(
+ hasBody(
+ compoundStmt(
+ has(
+ cxxThisExpr(
+ hasType(
+ asString("class declToImport *")))))))));
}
TEST(ImportExpr, ImportAtomicExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport(
- "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", Lang_CXX,
- "", Lang_CXX, Verifier,
- functionDecl(hasBody(compoundStmt(has(atomicExpr(
- has(ignoringParenImpCasts(
- declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
- hasType(asString("int *"))))),
- has(integerLiteral(equals(1), hasType(asString("int")))))))))));
+ testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(hasBody(compoundStmt(has(atomicExpr(
+ has(ignoringParenImpCasts(
+ declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
+ hasType(asString("int *"))))),
+ has(integerLiteral(equals(1), hasType(asString("int"))))))))));
}
TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- testImport(
- "void declToImport() { loop: goto loop; &&loop; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
- has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))
- )))));
+ testImport(
+ "void declToImport() { loop: goto loop; &&loop; }", Lang_C, "", Lang_C,
+ Verifier,
+ functionDecl(hasBody(compoundStmt(
+ has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
+ has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))))));
}
AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
@@ -256,7 +274,7 @@ AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
TEST(ImportExpr, ImportParenListExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport(
+ testImport(
"template<typename T> class dummy { void f() { dummy X(*this); } };"
"typedef dummy<int> declToImport;"
"template class dummy<int>;",
@@ -268,187 +286,181 @@ TEST(ImportExpr, ImportParenListExpr) {
hasBody(compoundStmt(has(declStmt(hasSingleDecl(
varDecl(hasInitializer(parenListExpr(has(unaryOperator(
hasOperatorName("*"),
- hasUnaryOperand(cxxThisExpr()))))))))))))))))))))))));
+ hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
}
TEST(ImportExpr, ImportSwitch) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasBody(compoundStmt(
- has(switchStmt(has(compoundStmt(has(caseStmt()))))))))));
+ testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(hasBody(compoundStmt(
+ has(switchStmt(has(compoundStmt(has(caseStmt())))))))));
}
TEST(ImportExpr, ImportStmtExpr) {
MatchVerifier<Decl> Verifier;
// NOTE: has() ignores implicit casts, using hasDescendant() to match it
- EXPECT_TRUE(
- testImport(
- "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- declStmt(
- hasSingleDecl(
- varDecl(
- hasName("C"),
- hasType(asString("int")),
- hasInitializer(
- stmtExpr(
- hasAnySubstatement(
- declStmt(
- hasSingleDecl(
- varDecl(
- hasName("X"),
- hasType(asString("int")),
- hasInitializer(
- integerLiteral(equals(4))))))),
- hasDescendant(
- implicitCastExpr()
- ))))))))))));
+ testImport(
+ "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ declStmt(
+ hasSingleDecl(
+ varDecl(
+ hasName("C"),
+ hasType(asString("int")),
+ hasInitializer(
+ stmtExpr(
+ hasAnySubstatement(
+ declStmt(
+ hasSingleDecl(
+ varDecl(
+ hasName("X"),
+ hasType(asString("int")),
+ hasInitializer(
+ integerLiteral(equals(4))))))),
+ hasDescendant(
+ implicitCastExpr()
+ )))))))))));
}
TEST(ImportExpr, ImportConditionalOperator) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- testImport(
- "void declToImport() { true ? 1 : -5; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- conditionalOperator(
- hasCondition(cxxBoolLiteral(equals(true))),
- hasTrueExpression(integerLiteral(equals(1))),
- hasFalseExpression(
- unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
- ))))))));
+ testImport(
+ "void declToImport() { true ? 1 : -5; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ conditionalOperator(
+ hasCondition(cxxBoolLiteral(equals(true))),
+ hasTrueExpression(integerLiteral(equals(1))),
+ hasFalseExpression(
+ unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
+ )))))));
}
TEST(ImportExpr, ImportBinaryConditionalOperator) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- testImport(
- "void declToImport() { 1 ?: -5; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- binaryConditionalOperator(
- hasCondition(
- implicitCastExpr(
- hasSourceExpression(
- opaqueValueExpr(
- hasSourceExpression(integerLiteral(equals(1))))),
- hasType(booleanType()))),
- hasTrueExpression(
- opaqueValueExpr(hasSourceExpression(
- integerLiteral(equals(1))))),
- hasFalseExpression(
- unaryOperator(hasOperatorName("-"),
- hasUnaryOperand(integerLiteral(equals(5)))))
- )))))));
+ testImport(
+ "void declToImport() { 1 ?: -5; }", Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ binaryConditionalOperator(
+ hasCondition(
+ implicitCastExpr(
+ hasSourceExpression(
+ opaqueValueExpr(
+ hasSourceExpression(integerLiteral(equals(1))))),
+ hasType(booleanType()))),
+ hasTrueExpression(
+ opaqueValueExpr(hasSourceExpression(
+ integerLiteral(equals(1))))),
+ hasFalseExpression(
+ unaryOperator(hasOperatorName("-"),
+ hasUnaryOperand(integerLiteral(equals(5)))))
+ ))))));
}
TEST(ImportExpr, ImportDesignatedInitExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport("void declToImport() {"
- " struct point { double x; double y; };"
- " struct point ptarray[10] = "
- "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- declStmt(
- hasSingleDecl(
- varDecl(
- hasInitializer(
- initListExpr(
- hasSyntacticForm(
- initListExpr(
- has(
- designatedInitExpr(
- designatorCountIs(2),
- has(floatLiteral(
- equals(1.0))),
- has(integerLiteral(
- equals(2))))),
- has(
- designatedInitExpr(
- designatorCountIs(2),
- has(floatLiteral(
- equals(2.0))),
- has(integerLiteral(
- equals(2))))),
- has(
- designatedInitExpr(
- designatorCountIs(2),
- has(floatLiteral(
- equals(1.0))),
- has(integerLiteral(
- equals(0)))))
- )))))))))))));
+ testImport("void declToImport() {"
+ " struct point { double x; double y; };"
+ " struct point ptarray[10] = "
+ "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ declStmt(
+ hasSingleDecl(
+ varDecl(
+ hasInitializer(
+ initListExpr(
+ hasSyntacticForm(
+ initListExpr(
+ has(
+ designatedInitExpr(
+ designatorCountIs(2),
+ has(floatLiteral(
+ equals(1.0))),
+ has(integerLiteral(
+ equals(2))))),
+ has(
+ designatedInitExpr(
+ designatorCountIs(2),
+ has(floatLiteral(
+ equals(2.0))),
+ has(integerLiteral(
+ equals(2))))),
+ has(
+ designatedInitExpr(
+ designatorCountIs(2),
+ has(floatLiteral(
+ equals(1.0))),
+ has(integerLiteral(
+ equals(0)))))
+ ))))))))))));
}
TEST(ImportExpr, ImportPredefinedExpr) {
MatchVerifier<Decl> Verifier;
// __func__ expands as StringLiteral("declToImport")
- EXPECT_TRUE(testImport("void declToImport() { __func__; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- predefinedExpr(
- hasType(
- asString("const char [13]")),
- has(
- stringLiteral(
- hasType(
- asString("const char [13]")))))))))));
+ testImport("void declToImport() { __func__; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ predefinedExpr(
+ hasType(
+ asString("const char [13]")),
+ has(
+ stringLiteral(
+ hasType(
+ asString("const char [13]"))))))))));
}
TEST(ImportExpr, ImportInitListExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- testImport(
- "void declToImport() {"
- " struct point { double x; double y; };"
- " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
- " [0].x = 1.0 }; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- declStmt(
- hasSingleDecl(
- varDecl(
- hasInitializer(
- initListExpr(
- has(
- cxxConstructExpr(
- requiresZeroInitialization())),
- has(
- initListExpr(
- hasType(asString("struct point")),
- has(floatLiteral(equals(1.0))),
- has(implicitValueInitExpr(
- hasType(asString("double")))))),
- has(
- initListExpr(
- hasType(asString("struct point")),
- has(floatLiteral(equals(2.0))),
- has(floatLiteral(equals(1.0)))))
- )))))))))));
+ testImport(
+ "void declToImport() {"
+ " struct point { double x; double y; };"
+ " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
+ " [0].x = 1.0 }; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ declStmt(
+ hasSingleDecl(
+ varDecl(
+ hasInitializer(
+ initListExpr(
+ has(
+ cxxConstructExpr(
+ requiresZeroInitialization())),
+ has(
+ initListExpr(
+ hasType(asString("struct point")),
+ has(floatLiteral(equals(1.0))),
+ has(implicitValueInitExpr(
+ hasType(asString("double")))))),
+ has(
+ initListExpr(
+ hasType(asString("struct point")),
+ has(floatLiteral(equals(2.0))),
+ has(floatLiteral(equals(1.0)))))
+ ))))))))));
}
@@ -456,102 +468,70 @@ const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
TEST(ImportExpr, ImportVAArgExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- testImport(
- "void declToImport(__builtin_va_list list, ...) {"
- " (void)__builtin_va_arg(list, int); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- cStyleCastExpr(
- hasSourceExpression(
- vaArgExpr()))))))));
+ testImport("void declToImport(__builtin_va_list list, ...) {"
+ " (void)__builtin_va_arg(list, int); }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ cStyleCastExpr(
+ hasSourceExpression(
+ vaArgExpr())))))));
}
TEST(ImportType, ImportAtomicType) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport("void declToImport() { typedef _Atomic(int) a_int; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- declStmt(
- has(
- typedefDecl(
- has(atomicType()))))))))));
+ testImport("void declToImport() { typedef _Atomic(int) a_int; }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ declStmt(
+ has(
+ typedefDecl(
+ has(atomicType())))))))));
}
TEST(ImportType, ImportTypeAliasTemplate) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport("template <int K>"
- "struct dummy { static const int i = K; };"
- "template <int K> using dummy2 = dummy<K>;"
- "int declToImport() { return dummy2<3>::i; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- returnStmt(
- has(
- implicitCastExpr(
- has(
- declRefExpr()))))))))));
-}
-
-TEST(ImportDecl, ImportFunctionTemplateDecl) {
- MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport("template <typename T> void declToImport() { };",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl()));
-}
-
-const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
- cxxDependentScopeMemberExpr;
-
-TEST(ImportExpr, ImportCXXDependentScopeMemberExpr) {
- MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport("template <typename T> class C { T t; };"
- "template <typename T> void declToImport() {"
- " C<T> d;"
- " d.t;"
- "}",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(has(functionDecl(has(compoundStmt(
- has(cxxDependentScopeMemberExpr()))))))));
- EXPECT_TRUE(testImport("template <typename T> class C { T t; };"
- "template <typename T> void declToImport() {"
- " C<T> d;"
- " (&d)->t;"
- "}",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(has(functionDecl(has(compoundStmt(
- has(cxxDependentScopeMemberExpr()))))))));
+ testImport("template <int K>"
+ "struct dummy { static const int i = K; };"
+ "template <int K> using dummy2 = dummy<K>;"
+ "int declToImport() { return dummy2<3>::i; }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ returnStmt(
+ has(
+ implicitCastExpr(
+ has(
+ declRefExpr())))))))));
}
TEST(ImportType, ImportPackExpansion) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport("template <typename... Args>"
- "struct dummy {"
- " dummy(Args... args) {}"
- " static const int i = 4;"
- "};"
- "int declToImport() { return dummy<int>::i; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- returnStmt(
- has(
- implicitCastExpr(
- has(
- declRefExpr()))))))))));
+ testImport("template <typename... Args>"
+ "struct dummy {"
+ " dummy(Args... args) {}"
+ " static const int i = 4;"
+ "};"
+ "int declToImport() { return dummy<int>::i; }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ returnStmt(
+ has(
+ implicitCastExpr(
+ has(
+ declRefExpr())))))))));
}
/// \brief Matches __builtin_types_compatible_p:
@@ -565,35 +545,35 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
TEST(ImportExpr, ImportTypeTraitExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport("void declToImport() { "
- " __builtin_types_compatible_p(int, int);"
- "}",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- typeTraitExpr(hasType(asString("int")))))))));
+ testImport("void declToImport() { "
+ " __builtin_types_compatible_p(int, int);"
+ "}",
+ Lang_C, "", Lang_C, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ typeTraitExpr(hasType(asString("int"))))))));
}
TEST(ImportExpr, ImportTypeTraitExprValDep) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(testImport("template<typename T> struct declToImport {"
- " void m() { __is_pod(T); }"
- "};"
- "void f() { declToImport<int>().m(); }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- classTemplateDecl(
+ testImport("template<typename T> struct declToImport {"
+ " void m() { __is_pod(T); }"
+ "};"
+ "void f() { declToImport<int>().m(); }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ classTemplateDecl(
+ has(
+ cxxRecordDecl(
+ has(
+ functionDecl(
+ hasBody(
+ compoundStmt(
has(
- cxxRecordDecl(
- has(
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- typeTraitExpr(
- hasType(booleanType())
- )))))))))));
+ typeTraitExpr(
+ hasType(booleanType())
+ ))))))))));
}
const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
@@ -601,31 +581,28 @@ const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
TEST(ImportExpr, ImportCXXPseudoDestructorExpr) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- testImport("typedef int T;"
- "void declToImport(int *p) {"
- " T t;"
- " p->T::~T();"
- "}",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(has(compoundStmt(has(
- callExpr(has(cxxPseudoDestructorExpr()))))))));
+ testImport("typedef int T;"
+ "void declToImport(int *p) {"
+ " T t;"
+ " p->T::~T();"
+ "}",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(has(compoundStmt(has(
+ callExpr(has(cxxPseudoDestructorExpr())))))));
}
TEST(ImportDecl, ImportUsingDecl) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- testImport(
- "namespace foo { int bar; }"
- "int declToImport(){ using foo::bar; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(
- has(
- compoundStmt(
- has(
- declStmt(
- has(
- usingDecl()))))))));
+ testImport("namespace foo { int bar; }"
+ "int declToImport(){ using foo::bar; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ functionDecl(
+ has(
+ compoundStmt(
+ has(
+ declStmt(
+ has(
+ usingDecl())))))));
}
/// \brief Matches shadow declarations introduced into a scope by a
@@ -643,14 +620,10 @@ const internal::VariadicDynCastAllOfMatcher<Decl,
TEST(ImportDecl, ImportUsingShadowDecl) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- testImport(
- "namespace foo { int bar; }"
- "namespace declToImport { using foo::bar; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- namespaceDecl(
- has(
- usingShadowDecl()))));
+ testImport("namespace foo { int bar; }"
+ "namespace declToImport { using foo::bar; }",
+ Lang_CXX, "", Lang_CXX, Verifier,
+ namespaceDecl(has(usingShadowDecl())));
}
} // end namespace ast_matchers
diff --git a/unittests/AST/NamedDeclPrinterTest.cpp b/unittests/AST/NamedDeclPrinterTest.cpp
index 92df4577ac77..002bb28f374d 100644
--- a/unittests/AST/NamedDeclPrinterTest.cpp
+++ b/unittests/AST/NamedDeclPrinterTest.cpp
@@ -143,7 +143,7 @@ TEST(NamedDeclPrinter, TestNamedEnum) {
ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
"enum X { A };",
"A",
- "X::A"));
+ "A"));
}
TEST(NamedDeclPrinter, TestScopedNamedEnum) {
@@ -164,7 +164,7 @@ TEST(NamedDeclPrinter, TestClassWithUnscopedNamedEnum) {
ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
"class X { enum Y { A }; };",
"A",
- "X::Y::A"));
+ "X::A"));
}
TEST(NamedDeclPrinter, TestClassWithScopedNamedEnum) {
diff --git a/unittests/CodeGen/CMakeLists.txt b/unittests/CodeGen/CMakeLists.txt
index 3fb79a03075d..856dbce08ea9 100644
--- a/unittests/CodeGen/CMakeLists.txt
+++ b/unittests/CodeGen/CMakeLists.txt
@@ -7,6 +7,7 @@ add_clang_unittest(ClangCodeGenTests
BufferSourceTest.cpp
CodeGenExternalTest.cpp
IncrementalProcessingTest.cpp
+ TBAAMetadataTest.cpp
)
target_link_libraries(ClangCodeGenTests
diff --git a/unittests/CodeGen/IRMatchers.h b/unittests/CodeGen/IRMatchers.h
new file mode 100644
index 000000000000..5150ca40fb42
--- /dev/null
+++ b/unittests/CodeGen/IRMatchers.h
@@ -0,0 +1,453 @@
+//=== unittests/CodeGen/IRMatchers.h - Match on the LLVM IR -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides a simple mechanism for performing search operations over
+/// IR including metadata and types. It allows writing complex search patterns
+/// using understandable syntax. For instance, the code:
+///
+/// \code
+/// const BasicBlock *BB = ...
+/// const Instruction *I = match(BB,
+/// MInstruction(Instruction::Store,
+/// MConstInt(4, 8),
+/// MMTuple(
+/// MMTuple(
+/// MMString("omnipotent char"),
+/// MMTuple(
+/// MMString("Simple C/C++ TBAA")),
+/// MConstInt(0, 64)),
+/// MSameAs(0),
+/// MConstInt(0))));
+/// \endcode
+///
+/// searches the basic block BB for the 'store' instruction, first argument of
+/// which is 'i8 4', and the attached metadata has an item described by the
+/// given tree.
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_UNITTESTS_CODEGEN_IRMATCHERS_H
+#define CLANG_UNITTESTS_CODEGEN_IRMATCHERS_H
+
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Value.h"
+
+namespace llvm {
+
+/// Keeps information about pending match queries.
+///
+/// This class stores state of all unfinished match actions. It allows to
+/// use queries like "this operand is the same as n-th operand", which are
+/// hard to implement otherwise.
+///
+class MatcherContext {
+public:
+
+ /// Describes pending match query.
+ ///
+ /// The query is represented by the current entity being investigated (type,
+ /// value or metadata). If the entity is a member of a list (like arguments),
+ /// the query also keeps the entity number in that list.
+ ///
+ class Query {
+ PointerUnion3<const Value *, const Metadata *, const Type *> Entity;
+ unsigned OperandNo;
+
+ public:
+ Query(const Value *V, unsigned N) : Entity(V), OperandNo(N) {}
+ Query(const Metadata *M, unsigned N) : Entity(M), OperandNo(N) {}
+ Query(const Type *T, unsigned N) : Entity(T), OperandNo(N) {}
+
+ template<typename T>
+ const T *get() const {
+ return Entity.dyn_cast<const T *>();
+ }
+
+ unsigned getOperandNo() const { return OperandNo; }
+ };
+
+ template<typename T>
+ void push(const T *V, unsigned N = ~0) {
+ MatchStack.push_back(Query(V, N));
+ }
+
+ void pop() { MatchStack.pop_back(); }
+
+ template<typename T>
+ const T *top() const { return MatchStack.back().get<T>(); }
+
+ size_t size() const { return MatchStack.size(); }
+
+ unsigned getOperandNo() const { return MatchStack.back().getOperandNo(); }
+
+ /// Returns match query at the given offset from the top of queries.
+ ///
+ /// Offset 0 corresponds to the topmost query.
+ ///
+ const Query &getQuery(unsigned Offset) const {
+ assert(MatchStack.size() > Offset);
+ return MatchStack[MatchStack.size() - 1 - Offset];
+ }
+
+private:
+ SmallVector<Query, 8> MatchStack;
+};
+
+
+/// Base of all matcher classes.
+///
+class Matcher {
+public:
+ virtual ~Matcher() {}
+
+ /// Returns true if the entity on the top of the specified context satisfies
+ /// the matcher condition.
+ ///
+ virtual bool match(MatcherContext &MC) = 0;
+};
+
+
+/// Base class of matchers that test particular entity.
+///
+template<typename T>
+class EntityMatcher : public Matcher {
+public:
+ bool match(MatcherContext &MC) override {
+ if (auto V = MC.top<T>())
+ return matchEntity(*V, MC);
+ return false;
+ }
+ virtual bool matchEntity(const T &M, MatcherContext &C) = 0;
+};
+
+
+/// Matcher that matches any entity of the specified kind.
+///
+template<typename T>
+class AnyMatcher : public EntityMatcher<T> {
+public:
+ bool matchEntity(const T &M, MatcherContext &C) override { return true; }
+};
+
+
+/// Matcher that tests if the current entity satisfies the specified
+/// condition.
+///
+template<typename T>
+class CondMatcher : public EntityMatcher<T> {
+ std::function<bool(const T &)> Condition;
+public:
+ CondMatcher(std::function<bool(const T &)> C) : Condition(C) {}
+ bool matchEntity(const T &V, MatcherContext &C) override {
+ return Condition(V);
+ }
+};
+
+
+/// Matcher that save pointer to the entity that satisfies condition of the
+// specified matcher.
+///
+template<typename T>
+class SavingMatcher : public EntityMatcher<T> {
+ const T *&Var;
+ std::shared_ptr<Matcher> Next;
+public:
+ SavingMatcher(const T *&V, std::shared_ptr<Matcher> N) : Var(V), Next(N) {}
+ bool matchEntity(const T &V, MatcherContext &C) override {
+ bool Result = Next->match(C);
+ if (Result)
+ Var = &V;
+ return Result;
+ }
+};
+
+
+/// Matcher that checks that the entity is identical to another entity in the
+/// same container.
+///
+class SameAsMatcher : public Matcher {
+ unsigned OpNo;
+public:
+ SameAsMatcher(unsigned N) : OpNo(N) {}
+ bool match(MatcherContext &C) override {
+ if (C.getOperandNo() != ~0U) {
+ // Handle all known containers here.
+ const MatcherContext::Query &StackRec = C.getQuery(1);
+ if (const Metadata *MR = StackRec.get<Metadata>()) {
+ if (const auto *MT = dyn_cast<MDTuple>(MR)) {
+ if (OpNo < MT->getNumOperands())
+ return C.top<Metadata>() == MT->getOperand(OpNo).get();
+ return false;
+ }
+ llvm_unreachable("Unknown metadata container");
+ }
+ if (const Value *VR = StackRec.get<Value>()) {
+ if (const auto *Insn = dyn_cast<Instruction>(VR)) {
+ if (OpNo < Insn->getNumOperands())
+ return C.top<Value>() == Insn->getOperand(OpNo);
+ return false;
+ }
+ llvm_unreachable("Unknown value container");
+ }
+ llvm_unreachable("Unknown type container");
+ }
+ return false;
+ }
+};
+
+
+/// Matcher that tests if the entity is a constant integer.
+///
+class ConstantIntMatcher : public Matcher {
+ uint64_t IntValue;
+ unsigned Width;
+public:
+ ConstantIntMatcher(uint64_t V, unsigned W = 0) : IntValue(V), Width(W) {}
+ bool match(MatcherContext &Ctx) override {
+ if (const Value *V = Ctx.top<Value>()) {
+ if (const auto *CI = dyn_cast<ConstantInt>(V))
+ return (Width == 0 || CI->getBitWidth() == Width) &&
+ CI->getLimitedValue() == IntValue;
+ }
+ if (const Metadata *M = Ctx.top<Metadata>()) {
+ if (const auto *MT = dyn_cast<ValueAsMetadata>(M))
+ if (const auto *C = dyn_cast<ConstantInt>(MT->getValue()))
+ return (Width == 0 || C->getBitWidth() == Width) &&
+ C->getLimitedValue() == IntValue;
+ }
+ return false;
+ }
+};
+
+
+/// Value matcher tuned to test instructions.
+///
+class InstructionMatcher : public EntityMatcher<Value> {
+ SmallVector<std::shared_ptr<Matcher>, 8> OperandMatchers;
+ std::shared_ptr<EntityMatcher<Metadata>> MetaMatcher = nullptr;
+ unsigned Code;
+public:
+ InstructionMatcher(unsigned C) : Code(C) {}
+
+ void push(std::shared_ptr<EntityMatcher<Metadata>> M) {
+ assert(!MetaMatcher && "Only one metadata matcher may be specified");
+ MetaMatcher = M;
+ }
+ void push(std::shared_ptr<Matcher> V) { OperandMatchers.push_back(V); }
+ template<typename... Args>
+ void push(std::shared_ptr<Matcher> V, Args... A) {
+ push(V);
+ push(A...);
+ }
+
+ virtual bool matchInstruction(const Instruction &I) {
+ return I.getOpcode() == Code;
+ }
+
+ bool matchEntity(const Value &V, MatcherContext &C) override {
+ if (const auto *I = dyn_cast<Instruction>(&V)) {
+ if (!matchInstruction(*I))
+ return false;
+ if (OperandMatchers.size() > I->getNumOperands())
+ return false;
+ for (unsigned N = 0, E = OperandMatchers.size(); N != E; ++N) {
+ C.push(I->getOperand(N), N);
+ if (!OperandMatchers[N]->match(C)) {
+ C.pop();
+ return false;
+ }
+ C.pop();
+ }
+ if (MetaMatcher) {
+ SmallVector<std::pair<unsigned, MDNode *>, 8> MDs;
+ I->getAllMetadata(MDs);
+ bool Found = false;
+ for (auto Item : MDs) {
+ C.push(Item.second);
+ if (MetaMatcher->match(C)) {
+ Found = true;
+ C.pop();
+ break;
+ }
+ C.pop();
+ }
+ return Found;
+ }
+ return true;
+ }
+ return false;
+ }
+};
+
+
+/// Matcher that tests type of the current value using the specified
+/// type matcher.
+///
+class ValueTypeMatcher : public EntityMatcher<Value> {
+ std::shared_ptr<EntityMatcher<Type>> TyM;
+public:
+ ValueTypeMatcher(std::shared_ptr<EntityMatcher<Type>> T) : TyM(T) {}
+ ValueTypeMatcher(const Type *T)
+ : TyM(new CondMatcher<Type>([T](const Type &Ty) -> bool {
+ return &Ty == T;
+ })) {}
+ bool matchEntity(const Value &V, MatcherContext &Ctx) override {
+ Type *Ty = V.getType();
+ Ctx.push(Ty);
+ bool Res = TyM->match(Ctx);
+ Ctx.pop();
+ return Res;
+ }
+};
+
+
+/// Matcher that matches string metadata.
+///
+class NameMetaMatcher : public EntityMatcher<Metadata> {
+ StringRef Name;
+public:
+ NameMetaMatcher(StringRef N) : Name(N) {}
+ bool matchEntity(const Metadata &M, MatcherContext &C) override {
+ if (auto *MDS = dyn_cast<MDString>(&M))
+ return MDS->getString().equals(Name);
+ return false;
+ }
+};
+
+
+/// Matcher that matches metadata tuples.
+///
+class MTupleMatcher : public EntityMatcher<Metadata> {
+ SmallVector<std::shared_ptr<Matcher>, 4> Operands;
+public:
+ void push(std::shared_ptr<Matcher> M) { Operands.push_back(M); }
+ template<typename... Args>
+ void push(std::shared_ptr<Matcher> M, Args... A) {
+ push(M);
+ push(A...);
+ }
+ bool matchEntity(const Metadata &M, MatcherContext &C) override {
+ if (const auto *MT = dyn_cast<MDTuple>(&M)) {
+ if (MT->getNumOperands() != Operands.size())
+ return false;
+ for (unsigned I = 0, E = MT->getNumOperands(); I != E; ++I) {
+ const MDOperand &Op = MT->getOperand(I);
+ C.push(Op.get(), I);
+ if (!Operands[I]->match(C)) {
+ C.pop();
+ return false;
+ }
+ C.pop();
+ }
+ return true;
+ }
+ return false;
+ }
+};
+
+
+// Helper function used to construct matchers.
+
+std::shared_ptr<Matcher> MSameAs(unsigned N) {
+ return std::shared_ptr<Matcher>(new SameAsMatcher(N));
+}
+
+template<typename... T>
+std::shared_ptr<InstructionMatcher> MInstruction(unsigned C, T... Args) {
+ auto Result = new InstructionMatcher(C);
+ Result->push(Args...);
+ return std::shared_ptr<InstructionMatcher>(Result);
+}
+
+std::shared_ptr<Matcher> MConstInt(uint64_t V, unsigned W = 0) {
+ return std::shared_ptr<Matcher>(new ConstantIntMatcher(V, W));
+}
+
+std::shared_ptr<EntityMatcher<Value>>
+ MValType(std::shared_ptr<EntityMatcher<Type>> T) {
+ return std::shared_ptr<EntityMatcher<Value>>(new ValueTypeMatcher(T));
+}
+
+std::shared_ptr<EntityMatcher<Value>> MValType(const Type *T) {
+ return std::shared_ptr<EntityMatcher<Value>>(new ValueTypeMatcher(T));
+}
+
+std::shared_ptr<EntityMatcher<Type>>
+MType(std::function<bool(const Type &)> C) {
+ return std::shared_ptr<EntityMatcher<Type>>(new CondMatcher<Type>(C));
+}
+
+std::shared_ptr<EntityMatcher<Metadata>> MMAny() {
+ return std::shared_ptr<EntityMatcher<Metadata>>(new AnyMatcher<Metadata>);
+}
+
+std::shared_ptr<EntityMatcher<Metadata>>
+MMSave(const Metadata *&V, std::shared_ptr<EntityMatcher<Metadata>> M) {
+ return std::shared_ptr<EntityMatcher<Metadata>>(
+ new SavingMatcher<Metadata>(V, M));
+}
+
+std::shared_ptr<EntityMatcher<Metadata>>
+MMString(const char *Name) {
+ return std::shared_ptr<EntityMatcher<Metadata>>(new NameMetaMatcher(Name));
+}
+
+template<typename... T>
+std::shared_ptr<EntityMatcher<Metadata>> MMTuple(T... Args) {
+ auto Res = new MTupleMatcher();
+ Res->push(Args...);
+ return std::shared_ptr<EntityMatcher<Metadata>>(Res);
+}
+
+
+/// Looks for the instruction that satisfies condition of the specified
+/// matcher inside the given basic block.
+/// \returns Pointer to the found instruction or nullptr if such instruction
+/// was not found.
+///
+const Instruction *match(const BasicBlock *BB, std::shared_ptr<Matcher> M) {
+ MatcherContext MC;
+ for (const auto &I : *BB) {
+ MC.push(&I);
+ if (M->match(MC))
+ return &I;
+ MC.pop();
+ }
+ assert(MC.size() == 0);
+ return nullptr;
+}
+
+
+/// Looks for the instruction that satisfies condition of the specified
+/// matcher starting from the specified instruction inside the same basic block.
+///
+/// The given instruction is not checked.
+///
+const Instruction *matchNext(const Instruction *I, std::shared_ptr<Matcher> M) {
+ if (!I)
+ return nullptr;
+ MatcherContext MC;
+ const BasicBlock *BB = I->getParent();
+ if (!BB)
+ return nullptr;
+ for (auto P = ++BasicBlock::const_iterator(I), E = BB->end(); P != E; ++P) {
+ MC.push(&*P);
+ if (M->match(MC))
+ return &*P;
+ MC.pop();
+ }
+ assert(MC.size() == 0);
+ return nullptr;
+}
+
+}
+#endif
diff --git a/unittests/CodeGen/TBAAMetadataTest.cpp b/unittests/CodeGen/TBAAMetadataTest.cpp
new file mode 100644
index 000000000000..7514160e6e3a
--- /dev/null
+++ b/unittests/CodeGen/TBAAMetadataTest.cpp
@@ -0,0 +1,1299 @@
+//=== unittests/CodeGen/TBAAMetadataTest.cpp - Checks metadata generation -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IRMatchers.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Parse/ParseAST.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+struct TestCompiler {
+ LLVMContext Context;
+ clang::CompilerInstance compiler;
+ clang::CodeGenerator *CG = nullptr;
+ llvm::Module *M = nullptr;
+ unsigned PtrSize = 0;
+
+ void init(const char *TestProgram) {
+ compiler.createDiagnostics();
+ compiler.getCodeGenOpts().StructPathTBAA = 1;
+ compiler.getCodeGenOpts().OptimizationLevel = 1;
+
+ std::string TrStr = llvm::Triple::normalize(llvm::sys::getProcessTriple());
+ llvm::Triple Tr(TrStr);
+ Tr.setOS(Triple::Linux);
+ Tr.setVendor(Triple::VendorType::UnknownVendor);
+ Tr.setEnvironment(Triple::EnvironmentType::UnknownEnvironment);
+ compiler.getTargetOpts().Triple = Tr.getTriple();
+ compiler.setTarget(clang::TargetInfo::CreateTargetInfo(
+ compiler.getDiagnostics(),
+ std::make_shared<clang::TargetOptions>(compiler.getTargetOpts())));
+
+ const clang::TargetInfo &TInfo = compiler.getTarget();
+ PtrSize = TInfo.getPointerWidth(0) / 8;
+
+ compiler.createFileManager();
+ compiler.createSourceManager(compiler.getFileManager());
+ compiler.createPreprocessor(clang::TU_Prefix);
+
+ compiler.createASTContext();
+
+ CG = CreateLLVMCodeGen(
+ compiler.getDiagnostics(),
+ "main-module",
+ compiler.getHeaderSearchOpts(),
+ compiler.getPreprocessorOpts(),
+ compiler.getCodeGenOpts(),
+ Context);
+ compiler.setASTConsumer(std::unique_ptr<clang::ASTConsumer>(CG));
+
+ compiler.createSema(clang::TU_Prefix, nullptr);
+
+ clang::SourceManager &sm = compiler.getSourceManager();
+ sm.setMainFileID(sm.createFileID(
+ llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User));
+ }
+
+ const BasicBlock *compile() {
+ clang::ParseAST(compiler.getSema(), false, false);
+ M = CG->GetModule();
+
+ // Do not expect more than one function definition.
+ auto FuncPtr = M->begin();
+ for (; FuncPtr != M->end(); ++FuncPtr)
+ if (!FuncPtr->isDeclaration())
+ break;
+ assert(FuncPtr != M->end());
+ const llvm::Function &Func = *FuncPtr;
+ ++FuncPtr;
+ for (; FuncPtr != M->end(); ++FuncPtr)
+ if (!FuncPtr->isDeclaration())
+ break;
+ assert(FuncPtr == M->end());
+
+ // The function must consist of single basic block.
+ auto BBPtr = Func.begin();
+ assert(Func.begin() != Func.end());
+ const BasicBlock &BB = *BBPtr;
+ ++BBPtr;
+ assert(BBPtr == Func.end());
+
+ return &BB;
+ }
+};
+
+
+auto OmnipotentCharC = MMTuple(
+ MMString("omnipotent char"),
+ MMTuple(
+ MMString("Simple C/C++ TBAA")),
+ MConstInt(0, 64)
+);
+
+
+auto OmnipotentCharCXX = MMTuple(
+ MMString("omnipotent char"),
+ MMTuple(
+ MMString("Simple C++ TBAA")),
+ MConstInt(0, 64)
+);
+
+
+TEST(TBAAMetadataTest, BasicTypes) {
+ const char TestProgram[] = R"**(
+ void func(char *CP, short *SP, int *IP, long long *LP, void **VPP,
+ int **IPP) {
+ *CP = 4;
+ *SP = 11;
+ *IP = 601;
+ *LP = 604;
+ *VPP = CP;
+ *IPP = IP;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().C11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MConstInt(4, 8),
+ MMTuple(
+ OmnipotentCharC,
+ MSameAs(0),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(11, 16),
+ MMTuple(
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MSameAs(0),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(601, 32),
+ MMTuple(
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MSameAs(0),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(604, 64),
+ MMTuple(
+ MMTuple(
+ MMString("long long"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MSameAs(0),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MValType(Type::getInt8PtrTy(Compiler.Context)),
+ MMTuple(
+ MMTuple(
+ MMString("any pointer"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MSameAs(0),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MValType(Type::getInt32PtrTy(Compiler.Context)),
+ MMTuple(
+ MMTuple(
+ MMString("any pointer"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MSameAs(0),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+}
+
+TEST(TBAAMetadataTest, CFields) {
+ const char TestProgram[] = R"**(
+ struct ABC {
+ short f16;
+ int f32;
+ long long f64;
+ unsigned short f16_2;
+ unsigned f32_2;
+ unsigned long long f64_2;
+ };
+
+ void func(struct ABC *A) {
+ A->f32 = 4;
+ A->f16 = 11;
+ A->f64 = 601;
+ A->f16_2 = 22;
+ A->f32_2 = 77;
+ A->f64_2 = 604;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().C11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ auto StructABC = MMTuple(
+ MMString("ABC"),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(0),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(4),
+ MMTuple(
+ MMString("long long"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(8),
+ MSameAs(1),
+ MConstInt(16),
+ MSameAs(3),
+ MConstInt(20),
+ MSameAs(5),
+ MConstInt(24));
+
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MConstInt(4, 32),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(4))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(11, 16),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(601, 64),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("long long"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(8))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(22, 16),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(16))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(77, 32),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(20))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(604, 64),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("long long"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(24))));
+ ASSERT_TRUE(I);
+}
+
+TEST(TBAAMetadataTest, CTypedefFields) {
+ const char TestProgram[] = R"**(
+ typedef struct {
+ short f16;
+ int f32;
+ } ABC;
+ typedef struct {
+ short value_f16;
+ int value_f32;
+ } CDE;
+
+ void func(ABC *A, CDE *B) {
+ A->f32 = 4;
+ A->f16 = 11;
+ B->value_f32 = 44;
+ B->value_f16 = 111;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().C11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ auto NamelessStruct = MMTuple(
+ MMString(""),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(0),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(4));
+
+ const Metadata *MetaABC = nullptr;
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MConstInt(4, 32),
+ MMTuple(
+ MMSave(MetaABC, NamelessStruct),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(4))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(11, 16),
+ MMTuple(
+ NamelessStruct,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ const Metadata *MetaCDE = nullptr;
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(44, 32),
+ MMTuple(
+ MMSave(MetaCDE, NamelessStruct),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(4))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(111, 16),
+ MMTuple(
+ NamelessStruct,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ // FIXME: Nameless structures used in definitions of 'ABC' and 'CDE' are
+ // different structures and must be described by different descriptors.
+ //ASSERT_TRUE(MetaABC != MetaCDE);
+}
+
+TEST(TBAAMetadataTest, CTypedefFields2) {
+ const char TestProgram[] = R"**(
+ typedef struct {
+ short f16;
+ int f32;
+ } ABC;
+ typedef struct {
+ short f16;
+ int f32;
+ } CDE;
+
+ void func(ABC *A, CDE *B) {
+ A->f32 = 4;
+ A->f16 = 11;
+ B->f32 = 44;
+ B->f16 = 111;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().C11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ auto NamelessStruct = MMTuple(
+ MMString(""),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(0),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(4));
+
+ const Metadata *MetaABC = nullptr;
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MConstInt(4, 32),
+ MMTuple(
+ MMSave(MetaABC, NamelessStruct),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(4))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(11, 16),
+ MMTuple(
+ NamelessStruct,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ const Metadata *MetaCDE = nullptr;
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(44, 32),
+ MMTuple(
+ MMSave(MetaCDE, NamelessStruct),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(4))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(111, 16),
+ MMTuple(
+ NamelessStruct,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ // FIXME: Nameless structures used in definitions of 'ABC' and 'CDE' are
+ // different structures, although they have the same field sequence. They must
+ // be described by different descriptors.
+ //ASSERT_TRUE(MetaABC != MetaCDE);
+}
+
+TEST(TBAAMetadataTest, CTypedefFields3) {
+ const char TestProgram[] = R"**(
+ typedef struct {
+ short f16;
+ int f32;
+ } ABC;
+ typedef struct {
+ int f32;
+ short f16;
+ } CDE;
+
+ void func(ABC *A, CDE *B) {
+ A->f32 = 4;
+ A->f16 = 11;
+ B->f32 = 44;
+ B->f16 = 111;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().C11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ auto NamelessStruct1 = MMTuple(
+ MMString(""),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(0),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(4));
+
+ auto NamelessStruct2 = MMTuple(
+ MMString(""),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(0),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(4));
+
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MConstInt(4, 32),
+ MMTuple(
+ NamelessStruct1,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(4))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(11, 16),
+ MMTuple(
+ NamelessStruct1,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(44, 32),
+ MMTuple(
+ NamelessStruct2,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(111, 16),
+ MMTuple(
+ NamelessStruct2,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharC,
+ MConstInt(0)),
+ MConstInt(4))));
+ ASSERT_TRUE(I);
+}
+
+TEST(TBAAMetadataTest, CXXFields) {
+ const char TestProgram[] = R"**(
+ struct ABC {
+ short f16;
+ int f32;
+ long long f64;
+ unsigned short f16_2;
+ unsigned f32_2;
+ unsigned long long f64_2;
+ };
+
+ void func(struct ABC *A) {
+ A->f32 = 4;
+ A->f16 = 11;
+ A->f64 = 601;
+ A->f16_2 = 22;
+ A->f32_2 = 77;
+ A->f64_2 = 604;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().CPlusPlus = 1;
+ Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ auto StructABC = MMTuple(
+ MMString("_ZTS3ABC"),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(4),
+ MMTuple(
+ MMString("long long"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(8),
+ MSameAs(1),
+ MConstInt(16),
+ MSameAs(3),
+ MConstInt(20),
+ MSameAs(5),
+ MConstInt(24));
+
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MConstInt(4, 32),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(4))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(11, 16),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(601, 64),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("long long"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(8))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(22, 16),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(16))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(77, 32),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(20))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(604, 64),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("long long"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(24))));
+ ASSERT_TRUE(I);
+}
+
+TEST(TBAAMetadataTest, CXXTypedefFields) {
+ const char TestProgram[] = R"**(
+ typedef struct {
+ short f16;
+ int f32;
+ } ABC;
+ typedef struct {
+ short value_f16;
+ int value_f32;
+ } CDE;
+
+ void func(ABC *A, CDE *B) {
+ A->f32 = 4;
+ A->f16 = 11;
+ B->value_f32 = 44;
+ B->value_f16 = 111;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().CPlusPlus = 1;
+ Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ auto StructABC = MMTuple(
+ MMString("_ZTS3ABC"),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(4));
+
+ auto StructCDE = MMTuple(
+ MMString("_ZTS3CDE"),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(4));
+
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MConstInt(4, 32),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(4))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(11, 16),
+ MMTuple(
+ StructABC,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(44, 32),
+ MMTuple(
+ StructCDE,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(4))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(111, 16),
+ MMTuple(
+ StructCDE,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+}
+
+TEST(TBAAMetadataTest, StructureFields) {
+ const char TestProgram[] = R"**(
+ struct Inner {
+ int f32;
+ };
+
+ struct Outer {
+ short f16;
+ Inner b1;
+ Inner b2;
+ };
+
+ void func(Outer *S) {
+ S->f16 = 14;
+ S->b1.f32 = 35;
+ S->b2.f32 = 77;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().CPlusPlus = 1;
+ Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ auto StructInner = MMTuple(
+ MMString("_ZTS5Inner"),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0));
+
+ auto StructOuter = MMTuple(
+ MMString("_ZTS5Outer"),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0),
+ StructInner,
+ MConstInt(4),
+ MSameAs(3),
+ MConstInt(8));
+
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MConstInt(14, 16),
+ MMTuple(
+ StructOuter,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(35, 32),
+ MMTuple(
+ StructOuter,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(4))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(77, 32),
+ MMTuple(
+ StructOuter,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(8))));
+ ASSERT_TRUE(I);
+}
+
+TEST(TBAAMetadataTest, ArrayFields) {
+ const char TestProgram[] = R"**(
+ struct Inner {
+ int f32;
+ };
+
+ struct Outer {
+ short f16;
+ Inner b1[2];
+ };
+
+ void func(Outer *S) {
+ S->f16 = 14;
+ S->b1[0].f32 = 35;
+ S->b1[1].f32 = 77;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().CPlusPlus = 1;
+ Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ auto StructInner = MMTuple(
+ MMString("_ZTS5Inner"),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0));
+
+ auto StructOuter = MMTuple(
+ MMString("_ZTS5Outer"),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0),
+ OmnipotentCharCXX, // FIXME: Info about array field is lost.
+ MConstInt(4));
+
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MConstInt(14, 16),
+ MMTuple(
+ StructOuter,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(35, 32),
+ MMTuple(
+ StructInner,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(77, 32),
+ MMTuple(
+ StructInner,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+}
+
+TEST(TBAAMetadataTest, BaseClass) {
+ const char TestProgram[] = R"**(
+ struct Base {
+ int f32;
+ };
+
+ struct Derived : public Base {
+ short f16;
+ };
+
+ void func(Base *B, Derived *D) {
+ B->f32 = 14;
+ D->f16 = 35;
+ D->f32 = 77;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().CPlusPlus = 1;
+ Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ auto ClassBase = MMTuple(
+ MMString("_ZTS4Base"),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0));
+
+ auto ClassDerived = MMTuple(
+ MMString("_ZTS7Derived"),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(4));
+
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MConstInt(14, 32),
+ MMTuple(
+ ClassBase,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(35, 16),
+ MMTuple(
+ ClassDerived,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(4))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(77, 32),
+ MMTuple(
+ ClassBase,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+}
+
+TEST(TBAAMetadataTest, PolymorphicClass) {
+ const char TestProgram[] = R"**(
+ struct Base {
+ virtual void m1(int *) = 0;
+ int f32;
+ };
+
+ struct Derived : public Base {
+ virtual void m1(int *) override;
+ short f16;
+ };
+
+ void func(Base *B, Derived *D) {
+ B->f32 = 14;
+ D->f16 = 35;
+ D->f32 = 77;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().CPlusPlus = 1;
+ Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ auto ClassBase = MMTuple(
+ MMString("_ZTS4Base"),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(Compiler.PtrSize));
+
+ auto ClassDerived = MMTuple(
+ MMString("_ZTS7Derived"),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(Compiler.PtrSize + 4));
+
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MConstInt(14, 32),
+ MMTuple(
+ ClassBase,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(Compiler.PtrSize))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(35, 16),
+ MMTuple(
+ ClassDerived,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(Compiler.PtrSize + 4))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(77, 32),
+ MMTuple(
+ ClassBase,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(Compiler.PtrSize))));
+ ASSERT_TRUE(I);
+}
+
+TEST(TBAAMetadataTest, VirtualBase) {
+ const char TestProgram[] = R"**(
+ struct Base {
+ int f32;
+ };
+
+ struct Derived : public virtual Base {
+ short f16;
+ };
+
+ void func(Base *B, Derived *D) {
+ B->f32 = 14;
+ D->f16 = 35;
+ D->f32 = 77;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().CPlusPlus = 1;
+ Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ auto ClassBase = MMTuple(
+ MMString("_ZTS4Base"),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0));
+
+ auto ClassDerived = MMTuple(
+ MMString("_ZTS7Derived"),
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(Compiler.PtrSize));
+
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MConstInt(14, 32),
+ MMTuple(
+ ClassBase,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(35, 16),
+ MMTuple(
+ ClassDerived,
+ MMTuple(
+ MMString("short"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(Compiler.PtrSize))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Load,
+ MMTuple(
+ MMTuple(
+ MMString("vtable pointer"),
+ MMTuple(
+ MMString("Simple C++ TBAA")),
+ MConstInt(0)),
+ MSameAs(0),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(77, 32),
+ MMTuple(
+ ClassBase,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+}
+
+TEST(TBAAMetadataTest, TemplSpec) {
+ const char TestProgram[] = R"**(
+ template<typename T1, typename T2>
+ struct ABC {
+ T1 f1;
+ T2 f2;
+ };
+
+ void func(ABC<double, int> *p) {
+ p->f1 = 12.1;
+ p->f2 = 44;
+ }
+ )**";
+
+ TestCompiler Compiler;
+ Compiler.compiler.getLangOpts().CPlusPlus = 1;
+ Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
+ Compiler.init(TestProgram);
+ const BasicBlock *BB = Compiler.compile();
+
+ auto SpecABC = MMTuple(
+ MMString("_ZTS3ABCIdiE"),
+ MMTuple(
+ MMString("double"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0),
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(8));
+
+ const Instruction *I = match(BB,
+ MInstruction(Instruction::Store,
+ MValType(MType([](const Type &T)->bool { return T.isDoubleTy(); })),
+ MMTuple(
+ SpecABC,
+ MMTuple(
+ MMString("double"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(0))));
+ ASSERT_TRUE(I);
+
+ I = matchNext(I,
+ MInstruction(Instruction::Store,
+ MConstInt(44, 32),
+ MMTuple(
+ SpecABC,
+ MMTuple(
+ MMString("int"),
+ OmnipotentCharCXX,
+ MConstInt(0)),
+ MConstInt(8))));
+ ASSERT_TRUE(I);
+}
+}
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index 70ce15f5a24e..b0e2ddd91362 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -2622,6 +2622,31 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
OS << " }\n";
}
+// Helper function for GenerateTargetSpecificAttrChecks that alters the 'Test'
+// parameter with only a single check type, if applicable.
+static void GenerateTargetSpecificAttrCheck(const Record *R, std::string &Test,
+ std::string *FnName,
+ StringRef ListName,
+ StringRef CheckAgainst,
+ StringRef Scope) {
+ if (!R->isValueUnset(ListName)) {
+ Test += " && (";
+ std::vector<StringRef> Items = R->getValueAsListOfStrings(ListName);
+ for (auto I = Items.begin(), E = Items.end(); I != E; ++I) {
+ StringRef Part = *I;
+ Test += CheckAgainst;
+ Test += " == ";
+ Test += Scope;
+ Test += Part;
+ if (I + 1 != E)
+ Test += " || ";
+ if (FnName)
+ *FnName += Part;
+ }
+ Test += ")";
+ }
+}
+
// Generate a conditional expression to check if the current target satisfies
// the conditions for a TargetSpecificAttr record, and append the code for
// those checks to the Test string. If the FnName string pointer is non-null,
@@ -2635,29 +2660,15 @@ static void GenerateTargetSpecificAttrChecks(const Record *R,
// named "T" and a TargetInfo object named "Target" within
// scope that can be used to determine whether the attribute exists in
// a given target.
- Test += "(";
-
- for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
- StringRef Part = *I;
- Test += "T.getArch() == llvm::Triple::";
- Test += Part;
- if (I + 1 != E)
- Test += " || ";
- if (FnName)
- *FnName += Part;
- }
- Test += ")";
-
- // If the attribute is specific to particular OSes, check those.
- if (!R->isValueUnset("OSes")) {
- // We know that there was at least one arch test, so we need to and in the
- // OS tests.
+ Test += "true";
+ // If one or more architectures is specified, check those. Arches are handled
+ // differently because GenerateTargetRequirements needs to combine the list
+ // with ParseKind.
+ if (!Arches.empty()) {
Test += " && (";
- std::vector<StringRef> OSes = R->getValueAsListOfStrings("OSes");
- for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
+ for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
StringRef Part = *I;
-
- Test += "T.getOS() == llvm::Triple::";
+ Test += "T.getArch() == llvm::Triple::";
Test += Part;
if (I + 1 != E)
Test += " || ";
@@ -2667,21 +2678,17 @@ static void GenerateTargetSpecificAttrChecks(const Record *R,
Test += ")";
}
+ // If the attribute is specific to particular OSes, check those.
+ GenerateTargetSpecificAttrCheck(R, Test, FnName, "OSes", "T.getOS()",
+ "llvm::Triple::");
+
// If one or more CXX ABIs are specified, check those as well.
- if (!R->isValueUnset("CXXABIs")) {
- Test += " && (";
- std::vector<StringRef> CXXABIs = R->getValueAsListOfStrings("CXXABIs");
- for (auto I = CXXABIs.begin(), E = CXXABIs.end(); I != E; ++I) {
- StringRef Part = *I;
- Test += "Target.getCXXABI().getKind() == TargetCXXABI::";
- Test += Part;
- if (I + 1 != E)
- Test += " || ";
- if (FnName)
- *FnName += Part;
- }
- Test += ")";
- }
+ GenerateTargetSpecificAttrCheck(R, Test, FnName, "CXXABIs",
+ "Target.getCXXABI().getKind()",
+ "TargetCXXABI::");
+ // If one or more object formats is specified, check those.
+ GenerateTargetSpecificAttrCheck(R, Test, FnName, "ObjectFormats",
+ "T.getObjectFormat()", "llvm::Triple::");
}
static void GenerateHasAttrSpellingStringSwitch(
@@ -3301,11 +3308,6 @@ static std::string GenerateTargetRequirements(const Record &Attr,
// Get the list of architectures to be tested for.
const Record *R = Attr.getValueAsDef("Target");
std::vector<StringRef> Arches = R->getValueAsListOfStrings("Arches");
- if (Arches.empty()) {
- PrintError(Attr.getLoc(), "Empty list of target architectures for a "
- "target-specific attr");
- return "defaultTargetRequirements";
- }
// If there are other attributes which share the same parsed attribute kind,
// such as target-specific attributes with a shared spelling, collapse the
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 49c1edce3220..6982bfc43db4 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -773,19 +773,19 @@ void Type::applyTypespec(bool &Quad) {
break;
case 'h':
Float = true;
- // Fall through
+ LLVM_FALLTHROUGH;
case 's':
ElementBitwidth = 16;
break;
case 'f':
Float = true;
- // Fall through
+ LLVM_FALLTHROUGH;
case 'i':
ElementBitwidth = 32;
break;
case 'd':
Float = true;
- // Fall through
+ LLVM_FALLTHROUGH;
case 'l':
ElementBitwidth = 64;
break;
@@ -860,6 +860,10 @@ void Type::applyModifier(char Mod) {
Float = true;
ElementBitwidth = 64;
break;
+ case 'H':
+ Float = true;
+ ElementBitwidth = 16;
+ break;
case 'g':
if (AppliedQuad)
Bitwidth /= 2;
@@ -1006,7 +1010,7 @@ std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const {
}
static bool isFloatingPointProtoModifier(char Mod) {
- return Mod == 'F' || Mod == 'f';
+ return Mod == 'F' || Mod == 'f' || Mod == 'H';
}
std::string Intrinsic::getBuiltinTypeStr() {