diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-08 17:13:11 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-08 17:13:11 +0000 |
commit | 0a5fb09b599c1bdea3cd11168bb8f4ff4040316e (patch) | |
tree | 5e94367d1a8032322c6871cfe16714c0982fd61a | |
parent | f0c0337bbfb63d1f9edf145aab535bdf82c20454 (diff) |
Vendor import of clang trunk r302418:vendor/clang/clang-trunk-r302418
Notes
Notes:
svn path=/vendor/clang/dist/; revision=317951
svn path=/vendor/clang/clang-trunk-r302418/; revision=317952; tag=vendor/clang/clang-trunk-r302418
112 files changed, 2865 insertions, 505 deletions
diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst index 187dae751be1..f8dd1a39c676 100644 --- a/docs/LanguageExtensions.rst +++ b/docs/LanguageExtensions.rst @@ -780,14 +780,14 @@ Use ``__has_feature(cxx_variadic_templates)`` or ``__has_extension(cxx_variadic_templates)`` to determine if support for variadic templates is enabled. -C++1y +C++14 ----- -The features listed below are part of the committee draft for the C++1y -standard. As a result, all these features are enabled with the ``-std=c++1y`` -or ``-std=gnu++1y`` option when compiling C++ code. +The features listed below are part of the C++14 standard. As a result, all +these features are enabled with the ``-std=C++14`` or ``-std=gnu++14`` option +when compiling C++ code. -C++1y binary literals +C++14 binary literals ^^^^^^^^^^^^^^^^^^^^^ Use ``__has_feature(cxx_binary_literals)`` or @@ -795,37 +795,37 @@ Use ``__has_feature(cxx_binary_literals)`` or binary literals (for instance, ``0b10010``) are recognized. Clang supports this feature as an extension in all language modes. -C++1y contextual conversions +C++14 contextual conversions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use ``__has_feature(cxx_contextual_conversions)`` or -``__has_extension(cxx_contextual_conversions)`` to determine if the C++1y rules +``__has_extension(cxx_contextual_conversions)`` to determine if the C++14 rules are used when performing an implicit conversion for an array bound in a *new-expression*, the operand of a *delete-expression*, an integral constant expression, or a condition in a ``switch`` statement. -C++1y decltype(auto) +C++14 decltype(auto) ^^^^^^^^^^^^^^^^^^^^ Use ``__has_feature(cxx_decltype_auto)`` or ``__has_extension(cxx_decltype_auto)`` to determine if support for the ``decltype(auto)`` placeholder type is enabled. -C++1y default initializers for aggregates +C++14 default initializers for aggregates ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use ``__has_feature(cxx_aggregate_nsdmi)`` or ``__has_extension(cxx_aggregate_nsdmi)`` to determine if support for default initializers in aggregate members is enabled. -C++1y digit separators +C++14 digit separators ^^^^^^^^^^^^^^^^^^^^^^ Use ``__cpp_digit_separators`` to determine if support for digit separators using single quotes (for instance, ``10'000``) is enabled. At this time, there is no corresponding ``__has_feature`` name -C++1y generalized lambda capture +C++14 generalized lambda capture ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use ``__has_feature(cxx_init_captures)`` or @@ -833,7 +833,7 @@ Use ``__has_feature(cxx_init_captures)`` or lambda captures with explicit initializers is enabled (for instance, ``[n(0)] { return ++n; }``). -C++1y generic lambdas +C++14 generic lambdas ^^^^^^^^^^^^^^^^^^^^^ Use ``__has_feature(cxx_generic_lambdas)`` or @@ -841,7 +841,7 @@ Use ``__has_feature(cxx_generic_lambdas)`` or (polymorphic) lambdas is enabled (for instance, ``[] (auto x) { return x + 1; }``). -C++1y relaxed constexpr +C++14 relaxed constexpr ^^^^^^^^^^^^^^^^^^^^^^^ Use ``__has_feature(cxx_relaxed_constexpr)`` or @@ -849,7 +849,7 @@ Use ``__has_feature(cxx_relaxed_constexpr)`` or declarations, local variable modification, and control flow constructs are permitted in ``constexpr`` functions. -C++1y return type deduction +C++14 return type deduction ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use ``__has_feature(cxx_return_type_deduction)`` or @@ -857,7 +857,7 @@ Use ``__has_feature(cxx_return_type_deduction)`` or for return type deduction for functions (using ``auto`` as a return type) is enabled. -C++1y runtime-sized arrays +C++14 runtime-sized arrays ^^^^^^^^^^^^^^^^^^^^^^^^^^ Use ``__has_feature(cxx_runtime_array)`` or @@ -866,7 +866,7 @@ for arrays of runtime bound (a restricted form of variable-length arrays) is enabled. Clang's implementation of this feature is incomplete. -C++1y variable templates +C++14 variable templates ^^^^^^^^^^^^^^^^^^^^^^^^ Use ``__has_feature(cxx_variable_templates)`` or diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 736e1dfcabcf..c91b2a249029 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -924,6 +924,19 @@ in </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxStdInitializerListExpr0')"><a name="cxxStdInitializerListExpr0Anchor">cxxStdInitializerListExpr</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXStdInitializerListExpr.html">CXXStdInitializerListExpr</a>>...</td></tr> +<tr><td colspan="4" class="doc" id="cxxStdInitializerListExpr0"><pre>Matches C++ initializer list expressions. + +Given + std::vector<int> a({ 1, 2, 3 }); + std::vector<int> b = { 4, 5 }; + int c[] = { 6, 7 }; + std::pair<int, int> d = { 8, 9 }; +cxxStdInitializerListExpr() + matches "{ 1, 2, 3 }" and "{ 4, 5 }" +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxTemporaryObjectExpr0')"><a name="cxxTemporaryObjectExpr0Anchor">cxxTemporaryObjectExpr</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>...</td></tr> <tr><td colspan="4" class="doc" id="cxxTemporaryObjectExpr0"><pre>Matches functional cast expressions having N != 1 arguments @@ -1160,7 +1173,7 @@ Example matches [&](){return 5;} <tr><td colspan="4" class="doc" id="materializeTemporaryExpr0"><pre>Matches nodes where temporaries are materialized. Example: Given - struct T {void func()}; + struct T {void func();}; T f(); void g(T); materializeTemporaryExpr() matches 'f()' in these statements @@ -5233,7 +5246,7 @@ Example matches y in x(y) <tr><td colspan="4" class="doc" id="hasReceiverType0"><pre>Matches on the receiver of an ObjectiveC Message expression. Example -matcher = objCMessageExpr(hasRecieverType(asString("UIWebView *"))); +matcher = objCMessageExpr(hasReceiverType(asString("UIWebView *"))); matches the [webView ...] message invocation. NSString *webViewJavaScript = ... UIWebView *webView = ... diff --git a/docs/SanitizerCoverage.rst b/docs/SanitizerCoverage.rst index 1c42b4236a93..06bafd6b3a04 100644 --- a/docs/SanitizerCoverage.rst +++ b/docs/SanitizerCoverage.rst @@ -144,8 +144,9 @@ Use these flags together with ``trace-pc-guard`` or ``trace-pc``, like this: ``-fsanitize-coverage=func,trace-pc-guard``. When ``edge`` or ``bb`` is used, some of the edges/blocks may still be left -uninstrumented if such instrumentation is considered redundant. -**TODO**: add a user-visible option to disable the optimization. +uninstrumented (pruned) if such instrumentation is considered redundant. +Use ``no-prune`` (e.g. ``-fsanitize-coverage=bb,no-prune,trace-pc-guard``) +to disable pruning. This could be useful for better coverage visualization. Edge coverage diff --git a/docs/ThreadSafetyAnalysis.rst b/docs/ThreadSafetyAnalysis.rst index 19ec2352ff2b..47cf4ef3994e 100644 --- a/docs/ThreadSafetyAnalysis.rst +++ b/docs/ThreadSafetyAnalysis.rst @@ -764,8 +764,6 @@ implementation. #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op #endif - #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) - #define CAPABILITY(x) \ THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) diff --git a/include/clang/AST/ODRHash.h b/include/clang/AST/ODRHash.h index 9af8488fca10..e4cc12d35891 100644 --- a/include/clang/AST/ODRHash.h +++ b/include/clang/AST/ODRHash.h @@ -25,7 +25,7 @@ namespace clang { class Decl; class IdentifierInfo; -class NestedNameSpecifer; +class NestedNameSpecifier; class Stmt; class TemplateParameterList; diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index f11469b8fc20..0ab8d5fe4fc1 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -1223,6 +1223,20 @@ AST_MATCHER_P(InitListExpr, hasSyntacticForm, InnerMatcher.matches(*SyntForm, Finder, Builder)); } +/// \brief Matches C++ initializer list expressions. +/// +/// Given +/// \code +/// std::vector<int> a({ 1, 2, 3 }); +/// std::vector<int> b = { 4, 5 }; +/// int c[] = { 6, 7 }; +/// std::pair<int, int> d = { 8, 9 }; +/// \endcode +/// cxxStdInitializerListExpr() +/// matches "{ 1, 2, 3 }" and "{ 4, 5 }" +const internal::VariadicDynCastAllOfMatcher<Stmt, + CXXStdInitializerListExpr> cxxStdInitializerListExpr; + /// \brief Matches implicit initializers of init list expressions. /// /// Given diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 04a948a6c46e..3eeeb1bdc971 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -864,6 +864,13 @@ def OpenCLUnrollHint : InheritableAttr { let Documentation = [OpenCLUnrollHintDocs]; } +def OpenCLIntelReqdSubGroupSize: InheritableAttr { + let Spellings = [GNU<"intel_reqd_sub_group_size">]; + let Args = [UnsignedArgument<"SubGroupSize">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [OpenCLIntelReqdSubGroupSizeDocs]; +} + // This attribute is both a type attribute, and a declaration attribute (for // parameter variables). def OpenCLAccess : Attr { diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index be2a91515ae8..9e2fdf4834aa 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -2216,6 +2216,21 @@ s6.11.5 for details. }]; } +def OpenCLIntelReqdSubGroupSizeDocs : Documentation { + let Category = DocCatStmt; + let Heading = "__attribute__((intel_reqd_sub_group_size))"; + let Content = [{ +The optional attribute intel_reqd_sub_group_size can be used to indicate that +the kernel must be compiled and executed with the specified subgroup size. When +this attribute is present, get_max_sub_group_size() is guaranteed to return the +specified integer value. This is important for the correctness of many subgroup +algorithms, and in some cases may be used by the compiler to generate more optimal +code. See `cl_intel_required_subgroup_size +<https://www.khronos.org/registry/OpenCL/extensions/intel/cl_intel_required_subgroup_size.txt>` +for details. + }]; +} + def OpenCLAccessDocs : Documentation { let Category = DocCatStmt; let Heading = "__read_only, __write_only, __read_write (read_only, write_only, read_write)"; diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def index 6cc7308d4cbc..e8db347d4be5 100644 --- a/include/clang/Basic/BuiltinsARM.def +++ b/include/clang/Basic/BuiltinsARM.def @@ -25,11 +25,93 @@ // In libgcc BUILTIN(__clear_cache, "vv*v*", "i") +// 16-bit multiplications +BUILTIN(__builtin_arm_smulbb, "iii", "nc") +BUILTIN(__builtin_arm_smulbt, "iii", "nc") +BUILTIN(__builtin_arm_smultb, "iii", "nc") +BUILTIN(__builtin_arm_smultt, "iii", "nc") +BUILTIN(__builtin_arm_smulwb, "iii", "nc") +BUILTIN(__builtin_arm_smulwt, "iii", "nc") + // Saturating arithmetic BUILTIN(__builtin_arm_qadd, "iii", "nc") BUILTIN(__builtin_arm_qsub, "iii", "nc") BUILTIN(__builtin_arm_ssat, "iiUi", "nc") -BUILTIN(__builtin_arm_usat, "UiUiUi", "nc") +BUILTIN(__builtin_arm_usat, "UiiUi", "nc") + +BUILTIN(__builtin_arm_smlabb, "iiii", "nc") +BUILTIN(__builtin_arm_smlabt, "iiii", "nc") +BUILTIN(__builtin_arm_smlatb, "iiii", "nc") +BUILTIN(__builtin_arm_smlatt, "iiii", "nc") +BUILTIN(__builtin_arm_smlawb, "iiii", "nc") +BUILTIN(__builtin_arm_smlawt, "iiii", "nc") + +BUILTIN(__builtin_arm_ssat16, "iii", "nc") +BUILTIN(__builtin_arm_usat16, "iii", "nc") + +BUILTIN(__builtin_arm_sxtab16, "iii", "nc") +BUILTIN(__builtin_arm_sxtb16, "ii", "nc") +BUILTIN(__builtin_arm_uxtab16, "iii", "nc") +BUILTIN(__builtin_arm_uxtb16, "ii", "nc") + +BUILTIN(__builtin_arm_sel, "iii", "nc") + +BUILTIN(__builtin_arm_qadd8, "iii", "nc") +BUILTIN(__builtin_arm_qsub8, "iii", "nc") +BUILTIN(__builtin_arm_sadd8, "iii", "nc") +BUILTIN(__builtin_arm_shadd8, "iii", "nc") +BUILTIN(__builtin_arm_shsub8, "iii", "nc") +BUILTIN(__builtin_arm_ssub8, "iii", "nc") +BUILTIN(__builtin_arm_uadd8, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uhadd8, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uhsub8, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uqadd8, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uqsub8, "UiUiUi", "nc") +BUILTIN(__builtin_arm_usub8, "UiUiUi", "nc") + +// Sum of 8-bit absolute differences +BUILTIN(__builtin_arm_usad8, "UiUiUi", "nc") +BUILTIN(__builtin_arm_usada8, "UiUiUiUi", "nc") + +// Parallel 16-bit addition and subtraction +BUILTIN(__builtin_arm_qadd16, "iii", "nc") +BUILTIN(__builtin_arm_qasx, "iii", "nc") +BUILTIN(__builtin_arm_qsax, "iii", "nc") +BUILTIN(__builtin_arm_qsub16, "iii", "nc") +BUILTIN(__builtin_arm_sadd16, "iii", "nc") +BUILTIN(__builtin_arm_sasx, "iii", "nc") +BUILTIN(__builtin_arm_shadd16, "iii", "nc") +BUILTIN(__builtin_arm_shasx, "iii", "nc") +BUILTIN(__builtin_arm_shsax, "iii", "nc") +BUILTIN(__builtin_arm_shsub16, "iii", "nc") +BUILTIN(__builtin_arm_ssax, "iii", "nc") +BUILTIN(__builtin_arm_ssub16, "iii", "nc") +BUILTIN(__builtin_arm_uadd16, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uasx, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uhadd16, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uhasx, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uhsax, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uhsub16, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uqadd16, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uqasx, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uqsax, "UiUiUi", "nc") +BUILTIN(__builtin_arm_uqsub16, "UiUiUi", "nc") +BUILTIN(__builtin_arm_usax, "UiUiUi", "nc") +BUILTIN(__builtin_arm_usub16, "UiUiUi", "nc") + +// Parallel 16-bit multiplication +BUILTIN(__builtin_arm_smlad, "iiii", "nc") +BUILTIN(__builtin_arm_smladx, "iiii", "nc") +BUILTIN(__builtin_arm_smlald, "LLiiiLLi", "nc") +BUILTIN(__builtin_arm_smlaldx, "LLiiiLLi", "nc") +BUILTIN(__builtin_arm_smlsd, "iiii", "nc") +BUILTIN(__builtin_arm_smlsdx, "iiii", "nc") +BUILTIN(__builtin_arm_smlsld, "LLiiiLLi", "nc") +BUILTIN(__builtin_arm_smlsldx, "LLiiiLLi", "nc") +BUILTIN(__builtin_arm_smuad, "iii", "nc") +BUILTIN(__builtin_arm_smuadx, "iii", "nc") +BUILTIN(__builtin_arm_smusd, "iii", "nc") +BUILTIN(__builtin_arm_smusdx, "iii", "nc") // Bit manipulation BUILTIN(__builtin_arm_rbit, "UiUi", "nc") diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index c8a3c2f4d3ab..68b868ce8e6e 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -668,6 +668,12 @@ TARGET_BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "", "bmi2") // TBM TARGET_BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "", "tbm") +// LWP +TARGET_BUILTIN(__builtin_ia32_llwpcb, "vv*", "", "lwp") +TARGET_BUILTIN(__builtin_ia32_slwpcb, "v*", "", "lwp") +TARGET_BUILTIN(__builtin_ia32_lwpins32, "UcUiUiUi", "", "lwp") +TARGET_BUILTIN(__builtin_ia32_lwpval32, "vUiUiUi", "", "lwp") + // SHA TARGET_BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "", "sha") TARGET_BUILTIN(__builtin_ia32_sha1nexte, "V4iV4iV4i", "", "sha") diff --git a/include/clang/Basic/BuiltinsX86_64.def b/include/clang/Basic/BuiltinsX86_64.def index d38f522c3812..2851184c2c84 100644 --- a/include/clang/Basic/BuiltinsX86_64.def +++ b/include/clang/Basic/BuiltinsX86_64.def @@ -69,6 +69,8 @@ TARGET_BUILTIN(__builtin_ia32_bzhi_di, "ULLiULLiULLi", "", "bmi2") TARGET_BUILTIN(__builtin_ia32_pdep_di, "ULLiULLiULLi", "", "bmi2") TARGET_BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "", "bmi2") TARGET_BUILTIN(__builtin_ia32_bextri_u64, "ULLiULLiIULLi", "", "tbm") +TARGET_BUILTIN(__builtin_ia32_lwpins64, "UcULLiUiUi", "", "lwp") +TARGET_BUILTIN(__builtin_ia32_lwpval64, "vULLiUiUi", "", "lwp") TARGET_BUILTIN(__builtin_ia32_pbroadcastq512_gpr_mask, "V8LLiLLiV8LLiUc", "", "avx512f") TARGET_BUILTIN(__builtin_ia32_pbroadcastq128_gpr_mask, "V2LLiULLiV2LLiUc","","avx512vl") TARGET_BUILTIN(__builtin_ia32_pbroadcastq256_gpr_mask, "V4LLiULLiV4LLiUc","","avx512vl") diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index cd284e94303b..77db8993f018 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -475,8 +475,6 @@ def warn_pragma_pop_macro_no_push : Warning< def warn_pragma_message : Warning<"%0">, InGroup<PoundPragmaMessage>, DefaultWarnNoWerror; def err_pragma_message : Error<"%0">; -def err_pragma_module_import_expected_module_name : Error< - "expected %select{identifier in|'.' or end of directive after}0 module name">; def warn_pragma_ignored : Warning<"unknown pragma ignored">, InGroup<UnknownPragmas>, DefaultIgnore; def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, @@ -511,6 +509,22 @@ def warn_pragma_debug_unexpected_command : Warning< "unexpected debug command '%0'">, InGroup<IgnoredPragmas>; def warn_pragma_debug_missing_argument : Warning< "missing argument to debug command '%0'">, InGroup<IgnoredPragmas>; +// #pragma module +def err_pp_expected_module_name : Error< + "expected %select{identifier after '.' in |}0module name">; +def err_pp_module_begin_wrong_module : Error< + "must specify '-fmodule-name=%0' to enter %select{|submodule of }1" + "this module%select{ (current module is %3)|}2">; +def err_pp_module_begin_no_module_map : Error< + "no module map available for module %0">; +def err_pp_module_begin_no_submodule : Error< + "submodule %0.%1 not declared in module map">; +def err_pp_module_begin_without_module_end : Error< + "no matching '#pragma clang module end' for this " + "'#pragma clang module begin'">; +def err_pp_module_end_without_module_begin : Error< + "no matching '#pragma clang module begin' for this " + "'#pragma clang module end'">; def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">; def err_paste_at_start : Error< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 6a3a2124a5ff..a0c0e5f86449 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -730,6 +730,9 @@ def err_super_in_lambda_unsupported : Error< def warn_pragma_unused_undeclared_var : Warning< "undeclared variable %0 used as an argument for '#pragma unused'">, InGroup<IgnoredPragmas>; +def warn_atl_uuid_deprecated : Warning< + "specifying 'uuid' as an ATL attribute is deprecated; use __declspec instead">, + InGroup<DeprecatedDeclarations>; def warn_pragma_unused_expected_var_arg : Warning< "only variables can be arguments to '#pragma unused'">, InGroup<IgnoredPragmas>; @@ -2088,7 +2091,7 @@ def err_enum_invalid_underlying : Error< "non-integral type %0 is an invalid underlying type">; def err_enumerator_too_large : Error< "enumerator value is not representable in the underlying type %0">; -def ext_enumerator_too_large : ExtWarn< +def ext_enumerator_too_large : Extension< "enumerator value is not representable in the underlying type %0">, InGroup<MicrosoftEnumValue>; def err_enumerator_wrapped : Error< @@ -2868,7 +2871,8 @@ def warn_partial_availability : Warning<"%0 is only available conditionally">, def note_partial_availability_silence : Note< "explicitly redeclare %0 to silence this warning">; def note_unguarded_available_silence : Note< - "enclose %0 in an @available check to silence this warning">; + "enclose %0 in %select{an @available|a __builtin_available}1 check to silence" + " this warning">; def warn_partial_message : Warning<"%0 is partial: %1">, InGroup<UnguardedAvailability>, DefaultIgnore; def warn_partial_fwdclass_message : Warning< @@ -4759,7 +4763,7 @@ def ext_forward_ref_enum : Extension< "ISO C forbids forward references to 'enum' types">; def err_forward_ref_enum : Error< "ISO C++ forbids forward references to 'enum' types">; -def ext_ms_forward_ref_enum : Extension< +def ext_ms_forward_ref_enum : ExtWarn< "forward references to 'enum' types are a Microsoft extension">, InGroup<MicrosoftEnumForwardReference>; def ext_forward_ref_enum_def : Extension< @@ -7920,7 +7924,11 @@ def warn_empty_switch_body : Warning< def note_empty_body_on_separate_line : Note< "put the semicolon on a separate line to silence this warning">; -def err_va_start_used_in_non_variadic_function : Error< +def err_va_start_captured_stmt : Error< + "'va_start' cannot be used in a captured statement">; +def err_va_start_outside_function : Error< + "'va_start' cannot be used outside a function">; +def err_va_start_fixed_function : Error< "'va_start' used in function with fixed args">; def err_va_start_used_in_wrong_abi_function : Error< "'va_start' used in %select{System V|Win64}0 ABI function">; @@ -8297,6 +8305,8 @@ def err_sampler_argument_required : Error< "sampler_t variable required - got %0">; def err_wrong_sampler_addressspace: Error< "sampler type cannot be used with the __local and __global address space qualifiers">; +def err_opencl_nonconst_global_sampler : Error< + "global sampler requires a const or constant address space qualifier">; def err_opencl_cast_non_zero_to_event_t : Error< "cannot cast non-zero value '%0' to 'event_t'">; def err_opencl_global_invalid_addr_space : Error< @@ -8971,6 +8981,9 @@ def warn_nullability_lost : Warning< "implicit conversion from nullable pointer %0 to non-nullable pointer " "type %1">, InGroup<NullableToNonNullConversion>, DefaultIgnore; +def warn_zero_as_null_pointer_constant : Warning< + "zero as null pointer constant">, + InGroup<DiagGroup<"zero-as-null-pointer-constant">>, DefaultIgnore; def err_nullability_cs_multilevel : Error< "nullability keyword %0 cannot be applied to multi-level pointer type %1">; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 63348c094c93..bd2062d967b4 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -297,6 +297,9 @@ def fsanitize_coverage_trace_pc def fsanitize_coverage_trace_pc_guard : Flag<["-"], "fsanitize-coverage-trace-pc-guard">, HelpText<"Enable PC tracing with guard in sanitizer coverage">; +def fsanitize_coverage_no_prune + : Flag<["-"], "fsanitize-coverage-no-prune">, + HelpText<"Disable coverage pruning (i.e. instrument all blocks/edges)">; def fprofile_instrument_EQ : Joined<["-"], "fprofile-instrument=">, HelpText<"Enable PGO instrumentation. The accepted value is clang, llvm, " "or none">; diff --git a/include/clang/Driver/Distro.h b/include/clang/Driver/Distro.h index e2fb8b643350..fab49862a442 100644 --- a/include/clang/Driver/Distro.h +++ b/include/clang/Driver/Distro.h @@ -57,6 +57,7 @@ public: UbuntuXenial, UbuntuYakkety, UbuntuZesty, + UbuntuArtful, UnknownDistro }; @@ -110,9 +111,9 @@ public: } bool IsUbuntu() const { - return DistroVal >= UbuntuHardy && DistroVal <= UbuntuZesty; + return DistroVal >= UbuntuHardy && DistroVal <= UbuntuArtful; } - + /// @} }; diff --git a/include/clang/Driver/Multilib.h b/include/clang/Driver/Multilib.h index 0419186b745d..36d2493b1afc 100644 --- a/include/clang/Driver/Multilib.h +++ b/include/clang/Driver/Multilib.h @@ -70,13 +70,21 @@ public: /// All elements begin with either '+' or '-' const flags_list &flags() const { return Flags; } flags_list &flags() { return Flags; } + /// Add a flag to the flags list + /// \p Flag must be a flag accepted by the driver with its leading '-' removed, + /// and replaced with either: + /// '-' which contraindicates using this multilib with that flag + /// or: + /// '+' which promotes using this multilib in the presence of that flag + /// otherwise '-print-multi-lib' will not emit them correctly. Multilib &flag(StringRef F) { assert(F.front() == '+' || F.front() == '-'); Flags.push_back(F); return *this; } + LLVM_DUMP_METHOD void dump() const; /// \brief print summary of the Multilib void print(raw_ostream &OS) const; @@ -150,6 +158,7 @@ public: unsigned size() const { return Multilibs.size(); } + LLVM_DUMP_METHOD void dump() const; void print(raw_ostream &OS) const; MultilibSet &setIncludeDirsCallback(IncludeDirsFunc F) { diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 1272a36ecc70..31015228f362 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1688,6 +1688,8 @@ def mllvm : Separate<["-"], "mllvm">, Flags<[CC1Option,CC1AsOption,CoreOption]>, HelpText<"Additional arguments to forward to LLVM's option processing">; def mmacosx_version_min_EQ : Joined<["-"], "mmacosx-version-min=">, Group<m_Group>, HelpText<"Set Mac OS X deployment target">; +def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">, + Group<m_Group>, Alias<mmacosx_version_min_EQ>; def mms_bitfields : Flag<["-"], "mms-bitfields">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard">; def mno_ms_bitfields : Flag<["-"], "mno-ms-bitfields">, Group<m_Group>, @@ -1750,6 +1752,7 @@ def mno_bmi : Flag<["-"], "mno-bmi">, Group<m_x86_Features_Group>; def mno_bmi2 : Flag<["-"], "mno-bmi2">, Group<m_x86_Features_Group>; def mno_popcnt : Flag<["-"], "mno-popcnt">, Group<m_x86_Features_Group>; def mno_tbm : Flag<["-"], "mno-tbm">, Group<m_x86_Features_Group>; +def mno_lwp : Flag<["-"], "mno-lwp">, Group<m_x86_Features_Group>; def mno_fma4 : Flag<["-"], "mno-fma4">, Group<m_x86_Features_Group>; def mno_fma : Flag<["-"], "mno-fma">, Group<m_x86_Features_Group>; def mno_xop : Flag<["-"], "mno-xop">, Group<m_x86_Features_Group>; @@ -1949,6 +1952,7 @@ def mbmi : Flag<["-"], "mbmi">, Group<m_x86_Features_Group>; def mbmi2 : Flag<["-"], "mbmi2">, Group<m_x86_Features_Group>; def mpopcnt : Flag<["-"], "mpopcnt">, Group<m_x86_Features_Group>; def mtbm : Flag<["-"], "mtbm">, Group<m_x86_Features_Group>; +def mlwp : Flag<["-"], "mlwp">, Group<m_x86_Features_Group>; def mfma4 : Flag<["-"], "mfma4">, Group<m_x86_Features_Group>; def mfma : Flag<["-"], "mfma">, Group<m_x86_Features_Group>; def mxop : Flag<["-"], "mxop">, Group<m_x86_Features_Group>; diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 0b7d466ab3d4..7495ad808c99 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -160,6 +160,7 @@ CODEGENOPT(SanitizeCoverageTracePC, 1, 0) ///< Enable PC tracing ///< in sanitizer coverage. CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard ///< in sanitizer coverage. +CODEGENOPT(SanitizeCoverageNoPrune, 1, 0) ///< Disable coverage pruning. CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers. CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h index 384499a3d82a..8d690a448f85 100644 --- a/include/clang/Frontend/FrontendAction.h +++ b/include/clang/Frontend/FrontendAction.h @@ -146,6 +146,8 @@ public: return *CurrentASTUnit; } + Module *getCurrentModule() const; + std::unique_ptr<ASTUnit> takeCurrentASTUnit() { return std::move(CurrentASTUnit); } diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 64c6f2a03f2b..6e24e1893ab6 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -538,9 +538,15 @@ public: /// /// \param File The module map file. /// \param IsSystem Whether this file is in a system header directory. + /// \param ID If the module map file is already mapped (perhaps as part of + /// processing a preprocessed module), the ID of the file. + /// \param Offset [inout] An offset within ID to start parsing. On exit, + /// filled by the end of the parsed contents (either EOF or the + /// location of an end-of-module-map pragma). /// /// \returns true if an error occurred, false otherwise. - bool loadModuleMapFile(const FileEntry *File, bool IsSystem); + bool loadModuleMapFile(const FileEntry *File, bool IsSystem, + FileID ID = FileID(), unsigned *Offset = nullptr); /// \brief Collect the set of all known, top-level modules. /// @@ -686,7 +692,9 @@ private: LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File, bool IsSystem, - const DirectoryEntry *Dir); + const DirectoryEntry *Dir, + FileID ID = FileID(), + unsigned *Offset = nullptr); /// \brief Try to load the module map file in the given directory. /// diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 6ac6316d1248..3be733167e5c 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -478,6 +478,11 @@ public: return getCharAndSizeSlowNoWarn(Ptr, Size, LangOpts); } + /// Returns the leading whitespace for line that corresponds to the given + /// location \p Loc. + static StringRef getIndentationForLine(SourceLocation Loc, + const SourceManager &SM); + //===--------------------------------------------------------------------===// // Internal implementation interfaces. private: diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 46136725d87a..0fd6abe2f7d0 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -546,14 +546,20 @@ public: /// \param HomeDir The directory in which relative paths within this module /// map file will be resolved. /// + /// \param ID The FileID of the file to process, if we've already entered it. + /// + /// \param Offset [inout] On input the offset at which to start parsing. On + /// output, the offset at which the module map terminated. + /// /// \param ExternModuleLoc The location of the "extern module" declaration /// that caused us to load this module map file, if any. /// /// \returns true if an error occurred, false otherwise. bool parseModuleMapFile(const FileEntry *File, bool IsSystem, - const DirectoryEntry *HomeDir, + const DirectoryEntry *HomeDir, FileID ID = FileID(), + unsigned *Offset = nullptr, SourceLocation ExternModuleLoc = SourceLocation()); - + /// \brief Dump the contents of the module map, for debugging purposes. void dump(); diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index b1a7325c3426..0e3f563785d4 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -324,7 +324,7 @@ class Preprocessor { /// \brief If the current lexer is for a submodule that is being built, this /// is that submodule. - Module *CurSubmodule; + Module *CurLexerSubmodule; /// \brief Keeps track of the stack of files currently /// \#included, and macros currently being expanded from, not counting @@ -507,16 +507,19 @@ class Preprocessor { /// \brief Information about a submodule that we're currently building. struct BuildingSubmoduleInfo { - BuildingSubmoduleInfo(Module *M, SourceLocation ImportLoc, + BuildingSubmoduleInfo(Module *M, SourceLocation ImportLoc, bool IsPragma, SubmoduleState *OuterSubmoduleState, unsigned OuterPendingModuleMacroNames) - : M(M), ImportLoc(ImportLoc), OuterSubmoduleState(OuterSubmoduleState), + : M(M), ImportLoc(ImportLoc), IsPragma(IsPragma), + OuterSubmoduleState(OuterSubmoduleState), OuterPendingModuleMacroNames(OuterPendingModuleMacroNames) {} /// The module that we are building. Module *M; /// The location at which the module was included. SourceLocation ImportLoc; + /// Whether we entered this submodule via a pragma. + bool IsPragma; /// The previous SubmoduleState. SubmoduleState *OuterSubmoduleState; /// The number of pending module macro names when we started building this. @@ -773,8 +776,9 @@ public: /// expansions going on at the time. PreprocessorLexer *getCurrentFileLexer() const; - /// \brief Return the submodule owning the file being lexed. - Module *getCurrentSubmodule() const { return CurSubmodule; } + /// \brief Return the submodule owning the file being lexed. This may not be + /// the current module if we have changed modules since entering the file. + Module *getCurrentLexerSubmodule() const { return CurLexerSubmodule; } /// \brief Returns the FileID for the preprocessor predefines. FileID getPredefinesFileID() const { return PredefinesFileID; } @@ -1726,13 +1730,16 @@ public: bool CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef, bool *ShadowFlag = nullptr); -private: + void EnterSubmodule(Module *M, SourceLocation ImportLoc, bool ForPragma); + Module *LeaveSubmodule(bool ForPragma); +private: void PushIncludeMacroStack() { assert(CurLexerKind != CLK_CachingLexer && "cannot push a caching lexer"); - IncludeMacroStack.emplace_back( - CurLexerKind, CurSubmodule, std::move(CurLexer), std::move(CurPTHLexer), - CurPPLexer, std::move(CurTokenLexer), CurDirLookup); + IncludeMacroStack.emplace_back(CurLexerKind, CurLexerSubmodule, + std::move(CurLexer), std::move(CurPTHLexer), + CurPPLexer, std::move(CurTokenLexer), + CurDirLookup); CurPPLexer = nullptr; } @@ -1742,16 +1749,13 @@ private: CurPPLexer = IncludeMacroStack.back().ThePPLexer; CurTokenLexer = std::move(IncludeMacroStack.back().TheTokenLexer); CurDirLookup = IncludeMacroStack.back().TheDirLookup; - CurSubmodule = IncludeMacroStack.back().TheSubmodule; + CurLexerSubmodule = IncludeMacroStack.back().TheSubmodule; CurLexerKind = IncludeMacroStack.back().CurLexerKind; IncludeMacroStack.pop_back(); } void PropagateLineStartLeadingSpaceInfo(Token &Result); - void EnterSubmodule(Module *M, SourceLocation ImportLoc); - void LeaveSubmodule(); - /// Determine whether we need to create module macros for #defines in the /// current context. bool needModuleMacros() const; @@ -1967,7 +1971,6 @@ public: void HandlePragmaPoison(); void HandlePragmaSystemHeader(Token &SysHeaderTok); void HandlePragmaDependency(Token &DependencyTok); - void HandlePragmaModuleImport(Token &Tok); void HandlePragmaPushMacro(Token &Tok); void HandlePragmaPopMacro(Token &Tok); void HandlePragmaIncludeAlias(Token &Tok); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index eca383bee2f5..e5961079f7c2 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3766,6 +3766,9 @@ public: void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType, SourceLocation Loc); + /// Warn when implicitly casting 0 to nullptr. + void diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E); + ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) { return DelayedDiagnostics.push(pool); } diff --git a/include/clang/Tooling/FixIt.h b/include/clang/Tooling/FixIt.h index e2259d4357bc..c1e508849280 100644 --- a/include/clang/Tooling/FixIt.h +++ b/include/clang/Tooling/FixIt.h @@ -65,6 +65,13 @@ FixItHint createReplacement(const D &Destination, const S &Source, getText(Source, Context)); } +// \brief Returns a FixItHint to replace \p Destination by \p Source. +template <typename D> +FixItHint createReplacement(const D &Destination, StringRef Source) { + return FixItHint::CreateReplacement(internal::getSourceRange(Destination), + Source); +} + } // end namespace fixit } // end namespace tooling } // end namespace clang diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp index 6f935620888f..26743d86f5e7 100644 --- a/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/lib/ASTMatchers/Dynamic/Registry.cpp @@ -153,6 +153,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(cxxRecordDecl); REGISTER_MATCHER(cxxReinterpretCastExpr); REGISTER_MATCHER(cxxStaticCastExpr); + REGISTER_MATCHER(cxxStdInitializerListExpr); REGISTER_MATCHER(cxxTemporaryObjectExpr); REGISTER_MATCHER(cxxThisExpr); REGISTER_MATCHER(cxxThrowExpr); diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index 6bdef78c074f..c355445dc1e7 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -146,10 +146,9 @@ void DiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1, } void DiagnosticsEngine::ReportDelayed() { - Report(DelayedDiagID) << DelayedDiagArg1 << DelayedDiagArg2; + unsigned ID = DelayedDiagID; DelayedDiagID = 0; - DelayedDiagArg1.clear(); - DelayedDiagArg2.clear(); + Report(ID) << DelayedDiagArg1 << DelayedDiagArg2; } void DiagnosticsEngine::DiagStateMap::appendFirst( @@ -420,11 +419,10 @@ bool DiagnosticsEngine::EmitCurrentDiagnostic(bool Force) { } // Clear out the current diagnostic object. - unsigned DiagID = CurDiagID; Clear(); // If there was a delayed diagnostic, emit it now. - if (!Force && DelayedDiagID && DelayedDiagID != DiagID) + if (!Force && DelayedDiagID) ReportDelayed(); return Emitted; diff --git a/lib/Basic/DiagnosticIDs.cpp b/lib/Basic/DiagnosticIDs.cpp index 2852b40026c2..ce493c1e5cab 100644 --- a/lib/Basic/DiagnosticIDs.cpp +++ b/lib/Basic/DiagnosticIDs.cpp @@ -666,6 +666,10 @@ bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { } } + // Make sure we set FatalErrorOccurred to ensure that the notes from the + // diagnostic that caused `fatal_too_many_errors` won't be emitted. + if (Diag.CurDiagID == diag::fatal_too_many_errors) + Diag.FatalErrorOccurred = true; // Finally, report it. EmitDiag(Diag, DiagLevel); return true; diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 78b03b1c314a..33eb0b05ddcd 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -2591,6 +2591,7 @@ class X86TargetInfo : public TargetInfo { bool HasRDSEED = false; bool HasADX = false; bool HasTBM = false; + bool HasLWP = false; bool HasFMA = false; bool HasF16C = false; bool HasAVX512CD = false; @@ -3363,6 +3364,7 @@ bool X86TargetInfo::initFeatureMap( case CK_BDVER1: // xop implies avx, sse4a and fma4. setFeatureEnabledImpl(Features, "xop", true); + setFeatureEnabledImpl(Features, "lwp", true); setFeatureEnabledImpl(Features, "lzcnt", true); setFeatureEnabledImpl(Features, "aes", true); setFeatureEnabledImpl(Features, "pclmul", true); @@ -3634,6 +3636,8 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasADX = true; } else if (Feature == "+tbm") { HasTBM = true; + } else if (Feature == "+lwp") { + HasLWP = true; } else if (Feature == "+fma") { HasFMA = true; } else if (Feature == "+f16c") { @@ -3949,6 +3953,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasTBM) Builder.defineMacro("__TBM__"); + if (HasLWP) + Builder.defineMacro("__LWP__"); + if (HasMWAITX) Builder.defineMacro("__MWAITX__"); @@ -4132,6 +4139,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("sse4.2", SSELevel >= SSE42) .Case("sse4a", XOPLevel >= SSE4A) .Case("tbm", HasTBM) + .Case("lwp", HasLWP) .Case("x86", true) .Case("x86_32", getTriple().getArch() == llvm::Triple::x86) .Case("x86_64", getTriple().getArch() == llvm::Triple::x86_64) @@ -5443,6 +5451,7 @@ public: .Case("softfloat", SoftFloat) .Case("thumb", isThumb()) .Case("neon", (FPU & NeonFPU) && !SoftFloat) + .Case("vfp", FPU && !SoftFloat) .Case("hwdiv", HWDiv & HWDivThumb) .Case("hwdiv-arm", HWDiv & HWDivARM) .Default(false); diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 03883805199f..0d96f2efa60a 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -185,6 +185,7 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder, Opts.Use8bitCounters = CGOpts.SanitizeCoverage8bitCounters; Opts.TracePC = CGOpts.SanitizeCoverageTracePC; Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard; + Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune; PM.add(createSanitizerCoverageModulePass(Opts)); } @@ -974,10 +975,14 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, // via a WriteIndexesThinBackend. FunctionImporter::ImportMapTy ImportList; for (auto &GlobalList : *CombinedIndex) { + // Ignore entries for undefined references. + if (GlobalList.second.SummaryList.empty()) + continue; + auto GUID = GlobalList.first; - assert(GlobalList.second.size() == 1 && + assert(GlobalList.second.SummaryList.size() == 1 && "Expected individual combined index to have one summary per GUID"); - auto &Summary = GlobalList.second[0]; + auto &Summary = GlobalList.second.SummaryList[0]; // Skip the summaries for the importing module. These are included to // e.g. record required linkage changes. if (Summary->modulePath() == M->getModuleIdentifier()) diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 791a57e61f53..2b2a92dd6019 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -623,9 +623,13 @@ static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) { // For const-qualified captures, emit clang.arc.use to ensure the captured // object doesn't get released while we are still depending on its validity // within the block. - if (VT.isConstQualified() && VT.getObjCLifetime() == Qualifiers::OCL_Strong) + if (VT.isConstQualified() && + VT.getObjCLifetime() == Qualifiers::OCL_Strong && + CGF.CGM.getCodeGenOpts().OptimizationLevel != 0) { + assert(CGF.CGM.getLangOpts().ObjCAutoRefCount && + "expected ObjC ARC to be enabled"); destroyer = CodeGenFunction::emitARCIntrinsicUse; - else if (dtorKind == QualType::DK_objc_strong_lifetime) { + } else if (dtorKind == QualType::DK_objc_strong_lifetime) { destroyer = CodeGenFunction::destroyARCStrongImprecise; } else { destroyer = CGF.getDestroyer(dtorKind); diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 6ea0a325a429..2f05c0e910e5 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -2751,7 +2751,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, // Push a clang.arc.use cleanup for each object in RetainableOperands. The // cleanup will cause the use to appear after the final log call, keeping - // the object valid while it’s held in the log buffer. Note that if there’s + // the object valid while it's held in the log buffer. Note that if there's // a release cleanup on the object, it will already be active; since // cleanups are emitted in reverse order, the use will occur before the // object is released. diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 6e6eb7d7f13c..7b42850df968 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -658,34 +658,42 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD, GenOpenCLArgMetadata(FD, Fn, CGM, Context, Builder, getContext()); if (const VecTypeHintAttr *A = FD->getAttr<VecTypeHintAttr>()) { - QualType hintQTy = A->getTypeHint(); - const ExtVectorType *hintEltQTy = hintQTy->getAs<ExtVectorType>(); - bool isSignedInteger = - hintQTy->isSignedIntegerType() || - (hintEltQTy && hintEltQTy->getElementType()->isSignedIntegerType()); - llvm::Metadata *attrMDArgs[] = { + QualType HintQTy = A->getTypeHint(); + const ExtVectorType *HintEltQTy = HintQTy->getAs<ExtVectorType>(); + bool IsSignedInteger = + HintQTy->isSignedIntegerType() || + (HintEltQTy && HintEltQTy->getElementType()->isSignedIntegerType()); + llvm::Metadata *AttrMDArgs[] = { llvm::ConstantAsMetadata::get(llvm::UndefValue::get( CGM.getTypes().ConvertType(A->getTypeHint()))), llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( llvm::IntegerType::get(Context, 32), - llvm::APInt(32, (uint64_t)(isSignedInteger ? 1 : 0))))}; - Fn->setMetadata("vec_type_hint", llvm::MDNode::get(Context, attrMDArgs)); + llvm::APInt(32, (uint64_t)(IsSignedInteger ? 1 : 0))))}; + Fn->setMetadata("vec_type_hint", llvm::MDNode::get(Context, AttrMDArgs)); } if (const WorkGroupSizeHintAttr *A = FD->getAttr<WorkGroupSizeHintAttr>()) { - llvm::Metadata *attrMDArgs[] = { + llvm::Metadata *AttrMDArgs[] = { llvm::ConstantAsMetadata::get(Builder.getInt32(A->getXDim())), llvm::ConstantAsMetadata::get(Builder.getInt32(A->getYDim())), llvm::ConstantAsMetadata::get(Builder.getInt32(A->getZDim()))}; - Fn->setMetadata("work_group_size_hint", llvm::MDNode::get(Context, attrMDArgs)); + Fn->setMetadata("work_group_size_hint", llvm::MDNode::get(Context, AttrMDArgs)); } if (const ReqdWorkGroupSizeAttr *A = FD->getAttr<ReqdWorkGroupSizeAttr>()) { - llvm::Metadata *attrMDArgs[] = { + llvm::Metadata *AttrMDArgs[] = { llvm::ConstantAsMetadata::get(Builder.getInt32(A->getXDim())), llvm::ConstantAsMetadata::get(Builder.getInt32(A->getYDim())), llvm::ConstantAsMetadata::get(Builder.getInt32(A->getZDim()))}; - Fn->setMetadata("reqd_work_group_size", llvm::MDNode::get(Context, attrMDArgs)); + Fn->setMetadata("reqd_work_group_size", llvm::MDNode::get(Context, AttrMDArgs)); + } + + if (const OpenCLIntelReqdSubGroupSizeAttr *A = + FD->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) { + llvm::Metadata *AttrMDArgs[] = { + llvm::ConstantAsMetadata::get(Builder.getInt32(A->getSubGroupSize()))}; + Fn->setMetadata("intel_reqd_sub_group_size", + llvm::MDNode::get(Context, AttrMDArgs)); } } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index b69640894f11..459841aee5a2 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1413,16 +1413,8 @@ private: /// True if we need emit the life-time markers. const bool ShouldEmitLifetimeMarkers; - /// Add a kernel metadata node to the named metadata node 'opencl.kernels'. - /// In the kernel metadata node, reference the kernel function and metadata - /// nodes for its optional attribute qualifiers (OpenCL 1.1 6.7.2): - /// - A node for the vec_type_hint(<type>) qualifier contains string - /// "vec_type_hint", an undefined value of the <type> data type, - /// and a Boolean that is true if the <type> is integer and signed. - /// - A node for the work_group_size_hint(X,Y,Z) qualifier contains string - /// "work_group_size_hint", and three 32-bit integers X, Y and Z. - /// - A node for the reqd_work_group_size(X,Y,Z) qualifier contains string - /// "reqd_work_group_size", and three 32-bit integers X, Y and Z. + /// Add OpenCL kernel arg metadata and the kernel attribute meatadata to + /// the function metadata. void EmitOpenCLKernelMetadata(const FunctionDecl *FD, llvm::Function *Fn); diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index ecd81d84b1fa..4ebbef7dfb5b 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -4890,10 +4890,16 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const { // Empty records are always ignored on Darwin, but actually passed in C++ mode // elsewhere for GNU compatibility. - if (isEmptyRecord(getContext(), Ty, true)) { + uint64_t Size = getContext().getTypeSize(Ty); + bool IsEmpty = isEmptyRecord(getContext(), Ty, true); + if (IsEmpty || Size == 0) { if (!getContext().getLangOpts().CPlusPlus || isDarwinPCS()) return ABIArgInfo::getIgnore(); + // GNU C mode. The only argument that gets ignored is an empty one with size + // 0. + if (IsEmpty && Size == 0) + return ABIArgInfo::getIgnore(); return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); } @@ -4906,7 +4912,6 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const { } // Aggregates <= 16 bytes are passed directly in registers or on the stack. - uint64_t Size = getContext().getTypeSize(Ty); if (Size <= 128) { // On RenderScript, coerce Aggregates <= 16 bytes to an integer array of // same size and alignment. @@ -4946,7 +4951,8 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const { : ABIArgInfo::getDirect()); } - if (isEmptyRecord(getContext(), RetTy, true)) + uint64_t Size = getContext().getTypeSize(RetTy); + if (isEmptyRecord(getContext(), RetTy, true) || Size == 0) return ABIArgInfo::getIgnore(); const Type *Base = nullptr; @@ -4956,7 +4962,6 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const { return ABIArgInfo::getDirect(); // Aggregates <= 16 bytes are returned directly in registers or on the stack. - uint64_t Size = getContext().getTypeSize(RetTy); if (Size <= 128) { // On RenderScript, coerce Aggregates <= 16 bytes to an integer array of // same size and alignment. diff --git a/lib/Driver/Distro.cpp b/lib/Driver/Distro.cpp index d305b179449f..2df297f3cfc2 100644 --- a/lib/Driver/Distro.cpp +++ b/lib/Driver/Distro.cpp @@ -47,6 +47,7 @@ static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) { .Case("xenial", Distro::UbuntuXenial) .Case("yakkety", Distro::UbuntuYakkety) .Case("zesty", Distro::UbuntuZesty) + .Case("artful", Distro::UbuntuArtful) .Default(Distro::UnknownDistro); if (Version != Distro::UnknownDistro) return Version; diff --git a/lib/Driver/Multilib.cpp b/lib/Driver/Multilib.cpp index 43b62f7b3612..16a81603b31e 100644 --- a/lib/Driver/Multilib.cpp +++ b/lib/Driver/Multilib.cpp @@ -80,6 +80,10 @@ Multilib &Multilib::includeSuffix(StringRef S) { return *this; } +LLVM_DUMP_METHOD void Multilib::dump() const { + print(llvm::errs()); +} + void Multilib::print(raw_ostream &OS) const { assert(GCCSuffix.empty() || (StringRef(GCCSuffix).front() == '/')); if (GCCSuffix.empty()) @@ -270,6 +274,10 @@ bool MultilibSet::select(const Multilib::flags_list &Flags, Multilib &M) const { return false; } +LLVM_DUMP_METHOD void MultilibSet::dump() const { + print(llvm::errs()); +} + void MultilibSet::print(raw_ostream &OS) const { for (const Multilib &M : *this) OS << M << "\n"; diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index 4dd4929c9148..c298302c477c 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -55,6 +55,7 @@ enum CoverageFeature { Coverage8bitCounters = 1 << 8, CoverageTracePC = 1 << 9, CoverageTracePCGuard = 1 << 10, + CoverageNoPrune = 1 << 11, }; /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any @@ -629,7 +630,8 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"), std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"), std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"), - std::make_pair(CoverageTracePCGuard, "-fsanitize-coverage-trace-pc-guard")}; + std::make_pair(CoverageTracePCGuard, "-fsanitize-coverage-trace-pc-guard"), + std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune")}; for (auto F : CoverageFlags) { if (CoverageFeatures & F.first) CmdArgs.push_back(Args.MakeArgString(F.second)); @@ -786,6 +788,7 @@ int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) { .Case("8bit-counters", Coverage8bitCounters) .Case("trace-pc", CoverageTracePC) .Case("trace-pc-guard", CoverageTracePCGuard) + .Case("no-prune", CoverageNoPrune) .Default(0); if (F == 0) D.Diag(clang::diag::err_drv_unsupported_option_argument) diff --git a/lib/Driver/ToolChains/CrossWindows.cpp b/lib/Driver/ToolChains/CrossWindows.cpp index b030c636adab..d290c62a056a 100644 --- a/lib/Driver/ToolChains/CrossWindows.cpp +++ b/lib/Driver/ToolChains/CrossWindows.cpp @@ -204,7 +204,7 @@ CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D, const llvm::Triple &T, const llvm::opt::ArgList &Args) : Generic_GCC(D, T, Args) { - if (GetCXXStdlibType(Args) == ToolChain::CST_Libstdcxx) { + if (D.CCCIsCXX() && GetCXXStdlibType(Args) == ToolChain::CST_Libstdcxx) { const std::string &SysRoot = D.SysRoot; // libstdc++ resides in /usr/lib, but depends on libgcc which is placed in diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp index d29d826b5f44..f1015e62eec8 100644 --- a/lib/Driver/ToolChains/Gnu.cpp +++ b/lib/Driver/ToolChains/Gnu.cpp @@ -893,6 +893,8 @@ static bool isSoftFloatABI(const ArgList &Args) { A->getValue() == StringRef("soft")); } +/// \p Flag must be a flag accepted by the driver with its leading '-' removed, +// otherwise '-print-multi-lib' will not emit them correctly. static void addMultilibFlag(bool Enabled, const char *const Flag, std::vector<std::string> &Flags) { if (Enabled) @@ -1437,17 +1439,17 @@ static void findAndroidArmMultilibs(const Driver &D, // Find multilibs with subdirectories like armv7-a, thumb, armv7-a/thumb. FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS()); Multilib ArmV7Multilib = makeMultilib("/armv7-a") - .flag("+armv7") - .flag("-thumb"); + .flag("+march=armv7-a") + .flag("-mthumb"); Multilib ThumbMultilib = makeMultilib("/thumb") - .flag("-armv7") - .flag("+thumb"); + .flag("-march=armv7-a") + .flag("+mthumb"); Multilib ArmV7ThumbMultilib = makeMultilib("/armv7-a/thumb") - .flag("+armv7") - .flag("+thumb"); + .flag("+march=armv7-a") + .flag("+mthumb"); Multilib DefaultMultilib = makeMultilib("") - .flag("-armv7") - .flag("-thumb"); + .flag("-march=armv7-a") + .flag("-mthumb"); MultilibSet AndroidArmMultilibs = MultilibSet() .Either(ThumbMultilib, ArmV7Multilib, @@ -1465,8 +1467,8 @@ static void findAndroidArmMultilibs(const Driver &D, bool IsArmV7Mode = (IsArmArch || IsThumbArch) && (llvm::ARM::parseArchVersion(Arch) == 7 || (IsArmArch && Arch == "" && IsV7SubArch)); - addMultilibFlag(IsArmV7Mode, "armv7", Flags); - addMultilibFlag(IsThumbMode, "thumb", Flags); + addMultilibFlag(IsArmV7Mode, "march=armv7-a", Flags); + addMultilibFlag(IsThumbMode, "mthumb", Flags); if (AndroidArmMultilibs.select(Flags, Result.SelectedMultilib)) Result.Multilibs = AndroidArmMultilibs; diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h index 3b3600fede97..0c5a5284627c 100644 --- a/lib/Format/FormatToken.h +++ b/lib/Format/FormatToken.h @@ -53,6 +53,8 @@ namespace format { TYPE(InlineASMColon) \ TYPE(JavaAnnotation) \ TYPE(JsComputedPropertyName) \ + TYPE(JsExponentiation) \ + TYPE(JsExponentiationEqual) \ TYPE(JsFatArrow) \ TYPE(JsNonNullAssertion) \ TYPE(JsTypeColon) \ diff --git a/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp index 1acc0c306512..45c3ae1afe5f 100644 --- a/lib/Format/FormatTokenLexer.cpp +++ b/lib/Format/FormatTokenLexer.cpp @@ -74,6 +74,10 @@ void FormatTokenLexer::tryMergePreviousTokens() { static const tok::TokenKind JSShiftEqual[] = {tok::greater, tok::greater, tok::greaterequal}; static const tok::TokenKind JSRightArrow[] = {tok::equal, tok::greater}; + static const tok::TokenKind JSExponentiation[] = {tok::star, tok::star}; + static const tok::TokenKind JSExponentiationEqual[] = {tok::star, + tok::starequal}; + // FIXME: Investigate what token type gives the correct operator priority. if (tryMergeTokens(JSIdentity, TT_BinaryOperator)) return; @@ -83,6 +87,12 @@ void FormatTokenLexer::tryMergePreviousTokens() { return; if (tryMergeTokens(JSRightArrow, TT_JsFatArrow)) return; + if (tryMergeTokens(JSExponentiation, TT_JsExponentiation)) + return; + if (tryMergeTokens(JSExponentiationEqual, TT_JsExponentiationEqual)) { + Tokens.back()->Tok.setKind(tok::starequal); + return; + } } if (Style.Language == FormatStyle::LK_Java) { diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index d3ebf48315e2..96854b8fbc1a 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -766,6 +766,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.SanitizeCoverageTracePC = Args.hasArg(OPT_fsanitize_coverage_trace_pc); Opts.SanitizeCoverageTracePCGuard = Args.hasArg(OPT_fsanitize_coverage_trace_pc_guard); + Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune); Opts.SanitizeMemoryTrackOrigins = getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags); Opts.SanitizeMemoryUseAfterDtor = diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index d26b6937b851..1fbb2b054bad 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -136,6 +136,12 @@ void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput, CurrentASTUnit = std::move(AST); } +Module *FrontendAction::getCurrentModule() const { + CompilerInstance &CI = getCompilerInstance(); + return CI.getPreprocessor().getHeaderSearchInfo().lookupModule( + CI.getLangOpts().CurrentModule, /*AllowSearch*/false); +} + std::unique_ptr<ASTConsumer> FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI, StringRef InFile) { @@ -188,16 +194,25 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI, return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); } -// For preprocessed files, if the first line is the linemarker and specifies -// the original source file name, use that name as the input file name. -static bool ReadOriginalFileName(CompilerInstance &CI, std::string &InputFile) -{ - bool Invalid = false; +/// For preprocessed files, if the first line is the linemarker and specifies +/// the original source file name, use that name as the input file name. +/// Returns the location of the first token after the line marker directive. +/// +/// \param CI The compiler instance. +/// \param InputFile Populated with the filename from the line marker. +/// \param AddLineNote If \c true, add a line note corresponding to this line +/// directive. Only use this if the directive will not actually be +/// visited by the preprocessor. +static SourceLocation ReadOriginalFileName(CompilerInstance &CI, + std::string &InputFile, + bool AddLineNote = false) { auto &SourceMgr = CI.getSourceManager(); auto MainFileID = SourceMgr.getMainFileID(); + + bool Invalid = false; const auto *MainFileBuf = SourceMgr.getBuffer(MainFileID, &Invalid); if (Invalid) - return false; + return SourceLocation(); std::unique_ptr<Lexer> RawLexer( new Lexer(MainFileID, MainFileBuf, SourceMgr, CI.getLangOpts())); @@ -209,19 +224,37 @@ static bool ReadOriginalFileName(CompilerInstance &CI, std::string &InputFile) // we use FILENAME as the input file name. Token T; if (RawLexer->LexFromRawLexer(T) || T.getKind() != tok::hash) - return false; + return SourceLocation(); if (RawLexer->LexFromRawLexer(T) || T.isAtStartOfLine() || T.getKind() != tok::numeric_constant) - return false; + return SourceLocation(); + + unsigned LineNo; + SourceLocation LineNoLoc = T.getLocation(); + if (AddLineNote) { + llvm::SmallString<16> Buffer; + if (Lexer::getSpelling(LineNoLoc, Buffer, SourceMgr, CI.getLangOpts()) + .getAsInteger(10, LineNo)) + return SourceLocation(); + } + RawLexer->LexFromRawLexer(T); if (T.isAtStartOfLine() || T.getKind() != tok::string_literal) - return false; + return SourceLocation(); StringLiteralParser Literal(T, CI.getPreprocessor()); if (Literal.hadError) - return false; + return SourceLocation(); + RawLexer->LexFromRawLexer(T); + if (T.isNot(tok::eof) && !T.isAtStartOfLine()) + return SourceLocation(); InputFile = Literal.GetString().str(); - return true; + + if (AddLineNote) + CI.getSourceManager().AddLineNote( + LineNoLoc, LineNo, SourceMgr.getLineTableFilenameID(InputFile)); + + return T.getLocation(); } static SmallVectorImpl<char> & @@ -339,42 +372,44 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, return std::error_code(); } -/// Parse a module map and compute the corresponding real input buffer that -/// should be used to build the module described by that module map and the -/// current module name. -static std::unique_ptr<llvm::MemoryBuffer> -getInputBufferForModuleMap(CompilerInstance &CI, StringRef Filename, - bool IsSystem) { - // Find the module map file. - const FileEntry *ModuleMap = - CI.getFileManager().getFile(Filename, /*openFile*/true); - if (!ModuleMap) { - CI.getDiagnostics().Report(diag::err_module_map_not_found) - << Filename; - return nullptr; - } +static bool +loadModuleMapForModuleBuild(CompilerInstance &CI, StringRef Filename, + bool IsSystem, bool IsPreprocessed, + unsigned &Offset) { + auto &SrcMgr = CI.getSourceManager(); + HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); - // Find the module map file from which it was generated, if different. - const FileEntry *OriginalModuleMap = ModuleMap; - StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap; - if (!OriginalModuleMapName.empty()) { - OriginalModuleMap = CI.getFileManager().getFile(OriginalModuleMapName, - /*openFile*/ true); - if (!OriginalModuleMap) { - CI.getDiagnostics().Report(diag::err_module_map_not_found) - << OriginalModuleMapName; - return nullptr; - } + // Map the current input to a file. + FileID ModuleMapID = SrcMgr.getMainFileID(); + const FileEntry *ModuleMap = SrcMgr.getFileEntryForID(ModuleMapID); + + // If the module map is preprocessed, handle the initial line marker; + // line directives are not part of the module map syntax in general. + Offset = 0; + if (IsPreprocessed) { + std::string PresumedModuleMapFile; + SourceLocation EndOfLineMarker = + ReadOriginalFileName(CI, PresumedModuleMapFile, /*AddLineNote*/true); + if (EndOfLineMarker.isValid()) + Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second; + // FIXME: Use PresumedModuleMapFile as the MODULE_MAP_FILE in the PCM. } - - // Parse the module map file. - HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); - if (HS.loadModuleMapFile(ModuleMap, IsSystem)) - return nullptr; - + + // Load the module map file. + if (HS.loadModuleMapFile(ModuleMap, IsSystem, ModuleMapID, &Offset)) + return true; + + if (SrcMgr.getBuffer(ModuleMapID)->getBufferSize() == Offset) + Offset = 0; + + return false; +} + +static Module *prepareToBuildModule(CompilerInstance &CI, + StringRef ModuleMapFilename) { if (CI.getLangOpts().CurrentModule.empty()) { CI.getDiagnostics().Report(diag::err_missing_module_name); - + // FIXME: Eventually, we could consider asking whether there was just // a single module described in the module map, and use that as a // default. Then it would be fairly trivial to just "compile" a module @@ -382,21 +417,14 @@ getInputBufferForModuleMap(CompilerInstance &CI, StringRef Filename, return nullptr; } - // If we're being run from the command-line, the module build stack will not - // have been filled in yet, so complete it now in order to allow us to detect - // module cycles. - SourceManager &SourceMgr = CI.getSourceManager(); - if (SourceMgr.getModuleBuildStack().empty()) - SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule, - FullSourceLoc(SourceLocation(), SourceMgr)); - // Dig out the module definition. + HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule, /*AllowSearch=*/false); if (!M) { CI.getDiagnostics().Report(diag::err_missing_module) - << CI.getLangOpts().CurrentModule << Filename; - + << CI.getLangOpts().CurrentModule << ModuleMapFilename; + return nullptr; } @@ -417,11 +445,45 @@ getInputBufferForModuleMap(CompilerInstance &CI, StringRef Filename, return nullptr; } - if (OriginalModuleMap != ModuleMap) { - M->IsInferred = true; - HS.getModuleMap().setInferredModuleAllowedBy(M, OriginalModuleMap); + // Inform the preprocessor that includes from within the input buffer should + // be resolved relative to the build directory of the module map file. + CI.getPreprocessor().setMainFileDir(M->Directory); + + // If the module was inferred from a different module map (via an expanded + // umbrella module definition), track that fact. + // FIXME: It would be preferable to fill this in as part of processing + // the module map, rather than adding it after the fact. + StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap; + if (!OriginalModuleMapName.empty()) { + auto *OriginalModuleMap = + CI.getFileManager().getFile(OriginalModuleMapName, + /*openFile*/ true); + if (!OriginalModuleMap) { + CI.getDiagnostics().Report(diag::err_module_map_not_found) + << OriginalModuleMapName; + return nullptr; + } + if (OriginalModuleMap != CI.getSourceManager().getFileEntryForID( + CI.getSourceManager().getMainFileID())) { + M->IsInferred = true; + CI.getPreprocessor().getHeaderSearchInfo().getModuleMap() + .setInferredModuleAllowedBy(M, OriginalModuleMap); + } } + // If we're being run from the command-line, the module build stack will not + // have been filled in yet, so complete it now in order to allow us to detect + // module cycles. + SourceManager &SourceMgr = CI.getSourceManager(); + if (SourceMgr.getModuleBuildStack().empty()) + SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule, + FullSourceLoc(SourceLocation(), SourceMgr)); + return M; +} + +/// Compute the input buffer that should be used to build the specified module. +static std::unique_ptr<llvm::MemoryBuffer> +getInputBufferForModule(CompilerInstance &CI, Module *M) { FileManager &FileMgr = CI.getFileManager(); // Collect the set of #includes we need to build the module. @@ -441,10 +503,6 @@ getInputBufferForModuleMap(CompilerInstance &CI, StringRef Filename, return nullptr; } - // Inform the preprocessor that includes from within the input buffer should - // be resolved relative to the build directory of the module map file. - CI.getPreprocessor().setMainFileDir(M->Directory); - return llvm::MemoryBuffer::getMemBufferCopy( HeaderContents, Module::getModuleInputBufferName()); } @@ -457,7 +515,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, setCompilerInstance(&CI); StringRef InputFile = Input.getFile(); - FrontendInputFile FileToProcess = Input; bool HasBegunSourceFile = false; if (!BeginInvocation(CI)) goto failure; @@ -597,36 +654,45 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, &CI.getPreprocessor()); HasBegunSourceFile = true; + // Initialize the main file entry. + if (!CI.InitializeSourceManager(Input)) + goto failure; + // For module map files, we first parse the module map and synthesize a // "<module-includes>" buffer before more conventional processing. if (Input.getKind().getFormat() == InputKind::ModuleMap) { CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap); - auto Buffer = getInputBufferForModuleMap(CI, InputFile, Input.isSystem()); - if (!Buffer) + unsigned OffsetToContents; + if (loadModuleMapForModuleBuild(CI, Input.getFile(), Input.isSystem(), + Input.isPreprocessed(), OffsetToContents)) goto failure; - Module *CurrentModule = - CI.getPreprocessor().getHeaderSearchInfo().lookupModule( - CI.getLangOpts().CurrentModule, - /*AllowSearch=*/false); - assert(CurrentModule && "no module info for current module"); + auto *CurrentModule = prepareToBuildModule(CI, Input.getFile()); + if (!CurrentModule) + goto failure; + + if (OffsetToContents) + // If the module contents are in the same file, skip to them. + CI.getPreprocessor().setSkipMainFilePreamble(OffsetToContents, true); + else { + // Otherwise, convert the module description to a suitable input buffer. + auto Buffer = getInputBufferForModule(CI, CurrentModule); + if (!Buffer) + goto failure; - // The input that we end up processing is the generated buffer, not the - // module map file itself. - FileToProcess = FrontendInputFile( - Buffer.release(), Input.getKind().withFormat(InputKind::Source), - CurrentModule->IsSystem); + // Reinitialize the main file entry to refer to the new input. + if (!CI.InitializeSourceManager(FrontendInputFile( + Buffer.release(), Input.getKind().withFormat(InputKind::Source), + CurrentModule->IsSystem))) + goto failure; + } } // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; - // Initialize the main file entry. - if (!CI.InitializeSourceManager(FileToProcess)) - goto failure; - // Create the AST context and consumer unless this is a preprocessor only // action. if (!usesPreprocessorOnly()) { @@ -636,13 +702,12 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // For preprocessed files, check if the first line specifies the original // source file name with a linemarker. - std::string OrigFile; + std::string PresumedInputFile = InputFile; if (Input.isPreprocessed()) - if (ReadOriginalFileName(CI, OrigFile)) - InputFile = OrigFile; + ReadOriginalFileName(CI, PresumedInputFile); std::unique_ptr<ASTConsumer> Consumer = - CreateWrappedASTConsumer(CI, InputFile); + CreateWrappedASTConsumer(CI, PresumedInputFile); if (!Consumer) goto failure; diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index dd7c12f60f0e..baaf93b167bc 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -542,6 +542,18 @@ void PrintPreprocessedAction::ExecuteAction() { CI.createDefaultOutputFile(BinaryMode, getCurrentFile()); if (!OS) return; + // If we're preprocessing a module map, start by dumping the contents of the + // module itself before switching to the input buffer. + auto &Input = getCurrentInput(); + if (Input.getKind().getFormat() == InputKind::ModuleMap) { + if (Input.isFile()) + (*OS) << "# 1 \"" << Input.getFile() << "\"\n"; + // FIXME: Include additional information here so that we don't need the + // original source files to exist on disk. + getCurrentModule()->print(*OS); + (*OS) << "#pragma clang module contents\n"; + } + DoPrintPreprocessedInput(CI.getPreprocessor(), OS.get(), CI.getPreprocessorOutputOpts()); } diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index ffedf3cac847..832eaf2926f0 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -174,6 +174,9 @@ public: void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD, const MacroDirective *Undef) override; + + void BeginModule(const Module *M); + void EndModule(const Module *M); }; } // end anonymous namespace @@ -372,6 +375,20 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc, } } +/// Handle entering the scope of a module during a module compilation. +void PrintPPOutputPPCallbacks::BeginModule(const Module *M) { + startNewLineIfNeeded(); + OS << "#pragma clang module begin " << M->getFullModuleName(); + setEmittedDirectiveOnThisLine(); +} + +/// Handle leaving the scope of a module during a module compilation. +void PrintPPOutputPPCallbacks::EndModule(const Module *M) { + startNewLineIfNeeded(); + OS << "#pragma clang module end /*" << M->getFullModuleName() << "*/"; + setEmittedDirectiveOnThisLine(); +} + /// Ident - Handle #ident directives when read by the preprocessor. /// void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, StringRef S) { @@ -685,13 +702,27 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, // -traditional-cpp the lexer keeps /all/ whitespace, including comments. SourceLocation StartLoc = Tok.getLocation(); Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength())); - } else if (Tok.is(tok::annot_module_include) || - Tok.is(tok::annot_module_begin) || - Tok.is(tok::annot_module_end)) { + } else if (Tok.is(tok::annot_module_include)) { // PrintPPOutputPPCallbacks::InclusionDirective handles producing // appropriate output here. Ignore this token entirely. PP.Lex(Tok); continue; + } else if (Tok.is(tok::annot_module_begin)) { + // FIXME: We retrieve this token after the FileChanged callback, and + // retrieve the module_end token before the FileChanged callback, so + // we render this within the file and render the module end outside the + // file, but this is backwards from the token locations: the module_begin + // token is at the include location (outside the file) and the module_end + // token is at the EOF location (within the file). + Callbacks->BeginModule( + reinterpret_cast<Module *>(Tok.getAnnotationValue())); + PP.Lex(Tok); + continue; + } else if (Tok.is(tok::annot_module_end)) { + Callbacks->EndModule( + reinterpret_cast<Module *>(Tok.getAnnotationValue())); + PP.Lex(Tok); + continue; } else if (IdentifierInfo *II = Tok.getIdentifierInfo()) { OS << II->getName(); } else if (Tok.isLiteral() && !Tok.needsCleaning() && diff --git a/lib/Frontend/Rewrite/FrontendActions.cpp b/lib/Frontend/Rewrite/FrontendActions.cpp index 2e76e2e3151e..8c5eb161b5ab 100644 --- a/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/lib/Frontend/Rewrite/FrontendActions.cpp @@ -196,6 +196,18 @@ void RewriteIncludesAction::ExecuteAction() { CI.createDefaultOutputFile(true, getCurrentFile()); if (!OS) return; + // If we're preprocessing a module map, start by dumping the contents of the + // module itself before switching to the input buffer. + auto &Input = getCurrentInput(); + if (Input.getKind().getFormat() == InputKind::ModuleMap) { + if (Input.isFile()) + (*OS) << "# 1 \"" << Input.getFile() << "\"\n"; + // FIXME: Include additional information here so that we don't need the + // original source files to exist on disk. + getCurrentModule()->print(*OS); + (*OS) << "#pragma clang module contents\n"; + } + RewriteIncludesInInput(CI.getPreprocessor(), OS.get(), CI.getPreprocessorOutputOpts()); } diff --git a/lib/Frontend/Rewrite/InclusionRewriter.cpp b/lib/Frontend/Rewrite/InclusionRewriter.cpp index ee61f76d029d..d45cbc01df8c 100644 --- a/lib/Frontend/Rewrite/InclusionRewriter.cpp +++ b/lib/Frontend/Rewrite/InclusionRewriter.cpp @@ -46,6 +46,8 @@ class InclusionRewriter : public PPCallbacks { std::map<unsigned, IncludedFile> FileIncludes; /// Tracks where inclusions that import modules are found. std::map<unsigned, const Module *> ModuleIncludes; + /// Tracks where inclusions that enter modules (in a module build) are found. + std::map<unsigned, const Module *> ModuleEntryIncludes; /// Used transitively for building up the FileIncludes mapping over the /// various \c PPCallbacks callbacks. SourceLocation LastInclusionLocation; @@ -57,6 +59,11 @@ public: PredefinesBuffer = Buf; } void detectMainFileEOL(); + void handleModuleBegin(Token &Tok) { + assert(Tok.getKind() == tok::annot_module_begin); + ModuleEntryIncludes.insert({Tok.getLocation().getRawEncoding(), + (Module *)Tok.getAnnotationValue()}); + } private: void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, @@ -84,6 +91,7 @@ private: bool &FileExists); const IncludedFile *FindIncludeAtLocation(SourceLocation Loc) const; const Module *FindModuleAtLocation(SourceLocation Loc) const; + const Module *FindEnteredModule(SourceLocation Loc) const; StringRef NextIdentifierName(Lexer &RawLex, Token &RawToken); }; @@ -211,6 +219,16 @@ InclusionRewriter::FindModuleAtLocation(SourceLocation Loc) const { return nullptr; } +/// Simple lookup for a SourceLocation (specifically one denoting the hash in +/// an inclusion directive) in the map of module entry information. +const Module * +InclusionRewriter::FindEnteredModule(SourceLocation Loc) const { + const auto I = ModuleEntryIncludes.find(Loc.getRawEncoding()); + if (I != ModuleEntryIncludes.end()) + return I->second; + return nullptr; +} + /// Detect the likely line ending style of \p FromFile by examining the first /// newline found within it. static StringRef DetectEOL(const MemoryBuffer &FromFile) { @@ -452,8 +470,18 @@ void InclusionRewriter::Process(FileID FileId, if (const Module *Mod = FindModuleAtLocation(Loc)) WriteImplicitModuleImport(Mod); else if (const IncludedFile *Inc = FindIncludeAtLocation(Loc)) { + const Module *Mod = FindEnteredModule(Loc); + if (Mod) + OS << "#pragma clang module begin " << Mod->getFullModuleName() + << "\n"; + // Include and recursively process the file. Process(Inc->Id, Inc->FileType); + + if (Mod) + OS << "#pragma clang module end /*" << Mod->getFullModuleName() + << "*/\n"; + // Add line marker to indicate we're returning from an included // file. LineInfoExtra = " 2"; @@ -590,6 +618,8 @@ void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS, PP.SetMacroExpansionOnlyInDirectives(); do { PP.Lex(Tok); + if (Tok.is(tok::annot_module_begin)) + Rewrite->handleModuleBegin(Tok); } while (Tok.isNot(tok::eof)); Rewrite->setPredefinesBuffer(SM.getBuffer(PP.getPredefinesFileID())); Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User); diff --git a/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt index 35aff4017e93..6091db08a93b 100644 --- a/lib/Headers/CMakeLists.txt +++ b/lib/Headers/CMakeLists.txt @@ -45,6 +45,7 @@ set(files inttypes.h iso646.h limits.h + lwpintrin.h lzcntintrin.h mm3dnow.h mmintrin.h diff --git a/lib/Headers/arm_acle.h b/lib/Headers/arm_acle.h index 8423e62a381b..ab2589798269 100644 --- a/lib/Headers/arm_acle.h +++ b/lib/Headers/arm_acle.h @@ -225,19 +225,49 @@ __rbitl(unsigned long __t) { } /* + * 9.3 16-bit multiplications + */ +#if __ARM_FEATURE_DSP +static __inline__ int32_t __attribute__((__always_inline__,__nodebug__)) +__smulbb(int32_t __a, int32_t __b) { + return __builtin_arm_smulbb(__a, __b); +} +static __inline__ int32_t __attribute__((__always_inline__,__nodebug__)) +__smulbt(int32_t __a, int32_t __b) { + return __builtin_arm_smulbt(__a, __b); +} +static __inline__ int32_t __attribute__((__always_inline__,__nodebug__)) +__smultb(int32_t __a, int32_t __b) { + return __builtin_arm_smultb(__a, __b); +} +static __inline__ int32_t __attribute__((__always_inline__,__nodebug__)) +__smultt(int32_t __a, int32_t __b) { + return __builtin_arm_smultt(__a, __b); +} +static __inline__ int32_t __attribute__((__always_inline__,__nodebug__)) +__smulwb(int32_t __a, int32_t __b) { + return __builtin_arm_smulwb(__a, __b); +} +static __inline__ int32_t __attribute__((__always_inline__,__nodebug__)) +__smulwt(int32_t __a, int32_t __b) { + return __builtin_arm_smulwt(__a, __b); +} +#endif + +/* * 9.4 Saturating intrinsics * * FIXME: Change guard to their corrosponding __ARM_FEATURE flag when Q flag * intrinsics are implemented and the flag is enabled. */ /* 9.4.1 Width-specified saturation intrinsics */ -#if __ARM_32BIT_STATE +#if __ARM_FEATURE_SAT #define __ssat(x, y) __builtin_arm_ssat(x, y) #define __usat(x, y) __builtin_arm_usat(x, y) #endif /* 9.4.2 Saturating addition and subtraction intrinsics */ -#if __ARM_32BIT_STATE +#if __ARM_FEATURE_DSP static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) __qadd(int32_t __t, int32_t __v) { return __builtin_arm_qadd(__t, __v); @@ -254,6 +284,290 @@ __qdbl(int32_t __t) { } #endif +/* 9.4.3 Accumultating multiplications */ +#if __ARM_FEATURE_DSP +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smlabb(int32_t __a, int32_t __b, int32_t __c) { + return __builtin_arm_smlabb(__a, __b, __c); +} +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smlabt(int32_t __a, int32_t __b, int32_t __c) { + return __builtin_arm_smlabt(__a, __b, __c); +} +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smlatb(int32_t __a, int32_t __b, int32_t __c) { + return __builtin_arm_smlatb(__a, __b, __c); +} +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smlatt(int32_t __a, int32_t __b, int32_t __c) { + return __builtin_arm_smlatt(__a, __b, __c); +} +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smlawb(int32_t __a, int32_t __b, int32_t __c) { + return __builtin_arm_smlawb(__a, __b, __c); +} +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smlawt(int32_t __a, int32_t __b, int32_t __c) { + return __builtin_arm_smlawt(__a, __b, __c); +} +#endif + + +/* 9.5.4 Parallel 16-bit saturation */ +#if __ARM_FEATURE_SIMD32 +#define __ssat16(x, y) __builtin_arm_ssat16(x, y) +#define __usat16(x, y) __builtin_arm_usat16(x, y) +#endif + +/* 9.5.5 Packing and unpacking */ +#if __ARM_FEATURE_SIMD32 +typedef int32_t int8x4_t; +typedef int32_t int16x2_t; +typedef uint32_t uint8x4_t; +typedef uint32_t uint16x2_t; + +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__sxtab16(int16x2_t __a, int8x4_t __b) { + return __builtin_arm_sxtab16(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__sxtb16(int8x4_t __a) { + return __builtin_arm_sxtb16(__a); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__uxtab16(int16x2_t __a, int8x4_t __b) { + return __builtin_arm_uxtab16(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__uxtb16(int8x4_t __a) { + return __builtin_arm_uxtb16(__a); +} +#endif + +/* 9.5.6 Parallel selection */ +#if __ARM_FEATURE_SIMD32 +static __inline__ uint8x4_t __attribute__((__always_inline__, __nodebug__)) +__sel(uint8x4_t __a, uint8x4_t __b) { + return __builtin_arm_sel(__a, __b); +} +#endif + +/* 9.5.7 Parallel 8-bit addition and subtraction */ +#if __ARM_FEATURE_SIMD32 +static __inline__ int8x4_t __attribute__((__always_inline__, __nodebug__)) +__qadd8(int8x4_t __a, int8x4_t __b) { + return __builtin_arm_qadd8(__a, __b); +} +static __inline__ int8x4_t __attribute__((__always_inline__, __nodebug__)) +__qsub8(int8x4_t __a, int8x4_t __b) { + return __builtin_arm_qsub8(__a, __b); +} +static __inline__ int8x4_t __attribute__((__always_inline__, __nodebug__)) +__sadd8(int8x4_t __a, int8x4_t __b) { + return __builtin_arm_sadd8(__a, __b); +} +static __inline__ int8x4_t __attribute__((__always_inline__, __nodebug__)) +__shadd8(int8x4_t __a, int8x4_t __b) { + return __builtin_arm_shadd8(__a, __b); +} +static __inline__ int8x4_t __attribute__((__always_inline__, __nodebug__)) +__shsub8(int8x4_t __a, int8x4_t __b) { + return __builtin_arm_shsub8(__a, __b); +} +static __inline__ int8x4_t __attribute__((__always_inline__, __nodebug__)) +__ssub8(int8x4_t __a, int8x4_t __b) { + return __builtin_arm_ssub8(__a, __b); +} +static __inline__ uint8x4_t __attribute__((__always_inline__, __nodebug__)) +__uadd8(uint8x4_t __a, uint8x4_t __b) { + return __builtin_arm_uadd8(__a, __b); +} +static __inline__ uint8x4_t __attribute__((__always_inline__, __nodebug__)) +__uhadd8(uint8x4_t __a, uint8x4_t __b) { + return __builtin_arm_uhadd8(__a, __b); +} +static __inline__ uint8x4_t __attribute__((__always_inline__, __nodebug__)) +__uhsub8(uint8x4_t __a, uint8x4_t __b) { + return __builtin_arm_uhsub8(__a, __b); +} +static __inline__ uint8x4_t __attribute__((__always_inline__, __nodebug__)) +__uqadd8(uint8x4_t __a, uint8x4_t __b) { + return __builtin_arm_uqadd8(__a, __b); +} +static __inline__ uint8x4_t __attribute__((__always_inline__, __nodebug__)) +__uqsub8(uint8x4_t __a, uint8x4_t __b) { + return __builtin_arm_uqsub8(__a, __b); +} +static __inline__ uint8x4_t __attribute__((__always_inline__, __nodebug__)) +__usub8(uint8x4_t __a, uint8x4_t __b) { + return __builtin_arm_usub8(__a, __b); +} +#endif + +/* 9.5.8 Sum of 8-bit absolute differences */ +#if __ARM_FEATURE_SIMD32 +static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) +__usad8(uint8x4_t __a, uint8x4_t __b) { + return __builtin_arm_usad8(__a, __b); +} +static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) +__usada8(uint8x4_t __a, uint8x4_t __b, uint32_t __c) { + return __builtin_arm_usada8(__a, __b, __c); +} +#endif + +/* 9.5.9 Parallel 16-bit addition and subtraction */ +#if __ARM_FEATURE_SIMD32 +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__qadd16(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_qadd16(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__qasx(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_qasx(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__qsax(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_qsax(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__qsub16(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_qsub16(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__sadd16(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_sadd16(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__sasx(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_sasx(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__shadd16(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_shadd16(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__shasx(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_shasx(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__shsax(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_shsax(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__shsub16(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_shsub16(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__ssax(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_ssax(__a, __b); +} +static __inline__ int16x2_t __attribute__((__always_inline__, __nodebug__)) +__ssub16(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_ssub16(__a, __b); +} +static __inline__ uint16x2_t __attribute__((__always_inline__, __nodebug__)) +__uadd16(uint16x2_t __a, uint16x2_t __b) { + return __builtin_arm_uadd16(__a, __b); +} +static __inline__ uint16x2_t __attribute__((__always_inline__, __nodebug__)) +__uasx(uint16x2_t __a, uint16x2_t __b) { + return __builtin_arm_uasx(__a, __b); +} +static __inline__ uint16x2_t __attribute__((__always_inline__, __nodebug__)) +__uhadd16(uint16x2_t __a, uint16x2_t __b) { + return __builtin_arm_uhadd16(__a, __b); +} +static __inline__ uint16x2_t __attribute__((__always_inline__, __nodebug__)) +__uhasx(uint16x2_t __a, uint16x2_t __b) { + return __builtin_arm_uhasx(__a, __b); +} +static __inline__ uint16x2_t __attribute__((__always_inline__, __nodebug__)) +__uhsax(uint16x2_t __a, uint16x2_t __b) { + return __builtin_arm_uhsax(__a, __b); +} +static __inline__ uint16x2_t __attribute__((__always_inline__, __nodebug__)) +__uhsub16(uint16x2_t __a, uint16x2_t __b) { + return __builtin_arm_uhsub16(__a, __b); +} +static __inline__ uint16x2_t __attribute__((__always_inline__, __nodebug__)) +__uqadd16(uint16x2_t __a, uint16x2_t __b) { + return __builtin_arm_uqadd16(__a, __b); +} +static __inline__ uint16x2_t __attribute__((__always_inline__, __nodebug__)) +__uqasx(uint16x2_t __a, uint16x2_t __b) { + return __builtin_arm_uqasx(__a, __b); +} +static __inline__ uint16x2_t __attribute__((__always_inline__, __nodebug__)) +__uqsax(uint16x2_t __a, uint16x2_t __b) { + return __builtin_arm_uqsax(__a, __b); +} +static __inline__ uint16x2_t __attribute__((__always_inline__, __nodebug__)) +__uqsub16(uint16x2_t __a, uint16x2_t __b) { + return __builtin_arm_uqsub16(__a, __b); +} +static __inline__ uint16x2_t __attribute__((__always_inline__, __nodebug__)) +__usax(uint16x2_t __a, uint16x2_t __b) { + return __builtin_arm_usax(__a, __b); +} +static __inline__ uint16x2_t __attribute__((__always_inline__, __nodebug__)) +__usub16(uint16x2_t __a, uint16x2_t __b) { + return __builtin_arm_usub16(__a, __b); +} +#endif + +/* 9.5.10 Parallel 16-bit multiplications */ +#if __ARM_FEATURE_SIMD32 +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smlad(int16x2_t __a, int16x2_t __b, int32_t __c) { + return __builtin_arm_smlad(__a, __b, __c); +} +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smladx(int16x2_t __a, int16x2_t __b, int32_t __c) { + return __builtin_arm_smladx(__a, __b, __c); +} +static __inline__ int64_t __attribute__((__always_inline__, __nodebug__)) +__smlald(int16x2_t __a, int16x2_t __b, int64_t __c) { + return __builtin_arm_smlald(__a, __b, __c); +} +static __inline__ int64_t __attribute__((__always_inline__, __nodebug__)) +__smlaldx(int16x2_t __a, int16x2_t __b, int64_t __c) { + return __builtin_arm_smlaldx(__a, __b, __c); +} +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smlsd(int16x2_t __a, int16x2_t __b, int32_t __c) { + return __builtin_arm_smlsd(__a, __b, __c); +} +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smlsdx(int16x2_t __a, int16x2_t __b, int32_t __c) { + return __builtin_arm_smlsdx(__a, __b, __c); +} +static __inline__ int64_t __attribute__((__always_inline__, __nodebug__)) +__smlsld(int16x2_t __a, int16x2_t __b, int64_t __c) { + return __builtin_arm_smlsld(__a, __b, __c); +} +static __inline__ int64_t __attribute__((__always_inline__, __nodebug__)) +__smlsldx(int16x2_t __a, int16x2_t __b, int64_t __c) { + return __builtin_arm_smlsldx(__a, __b, __c); +} +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smuad(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_smuad(__a, __b); +} +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smuadx(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_smuadx(__a, __b); +} +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smusd(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_smusd(__a, __b); +} +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__smusdx(int16x2_t __a, int16x2_t __b) { + return __builtin_arm_smusdx(__a, __b); +} +#endif + /* 9.7 CRC32 intrinsics */ #if __ARM_FEATURE_CRC32 static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) diff --git a/lib/Headers/lwpintrin.h b/lib/Headers/lwpintrin.h new file mode 100644 index 000000000000..c95fdd9a201a --- /dev/null +++ b/lib/Headers/lwpintrin.h @@ -0,0 +1,150 @@ +/*===---- lwpintrin.h - LWP intrinsics -------------------------------------=== + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef __X86INTRIN_H +#error "Never use <lwpintrin.h> directly; include <x86intrin.h> instead." +#endif + +#ifndef __LWPINTRIN_H +#define __LWPINTRIN_H + +/* Define the default attributes for the functions in this file. */ +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("lwp"))) + +/// \brief Parses the LWPCB at the specified address and enables +/// profiling if valid. +/// +/// \headerfile <x86intrin.h> +/// +/// This intrinsic corresponds to the <c> LLWPCB </c> instruction. +/// +/// \param __addr +/// Address to the new Lightweight Profiling Control Block (LWPCB). If the +/// LWPCB is valid, writes the address into the LWP_CBADDR MSR and enables +/// Lightweight Profiling. +static __inline__ void __DEFAULT_FN_ATTRS +__llwpcb (void *__addr) +{ + __builtin_ia32_llwpcb(__addr); +} + +/// \brief Flushes the LWP state to memory and returns the address of the LWPCB. +/// +/// \headerfile <x86intrin.h> +/// +/// This intrinsic corresponds to the <c> SLWPCB </c> instruction. +/// +/// \return +/// Address to the current Lightweight Profiling Control Block (LWPCB). +/// If LWP is not currently enabled, returns NULL. +static __inline__ void* __DEFAULT_FN_ATTRS +__slwpcb () +{ + return __builtin_ia32_slwpcb(); +} + +/// \brief Inserts programmed event record into the LWP event ring buffer +/// and advances the ring buffer pointer. +/// +/// \headerfile <x86intrin.h> +/// +/// This intrinsic corresponds to the <c> LWPINS </c> instruction. +/// +/// \param DATA2 +/// A 32-bit value is zero-extended and inserted into the 64-bit Data2 field. +/// \param DATA1 +/// A 32-bit value is inserted into the 32-bit Data1 field. +/// \param FLAGS +/// A 32-bit immediate value is inserted into the 32-bit Flags field. +/// \returns If the ring buffer is full and LWP is running in Synchronized Mode, +/// the event record overwrites the last record in the buffer, the MissedEvents +/// counter in the LWPCB is incremented, the head pointer is not advanced, and +/// 1 is returned. Otherwise 0 is returned. +#define __lwpins32(DATA2, DATA1, FLAGS) \ + (__builtin_ia32_lwpins32((unsigned int) (DATA2), (unsigned int) (DATA1), \ + (unsigned int) (FLAGS))) + +/// \brief Decrements the LWP programmed value sample event counter. If the result is +/// negative, inserts an event record into the LWP event ring buffer in memory +/// and advances the ring buffer pointer. +/// +/// \headerfile <x86intrin.h> +/// +/// This intrinsic corresponds to the <c> LWPVAL </c> instruction. +/// +/// \param DATA2 +/// A 32-bit value is zero-extended and inserted into the 64-bit Data2 field. +/// \param DATA1 +/// A 32-bit value is inserted into the 32-bit Data1 field. +/// \param FLAGS +/// A 32-bit immediate value is inserted into the 32-bit Flags field. +#define __lwpval32(DATA2, DATA1, FLAGS) \ + (__builtin_ia32_lwpval32((unsigned int) (DATA2), (unsigned int) (DATA1), \ + (unsigned int) (FLAGS))) + +#ifdef __x86_64__ + +/// \brief Inserts programmed event record into the LWP event ring buffer +/// and advances the ring buffer pointer. +/// +/// \headerfile <x86intrin.h> +/// +/// This intrinsic corresponds to the <c> LWPINS </c> instruction. +/// +/// \param DATA2 +/// A 64-bit value is inserted into the 64-bit Data2 field. +/// \param DATA1 +/// A 32-bit value is inserted into the 32-bit Data1 field. +/// \param FLAGS +/// A 32-bit immediate value is inserted into the 32-bit Flags field. +/// \returns If the ring buffer is full and LWP is running in Synchronized Mode, +/// the event record overwrites the last record in the buffer, the MissedEvents +/// counter in the LWPCB is incremented, the head pointer is not advanced, and +/// 1 is returned. Otherwise 0 is returned. +#define __lwpins64(DATA2, DATA1, FLAGS) \ + (__builtin_ia32_lwpins64((unsigned long long) (DATA2), (unsigned int) (DATA1), \ + (unsigned int) (FLAGS))) + +/// \brief Decrements the LWP programmed value sample event counter. If the result is +/// negative, inserts an event record into the LWP event ring buffer in memory +/// and advances the ring buffer pointer. +/// +/// \headerfile <x86intrin.h> +/// +/// This intrinsic corresponds to the <c> LWPVAL </c> instruction. +/// +/// \param DATA2 +/// A 64-bit value is and inserted into the 64-bit Data2 field. +/// \param DATA1 +/// A 32-bit value is inserted into the 32-bit Data1 field. +/// \param FLAGS +/// A 32-bit immediate value is inserted into the 32-bit Flags field. +#define __lwpval64(DATA2, DATA1, FLAGS) \ + (__builtin_ia32_lwpval64((unsigned long long) (DATA2), (unsigned int) (DATA1), \ + (unsigned int) (FLAGS))) + +#endif + +#undef __DEFAULT_FN_ATTRS + +#endif /* __LWPINTRIN_H */ diff --git a/lib/Headers/x86intrin.h b/lib/Headers/x86intrin.h index 2003029cb5a8..ef1d02948c8b 100644 --- a/lib/Headers/x86intrin.h +++ b/lib/Headers/x86intrin.h @@ -72,6 +72,10 @@ #include <tbmintrin.h> #endif +#if !defined(_MSC_VER) || __has_feature(modules) || defined(__LWP__) +#include <lwpintrin.h> +#endif + #if !defined(_MSC_VER) || __has_feature(modules) || defined(__F16C__) #include <f16cintrin.h> #endif diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp index e8b2f1052d73..7de70a10b692 100644 --- a/lib/Index/IndexDecl.cpp +++ b/lib/Index/IndexDecl.cpp @@ -184,9 +184,7 @@ public: continue; } Relations.emplace_back( - SymbolRoleSet(SymbolRole::RelationOverrideOf) | - SymbolRoleSet(SymbolRole::RelationSpecializationOf), - ND); + SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND); } } } diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index bd425a07c33a..f5b7c59e446f 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -1325,7 +1325,8 @@ static const FileEntry *getPrivateModuleMap(const FileEntry *File, return FileMgr.getFile(PrivateFilename); } -bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { +bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem, + FileID ID, unsigned *Offset) { // Find the directory for the module. For frameworks, that may require going // up from the 'Modules' directory. const DirectoryEntry *Dir = nullptr; @@ -1344,7 +1345,7 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { } } - switch (loadModuleMapFileImpl(File, IsSystem, Dir)) { + switch (loadModuleMapFileImpl(File, IsSystem, Dir, ID, Offset)) { case LMM_AlreadyLoaded: case LMM_NewlyLoaded: return false; @@ -1357,7 +1358,8 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { HeaderSearch::LoadModuleMapResult HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem, - const DirectoryEntry *Dir) { + const DirectoryEntry *Dir, FileID ID, + unsigned *Offset) { assert(File && "expected FileEntry"); // Check whether we've already loaded this module map, and mark it as being @@ -1366,7 +1368,7 @@ HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem, if (!AddResult.second) return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; - if (ModMap.parseModuleMapFile(File, IsSystem, Dir)) { + if (ModMap.parseModuleMapFile(File, IsSystem, Dir, ID, Offset)) { LoadedModuleMaps[File] = false; return LMM_InvalidModuleMap; } diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 003c9b5eed1b..3d6fe91115a9 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -452,6 +452,29 @@ bool Lexer::getRawToken(SourceLocation Loc, Token &Result, return false; } +/// Returns the pointer that points to the beginning of line that contains +/// the given offset, or null if the offset if invalid. +static const char *findBeginningOfLine(StringRef Buffer, unsigned Offset) { + const char *BufStart = Buffer.data(); + if (Offset >= Buffer.size()) + return nullptr; + const char *StrData = BufStart + Offset; + + if (StrData[0] == '\n' || StrData[0] == '\r') + return StrData; + + const char *LexStart = StrData; + while (LexStart != BufStart) { + if (LexStart[0] == '\n' || LexStart[0] == '\r') { + ++LexStart; + break; + } + + --LexStart; + } + return LexStart; +} + static SourceLocation getBeginningOfFileToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts) { @@ -467,27 +490,15 @@ static SourceLocation getBeginningOfFileToken(SourceLocation Loc, // Back up from the current location until we hit the beginning of a line // (or the buffer). We'll relex from that point. - const char *BufStart = Buffer.data(); - if (LocInfo.second >= Buffer.size()) - return Loc; - - const char *StrData = BufStart+LocInfo.second; - if (StrData[0] == '\n' || StrData[0] == '\r') + const char *StrData = Buffer.data() + LocInfo.second; + const char *LexStart = findBeginningOfLine(Buffer, LocInfo.second); + if (!LexStart || LexStart == StrData) return Loc; - - const char *LexStart = StrData; - while (LexStart != BufStart) { - if (LexStart[0] == '\n' || LexStart[0] == '\r') { - ++LexStart; - break; - } - - --LexStart; - } // Create a lexer starting at the beginning of this token. SourceLocation LexerStartLoc = Loc.getLocWithOffset(-LocInfo.second); - Lexer TheLexer(LexerStartLoc, LangOpts, BufStart, LexStart, Buffer.end()); + Lexer TheLexer(LexerStartLoc, LangOpts, Buffer.data(), LexStart, + Buffer.end()); TheLexer.SetCommentRetentionState(true); // Lex tokens until we find the token that contains the source location. @@ -1038,6 +1049,27 @@ bool Lexer::isIdentifierBodyChar(char c, const LangOptions &LangOpts) { return isIdentifierBody(c, LangOpts.DollarIdents); } +StringRef Lexer::getIndentationForLine(SourceLocation Loc, + const SourceManager &SM) { + if (Loc.isInvalid() || Loc.isMacroID()) + return ""; + std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); + if (LocInfo.first.isInvalid()) + return ""; + bool Invalid = false; + StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); + if (Invalid) + return ""; + const char *Line = findBeginningOfLine(Buffer, LocInfo.second); + if (!Line) + return ""; + StringRef Rest = Buffer.substr(Line - Buffer.data()); + size_t NumWhitespaceChars = Rest.find_first_not_of(" \t"); + return NumWhitespaceChars == StringRef::npos + ? "" + : Rest.take_front(NumWhitespaceChars); +} + //===----------------------------------------------------------------------===// // Diagnostics forwarding code. //===----------------------------------------------------------------------===// diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 512d7dc5de68..70d37d3d7082 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -1132,14 +1132,17 @@ namespace clang { } bool parseModuleMapFile(); + + bool terminatedByDirective() { return false; } + SourceLocation getLocation() { return Tok.getLocation(); } }; } SourceLocation ModuleMapParser::consumeToken() { -retry: SourceLocation Result = Tok.getLocation(); + +retry: Tok.clear(); - Token LToken; L.LexFromRawLexer(LToken); Tok.Location = LToken.getLocation().getRawEncoding(); @@ -1232,9 +1235,28 @@ retry: case tok::comment: goto retry; - + + case tok::hash: + // A module map can be terminated prematurely by + // #pragma clang module contents + // When building the module, we'll treat the rest of the file as the + // contents of the module. + { + auto NextIsIdent = [&](StringRef Str) -> bool { + L.LexFromRawLexer(LToken); + return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && + LToken.getRawIdentifier() == Str; + }; + if (NextIsIdent("pragma") && NextIsIdent("clang") && + NextIsIdent("module") && NextIsIdent("contents")) { + Tok.Kind = MMToken::EndOfFile; + break; + } + } + LLVM_FALLTHROUGH; + default: - Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); + Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); HadError = true; goto retry; } @@ -1682,7 +1704,8 @@ void ModuleMapParser::parseExternModuleDecl() { File, /*IsSystem=*/false, Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd ? Directory - : File->getDir(), ExternLoc); + : File->getDir(), + FileID(), nullptr, ExternLoc); } /// Whether to add the requirement \p Feature to the module \p M. @@ -2522,28 +2545,45 @@ bool ModuleMapParser::parseModuleMapFile() { } bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, - const DirectoryEntry *Dir, + const DirectoryEntry *Dir, FileID ID, + unsigned *Offset, SourceLocation ExternModuleLoc) { + assert(Target && "Missing target information"); llvm::DenseMap<const FileEntry *, bool>::iterator Known = ParsedModuleMap.find(File); if (Known != ParsedModuleMap.end()) return Known->second; + // If the module map file wasn't already entered, do so now. + if (ID.isInvalid()) { + auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User; + ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); + } + assert(Target && "Missing target information"); - auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User; - FileID ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); if (!Buffer) return ParsedModuleMap[File] = true; + assert((!Offset || *Offset <= Buffer->getBufferSize()) && + "invalid buffer offset"); // Parse this module map file. - Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts); + Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, + Buffer->getBufferStart(), + Buffer->getBufferStart() + (Offset ? *Offset : 0), + Buffer->getBufferEnd()); SourceLocation Start = L.getSourceLocation(); ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, BuiltinIncludeDir, IsSystem); bool Result = Parser.parseModuleMapFile(); ParsedModuleMap[File] = Result; + if (Offset) { + auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); + assert(Loc.first == ID && "stopped in a different file?"); + *Offset = Loc.second; + } + // Notify callbacks that we parsed it. for (const auto &Cb : Callbacks) Cb->moduleMapFileRead(Start, *File, IsSystem); diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 4826e399afda..06fee8e5b0a8 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -2049,12 +2049,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, M->getTopLevelModuleName() == getLangOpts().CurrentModule) return; - assert(!CurSubmodule && "should not have marked this as a module yet"); - CurSubmodule = M; + assert(!CurLexerSubmodule && "should not have marked this as a module yet"); + CurLexerSubmodule = M; // Let the macro handling code know that any future macros are within // the new submodule. - EnterSubmodule(M, HashLoc); + EnterSubmodule(M, HashLoc, /*ForPragma*/false); // Let the parser know that any future declarations are within the new // submodule. @@ -2082,7 +2082,7 @@ void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc, } else if (isInPrimaryFile()) { Lookup = nullptr; Diag(IncludeNextTok, diag::pp_include_next_in_primary); - } else if (CurSubmodule) { + } else if (CurLexerSubmodule) { // Start looking up in the directory *after* the one in which the current // file would be found, if any. assert(CurPPLexer && "#include_next directive in macro?"); diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index fcc49b387034..1938328c904d 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -117,7 +117,7 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer, CurLexer.reset(TheLexer); CurPPLexer = TheLexer; CurDirLookup = CurDir; - CurSubmodule = nullptr; + CurLexerSubmodule = nullptr; if (CurLexerKind != CLK_LexAfterModuleImport) CurLexerKind = CLK_Lexer; @@ -142,7 +142,7 @@ void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL, CurDirLookup = CurDir; CurPTHLexer.reset(PL); CurPPLexer = CurPTHLexer.get(); - CurSubmodule = nullptr; + CurLexerSubmodule = nullptr; if (CurLexerKind != CLK_LexAfterModuleImport) CurLexerKind = CLK_PTHLexer; @@ -337,6 +337,26 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { assert(!CurTokenLexer && "Ending a file when currently in a macro!"); + // If we have an unclosed module region from a pragma at the end of a + // module, complain and close it now. + // FIXME: This is not correct if we are building a module from PTH. + const bool LeavingSubmodule = CurLexer && CurLexerSubmodule; + if ((LeavingSubmodule || IncludeMacroStack.empty()) && + !BuildingSubmoduleStack.empty() && + BuildingSubmoduleStack.back().IsPragma) { + Diag(BuildingSubmoduleStack.back().ImportLoc, + diag::err_pp_module_begin_without_module_end); + Module *M = LeaveSubmodule(/*ForPragma*/true); + + Result.startToken(); + const char *EndPos = getCurLexerEndPos(); + CurLexer->BufferPtr = EndPos; + CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end); + Result.setAnnotationEndLoc(Result.getLocation()); + Result.setAnnotationValue(M); + return true; + } + // See if this file had a controlling macro. if (CurPPLexer) { // Not ending a macro, ignore it. if (const IdentifierInfo *ControllingMacro = @@ -442,18 +462,17 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { if (Callbacks && !isEndOfMacro && CurPPLexer) ExitedFID = CurPPLexer->getFileID(); - bool LeavingSubmodule = CurSubmodule && CurLexer; if (LeavingSubmodule) { + // We're done with this submodule. + Module *M = LeaveSubmodule(/*ForPragma*/false); + // Notify the parser that we've left the module. const char *EndPos = getCurLexerEndPos(); Result.startToken(); CurLexer->BufferPtr = EndPos; CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end); Result.setAnnotationEndLoc(Result.getLocation()); - Result.setAnnotationValue(CurSubmodule); - - // We're done with this submodule. - LeaveSubmodule(); + Result.setAnnotationValue(M); } // We're done with the #included file. @@ -628,11 +647,13 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) { assert(!FoundLexer && "Lexer should return EOD before EOF in PP mode"); } -void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) { +void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc, + bool ForPragma) { if (!getLangOpts().ModulesLocalVisibility) { // Just track that we entered this submodule. - BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo( - M, ImportLoc, CurSubmoduleState, PendingModuleMacroNames.size())); + BuildingSubmoduleStack.push_back( + BuildingSubmoduleInfo(M, ImportLoc, ForPragma, CurSubmoduleState, + PendingModuleMacroNames.size())); return; } @@ -673,8 +694,9 @@ void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) { } // Track that we entered this module. - BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo( - M, ImportLoc, CurSubmoduleState, PendingModuleMacroNames.size())); + BuildingSubmoduleStack.push_back( + BuildingSubmoduleInfo(M, ImportLoc, ForPragma, CurSubmoduleState, + PendingModuleMacroNames.size())); // Switch to this submodule as the current submodule. CurSubmoduleState = &State; @@ -697,7 +719,13 @@ bool Preprocessor::needModuleMacros() const { return getLangOpts().isCompilingModule(); } -void Preprocessor::LeaveSubmodule() { +Module *Preprocessor::LeaveSubmodule(bool ForPragma) { + if (BuildingSubmoduleStack.empty() || + BuildingSubmoduleStack.back().IsPragma != ForPragma) { + assert(ForPragma && "non-pragma module enter/leave mismatch"); + return nullptr; + } + auto &Info = BuildingSubmoduleStack.back(); Module *LeavingMod = Info.M; @@ -711,7 +739,7 @@ void Preprocessor::LeaveSubmodule() { // of pending names for the surrounding submodule. BuildingSubmoduleStack.pop_back(); makeModuleVisible(LeavingMod, ImportLoc); - return; + return LeavingMod; } // Create ModuleMacros for any macros defined in this submodule. @@ -800,4 +828,5 @@ void Preprocessor::LeaveSubmodule() { // A nested #include makes the included submodule visible. makeModuleVisible(LeavingMod, ImportLoc); + return LeavingMod; } diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 196223981d74..6c7663994a49 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -1453,7 +1453,7 @@ static bool EvaluateHasIncludeNext(Token &Tok, } else if (PP.isInPrimaryFile()) { Lookup = nullptr; PP.Diag(Tok, diag::pp_include_next_in_primary); - } else if (PP.getCurrentSubmodule()) { + } else if (PP.getCurrentLexerSubmodule()) { // Start looking up in the directory *after* the one in which the current // file would be found, if any. assert(PP.getCurrentLexer() && "#include_next directive in macro?"); diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 576151a98b2c..99d56182c1bb 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -534,47 +534,6 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { } } -void Preprocessor::HandlePragmaModuleImport(Token &ImportTok) { - SourceLocation ImportLoc = ImportTok.getLocation(); - - Token Tok; - - llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> ModuleName; - while (true) { - LexUnexpandedToken(Tok); - if (Tok.isNot(tok::identifier)) { - Diag(Tok.getLocation(), - diag::err_pragma_module_import_expected_module_name) << 0; - return; - } - - ModuleName.emplace_back(Tok.getIdentifierInfo(), Tok.getLocation()); - - LexUnexpandedToken(Tok); - assert(Tok.isNot(tok::eof)); - if (Tok.is(tok::eod)) - break; - if (Tok.isNot(tok::period)) { - Diag(Tok.getLocation(), - diag::err_pragma_module_import_expected_module_name) << 1; - return; - } - } - - // If we have a non-empty module path, load the named module. - Module *Imported = - TheModuleLoader.loadModule(ImportLoc, ModuleName, Module::Hidden, - /*IsIncludeDirective=*/false); - if (!Imported) - return; - - makeModuleVisible(Imported, ImportLoc); - EnterAnnotationToken(SourceRange(ImportLoc, Tok.getLocation()), - tok::annot_module_include, Imported); - if (Callbacks) - Callbacks->moduleImport(ImportLoc, ModuleName, Imported); -} - /// ParsePragmaPushOrPopMacro - Handle parsing of pragma push_macro/pop_macro. /// Return the IdentifierInfo* associated with the macro to push or pop. IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) { @@ -1342,6 +1301,26 @@ public: } }; +static bool LexModuleName( + Preprocessor &PP, Token &Tok, + llvm::SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>> + &ModuleName) { + while (true) { + PP.LexUnexpandedToken(Tok); + if (Tok.isAnnotation() || !Tok.getIdentifierInfo()) { + PP.Diag(Tok.getLocation(), diag::err_pp_expected_module_name) + << ModuleName.empty(); + return true; + } + + ModuleName.emplace_back(Tok.getIdentifierInfo(), Tok.getLocation()); + + PP.LexUnexpandedToken(Tok); + if (Tok.isNot(tok::period)) + return false; + } +} + /// Handle the clang \#pragma module import extension. The syntax is: /// \code /// #pragma clang module import some.module.name @@ -1350,8 +1329,108 @@ struct PragmaModuleImportHandler : public PragmaHandler { PragmaModuleImportHandler() : PragmaHandler("import") {} void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &ImportTok) override { - PP.HandlePragmaModuleImport(ImportTok); + Token &Tok) override { + SourceLocation ImportLoc = Tok.getLocation(); + + // Read the module name. + llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> + ModuleName; + if (LexModuleName(PP, Tok, ModuleName)) + return; + + if (Tok.isNot(tok::eod)) + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + + // If we have a non-empty module path, load the named module. + Module *Imported = + PP.getModuleLoader().loadModule(ImportLoc, ModuleName, Module::Hidden, + /*IsIncludeDirective=*/false); + if (!Imported) + return; + + PP.makeModuleVisible(Imported, ImportLoc); + PP.EnterAnnotationToken(SourceRange(ImportLoc, ModuleName.back().second), + tok::annot_module_include, Imported); + if (auto *CB = PP.getPPCallbacks()) + CB->moduleImport(ImportLoc, ModuleName, Imported); + } +}; + +/// Handle the clang \#pragma module begin extension. The syntax is: +/// \code +/// #pragma clang module begin some.module.name +/// ... +/// #pragma clang module end +/// \endcode +struct PragmaModuleBeginHandler : public PragmaHandler { + PragmaModuleBeginHandler() : PragmaHandler("begin") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + SourceLocation BeginLoc = Tok.getLocation(); + + // Read the module name. + llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> + ModuleName; + if (LexModuleName(PP, Tok, ModuleName)) + return; + + if (Tok.isNot(tok::eod)) + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + + // We can only enter submodules of the current module. + StringRef Current = PP.getLangOpts().CurrentModule; + if (ModuleName.front().first->getName() != Current) { + PP.Diag(ModuleName.front().second, diag::err_pp_module_begin_wrong_module) + << ModuleName.front().first << (ModuleName.size() > 1) + << Current.empty() << Current; + return; + } + + // Find the module we're entering. We require that a module map for it + // be loaded or implicitly loadable. + // FIXME: We could create the submodule here. We'd need to know whether + // it's supposed to be explicit, but not much else. + Module *M = PP.getHeaderSearchInfo().getModuleMap().findModule(Current); + if (!M) { + PP.Diag(ModuleName.front().second, + diag::err_pp_module_begin_no_module_map) << Current; + return; + } + for (unsigned I = 1; I != ModuleName.size(); ++I) { + auto *NewM = M->findSubmodule(ModuleName[I].first->getName()); + if (!NewM) { + PP.Diag(ModuleName[I].second, diag::err_pp_module_begin_no_submodule) + << M->getFullModuleName() << ModuleName[I].first; + return; + } + M = NewM; + } + + // Enter the scope of the submodule. + PP.EnterSubmodule(M, BeginLoc, /*ForPragma*/true); + PP.EnterAnnotationToken(SourceRange(BeginLoc, ModuleName.back().second), + tok::annot_module_begin, M); + } +}; + +/// Handle the clang \#pragma module end extension. +struct PragmaModuleEndHandler : public PragmaHandler { + PragmaModuleEndHandler() : PragmaHandler("end") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + SourceLocation Loc = Tok.getLocation(); + + PP.LexUnexpandedToken(Tok); + if (Tok.isNot(tok::eod)) + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + + Module *M = PP.LeaveSubmodule(/*ForPragma*/true); + if (M) + PP.EnterAnnotationToken(SourceRange(Loc), tok::annot_module_end, M); + else + PP.Diag(Loc, diag::err_pp_module_end_without_module_begin); } }; @@ -1582,6 +1661,8 @@ void Preprocessor::RegisterBuiltinPragmas() { auto *ModuleHandler = new PragmaNamespace("module"); AddPragmaHandler("clang", ModuleHandler); ModuleHandler->AddPragma(new PragmaModuleImportHandler()); + ModuleHandler->AddPragma(new PragmaModuleBeginHandler()); + ModuleHandler->AddPragma(new PragmaModuleEndHandler()); AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler()); AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler()); diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index babef5dcc7ca..e409ab036535 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -85,10 +85,10 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, LastTokenWasAt(false), ModuleImportExpectsIdentifier(false), CodeCompletionReached(false), CodeCompletionII(nullptr), MainFileDir(nullptr), SkipMainFilePreamble(0, true), CurPPLexer(nullptr), - CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), CurSubmodule(nullptr), - Callbacks(nullptr), CurSubmoduleState(&NullSubmoduleState), - MacroArgCache(nullptr), Record(nullptr), MIChainHead(nullptr), - DeserialMIChainHead(nullptr) { + CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), + CurLexerSubmodule(nullptr), Callbacks(nullptr), + CurSubmoduleState(&NullSubmoduleState), MacroArgCache(nullptr), + Record(nullptr), MIChainHead(nullptr), DeserialMIChainHead(nullptr) { OwnsHeaderSearch = OwnsHeaders; CounterValue = 0; // __COUNTER__ starts at 0. diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index a53c8014ebaf..049e046cece1 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -183,6 +183,12 @@ void TokenLexer::ExpandFunctionArguments() { // preprocessor already verified that the following token is a macro name // when the #define was parsed. const Token &CurTok = Tokens[i]; + // We don't want a space for the next token after a paste + // operator. In valid code, the token will get smooshed onto the + // preceding one anyway. In assembler-with-cpp mode, invalid + // pastes are allowed through: in this case, we do not want the + // extra whitespace to be added. For example, we want ". ## foo" + // -> ".foo" not ". foo". if (i != 0 && !Tokens[i-1].is(tok::hashhash) && CurTok.hasLeadingSpace()) NextTokGetsSpace = true; @@ -317,6 +323,7 @@ void TokenLexer::ExpandFunctionArguments() { const Token *ArgToks = ActualArgs->getUnexpArgument(ArgNo); unsigned NumToks = MacroArgs::getArgLength(ArgToks); if (NumToks) { // Not an empty argument? + bool VaArgsPseudoPaste = false; // If this is the GNU ", ## __VA_ARGS__" extension, and we just learned // that __VA_ARGS__ expands to multiple tokens, avoid a pasting error when // the expander trys to paste ',' with the first token of the __VA_ARGS__ @@ -325,6 +332,7 @@ void TokenLexer::ExpandFunctionArguments() { ResultToks[ResultToks.size()-2].is(tok::comma) && (unsigned)ArgNo == Macro->getNumArgs()-1 && Macro->isVariadic()) { + VaArgsPseudoPaste = true; // Remove the paste operator, report use of the extension. PP.Diag(ResultToks.pop_back_val().getLocation(), diag::ext_paste_comma); } @@ -344,18 +352,16 @@ void TokenLexer::ExpandFunctionArguments() { ResultToks.end()-NumToks, ResultToks.end()); } - // If this token (the macro argument) was supposed to get leading - // whitespace, transfer this information onto the first token of the - // expansion. - // - // Do not do this if the paste operator occurs before the macro argument, - // as in "A ## MACROARG". In valid code, the first token will get - // smooshed onto the preceding one anyway (forming AMACROARG). In - // assembler-with-cpp mode, invalid pastes are allowed through: in this - // case, we do not want the extra whitespace to be added. For example, - // we want ". ## foo" -> ".foo" not ". foo". - if (NextTokGetsSpace) - ResultToks[ResultToks.size()-NumToks].setFlag(Token::LeadingSpace); + // Transfer the leading whitespace information from the token + // (the macro argument) onto the first token of the + // expansion. Note that we don't do this for the GNU + // pseudo-paste extension ", ## __VA_ARGS__". + if (!VaArgsPseudoPaste) { + ResultToks[ResultToks.size() - NumToks].setFlagValue(Token::StartOfLine, + false); + ResultToks[ResultToks.size() - NumToks].setFlagValue( + Token::LeadingSpace, NextTokGetsSpace); + } NextTokGetsSpace = false; continue; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index b25152a3183e..ad7b319676e9 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -4151,8 +4151,6 @@ void Parser::ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs) { } if (!T.consumeClose()) { - // FIXME: Warn that this syntax is deprecated, with a Fix-It suggesting - // using __declspec(uuid()) instead. Attrs.addNew(UuidIdent, SourceRange(UuidLoc, T.getCloseLocation()), nullptr, SourceLocation(), ArgExprs.data(), ArgExprs.size(), AttributeList::AS_Microsoft); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 94e792c1d17d..2f493fa5fbef 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -383,6 +383,19 @@ void Sema::diagnoseNullableToNonnullConversion(QualType DstType, Diag(Loc, diag::warn_nullability_lost) << SrcType << DstType; } +void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) { + if (Kind != CK_NullToPointer && Kind != CK_NullToMemberPointer) + return; + if (E->getType()->isNullPtrType()) + return; + // nullptr only exists from C++11 on, so don't warn on its absence earlier. + if (!getLangOpts().CPlusPlus11) + return; + + Diag(E->getLocStart(), diag::warn_zero_as_null_pointer_constant) + << FixItHint::CreateReplacement(E->getSourceRange(), "nullptr"); +} + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. /// If there is already an implicit cast, merge into the existing one. /// The result is of the given category. @@ -407,6 +420,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, #endif diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getLocStart()); + diagnoseZeroToNullptrConversion(Kind, E); QualType ExprTy = Context.getCanonicalType(E->getType()); QualType TypeTy = Context.getCanonicalType(Ty); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index a206100b89eb..14dd6267b854 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -3652,22 +3652,29 @@ static bool checkVAStartIsInVariadicFunction(Sema &S, Expr *Fn, // and get its parameter list. bool IsVariadic = false; ArrayRef<ParmVarDecl *> Params; - if (BlockScopeInfo *CurBlock = S.getCurBlock()) { - IsVariadic = CurBlock->TheDecl->isVariadic(); - Params = CurBlock->TheDecl->parameters(); - } else if (FunctionDecl *FD = S.getCurFunctionDecl()) { + DeclContext *Caller = S.CurContext; + if (auto *Block = dyn_cast<BlockDecl>(Caller)) { + IsVariadic = Block->isVariadic(); + Params = Block->parameters(); + } else if (auto *FD = dyn_cast<FunctionDecl>(Caller)) { IsVariadic = FD->isVariadic(); Params = FD->parameters(); - } else if (ObjCMethodDecl *MD = S.getCurMethodDecl()) { + } else if (auto *MD = dyn_cast<ObjCMethodDecl>(Caller)) { IsVariadic = MD->isVariadic(); // FIXME: This isn't correct for methods (results in bogus warning). Params = MD->parameters(); + } else if (isa<CapturedDecl>(Caller)) { + // We don't support va_start in a CapturedDecl. + S.Diag(Fn->getLocStart(), diag::err_va_start_captured_stmt); + return true; } else { - llvm_unreachable("unknown va_start context"); + // This must be some other declcontext that parses exprs. + S.Diag(Fn->getLocStart(), diag::err_va_start_outside_function); + return true; } if (!IsVariadic) { - S.Diag(Fn->getLocStart(), diag::err_va_start_used_in_non_variadic_function); + S.Diag(Fn->getLocStart(), diag::err_va_start_fixed_function); return true; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d4c0783638d1..2612023f59db 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -6070,12 +6070,24 @@ NamedDecl *Sema::ActOnVariableDeclarator( } } - // OpenCL v1.2 s6.9.b p4: - // The sampler type cannot be used with the __local and __global address - // space qualifiers. - if (R->isSamplerT() && (R.getAddressSpace() == LangAS::opencl_local || - R.getAddressSpace() == LangAS::opencl_global)) { - Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace); + if (R->isSamplerT()) { + // OpenCL v1.2 s6.9.b p4: + // The sampler type cannot be used with the __local and __global address + // space qualifiers. + if (R.getAddressSpace() == LangAS::opencl_local || + R.getAddressSpace() == LangAS::opencl_global) { + Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace); + } + + // OpenCL v1.2 s6.12.14.1: + // A global sampler must be declared with either the constant address + // space qualifier or with the const qualifier. + if (DC->isTranslationUnit() && + !(R.getAddressSpace() == LangAS::opencl_constant || + R.isConstQualified())) { + Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler); + D.setInvalidType(); + } } // OpenCL v1.2 s6.9.r: @@ -15902,7 +15914,7 @@ void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { VisibleModules.setVisible(Mod, DirectiveLoc); } -void Sema::ActOnModuleEnd(SourceLocation EofLoc, Module *Mod) { +void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) { if (getLangOpts().ModulesLocalVisibility) { VisibleModules = std::move(ModuleScopes.back().OuterVisibleModules); // Leaving a module hides namespace names, so our visible namespace cache @@ -15914,12 +15926,19 @@ void Sema::ActOnModuleEnd(SourceLocation EofLoc, Module *Mod) { "left the wrong module scope"); ModuleScopes.pop_back(); - // We got to the end of processing a #include of a local module. Create an + // We got to the end of processing a local module. Create an // ImportDecl as we would for an imported module. - FileID File = getSourceManager().getFileID(EofLoc); - assert(File != getSourceManager().getMainFileID() && - "end of submodule in main source file"); - SourceLocation DirectiveLoc = getSourceManager().getIncludeLoc(File); + FileID File = getSourceManager().getFileID(EomLoc); + SourceLocation DirectiveLoc; + if (EomLoc == getSourceManager().getLocForEndOfFile(File)) { + // We reached the end of a #included module header. Use the #include loc. + assert(File != getSourceManager().getMainFileID() && + "end of submodule in main source file"); + DirectiveLoc = getSourceManager().getIncludeLoc(File); + } else { + // We reached an EOM pragma. Use the pragma location. + DirectiveLoc = EomLoc; + } BuildModuleInclude(DirectiveLoc, Mod); } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index bb5434a03a10..97d273f6ddb6 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2891,6 +2891,28 @@ static void handleWorkGroupSize(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } +// Handles intel_reqd_sub_group_size. +static void handleSubGroupSize(Sema &S, Decl *D, const AttributeList &Attr) { + uint32_t SGSize; + const Expr *E = Attr.getArgAsExpr(0); + if (!checkUInt32Argument(S, Attr, E, SGSize)) + return; + if (SGSize == 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero) + << Attr.getName() << E->getSourceRange(); + return; + } + + OpenCLIntelReqdSubGroupSizeAttr *Existing = + D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>(); + if (Existing && Existing->getSubGroupSize() != SGSize) + S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName(); + + D->addAttr(::new (S.Context) OpenCLIntelReqdSubGroupSizeAttr( + Attr.getRange(), S.Context, SGSize, + Attr.getAttributeSpellingListIndex())); +} + static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) { if (!Attr.hasParsedType()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) @@ -5057,6 +5079,15 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { } } + // FIXME: It'd be nice to also emit a fixit removing uuid(...) (and, if it's + // the only thing in the [] list, the [] too), and add an insertion of + // __declspec(uuid(...)). But sadly, neither the SourceLocs of the commas + // separating attributes nor of the [ and the ] are in the AST. + // Cf "SourceLocations of attribute list delimiters - [[ ... , ... ]] etc" + // on cfe-dev. + if (Attr.isMicrosoftAttribute()) // Check for [uuid(...)] spelling. + S.Diag(Attr.getLoc(), diag::warn_atl_uuid_deprecated); + UuidAttr *UA = S.mergeUuidAttr(D, Attr.getRange(), Attr.getAttributeSpellingListIndex(), StrRef); if (UA) @@ -6157,6 +6188,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ReqdWorkGroupSize: handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, Attr); break; + case AttributeList::AT_OpenCLIntelReqdSubGroupSize: + handleSubGroupSize(S, D, Attr); + break; case AttributeList::AT_VecTypeHint: handleVecTypeHint(S, D, Attr); break; @@ -6521,6 +6555,9 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) << A << ExpectedKernelFunction; D->setInvalidDecl(); + } else if (Attr *A = D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) { + Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; + D->setInvalidDecl(); } } } @@ -7104,6 +7141,69 @@ void Sema::EmitAvailabilityWarning(AvailabilityResult AR, namespace { +/// Returns true if the given statement can be a body-like child of \p Parent. +bool isBodyLikeChildStmt(const Stmt *S, const Stmt *Parent) { + switch (Parent->getStmtClass()) { + case Stmt::IfStmtClass: + return cast<IfStmt>(Parent)->getThen() == S || + cast<IfStmt>(Parent)->getElse() == S; + case Stmt::WhileStmtClass: + return cast<WhileStmt>(Parent)->getBody() == S; + case Stmt::DoStmtClass: + return cast<DoStmt>(Parent)->getBody() == S; + case Stmt::ForStmtClass: + return cast<ForStmt>(Parent)->getBody() == S; + case Stmt::CXXForRangeStmtClass: + return cast<CXXForRangeStmt>(Parent)->getBody() == S; + case Stmt::ObjCForCollectionStmtClass: + return cast<ObjCForCollectionStmt>(Parent)->getBody() == S; + case Stmt::CaseStmtClass: + case Stmt::DefaultStmtClass: + return cast<SwitchCase>(Parent)->getSubStmt() == S; + default: + return false; + } +} + +class StmtUSEFinder : public RecursiveASTVisitor<StmtUSEFinder> { + const Stmt *Target; + +public: + bool VisitStmt(Stmt *S) { return S != Target; } + + /// Returns true if the given statement is present in the given declaration. + static bool isContained(const Stmt *Target, const Decl *D) { + StmtUSEFinder Visitor; + Visitor.Target = Target; + return !Visitor.TraverseDecl(const_cast<Decl *>(D)); + } +}; + +/// Traverses the AST and finds the last statement that used a given +/// declaration. +class LastDeclUSEFinder : public RecursiveASTVisitor<LastDeclUSEFinder> { + const Decl *D; + +public: + bool VisitDeclRefExpr(DeclRefExpr *DRE) { + if (DRE->getDecl() == D) + return false; + return true; + } + + static const Stmt *findLastStmtThatUsesDecl(const Decl *D, + const CompoundStmt *Scope) { + LastDeclUSEFinder Visitor; + Visitor.D = D; + for (auto I = Scope->body_rbegin(), E = Scope->body_rend(); I != E; ++I) { + const Stmt *S = *I; + if (!Visitor.TraverseStmt(const_cast<Stmt *>(S))) + return S; + } + return nullptr; + } +}; + /// \brief This class implements -Wunguarded-availability. /// /// This is done with a traversal of the AST of a function that makes reference @@ -7119,6 +7219,7 @@ class DiagnoseUnguardedAvailability /// Stack of potentially nested 'if (@available(...))'s. SmallVector<VersionTuple, 8> AvailabilityStack; + SmallVector<const Stmt *, 16> StmtStack; void DiagnoseDeclAvailability(NamedDecl *D, SourceRange Range); @@ -7129,6 +7230,15 @@ public: SemaRef.Context.getTargetInfo().getPlatformMinVersion()); } + bool TraverseStmt(Stmt *S) { + if (!S) + return true; + StmtStack.push_back(S); + bool Result = Base::TraverseStmt(S); + StmtStack.pop_back(); + return Result; + } + void IssueDiagnostics(Stmt *S) { TraverseStmt(S); } bool TraverseIfStmt(IfStmt *If); @@ -7186,9 +7296,73 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( SemaRef.Diag(D->getLocation(), diag::note_availability_specified_here) << D << /* partial */ 3; - // FIXME: Replace this with a fixit diagnostic. - SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence) - << Range << D; + auto FixitDiag = + SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence) + << Range << D + << (SemaRef.getLangOpts().ObjC1 ? /*@available*/ 0 + : /*__builtin_available*/ 1); + + // Find the statement which should be enclosed in the if @available check. + if (StmtStack.empty()) + return; + const Stmt *StmtOfUse = StmtStack.back(); + const CompoundStmt *Scope = nullptr; + for (const Stmt *S : llvm::reverse(StmtStack)) { + if (const auto *CS = dyn_cast<CompoundStmt>(S)) { + Scope = CS; + break; + } + if (isBodyLikeChildStmt(StmtOfUse, S)) { + // The declaration won't be seen outside of the statement, so we don't + // have to wrap the uses of any declared variables in if (@available). + // Therefore we can avoid setting Scope here. + break; + } + StmtOfUse = S; + } + const Stmt *LastStmtOfUse = nullptr; + if (isa<DeclStmt>(StmtOfUse) && Scope) { + for (const Decl *D : cast<DeclStmt>(StmtOfUse)->decls()) { + if (StmtUSEFinder::isContained(StmtStack.back(), D)) { + LastStmtOfUse = LastDeclUSEFinder::findLastStmtThatUsesDecl(D, Scope); + break; + } + } + } + + const SourceManager &SM = SemaRef.getSourceManager(); + SourceLocation IfInsertionLoc = + SM.getExpansionLoc(StmtOfUse->getLocStart()); + SourceLocation StmtEndLoc = + SM.getExpansionRange( + (LastStmtOfUse ? LastStmtOfUse : StmtOfUse)->getLocEnd()) + .second; + if (SM.getFileID(IfInsertionLoc) != SM.getFileID(StmtEndLoc)) + return; + + StringRef Indentation = Lexer::getIndentationForLine(IfInsertionLoc, SM); + const char *ExtraIndentation = " "; + std::string FixItString; + llvm::raw_string_ostream FixItOS(FixItString); + FixItOS << "if (" << (SemaRef.getLangOpts().ObjC1 ? "@available" + : "__builtin_available") + << "(" << SemaRef.getASTContext().getTargetInfo().getPlatformName() + << " " << Introduced.getAsString() << ", *)) {\n" + << Indentation << ExtraIndentation; + FixitDiag << FixItHint::CreateInsertion(IfInsertionLoc, FixItOS.str()); + SourceLocation ElseInsertionLoc = Lexer::findLocationAfterToken( + StmtEndLoc, tok::semi, SM, SemaRef.getLangOpts(), + /*SkipTrailingWhitespaceAndNewLine=*/false); + if (ElseInsertionLoc.isInvalid()) + ElseInsertionLoc = + Lexer::getLocForEndOfToken(StmtEndLoc, 0, SM, SemaRef.getLangOpts()); + FixItOS.str().clear(); + FixItOS << "\n" + << Indentation << "} else {\n" + << Indentation << ExtraIndentation + << "// Fallback on earlier versions\n" + << Indentation << "}"; + FixitDiag << FixItHint::CreateInsertion(ElseInsertionLoc, FixItOS.str()); } } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index fe9ba6f1f811..370461c4a24e 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -4347,10 +4347,8 @@ static void checkObjCMethodX86VectorTypes(Sema &SemaRef, AcceptedInVersion = VersionTuple(/*Major=*/10, /*Minor=*/11); else return; - VersionTuple MethodVersion = Method->getVersionIntroduced(); if (SemaRef.getASTContext().getTargetInfo().getPlatformMinVersion() >= - AcceptedInVersion && - (MethodVersion.empty() || MethodVersion >= AcceptedInVersion)) + AcceptedInVersion) return; SemaRef.Diag(Loc, diag::err_objc_method_unsupported_param_ret_type) << T << (Method->getReturnType()->isVectorType() ? /*return value*/ 1 diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d63151ef6759..849e978e2d86 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5399,9 +5399,11 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // that the callee might not preserve them. This is easy to diagnose here, // but can be very challenging to debug. if (auto *Caller = getCurFunctionDecl()) - if (Caller->hasAttr<ARMInterruptAttr>()) - if (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>()) + if (Caller->hasAttr<ARMInterruptAttr>()) { + bool VFP = Context.getTargetInfo().hasFeature("vfp"); + if (VFP && (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>())) Diag(Fn->getExprLoc(), diag::warn_arm_interrupt_calling_convention); + } // Promote the function operand. // We special-case function promotion here because we only allow promoting diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 9ffc23b5adba..5d7eada28717 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2828,7 +2828,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, // [...] If the first overload resolution fails or was not performed, or // if the type of the first parameter of the selected constructor is not - // an rvalue reference to the object’s type (possibly cv-qualified), + // an rvalue reference to the object's type (possibly cv-qualified), // overload resolution is performed again, considering the object as an // lvalue. if (!RRefType || diff --git a/lib/Tooling/JSONCompilationDatabase.cpp b/lib/Tooling/JSONCompilationDatabase.cpp index 738e610ed946..f9a230eb63a0 100644 --- a/lib/Tooling/JSONCompilationDatabase.cpp +++ b/lib/Tooling/JSONCompilationDatabase.cpp @@ -146,12 +146,8 @@ class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin { loadFromDirectory(StringRef Directory, std::string &ErrorMessage) override { SmallString<1024> JSONDatabasePath(Directory); llvm::sys::path::append(JSONDatabasePath, "compile_commands.json"); - std::unique_ptr<CompilationDatabase> Database( - JSONCompilationDatabase::loadFromFile( - JSONDatabasePath, ErrorMessage, JSONCommandLineSyntax::AutoDetect)); - if (!Database) - return nullptr; - return Database; + return JSONCompilationDatabase::loadFromFile( + JSONDatabasePath, ErrorMessage, JSONCommandLineSyntax::AutoDetect); } }; diff --git a/test/CodeGen/aarch64-args.cpp b/test/CodeGen/aarch64-args.cpp new file mode 100644 index 000000000000..409773627261 --- /dev/null +++ b/test/CodeGen/aarch64-args.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -triple arm64-apple-ios7.0 -target-abi darwinpcs -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - -x c %s | FileCheck %s --check-prefix=CHECK-GNU-C +// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GNU-CXX + +// Empty structs are ignored for PCS purposes on Darwin and in C mode elsewhere. +// In C++ mode on ELF they consume a register slot though. Functions are +// slightly bigger than minimal to make confirmation against actual GCC +// behaviour easier. + +#if __cplusplus +#define EXTERNC extern "C" +#else +#define EXTERNC +#endif + +struct Empty {}; + +// CHECK: define i32 @empty_arg(i32 %a) +// CHECK-GNU-C: define i32 @empty_arg(i32 %a) +// CHECK-GNU-CXX: define i32 @empty_arg(i8 %e.coerce, i32 %a) +EXTERNC int empty_arg(struct Empty e, int a) { + return a; +} + +// CHECK: define void @empty_ret() +// CHECK-GNU-C: define void @empty_ret() +// CHECK-GNU-CXX: define void @empty_ret() +EXTERNC struct Empty empty_ret() { + struct Empty e; + return e; +} + +// However, what counts as "empty" is a baroque mess. This is super-empty, it's +// ignored even in C++ mode. It also has sizeof == 0, violating C++, but that's +// legacy for you: + +struct SuperEmpty { + int arr[0]; +}; + +// CHECK: define i32 @super_empty_arg(i32 %a) +// CHECK-GNU-C: define i32 @super_empty_arg(i32 %a) +// CHECK-GNU-CXX: define i32 @super_empty_arg(i32 %a) +EXTERNC int super_empty_arg(struct SuperEmpty e, int a) { + return a; +} + +// This is not empty. It has 0 size but consumes a register slot for GCC. + +struct SortOfEmpty { + struct SuperEmpty e; +}; + +// CHECK: define i32 @sort_of_empty_arg(i32 %a) +// CHECK-GNU-C: define i32 @sort_of_empty_arg(i32 %a) +// CHECK-GNU-CXX: define i32 @sort_of_empty_arg(i8 %e.coerce, i32 %a) +EXTERNC int sort_of_empty_arg(struct Empty e, int a) { + return a; +} + +// CHECK: define void @sort_of_empty_ret() +// CHECK-GNU-C: define void @sort_of_empty_ret() +// CHECK-GNU-CXX: define void @sort_of_empty_ret() +EXTERNC struct SortOfEmpty sort_of_empty_ret() { + struct SortOfEmpty e; + return e; +} diff --git a/test/CodeGen/arm_acle.c b/test/CodeGen/arm_acle.c index b4f39bef1572..7c8a5aa8adb0 100644 --- a/test/CodeGen/arm_acle.c +++ b/test/CodeGen/arm_acle.c @@ -76,7 +76,7 @@ void test_dbg(void) { // AArch32: call i32 @llvm.arm.strex // AArch64: call i64 @llvm.aarch64.ldxr // AArch64: call i32 @llvm.aarch64.stxr -uint32_t test_swp(uint32_t x, volatile void *p) { +void test_swp(uint32_t x, volatile void *p) { __swp(x, p); } @@ -118,6 +118,7 @@ void test_nop(void) { } /* 9 DATA-PROCESSING INTRINSICS */ + /* 9.2 Miscellaneous data-processing intrinsics */ // ARM-LABEL: test_ror // ARM: lshr @@ -266,8 +267,7 @@ uint64_t test_rbitll(uint64_t t) { } /* 9.4 Saturating intrinsics */ -#ifdef __ARM_32BIT_STATE - +#ifdef __ARM_FEATURE_SAT /* 9.4.1 Width-specified saturation intrinsics */ // AArch32-LABEL: test_ssat // AArch32: call i32 @llvm.arm.ssat(i32 %t, i32 1) @@ -277,11 +277,13 @@ int32_t test_ssat(int32_t t) { // AArch32-LABEL: test_usat // AArch32: call i32 @llvm.arm.usat(i32 %t, i32 2) -int32_t test_usat(int32_t t) { +uint32_t test_usat(int32_t t) { return __usat(t, 2); } +#endif /* 9.4.2 Saturating addition and subtraction intrinsics */ +#ifdef __ARM_FEATURE_DSP // AArch32-LABEL: test_qadd // AArch32: call i32 @llvm.arm.qadd(i32 %a, i32 %b) int32_t test_qadd(int32_t a, int32_t b) { @@ -304,6 +306,389 @@ int32_t test_qdbl() { } #endif +/* + * 9.3 16-bit multiplications + */ +#if __ARM_FEATURE_DSP +// AArch32-LABEL: test_smulbb +// AArch32: call i32 @llvm.arm.smulbb +int32_t test_smulbb(int32_t a, int32_t b) { + return __smulbb(a, b); +} +// AArch32-LABEL: test_smulbt +// AArch32: call i32 @llvm.arm.smulbt +int32_t test_smulbt(int32_t a, int32_t b) { + return __smulbt(a, b); +} +// AArch32-LABEL: test_smultb +// AArch32: call i32 @llvm.arm.smultb +int32_t test_smultb(int32_t a, int32_t b) { + return __smultb(a, b); +} +// AArch32-LABEL: test_smultt +// AArch32: call i32 @llvm.arm.smultt +int32_t test_smultt(int32_t a, int32_t b) { + return __smultt(a, b); +} +// AArch32-LABEL: test_smulwb +// AArch32: call i32 @llvm.arm.smulwb +int32_t test_smulwb(int32_t a, int32_t b) { + return __smulwb(a, b); +} +// AArch32-LABEL: test_smulwt +// AArch32: call i32 @llvm.arm.smulwt +int32_t test_smulwt(int32_t a, int32_t b) { + return __smulwt(a, b); +} +#endif + +/* 9.4.3 Accumultating multiplications */ +#if __ARM_FEATURE_DSP +// AArch32-LABEL: test_smlabb +// AArch32: call i32 @llvm.arm.smlabb(i32 %a, i32 %b, i32 %c) +int32_t test_smlabb(int32_t a, int32_t b, int32_t c) { + return __smlabb(a, b, c); +} +// AArch32-LABEL: test_smlabt +// AArch32: call i32 @llvm.arm.smlabt(i32 %a, i32 %b, i32 %c) +int32_t test_smlabt(int32_t a, int32_t b, int32_t c) { + return __smlabt(a, b, c); +} +// AArch32-LABEL: test_smlatb +// AArch32: call i32 @llvm.arm.smlatb(i32 %a, i32 %b, i32 %c) +int32_t test_smlatb(int32_t a, int32_t b, int32_t c) { + return __smlatb(a, b, c); +} +// AArch32-LABEL: test_smlatt +// AArch32: call i32 @llvm.arm.smlatt(i32 %a, i32 %b, i32 %c) +int32_t test_smlatt(int32_t a, int32_t b, int32_t c) { + return __smlatt(a, b, c); +} +// AArch32-LABEL: test_smlawb +// AArch32: call i32 @llvm.arm.smlawb(i32 %a, i32 %b, i32 %c) +int32_t test_smlawb(int32_t a, int32_t b, int32_t c) { + return __smlawb(a, b, c); +} +// AArch32-LABEL: test_smlawt +// AArch32: call i32 @llvm.arm.smlawt(i32 %a, i32 %b, i32 %c) +int32_t test_smlawt(int32_t a, int32_t b, int32_t c) { + return __smlawt(a, b, c); +} +#endif + +/* 9.5.4 Parallel 16-bit saturation */ +#if __ARM_FEATURE_SIMD32 +// AArch32-LABEL: test_ssat16 +// AArch32: call i32 @llvm.arm.ssat16 +int16x2_t test_ssat16(int16x2_t a) { + return __ssat16(a, 15); +} +// AArch32-LABEL: test_usat16 +// AArch32: call i32 @llvm.arm.usat16 +uint16x2_t test_usat16(int16x2_t a) { + return __usat16(a, 15); +} +#endif + +/* 9.5.5 Packing and unpacking */ +#if __ARM_FEATURE_SIMD32 +// AArch32-LABEL: test_sxtab16 +// AArch32: call i32 @llvm.arm.sxtab16 +int16x2_t test_sxtab16(int16x2_t a, int8x4_t b) { + return __sxtab16(a, b); +} +// AArch32-LABEL: test_sxtb16 +// AArch32: call i32 @llvm.arm.sxtb16 +int16x2_t test_sxtb16(int8x4_t a) { + return __sxtb16(a); +} +// AArch32-LABEL: test_uxtab16 +// AArch32: call i32 @llvm.arm.uxtab16 +int16x2_t test_uxtab16(int16x2_t a, int8x4_t b) { + return __uxtab16(a, b); +} +// AArch32-LABEL: test_uxtb16 +// AArch32: call i32 @llvm.arm.uxtb16 +int16x2_t test_uxtb16(int8x4_t a) { + return __uxtb16(a); +} +#endif + +/* 9.5.6 Parallel selection */ +#if __ARM_FEATURE_SIMD32 +// AArch32-LABEL: test_sel +// AArch32: call i32 @llvm.arm.sel +uint8x4_t test_sel(uint8x4_t a, uint8x4_t b) { + return __sel(a, b); +} +#endif + +/* 9.5.7 Parallel 8-bit addition and subtraction */ +#if __ARM_FEATURE_SIMD32 +// AArch32-LABEL: test_qadd8 +// AArch32: call i32 @llvm.arm.qadd8 +int16x2_t test_qadd8(int8x4_t a, int8x4_t b) { + return __qadd8(a, b); +} +// AArch32-LABEL: test_qsub8 +// AArch32: call i32 @llvm.arm.qsub8 +int8x4_t test_qsub8(int8x4_t a, int8x4_t b) { + return __qsub8(a, b); +} +// AArch32-LABEL: test_sadd8 +// AArch32: call i32 @llvm.arm.sadd8 +int8x4_t test_sadd8(int8x4_t a, int8x4_t b) { + return __sadd8(a, b); +} +// AArch32-LABEL: test_shadd8 +// AArch32: call i32 @llvm.arm.shadd8 +int8x4_t test_shadd8(int8x4_t a, int8x4_t b) { + return __shadd8(a, b); +} +// AArch32-LABEL: test_shsub8 +// AArch32: call i32 @llvm.arm.shsub8 +int8x4_t test_shsub8(int8x4_t a, int8x4_t b) { + return __shsub8(a, b); +} +// AArch32-LABEL: test_ssub8 +// AArch32: call i32 @llvm.arm.ssub8 +int8x4_t test_ssub8(int8x4_t a, int8x4_t b) { + return __ssub8(a, b); +} +// AArch32-LABEL: test_uadd8 +// AArch32: call i32 @llvm.arm.uadd8 +uint8x4_t test_uadd8(uint8x4_t a, uint8x4_t b) { + return __uadd8(a, b); +} +// AArch32-LABEL: test_uhadd8 +// AArch32: call i32 @llvm.arm.uhadd8 +uint8x4_t test_uhadd8(uint8x4_t a, uint8x4_t b) { + return __uhadd8(a, b); +} +// AArch32-LABEL: test_uhsub8 +// AArch32: call i32 @llvm.arm.uhsub8 +uint8x4_t test_uhsub8(uint8x4_t a, uint8x4_t b) { + return __uhsub8(a, b); +} +// AArch32-LABEL: test_uqadd8 +// AArch32: call i32 @llvm.arm.uqadd8 +uint8x4_t test_uqadd8(uint8x4_t a, uint8x4_t b) { + return __uqadd8(a, b); +} +// AArch32-LABEL: test_uqsub8 +// AArch32: call i32 @llvm.arm.uqsub8 +uint8x4_t test_uqsub8(uint8x4_t a, uint8x4_t b) { + return __uqsub8(a, b); +} +// AArch32-LABEL: test_usub8 +// AArch32: call i32 @llvm.arm.usub8 +uint8x4_t test_usub8(uint8x4_t a, uint8x4_t b) { + return __usub8(a, b); +} +#endif + +/* 9.5.8 Sum of 8-bit absolute differences */ +#if __ARM_FEATURE_SIMD32 +// AArch32-LABEL: test_usad8 +// AArch32: call i32 @llvm.arm.usad8 +uint32_t test_usad8(uint8x4_t a, uint8x4_t b) { + return __usad8(a, b); +} +// AArch32-LABEL: test_usada8 +// AArch32: call i32 @llvm.arm.usada8 +uint32_t test_usada8(uint8_t a, uint8_t b, uint8_t c) { + return __usada8(a, b, c); +} +#endif + +/* 9.5.9 Parallel 16-bit addition and subtraction */ +#if __ARM_FEATURE_SIMD32 +// AArch32-LABEL: test_qadd16 +// AArch32: call i32 @llvm.arm.qadd16 +int16x2_t test_qadd16(int16x2_t a, int16x2_t b) { + return __qadd16(a, b); +} +// AArch32-LABEL: test_qasx +// AArch32: call i32 @llvm.arm.qasx +int16x2_t test_qasx(int16x2_t a, int16x2_t b) { + return __qasx(a, b); +} +// AArch32-LABEL: test_qsax +// AArch32: call i32 @llvm.arm.qsax +int16x2_t test_qsax(int16x2_t a, int16x2_t b) { + return __qsax(a, b); +} +// AArch32-LABEL: test_qsub16 +// AArch32: call i32 @llvm.arm.qsub16 +int16x2_t test_qsub16(int16x2_t a, int16x2_t b) { + return __qsub16(a, b); +} +// AArch32-LABEL: test_sadd16 +// AArch32: call i32 @llvm.arm.sadd16 +int16x2_t test_sadd16(int16x2_t a, int16x2_t b) { + return __sadd16(a, b); +} +// AArch32-LABEL: test_sasx +// AArch32: call i32 @llvm.arm.sasx +int16x2_t test_sasx(int16x2_t a, int16x2_t b) { + return __sasx(a, b); +} +// AArch32-LABEL: test_shadd16 +// AArch32: call i32 @llvm.arm.shadd16 +int16x2_t test_shadd16(int16x2_t a, int16x2_t b) { + return __shadd16(a, b); +} +// AArch32-LABEL: test_shasx +// AArch32: call i32 @llvm.arm.shasx +int16x2_t test_shasx(int16x2_t a, int16x2_t b) { + return __shasx(a, b); +} +// AArch32-LABEL: test_shsax +// AArch32: call i32 @llvm.arm.shsax +int16x2_t test_shsax(int16x2_t a, int16x2_t b) { + return __shsax(a, b); +} +// AArch32-LABEL: test_shsub16 +// AArch32: call i32 @llvm.arm.shsub16 +int16x2_t test_shsub16(int16x2_t a, int16x2_t b) { + return __shsub16(a, b); +} +// AArch32-LABEL: test_ssax +// AArch32: call i32 @llvm.arm.ssax +int16x2_t test_ssax(int16x2_t a, int16x2_t b) { + return __ssax(a, b); +} +// AArch32-LABEL: test_ssub16 +// AArch32: call i32 @llvm.arm.ssub16 +int16x2_t test_ssub16(int16x2_t a, int16x2_t b) { + return __ssub16(a, b); +} +// AArch32-LABEL: test_uadd16 +// AArch32: call i32 @llvm.arm.uadd16 +uint16x2_t test_uadd16(uint16x2_t a, uint16x2_t b) { + return __uadd16(a, b); +} +// AArch32-LABEL: test_uasx +// AArch32: call i32 @llvm.arm.uasx +uint16x2_t test_uasx(uint16x2_t a, uint16x2_t b) { + return __uasx(a, b); +} +// AArch32-LABEL: test_uhadd16 +// AArch32: call i32 @llvm.arm.uhadd16 +uint16x2_t test_uhadd16(uint16x2_t a, uint16x2_t b) { + return __uhadd16(a, b); +} +// AArch32-LABEL: test_uhasx +// AArch32: call i32 @llvm.arm.uhasx +uint16x2_t test_uhasx(uint16x2_t a, uint16x2_t b) { + return __uhasx(a, b); +} +// AArch32-LABEL: test_uhsax +// AArch32: call i32 @llvm.arm.uhsax +uint16x2_t test_uhsax(uint16x2_t a, uint16x2_t b) { + return __uhsax(a, b); +} +// AArch32-LABEL: test_uhsub16 +// AArch32: call i32 @llvm.arm.uhsub16 +uint16x2_t test_uhsub16(uint16x2_t a, uint16x2_t b) { + return __uhsub16(a, b); +} +// AArch32-LABEL: test_uqadd16 +// AArch32: call i32 @llvm.arm.uqadd16 +uint16x2_t test_uqadd16(uint16x2_t a, uint16x2_t b) { + return __uqadd16(a, b); +} +// AArch32-LABEL: test_uqasx +// AArch32: call i32 @llvm.arm.uqasx +uint16x2_t test_uqasx(uint16x2_t a, uint16x2_t b) { + return __uqasx(a, b); +} +// AArch32-LABEL: test_uqsax +// AArch32: call i32 @llvm.arm.uqsax +uint16x2_t test_uqsax(uint16x2_t a, uint16x2_t b) { + return __uqsax(a, b); +} +// AArch32-LABEL: test_uqsub16 +// AArch32: call i32 @llvm.arm.uqsub16 +uint16x2_t test_uqsub16(uint16x2_t a, uint16x2_t b) { + return __uqsub16(a, b); +} +// AArch32-LABEL: test_usax +// AArch32: call i32 @llvm.arm.usax +uint16x2_t test_usax(uint16x2_t a, uint16x2_t b) { + return __usax(a, b); +} +// AArch32-LABEL: test_usub16 +// AArch32: call i32 @llvm.arm.usub16 +uint16x2_t test_usub16(uint16x2_t a, uint16x2_t b) { + return __usub16(a, b); +} +#endif + +/* 9.5.10 Parallel 16-bit multiplications */ +#if __ARM_FEATURE_SIMD32 +// AArch32-LABEL: test_smlad +// AArch32: call i32 @llvm.arm.smlad +int32_t test_smlad(int16x2_t a, int16x2_t b, int32_t c) { + return __smlad(a, b, c); +} +// AArch32-LABEL: test_smladx +// AArch32: call i32 @llvm.arm.smladx +int32_t test_smladx(int16x2_t a, int16x2_t b, int32_t c) { + return __smladx(a, b, c); +} +// AArch32-LABEL: test_smlald +// AArch32: call i64 @llvm.arm.smlald +int64_t test_smlald(int16x2_t a, int16x2_t b, int64_t c) { + return __smlald(a, b, c); +} +// AArch32-LABEL: test_smlaldx +// AArch32: call i64 @llvm.arm.smlaldx +int64_t test_smlaldx(int16x2_t a, int16x2_t b, int64_t c) { + return __smlaldx(a, b, c); +} +// AArch32-LABEL: test_smlsd +// AArch32: call i32 @llvm.arm.smlsd +int32_t test_smlsd(int16x2_t a, int16x2_t b, int32_t c) { + return __smlsd(a, b, c); +} +// AArch32-LABEL: test_smlsdx +// AArch32: call i32 @llvm.arm.smlsdx +int32_t test_smlsdx(int16x2_t a, int16x2_t b, int32_t c) { + return __smlsdx(a, b, c); +} +// AArch32-LABEL: test_smlsld +// AArch32: call i64 @llvm.arm.smlsld +int64_t test_smlsld(int16x2_t a, int16x2_t b, int64_t c) { + return __smlsld(a, b, c); +} +// AArch32-LABEL: test_smlsldx +// AArch32: call i64 @llvm.arm.smlsldx +int64_t test_smlsldx(int16x2_t a, int16x2_t b, int64_t c) { + return __smlsldx(a, b, c); +} +// AArch32-LABEL: test_smuad +// AArch32: call i32 @llvm.arm.smuad +int32_t test_smuad(int16x2_t a, int16x2_t b) { + return __smuad(a, b); +} +// AArch32-LABEL: test_smuadx +// AArch32: call i32 @llvm.arm.smuadx +int32_t test_smuadx(int16x2_t a, int16x2_t b) { + return __smuadx(a, b); +} +// AArch32-LABEL: test_smusd +// AArch32: call i32 @llvm.arm.smusd +int32_t test_smusd(int16x2_t a, int16x2_t b) { + return __smusd(a, b); +} +// AArch32-LABEL: test_smusdx +// AArch32: call i32 @llvm.arm.smusdx +int32_t test_smusdx(int16x2_t a, int16x2_t b) { + return __smusdx(a, b); +} +#endif + /* 9.7 CRC32 intrinsics */ // ARM-LABEL: test_crc32b // AArch32: call i32 @llvm.arm.crc32b diff --git a/test/CodeGen/lwp-builtins.c b/test/CodeGen/lwp-builtins.c new file mode 100644 index 000000000000..c689c3974d4b --- /dev/null +++ b/test/CodeGen/lwp-builtins.c @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +lwp -emit-llvm -o - -Wall -Werror | FileCheck %s + +#include <x86intrin.h> + +void test_llwpcb(void *ptr) { + // CHECK-LABEL: @test_llwpcb + // CHECK: call void @llvm.x86.llwpcb(i8* %{{.*}}) + __llwpcb(ptr); +} + +void* test_slwpcb() { + // CHECK-LABEL: @test_slwpcb + // CHECK: call i8* @llvm.x86.slwpcb() + return __slwpcb(); +} + +unsigned char test_lwpins32(unsigned val2, unsigned val1) { + // CHECK-LABEL: @test_lwpins32 + // CHECK: call i8 @llvm.x86.lwpins32(i32 + return __lwpins32(val2, val1, 0x01234); +} + +unsigned char test_lwpins64(unsigned long long val2, unsigned val1) { + // CHECK-LABEL: @test_lwpins64 + // CHECK: call i8 @llvm.x86.lwpins64(i64 + return __lwpins64(val2, val1, 0x56789); +} + +void test_lwpval32(unsigned val2, unsigned val1) { + // CHECK-LABEL: @test_lwpval32 + // CHECK: call void @llvm.x86.lwpval32(i32 + __lwpval32(val2, val1, 0x01234); +} + +void test_lwpval64(unsigned long long val2, unsigned val1) { + // CHECK-LABEL: @test_lwpval64 + // CHECK: call void @llvm.x86.lwpval64(i64 + __lwpval64(val2, val1, 0xABCDEF); +} diff --git a/test/CodeGen/mozilla-ms-inline-asm.c b/test/CodeGen/mozilla-ms-inline-asm.c index 3335a87fefe5..26e8ebce1e28 100644 --- a/test/CodeGen/mozilla-ms-inline-asm.c +++ b/test/CodeGen/mozilla-ms-inline-asm.c @@ -18,25 +18,25 @@ void invoke(void* that, unsigned methodIndex, // CHECK: store i32 %2, i32* %7, align 4 // CHECK: store i8* %3, i8** %8, align 4 // CHECK: call void asm sideeffect inteldialect -// CHECK: mov edx,dword ptr $1 -// CHECK: test edx,edx -// CHECK: jz {{[^_]*}}__MSASMLABEL_.${:uid}__noparams -// ^ Can't use {{.*}} here because the matching is greedy. -// CHECK: mov eax,edx -// CHECK: shl eax,$$3 -// CHECK: sub esp,eax -// CHECK: mov ecx,esp -// CHECK: push dword ptr $0 -// CHECK: call dword ptr $2 -// CHECK: {{.*}}__MSASMLABEL_.${:uid}__noparams: -// CHECK: mov ecx,dword ptr $3 -// CHECK: push ecx -// CHECK: mov edx,[ecx] -// CHECK: mov eax,dword ptr $4 -// CHECK: call dword ptr[edx+eax*$$4] -// CHECK: mov esp,ebp -// CHECK: pop ebp -// CHECK: ret +// CHECK-SAME: mov edx,$1 +// CHECK-SAME: test edx,edx +// CHECK-SAME: jz {{[^_]*}}__MSASMLABEL_.${:uid}__noparams +// ^ Can't use {{.*}} here because the matching is greedy. +// CHECK-SAME: mov eax,edx +// CHECK-SAME: shl eax,$$3 +// CHECK-SAME: sub esp,eax +// CHECK-SAME: mov ecx,esp +// CHECK-SAME: push $0 +// CHECK-SAME: call dword ptr $2 +// CHECK-SAME: {{.*}}__MSASMLABEL_.${:uid}__noparams: +// CHECK-SAME: mov ecx,$3 +// CHECK-SAME: push ecx +// CHECK-SAME: mov edx,[ecx] +// CHECK-SAME: mov eax,$4 +// CHECK-SAME: call dword ptr[edx+eax*$$4] +// CHECK-SAME: mov esp,ebp +// CHECK-SAME: pop ebp +// CHECK-SAME: ret // CHECK: "=*m,*m,*m,*m,*m,~{eax},~{ebp},~{ecx},~{edx},~{flags},~{esp},~{dirflag},~{fpsr},~{flags}" // CHECK: (i8** %8, i32* %7, void (...)* bitcast (void ()* @invoke_copy_to_stack to void (...)*), i8** %5, i32* %6) // CHECK: ret void diff --git a/test/CodeGen/ms-inline-asm-64.c b/test/CodeGen/ms-inline-asm-64.c index d6f6e2ee0e0e..69828feb3623 100644 --- a/test/CodeGen/ms-inline-asm-64.c +++ b/test/CodeGen/ms-inline-asm-64.c @@ -5,14 +5,18 @@ void t1() { int var = 10; __asm mov rax, offset var ; rax = address of myvar // CHECK: t1 -// CHECK: call void asm sideeffect inteldialect "mov rax, $0", "r,~{rax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov rax, $0 +// CHECK-SAME: "r,~{rax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) } void t2() { int var = 10; __asm mov [eax], offset var // CHECK: t2 -// CHECK: call void asm sideeffect inteldialect "mov [eax], $0", "r,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov [eax], $0 +// CHECK-SAME: "r,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) } struct t3_type { int a, b; }; @@ -28,7 +32,11 @@ int t3() { } return foo.b; // CHECK: t3 -// CHECK: call void asm sideeffect inteldialect "lea ebx, qword ptr $0\0A\09mov eax, [ebx].0\0A\09mov [ebx].4, ecx", "*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(%struct.t3_type* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: lea ebx, $0 +// CHECK-SAME: mov eax, [ebx].0 +// CHECK-SAME: mov [ebx].4, ecx +// CHECK-SAME: "*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(%struct.t3_type* %{{.*}}) } int t4() { @@ -44,5 +52,9 @@ int t4() { } return foo.b; // CHECK: t4 -// CHECK: call void asm sideeffect inteldialect "lea ebx, qword ptr $0\0A\09mov eax, [ebx].0\0A\09mov [ebx].4, ecx", "*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(%struct.t3_type* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: lea ebx, $0 +// CHECK-SAME: mov eax, [ebx].0 +// CHECK-SAME: mov [ebx].4, ecx +// CHECK-SAME: "*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(%struct.t3_type* %{{.*}}) } diff --git a/test/CodeGen/ms-inline-asm-avx512.c b/test/CodeGen/ms-inline-asm-avx512.c index c1b783a2107c..6189e50d2116 100644 --- a/test/CodeGen/ms-inline-asm-avx512.c +++ b/test/CodeGen/ms-inline-asm-avx512.c @@ -1,5 +1,5 @@ // REQUIRES: x86-registered-target -// RUN: %clang_cc1 %s -triple x86_64-pc-windows-msvc -target-cpu knl -fasm-blocks -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple x86_64-pc-windows-msvc -target-cpu skylake-avx512 -fasm-blocks -emit-llvm -o - | FileCheck %s void t1() { // CHECK: @t1 @@ -19,3 +19,16 @@ void t2() { vaddpd zmm8 {k1}, zmm27, zmm6 } } + +void ignore_fe_size() { + // CHECK-LABEL: define void @ignore_fe_size() + char c; + // CHECK: vaddps xmm1, xmm2, $1{1to4} + __asm vaddps xmm1, xmm2, [c]{1to4} + // CHECK: vaddps xmm1, xmm2, $2 + __asm vaddps xmm1, xmm2, [c] + // CHECK: mov eax, $3 + __asm mov eax, [c] + // CHECK: mov $0, rax + __asm mov [c], rax +} diff --git a/test/CodeGen/ms-inline-asm.c b/test/CodeGen/ms-inline-asm.c index c4fe08a3e13b..5182d7f2e81a 100644 --- a/test/CodeGen/ms-inline-asm.c +++ b/test/CodeGen/ms-inline-asm.c @@ -92,7 +92,11 @@ void t9() { __asm { pop ebx } } // CHECK: t9 -// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$0x07\0A\09pop ebx\0A\09", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: push ebx +// CHECK-SAME: mov ebx, $$0x07 +// CHECK-SAME: pop ebx +// CHECK-SAME: "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() } unsigned t10(void) { @@ -107,7 +111,10 @@ unsigned t10(void) { // CHECK: [[I:%[a-zA-Z0-9]+]] = alloca i32, align 4 // CHECK: [[J:%[a-zA-Z0-9]+]] = alloca i32, align 4 // CHECK: store i32 1, i32* [[I]], align 4 -// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $2\0A\09mov dword ptr $0, eax", "=*m,={eax},*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}) +// CHECK: call i32 asm sideeffect inteldialect +// CHECK-SAME: mov eax, $2 +// CHECK-SAME: mov $0, eax +// CHECK-SAME: "=*m,={eax},*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}) // CHECK: [[RET:%[a-zA-Z0-9]+]] = load i32, i32* [[J]], align 4 // CHECK: ret i32 [[RET]] } @@ -128,7 +135,12 @@ unsigned t12(void) { } return j + m; // CHECK: t12 -// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $3\0A\09mov dword ptr $0, eax\0A\09mov eax, dword ptr $4\0A\09mov dword ptr $1, eax", "=*m,=*m,={eax},*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) +// CHECK: call i32 asm sideeffect inteldialect +// CHECK-SAME: mov eax, $3 +// CHECK-SAME: mov $0, eax +// CHECK-SAME: mov eax, $4 +// CHECK-SAME: mov $1, eax +// CHECK-SAME: "=*m,=*m,={eax},*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) } void t13() { @@ -136,8 +148,23 @@ void t13() { short j = 2; __asm movzx eax, i __asm movzx eax, j -// CHECK: t13 -// CHECK: call void asm sideeffect inteldialect "movzx eax, byte ptr $0\0A\09movzx eax, word ptr $1", "*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}}i, i16* %{{.*}}j) +// CHECK-LABEL: define void @t13() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: movzx eax, byte ptr $0 +// CHECK-SAME: movzx eax, word ptr $1 +// CHECK-SAME: "*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}}i, i16* %{{.*}}j) +} + +void t13_brac() { + char i = 1; + short j = 2; + __asm movzx eax, [i] + __asm movzx eax, [j] +// CHECK-LABEL: define void @t13_brac() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: movzx eax, byte ptr $0 +// CHECK-SAME: movzx eax, word ptr $1 +// CHECK-SAME: "*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}}i, i16* %{{.*}}j) } void t14() { @@ -150,7 +177,7 @@ void t14() { .endif } // CHECK: t14 -// CHECK: call void asm sideeffect inteldialect ".if 1\0A\09mov eax, dword ptr $0\0A\09.else\0A\09mov ebx, j\0A\09.endif", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect ".if 1\0A\09mov eax, $0\0A\09.else\0A\09mov ebx, j\0A\09.endif", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) } int gvar = 10; @@ -158,7 +185,7 @@ void t15() { // CHECK: t15 int lvar = 10; __asm mov eax, lvar ; eax = 10 -// CHECK: mov eax, dword ptr $0 +// CHECK: mov eax, $0 __asm mov eax, offset lvar ; eax = address of lvar // CHECK: mov eax, $1 __asm mov eax, offset gvar ; eax = address of gvar @@ -236,7 +263,11 @@ void t21() { __asm pop ebx } // CHECK: t21 -// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$07H\0A\09pop ebx", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: push ebx +// CHECK-SAME: mov ebx, $$07H +// CHECK-SAME: pop ebx +// CHECK-SAME: "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() } extern void t22_helper(int x); @@ -252,9 +283,15 @@ void t22() { __asm pop ebx } // CHECK: t22 -// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, esp", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: push ebx +// CHECK-SAME: mov ebx, esp +// CHECK-SAME: "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() // CHECK: call void @t22_helper -// CHECK: call void asm sideeffect inteldialect "mov esp, ebx\0A\09pop ebx", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov esp, ebx +// CHECK-SAME: pop ebx +// CHECK-SAME: "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() } void t23() { @@ -342,9 +379,9 @@ int *t30() { int *res; __asm lea edi, results -// CHECK: lea edi, dword ptr $2 +// CHECK: lea edi, $2 __asm mov res, edi -// CHECK: mov dword ptr $0, edi +// CHECK: mov $0, edi return res; // CHECK: "=*m,={eax},*m,~{edi},~{dirflag},~{fpsr},~{flags}"(i32** %{{.*}}, [2 x i32]* @{{.*}}) } @@ -362,7 +399,7 @@ void t32() { // CHECK: t32 int i; __asm mov eax, i -// CHECK: mov eax, dword ptr $0 +// CHECK: mov eax, $0 __asm mov eax, dword ptr i // CHECK: mov eax, dword ptr $1 __asm mov ax, word ptr i @@ -376,7 +413,7 @@ void t33() { // CHECK: t33 int i; __asm mov eax, [i] -// CHECK: mov eax, dword ptr $0 +// CHECK: mov eax, $0 __asm mov eax, dword ptr [i] // CHECK: mov eax, dword ptr $1 __asm mov ax, word ptr [i] @@ -409,31 +446,31 @@ void t36() { int arr[4]; // Work around PR20368: These should be single line blocks __asm { mov eax, 4[arr] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4[arr + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 8[arr + 4 + 32*2 - 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$72$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$72$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 12[4 + arr] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$16$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$16$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4[4 + arr + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4[64 + arr + (2*32)] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$132$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$132$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4[64 + arr - 2*32] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, [arr + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, [arr + 4 + 32*2 - 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$64$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$64$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, [4 + arr] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, [4 + arr + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, [64 + arr + (2*32)] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$128$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$128$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, [64 + arr - 2*32] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) } void t37() { @@ -464,21 +501,21 @@ void t38() { int arr[4]; // Work around PR20368: These should be single line blocks __asm { mov eax, 4+4[arr] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, (4+4)[arr + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 8*2[arr + 4 + 32*2 - 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$80$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$80$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 12+20[4 + arr] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$36$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$36$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4*16+4[4 + arr + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$76$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$76$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4*4[64 + arr + (2*32)] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$144$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$144$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4*(4-2)[64 + arr - 2*32] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 32*(4-2)[arr - 2*32] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$0$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$0$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) } void cpuid() { @@ -554,7 +591,7 @@ void t42() { // CHECK-LABEL: define void @t42 int flags; __asm mov flags, eax -// CHECK: mov dword ptr $0, eax +// CHECK: mov $0, eax // CHECK: "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %flags) } @@ -563,31 +600,31 @@ void t43() { C strct; // Work around PR20368: These should be single line blocks __asm { mov eax, 4[strct.c1] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, 4[strct.c3 + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, 8[strct.c2.a + 4 + 32*2 - 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$72$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$72$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, 12[4 + strct.c2.b] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$16$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$16$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, 4[4 + strct.c4.b2.b + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, 4[64 + strct.c1 + (2*32)] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$132$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$132$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, 4[64 + strct.c2.a - 2*32] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, [strct.c4.b1 + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, [strct.c4.b2.a + 4 + 32*2 - 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$64$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$64$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, [4 + strct.c1] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, [4 + strct.c2.b + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, [64 + strct.c3 + (2*32)] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$128$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$128$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, [64 + strct.c4.b2.b - 2*32] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) } void call_clobber() { @@ -662,7 +699,7 @@ void mxcsr() { __asm fxrstor buf } // CHECK-LABEL: define void @mxcsr -// CHECK: call void asm sideeffect inteldialect "fxrstor byte ptr $0", "=*m,~{dirflag},~{fpsr},~{flags}" +// CHECK: call void asm sideeffect inteldialect "fxrstor $0", "=*m,~{dirflag},~{fpsr},~{flags}" typedef union _LARGE_INTEGER { struct { @@ -680,7 +717,7 @@ int test_indirect_field(LARGE_INTEGER LargeInteger) { __asm mov eax, LargeInteger.LowPart } // CHECK-LABEL: define i32 @test_indirect_field( -// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $1", +// CHECK: call i32 asm sideeffect inteldialect "mov eax, $1", // MS ASM containing labels must not be duplicated (PR23715). // CHECK: attributes [[ATTR1]] = { diff --git a/test/CodeGen/ms-inline-asm.cpp b/test/CodeGen/ms-inline-asm.cpp index 424c1992cc2c..a435e4b826d8 100644 --- a/test/CodeGen/ms-inline-asm.cpp +++ b/test/CodeGen/ms-inline-asm.cpp @@ -14,15 +14,21 @@ struct Foo { }; void t1() { +// CHECK-LABEL: define void @_Z2t1v() Foo::ptr = (int *)0xDEADBEEF; Foo::Bar::ptr = (int *)0xDEADBEEF; +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov eax, $0 +// CHECK-SAME: mov eax, $1 +// CHECK-SAME: mov eax, $2 +// CHECK-SAME: mov eax, dword ptr $3 +// CHECK-SAME: mov eax, dword ptr $4 +// CHECK-SAME: "*m,*m,*m,*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE) __asm mov eax, Foo ::ptr __asm mov eax, Foo :: Bar :: ptr __asm mov eax, [Foo:: ptr] __asm mov eax, dword ptr [Foo :: ptr] __asm mov eax, dword ptr [Foo :: ptr] -// CHECK: @_Z2t1v -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0\0A\09mov eax, dword ptr $1\0A\09mov eax, dword ptr $2\0A\09mov eax, dword ptr $3\0A\09mov eax, dword ptr $4", "*m,*m,*m,*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE) } int gvar = 10; @@ -30,8 +36,11 @@ void t2() { int lvar = 10; __asm mov eax, offset Foo::ptr __asm mov eax, offset Foo::Bar::ptr -// CHECK: t2 -// CHECK: call void asm sideeffect inteldialect "mov eax, $0\0A\09mov eax, $1", "r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE) +// CHECK-LABEL: define void @_Z2t2v() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov eax, $0 +// CHECK-SAME: mov eax, $1 +// CHECK-SAME: "r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE) } // CHECK-LABEL: define void @_Z2t3v() @@ -50,7 +59,20 @@ void t3() { __asm mov eax, SIZE Foo::Bar::ptr __asm mov eax, SIZE Foo::arr __asm mov eax, SIZE Foo::Bar::arr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$1\0A\09mov eax, $$1\0A\09mov eax, $$4\0A\09mov eax, $$2\0A\09mov eax, $$4\0A\09mov eax, $$4\0A\09mov eax, $$4\0A\09mov eax, $$1\0A\09mov eax, $$4\0A\09mov eax, $$4\0A\09mov eax, $$16\0A\09mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov eax, $$1 +// CHECK-SAME: mov eax, $$1 +// CHECK-SAME: mov eax, $$4 +// CHECK-SAME: mov eax, $$2 +// CHECK-SAME: mov eax, $$4 +// CHECK-SAME: mov eax, $$4 +// CHECK-SAME: mov eax, $$4 +// CHECK-SAME: mov eax, $$1 +// CHECK-SAME: mov eax, $$4 +// CHECK-SAME: mov eax, $$4 +// CHECK-SAME: mov eax, $$16 +// CHECK-SAME: mov eax, $$2 +// CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"() } @@ -67,7 +89,10 @@ void T4::test() { // CHECK: [[X:%.*]] = getelementptr inbounds [[T4]], [[T4]]* [[THIS]], i32 0, i32 0 __asm mov eax, x; __asm mov y, eax; -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $1\0A\09mov dword ptr $0, eax", "=*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* @_ZN2T41yE, i32* {{.*}}) +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov eax, $1 +// CHECK-SAME: mov $0, eax +// CHECK-SAME: "=*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* @_ZN2T41yE, i32* {{.*}}) } template <class T> struct T5 { @@ -82,7 +107,11 @@ void test5() { __asm push y __asm call T5<int>::create<float> __asm mov x, eax - // CHECK: call void asm sideeffect inteldialect "push dword ptr $0\0A\09call dword ptr $2\0A\09mov dword ptr $1, eax", "=*m,=*m,*m,~{esp},~{dirflag},~{fpsr},~{flags}"(i32* %y, i32* %x, i32 (float)* @_ZN2T5IiE6createIfEEiT_) + // CHECK: call void asm sideeffect inteldialect + // CHECK-SAME: push $0 + // CHECK-SAME: call dword ptr $2 + // CHECK-SAME: mov $1, eax + // CHECK-SAME: "=*m,=*m,*m,~{esp},~{dirflag},~{fpsr},~{flags}"(i32* %y, i32* %x, i32 (float)* @_ZN2T5IiE6createIfEEiT_) } // Just verify this doesn't emit an error. @@ -100,7 +129,9 @@ void t7_struct() { }; __asm mov eax, [eax].A.b // CHECK-LABEL: define void @_Z9t7_structv - // CHECK: call void asm sideeffect inteldialect "mov eax, [eax].4", "~{eax},~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect + // CHECK-SAME: mov eax, [eax].4 + // CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t7_typedef() { @@ -110,7 +141,9 @@ void t7_typedef() { } A; __asm mov eax, [eax].A.b // CHECK-LABEL: define void @_Z10t7_typedefv - // CHECK: call void asm sideeffect inteldialect "mov eax, [eax].4", "~{eax},~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect + // CHECK-SAME: mov eax, [eax].4 + // CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t7_using() { @@ -120,20 +153,28 @@ void t7_using() { }; __asm mov eax, [eax].A.b // CHECK-LABEL: define void @_Z8t7_usingv - // CHECK: call void asm sideeffect inteldialect "mov eax, [eax].4", "~{eax},~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect + // CHECK-SAME: mov eax, [eax].4 + // CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t8() { __asm some_label: // CHECK-LABEL: define void @_Z2t8v() - // CHECK: call void asm sideeffect inteldialect "L__MSASMLABEL_.${:uid}__some_label:", "~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect + // CHECK-SAME: L__MSASMLABEL_.${:uid}__some_label: + // CHECK-SAME: "~{dirflag},~{fpsr},~{flags}"() struct A { static void g() { __asm jmp some_label ; This should jump forwards __asm some_label: __asm nop // CHECK-LABEL: define internal void @_ZZ2t8vEN1A1gEv() - // CHECK: call void asm sideeffect inteldialect "jmp L__MSASMLABEL_.${:uid}__some_label\0A\09L__MSASMLABEL_.${:uid}__some_label:\0A\09nop", "~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect + // CHECK-SAME: jmp L__MSASMLABEL_.${:uid}__some_label + // CHECK-SAME: L__MSASMLABEL_.${:uid}__some_label: + // CHECK-SAME: nop + // CHECK-SAME: "~{dirflag},~{fpsr},~{flags}"() } }; A::g(); diff --git a/test/CodeGen/thinlto_backend.ll b/test/CodeGen/thinlto_backend.ll index ac0b3b76ef7d..813bb62c1a29 100644 --- a/test/CodeGen/thinlto_backend.ll +++ b/test/CodeGen/thinlto_backend.ll @@ -35,8 +35,12 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" declare void @f2() +declare i8* @f3() define void @f1() { call void @f2() + ; Make sure that the backend can handle undefined references. + ; Do an indirect call so that the undefined ref shows up in the combined index. + call void bitcast (i8*()* @f3 to void()*)() ret void } diff --git a/test/CodeGenCXX/ms-inline-asm-fields.cpp b/test/CodeGenCXX/ms-inline-asm-fields.cpp index 6f329330bda4..5ee6acf57466 100644 --- a/test/CodeGenCXX/ms-inline-asm-fields.cpp +++ b/test/CodeGenCXX/ms-inline-asm-fields.cpp @@ -17,14 +17,14 @@ A a_global; extern "C" int test_param_field(A p) { // CHECK: define i32 @test_param_field(%struct.A* byval align 4 %p) // CHECK: getelementptr inbounds %struct.A, %struct.A* %p, i32 0, i32 0 -// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $1" +// CHECK: call i32 asm sideeffect inteldialect "mov eax, $1" // CHECK: ret i32 __asm mov eax, p.a1 } extern "C" int test_namespace_global() { // CHECK: define i32 @test_namespace_global() -// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $1", "{{.*}}"(i32* getelementptr inbounds (%struct.A, %struct.A* @_ZN4asdf8a_globalE, i32 0, i32 2, i32 1)) +// CHECK: call i32 asm sideeffect inteldialect "mov eax, $1", "{{.*}}"(i32* getelementptr inbounds (%struct.A, %struct.A* @_ZN4asdf8a_globalE, i32 0, i32 2, i32 1)) // CHECK: ret i32 __asm mov eax, asdf::a_global.a3.b2 } diff --git a/test/CodeGenObjC/arc-foreach.m b/test/CodeGenObjC/arc-foreach.m index e34445704e37..e3b3f1aa5ce4 100644 --- a/test/CodeGenObjC/arc-foreach.m +++ b/test/CodeGenObjC/arc-foreach.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -emit-llvm %s -o %t-64.s -// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -fobjc-arc -fobjc-runtime-has-weak -emit-llvm %s -o - | FileCheck -check-prefix CHECK-LP64 %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -emit-llvm %s -o - | FileCheck -check-prefix CHECK-LP64-OPT %s // rdar://9503326 // rdar://9606600 @@ -29,6 +29,11 @@ void test0(NSArray *array) { // CHECK-LP64-NEXT: [[BUFFER:%.*]] = alloca [16 x i8*], align 8 // CHECK-LP64-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], +// CHECK-LP64-OPT-LABEL: define void @test0 +// CHECK-LP64-OPT: [[STATE:%.*]] = alloca [[STATE_T:%.*]], align 8 +// CHECK-LP64-OPT-NEXT: [[BUFFER:%.*]] = alloca [16 x i8*], align 8 +// CHECK-LP64-OPT-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8 + // Initialize 'array'. // CHECK-LP64-NEXT: store [[ARRAY_T]]* null, [[ARRAY_T]]** [[ARRAY]] // CHECK-LP64-NEXT: [[ZERO:%.*]] = bitcast [[ARRAY_T]]** [[ARRAY]] to i8** @@ -66,8 +71,12 @@ void test0(NSArray *array) { // CHECK-LP64-NEXT: store i8* [[T1]], i8** [[T0]] // CHECK-LP64-NEXT: [[BLOCK1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] // CHECK-LP64-NEXT: call void @use_block(void ()* [[BLOCK1]]) -// CHECK-LP64-NEXT: [[CAPTURE:%.*]] = load i8*, i8** [[D0]] -// CHECK-LP64: call void (...) @clang.arc.use(i8* [[CAPTURE]]) +// CHECK-LP64-NEXT: call void @objc_storeStrong(i8** [[D0]], i8* null) +// CHECK-LP64-NOT: call void (...) @clang.arc.use(i8* [[CAPTURE]]) + +// CHECK-LP64-OPT: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i64 0, i32 5 +// CHECK-LP64-OPT: [[CAPTURE:%.*]] = load i8*, i8** [[D0]] +// CHECK-LP64-OPT: call void (...) @clang.arc.use(i8* [[CAPTURE]]) // CHECK-LP64: [[T0:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ // CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[SAVED_ARRAY]] to i8* @@ -200,15 +209,24 @@ NSArray *array4; // CHECK-LP64: [[T0:%.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>* [[BLOCK]], i32 0, i32 5 // CHECK-LP64: [[BC:%.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>* [[BLOCK]], i32 0, i32 5 // CHECK-LP64: [[T1:%.*]] = load [[TY]]*, [[TY]]** [[SELF_ADDR]] -// CHECK-LP64: store [[TY]]* [[T1]], [[TY]]** [[BC]] +// CHECK-LP64: store [[TY]]* [[T1]], [[TY]]** [[BC]], align 8 -// CHECK-LP64: [[T5:%.*]] = load [[TY]]*, [[TY]]** [[T0]] -// CHECK-LP64: call void (...) @clang.arc.use([[TY]]* [[T5]]) +// CHECK-LP64-OPT-LABEL: define internal void @"\01-[I1 foo2]"( +// CHECK-LP64-OPT: [[TY:%.*]]* %self +// CHECK-LP64-OPT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], +// CHECK-LP64-OPT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i64 0, i32 5 + +// CHECK-LP64: [[T5:%.*]] = bitcast [[TY]]** [[T0]] to i8** +// CHECK-LP64: call void @objc_storeStrong(i8** [[T5]], i8* null) +// CHECK-LP64-NOT: call void (...) @clang.arc.use([[TY]]* [[T5]]) // CHECK-LP64: switch i32 {{%.*}}, label %[[UNREACHABLE:.*]] [ // CHECK-LP64-NEXT: i32 0, label %[[CLEANUP_CONT:.*]] // CHECK-LP64-NEXT: i32 2, label %[[FORCOLL_END:.*]] // CHECK-LP64-NEXT: ] +// CHECK-LP64-OPT: [[T5:%.*]] = load [[TY]]*, [[TY]]** [[T0]] +// CHECK-LP64-OPT: call void (...) @clang.arc.use([[TY]]* [[T5]]) + // CHECK-LP64: {{^|:}}[[CLEANUP_CONT]] // CHECK-LP64-NEXT: br label %[[FORCOLL_END]] diff --git a/test/CodeGenOpenCL/kernel-attributes.cl b/test/CodeGenOpenCL/kernel-attributes.cl index 4a116dd08551..e61a75f7b537 100644 --- a/test/CodeGenOpenCL/kernel-attributes.cl +++ b/test/CodeGenOpenCL/kernel-attributes.cl @@ -8,7 +8,11 @@ kernel __attribute__((vec_type_hint(int))) __attribute__((reqd_work_group_size( kernel __attribute__((vec_type_hint(uint4))) __attribute__((work_group_size_hint(8,16,32))) void kernel2(int a) {} // CHECK: define void @kernel2(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD3:[0-9]+]] !work_group_size_hint ![[MD4:[0-9]+]] +kernel __attribute__((intel_reqd_sub_group_size(8))) void kernel3(int a) {} +// CHECK: define void @kernel3(i32 {{[^%]*}}%a) {{[^{]+}} !intel_reqd_sub_group_size ![[MD5:[0-9]+]] + // CHECK: [[MD1]] = !{i32 undef, i32 1} // CHECK: [[MD2]] = !{i32 1, i32 2, i32 4} // CHECK: [[MD3]] = !{<4 x i32> undef, i32 0} // CHECK: [[MD4]] = !{i32 8, i32 16, i32 32} +// CHECK: [[MD5]] = !{i32 8} diff --git a/test/Driver/android-ndk-standalone.cpp b/test/Driver/android-ndk-standalone.cpp index 7fe6d3c3c2ca..86ab85269f76 100644 --- a/test/Driver/android-ndk-standalone.cpp +++ b/test/Driver/android-ndk-standalone.cpp @@ -172,6 +172,20 @@ // CHECK-ARMV7THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a" // CHECK-ARMV7THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib" // CHECK-ARMV7THUMB: "-L{{.*}}/sysroot/usr/lib" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target arm-linux-androideabi -stdlib=libstdc++ \ +// RUN: -march=armv7-a -mthumb \ +// RUN: -B%S/Inputs/basic_android_ndk_tree \ +// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \ +// RUN: -print-multi-lib \ +// RUN: | FileCheck --check-prefix=CHECK-ARM-MULTILIBS %s + +// CHECK-ARM-MULTILIBS: thumb;@mthumb +// CHECK-ARM-MULTILIBS-NEXT: armv7-a;@march=armv7-a +// CHECK-ARM-MULTILIBS-NEXT: armv7-a/thumb;@march=armv7-a@mthumb +// CHECK-ARM-MULTILIBS-NEXT: .; + // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target armv7a-none-linux-androideabi -stdlib=libstdc++ \ diff --git a/test/Driver/darwin-version.c b/test/Driver/darwin-version.c index 009f8483a000..8f08bb9dec4a 100644 --- a/test/Driver/darwin-version.c +++ b/test/Driver/darwin-version.c @@ -29,9 +29,13 @@ // 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: FileCheck --check-prefix=CHECK-VERSION-OSX10 %s +// RUN: %clang -target x86_64-apple-macosx -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: FileCheck --check-prefix=CHECK-VERSION-MISSING %s +// RUN: %clang -target x86_64-apple-macosx -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 | \ // RUN: FileCheck --check-prefix=CHECK-VERSION-WATCHOS20 %s diff --git a/test/Driver/fsanitize-coverage.c b/test/Driver/fsanitize-coverage.c index 22c26be99b69..cf0941477bba 100644 --- a/test/Driver/fsanitize-coverage.c +++ b/test/Driver/fsanitize-coverage.c @@ -80,6 +80,10 @@ // CHECK-EXTEND-LEGACY: -fsanitize-coverage-type=1 // CHECK-EXTEND-LEGACY: -fsanitize-coverage-trace-cmp +// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=no-prune,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_NOPRUNE +// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=no-prune,func,trace-pc-guard %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_NOPRUNE +// CHECK_NOPRUNE: -fsanitize-coverage-no-prune + // RUN: %clang_cl --target=i386-pc-win32 -fsanitize=address -fsanitize-coverage=func,trace-pc-guard -c -### -- %s 2>&1 | FileCheck %s -check-prefix=CLANG-CL-COVERAGE // CLANG-CL-COVERAGE-NOT: error: // CLANG-CL-COVERAGE-NOT: warning: diff --git a/test/Driver/windows-cross.c b/test/Driver/windows-cross.c index de6fcba7a504..90fefbadfea1 100644 --- a/test/Driver/windows-cross.c +++ b/test/Driver/windows-cross.c @@ -1,12 +1,17 @@ -// RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -stdlib=libstdc++ -rtlib=platform -o /dev/null %s 2>&1 \ -// RUN: | FileCheck %s --check-prefix CHECK-BASIC +// RUN: %clang -### --driver-mode=g++ -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -stdlib=libstdc++ -rtlib=platform -o /dev/null %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix CHECK-BASIC-LIBSTDCXX -// CHECK-BASIC: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "-L{{.*}}/Inputs/Windows/ARM/8.1/usr/lib" "-L{{.*}}/Inputs/Windows/ARM/8.1/usr/lib/gcc" "{{.*}}.o" "-lmsvcrt" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" +// CHECK-BASIC-LIBSTDCXX: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "-L{{.*}}/Inputs/Windows/ARM/8.1/usr/lib" "-L{{.*}}/Inputs/Windows/ARM/8.1/usr/lib/gcc" "{{.*}}.o" "-lstdc++" "-lmingw32" "-lmingwex" "-lgcc" "-lmoldname" "-lmingw32" "-lmsvcrt" "-lgcc_s" "-lgcc" + +// RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -stdlib=libstdc++ -rtlib=compiler-rt -o /dev/null %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix CHECK-BASIC-LIBCXX + +// CHECK-BASIC-LIBCXX: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{[^"]*}}.o" "-lmsvcrt" // RUN: %clang -### -target armv7-windows-itanium --sysroot %s/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -rtlib=compiler-rt -stdlib=libstdc++ -o /dev/null %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-RTLIB -// CHECK-RTLIB: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "-L{{.*}}/Inputs/Windows/ARM/8.1/usr/lib" "-L{{.*}}/Inputs/Windows/ARM/8.1/usr/lib/gcc" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" +// CHECK-RTLIB: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" // RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -rtlib=compiler-rt -stdlib=libc++ -o /dev/null %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-C-LIBCXX diff --git a/test/FixIt/fixit-availability.c b/test/FixIt/fixit-availability.c new file mode 100644 index 000000000000..fa641b4b98c6 --- /dev/null +++ b/test/FixIt/fixit-availability.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunguarded-availability -fdiagnostics-parseable-fixits -triple x86_64-apple-darwin9 %s 2>&1 | FileCheck %s + +__attribute__((availability(macos, introduced=10.12))) +int function(void); + +void use() { + function(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (__builtin_available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:14-[[@LINE-2]]:14}:"\n } else {\n // Fallback on earlier versions\n }" +} diff --git a/test/FixIt/fixit-availability.mm b/test/FixIt/fixit-availability.mm new file mode 100644 index 000000000000..6bf8f49ddc0d --- /dev/null +++ b/test/FixIt/fixit-availability.mm @@ -0,0 +1,111 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunguarded-availability -fdiagnostics-parseable-fixits -triple x86_64-apple-darwin9 %s 2>&1 | FileCheck %s + +__attribute__((availability(macos, introduced=10.12))) +int function(void); + +void anotherFunction(int function); + +int use() { + function(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:14-[[@LINE-2]]:14}:"\n } else {\n // Fallback on earlier versions\n }" + int y = function(), x = 0; +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:29-[[@LINE-2]]:29}:"\n } else {\n // Fallback on earlier versions\n }" + x += function(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:19-[[@LINE-2]]:19}:"\n } else {\n // Fallback on earlier versions\n }" + if (1) { + x = function(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:20-[[@LINE-2]]:20}:"\n } else {\n // Fallback on earlier versions\n }" + } + anotherFunction(function()); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:31-[[@LINE-2]]:31}:"\n } else {\n // Fallback on earlier versions\n }" + if (function()) { +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE+1]]:4-[[@LINE+1]]:4}:"\n } else {\n // Fallback on earlier versions\n }" + } + while (function()) + // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " + // CHECK-NEXT: fix-it:{{.*}}:{[[@LINE+1]]:6-[[@LINE+1]]:6}:"\n } else {\n // Fallback on earlier versions\n }" + ; + do + function(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:"\n } else {\n // Fallback on earlier versions\n }" + while (1); + for (int i = 0; i < 10; ++i) + function(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:"\n } else {\n // Fallback on earlier versions\n }" + switch (x) { + case 0: + function(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:"\n } else {\n // Fallback on earlier versions\n }" + case 2: + anotherFunction(1); + function(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:"\n } else {\n // Fallback on earlier versions\n }" + break; + default: + function(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:"\n } else {\n // Fallback on earlier versions\n }" + break; + } + return function(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:21-[[@LINE-2]]:21}:"\n } else {\n // Fallback on earlier versions\n }" +} + +#define MYFUNCTION function + +#define MACRO_ARGUMENT(X) X +#define MACRO_ARGUMENT_SEMI(X) X; +#define MACRO_ARGUMENT_2(X) if (1) X; + +#define INNER_MACRO if (1) MACRO_ARGUMENT(function()); else ; + +void useInMacros() { + MYFUNCTION(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:"\n } else {\n // Fallback on earlier versions\n }" + + MACRO_ARGUMENT_SEMI(function()) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:34-[[@LINE-2]]:34}:"\n } else {\n // Fallback on earlier versions\n }" + MACRO_ARGUMENT(function()); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:30-[[@LINE-2]]:30}:"\n } else {\n // Fallback on earlier versions\n }" + MACRO_ARGUMENT_2(function()); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:32-[[@LINE-2]]:32}:"\n } else {\n // Fallback on earlier versions\n }" + + INNER_MACRO +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:14-[[@LINE-2]]:14}:"\n } else {\n // Fallback on earlier versions\n }" +} + +void wrapDeclStmtUses() { + int x = 0, y = function(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE+13]]:22-[[@LINE+13]]:22}:"\n } else {\n // Fallback on earlier versions\n }" + { + int z = function(); + if (z) { + + } +// CHECK: fix-it:{{.*}}:{[[@LINE-4]]:5-[[@LINE-4]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:6-[[@LINE-2]]:6}:"\n } else {\n // Fallback on earlier versions\n }" + } + if (y) + int z = function(); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"if (@available(macos 10.12, *)) {\n " +// CHECK-NEXT: fix-it:{{.*}}:{[[@LINE-2]]:24-[[@LINE-2]]:24}:"\n } else {\n // Fallback on earlier versions\n }" + anotherFunction(y); + anotherFunction(x); +} diff --git a/test/Index/Core/index-source.cpp b/test/Index/Core/index-source.cpp index 7bb366c53611..6f902610e673 100644 --- a/test/Index/Core/index-source.cpp +++ b/test/Index/Core/index-source.cpp @@ -139,13 +139,13 @@ class PseudoOverridesInSpecializations { template<> class PseudoOverridesInSpecializations<double, int> { void function() { } -// CHECK: [[@LINE-1]]:8 | instance-method/C++ | function | c:@S@PseudoOverridesInSpecializations>#d#I@F@function# | __ZN32PseudoOverridesInSpecializationsIdiE8functionEv | Def,RelChild,RelOver,RelSpecialization | rel: 2 +// CHECK: [[@LINE-1]]:8 | instance-method/C++ | function | c:@S@PseudoOverridesInSpecializations>#d#I@F@function# | __ZN32PseudoOverridesInSpecializationsIdiE8functionEv | Def,RelChild,RelSpecialization | rel: 2 // CHECK-NEXT: RelChild -// CHECK-NEXT: RelOver,RelSpecialization | function | c:@ST>2#T#T@PseudoOverridesInSpecializations@F@function# +// CHECK-NEXT: RelSpecialization | function | c:@ST>2#T#T@PseudoOverridesInSpecializations@F@function# void staticFunction() { } // CHECK: [[@LINE-1]]:8 | instance-method/C++ | staticFunction | c:@S@PseudoOverridesInSpecializations>#d#I@F@staticFunction# | __ZN32PseudoOverridesInSpecializationsIdiE14staticFunctionEv | Def,RelChild | rel: 1 -// CHECK-NOT: RelOver +// CHECK-NOT: RelSpecialization int notOverridingField = 0; @@ -153,57 +153,56 @@ class PseudoOverridesInSpecializations<double, int> { int checLabelBreak = 0; int field = 0; -// CHECK: [[@LINE-1]]:7 | field/C++ | field | c:@S@PseudoOverridesInSpecializations>#d#I@FI@field | <no-cgname> | Def,RelChild,RelOver,RelSpecialization | rel: 2 +// CHECK: [[@LINE-1]]:7 | field/C++ | field | c:@S@PseudoOverridesInSpecializations>#d#I@FI@field | <no-cgname> | Def,RelChild,RelSpecialization | rel: 2 // CHECK-NEXT: RelChild -// CHECK-NEXT: RelOver,RelSpecialization | field | c:@ST>2#T#T@PseudoOverridesInSpecializations@FI@field +// CHECK-NEXT: RelSpecialization | field | c:@ST>2#T#T@PseudoOverridesInSpecializations@FI@field static double variable; -// CHECK: [[@LINE-1]]:17 | static-property/C++ | variable | c:@S@PseudoOverridesInSpecializations>#d#I@variable | __ZN32PseudoOverridesInSpecializationsIdiE8variableE | Decl,RelChild,RelOver,RelSpecialization | rel: 2 +// CHECK: [[@LINE-1]]:17 | static-property/C++ | variable | c:@S@PseudoOverridesInSpecializations>#d#I@variable | __ZN32PseudoOverridesInSpecializationsIdiE8variableE | Decl,RelChild,RelSpecialization | rel: 2 // CHECK-NEXT: RelChild -// CHECK-NEXT: RelOver,RelSpecialization | variable | c:@ST>2#T#T@PseudoOverridesInSpecializations@variable +// CHECK-NEXT: RelSpecialization | variable | c:@ST>2#T#T@PseudoOverridesInSpecializations@variable typedef double TypeDef; -// CHECK: [[@LINE-1]]:18 | type-alias/C | TypeDef | c:index-source.cpp@S@PseudoOverridesInSpecializations>#d#I@T@TypeDef | <no-cgname> | Def,RelChild,RelOver,RelSpecialization | rel: 2 +// CHECK: [[@LINE-1]]:18 | type-alias/C | TypeDef | c:index-source.cpp@S@PseudoOverridesInSpecializations>#d#I@T@TypeDef | <no-cgname> | Def,RelChild,RelSpecialization | rel: 2 // CHECK-NEXT: RelChild -// CHECK-NEXT: RelOver,RelSpecialization | TypeDef | c:index-source.cpp@ST>2#T#T@PseudoOverridesInSpecializations@T@TypeDef +// CHECK-NEXT: RelSpecialization | TypeDef | c:index-source.cpp@ST>2#T#T@PseudoOverridesInSpecializations@T@TypeDef using TypeAlias = int; -// CHECK: [[@LINE-1]]:9 | type-alias/C++ | TypeAlias | c:@S@PseudoOverridesInSpecializations>#d#I@TypeAlias | <no-cgname> | Def,RelChild,RelOver,RelSpecialization | rel: 2 +// CHECK: [[@LINE-1]]:9 | type-alias/C++ | TypeAlias | c:@S@PseudoOverridesInSpecializations>#d#I@TypeAlias | <no-cgname> | Def,RelChild,RelSpecialization | rel: 2 // CHECK-NEXT: RelChild -// CHECK-NEXT: RelOver,RelSpecialization | TypeAlias | c:@ST>2#T#T@PseudoOverridesInSpecializations@TypeAlias +// CHECK-NEXT: RelSpecialization | TypeAlias | c:@ST>2#T#T@PseudoOverridesInSpecializations@TypeAlias enum anEnum { }; -// CHECK: [[@LINE-1]]:8 | enum/C | anEnum | c:@S@PseudoOverridesInSpecializations>#d#I@E@anEnum | <no-cgname> | Def,RelChild,RelOver,RelSpecialization | rel: 2 +// CHECK: [[@LINE-1]]:8 | enum/C | anEnum | c:@S@PseudoOverridesInSpecializations>#d#I@E@anEnum | <no-cgname> | Def,RelChild,RelSpecialization | rel: 2 // CHECK-NEXT: RelChild -// CHECK-NEXT: RelOver,RelSpecialization | anEnum | c:@ST>2#T#T@PseudoOverridesInSpecializations@E@anEnum +// CHECK-NEXT: RelSpecialization | anEnum | c:@ST>2#T#T@PseudoOverridesInSpecializations@E@anEnum class Struct { }; -// CHECK: [[@LINE-1]]:9 | class/C++ | Struct | c:@S@PseudoOverridesInSpecializations>#d#I@S@Struct | <no-cgname> | Def,RelChild,RelOver,RelSpecialization | rel: 2 +// CHECK: [[@LINE-1]]:9 | class/C++ | Struct | c:@S@PseudoOverridesInSpecializations>#d#I@S@Struct | <no-cgname> | Def,RelChild,RelSpecialization | rel: 2 // CHECK-NEXT: RelChild -// CHECK-NEXT: RelOver,RelSpecialization | Struct | c:@ST>2#T#T@PseudoOverridesInSpecializations@S@Struct +// CHECK-NEXT: RelSpecialization | Struct | c:@ST>2#T#T@PseudoOverridesInSpecializations@S@Struct union Union { }; -// CHECK: [[@LINE-1]]:9 | union/C | Union | c:@S@PseudoOverridesInSpecializations>#d#I@U@Union | <no-cgname> | Def,RelChild,RelOver,RelSpecialization | rel: 2 +// CHECK: [[@LINE-1]]:9 | union/C | Union | c:@S@PseudoOverridesInSpecializations>#d#I@U@Union | <no-cgname> | Def,RelChild,RelSpecialization | rel: 2 // CHECK-NEXT: RelChild -// CHECK-NEXT: RelOver,RelSpecialization | Union | c:@ST>2#T#T@PseudoOverridesInSpecializations@U@Union +// CHECK-NEXT: RelSpecialization | Union | c:@ST>2#T#T@PseudoOverridesInSpecializations@U@Union struct TypealiasOrRecord { }; -// CHECK: [[@LINE-1]]:10 | struct/C | TypealiasOrRecord | c:@S@PseudoOverridesInSpecializations>#d#I@S@TypealiasOrRecord | <no-cgname> | Def,RelChild,RelOver,RelSpecialization | rel: 2 +// CHECK: [[@LINE-1]]:10 | struct/C | TypealiasOrRecord | c:@S@PseudoOverridesInSpecializations>#d#I@S@TypealiasOrRecord | <no-cgname> | Def,RelChild,RelSpecialization | rel: 2 // CHECK-NEXT: RelChild -// CHECK-NEXT: RelOver,RelSpecialization | TypealiasOrRecord | c:@ST>2#T#T@PseudoOverridesInSpecializations@TypealiasOrRecord +// CHECK-NEXT: RelSpecialization | TypealiasOrRecord | c:@ST>2#T#T@PseudoOverridesInSpecializations@TypealiasOrRecord template<typename U> struct InnerTemplate { }; -// CHECK: [[@LINE-1]]:31 | struct(Gen)/C++ | InnerTemplate | c:@S@PseudoOverridesInSpecializations>#d#I@ST>1#T@InnerTemplate | <no-cgname> | Def,RelChild,RelOver,RelSpecialization | rel: 2 +// CHECK: [[@LINE-1]]:31 | struct(Gen)/C++ | InnerTemplate | c:@S@PseudoOverridesInSpecializations>#d#I@ST>1#T@InnerTemplate | <no-cgname> | Def,RelChild,RelSpecialization | rel: 2 // CHECK-NEXT: RelChild -// CHECK-NEXT: RelOver,RelSpecialization | InnerTemplate | c:@ST>2#T#T@PseudoOverridesInSpecializations@ST>1#T@InnerTemplate +// CHECK-NEXT: RelSpecialization | InnerTemplate | c:@ST>2#T#T@PseudoOverridesInSpecializations@ST>1#T@InnerTemplate template<typename U> struct InnerTemplate <U*> { }; -// CHECK-NOT: RelOver }; template<typename S> class PseudoOverridesInSpecializations<float, S> { typedef float TypealiasOrRecord; -// CHECK: [[@LINE-1]]:17 | type-alias/C | TypealiasOrRecord | c:index-source.cpp@SP>1#T@PseudoOverridesInSpecializations>#f#t0.0@T@TypealiasOrRecord | <no-cgname> | Def,RelChild,RelOver,RelSpecialization | rel: 2 +// CHECK: [[@LINE-1]]:17 | type-alias/C | TypealiasOrRecord | c:index-source.cpp@SP>1#T@PseudoOverridesInSpecializations>#f#t0.0@T@TypealiasOrRecord | <no-cgname> | Def,RelChild,RelSpecialization | rel: 2 // CHECK-NEXT: RelChild -// CHECK-NEXT: RelOver,RelSpecialization | TypealiasOrRecord | c:@ST>2#T#T@PseudoOverridesInSpecializations@TypealiasOrRecord +// CHECK-NEXT: RelSpecialization | TypealiasOrRecord | c:@ST>2#T#T@PseudoOverridesInSpecializations@TypealiasOrRecord }; template<typename T, typename U> @@ -215,10 +214,10 @@ class ConflictingPseudoOverridesInSpecialization { template<typename T> class ConflictingPseudoOverridesInSpecialization<int, T> { void foo(T x); -// CHECK: [[@LINE-1]]:8 | instance-method/C++ | foo | c:@SP>1#T@ConflictingPseudoOverridesInSpecialization>#I#t0.0@F@foo#S0_# | <no-cgname> | Decl,RelChild,RelOver,RelSpecialization | rel: 3 +// CHECK: [[@LINE-1]]:8 | instance-method/C++ | foo | c:@SP>1#T@ConflictingPseudoOverridesInSpecialization>#I#t0.0@F@foo#S0_# | <no-cgname> | Decl,RelChild,RelSpecialization | rel: 3 // CHECK-NEXT: RelChild -// CHECK-NEXT: RelOver,RelSpecialization | foo | c:@ST>2#T#T@ConflictingPseudoOverridesInSpecialization@F@foo#t0.0# -// CHECK-NEXT: RelOver,RelSpecialization | foo | c:@ST>2#T#T@ConflictingPseudoOverridesInSpecialization@F@foo#t0.1# +// CHECK-NEXT: RelSpecialization | foo | c:@ST>2#T#T@ConflictingPseudoOverridesInSpecialization@F@foo#t0.0# +// CHECK-NEXT: RelSpecialization | foo | c:@ST>2#T#T@ConflictingPseudoOverridesInSpecialization@F@foo#t0.1# }; template<typename T, typename U, int x> diff --git a/test/Index/KeepGoingWithLotsOfErrors.mm b/test/Index/KeepGoingWithLotsOfErrors.mm new file mode 100644 index 000000000000..078ea6e2ea14 --- /dev/null +++ b/test/Index/KeepGoingWithLotsOfErrors.mm @@ -0,0 +1,29 @@ +// RUN: env CINDEXTEST_KEEP_GOING=1 c-index-test -code-completion-at=%s:25:1 %s +// Shouldn't crash! +// This is the minimized test that triggered an infinite recursion: + ++(BOOL) onEntity { +} + +-(const Object &) a_200 { +} + +-(int) struct { +} + +-(int) bar { +} + +-(int) part { +} + ++(some_type_t) piece { +} + ++(void) z_Z_42 { + ([self onEntity: [] { 42]; + } class: ^ { } +]; + [super]; + BOOL struct; +} diff --git a/test/Misc/pragma-attribute-supported-attributes-list.test b/test/Misc/pragma-attribute-supported-attributes-list.test index f6a7ce2869ac..0db17bdf4026 100644 --- a/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/test/Misc/pragma-attribute-supported-attributes-list.test @@ -2,7 +2,7 @@ // The number of supported attributes should never go down! -// CHECK: #pragma clang attribute supports 59 attributes: +// CHECK: #pragma clang attribute supports 60 attributes: // CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function) @@ -42,6 +42,7 @@ // CHECK-NEXT: ObjCRuntimeName (SubjectMatchRule_objc_interface, SubjectMatchRule_objc_protocol) // CHECK-NEXT: ObjCRuntimeVisible (SubjectMatchRule_objc_interface) // CHECK-NEXT: ObjCSubclassingRestricted (SubjectMatchRule_objc_interface) +// CHECK-NEXT: OpenCLIntelReqdSubGroupSize (SubjectMatchRule_function) // CHECK-NEXT: OpenCLNoSVM (SubjectMatchRule_variable) // CHECK-NEXT: OptimizeNone (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: Overloadable (SubjectMatchRule_function) diff --git a/test/Modules/Inputs/preprocess/file2.h b/test/Modules/Inputs/preprocess/file2.h new file mode 100644 index 000000000000..04bf796d1e9e --- /dev/null +++ b/test/Modules/Inputs/preprocess/file2.h @@ -0,0 +1,2 @@ +#include "file.h" +extern int file2; diff --git a/test/Modules/Inputs/preprocess/module.modulemap b/test/Modules/Inputs/preprocess/module.modulemap index a5c5b61dddc5..943435a953d0 100644 --- a/test/Modules/Inputs/preprocess/module.modulemap +++ b/test/Modules/Inputs/preprocess/module.modulemap @@ -1,2 +1,2 @@ module fwd { header "fwd.h" export * } -module file { header "file.h" export * } +module file { header "file.h" header "file2.h" export * } diff --git a/test/Modules/preprocess-module.cpp b/test/Modules/preprocess-module.cpp index 99fe8cf8c30b..a3b789238388 100644 --- a/test/Modules/preprocess-module.cpp +++ b/test/Modules/preprocess-module.cpp @@ -1,12 +1,101 @@ // RUN: rm -rf %t +// RUN: mkdir %t // RUN: not %clang_cc1 -fmodules -fmodule-name=file -I%S/Inputs/preprocess -x c++-module-map %S/Inputs/preprocess/module.modulemap -E 2>&1 | FileCheck %s --check-prefix=MISSING-FWD // MISSING-FWD: module 'fwd' is needed -// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodules-cache-path=%t -I%S/Inputs/preprocess -x c++-module-map %S/Inputs/preprocess/module.modulemap -E | FileCheck %s +// RUN: %clang_cc1 -fmodules -fmodule-name=fwd -I%S/Inputs/preprocess -x c++-module-map %S/Inputs/preprocess/module.modulemap -emit-module -o %t/fwd.pcm + +// Check that we can preprocess modules, and get the expected output. +// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -I%S/Inputs/preprocess -x c++-module-map %S/Inputs/preprocess/module.modulemap -E -o %t/no-rewrite.ii +// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -I%S/Inputs/preprocess -x c++-module-map %S/Inputs/preprocess/module.modulemap -E -frewrite-includes -o %t/rewrite.ii +// +// RUN: FileCheck %s --input-file %t/no-rewrite.ii --check-prefix=CHECK --check-prefix=NO-REWRITE +// RUN: FileCheck %s --input-file %t/rewrite.ii --check-prefix=CHECK --check-prefix=REWRITE + +// Check that we can build a module from the preprocessed output. +// FIXME: For now, we need the headers to exist. +// RUN: touch %t/file.h %t/file2.h +// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/no-rewrite.ii -emit-module -o %t/no-rewrite.pcm +// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/rewrite.ii -emit-module -o %t/rewrite.pcm + +// Check the module we built works. +// RUN: %clang_cc1 -fmodules -fmodule-file=%t/no-rewrite.pcm %s -verify +// RUN: %clang_cc1 -fmodules -fmodule-file=%t/rewrite.pcm %s -verify + + +// == module map +// CHECK: # 1 "{{.*}}module.modulemap" +// CHECK: module file { +// CHECK: header "file.h" +// CHECK: header "file2.h" +// CHECK: } + +// == file.h // CHECK: # 1 "<module-includes>" +// REWRITE: #if 0 +// REWRITE: #include "file.h" +// REWRITE: #endif +// +// FIXME: It would be preferable to consistently put the module begin/end in +// the same file, but the relative ordering of PP callbacks and module +// begin/end tokens makes that difficult. +// +// REWRITE: #pragma clang module begin file // CHECK: # 1 "{{.*}}file.h" 1 +// NO-REWRITE: #pragma clang module begin file +// NO-REWRITE: # 1 "{{.*}}file.h"{{$}} +// // CHECK: struct __FILE; -// CHECK: #pragma clang module import fwd /* clang -E: implicit import for #include "fwd.h" */ +// CHECK: #pragma clang module import fwd /* clang {{-E|-frewrite-includes}}: implicit import // CHECK: typedef struct __FILE FILE; +// +// REWRITE: #pragma clang module end // CHECK: # 2 "<module-includes>" 2 +// NO-REWRITE: #pragma clang module end + +// == file2.h +// REWRITE: #if 0 +// REWRITE: #include "file2.h" +// REWRITE: #endif +// +// REWRITE: #pragma clang module begin file +// CHECK: # 1 "{{.*}}file2.h" 1 +// NO-REWRITE: #pragma clang module begin file +// +// ==== recursively re-enter file.h +// REWRITE: #if 0 +// REWRITE: #include "file.h" +// REWRITE: #endif +// +// REWRITE: #pragma clang module begin file +// CHECK: # 1 "{{.*}}file.h" 1 +// NO-REWRITE: #pragma clang module begin file +// NO-REWRITE: # 1 "{{.*}}file.h"{{$}} +// +// CHECK: struct __FILE; +// CHECK: #pragma clang module import fwd /* clang {{-E|-frewrite-includes}}: implicit import +// CHECK: typedef struct __FILE FILE; +// +// REWRITE: #pragma clang module end +// CHECK: # 2 "{{.*}}file2.h" 2 +// NO-REWRITE: #pragma clang module end +// NO-REWRITE: # 2 "{{.*}}file2.h"{{$}} +// ==== return to file2.h +// +// CHECK: extern int file2; +// +// REWRITE: #pragma clang module end +// CHECK: # 3 "<module-includes>" 2 +// NO-REWRITE: #pragma clang module end + + +// expected-no-diagnostics + +// FIXME: This should be rejected: we have not imported the submodule defining it yet. +__FILE *a; + +#pragma clang module import file + +FILE *b; +int x = file2; diff --git a/test/OpenMP/varargs.cpp b/test/OpenMP/varargs.cpp new file mode 100644 index 000000000000..7738f83fab24 --- /dev/null +++ b/test/OpenMP/varargs.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -verify -fopenmp %s +void f(int a, ...) { +#pragma omp parallel for + for (int i = 0; i < 100; ++i) { + __builtin_va_list ap; + __builtin_va_start(ap, a); // expected-error {{'va_start' cannot be used in a captured statement}} + } +}; diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp index 830412ed474f..74f4bb3268de 100644 --- a/test/Parser/MicrosoftExtensions.cpp +++ b/test/Parser/MicrosoftExtensions.cpp @@ -60,7 +60,7 @@ struct struct_without_uuid { }; struct __declspec(uuid("000000A0-0000-0000-C000-000000000049")) struct_with_uuid2; -[uuid("000000A0-0000-0000-C000-000000000049")] struct struct_with_uuid3; +[uuid("000000A0-0000-0000-C000-000000000049")] struct struct_with_uuid3; // expected-warning{{specifying 'uuid' as an ATL attribute is deprecated; use __declspec instead}} struct struct_with_uuid2 {} ; diff --git a/test/Parser/ms-square-bracket-attributes.mm b/test/Parser/ms-square-bracket-attributes.mm index 98b2f6c2d3ea..a158cf7b2b90 100644 --- a/test/Parser/ms-square-bracket-attributes.mm +++ b/test/Parser/ms-square-bracket-attributes.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify -fms-extensions %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify -fms-extensions %s -Wno-deprecated-declarations typedef struct _GUID { unsigned long Data1; diff --git a/test/Preprocessor/aarch64-target-features.c b/test/Preprocessor/aarch64-target-features.c index c9c7f2dc4a4e..43a050b14c06 100644 --- a/test/Preprocessor/aarch64-target-features.c +++ b/test/Preprocessor/aarch64-target-features.c @@ -109,7 +109,7 @@ // CHECK-MCPU-THUNDERX2T99: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" // RUN: %clang -target x86_64-apple-macosx -arch arm64 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64 %s -// CHECK-ARCH-ARM64: "-target-cpu" "cyclone" "-target-feature" "+neon" "-target-feature" "+crypto" "-target-feature" "+zcm" "-target-feature" "+zcz" +// CHECK-ARCH-ARM64: "-target-cpu" "cyclone" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+crypto" "-target-feature" "+zcm" "-target-feature" "+zcz" // RUN: %clang -target aarch64 -march=armv8-a+fp+simd+crc+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-1 %s // RUN: %clang -target aarch64 -march=armv8-a+nofp+nosimd+nocrc+nocrypto+fp+simd+crc+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-1 %s diff --git a/test/Preprocessor/macro_paste_commaext.c b/test/Preprocessor/macro_paste_commaext.c index fdb8f982a929..60418effe7c3 100644 --- a/test/Preprocessor/macro_paste_commaext.c +++ b/test/Preprocessor/macro_paste_commaext.c @@ -1,13 +1,20 @@ -// RUN: %clang_cc1 %s -E | grep 'V);' -// RUN: %clang_cc1 %s -E | grep 'W, 1, 2);' -// RUN: %clang_cc1 %s -E | grep 'X, 1, 2);' -// RUN: %clang_cc1 %s -E | grep 'Y,);' -// RUN: %clang_cc1 %s -E | grep 'Z,);' +// RUN: %clang_cc1 %s -E | FileCheck --strict-whitespace --match-full-lines %s + +// In the following tests, note that the output is sensitive to the +// whitespace *preceeding* the varargs argument, as well as to +// interior whitespace. AFAIK, this is the only case where whitespace +// preceeding an argument matters, and might be considered a bug in +// GCC. Nevertheless, since this feature is a GCC extension in the +// first place, we'll follow along. #define debug(format, ...) format, ## __VA_ARGS__) +// CHECK:V); debug(V); -debug(W, 1, 2); +// CHECK:W,1, 2); +debug(W,1, 2); +// CHECK:X, 1, 2); debug(X, 1, 2 ); +// CHECK:Y,); debug(Y, ); +// CHECK:Z,); debug(Z,); - diff --git a/test/Preprocessor/pragma_module.c b/test/Preprocessor/pragma_module.c index d734f66efcef..90aa9481fb13 100644 --- a/test/Preprocessor/pragma_module.c +++ b/test/Preprocessor/pragma_module.c @@ -1,11 +1,52 @@ -// RUN: %clang -cc1 -E -fmodules %s -verify +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: echo 'module foo { module a {} module b {} } module bar {} module if {}' > %t/module.map +// RUN: %clang -cc1 -fmodules -fmodule-name=if -x c %t/module.map -emit-module -o %t/if.pcm +// RUN: %clang -cc1 -E -fmodules %s -fmodule-file=%t/if.pcm -verify -fmodule-name=foo -fmodule-map-file=%t/module.map +// RUN: %clang -cc1 -E -fmodules %s -fmodule-file=%t/if.pcm -verify -fmodule-name=foo -fmodule-map-file=%t/module.map -fmodules-local-submodule-visibility -DLOCAL_VIS // Just checking the syntax here; the semantics are tested elsewhere. -#pragma clang module import // expected-error {{expected identifier in module name}} -#pragma clang module import ! // expected-error {{expected identifier in module name}} -#pragma clang module import if // expected-error {{expected identifier in module name}} -#pragma clang module import foo ? bar // expected-error {{expected '.' or end of directive after module name}} -#pragma clang module import foo. // expected-error {{expected identifier}} -#pragma clang module import foo.bar.baz.quux // expected-error {{module 'foo' not found}} - -#error here // expected-error {{here}} +#pragma clang module import // expected-error {{expected module name}} +#pragma clang module import ! // expected-error {{expected module name}} +#pragma clang module import if // ok +#pragma clang module import foo ? bar // expected-warning {{extra tokens at end of #pragma}} +#pragma clang module import foo. // expected-error {{expected identifier after '.' in module name}} +#pragma clang module import foo.bar.baz.quux // expected-error {{no submodule named 'bar' in module 'foo'}} + +#pragma clang module begin ! // expected-error {{expected module name}} + +#pragma clang module begin foo.a blah // expected-warning {{extra tokens}} + #pragma clang module begin foo.a // nesting is OK + #define X 1 // expected-note 0-1{{previous}} + #ifndef X + #error X should be defined here + #endif + #pragma clang module end + + #ifndef X + #error X should still be defined + #endif +#pragma clang module end foo.a // expected-warning {{extra tokens}} + +// #pragma clang module begin/end also import the module into the enclosing context +#ifndef X +#error X should still be defined +#endif + +#pragma clang module begin foo.b + #if defined(X) && defined(LOCAL_VIS) + #error under -fmodules-local-submodule-visibility, X should not be defined + #endif + + #if !defined(X) && !defined(LOCAL_VIS) + #error without -fmodules-local-submodule-visibility, X should still be defined + #endif + + #pragma clang module import foo.a + #ifndef X + #error X should be defined here + #endif +#pragma clang module end + +#pragma clang module end // expected-error {{no matching '#pragma clang module begin'}} +#pragma clang module begin foo.a // expected-error {{no matching '#pragma clang module end'}} diff --git a/test/Preprocessor/stringize_space.c b/test/Preprocessor/stringize_space.c index ae70bf18187c..cbc7386cd09b 100644 --- a/test/Preprocessor/stringize_space.c +++ b/test/Preprocessor/stringize_space.c @@ -18,3 +18,14 @@ f( 1) // CHECK: {{^}}"-1" + +#define paste(a,b) str(a<b##ld) +paste(hello1, wor) +paste(hello2, + wor) +paste(hello3, +wor) + +// CHECK: {{^}}"hello1<world" +// CHECK: {{^}}"hello2<world" +// CHECK: {{^}}"hello3<world" diff --git a/test/Sema/arm-interrupt-attr.c b/test/Sema/arm-interrupt-attr.c index 3a6cdbe0e072..60691ab7f8e8 100644 --- a/test/Sema/arm-interrupt-attr.c +++ b/test/Sema/arm-interrupt-attr.c @@ -1,7 +1,8 @@ -// RUN: %clang_cc1 %s -triple arm-apple-darwin -verify -fsyntax-only -// RUN: %clang_cc1 %s -triple thumb-apple-darwin -verify -fsyntax-only -// RUN: %clang_cc1 %s -triple armeb-none-eabi -verify -fsyntax-only -// RUN: %clang_cc1 %s -triple thumbeb-none-eabi -verify -fsyntax-only +// RUN: %clang_cc1 %s -triple arm-apple-darwin -target-feature +vfp2 -verify -fsyntax-only +// RUN: %clang_cc1 %s -triple thumb-apple-darwin -target-feature +vfp3 -verify -fsyntax-only +// RUN: %clang_cc1 %s -triple armeb-none-eabi -target-feature +vfp4 -verify -fsyntax-only +// RUN: %clang_cc1 %s -triple thumbeb-none-eabi -target-feature +neon -verify -fsyntax-only +// RUN: %clang_cc1 %s -triple thumbeb-none-eabi -target-feature +neon -target-feature +soft-float -DSOFT -verify -fsyntax-only __attribute__((interrupt(IRQ))) void foo() {} // expected-error {{'interrupt' attribute requires a string}} __attribute__((interrupt("irq"))) void foo1() {} // expected-warning {{'interrupt' attribute argument not supported: irq}} @@ -24,6 +25,8 @@ void caller1() { callee1(); callee2(); } + +#ifndef SOFT __attribute__((interrupt("IRQ"))) void caller2() { callee1(); // expected-warning {{call to function without interrupt attribute could clobber interruptee's VFP registers}} callee2(); @@ -33,3 +36,14 @@ void (*callee3)(); __attribute__((interrupt("IRQ"))) void caller3() { callee3(); // expected-warning {{call to function without interrupt attribute could clobber interruptee's VFP registers}} } +#else +__attribute__((interrupt("IRQ"))) void caller2() { + callee1(); + callee2(); +} + +void (*callee3)(); +__attribute__((interrupt("IRQ"))) void caller3() { + callee3(); +} +#endif diff --git a/test/Sema/attr-availability.c b/test/Sema/attr-availability.c index c4133e3b9bc6..e105037c8ed0 100644 --- a/test/Sema/attr-availability.c +++ b/test/Sema/attr-availability.c @@ -30,7 +30,7 @@ void test_10095131() { ATSFontGetPostScriptName(100); // expected-error {{'ATSFontGetPostScriptName' is unavailable: obsoleted in macOS 9.0 - use ATSFontGetFullPostScriptName}} #if defined(WARN_PARTIAL) - // expected-warning@+2 {{is only available on macOS 10.8 or newer}} expected-note@+2 {{enclose 'PartiallyAvailable' in an @available check to silence this warning}} + // expected-warning@+2 {{is only available on macOS 10.8 or newer}} expected-note@+2 {{enclose 'PartiallyAvailable' in a __builtin_available check to silence this warning}} #endif PartiallyAvailable(); } diff --git a/test/SemaCXX/ms-uuid.cpp b/test/SemaCXX/ms-uuid.cpp index 461e3c12ff8a..e29dda878e68 100644 --- a/test/SemaCXX/ms-uuid.cpp +++ b/test/SemaCXX/ms-uuid.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -Wno-deprecated-declarations typedef struct _GUID { unsigned long Data1; diff --git a/test/SemaCXX/varargs.cpp b/test/SemaCXX/varargs.cpp index 6a1883786a33..f9027c247993 100644 --- a/test/SemaCXX/varargs.cpp +++ b/test/SemaCXX/varargs.cpp @@ -1,12 +1,59 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++03 -verify %s +// RUN: %clang_cc1 -std=c++03 -verify %s +// RUN: %clang_cc1 -std=c++11 -verify %s + +__builtin_va_list ap; class string; void f(const string& s, ...) { // expected-note {{parameter of type 'const string &' is declared here}} - __builtin_va_list ap; __builtin_va_start(ap, s); // expected-warning {{passing an object of reference type to 'va_start' has undefined behavior}} } void g(register int i, ...) { - __builtin_va_list ap; - __builtin_va_start(ap, i); // okay + __builtin_va_start(ap, i); // UB in C, OK in C++ +} + +// Don't crash when there is no last parameter. +void no_params(...) { + int a; + __builtin_va_start(ap, a); // expected-warning {{second argument to 'va_start' is not the last named parameter}} +} + +// Reject this. The __builtin_va_start would execute in Foo's non-variadic +// default ctor. +void record_context(int a, ...) { + struct Foo { + // expected-error@+1 {{'va_start' cannot be used outside a function}} + void meth(int a, int b = (__builtin_va_start(ap, a), 0)) {} + }; +} + +#if __cplusplus >= 201103L +// We used to have bugs identifying the correct enclosing function scope in a +// lambda. + +void fixed_lambda_varargs_function(int a, ...) { + [](int b) { + __builtin_va_start(ap, b); // expected-error {{'va_start' used in function with fixed args}} + }(42); +} +void varargs_lambda_fixed_function(int a) { + [](int b, ...) { + __builtin_va_start(ap, b); // correct + }(42); +} + +auto fixed_lambda_global = [](int f) { + __builtin_va_start(ap, f); // expected-error {{'va_start' used in function with fixed args}} +}; +auto varargs_lambda_global = [](int f, ...) { + __builtin_va_start(ap, f); // correct +}; + +void record_member_init(int a, ...) { + struct Foo { + int a = 0; + // expected-error@+1 {{'va_start' cannot be used outside a function}} + int b = (__builtin_va_start(ap, a), 0); + }; } +#endif diff --git a/test/SemaCXX/warn-zero-nullptr.cpp b/test/SemaCXX/warn-zero-nullptr.cpp new file mode 100644 index 000000000000..edd2a759b70f --- /dev/null +++ b/test/SemaCXX/warn-zero-nullptr.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -Wzero-as-null-pointer-constant -std=c++11 + +struct S {}; + +int (S::*mp0) = nullptr; +void (*fp0)() = nullptr; +void* p0 = nullptr; + +int (S::*mp1) = 0; // expected-warning{{zero as null pointer constant}} +void (*fp1)() = 0; // expected-warning{{zero as null pointer constant}} +void* p1 = 0; // expected-warning{{zero as null pointer constant}} + +// NULL is an integer constant expression, so warn on it too: +void* p2 = __null; // expected-warning{{zero as null pointer constant}} +void (*fp2)() = __null; // expected-warning{{zero as null pointer constant}} +int (S::*mp2) = __null; // expected-warning{{zero as null pointer constant}} + +void f0(void* v = 0); // expected-warning{{zero as null pointer constant}} +void f1(void* v); + +void g() { + f1(0); // expected-warning{{zero as null pointer constant}} +} + +// Warn on these too. Matches gcc and arguably makes sense. +void* pp = (decltype(nullptr))0; // expected-warning{{zero as null pointer constant}} +void* pp2 = static_cast<decltype(nullptr)>(0); // expected-warning{{zero as null pointer constant}} diff --git a/test/SemaObjC/x86-method-vector-values.m b/test/SemaObjC/x86-method-vector-values.m index 6c5189d08427..23d07b1b41fa 100644 --- a/test/SemaObjC/x86-method-vector-values.m +++ b/test/SemaObjC/x86-method-vector-values.m @@ -68,6 +68,8 @@ struct AggregateFloat { float v; }; #else +// expected-no-diagnostics + -(void)takeVector:(float3)v { } @@ -84,15 +86,9 @@ struct AggregateFloat { float v; }; } -(void)takeVector2:(float3)v AVAILABLE_MACOS_10_10 { -#ifdef MAC -// expected-error@-2 {{'float3' (vector of 3 'float' values) parameter type is unsupported}} -#endif } - (__m128)retM128_2 AVAILABLE_MACOS_10_10 { -#ifdef MAC -// expected-error@-2 {{'__m128' (vector of 4 'float' values) return type is unsupported}} -#endif __m128 value; return value; } @@ -101,9 +97,6 @@ struct AggregateFloat { float v; }; } -(void)takeVector4:(float3)v AVAILABLE_IOS_8 { -#ifdef IOS - // expected-error@-2 {{'float3' (vector of 3 'float' values) parameter type is unsupported}} -#endif } -(void)takeVector5:(float3)v AVAILABLE_IOS_9 { // no error diff --git a/test/SemaOpenCL/invalid-kernel-attrs.cl b/test/SemaOpenCL/invalid-kernel-attrs.cl index cedbb0664675..1f1359cceead 100644 --- a/test/SemaOpenCL/invalid-kernel-attrs.cl +++ b/test/SemaOpenCL/invalid-kernel-attrs.cl @@ -33,3 +33,7 @@ void f_kernel_image2d_t( kernel image2d_t image ) { // expected-error {{'kernel' kernel __attribute__((reqd_work_group_size(1,2,0))) void kernel11(){} // expected-error {{'reqd_work_group_size' attribute must be greater than 0}} kernel __attribute__((reqd_work_group_size(1,0,2))) void kernel12(){} // expected-error {{'reqd_work_group_size' attribute must be greater than 0}} kernel __attribute__((reqd_work_group_size(0,1,2))) void kernel13(){} // expected-error {{'reqd_work_group_size' attribute must be greater than 0}} + +__attribute__((intel_reqd_sub_group_size(8))) void kernel14(){} // expected-error {{attribute 'intel_reqd_sub_group_size' can only be applied to a kernel}} +kernel __attribute__((intel_reqd_sub_group_size(0))) void kernel15(){} // expected-error {{'intel_reqd_sub_group_size' attribute must be greater than 0}} +kernel __attribute__((intel_reqd_sub_group_size(8))) __attribute__((intel_reqd_sub_group_size(16))) void kernel16() {} //expected-warning{{attribute 'intel_reqd_sub_group_size' is already applied with different parameters}} diff --git a/test/SemaOpenCL/sampler_t.cl b/test/SemaOpenCL/sampler_t.cl index 0dddeeb39013..4d68dd20a17e 100644 --- a/test/SemaOpenCL/sampler_t.cl +++ b/test/SemaOpenCL/sampler_t.cl @@ -9,7 +9,8 @@ constant sampler_t glb_smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR; constant sampler_t glb_smp2; // expected-error{{variable in constant address space must be initialized}} -global sampler_t glb_smp3 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_NEAREST; // expected-error{{sampler type cannot be used with the __local and __global address space qualifiers}} +global sampler_t glb_smp3 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_NEAREST; // expected-error{{sampler type cannot be used with the __local and __global address space qualifiers}} expected-error {{global sampler requires a const or constant address space qualifier}} +const global sampler_t glb_smp3_const = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR; // expected-error{{sampler type cannot be used with the __local and __global address space qualifiers}} constant sampler_t glb_smp4 = 0; #ifdef CHECK_SAMPLER_VALUE @@ -38,6 +39,11 @@ constant struct sampler_s { sampler_t bad(void); //expected-error{{declaring function return value of type 'sampler_t' is not allowed}} +sampler_t global_nonconst_smp = 0; // expected-error {{global sampler requires a const or constant address space qualifier}} + +const sampler_t glb_smp10 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR; +const constant sampler_t glb_smp11 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR; + void kernel ker(sampler_t argsmp) { local sampler_t smp; // expected-error{{sampler type cannot be used with the __local and __global address space qualifiers}} const sampler_t const_smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR; diff --git a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 5c29334222df..dfaa441cd764 100644 --- a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -1020,6 +1020,29 @@ TEST(InitListExpression, MatchesInitListExpression) { matches("int i[1] = {42, [0] = 43};", integerLiteral(equals(42)))); } +TEST(CXXStdInitializerListExpression, MatchesCXXStdInitializerListExpression) { + const std::string code = "namespace std {" + "template <typename> class initializer_list {" + " public: initializer_list() noexcept {}" + "};" + "}" + "struct A {" + " A(std::initializer_list<int>) {}" + "};"; + EXPECT_TRUE(matches(code + "A a{0};", + cxxConstructExpr(has(cxxStdInitializerListExpr()), + hasDeclaration(cxxConstructorDecl( + ofClass(hasName("A"))))))); + EXPECT_TRUE(matches(code + "A a = {0};", + cxxConstructExpr(has(cxxStdInitializerListExpr()), + hasDeclaration(cxxConstructorDecl( + ofClass(hasName("A"))))))); + + EXPECT_TRUE(notMatches("int a[] = { 1, 2 };", cxxStdInitializerListExpr())); + EXPECT_TRUE(notMatches("struct B { int x, y; }; B b = { 5, 6 };", + cxxStdInitializerListExpr())); +} + TEST(UsingDeclaration, MatchesUsingDeclarations) { EXPECT_TRUE(matches("namespace X { int x; } using X::x;", usingDecl())); diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp index eda9e0a31da4..9144fe17e9ec 100644 --- a/unittests/Format/FormatTestJS.cpp +++ b/unittests/Format/FormatTestJS.cpp @@ -1786,5 +1786,11 @@ TEST_F(FormatTestJS, ImportComments) { getGoogleJSStyleWithColumns(25)); verifyFormat("// taze: x from 'location'", getGoogleJSStyleWithColumns(10)); } + +TEST_F(FormatTestJS, Exponentiation) { + verifyFormat("squared = x ** 2;"); + verifyFormat("squared **= 2;"); +} + } // end namespace tooling } // end namespace clang |