diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-24 01:00:23 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-24 01:00:23 +0000 |
commit | 6252156da5066bd47f63f8bd40404d1f89909d32 (patch) | |
tree | 743d1b59945b071890dc19b6bf5e9d3ff0d1399b | |
parent | 461a67fa15370a9ec88f8f8a240bf7c123bb2029 (diff) |
Vendor import of clang trunk r321414:vendor/clang/clang-trunk-r321414
Notes
Notes:
svn path=/vendor/clang/dist/; revision=327124
svn path=/vendor/clang/clang-trunk-r321414/; revision=327125; tag=vendor/clang/clang-trunk-r321414
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() { |