Vendor import of clang trunk r302418:
https://llvm.org/svn/llvm-project/cfe/trunk@302418
This commit is contained in:
parent
f0c0337bbf
commit
0a5fb09b59
docs
include/clang
AST
ASTMatchers
Basic
Attr.tdAttrDocs.tdBuiltinsARM.defBuiltinsX86.defBuiltinsX86_64.defDiagnosticLexKinds.tdDiagnosticSemaKinds.td
Driver
Frontend
Lex
Sema
Tooling
lib
ASTMatchers/Dynamic
Basic
CodeGen
Driver
Format
Frontend
Headers
Index
Lex
HeaderSearch.cppLexer.cppModuleMap.cppPPDirectives.cppPPLexerChange.cppPPMacroExpansion.cppPragma.cppPreprocessor.cppTokenLexer.cpp
Parse
Sema
Tooling
test
CodeGen
aarch64-args.cpparm_acle.clwp-builtins.cmozilla-ms-inline-asm.cms-inline-asm-64.cms-inline-asm-avx512.cms-inline-asm.cms-inline-asm.cppthinlto_backend.ll
CodeGenCXX
CodeGenObjC
CodeGenOpenCL
Driver
FixIt
Index
Misc
Modules
OpenMP
Parser
Preprocessor
@ -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
|
||||
|
@ -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 = ...
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
||||
|
@ -25,7 +25,7 @@ namespace clang {
|
||||
|
||||
class Decl;
|
||||
class IdentifierInfo;
|
||||
class NestedNameSpecifer;
|
||||
class NestedNameSpecifier;
|
||||
class Stmt;
|
||||
class TemplateParameterList;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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)";
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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<
|
||||
|
@ -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">;
|
||||
|
@ -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">;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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>;
|
||||
|
@ -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.
|
||||
|
@ -146,6 +146,8 @@ public:
|
||||
return *CurrentASTUnit;
|
||||
}
|
||||
|
||||
Module *getCurrentModule() const;
|
||||
|
||||
std::unique_ptr<ASTUnit> takeCurrentASTUnit() {
|
||||
return std::move(CurrentASTUnit);
|
||||
}
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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())
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -53,6 +53,8 @@ namespace format {
|
||||
TYPE(InlineASMColon) \
|
||||
TYPE(JavaAnnotation) \
|
||||
TYPE(JsComputedPropertyName) \
|
||||
TYPE(JsExponentiation) \
|
||||
TYPE(JsExponentiationEqual) \
|
||||
TYPE(JsFatArrow) \
|
||||
TYPE(JsNonNullAssertion) \
|
||||
TYPE(JsTypeColon) \
|
||||
|
@ -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) {
|
||||
|
@ -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 =
|
||||
|
@ -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();
|
||||
|
||||
// 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.
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// 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);
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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() &&
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -45,6 +45,7 @@ set(files
|
||||
inttypes.h
|
||||
iso646.h
|
||||
limits.h
|
||||
lwpintrin.h
|
||||
lzcntintrin.h
|
||||
mm3dnow.h
|
||||
mmintrin.h
|
||||
|
@ -224,6 +224,36 @@ __rbitl(unsigned long __t) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
@ -231,13 +261,13 @@ __rbitl(unsigned long __t) {
|
||||
* 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__))
|
||||
|
150
lib/Headers/lwpintrin.h
Normal file
150
lib/Headers/lwpintrin.h
Normal file
@ -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 */
|
@ -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
|
||||
|
@ -184,9 +184,7 @@ public:
|
||||
continue;
|
||||
}
|
||||
Relations.emplace_back(
|
||||
SymbolRoleSet(SymbolRole::RelationOverrideOf) |
|
||||
SymbolRoleSet(SymbolRole::RelationSpecializationOf),
|
||||
ND);
|
||||
SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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())
|
||||
const char *StrData = Buffer.data() + LocInfo.second;
|
||||
const char *LexStart = findBeginningOfLine(Buffer, LocInfo.second);
|
||||
if (!LexStart || LexStart == StrData)
|
||||
return Loc;
|
||||
|
||||
const char *StrData = BufStart+LocInfo.second;
|
||||
if (StrData[0] == '\n' || StrData[0] == '\r')
|
||||
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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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);
|
||||
|
@ -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?");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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?");
|
||||
|
@ -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());
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 ||
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
67
test/CodeGen/aarch64-args.cpp
Normal file
67
test/CodeGen/aarch64-args.cpp
Normal file
@ -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;
|
||||
}
|
@ -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
|
||||
|
39
test/CodeGen/lwp-builtins.c
Normal file
39
test/CodeGen/lwp-builtins.c
Normal file
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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* %{{.*}})
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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]] = {
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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]]
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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++ \
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
10
test/FixIt/fixit-availability.c
Normal file
10
test/FixIt/fixit-availability.c
Normal file
@ -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 }"
|
||||
}
|
111
test/FixIt/fixit-availability.mm
Normal file
111
test/FixIt/fixit-availability.mm
Normal file
@ -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);
|
||||
}
|
@ -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>
|
||||
|
29
test/Index/KeepGoingWithLotsOfErrors.mm
Normal file
29
test/Index/KeepGoingWithLotsOfErrors.mm
Normal file
@ -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;
|
||||
}
|
@ -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)
|
||||
|
2
test/Modules/Inputs/preprocess/file2.h
Normal file
2
test/Modules/Inputs/preprocess/file2.h
Normal file
@ -0,0 +1,2 @@
|
||||
#include "file.h"
|
||||
extern int file2;
|
@ -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 * }
|
||||
|
@ -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;
|
||||
|
8
test/OpenMP/varargs.cpp
Normal file
8
test/OpenMP/varargs.cpp
Normal file
@ -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}}
|
||||
}
|
||||
};
|
@ -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 {} ;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user