Vendor import of clang trunk r304149:

https://llvm.org/svn/llvm-project/cfe/trunk@304149
This commit is contained in:
Dimitry Andric 2017-05-29 16:25:46 +00:00
parent aa803409c3
commit b5aee35cc5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=319142
svn path=/vendor/clang/clang-trunk-r304149/; revision=319143; tag=vendor/clang/clang-trunk-r304149
251 changed files with 5069 additions and 1338 deletions

View File

@ -359,6 +359,10 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
PATTERN "*.inc"
PATTERN "*.h"
)
install(PROGRAMS utils/bash-autocomplete.sh
DESTINATION share/clang
)
endif()
add_definitions( -D_GNU_SOURCE )

View File

@ -1963,6 +1963,47 @@ def __repr__(self):
TypeKind.MEMBERPOINTER = TypeKind(117)
TypeKind.AUTO = TypeKind(118)
TypeKind.ELABORATED = TypeKind(119)
TypeKind.PIPE = TypeKind(120)
TypeKind.OCLIMAGE1DRO = TypeKind(121)
TypeKind.OCLIMAGE1DARRAYRO = TypeKind(122)
TypeKind.OCLIMAGE1DBUFFERRO = TypeKind(123)
TypeKind.OCLIMAGE2DRO = TypeKind(124)
TypeKind.OCLIMAGE2DARRAYRO = TypeKind(125)
TypeKind.OCLIMAGE2DDEPTHRO = TypeKind(126)
TypeKind.OCLIMAGE2DARRAYDEPTHRO = TypeKind(127)
TypeKind.OCLIMAGE2DMSAARO = TypeKind(128)
TypeKind.OCLIMAGE2DARRAYMSAARO = TypeKind(129)
TypeKind.OCLIMAGE2DMSAADEPTHRO = TypeKind(130)
TypeKind.OCLIMAGE2DARRAYMSAADEPTHRO = TypeKind(131)
TypeKind.OCLIMAGE3DRO = TypeKind(132)
TypeKind.OCLIMAGE1DWO = TypeKind(133)
TypeKind.OCLIMAGE1DARRAYWO = TypeKind(134)
TypeKind.OCLIMAGE1DBUFFERWO = TypeKind(135)
TypeKind.OCLIMAGE2DWO = TypeKind(136)
TypeKind.OCLIMAGE2DARRAYWO = TypeKind(137)
TypeKind.OCLIMAGE2DDEPTHWO = TypeKind(138)
TypeKind.OCLIMAGE2DARRAYDEPTHWO = TypeKind(139)
TypeKind.OCLIMAGE2DMSAAWO = TypeKind(140)
TypeKind.OCLIMAGE2DARRAYMSAAWO = TypeKind(141)
TypeKind.OCLIMAGE2DMSAADEPTHWO = TypeKind(142)
TypeKind.OCLIMAGE2DARRAYMSAADEPTHWO = TypeKind(143)
TypeKind.OCLIMAGE3DWO = TypeKind(144)
TypeKind.OCLIMAGE1DRW = TypeKind(145)
TypeKind.OCLIMAGE1DARRAYRW = TypeKind(146)
TypeKind.OCLIMAGE1DBUFFERRW = TypeKind(147)
TypeKind.OCLIMAGE2DRW = TypeKind(148)
TypeKind.OCLIMAGE2DARRAYRW = TypeKind(149)
TypeKind.OCLIMAGE2DDEPTHRW = TypeKind(150)
TypeKind.OCLIMAGE2DARRAYDEPTHRW = TypeKind(151)
TypeKind.OCLIMAGE2DMSAARW = TypeKind(152)
TypeKind.OCLIMAGE2DARRAYMSAARW = TypeKind(153)
TypeKind.OCLIMAGE2DMSAADEPTHRW = TypeKind(154)
TypeKind.OCLIMAGE2DARRAYMSAADEPTHRW = TypeKind(155)
TypeKind.OCLIMAGE3DRW = TypeKind(156)
TypeKind.OCLSAMPLER = TypeKind(157)
TypeKind.OCLEVENT = TypeKind(158)
TypeKind.OCLQUEUE = TypeKind(159)
TypeKind.OCLRESERVEID = TypeKind(160)
class RefQualifierKind(BaseEnumeration):
"""Describes a specific ref-qualifier of a type."""

View File

@ -0,0 +1,50 @@
set(LLVM_TARGETS_TO_BUILD ARM;X86 CACHE STRING "")
# Builtins
set(LLVM_BUILTIN_TARGETS "armv7m-none-eabi;armv6m-none-eabi;armv7em-none-eabi" CACHE STRING "Builtin Targets")
set(BUILTINS_armv6m-none-eabi_CMAKE_SYSROOT ${BAREMETAL_ARMV6M_SYSROOT} CACHE STRING "armv6m-none-eabi Sysroot")
set(BUILTINS_armv6m-none-eabi_CMAKE_SYSTEM_NAME Generic CACHE STRING "armv6m-none-eabi System Name")
set(BUILTINS_armv6m-none-eabi_COMPILER_RT_BAREMETAL_BUILD ON CACHE BOOL "armv6m-none-eabi Baremetal build")
set(BUILTINS_armv6m-none-eabi_COMPILER_RT_OS_DIR "baremetal" CACHE STRING "armv6m-none-eabi os dir")
set(BUILTINS_armv7m-none-eabi_CMAKE_SYSROOT ${BAREMETAL_ARMV7M_SYSROOT} CACHE STRING "armv7m-none-eabi Sysroot")
set(BUILTINS_armv7m-none-eabi_CMAKE_SYSTEM_NAME Generic CACHE STRING "armv7m-none-eabi System Name")
set(BUILTINS_armv7m-none-eabi_COMPILER_RT_BAREMETAL_BUILD ON CACHE BOOL "armv7m-none-eabi Baremetal build")
set(BUILTINS_armv7m-none-eabi_CMAKE_C_FLAGS "-mfpu=fp-armv8" CACHE STRING "armv7m-none-eabi C Flags")
set(BUILTINS_armv7m-none-eabi_CMAKE_ASM_FLAGS "-mfpu=fp-armv8" CACHE STRING "armv7m-none-eabi ASM Flags")
set(BUILTINS_armv7m-none-eabi_COMPILER_RT_OS_DIR "baremetal" CACHE STRING "armv7m-none-eabi os dir")
set(BUILTINS_armv7em-none-eabi_CMAKE_SYSROOT ${BAREMETAL_ARMV7EM_SYSROOT} CACHE STRING "armv7em-none-eabi Sysroot")
set(BUILTINS_armv7em-none-eabi_CMAKE_SYSTEM_NAME Generic CACHE STRING "armv7em-none-eabi System Name")
set(BUILTINS_armv7em-none-eabi_COMPILER_RT_BAREMETAL_BUILD ON CACHE BOOL "armv7em-none-eabi Baremetal build")
set(BUILTINS_armv7em-none-eabi_CMAKE_C_FLAGS "-mfpu=fp-armv8" CACHE STRING "armv7em-none-eabi C Flags")
set(BUILTINS_armv7em-none-eabi_CMAKE_ASM_FLAGS "-mfpu=fp-armv8" CACHE STRING "armv7em-none-eabi ASM Flags")
set(BUILTINS_armv7em-none-eabi_COMPILER_RT_OS_DIR "baremetal" CACHE STRING "armv7em-none-eabi os dir")
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
set(LLVM_TOOLCHAIN_TOOLS
llc
llvm-ar
llvm-cxxfilt
llvm-dwarfdump
llvm-dsymutil
llvm-nm
llvm-objdump
llvm-ranlib
llvm-readobj
llvm-size
llvm-symbolizer
opt
CACHE STRING "")
set(LLVM_DISTRIBUTION_COMPONENTS
clang
lld
clang-headers
builtins-armv6m-none-eabi
builtins-armv7m-none-eabi
builtins-armv7em-none-eabi
runtimes
${LLVM_TOOLCHAIN_TOOLS}
CACHE STRING "")

View File

@ -413,6 +413,9 @@ altivec
blocks
The "blocks" language feature is available.
coroutines
Support for the coroutines TS is available.
cplusplus
C++ support is available.

View File

@ -32,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
#define CINDEX_VERSION_MINOR 39
#define CINDEX_VERSION_MINOR 40
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@ -3076,7 +3076,52 @@ enum CXTypeKind {
*
* E.g., struct S, or via a qualified name, e.g., N::M::type, or both.
*/
CXType_Elaborated = 119
CXType_Elaborated = 119,
/* OpenCL PipeType. */
CXType_Pipe = 120,
/* OpenCL builtin types. */
CXType_OCLImage1dRO = 121,
CXType_OCLImage1dArrayRO = 122,
CXType_OCLImage1dBufferRO = 123,
CXType_OCLImage2dRO = 124,
CXType_OCLImage2dArrayRO = 125,
CXType_OCLImage2dDepthRO = 126,
CXType_OCLImage2dArrayDepthRO = 127,
CXType_OCLImage2dMSAARO = 128,
CXType_OCLImage2dArrayMSAARO = 129,
CXType_OCLImage2dMSAADepthRO = 130,
CXType_OCLImage2dArrayMSAADepthRO = 131,
CXType_OCLImage3dRO = 132,
CXType_OCLImage1dWO = 133,
CXType_OCLImage1dArrayWO = 134,
CXType_OCLImage1dBufferWO = 135,
CXType_OCLImage2dWO = 136,
CXType_OCLImage2dArrayWO = 137,
CXType_OCLImage2dDepthWO = 138,
CXType_OCLImage2dArrayDepthWO = 139,
CXType_OCLImage2dMSAAWO = 140,
CXType_OCLImage2dArrayMSAAWO = 141,
CXType_OCLImage2dMSAADepthWO = 142,
CXType_OCLImage2dArrayMSAADepthWO = 143,
CXType_OCLImage3dWO = 144,
CXType_OCLImage1dRW = 145,
CXType_OCLImage1dArrayRW = 146,
CXType_OCLImage1dBufferRW = 147,
CXType_OCLImage2dRW = 148,
CXType_OCLImage2dArrayRW = 149,
CXType_OCLImage2dDepthRW = 150,
CXType_OCLImage2dArrayDepthRW = 151,
CXType_OCLImage2dMSAARW = 152,
CXType_OCLImage2dArrayMSAARW = 153,
CXType_OCLImage2dMSAADepthRW = 154,
CXType_OCLImage2dArrayMSAADepthRW = 155,
CXType_OCLImage3dRW = 156,
CXType_OCLSampler = 157,
CXType_OCLEvent = 158,
CXType_OCLQueue = 159,
CXType_OCLReserveID = 160
};
/**

View File

@ -4284,6 +4284,9 @@ class DesignatedInitExpr final
}
Designator *getDesignator(unsigned Idx) { return &designators()[Idx]; }
const Designator *getDesignator(unsigned Idx) const {
return &designators()[Idx];
}
void setDesignators(const ASTContext &C, const Designator *Desigs,
unsigned NumDesigs);

View File

@ -308,7 +308,9 @@ class CoroutineBodyStmt final
OnFallthrough, ///< Handler for control flow falling off the body.
Allocate, ///< Coroutine frame memory allocation.
Deallocate, ///< Coroutine frame memory deallocation.
ReturnValue, ///< Return value for thunk function.
ReturnValue, ///< Return value for thunk function: p.get_return_object().
ResultDecl, ///< Declaration holding the result of get_return_object.
ReturnStmt, ///< Return statement for the thunk function.
ReturnStmtOnAllocFailure, ///< Return statement if allocation failed.
FirstParamMove ///< First offset for move construction of parameter copies.
};
@ -332,7 +334,9 @@ class CoroutineBodyStmt final
Stmt *OnFallthrough = nullptr;
Expr *Allocate = nullptr;
Expr *Deallocate = nullptr;
Stmt *ReturnValue = nullptr;
Expr *ReturnValue = nullptr;
Stmt *ResultDecl = nullptr;
Stmt *ReturnStmt = nullptr;
Stmt *ReturnStmtOnAllocFailure = nullptr;
ArrayRef<Stmt *> ParamMoves;
};
@ -381,10 +385,11 @@ class CoroutineBodyStmt final
Expr *getDeallocate() const {
return cast_or_null<Expr>(getStoredStmts()[SubStmt::Deallocate]);
}
Expr *getReturnValueInit() const {
return cast_or_null<Expr>(getStoredStmts()[SubStmt::ReturnValue]);
return cast<Expr>(getStoredStmts()[SubStmt::ReturnValue]);
}
Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; }
Stmt *getReturnStmt() const { return getStoredStmts()[SubStmt::ReturnStmt]; }
Stmt *getReturnStmtOnAllocFailure() const {
return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure];
}

View File

@ -149,6 +149,9 @@ class ExprArgument<string name, bit opt = 0> : Argument<name, opt>;
class FunctionArgument<string name, bit opt = 0, bit fake = 0> : Argument<name,
opt,
fake>;
class NamedArgument<string name, bit opt = 0, bit fake = 0> : Argument<name,
opt,
fake>;
class TypeArgument<string name, bit opt = 0> : Argument<name, opt>;
class UnsignedArgument<string name, bit opt = 0> : Argument<name, opt>;
class VariadicUnsignedArgument<string name> : Argument<name, 1>;
@ -1819,14 +1822,14 @@ def Unavailable : InheritableAttr {
def DiagnoseIf : InheritableAttr {
let Spellings = [GNU<"diagnose_if">];
let Subjects = SubjectList<[Function]>;
let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty]>;
let Args = [ExprArgument<"Cond">, StringArgument<"Message">,
EnumArgument<"DiagnosticType",
"DiagnosticType",
["error", "warning"],
["DT_Error", "DT_Warning"]>,
BoolArgument<"ArgDependent", 0, /*fake*/ 1>,
FunctionArgument<"Parent", 0, /*fake*/ 1>];
NamedArgument<"Parent", 0, /*fake*/ 1>];
let DuplicatesAllowedWhileMerging = 1;
let LateParsed = 1;
let AdditionalMembers = [{

View File

@ -36,6 +36,7 @@ BUILTIN(__builtin_amdgcn_workitem_id_z, "Ui", "nc")
// Instruction builtins.
//===----------------------------------------------------------------------===//
BUILTIN(__builtin_amdgcn_s_getreg, "UiIi", "n")
BUILTIN(__builtin_amdgcn_s_getpc, "LUi", "n")
BUILTIN(__builtin_amdgcn_s_waitcnt, "vIi", "n")
BUILTIN(__builtin_amdgcn_s_sendmsg, "vIiUi", "n")
BUILTIN(__builtin_amdgcn_s_sendmsghalt, "vIiUi", "n")

View File

@ -420,6 +420,9 @@ BUILTIN(__builtin_vsx_xvtstdcsp, "V4UiV4fIi", "")
BUILTIN(__builtin_vsx_insertword, "V16UcV4UiV16UcIi", "")
BUILTIN(__builtin_vsx_extractuword, "V2ULLiV16UcIi", "")
BUILTIN(__builtin_vsx_xxpermdi, "v.", "t")
BUILTIN(__builtin_vsx_xxsldwi, "v.", "t")
// HTM builtins
BUILTIN(__builtin_tbegin, "UiUIi", "")
BUILTIN(__builtin_tend, "UiUIi", "")

View File

@ -1107,6 +1107,9 @@ TARGET_BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "", "avx5
TARGET_BUILTIN(__builtin_ia32_vplzcntd_512_mask, "V16iV16iV16iUs", "", "avx512cd")
TARGET_BUILTIN(__builtin_ia32_vplzcntq_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512cd")
TARGET_BUILTIN(__builtin_ia32_vpopcntd_512, "V16iV16i", "", "avx512vpopcntdq")
TARGET_BUILTIN(__builtin_ia32_vpopcntq_512, "V8LLiV8LLi", "", "avx512vpopcntdq")
TARGET_BUILTIN(__builtin_ia32_vpermi2varhi128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
TARGET_BUILTIN(__builtin_ia32_vpermi2varhi256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
TARGET_BUILTIN(__builtin_ia32_vpermt2varhi128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")

View File

@ -87,6 +87,8 @@ VALUE_DIAGOPT(TemplateBacktraceLimit, 32, DefaultTemplateBacktraceLimit)
VALUE_DIAGOPT(ConstexprBacktraceLimit, 32, DefaultConstexprBacktraceLimit)
/// Limit number of times to perform spell checking.
VALUE_DIAGOPT(SpellCheckingLimit, 32, DefaultSpellCheckingLimit)
/// Limit number of lines shown in a snippet.
VALUE_DIAGOPT(SnippetLineLimit, 32, DefaultSnippetLineLimit)
VALUE_DIAGOPT(TabStop, 32, DefaultTabStop) /// The distance between tab stops.
/// Column limit for formatting message diagnostics, or 0 if unused.

View File

@ -63,11 +63,15 @@ class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{
enum TextDiagnosticFormat { Clang, MSVC, Vi };
// Default values.
enum { DefaultTabStop = 8, MaxTabStop = 100,
enum {
DefaultTabStop = 8,
MaxTabStop = 100,
DefaultMacroBacktraceLimit = 6,
DefaultTemplateBacktraceLimit = 10,
DefaultConstexprBacktraceLimit = 10,
DefaultSpellCheckingLimit = 50 };
DefaultSpellCheckingLimit = 50,
DefaultSnippetLineLimit = 1,
};
// Define simple diagnostic options (with no accessors).
#define DIAGOPT(Name, Bits, Default) unsigned Name : Bits;

View File

@ -537,10 +537,10 @@ def err_maybe_falloff_nonvoid_block : Error<
def err_falloff_nonvoid_block : Error<
"control reaches end of non-void block">;
def warn_maybe_falloff_nonvoid_coroutine : Warning<
"control may reach end of non-void coroutine">,
"control may reach end of coroutine; which is undefined behavior because the promise type %0 does not declare 'return_void()'">,
InGroup<ReturnType>;
def warn_falloff_nonvoid_coroutine : Warning<
"control reaches end of non-void coroutine">,
"control reaches end of coroutine; which is undefined behavior because the promise type %0 does not declare 'return_void()'">,
InGroup<ReturnType>;
def warn_suggest_noreturn_function : Warning<
"%select{function|method}0 %1 could be declared with attribute 'noreturn'">,
@ -1554,11 +1554,9 @@ def note_ivar_decl : Note<"instance variable is declared here">;
def note_bitfield_decl : Note<"bit-field is declared here">;
def note_implicit_param_decl : Note<"%0 is an implicit parameter">;
def note_member_synthesized_at : Note<
"implicit %select{default constructor|copy constructor|move constructor|copy "
"assignment operator|move assignment operator|destructor}0 for %1 first "
"required here">;
def note_inhctor_synthesized_at : Note<
"inherited constructor for %0 first required here">;
"in implicit %select{default constructor|copy constructor|move constructor|"
"copy assignment operator|move assignment operator|destructor}0 for %1 "
"first required here">;
def err_missing_default_ctor : Error<
"%select{constructor for %1 must explicitly initialize the|"
"implicit default constructor for %1 must explicitly initialize the|"
@ -2769,6 +2767,7 @@ def warn_attribute_wrong_decl_type : Warning<
"|types and namespaces"
"|Objective-C interfaces"
"|methods and properties"
"|functions, methods, and properties"
"|struct or union"
"|struct, union or class"
"|types"
@ -2883,6 +2882,10 @@ def warn_partial_message : Warning<"%0 is partial: %1">,
def warn_partial_fwdclass_message : Warning<
"%0 may be partial because the receiver type is unknown">,
InGroup<UnguardedAvailability>, DefaultIgnore;
def warn_at_available_unchecked_use : Warning<
"%select{@available|__builtin_available}0 does not guard availability here; "
"use if (%select{@available|__builtin_available}0) instead">,
InGroup<DiagGroup<"unsupported-availability-guard">>;
// Thread Safety Attributes
def warn_invalid_capability_name : Warning<
@ -6298,6 +6301,8 @@ def warn_ambiguous_suitable_delete_function_found : Warning<
InGroup<DiagGroup<"ambiguous-delete">>;
def note_member_declared_here : Note<
"member %0 declared here">;
def note_member_first_declared_here : Note<
"member %0 first declared here">;
def err_decrement_bool : Error<"cannot decrement expression of type bool">;
def warn_increment_bool : Warning<
"incrementing expression of type bool is deprecated and "
@ -8009,10 +8014,13 @@ def err_block_on_nonlocal : Error<
def err_block_on_vm : Error<
"__block attribute not allowed on declaration with a variably modified type">;
def err_shufflevector_non_vector : Error<
"first two arguments to __builtin_shufflevector must be vectors">;
def err_shufflevector_incompatible_vector : Error<
"first two arguments to __builtin_shufflevector must have the same type">;
def err_vec_builtin_non_vector : Error<
"first two arguments to %0 must be vectors">;
def err_vec_builtin_incompatible_vector : Error<
"first two arguments to %0 must have the same type">;
def err_vsx_builtin_nonconstant_argument : Error<
"argument %0 to %1 must be a 2-bit unsigned literal (i.e. 0, 1, 2 or 3)">;
def err_shufflevector_nonconstant_argument : Error<
"index for __builtin_shufflevector must be a constant integer">;
def err_shufflevector_argument_too_large : Error<
@ -8899,8 +8907,6 @@ def note_equivalent_internal_linkage_decl : Note<
def note_redefinition_modules_same_file : Note<
"'%0' included multiple times, additional include site in header from module '%1'">;
def note_redefinition_modules_same_file_modulemap : Note<
"consider adding '%0' as part of '%1' definition">;
def note_redefinition_include_same_file : Note<
"'%0' included multiple times, additional include site here">;
}
@ -8944,8 +8950,10 @@ def err_coroutine_promise_type_incomplete : Error<
def err_coroutine_type_missing_specialization : Error<
"this function cannot be a coroutine: missing definition of "
"specialization %q0">;
def err_coroutine_promise_return_ill_formed : Error<
"%0 declares both 'return_value' and 'return_void'">;
def err_coroutine_promise_incompatible_return_functions : Error<
"the coroutine promise type %0 declares both 'return_value' and 'return_void'">;
def err_coroutine_promise_requires_return_function : Error<
"the coroutine promise type %0 must declare either 'return_value' or 'return_void'">;
def note_coroutine_promise_implicit_await_transform_required_here : Note<
"call to 'await_transform' implicitly required by 'co_await' here">;
def note_coroutine_promise_suspend_implicitly_required : Note<
@ -8958,11 +8966,19 @@ def warn_coroutine_promise_unhandled_exception_required_with_exceptions : Warnin
InGroup<CoroutineMissingUnhandledException>;
def err_coroutine_promise_get_return_object_on_allocation_failure : Error<
"%0: 'get_return_object_on_allocation_failure()' must be a static member function">;
def err_seh_in_a_coroutine_with_cxx_exceptions : Error<
"cannot use SEH '__try' in a coroutine when C++ exceptions are enabled">;
def err_coroutine_promise_new_requires_nothrow : Error<
"%0 is required to have a non-throwing noexcept specification when the promise "
"type declares 'get_return_object_on_allocation_failure()'">;
def note_coroutine_promise_call_implicitly_required : Note<
"call to %0 implicitly required by coroutine function here">;
def err_await_suspend_invalid_return_type : Error<
"the return type of 'await_suspend' is required to be 'void' or 'bool' (have %0)"
>;
def note_await_ready_no_bool_conversion : Note<
"the return type of 'await_ready' is required to be contextually convertible to 'bool'"
>;
}
let CategoryName = "Documentation Issue" in {

View File

@ -1399,10 +1399,9 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// specified by Loc.
///
/// If FilenameID is -1, it is considered to be unspecified.
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID);
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID,
bool IsFileEntry, bool IsFileExit,
bool IsSystemHeader, bool IsExternCHeader);
SrcMgr::CharacteristicKind FileKind);
/// \brief Determine if the source manager has a line table.
bool hasLineTable() const { return LineTable != nullptr; }

View File

@ -101,8 +101,6 @@ class LineTableInfo {
}
unsigned getNumFilenames() const { return FilenamesByID.size(); }
void AddLineNote(FileID FID, unsigned Offset,
unsigned LineNo, int FilenameID);
void AddLineNote(FileID FID, unsigned Offset,
unsigned LineNo, int FilenameID,
unsigned EntryExit, SrcMgr::CharacteristicKind FileKind);

View File

@ -26,13 +26,21 @@ enum TemplateNameKind {
TNK_Function_template,
/// The name refers to a template whose specialization produces a
/// type. The template itself could be a class template, template
/// template parameter, or C++0x template alias.
/// template parameter, or template alias.
TNK_Type_template,
/// The name refers to a variable template whose specialization produces a
/// variable.
TNK_Var_template,
/// The name refers to a dependent template name. Whether the
/// template name is assumed to refer to a type template or a
/// The name refers to a dependent template name:
/// \code
/// template<typename MetaFun, typename T1, typename T2> struct apply2 {
/// typedef typename MetaFun::template apply<T1, T2>::type type;
/// };
/// \endcode
///
/// Here, "apply" is a dependent template name within the typename
/// specifier in the typedef. "apply" is a nested template, and
/// whether the template name is assumed to refer to a type template or a
/// function template depends on the context in which the template
/// name occurs.
TNK_Dependent_template_name

View File

@ -37,6 +37,7 @@ class XRayFunctionFilter {
NONE,
ALWAYS,
NEVER,
ALWAYS_ARG1,
};
ImbueAttribute shouldImbueFunction(StringRef FunctionName) const;

View File

@ -172,6 +172,8 @@ def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">,
def disable_lifetimemarkers : Flag<["-"], "disable-lifetime-markers">,
HelpText<"Disable lifetime-markers emission even when optimizations are "
"enabled">;
def disable_O0_optnone : Flag<["-"], "disable-O0-optnone">,
HelpText<"Disable adding the optnone attribute to functions at O0">;
def disable_red_zone : Flag<["-"], "disable-red-zone">,
HelpText<"Do not emit code that uses the red zone.">;
def dwarf_column_info : Flag<["-"], "dwarf-column-info">,
@ -359,6 +361,9 @@ def fconstexpr_backtrace_limit : Separate<["-"], "fconstexpr-backtrace-limit">,
HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit).">;
def fspell_checking_limit : Separate<["-"], "fspell-checking-limit">, MetaVarName<"<N>">,
HelpText<"Set the maximum number of times to perform spell checking on unrecognized identifiers (0 = no limit).">;
def fcaret_diagnostics_max_lines :
Separate<["-"], "fcaret-diagnostics-max-lines">, MetaVarName<"<N>">,
HelpText<"Set the maximum number of source lines to show in a caret diagnostic">;
def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">,
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
def verify : Flag<["-"], "verify">,

View File

@ -469,6 +469,7 @@ def arch__errors__fatal : Flag<["-"], "arch_errors_fatal">;
def arch : Separate<["-"], "arch">, Flags<[DriverOption]>;
def arch__only : Separate<["-"], "arch_only">;
def a : Joined<["-"], "a">;
def autocomplete : Joined<["--"], "autocomplete=">;
def bind__at__load : Flag<["-"], "bind_at_load">;
def bundle__loader : Separate<["-"], "bundle_loader">;
def bundle : Flag<["-"], "bundle">;
@ -1740,6 +1741,7 @@ def mno_avx : Flag<["-"], "mno-avx">, Group<m_x86_Features_Group>;
def mno_avx2 : Flag<["-"], "mno-avx2">, Group<m_x86_Features_Group>;
def mno_avx512f : Flag<["-"], "mno-avx512f">, Group<m_x86_Features_Group>;
def mno_avx512cd : Flag<["-"], "mno-avx512cd">, Group<m_x86_Features_Group>;
def mno_avx512vpopcntdq : Flag<["-"], "mno-avx512vpopcntdq">, Group<m_x86_Features_Group>;
def mno_avx512er : Flag<["-"], "mno-avx512er">, Group<m_x86_Features_Group>;
def mno_avx512pf : Flag<["-"], "mno-avx512pf">, Group<m_x86_Features_Group>;
def mno_avx512dq : Flag<["-"], "mno-avx512dq">, Group<m_x86_Features_Group>;
@ -1940,6 +1942,7 @@ def mavx : Flag<["-"], "mavx">, Group<m_x86_Features_Group>;
def mavx2 : Flag<["-"], "mavx2">, Group<m_x86_Features_Group>;
def mavx512f : Flag<["-"], "mavx512f">, Group<m_x86_Features_Group>;
def mavx512cd : Flag<["-"], "mavx512cd">, Group<m_x86_Features_Group>;
def mavx512vpopcntdq : Flag<["-"], "mavx512vpopcntdq">, Group<m_x86_Features_Group>;
def mavx512er : Flag<["-"], "mavx512er">, Group<m_x86_Features_Group>;
def mavx512pf : Flag<["-"], "mavx512pf">, Group<m_x86_Features_Group>;
def mavx512dq : Flag<["-"], "mavx512dq">, Group<m_x86_Features_Group>;

View File

@ -710,16 +710,35 @@ struct FormatStyle {
/// \endcode
bool BreakBeforeTernaryOperators;
/// \brief Always break constructor initializers before commas and align
/// the commas with the colon.
/// \code
/// true: false:
/// SomeClass::Constructor() vs. SomeClass::Constructor() : a(a),
/// : a(a) b(b),
/// , b(b) c(c) {}
/// , c(c) {}
/// \endcode
bool BreakConstructorInitializersBeforeComma;
/// \brief Different ways to break initializers.
enum BreakConstructorInitializersStyle
{
/// Break constructor initializers before the colon and after the commas.
/// \code
/// Constructor()
/// : initializer1(),
/// initializer2()
/// \endcode
BCIS_BeforeColon,
/// Break constructor initializers before the colon and commas, and align
/// the commas with the colon.
/// \code
/// Constructor()
/// : initializer1()
/// , initializer2()
/// \endcode
BCIS_BeforeComma,
/// Break constructor initializers after the colon and commas.
/// \code
/// Constructor() :
/// initializer1(),
/// initializer2()
/// \endcode
BCIS_AfterColon
};
/// \brief The constructor initializers style to use..
BreakConstructorInitializersStyle BreakConstructorInitializers;
/// \brief Break after each annotation on a field in Java files.
/// \code{.java}
@ -1390,8 +1409,7 @@ struct FormatStyle {
BreakBeforeBinaryOperators == R.BreakBeforeBinaryOperators &&
BreakBeforeBraces == R.BreakBeforeBraces &&
BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators &&
BreakConstructorInitializersBeforeComma ==
R.BreakConstructorInitializersBeforeComma &&
BreakConstructorInitializers == R.BreakConstructorInitializers &&
BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations &&
BreakStringLiterals == R.BreakStringLiterals &&
ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas &&

View File

@ -59,6 +59,10 @@ class TargetInfo;
class FrontendAction;
class ASTDeserializationListener;
namespace vfs {
class FileSystem;
}
/// \brief Utility class for loading a ASTContext from an AST file.
///
class ASTUnit : public ModuleLoader {
@ -420,7 +424,8 @@ class ASTUnit : public ModuleLoader {
explicit ASTUnit(bool MainFileIsAST);
bool Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer);
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,
IntrusiveRefCntPtr<vfs::FileSystem> VFS);
struct ComputedPreamble {
llvm::MemoryBuffer *Buffer;
@ -434,11 +439,13 @@ class ASTUnit : public ModuleLoader {
PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {}
};
ComputedPreamble ComputePreamble(CompilerInvocation &Invocation,
unsigned MaxLines);
unsigned MaxLines,
IntrusiveRefCntPtr<vfs::FileSystem> VFS);
std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild = true,
const CompilerInvocation &PreambleInvocationIn,
IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild = true,
unsigned MaxLines = 0);
void RealizeTopLevelDeclsFromPreamble();
@ -731,11 +738,17 @@ class ASTUnit : public ModuleLoader {
/// of this translation unit should be precompiled, to improve the performance
/// of reparsing. Set to zero to disable preambles.
///
/// \param VFS - A vfs::FileSystem to be used for all file accesses. Note that
/// preamble is saved to a temporary directory on a RealFileSystem, so in order
/// for it to be loaded correctly, VFS should have access to it(i.e., be an
/// overlay over RealFileSystem).
///
/// \returns \c true if a catastrophic failure occurred (which means that the
/// \c ASTUnit itself is invalid), or \c false otherwise.
bool LoadFromCompilerInvocation(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
unsigned PrecompilePreambleAfterNParses);
unsigned PrecompilePreambleAfterNParses,
IntrusiveRefCntPtr<vfs::FileSystem> VFS);
public:
@ -826,6 +839,11 @@ class ASTUnit : public ModuleLoader {
/// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
/// mainly to allow the caller to see the diagnostics.
///
/// \param VFS - A vfs::FileSystem to be used for all file accesses. Note that
/// preamble is saved to a temporary directory on a RealFileSystem, so in order
/// for it to be loaded correctly, VFS should have access to it(i.e., be an
/// overlay over RealFileSystem). RealFileSystem will be used if \p VFS is nullptr.
///
// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
// shouldn't need to specify them at construction time.
static ASTUnit *LoadFromCommandLine(
@ -842,15 +860,23 @@ class ASTUnit : public ModuleLoader {
bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false,
bool UserFilesAreVolatile = false, bool ForSerialization = false,
llvm::Optional<StringRef> ModuleFormat = llvm::None,
std::unique_ptr<ASTUnit> *ErrAST = nullptr);
std::unique_ptr<ASTUnit> *ErrAST = nullptr,
IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
/// \brief Reparse the source files using the same command-line options that
/// were originally used to produce this translation unit.
///
/// \param VFS - A vfs::FileSystem to be used for all file accesses. Note that
/// preamble is saved to a temporary directory on a RealFileSystem, so in order
/// for it to be loaded correctly, VFS should give an access to this(i.e. be an
/// overlay over RealFileSystem). FileMgr->getVirtualFileSystem() will be used if
/// \p VFS is nullptr.
///
/// \returns True if a failure occurred that causes the ASTUnit not to
/// contain any translation-unit information, false otherwise.
bool Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
ArrayRef<RemappedFile> RemappedFiles = None);
ArrayRef<RemappedFile> RemappedFiles = None,
IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
/// \brief Perform code completion at the given file, line, and
/// column within this translation unit.

View File

@ -53,6 +53,7 @@ CODEGENOPT(DisableLLVMPasses , 1, 0) ///< Don't run any LLVM IR passes to get
///< the pristine IR generated by the
///< frontend.
CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any lifetime markers
CODEGENOPT(DisableO0ImplyOptNone , 1, 0) ///< Don't annonate function with optnone at O0
CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental
///< pass manager.
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.

View File

@ -225,6 +225,11 @@ IntrusiveRefCntPtr<vfs::FileSystem>
createVFSFromCompilerInvocation(const CompilerInvocation &CI,
DiagnosticsEngine &Diags);
IntrusiveRefCntPtr<vfs::FileSystem>
createVFSFromCompilerInvocation(const CompilerInvocation &CI,
DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<vfs::FileSystem> BaseFS);
} // end namespace clang
#endif

View File

@ -257,6 +257,23 @@ class ModuleMap {
/// resolved.
Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const;
/// Resolve the given header directive to an actual header file.
///
/// \param M The module in which we're resolving the header directive.
/// \param Header The header directive to resolve.
/// \param RelativePathName Filled in with the relative path name from the
/// module to the resolved header.
/// \return The resolved file, if any.
const FileEntry *resolveHeader(Module *M,
Module::UnresolvedHeaderDirective Header,
SmallVectorImpl<char> &RelativePathName);
/// Attempt to resolve the specified header directive as naming a builtin
/// header.
const FileEntry *
resolveAsBuiltinHeader(Module *M, Module::UnresolvedHeaderDirective Header,
SmallVectorImpl<char> &BuiltinPathName);
/// \brief Looks up the modules that \p File corresponds to.
///
/// If \p File represents a builtin header within Clang's builtin include

View File

@ -915,6 +915,7 @@ enum AttributeDeclKind {
ExpectedTypeOrNamespace,
ExpectedObjectiveCInterface,
ExpectedMethodOrProperty,
ExpectedFunctionOrMethodOrProperty,
ExpectedStructOrUnion,
ExpectedStructOrUnionOrClass,
ExpectedType,

View File

@ -145,12 +145,15 @@ namespace clang {
/// expressions, or template names, and the source locations for important
/// tokens. All of the information about template arguments is allocated
/// directly after this structure.
struct TemplateIdAnnotation {
struct TemplateIdAnnotation final
: private llvm::TrailingObjects<TemplateIdAnnotation,
ParsedTemplateArgument> {
friend TrailingObjects;
/// \brief The nested-name-specifier that precedes the template name.
CXXScopeSpec SS;
/// TemplateKWLoc - The location of the template keyword within the
/// source.
/// TemplateKWLoc - The location of the template keyword.
/// For e.g. typename T::template Y<U>
SourceLocation TemplateKWLoc;
/// TemplateNameLoc - The location of the template name within the
@ -183,34 +186,56 @@ namespace clang {
/// \brief Retrieves a pointer to the template arguments
ParsedTemplateArgument *getTemplateArgs() {
return reinterpret_cast<ParsedTemplateArgument *>(this + 1);
return getTrailingObjects<ParsedTemplateArgument>();
}
/// \brief Creates a new TemplateIdAnnotation with NumArgs arguments and
/// appends it to List.
static TemplateIdAnnotation *
Allocate(unsigned NumArgs, SmallVectorImpl<TemplateIdAnnotation*> &List) {
TemplateIdAnnotation *TemplateId
= (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
sizeof(ParsedTemplateArgument) * NumArgs);
TemplateId->NumArgs = NumArgs;
// Default-construct nested-name-specifier.
new (&TemplateId->SS) CXXScopeSpec();
// Default-construct parsed template arguments.
ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs();
for (unsigned I = 0; I != NumArgs; ++I)
new (TemplateArgs + I) ParsedTemplateArgument();
List.push_back(TemplateId);
Create(CXXScopeSpec SS, SourceLocation TemplateKWLoc,
SourceLocation TemplateNameLoc, IdentifierInfo *Name,
OverloadedOperatorKind OperatorKind,
ParsedTemplateTy OpaqueTemplateName, TemplateNameKind TemplateKind,
SourceLocation LAngleLoc, SourceLocation RAngleLoc,
ArrayRef<ParsedTemplateArgument> TemplateArgs,
SmallVectorImpl<TemplateIdAnnotation *> &CleanupList) {
TemplateIdAnnotation *TemplateId = new (std::malloc(
totalSizeToAlloc<ParsedTemplateArgument>(TemplateArgs.size())))
TemplateIdAnnotation(SS, TemplateKWLoc, TemplateNameLoc, Name,
OperatorKind, OpaqueTemplateName, TemplateKind,
LAngleLoc, RAngleLoc, TemplateArgs);
CleanupList.push_back(TemplateId);
return TemplateId;
}
void Destroy() {
SS.~CXXScopeSpec();
void Destroy() {
std::for_each(
getTemplateArgs(), getTemplateArgs() + NumArgs,
[](ParsedTemplateArgument &A) { A.~ParsedTemplateArgument(); });
this->~TemplateIdAnnotation();
free(this);
}
private:
TemplateIdAnnotation(const TemplateIdAnnotation &) = delete;
TemplateIdAnnotation(CXXScopeSpec SS, SourceLocation TemplateKWLoc,
SourceLocation TemplateNameLoc, IdentifierInfo *Name,
OverloadedOperatorKind OperatorKind,
ParsedTemplateTy OpaqueTemplateName,
TemplateNameKind TemplateKind,
SourceLocation LAngleLoc, SourceLocation RAngleLoc,
ArrayRef<ParsedTemplateArgument> TemplateArgs) noexcept
: SS(SS), TemplateKWLoc(TemplateKWLoc),
TemplateNameLoc(TemplateNameLoc), Name(Name), Operator(OperatorKind),
Template(OpaqueTemplateName), Kind(TemplateKind),
LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
NumArgs(TemplateArgs.size()) {
std::uninitialized_copy(TemplateArgs.begin(), TemplateArgs.end(),
getTemplateArgs());
}
~TemplateIdAnnotation() = default;
};
/// Retrieves the range of the given template parameter lists.

View File

@ -388,6 +388,8 @@ class FunctionScopeInfo {
(HasBranchProtectedScope && HasBranchIntoScope));
}
bool isCoroutine() const { return !FirstCoroutineStmtLoc.isInvalid(); }
void setFirstCoroutineStmt(SourceLocation Loc, StringRef Keyword) {
assert(FirstCoroutineStmtLoc.isInvalid() &&
"first coroutine statement location already set");

View File

@ -689,17 +689,37 @@ class Sema {
class SynthesizedFunctionScope {
Sema &S;
Sema::ContextRAII SavedContext;
bool PushedCodeSynthesisContext = false;
public:
SynthesizedFunctionScope(Sema &S, DeclContext *DC)
: S(S), SavedContext(S, DC)
{
: S(S), SavedContext(S, DC) {
S.PushFunctionScope();
S.PushExpressionEvaluationContext(
Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
if (auto *FD = dyn_cast<FunctionDecl>(DC))
FD->setWillHaveBody(true);
else
assert(isa<ObjCMethodDecl>(DC));
}
void addContextNote(SourceLocation UseLoc) {
assert(!PushedCodeSynthesisContext);
Sema::CodeSynthesisContext Ctx;
Ctx.Kind = Sema::CodeSynthesisContext::DefiningSynthesizedFunction;
Ctx.PointOfInstantiation = UseLoc;
Ctx.Entity = cast<Decl>(S.CurContext);
S.pushCodeSynthesisContext(Ctx);
PushedCodeSynthesisContext = true;
}
~SynthesizedFunctionScope() {
if (PushedCodeSynthesisContext)
S.popCodeSynthesisContext();
if (auto *FD = dyn_cast<FunctionDecl>(S.CurContext))
FD->setWillHaveBody(false);
S.PopExpressionEvaluationContext();
S.PopFunctionScopeInfo();
}
@ -2727,7 +2747,7 @@ class Sema {
/// of a function.
///
/// Returns true if any errors were emitted.
bool diagnoseArgIndependentDiagnoseIfAttrs(const FunctionDecl *Function,
bool diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND,
SourceLocation Loc);
/// Returns whether the given function's address can be taken or not,
@ -6974,6 +6994,10 @@ class Sema {
/// We are declaring an implicit special member function.
DeclaringSpecialMember,
/// We are defining a synthesized function (such as a defaulted special
/// member).
DefiningSynthesizedFunction,
} Kind;
/// \brief Was the enclosing context a non-instantiation SFINAE context?
@ -10121,6 +10145,7 @@ class Sema {
bool SemaBuiltinVAStartARM(CallExpr *Call);
bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs);
bool SemaBuiltinVSX(CallExpr *TheCall);
bool SemaBuiltinOSLogFormat(CallExpr *TheCall);
public:

View File

@ -60,16 +60,6 @@ struct CompileCommand {
/// The output file associated with the command.
std::string Output;
/// \brief An optional mapping from each file's path to its content for all
/// files needed for the compilation that are not available via the file
/// system.
///
/// Note that a tool implementation is required to fall back to the file
/// system if a source file is not provided in the mapped sources, as
/// compilation databases will usually not provide all files in mapped sources
/// for performance reasons.
std::vector<std::pair<std::string, std::string> > MappedSources;
};
/// \brief Interface for compilation databases.
@ -186,10 +176,11 @@ class FixedCompilationDatabase : public CompilationDatabase {
/// the number of arguments before "--", if "--" was found in the argument
/// list.
/// \param Argv Points to the command line arguments.
/// \param ErrorMsg Contains error text if the function returns null pointer.
/// \param Directory The base directory used in the FixedCompilationDatabase.
static FixedCompilationDatabase *loadFromCommandLine(int &Argc,
const char *const *Argv,
Twine Directory = ".");
static std::unique_ptr<FixedCompilationDatabase> loadFromCommandLine(
int &Argc, const char *const *Argv, std::string &ErrorMsg,
Twine Directory = ".");
/// \brief Constructs a compilation data base from a specified directory
/// and command line.

View File

@ -274,9 +274,17 @@ void Decl::setLexicalDeclContext(DeclContext *DC) {
} else {
getMultipleDC()->LexicalDC = DC;
}
Hidden = cast<Decl>(DC)->Hidden;
if (Hidden && !isFromASTFile() && hasLocalOwningModuleStorage())
setLocalOwningModule(cast<Decl>(DC)->getOwningModule());
// FIXME: We shouldn't be changing the lexical context of declarations
// imported from AST files.
if (!isFromASTFile()) {
Hidden = cast<Decl>(DC)->Hidden && hasLocalOwningModuleStorage();
if (Hidden)
setLocalOwningModule(cast<Decl>(DC)->getOwningModule());
}
assert((!Hidden || getOwningModule()) &&
"hidden declaration has no owning module");
}
void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
@ -440,8 +448,8 @@ const Attr *Decl::getDefiningAttr() const {
return nullptr;
}
StringRef getRealizedPlatform(const AvailabilityAttr *A,
const ASTContext &Context) {
static StringRef getRealizedPlatform(const AvailabilityAttr *A,
const ASTContext &Context) {
// Check if this is an App Extension "platform", and if so chop off
// the suffix for matching with the actual platform.
StringRef RealizedPlatform = A->getPlatform()->getName();

View File

@ -1230,8 +1230,7 @@ namespace {
IsNullPtr = V.isNullPointer();
}
void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false,
bool IsNullPtr_ = false, uint64_t Offset_ = 0) {
void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false) {
#ifndef NDEBUG
// We only allow a few types of invalid bases. Enforce that here.
if (BInvalid) {
@ -1242,11 +1241,20 @@ namespace {
#endif
Base = B;
Offset = CharUnits::fromQuantity(Offset_);
Offset = CharUnits::fromQuantity(0);
InvalidBase = BInvalid;
CallIndex = I;
Designator = SubobjectDesignator(getType(B));
IsNullPtr = IsNullPtr_;
IsNullPtr = false;
}
void setNull(QualType PointerTy, uint64_t TargetVal) {
Base = (Expr *)nullptr;
Offset = CharUnits::fromQuantity(TargetVal);
InvalidBase = false;
CallIndex = 0;
Designator = SubobjectDesignator(PointerTy->getPointeeType());
IsNullPtr = true;
}
void setInvalid(APValue::LValueBase B, unsigned I = 0) {
@ -5494,8 +5502,8 @@ class PointerExprEvaluator
return true;
}
bool ZeroInitialization(const Expr *E) {
auto Offset = Info.Ctx.getTargetNullPointerValue(E->getType());
Result.set((Expr*)nullptr, 0, false, true, Offset);
auto TargetVal = Info.Ctx.getTargetNullPointerValue(E->getType());
Result.setNull(E->getType(), TargetVal);
return true;
}

View File

@ -1689,6 +1689,8 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
// ::= _N # bool
// _O # <array in parameter>
// ::= _T # __float80 (Intel)
// ::= _S # char16_t
// ::= _U # char32_t
// ::= _W # wchar_t
// ::= _Z # __float80 (Digital Mars)
switch (T->getKind()) {

View File

@ -88,7 +88,7 @@ const VarDecl *CXXForRangeStmt::getLoopVariable() const {
}
CoroutineBodyStmt *CoroutineBodyStmt::Create(
const ASTContext &C, CoroutineBodyStmt::CtorArgs const& Args) {
const ASTContext &C, CoroutineBodyStmt::CtorArgs const &Args) {
std::size_t Size = totalSizeToAlloc<Stmt *>(
CoroutineBodyStmt::FirstParamMove + Args.ParamMoves.size());
@ -108,6 +108,8 @@ CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args)
SubStmts[CoroutineBodyStmt::Allocate] = Args.Allocate;
SubStmts[CoroutineBodyStmt::Deallocate] = Args.Deallocate;
SubStmts[CoroutineBodyStmt::ReturnValue] = Args.ReturnValue;
SubStmts[CoroutineBodyStmt::ResultDecl] = Args.ResultDecl;
SubStmts[CoroutineBodyStmt::ReturnStmt] = Args.ReturnStmt;
SubStmts[CoroutineBodyStmt::ReturnStmtOnAllocFailure] =
Args.ReturnStmtOnAllocFailure;
std::copy(Args.ParamMoves.begin(), Args.ParamMoves.end(),

View File

@ -92,6 +92,8 @@ Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
IsAutosynthesized = false;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Stmt *Body = FD->getBody();
if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
Body = CoroBody->getBody();
if (Manager && Manager->synthesizeBodies()) {
Stmt *SynthesizedBody =
getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(FD);

View File

@ -64,6 +64,7 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
bool HasFeature = llvm::StringSwitch<bool>(Feature)
.Case("altivec", LangOpts.AltiVec)
.Case("blocks", LangOpts.Blocks)
.Case("coroutines", LangOpts.CoroutinesTS)
.Case("cplusplus", LangOpts.CPlusPlus)
.Case("cplusplus11", LangOpts.CPlusPlus11)
.Case("freestanding", LangOpts.Freestanding)

View File

@ -183,48 +183,22 @@ unsigned LineTableInfo::getLineTableFilenameID(StringRef Name) {
return IterBool.first->second;
}
/// AddLineNote - Add a line note to the line table that indicates that there
/// is a \#line at the specified FID/Offset location which changes the presumed
/// location to LineNo/FilenameID.
void LineTableInfo::AddLineNote(FileID FID, unsigned Offset,
unsigned LineNo, int FilenameID) {
std::vector<LineEntry> &Entries = LineEntries[FID];
assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
"Adding line entries out of order!");
SrcMgr::CharacteristicKind Kind = SrcMgr::C_User;
unsigned IncludeOffset = 0;
if (!Entries.empty()) {
// If this is a '#line 4' after '#line 42 "foo.h"', make sure to remember
// that we are still in "foo.h".
if (FilenameID == -1)
FilenameID = Entries.back().FilenameID;
// If we are after a line marker that switched us to system header mode, or
// that set #include information, preserve it.
Kind = Entries.back().FileKind;
IncludeOffset = Entries.back().IncludeOffset;
}
Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, Kind,
IncludeOffset));
}
/// AddLineNote This is the same as the previous version of AddLineNote, but is
/// used for GNU line markers. If EntryExit is 0, then this doesn't change the
/// presumed \#include stack. If it is 1, this is a file entry, if it is 2 then
/// this is a file exit. FileKind specifies whether this is a system header or
/// extern C system header.
void LineTableInfo::AddLineNote(FileID FID, unsigned Offset,
unsigned LineNo, int FilenameID,
unsigned EntryExit,
/// Add a line note to the line table that indicates that there is a \#line or
/// GNU line marker at the specified FID/Offset location which changes the
/// presumed location to LineNo/FilenameID. If EntryExit is 0, then this doesn't
/// change the presumed \#include stack. If it is 1, this is a file entry, if
/// it is 2 then this is a file exit. FileKind specifies whether this is a
/// system header or extern C system header.
void LineTableInfo::AddLineNote(FileID FID, unsigned Offset, unsigned LineNo,
int FilenameID, unsigned EntryExit,
SrcMgr::CharacteristicKind FileKind) {
assert(FilenameID != -1 && "Unspecified filename should use other accessor");
std::vector<LineEntry> &Entries = LineEntries[FID];
// An unspecified FilenameID means use the last filename if available, or the
// main source file otherwise.
if (FilenameID == -1 && !Entries.empty())
FilenameID = Entries.back().FilenameID;
assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
"Adding line entries out of order!");
@ -281,47 +255,20 @@ unsigned SourceManager::getLineTableFilenameID(StringRef Name) {
return getLineTable().getLineTableFilenameID(Name);
}
/// AddLineNote - Add a line note to the line table for the FileID and offset
/// specified by Loc. If FilenameID is -1, it is considered to be
/// unspecified.
void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
int FilenameID) {
std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
bool Invalid = false;
const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
if (!Entry.isFile() || Invalid)
return;
const SrcMgr::FileInfo &FileInfo = Entry.getFile();
// Remember that this file has #line directives now if it doesn't already.
const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
getLineTable().AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID);
}
/// AddLineNote - Add a GNU line marker to the line table.
void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
int FilenameID, bool IsFileEntry,
bool IsFileExit, bool IsSystemHeader,
bool IsExternCHeader) {
// If there is no filename and no flags, this is treated just like a #line,
// which does not change the flags of the previous line marker.
if (FilenameID == -1) {
assert(!IsFileEntry && !IsFileExit && !IsSystemHeader && !IsExternCHeader &&
"Can't set flags without setting the filename!");
return AddLineNote(Loc, LineNo, FilenameID);
}
bool IsFileExit,
SrcMgr::CharacteristicKind FileKind) {
std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
bool Invalid = false;
const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
if (!Entry.isFile() || Invalid)
return;
const SrcMgr::FileInfo &FileInfo = Entry.getFile();
// Remember that this file has #line directives now if it doesn't already.
@ -329,14 +276,6 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
(void) getLineTable();
SrcMgr::CharacteristicKind FileKind;
if (IsExternCHeader)
FileKind = SrcMgr::C_ExternCSystem;
else if (IsSystemHeader)
FileKind = SrcMgr::C_System;
else
FileKind = SrcMgr::C_User;
unsigned EntryExit = 0;
if (IsFileEntry)
EntryExit = 1;

View File

@ -2169,15 +2169,20 @@ class AMDGPUTargetInfo final : public TargetInfo {
: DataLayoutStringR600);
assert(DataLayout->getAllocaAddrSpace() == AS.Private);
AddrSpaceMap =
llvm::StringSwitch<const LangAS::Map *>(Triple.getEnvironmentName())
.Case("opencl", &AMDGPUOpenCLPrivateIsZeroMap)
.Case("amdgiz", &AMDGPUNonOpenCLGenericIsZeroMap)
.Case("amdgizcl", &AMDGPUOpenCLGenericIsZeroMap)
.Default(&AMDGPUNonOpenCLPrivateIsZeroMap);
UseAddrSpaceMapMangling = true;
}
void adjust(LangOptions &Opts) override {
TargetInfo::adjust(Opts);
if (isGenericZero(getTriple())) {
AddrSpaceMap = Opts.OpenCL ? &AMDGPUOpenCLGenericIsZeroMap
: &AMDGPUNonOpenCLGenericIsZeroMap;
} else {
AddrSpaceMap = Opts.OpenCL ? &AMDGPUOpenCLPrivateIsZeroMap
: &AMDGPUNonOpenCLPrivateIsZeroMap;
}
}
uint64_t getPointerWidthV(unsigned AddrSpace) const override {
if (GPU <= GK_CAYMAN)
return 32;
@ -2619,6 +2624,7 @@ class X86TargetInfo : public TargetInfo {
bool HasFMA = false;
bool HasF16C = false;
bool HasAVX512CD = false;
bool HasAVX512VPOPCNTDQ = false;
bool HasAVX512ER = false;
bool HasAVX512PF = false;
bool HasAVX512DQ = false;
@ -3435,23 +3441,32 @@ void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features,
switch (Level) {
case AVX512F:
Features["avx512f"] = true;
LLVM_FALLTHROUGH;
case AVX2:
Features["avx2"] = true;
LLVM_FALLTHROUGH;
case AVX:
Features["avx"] = true;
Features["xsave"] = true;
LLVM_FALLTHROUGH;
case SSE42:
Features["sse4.2"] = true;
LLVM_FALLTHROUGH;
case SSE41:
Features["sse4.1"] = true;
LLVM_FALLTHROUGH;
case SSSE3:
Features["ssse3"] = true;
LLVM_FALLTHROUGH;
case SSE3:
Features["sse3"] = true;
LLVM_FALLTHROUGH;
case SSE2:
Features["sse2"] = true;
LLVM_FALLTHROUGH;
case SSE1:
Features["sse"] = true;
LLVM_FALLTHROUGH;
case NoSSE:
break;
}
@ -3462,29 +3477,37 @@ void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features,
case NoSSE:
case SSE1:
Features["sse"] = false;
LLVM_FALLTHROUGH;
case SSE2:
Features["sse2"] = Features["pclmul"] = Features["aes"] =
Features["sha"] = false;
LLVM_FALLTHROUGH;
case SSE3:
Features["sse3"] = false;
setXOPLevel(Features, NoXOP, false);
LLVM_FALLTHROUGH;
case SSSE3:
Features["ssse3"] = false;
LLVM_FALLTHROUGH;
case SSE41:
Features["sse4.1"] = false;
LLVM_FALLTHROUGH;
case SSE42:
Features["sse4.2"] = false;
LLVM_FALLTHROUGH;
case AVX:
Features["fma"] = Features["avx"] = Features["f16c"] = Features["xsave"] =
Features["xsaveopt"] = false;
setXOPLevel(Features, FMA4, false);
LLVM_FALLTHROUGH;
case AVX2:
Features["avx2"] = false;
LLVM_FALLTHROUGH;
case AVX512F:
Features["avx512f"] = Features["avx512cd"] = Features["avx512er"] =
Features["avx512pf"] = Features["avx512dq"] = Features["avx512bw"] =
Features["avx512vl"] = Features["avx512vbmi"] =
Features["avx512ifma"] = false;
Features["avx512pf"] = Features["avx512dq"] = Features["avx512bw"] =
Features["avx512vl"] = Features["avx512vbmi"] =
Features["avx512ifma"] = Features["avx512vpopcntdq"] = false;
}
}
@ -3494,10 +3517,13 @@ void X86TargetInfo::setMMXLevel(llvm::StringMap<bool> &Features,
switch (Level) {
case AMD3DNowAthlon:
Features["3dnowa"] = true;
LLVM_FALLTHROUGH;
case AMD3DNow:
Features["3dnow"] = true;
LLVM_FALLTHROUGH;
case MMX:
Features["mmx"] = true;
LLVM_FALLTHROUGH;
case NoMMX3DNow:
break;
}
@ -3508,8 +3534,10 @@ void X86TargetInfo::setMMXLevel(llvm::StringMap<bool> &Features,
case NoMMX3DNow:
case MMX:
Features["mmx"] = false;
LLVM_FALLTHROUGH;
case AMD3DNow:
Features["3dnow"] = false;
LLVM_FALLTHROUGH;
case AMD3DNowAthlon:
Features["3dnowa"] = false;
}
@ -3521,12 +3549,15 @@ void X86TargetInfo::setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level,
switch (Level) {
case XOP:
Features["xop"] = true;
LLVM_FALLTHROUGH;
case FMA4:
Features["fma4"] = true;
setSSELevel(Features, AVX, true);
LLVM_FALLTHROUGH;
case SSE4A:
Features["sse4a"] = true;
setSSELevel(Features, SSE3, true);
LLVM_FALLTHROUGH;
case NoXOP:
break;
}
@ -3537,8 +3568,10 @@ void X86TargetInfo::setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level,
case NoXOP:
case SSE4A:
Features["sse4a"] = false;
LLVM_FALLTHROUGH;
case FMA4:
Features["fma4"] = false;
LLVM_FALLTHROUGH;
case XOP:
Features["xop"] = false;
}
@ -3584,7 +3617,8 @@ void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
setSSELevel(Features, AVX512F, Enabled);
} else if (Name == "avx512cd" || Name == "avx512er" || Name == "avx512pf" ||
Name == "avx512dq" || Name == "avx512bw" || Name == "avx512vl" ||
Name == "avx512vbmi" || Name == "avx512ifma") {
Name == "avx512vbmi" || Name == "avx512ifma" ||
Name == "avx512vpopcntdq") {
if (Enabled)
setSSELevel(Features, AVX512F, Enabled);
// Enable BWI instruction if VBMI is being enabled.
@ -3668,6 +3702,8 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasF16C = true;
} else if (Feature == "+avx512cd") {
HasAVX512CD = true;
} else if (Feature == "+avx512vpopcntdq") {
HasAVX512VPOPCNTDQ = true;
} else if (Feature == "+avx512er") {
HasAVX512ER = true;
} else if (Feature == "+avx512pf") {
@ -3986,10 +4022,13 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
switch (XOPLevel) {
case XOP:
Builder.defineMacro("__XOP__");
LLVM_FALLTHROUGH;
case FMA4:
Builder.defineMacro("__FMA4__");
LLVM_FALLTHROUGH;
case SSE4A:
Builder.defineMacro("__SSE4A__");
LLVM_FALLTHROUGH;
case NoXOP:
break;
}
@ -4002,6 +4041,8 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
if (HasAVX512CD)
Builder.defineMacro("__AVX512CD__");
if (HasAVX512VPOPCNTDQ)
Builder.defineMacro("__AVX512VPOPCNTDQ__");
if (HasAVX512ER)
Builder.defineMacro("__AVX512ER__");
if (HasAVX512PF)
@ -4051,24 +4092,33 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
switch (SSELevel) {
case AVX512F:
Builder.defineMacro("__AVX512F__");
LLVM_FALLTHROUGH;
case AVX2:
Builder.defineMacro("__AVX2__");
LLVM_FALLTHROUGH;
case AVX:
Builder.defineMacro("__AVX__");
LLVM_FALLTHROUGH;
case SSE42:
Builder.defineMacro("__SSE4_2__");
LLVM_FALLTHROUGH;
case SSE41:
Builder.defineMacro("__SSE4_1__");
LLVM_FALLTHROUGH;
case SSSE3:
Builder.defineMacro("__SSSE3__");
LLVM_FALLTHROUGH;
case SSE3:
Builder.defineMacro("__SSE3__");
LLVM_FALLTHROUGH;
case SSE2:
Builder.defineMacro("__SSE2__");
Builder.defineMacro("__SSE2_MATH__"); // -mfp-math=sse always implied.
LLVM_FALLTHROUGH;
case SSE1:
Builder.defineMacro("__SSE__");
Builder.defineMacro("__SSE_MATH__"); // -mfp-math=sse always implied.
LLVM_FALLTHROUGH;
case NoSSE:
break;
}
@ -4097,10 +4147,13 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
switch (MMX3DNowLevel) {
case AMD3DNowAthlon:
Builder.defineMacro("__3dNOW_A__");
LLVM_FALLTHROUGH;
case AMD3DNow:
Builder.defineMacro("__3dNOW__");
LLVM_FALLTHROUGH;
case MMX:
Builder.defineMacro("__MMX__");
LLVM_FALLTHROUGH;
case NoMMX3DNow:
break;
}
@ -4112,6 +4165,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
}
if (CPU >= CK_i586)
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
if (HasFloat128)
Builder.defineMacro("__SIZEOF_FLOAT128__", "16");
}
bool X86TargetInfo::hasFeature(StringRef Feature) const {
@ -4121,6 +4177,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("avx2", SSELevel >= AVX2)
.Case("avx512f", SSELevel >= AVX512F)
.Case("avx512cd", HasAVX512CD)
.Case("avx512vpopcntdq", HasAVX512VPOPCNTDQ)
.Case("avx512er", HasAVX512ER)
.Case("avx512pf", HasAVX512PF)
.Case("avx512dq", HasAVX512DQ)
@ -4206,6 +4263,7 @@ bool X86TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
.Case("avx512bw", true)
.Case("avx512dq", true)
.Case("avx512cd", true)
.Case("avx512vpopcntdq", true)
.Case("avx512er", true)
.Case("avx512pf", true)
.Case("avx512vbmi", true)
@ -4589,7 +4647,9 @@ static void addMinGWDefines(const LangOptions &Opts, MacroBuilder &Builder) {
class MinGWX86_32TargetInfo : public WindowsX86_32TargetInfo {
public:
MinGWX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: WindowsX86_32TargetInfo(Triple, Opts) {}
: WindowsX86_32TargetInfo(Triple, Opts) {
HasFloat128 = true;
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
@ -4881,6 +4941,7 @@ class MinGWX86_64TargetInfo : public WindowsX86_64TargetInfo {
// with x86 FP ops. Weird.
LongDoubleWidth = LongDoubleAlign = 128;
LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
HasFloat128 = true;
}
void getTargetDefines(const LangOptions &Opts,

View File

@ -26,6 +26,8 @@ XRayFunctionFilter::ImbueAttribute
XRayFunctionFilter::shouldImbueFunction(StringRef FunctionName) const {
// First apply the always instrument list, than if it isn't an "always" see
// whether it's treated as a "never" instrument function.
if (AlwaysInstrument->inSection("fun", FunctionName, "arg1"))
return ImbueAttribute::ALWAYS_ARG1;
if (AlwaysInstrument->inSection("fun", FunctionName))
return ImbueAttribute::ALWAYS;
if (NeverInstrument->inSection("fun", FunctionName))

View File

@ -7332,39 +7332,42 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
AVX512PF,
AVX512VBMI,
AVX512IFMA,
AVX512VPOPCNTDQ,
MAX
};
X86Features Feature = StringSwitch<X86Features>(FeatureStr)
.Case("cmov", X86Features::CMOV)
.Case("mmx", X86Features::MMX)
.Case("popcnt", X86Features::POPCNT)
.Case("sse", X86Features::SSE)
.Case("sse2", X86Features::SSE2)
.Case("sse3", X86Features::SSE3)
.Case("ssse3", X86Features::SSSE3)
.Case("sse4.1", X86Features::SSE4_1)
.Case("sse4.2", X86Features::SSE4_2)
.Case("avx", X86Features::AVX)
.Case("avx2", X86Features::AVX2)
.Case("sse4a", X86Features::SSE4_A)
.Case("fma4", X86Features::FMA4)
.Case("xop", X86Features::XOP)
.Case("fma", X86Features::FMA)
.Case("avx512f", X86Features::AVX512F)
.Case("bmi", X86Features::BMI)
.Case("bmi2", X86Features::BMI2)
.Case("aes", X86Features::AES)
.Case("pclmul", X86Features::PCLMUL)
.Case("avx512vl", X86Features::AVX512VL)
.Case("avx512bw", X86Features::AVX512BW)
.Case("avx512dq", X86Features::AVX512DQ)
.Case("avx512cd", X86Features::AVX512CD)
.Case("avx512er", X86Features::AVX512ER)
.Case("avx512pf", X86Features::AVX512PF)
.Case("avx512vbmi", X86Features::AVX512VBMI)
.Case("avx512ifma", X86Features::AVX512IFMA)
.Default(X86Features::MAX);
X86Features Feature =
StringSwitch<X86Features>(FeatureStr)
.Case("cmov", X86Features::CMOV)
.Case("mmx", X86Features::MMX)
.Case("popcnt", X86Features::POPCNT)
.Case("sse", X86Features::SSE)
.Case("sse2", X86Features::SSE2)
.Case("sse3", X86Features::SSE3)
.Case("ssse3", X86Features::SSSE3)
.Case("sse4.1", X86Features::SSE4_1)
.Case("sse4.2", X86Features::SSE4_2)
.Case("avx", X86Features::AVX)
.Case("avx2", X86Features::AVX2)
.Case("sse4a", X86Features::SSE4_A)
.Case("fma4", X86Features::FMA4)
.Case("xop", X86Features::XOP)
.Case("fma", X86Features::FMA)
.Case("avx512f", X86Features::AVX512F)
.Case("bmi", X86Features::BMI)
.Case("bmi2", X86Features::BMI2)
.Case("aes", X86Features::AES)
.Case("pclmul", X86Features::PCLMUL)
.Case("avx512vl", X86Features::AVX512VL)
.Case("avx512bw", X86Features::AVX512BW)
.Case("avx512dq", X86Features::AVX512DQ)
.Case("avx512cd", X86Features::AVX512CD)
.Case("avx512er", X86Features::AVX512ER)
.Case("avx512pf", X86Features::AVX512PF)
.Case("avx512vbmi", X86Features::AVX512VBMI)
.Case("avx512ifma", X86Features::AVX512IFMA)
.Case("avx512vpopcntdq", X86Features::AVX512VPOPCNTDQ)
.Default(X86Features::MAX);
assert(Feature != X86Features::MAX && "Invalid feature!");
// Matching the struct layout from the compiler-rt/libgcc structure that is
@ -7517,7 +7520,12 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_storesd128_mask: {
return EmitX86MaskedStore(*this, Ops, 16);
}
case X86::BI__builtin_ia32_vpopcntd_512:
case X86::BI__builtin_ia32_vpopcntq_512: {
llvm::Type *ResultType = ConvertType(E->getType());
llvm::Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ResultType);
return Builder.CreateCall(F, Ops);
}
case X86::BI__builtin_ia32_cvtmask2b128:
case X86::BI__builtin_ia32_cvtmask2b256:
case X86::BI__builtin_ia32_cvtmask2b512:
@ -8442,6 +8450,80 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(F, Ops);
}
}
case PPC::BI__builtin_vsx_xxpermdi: {
ConstantInt *ArgCI = dyn_cast<ConstantInt>(Ops[2]);
assert(ArgCI && "Third arg must be constant integer!");
unsigned Index = ArgCI->getZExtValue();
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int64Ty, 2));
Ops[1] = Builder.CreateBitCast(Ops[1], llvm::VectorType::get(Int64Ty, 2));
// Element zero comes from the first input vector and element one comes from
// the second. The element indices within each vector are numbered in big
// endian order so the shuffle mask must be adjusted for this on little
// endian platforms (i.e. index is complemented and source vector reversed).
unsigned ElemIdx0;
unsigned ElemIdx1;
if (getTarget().isLittleEndian()) {
ElemIdx0 = (~Index & 1) + 2;
ElemIdx1 = (~Index & 2) >> 1;
} else { // BigEndian
ElemIdx0 = (Index & 2) >> 1;
ElemIdx1 = 2 + (Index & 1);
}
Constant *ShuffleElts[2] = {ConstantInt::get(Int32Ty, ElemIdx0),
ConstantInt::get(Int32Ty, ElemIdx1)};
Constant *ShuffleMask = llvm::ConstantVector::get(ShuffleElts);
Value *ShuffleCall =
Builder.CreateShuffleVector(Ops[0], Ops[1], ShuffleMask);
QualType BIRetType = E->getType();
auto RetTy = ConvertType(BIRetType);
return Builder.CreateBitCast(ShuffleCall, RetTy);
}
case PPC::BI__builtin_vsx_xxsldwi: {
ConstantInt *ArgCI = dyn_cast<ConstantInt>(Ops[2]);
assert(ArgCI && "Third argument must be a compile time constant");
unsigned Index = ArgCI->getZExtValue() & 0x3;
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int32Ty, 4));
Ops[1] = Builder.CreateBitCast(Ops[1], llvm::VectorType::get(Int32Ty, 4));
// Create a shuffle mask
unsigned ElemIdx0;
unsigned ElemIdx1;
unsigned ElemIdx2;
unsigned ElemIdx3;
if (getTarget().isLittleEndian()) {
// Little endian element N comes from element 8+N-Index of the
// concatenated wide vector (of course, using modulo arithmetic on
// the total number of elements).
ElemIdx0 = (8 - Index) % 8;
ElemIdx1 = (9 - Index) % 8;
ElemIdx2 = (10 - Index) % 8;
ElemIdx3 = (11 - Index) % 8;
} else {
// Big endian ElemIdx<N> = Index + N
ElemIdx0 = Index;
ElemIdx1 = Index + 1;
ElemIdx2 = Index + 2;
ElemIdx3 = Index + 3;
}
Constant *ShuffleElts[4] = {ConstantInt::get(Int32Ty, ElemIdx0),
ConstantInt::get(Int32Ty, ElemIdx1),
ConstantInt::get(Int32Ty, ElemIdx2),
ConstantInt::get(Int32Ty, ElemIdx3)};
Constant *ShuffleMask = llvm::ConstantVector::get(ShuffleElts);
Value *ShuffleCall =
Builder.CreateShuffleVector(Ops[0], Ops[1], ShuffleMask);
QualType BIRetType = E->getType();
auto RetTy = ConvertType(BIRetType);
return Builder.CreateBitCast(ShuffleCall, RetTy);
}
}
}

View File

@ -11,9 +11,11 @@
//
//===----------------------------------------------------------------------===//
#include "CGCleanup.h"
#include "CodeGenFunction.h"
#include "llvm/ADT/ScopeExit.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtVisitor.h"
using namespace clang;
using namespace CodeGen;
@ -57,6 +59,15 @@ struct clang::CodeGen::CGCoroData {
// builtin.
llvm::CallInst *CoroId = nullptr;
// Stores the llvm.coro.begin emitted in the function so that we can replace
// all coro.frame intrinsics with direct SSA value of coro.begin that returns
// the address of the coroutine frame of the current coroutine.
llvm::CallInst *CoroBegin = nullptr;
// Stores the last emitted coro.free for the deallocate expressions, we use it
// to wrap dealloc code with if(auto mem = coro.free) dealloc(mem).
llvm::CallInst *LastCoroFree = nullptr;
// If coro.id came from the builtin, remember the expression to give better
// diagnostic. If CoroIdExpr is nullptr, the coro.id was created by
// EmitCoroutineBody.
@ -142,6 +153,20 @@ static RValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro,
AwaitKind Kind, AggValueSlot aggSlot,
bool ignoreResult) {
auto *E = S.getCommonExpr();
// FIXME: rsmith 5/22/2017. Does it still make sense for us to have a
// UO_Coawait at all? As I recall, the only purpose it ever had was to
// represent a dependent co_await expression that couldn't yet be resolved to
// a CoawaitExpr. But now we have (and need!) a separate DependentCoawaitExpr
// node to store unqualified lookup results, it seems that the UnaryOperator
// portion of the representation serves no purpose (and as seen in this patch,
// it's getting in the way). Can we remove it?
// Skip passthrough operator co_await (present when awaiting on an LValue).
if (auto *UO = dyn_cast<UnaryOperator>(E))
if (UO->getOpcode() == UO_Coawait)
E = UO->getSubExpr();
auto Binder =
CodeGenFunction::OpaqueValueMappingData::bind(CGF, S.getOpaqueValue(), E);
auto UnbindOnExit = llvm::make_scope_exit([&] { Binder.unbind(CGF); });
@ -215,7 +240,67 @@ void CodeGenFunction::EmitCoreturnStmt(CoreturnStmt const &S) {
EmitBranchThroughCleanup(CurCoro.Data->FinalJD);
}
// For WinEH exception representation backend need to know what funclet coro.end
// Hunts for the parameter reference in the parameter copy/move declaration.
namespace {
struct GetParamRef : public StmtVisitor<GetParamRef> {
public:
DeclRefExpr *Expr = nullptr;
GetParamRef() {}
void VisitDeclRefExpr(DeclRefExpr *E) {
assert(Expr == nullptr && "multilple declref in param move");
Expr = E;
}
void VisitStmt(Stmt *S) {
for (auto *C : S->children()) {
if (C)
Visit(C);
}
}
};
}
// This class replaces references to parameters to their copies by changing
// the addresses in CGF.LocalDeclMap and restoring back the original values in
// its destructor.
namespace {
struct ParamReferenceReplacerRAII {
CodeGenFunction::DeclMapTy SavedLocals;
CodeGenFunction::DeclMapTy& LocalDeclMap;
ParamReferenceReplacerRAII(CodeGenFunction::DeclMapTy &LocalDeclMap)
: LocalDeclMap(LocalDeclMap) {}
void addCopy(DeclStmt const *PM) {
// Figure out what param it refers to.
assert(PM->isSingleDecl());
VarDecl const*VD = static_cast<VarDecl const*>(PM->getSingleDecl());
Expr const *InitExpr = VD->getInit();
GetParamRef Visitor;
Visitor.Visit(const_cast<Expr*>(InitExpr));
assert(Visitor.Expr);
auto *DREOrig = cast<DeclRefExpr>(Visitor.Expr);
auto *PD = DREOrig->getDecl();
auto it = LocalDeclMap.find(PD);
assert(it != LocalDeclMap.end() && "parameter is not found");
SavedLocals.insert({ PD, it->second });
auto copyIt = LocalDeclMap.find(VD);
assert(copyIt != LocalDeclMap.end() && "parameter copy is not found");
it->second = copyIt->getSecond();
}
~ParamReferenceReplacerRAII() {
for (auto&& SavedLocal : SavedLocals) {
LocalDeclMap.insert({SavedLocal.first, SavedLocal.second});
}
}
};
}
// For WinEH exception representation backend needs to know what funclet coro.end
// belongs to. That information is passed in a funclet bundle.
static SmallVector<llvm::OperandBundleDef, 1>
getBundlesForCoroEnd(CodeGenFunction &CGF) {
@ -257,24 +342,135 @@ namespace {
struct CallCoroDelete final : public EHScopeStack::Cleanup {
Stmt *Deallocate;
// TODO: Wrap deallocate in if(coro.free(...)) Deallocate.
// Emit "if (coro.free(CoroId, CoroBegin)) Deallocate;"
// Note: That deallocation will be emitted twice: once for a normal exit and
// once for exceptional exit. This usage is safe because Deallocate does not
// contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr()
// builds a single call to a deallocation function which is safe to emit
// multiple times.
void Emit(CodeGenFunction &CGF, Flags) override {
// Note: That deallocation will be emitted twice: once for a normal exit and
// once for exceptional exit. This usage is safe because Deallocate does not
// contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr()
// builds a single call to a deallocation function which is safe to emit
// multiple times.
// Remember the current point, as we are going to emit deallocation code
// first to get to coro.free instruction that is an argument to a delete
// call.
BasicBlock *SaveInsertBlock = CGF.Builder.GetInsertBlock();
auto *FreeBB = CGF.createBasicBlock("coro.free");
CGF.EmitBlock(FreeBB);
CGF.EmitStmt(Deallocate);
auto *AfterFreeBB = CGF.createBasicBlock("after.coro.free");
CGF.EmitBlock(AfterFreeBB);
// We should have captured coro.free from the emission of deallocate.
auto *CoroFree = CGF.CurCoro.Data->LastCoroFree;
if (!CoroFree) {
CGF.CGM.Error(Deallocate->getLocStart(),
"Deallocation expressoin does not refer to coro.free");
return;
}
// Get back to the block we were originally and move coro.free there.
auto *InsertPt = SaveInsertBlock->getTerminator();
CoroFree->moveBefore(InsertPt);
CGF.Builder.SetInsertPoint(InsertPt);
// Add if (auto *mem = coro.free) Deallocate;
auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy);
auto *Cond = CGF.Builder.CreateICmpNE(CoroFree, NullPtr);
CGF.Builder.CreateCondBr(Cond, FreeBB, AfterFreeBB);
// No longer need old terminator.
InsertPt->eraseFromParent();
CGF.Builder.SetInsertPoint(AfterFreeBB);
}
explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}
};
}
namespace {
struct GetReturnObjectManager {
CodeGenFunction &CGF;
CGBuilderTy &Builder;
const CoroutineBodyStmt &S;
Address GroActiveFlag;
CodeGenFunction::AutoVarEmission GroEmission;
GetReturnObjectManager(CodeGenFunction &CGF, const CoroutineBodyStmt &S)
: CGF(CGF), Builder(CGF.Builder), S(S), GroActiveFlag(Address::invalid()),
GroEmission(CodeGenFunction::AutoVarEmission::invalid()) {}
// The gro variable has to outlive coroutine frame and coroutine promise, but,
// it can only be initialized after coroutine promise was created, thus, we
// split its emission in two parts. EmitGroAlloca emits an alloca and sets up
// cleanups. Later when coroutine promise is available we initialize the gro
// and sets the flag that the cleanup is now active.
void EmitGroAlloca() {
auto *GroDeclStmt = dyn_cast<DeclStmt>(S.getResultDecl());
if (!GroDeclStmt) {
// If get_return_object returns void, no need to do an alloca.
return;
}
auto *GroVarDecl = cast<VarDecl>(GroDeclStmt->getSingleDecl());
// Set GRO flag that it is not initialized yet
GroActiveFlag =
CGF.CreateTempAlloca(Builder.getInt1Ty(), CharUnits::One(), "gro.active");
Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl);
// Remember the top of EHStack before emitting the cleanup.
auto old_top = CGF.EHStack.stable_begin();
CGF.EmitAutoVarCleanups(GroEmission);
auto top = CGF.EHStack.stable_begin();
// Make the cleanup conditional on gro.active
for (auto b = CGF.EHStack.find(top), e = CGF.EHStack.find(old_top);
b != e; b++) {
if (auto *Cleanup = dyn_cast<EHCleanupScope>(&*b)) {
assert(!Cleanup->hasActiveFlag() && "cleanup already has active flag?");
Cleanup->setActiveFlag(GroActiveFlag);
Cleanup->setTestFlagInEHCleanup();
Cleanup->setTestFlagInNormalCleanup();
}
}
}
void EmitGroInit() {
if (!GroActiveFlag.isValid()) {
// No Gro variable was allocated. Simply emit the call to
// get_return_object.
CGF.EmitStmt(S.getResultDecl());
return;
}
CGF.EmitAutoVarInit(GroEmission);
Builder.CreateStore(Builder.getTrue(), GroActiveFlag);
}
};
}
static void emitBodyAndFallthrough(CodeGenFunction &CGF,
const CoroutineBodyStmt &S, Stmt *Body) {
CGF.EmitStmt(Body);
const bool CanFallthrough = CGF.Builder.GetInsertBlock();
if (CanFallthrough)
if (Stmt *OnFallthrough = S.getFallthroughHandler())
CGF.EmitStmt(OnFallthrough);
}
void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
auto &TI = CGM.getContext().getTargetInfo();
unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth();
auto *EntryBB = Builder.GetInsertBlock();
auto *AllocBB = createBasicBlock("coro.alloc");
auto *InitBB = createBasicBlock("coro.init");
auto *FinalBB = createBasicBlock("coro.final");
auto *RetBB = createBasicBlock("coro.ret");
@ -284,12 +480,20 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
createCoroData(*this, CurCoro, CoroId);
CurCoro.Data->SuspendBB = RetBB;
// Backend is allowed to elide memory allocations, to help it, emit
// auto mem = coro.alloc() ? 0 : ... allocation code ...;
auto *CoroAlloc = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::coro_alloc), {CoroId});
Builder.CreateCondBr(CoroAlloc, AllocBB, InitBB);
EmitBlock(AllocBB);
auto *AllocateCall = EmitScalarExpr(S.getAllocate());
auto *AllocOrInvokeContBB = Builder.GetInsertBlock();
// Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided.
if (auto *RetOnAllocFailure = S.getReturnStmtOnAllocFailure()) {
auto *RetOnFailureBB = createBasicBlock("coro.ret.on.failure");
auto *InitBB = createBasicBlock("coro.init");
// See if allocation was successful.
auto *NullPtr = llvm::ConstantPointerNull::get(Int8PtrTy);
@ -299,40 +503,96 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
// If not, return OnAllocFailure object.
EmitBlock(RetOnFailureBB);
EmitStmt(RetOnAllocFailure);
EmitBlock(InitBB);
}
else {
Builder.CreateBr(InitBB);
}
EmitBlock(InitBB);
// Pass the result of the allocation to coro.begin.
auto *Phi = Builder.CreatePHI(VoidPtrTy, 2);
Phi->addIncoming(NullPtr, EntryBB);
Phi->addIncoming(AllocateCall, AllocOrInvokeContBB);
auto *CoroBegin = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::coro_begin), {CoroId, Phi});
CurCoro.Data->CoroBegin = CoroBegin;
GetReturnObjectManager GroManager(*this, S);
GroManager.EmitGroAlloca();
CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB);
{
ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap);
CodeGenFunction::RunCleanupsScope ResumeScope(*this);
EHStack.pushCleanup<CallCoroDelete>(NormalAndEHCleanup, S.getDeallocate());
// Create parameter copies. We do it before creating a promise, since an
// evolution of coroutine TS may allow promise constructor to observe
// parameter copies.
for (auto *PM : S.getParamMoves()) {
EmitStmt(PM);
ParamReplacer.addCopy(cast<DeclStmt>(PM));
// TODO: if(CoroParam(...)) need to surround ctor and dtor
// for the copy, so that llvm can elide it if the copy is
// not needed.
}
EmitStmt(S.getPromiseDeclStmt());
Address PromiseAddr = GetAddrOfLocalVar(S.getPromiseDecl());
auto *PromiseAddrVoidPtr =
new llvm::BitCastInst(PromiseAddr.getPointer(), VoidPtrTy, "", CoroId);
// Update CoroId to refer to the promise. We could not do it earlier because
// promise local variable was not emitted yet.
CoroId->setArgOperand(1, PromiseAddrVoidPtr);
// Now we have the promise, initialize the GRO
GroManager.EmitGroInit();
EHStack.pushCleanup<CallCoroEnd>(EHCleanup);
CurCoro.Data->CurrentAwaitKind = AwaitKind::Init;
EmitStmt(S.getInitSuspendStmt());
CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
// FIXME: Emit initial suspend and more before the body.
CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
EmitStmt(S.getBody());
if (auto *OnException = S.getExceptionHandler()) {
auto Loc = S.getLocStart();
CXXCatchStmt Catch(Loc, /*exDecl=*/nullptr, OnException);
auto *TryStmt = CXXTryStmt::Create(getContext(), Loc, S.getBody(), &Catch);
EnterCXXTryStmt(*TryStmt);
emitBodyAndFallthrough(*this, S, TryStmt->getTryBlock());
ExitCXXTryStmt(*TryStmt);
}
else {
emitBodyAndFallthrough(*this, S, S.getBody());
}
// See if we need to generate final suspend.
const bool CanFallthrough = Builder.GetInsertBlock();
const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0;
if (CanFallthrough || HasCoreturns) {
EmitBlock(FinalBB);
// FIXME: Emit final suspend.
CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
EmitStmt(S.getFinalSuspendStmt());
}
else {
// We don't need FinalBB. Emit it to make sure the block is deleted.
EmitBlock(FinalBB, /*IsFinished=*/true);
}
}
EmitBlock(RetBB);
// Emit coro.end before getReturnStmt (and parameter destructors), since
// resume and destroy parts of the coroutine should not include them.
llvm::Function *CoroEnd = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
Builder.CreateCall(CoroEnd, {NullPtr, Builder.getFalse()});
// FIXME: Emit return for the coroutine return object.
if (Stmt *Ret = S.getReturnStmt())
EmitStmt(Ret);
}
// Emit coroutine intrinsic and patch up arguments of the token type.
@ -342,6 +602,17 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E,
switch (IID) {
default:
break;
// The coro.frame builtin is replaced with an SSA value of the coro.begin
// intrinsic.
case llvm::Intrinsic::coro_frame: {
if (CurCoro.Data && CurCoro.Data->CoroBegin) {
return RValue::get(CurCoro.Data->CoroBegin);
}
CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_begin "
"has been used earlier in this function");
auto NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
return RValue::get(NullPtr);
}
// The following three intrinsics take a token parameter referring to a token
// returned by earlier call to @llvm.coro.id. Since we cannot represent it in
// builtins, we patch it up here.
@ -368,10 +639,22 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E,
llvm::Value *F = CGM.getIntrinsic(IID);
llvm::CallInst *Call = Builder.CreateCall(F, Args);
// Note: The following code is to enable to emit coro.id and coro.begin by
// hand to experiment with coroutines in C.
// If we see @llvm.coro.id remember it in the CoroData. We will update
// coro.alloc, coro.begin and coro.free intrinsics to refer to it.
if (IID == llvm::Intrinsic::coro_id) {
createCoroData(*this, CurCoro, Call, E);
}
else if (IID == llvm::Intrinsic::coro_begin) {
if (CurCoro.Data)
CurCoro.Data->CoroBegin = Call;
}
else if (IID == llvm::Intrinsic::coro_free) {
// Remember the last coro_free as we need it to build the conditional
// deletion of the coroutine frame.
if (CurCoro.Data)
CurCoro.Data->LastCoroFree = Call;
}
return RValue::get(Call);
}

View File

@ -1432,11 +1432,12 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
Load->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
}
if (TBAAInfo) {
llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo,
TBAAOffset);
if (TBAAPath)
CGM.DecorateInstructionWithTBAA(Load, TBAAPath,
false /*ConvertTypeToTag*/);
bool MayAlias = BaseInfo.getMayAlias();
llvm::MDNode *TBAA = MayAlias
? CGM.getTBAAInfo(getContext().CharTy)
: CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, TBAAOffset);
if (TBAA)
CGM.DecorateInstructionWithTBAA(Load, TBAA, MayAlias);
}
if (EmitScalarRangeCheck(Load, Ty, Loc)) {
@ -1522,11 +1523,12 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,
Store->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
}
if (TBAAInfo) {
llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo,
TBAAOffset);
if (TBAAPath)
CGM.DecorateInstructionWithTBAA(Store, TBAAPath,
false /*ConvertTypeToTag*/);
bool MayAlias = BaseInfo.getMayAlias();
llvm::MDNode *TBAA = MayAlias
? CGM.getTBAAInfo(getContext().CharTy)
: CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, TBAAOffset);
if (TBAA)
CGM.DecorateInstructionWithTBAA(Store, TBAA, MayAlias);
}
}
@ -3535,6 +3537,11 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
getFieldAlignmentSource(BaseInfo.getAlignmentSource());
LValueBaseInfo FieldBaseInfo(fieldAlignSource, BaseInfo.getMayAlias());
const RecordDecl *rec = field->getParent();
if (rec->isUnion() || rec->hasAttr<MayAliasAttr>())
FieldBaseInfo.setMayAlias(true);
bool mayAlias = FieldBaseInfo.getMayAlias();
if (field->isBitField()) {
const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(field->getParent());
@ -3556,11 +3563,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
return LValue::MakeBitfield(Addr, Info, fieldType, FieldBaseInfo);
}
const RecordDecl *rec = field->getParent();
QualType type = field->getType();
bool mayAlias = rec->hasAttr<MayAliasAttr>();
Address addr = base.getAddress();
unsigned cvr = base.getVRQualifiers();
bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA;

View File

@ -760,6 +760,7 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule());
CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
Fn->removeFnAttr(llvm::Attribute::NoInline);
Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
Fn->addFnAttr(llvm::Attribute::AlwaysInline);
CodeGenFunction CGF(CGM);
// Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
@ -2903,6 +2904,19 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
Desc);
CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
});
if (CGM.supportsCOMDAT()) {
// It is sufficient to call registration function only once, so create a
// COMDAT group for registration/unregistration functions and associated
// data. That would reduce startup time and code size. Registration
// function serves as a COMDAT group key.
auto ComdatKey = M.getOrInsertComdat(RegFn->getName());
RegFn->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage);
RegFn->setVisibility(llvm::GlobalValue::HiddenVisibility);
RegFn->setComdat(ComdatKey);
UnRegFn->setComdat(ComdatKey);
DeviceImages->setComdat(ComdatKey);
Desc->setComdat(ComdatKey);
}
return RegFn;
}
@ -3502,6 +3516,7 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
TaskPrivatesMapFnInfo);
TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
CodeGenFunction CGF(CGM);
CGF.disableDebugInfo();

View File

@ -861,6 +861,7 @@ llvm::Value *CGOpenMPRuntimeNVPTX::emitTeamsOutlinedFunction(
D, ThreadIDVar, InnermostKind, CodeGen);
llvm::Function *OutlinedFun = cast<llvm::Function>(OutlinedFunVal);
OutlinedFun->removeFnAttr(llvm::Attribute::NoInline);
OutlinedFun->removeFnAttr(llvm::Attribute::OptimizeNone);
OutlinedFun->addFnAttr(llvm::Attribute::AlwaysInline);
return OutlinedFun;
@ -1243,10 +1244,10 @@ static void emitReductionListCopy(
/// local = local @ remote
/// else
/// local = remote
llvm::Value *emitReduceScratchpadFunction(CodeGenModule &CGM,
ArrayRef<const Expr *> Privates,
QualType ReductionArrayTy,
llvm::Value *ReduceFn) {
static llvm::Value *
emitReduceScratchpadFunction(CodeGenModule &CGM,
ArrayRef<const Expr *> Privates,
QualType ReductionArrayTy, llvm::Value *ReduceFn) {
auto &C = CGM.getContext();
auto Int32Ty = C.getIntTypeForBitwidth(32, /* Signed */ true);
@ -1372,9 +1373,9 @@ llvm::Value *emitReduceScratchpadFunction(CodeGenModule &CGM,
/// for elem in Reduce List:
/// scratchpad[elem_id][index] = elem
///
llvm::Value *emitCopyToScratchpad(CodeGenModule &CGM,
ArrayRef<const Expr *> Privates,
QualType ReductionArrayTy) {
static llvm::Value *emitCopyToScratchpad(CodeGenModule &CGM,
ArrayRef<const Expr *> Privates,
QualType ReductionArrayTy) {
auto &C = CGM.getContext();
auto Int32Ty = C.getIntTypeForBitwidth(32, /* Signed */ true);

View File

@ -400,8 +400,11 @@ void CodeGenModule::Release() {
}
if (OpenMPRuntime)
if (llvm::Function *OpenMPRegistrationFunction =
OpenMPRuntime->emitRegistrationFunction())
AddGlobalCtor(OpenMPRegistrationFunction, 0);
OpenMPRuntime->emitRegistrationFunction()) {
auto ComdatKey = OpenMPRegistrationFunction->hasComdat() ?
OpenMPRegistrationFunction : nullptr;
AddGlobalCtor(OpenMPRegistrationFunction, 0, ComdatKey);
}
if (PGOReader) {
getModule().setProfileSummary(PGOReader->getSummary().getMD(VMContext));
if (PGOStats.hasDiagnostics())
@ -904,7 +907,16 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
return;
}
if (D->hasAttr<OptimizeNoneAttr>()) {
// Track whether we need to add the optnone LLVM attribute,
// starting with the default for this optimization level.
bool ShouldAddOptNone =
!CodeGenOpts.DisableO0ImplyOptNone && CodeGenOpts.OptimizationLevel == 0;
// We can't add optnone in the following cases, it won't pass the verifier.
ShouldAddOptNone &= !D->hasAttr<MinSizeAttr>();
ShouldAddOptNone &= !F->hasFnAttribute(llvm::Attribute::AlwaysInline);
ShouldAddOptNone &= !D->hasAttr<AlwaysInlineAttr>();
if (ShouldAddOptNone || D->hasAttr<OptimizeNoneAttr>()) {
B.addAttribute(llvm::Attribute::OptimizeNone);
// OptimizeNone implies noinline; we should not be inlining such functions.
@ -958,7 +970,8 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
// function.
if (!D->hasAttr<OptimizeNoneAttr>()) {
if (D->hasAttr<ColdAttr>()) {
B.addAttribute(llvm::Attribute::OptimizeForSize);
if (!ShouldAddOptNone)
B.addAttribute(llvm::Attribute::OptimizeForSize);
B.addAttribute(llvm::Attribute::Cold);
}
@ -1508,6 +1521,10 @@ bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
case ImbueAttr::ALWAYS:
Fn->addFnAttr("function-instrument", "xray-always");
break;
case ImbueAttr::ALWAYS_ARG1:
Fn->addFnAttr("function-instrument", "xray-always");
Fn->addFnAttr("xray-log-args", "1");
break;
case ImbueAttr::NEVER:
Fn->addFnAttr("function-instrument", "xray-never");
break;

View File

@ -4821,6 +4821,9 @@ class AArch64ABIInfo : public SwiftABIInfo {
bool isSwiftErrorInRegister() const override {
return true;
}
bool isLegalVectorTypeForSwift(CharUnits totalSize, llvm::Type *eltTy,
unsigned elts) const override;
};
class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
@ -4994,6 +4997,17 @@ bool AArch64ABIInfo::isIllegalVectorType(QualType Ty) const {
return false;
}
bool AArch64ABIInfo::isLegalVectorTypeForSwift(CharUnits totalSize,
llvm::Type *eltTy,
unsigned elts) const {
if (!llvm::isPowerOf2_32(elts))
return false;
if (totalSize.getQuantity() != 8 &&
(totalSize.getQuantity() != 16 || elts == 1))
return false;
return true;
}
bool AArch64ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
// Homogeneous aggregates for AAPCS64 must have base types of a floating
// point type or a short-vector type. This is the same as the 32-bit ABI,
@ -5382,6 +5396,8 @@ class ARMABIInfo : public SwiftABIInfo {
bool isSwiftErrorInRegister() const override {
return true;
}
bool isLegalVectorTypeForSwift(CharUnits totalSize, llvm::Type *eltTy,
unsigned elts) const override;
};
class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
@ -5894,6 +5910,20 @@ bool ARMABIInfo::isIllegalVectorType(QualType Ty) const {
return false;
}
bool ARMABIInfo::isLegalVectorTypeForSwift(CharUnits vectorSize,
llvm::Type *eltTy,
unsigned numElts) const {
if (!llvm::isPowerOf2_32(numElts))
return false;
unsigned size = getDataLayout().getTypeStoreSizeInBits(eltTy);
if (size > 64)
return false;
if (vectorSize.getQuantity() != 8 &&
(vectorSize.getQuantity() != 16 || numElts == 1))
return false;
return true;
}
bool ARMABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
// Homogeneous aggregates for AAPCS-VFP must have base types of float,
// double, or 64-bit or 128-bit vectors.

View File

@ -30,6 +30,7 @@ add_clang_library(clangDriver
ToolChains/AMDGPU.cpp
ToolChains/AVR.cpp
ToolChains/Bitrig.cpp
ToolChains/BareMetal.cpp
ToolChains/Clang.cpp
ToolChains/CloudABI.cpp
ToolChains/CommonArgs.cpp

View File

@ -22,6 +22,7 @@
#include "ToolChains/FreeBSD.h"
#include "ToolChains/Fuchsia.h"
#include "ToolChains/Gnu.h"
#include "ToolChains/BareMetal.h"
#include "ToolChains/Haiku.h"
#include "ToolChains/Hexagon.h"
#include "ToolChains/Lanai.h"
@ -598,6 +599,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
bool CCCPrintPhases;
InputArgList Args = ParseArgStrings(ArgList.slice(1));
if (Diags.hasErrorOccurred())
return nullptr;
// Silence driver warnings if requested
Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w));
@ -1216,6 +1219,13 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}
if (Arg *A = C.getArgs().getLastArg(options::OPT_autocomplete)) {
// Print out all options that start with a given argument. This is used for
// shell autocompletion.
llvm::outs() << llvm::join(Opts->findByPrefix(A->getValue()), " ") << '\n';
return false;
}
if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {
ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs());
switch (RLT) {
@ -3819,6 +3829,8 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
if (Target.getVendor() == llvm::Triple::Myriad)
TC = llvm::make_unique<toolchains::MyriadToolChain>(*this, Target,
Args);
else if (toolchains::BareMetal::handlesTarget(Target))
TC = llvm::make_unique<toolchains::BareMetal>(*this, Target, Args);
else if (Target.isOSBinFormatELF())
TC = llvm::make_unique<toolchains::Generic_ELF>(*this, Target, Args);
else if (Target.isOSBinFormatMachO())

View File

@ -0,0 +1,210 @@
//===--- BaremMetal.cpp - Bare Metal ToolChain ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "BareMetal.h"
#include "CommonArgs.h"
#include "InputInfo.h"
#include "Gnu.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm::opt;
using namespace clang;
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
}
BareMetal::~BareMetal() {}
/// Is the triple {arm,thumb}-none-none-{eabi,eabihf} ?
static bool isARMBareMetal(const llvm::Triple &Triple) {
if (Triple.getArch() != llvm::Triple::arm &&
Triple.getArch() != llvm::Triple::thumb)
return false;
if (Triple.getVendor() != llvm::Triple::UnknownVendor)
return false;
if (Triple.getOS() != llvm::Triple::UnknownOS)
return false;
if (Triple.getEnvironment() != llvm::Triple::EABI &&
Triple.getEnvironment() != llvm::Triple::EABIHF)
return false;
return true;
}
bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
return isARMBareMetal(Triple);
}
Tool *BareMetal::buildLinker() const {
return new tools::baremetal::Linker(*this);
}
std::string BareMetal::getThreadModel() const {
return "single";
}
bool BareMetal::isThreadModelSupported(const StringRef Model) const {
return Model == "single";
}
std::string BareMetal::getRuntimesDir() const {
SmallString<128> Dir(getDriver().ResourceDir);
llvm::sys::path::append(Dir, "lib", "baremetal");
return Dir.str();
}
void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> Dir(getDriver().ResourceDir);
llvm::sys::path::append(Dir, "include");
addSystemInclude(DriverArgs, CC1Args, Dir.str());
}
if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
SmallString<128> Dir(getDriver().SysRoot);
llvm::sys::path::append(Dir, "include");
addSystemInclude(DriverArgs, CC1Args, Dir.str());
}
}
void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
CC1Args.push_back("-nostdsysteminc");
}
std::string BareMetal::findLibCxxIncludePath(CXXStdlibType LibType) const {
StringRef SysRoot = getDriver().SysRoot;
if (SysRoot.empty())
return "";
switch (LibType) {
case ToolChain::CST_Libcxx: {
SmallString<128> Dir(SysRoot);
llvm::sys::path::append(Dir, "include", "c++", "v1");
return Dir.str();
}
case ToolChain::CST_Libstdcxx: {
SmallString<128> Dir(SysRoot);
llvm::sys::path::append(Dir, "include", "c++");
std::error_code EC;
Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""};
// Walk the subdirs, and find the one with the newest gcc version:
for (vfs::directory_iterator LI =
getDriver().getVFS().dir_begin(Dir.str(), EC), LE;
!EC && LI != LE; LI = LI.increment(EC)) {
StringRef VersionText = llvm::sys::path::filename(LI->getName());
auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText);
if (CandidateVersion.Major == -1)
continue;
if (CandidateVersion <= Version)
continue;
Version = CandidateVersion;
}
if (Version.Major == -1)
return "";
llvm::sys::path::append(Dir, Version.Text);
return Dir.str();
}
}
llvm_unreachable("unhandled LibType");
}
void BareMetal::AddClangCXXStdlibIncludeArgs(
const ArgList &DriverArgs, ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc) ||
DriverArgs.hasArg(options::OPT_nostdlibinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
std::string Path = findLibCxxIncludePath(GetCXXStdlibType(DriverArgs));
if (!Path.empty())
addSystemInclude(DriverArgs, CC1Args, Path);
}
void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
CmdArgs.push_back("-lc++abi");
break;
case ToolChain::CST_Libstdcxx:
CmdArgs.push_back("-lstdc++");
CmdArgs.push_back("-lsupc++");
break;
}
CmdArgs.push_back("-lunwind");
}
void BareMetal::AddLinkRuntimeLib(const ArgList &Args,
ArgStringList &CmdArgs) const {
CmdArgs.push_back(Args.MakeArgString("-lclang_rt.builtins-" +
getTriple().getArchName() + ".a"));
}
void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
auto &TC = static_cast<const toolchains::BareMetal&>(getToolChain());
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
CmdArgs.push_back("-Bstatic");
CmdArgs.push_back(Args.MakeArgString("-L" + TC.getRuntimesDir()));
Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
options::OPT_e, options::OPT_s, options::OPT_t,
options::OPT_Z_Flag, options::OPT_r});
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (C.getDriver().CCCIsCXX())
TC.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lm");
TC.AddLinkRuntimeLib(Args, CmdArgs);
}
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
C.addCommand(llvm::make_unique<Command>(JA, *this,
Args.MakeArgString(TC.GetLinkerPath()),
CmdArgs, Inputs));
}

View File

@ -0,0 +1,90 @@
//===--- BareMetal.h - Bare Metal Tool and ToolChain -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_BAREMETAL_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_BAREMETAL_H
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include <string>
namespace clang {
namespace driver {
namespace toolchains {
class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
public:
BareMetal(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
~BareMetal() override;
static bool handlesTarget(const llvm::Triple &Triple);
protected:
Tool *buildLinker() const override;
public:
bool useIntegratedAs() const override { return true; }
bool isCrossCompiling() const override { return true; }
bool isPICDefault() const override { return false; }
bool isPIEDefault() const override { return false; }
bool isPICDefaultForced() const override { return false; }
bool SupportsProfiling() const override { return false; }
bool SupportsObjCGC() const override { return false; }
std::string getThreadModel() const override;
bool isThreadModelSupported(const StringRef Model) const override;
RuntimeLibType GetDefaultRuntimeLibType() const override {
return ToolChain::RLT_CompilerRT;
}
CXXStdlibType GetDefaultCXXStdlibType() const override {
return ToolChain::CST_Libcxx;
}
const char *getDefaultLinker() const override { return "ld.lld"; }
std::string getRuntimesDir() const;
void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
std::string findLibCxxIncludePath(ToolChain::CXXStdlibType LibType) const;
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
};
} // namespace toolchains
namespace tools {
namespace baremetal {
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
Linker(const ToolChain &TC) : Tool("baremetal::Linker", "ld.lld", TC) {}
bool isLinkJob() const override { return true; }
bool hasIntegratedCPP() const override { return false; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
} // namespace baremetal
} // namespace tools
} // namespace driver
} // namespace clang
#endif

View File

@ -1598,6 +1598,49 @@ bool Generic_GCC::GCCVersion::isOlderThan(int RHSMajor, int RHSMinor,
return false;
}
/// \brief Parse a GCCVersion object out of a string of text.
///
/// This is the primary means of forming GCCVersion objects.
/*static*/
Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) {
const GCCVersion BadVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
std::pair<StringRef, StringRef> First = VersionText.split('.');
std::pair<StringRef, StringRef> Second = First.second.split('.');
GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
if (First.first.getAsInteger(10, GoodVersion.Major) || GoodVersion.Major < 0)
return BadVersion;
GoodVersion.MajorStr = First.first.str();
if (First.second.empty())
return GoodVersion;
if (Second.first.getAsInteger(10, GoodVersion.Minor) || GoodVersion.Minor < 0)
return BadVersion;
GoodVersion.MinorStr = Second.first.str();
// First look for a number prefix and parse that if present. Otherwise just
// stash the entire patch string in the suffix, and leave the number
// unspecified. This covers versions strings such as:
// 5 (handled above)
// 4.4
// 4.4.0
// 4.4.x
// 4.4.2-rc4
// 4.4.x-patched
// And retains any patch number it finds.
StringRef PatchText = GoodVersion.PatchSuffix = Second.second.str();
if (!PatchText.empty()) {
if (size_t EndNumber = PatchText.find_first_not_of("0123456789")) {
// Try to parse the number and any suffix.
if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) ||
GoodVersion.Patch < 0)
return BadVersion;
GoodVersion.PatchSuffix = PatchText.substr(EndNumber);
}
}
return GoodVersion;
}
static llvm::StringRef getGCCToolchainDir(const ArgList &Args) {
const Arg *A = Args.getLastArg(clang::driver::options::OPT_gcc_toolchain);
if (A)

View File

@ -372,49 +372,6 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
addPathIfExists(D, SysRoot + "/usr/lib", Paths);
}
/// \brief Parse a GCCVersion object out of a string of text.
///
/// This is the primary means of forming GCCVersion objects.
/*static*/
Generic_GCC::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) {
const GCCVersion BadVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
std::pair<StringRef, StringRef> First = VersionText.split('.');
std::pair<StringRef, StringRef> Second = First.second.split('.');
GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
if (First.first.getAsInteger(10, GoodVersion.Major) || GoodVersion.Major < 0)
return BadVersion;
GoodVersion.MajorStr = First.first.str();
if (First.second.empty())
return GoodVersion;
if (Second.first.getAsInteger(10, GoodVersion.Minor) || GoodVersion.Minor < 0)
return BadVersion;
GoodVersion.MinorStr = Second.first.str();
// First look for a number prefix and parse that if present. Otherwise just
// stash the entire patch string in the suffix, and leave the number
// unspecified. This covers versions strings such as:
// 5 (handled above)
// 4.4
// 4.4.0
// 4.4.x
// 4.4.2-rc4
// 4.4.x-patched
// And retains any patch number it finds.
StringRef PatchText = GoodVersion.PatchSuffix = Second.second.str();
if (!PatchText.empty()) {
if (size_t EndNumber = PatchText.find_first_not_of("0123456789")) {
// Try to parse the number and any suffix.
if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) ||
GoodVersion.Patch < 0)
return BadVersion;
GoodVersion.PatchSuffix = PatchText.substr(EndNumber);
}
}
return GoodVersion;
}
bool Linux::HasNativeLLVMSupport() const { return true; }
Tool *Linux::buildLinker() const { return new tools::gnutools::Linker(*this); }

View File

@ -217,6 +217,7 @@ MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
default:
D.Diag(clang::diag::err_target_unsupported_arch)
<< Triple.getArchName() << "myriad";
LLVM_FALLTHROUGH;
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::shave:

View File

@ -54,13 +54,14 @@ static bool startsNextParameter(const FormatToken &Current,
const FormatStyle &Style) {
const FormatToken &Previous = *Current.Previous;
if (Current.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializersBeforeComma)
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma)
return true;
return Previous.is(tok::comma) && !Current.isTrailingComment() &&
((Previous.isNot(TT_CtorInitializerComma) ||
!Style.BreakConstructorInitializersBeforeComma) &&
Style.BreakConstructorInitializers !=
FormatStyle::BCIS_BeforeComma) &&
(Previous.isNot(TT_InheritanceComma) ||
!Style.BreakBeforeInheritanceComma));
!Style.BreakBeforeInheritanceComma));
}
ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,
@ -178,13 +179,20 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
getLengthToMatchingParen(Previous) + State.Column - 1 >
getColumnLimit(State))
return true;
if (Current.is(TT_CtorInitializerColon) &&
(State.Column + State.Line->Last->TotalLength - Current.TotalLength + 2 >
const FormatToken &BreakConstructorInitializersToken =
Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon
? Previous
: Current;
if (BreakConstructorInitializersToken.is(TT_CtorInitializerColon) &&
(State.Column + State.Line->Last->TotalLength - Previous.TotalLength >
getColumnLimit(State) ||
State.Stack.back().BreakBeforeParameter) &&
((Style.AllowShortFunctionsOnASingleLine != FormatStyle::SFS_All) ||
Style.BreakConstructorInitializersBeforeComma || Style.ColumnLimit != 0))
(Style.AllowShortFunctionsOnASingleLine != FormatStyle::SFS_All ||
Style.BreakConstructorInitializers != FormatStyle::BCIS_BeforeColon ||
Style.ColumnLimit != 0))
return true;
if (Current.is(TT_ObjCMethodExpr) && !Previous.is(TT_SelectorName) &&
State.Line->startsWith(TT_ObjCMethodSpecifier))
return true;
@ -207,7 +215,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
// ...
// }.bind(...));
// FIXME: We should find a more generic solution to this problem.
!(State.Column <= NewLineColumn && Previous.isNot(tok::r_paren) &&
!(State.Column <= NewLineColumn &&
Style.Language == FormatStyle::LK_JavaScript))
return true;
@ -455,6 +463,11 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
!Previous.is(TT_OverloadedOperator)) ||
(Previous.is(tok::colon) && Previous.is(TT_ObjCMethodExpr)))) {
State.Stack.back().LastSpace = State.Column;
} else if (Previous.is(TT_CtorInitializerColon) &&
Style.BreakConstructorInitializers ==
FormatStyle::BCIS_AfterColon) {
State.Stack.back().Indent = State.Column;
State.Stack.back().LastSpace = State.Column;
} else if ((Previous.isOneOf(TT_BinaryOperator, TT_ConditionalExpr,
TT_CtorInitializerColon)) &&
((Previous.getPrecedence() != prec::Assignment &&
@ -614,7 +627,7 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
State.Stack[i].BreakBeforeParameter = true;
if (PreviousNonComment &&
!PreviousNonComment->isOneOf(tok::comma, tok::semi) &&
!PreviousNonComment->isOneOf(tok::comma, tok::colon, tok::semi) &&
(PreviousNonComment->isNot(TT_TemplateCloser) ||
Current.NestingLevel != 0) &&
!PreviousNonComment->isOneOf(
@ -676,7 +689,18 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return State.Stack[State.Stack.size() - 2].LastSpace;
return State.FirstIndent;
}
if (Current.is(tok::r_paren) && State.Stack.size() > 1)
// Indent a closing parenthesis at the previous level if followed by a semi or
// opening brace. This allows indentations such as:
// foo(
// a,
// );
// function foo(
// a,
// ) {
// code(); //
// }
if (Current.is(tok::r_paren) && State.Stack.size() > 1 &&
(!Current.Next || Current.Next->isOneOf(tok::semi, tok::l_brace)))
return State.Stack[State.Stack.size() - 2].LastSpace;
if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope())
return State.Stack[State.Stack.size() - 2].LastSpace;
@ -750,6 +774,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return ContinuationIndent;
if (NextNonComment->is(TT_CtorInitializerComma))
return State.Stack.back().Indent;
if (PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon)
return State.Stack.back().Indent;
if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
TT_InheritanceComma))
return State.FirstIndent + Style.ConstructorInitializerIndentWidth;
@ -810,19 +837,29 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
State.FirstIndent + Style.ContinuationIndentWidth;
}
}
if (Current.is(TT_CtorInitializerColon)) {
if (Current.is(TT_CtorInitializerColon) &&
Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon) {
// Indent 2 from the column, so:
// SomeClass::SomeClass()
// : First(...), ...
// Next(...)
// ^ line up here.
State.Stack.back().Indent =
State.Column + (Style.BreakConstructorInitializersBeforeComma ? 0 : 2);
State.Column + (Style.BreakConstructorInitializers ==
FormatStyle::BCIS_BeforeComma ? 0 : 2);
State.Stack.back().NestedBlockIndent = State.Stack.back().Indent;
if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
State.Stack.back().AvoidBinPacking = true;
State.Stack.back().BreakBeforeParameter = false;
}
if (Current.is(TT_CtorInitializerColon) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon) {
State.Stack.back().Indent =
State.FirstIndent + Style.ConstructorInitializerIndentWidth;
State.Stack.back().NestedBlockIndent = State.Stack.back().Indent;
if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
State.Stack.back().AvoidBinPacking = true;
}
if (Current.is(TT_InheritanceColon))
State.Stack.back().Indent =
State.FirstIndent + Style.ContinuationIndentWidth;

View File

@ -123,6 +123,14 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
}
};
template <> struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
static void enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
}
};
template <>
struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
@ -304,8 +312,19 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
IO.mapOptional("BreakBeforeTernaryOperators",
Style.BreakBeforeTernaryOperators);
bool BreakConstructorInitializersBeforeComma = false;
IO.mapOptional("BreakConstructorInitializersBeforeComma",
Style.BreakConstructorInitializersBeforeComma);
BreakConstructorInitializersBeforeComma);
IO.mapOptional("BreakConstructorInitializers",
Style.BreakConstructorInitializers);
// If BreakConstructorInitializersBeforeComma was specified but
// BreakConstructorInitializers was not, initialize the latter from the
// former for backwards compatibility.
if (BreakConstructorInitializersBeforeComma &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon)
Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
IO.mapOptional("BreakAfterJavaFieldAnnotations",
Style.BreakAfterJavaFieldAnnotations);
IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
@ -537,7 +556,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
false, false, false, false, false};
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializersBeforeComma = false;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakBeforeInheritanceComma = false;
LLVMStyle.BreakStringLiterals = true;
LLVMStyle.ColumnLimit = 80;
@ -694,7 +713,7 @@ FormatStyle getMozillaStyle() {
MozillaStyle.BinPackParameters = false;
MozillaStyle.BinPackArguments = false;
MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
MozillaStyle.BreakConstructorInitializersBeforeComma = true;
MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
MozillaStyle.BreakBeforeInheritanceComma = true;
MozillaStyle.ConstructorInitializerIndentWidth = 2;
MozillaStyle.ContinuationIndentWidth = 2;
@ -717,7 +736,7 @@ FormatStyle getWebKitStyle() {
Style.AlignTrailingComments = false;
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
Style.BreakConstructorInitializersBeforeComma = true;
Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
Style.Cpp11BracedListStyle = false;
Style.ColumnLimit = 0;
Style.FixNamespaceComments = false;
@ -1891,6 +1910,9 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName) {
// cleanups only apply to C++ (they mostly concern ctor commas etc.)
if (Style.Language != FormatStyle::LK_Cpp)
return tooling::Replacements();
std::unique_ptr<Environment> Env =
Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
Cleaner Clean(*Env, Style);

View File

@ -1996,7 +1996,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(tok::comment))
return 1000;
if (Left.isOneOf(TT_RangeBasedForLoopColon, TT_InheritanceColon))
if (Left.isOneOf(TT_RangeBasedForLoopColon, TT_InheritanceColon, TT_CtorInitializerColon))
return 2;
if (Right.isMemberAccess()) {
@ -2514,8 +2514,12 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Right.Previous->MatchingParen->NestingLevel == 0 &&
Style.AlwaysBreakTemplateDeclarations)
return true;
if ((Right.isOneOf(TT_CtorInitializerComma, TT_CtorInitializerColon)) &&
Style.BreakConstructorInitializersBeforeComma &&
if (Right.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&
!Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
return true;
if (Right.is(TT_CtorInitializerColon) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&
!Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
return true;
// Break only if we have multiple inheritance.
@ -2625,7 +2629,10 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
// The first comment in a braced lists is always interpreted as belonging to
// the first list element. Otherwise, it should be placed outside of the
// list.
return Left.BlockKind == BK_BracedInit;
return Left.BlockKind == BK_BracedInit ||
(Left.is(TT_CtorInitializerColon) &&
Style.BreakConstructorInitializers ==
FormatStyle::BCIS_AfterColon);
if (Left.is(tok::question) && Right.is(tok::colon))
return false;
if (Right.is(TT_ConditionalExpr) || Right.is(tok::question))
@ -2698,11 +2705,15 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))
return true;
if (Left.is(TT_CtorInitializerColon))
return Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon;
if (Right.is(TT_CtorInitializerColon))
return Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon;
if (Left.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializersBeforeComma)
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma)
return false;
if (Right.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializersBeforeComma)
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma)
return true;
if (Left.is(TT_InheritanceComma) && Style.BreakBeforeInheritanceComma)
return false;

View File

@ -90,6 +90,21 @@ namespace {
/// \brief Erase temporary files and the preamble file.
void Cleanup();
};
template <class T>
std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) {
if (!Val)
return nullptr;
return std::move(*Val);
}
template <class T>
bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
if (!Val)
return false;
Output = std::move(*Val);
return true;
}
}
static llvm::sys::SmartMutex<false> &getOnDiskMutex() {
@ -1019,7 +1034,8 @@ static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &
/// \returns True if a failure occurred that causes the ASTUnit not to
/// contain any translation-unit information, false otherwise.
bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer) {
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
SavedMainFileBuffer.reset();
if (!Invocation)
@ -1028,6 +1044,12 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// Create the compiler instance to use for building the AST.
std::unique_ptr<CompilerInstance> Clang(
new CompilerInstance(std::move(PCHContainerOps)));
if (FileMgr && VFS) {
assert(VFS == FileMgr->getVirtualFileSystem() &&
"VFS passed to Parse and VFS in FileMgr are different");
} else if (VFS) {
Clang->setVirtualFileSystem(VFS);
}
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
@ -1170,7 +1192,8 @@ static std::string GetPreamblePCHPath() {
/// that corresponds to the main file along with a pair (bytes, start-of-line)
/// that describes the preamble.
ASTUnit::ComputedPreamble
ASTUnit::ComputePreamble(CompilerInvocation &Invocation, unsigned MaxLines) {
ASTUnit::ComputePreamble(CompilerInvocation &Invocation, unsigned MaxLines,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
PreprocessorOptions &PreprocessorOpts = Invocation.getPreprocessorOpts();
@ -1180,28 +1203,32 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation, unsigned MaxLines) {
llvm::MemoryBuffer *Buffer = nullptr;
std::unique_ptr<llvm::MemoryBuffer> BufferOwner;
std::string MainFilePath(FrontendOpts.Inputs[0].getFile());
llvm::sys::fs::UniqueID MainFileID;
if (!llvm::sys::fs::getUniqueID(MainFilePath, MainFileID)) {
auto MainFileStatus = VFS->status(MainFilePath);
if (MainFileStatus) {
llvm::sys::fs::UniqueID MainFileID = MainFileStatus->getUniqueID();
// Check whether there is a file-file remapping of the main file
for (const auto &RF : PreprocessorOpts.RemappedFiles) {
std::string MPath(RF.first);
llvm::sys::fs::UniqueID MID;
if (!llvm::sys::fs::getUniqueID(MPath, MID)) {
auto MPathStatus = VFS->status(MPath);
if (MPathStatus) {
llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();
if (MainFileID == MID) {
// We found a remapping. Try to load the resulting, remapped source.
BufferOwner = getBufferForFile(RF.second);
BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second));
if (!BufferOwner)
return ComputedPreamble(nullptr, nullptr, 0, true);
}
}
}
// Check whether there is a file-buffer remapping. It supercedes the
// file-file remapping.
for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {
std::string MPath(RB.first);
llvm::sys::fs::UniqueID MID;
if (!llvm::sys::fs::getUniqueID(MPath, MID)) {
auto MPathStatus = VFS->status(MPath);
if (MPathStatus) {
llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();
if (MainFileID == MID) {
// We found a remapping.
BufferOwner.reset();
@ -1213,7 +1240,7 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation, unsigned MaxLines) {
// If the main source file was not remapped, load it now.
if (!Buffer && !BufferOwner) {
BufferOwner = getBufferForFile(FrontendOpts.Inputs[0].getFile());
BufferOwner = valueOrNull(VFS->getBufferForFile(FrontendOpts.Inputs[0].getFile()));
if (!BufferOwner)
return ComputedPreamble(nullptr, nullptr, 0, true);
}
@ -1324,8 +1351,10 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts,
std::unique_ptr<llvm::MemoryBuffer>
ASTUnit::getMainBufferWithPrecompiledPreamble(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild,
const CompilerInvocation &PreambleInvocationIn,
IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild,
unsigned MaxLines) {
assert(VFS && "VFS is null");
auto PreambleInvocation =
std::make_shared<CompilerInvocation>(PreambleInvocationIn);
@ -1333,7 +1362,8 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
PreprocessorOptions &PreprocessorOpts
= PreambleInvocation->getPreprocessorOpts();
ComputedPreamble NewPreamble = ComputePreamble(*PreambleInvocation, MaxLines);
ComputedPreamble NewPreamble =
ComputePreamble(*PreambleInvocation, MaxLines, VFS);
if (!NewPreamble.Size) {
// We couldn't find a preamble in the main source. Clear out the current
@ -1369,7 +1399,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
break;
vfs::Status Status;
if (FileMgr->getNoncachedStatValue(R.second, Status)) {
if (!moveOnNoError(VFS->status(R.second), Status)) {
// If we can't stat the file we're remapping to, assume that something
// horrible happened.
AnyFileChanged = true;
@ -1386,7 +1416,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
break;
vfs::Status Status;
if (FileMgr->getNoncachedStatValue(RB.first, Status)) {
if (!moveOnNoError(VFS->status(RB.first), Status)) {
AnyFileChanged = true;
break;
}
@ -1401,7 +1431,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
!AnyFileChanged && F != FEnd;
++F) {
vfs::Status Status;
if (FileMgr->getNoncachedStatValue(F->first(), Status)) {
if (!moveOnNoError(VFS->status(F->first()), Status)) {
// If we can't stat the file, assume that something horrible happened.
AnyFileChanged = true;
break;
@ -1546,14 +1576,14 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
TopLevelDeclsInPreamble.clear();
PreambleDiagnostics.clear();
IntrusiveRefCntPtr<vfs::FileSystem> VFS =
createVFSFromCompilerInvocation(Clang->getInvocation(), getDiagnostics());
VFS = createVFSFromCompilerInvocation(Clang->getInvocation(),
getDiagnostics(), VFS);
if (!VFS)
return nullptr;
// Create a file manager object to provide access to and cache the filesystem.
Clang->setFileManager(new FileManager(Clang->getFileSystemOpts(), VFS));
// Create the source manager.
Clang->setSourceManager(new SourceManager(getDiagnostics(),
Clang->getFileManager()));
@ -1863,10 +1893,13 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
bool ASTUnit::LoadFromCompilerInvocation(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
unsigned PrecompilePreambleAfterNParses) {
unsigned PrecompilePreambleAfterNParses,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
if (!Invocation)
return true;
assert(VFS && "VFS is null");
// We'll manage file buffers ourselves.
Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true;
Invocation->getFrontendOpts().DisableFree = false;
@ -1877,19 +1910,19 @@ bool ASTUnit::LoadFromCompilerInvocation(
if (PrecompilePreambleAfterNParses > 0) {
PreambleRebuildCounter = PrecompilePreambleAfterNParses;
OverrideMainBuffer =
getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation);
getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);
getDiagnostics().Reset();
ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
}
SimpleTimer ParsingTimer(WantTiming);
ParsingTimer.setOutput("Parsing " + getMainFileName());
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer>
MemBufferCleanup(OverrideMainBuffer.get());
return Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer));
return Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);
}
std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
@ -1923,7 +1956,8 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
DiagCleanup(Diags.get());
if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
PrecompilePreambleAfterNParses))
PrecompilePreambleAfterNParses,
AST->FileMgr->getVirtualFileSystem()))
return nullptr;
return AST;
}
@ -1938,7 +1972,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies,
bool UserFilesAreVolatile, bool ForSerialization,
llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST) {
llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
assert(Diags.get() && "no DiagnosticsEngine was provided");
SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
@ -1979,8 +2014,9 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
ConfigureDiags(Diags, *AST, CaptureDiagnostics);
AST->Diagnostics = Diags;
AST->FileSystemOpts = CI->getFileSystemOpts();
IntrusiveRefCntPtr<vfs::FileSystem> VFS =
createVFSFromCompilerInvocation(*CI, *Diags);
if (!VFS)
VFS = vfs::getRealFileSystem();
VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
if (!VFS)
return nullptr;
AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
@ -2006,7 +2042,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
ASTUnitCleanup(AST.get());
if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
PrecompilePreambleAfterNParses)) {
PrecompilePreambleAfterNParses,
VFS)) {
// Some error occurred, if caller wants to examine diagnostics, pass it the
// ASTUnit.
if (ErrAST) {
@ -2020,10 +2057,16 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
}
bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
ArrayRef<RemappedFile> RemappedFiles) {
ArrayRef<RemappedFile> RemappedFiles,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
if (!Invocation)
return true;
if (!VFS) {
assert(FileMgr && "FileMgr is null on Reparse call");
VFS = FileMgr->getVirtualFileSystem();
}
clearFileLevelDecls();
SimpleTimer ParsingTimer(WantTiming);
@ -2045,7 +2088,8 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
if (!getPreambleFile(this).empty() || PreambleRebuildCounter > 0)
OverrideMainBuffer =
getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation);
getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);
// Clear out the diagnostics state.
FileMgr.reset();
@ -2056,7 +2100,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// Parse the sources
bool Result =
Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer));
Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);
// If we're caching global code-completion results, and the top-level
// declarations have changed, clear out the code-completion cache.
@ -2414,15 +2458,19 @@ void ASTUnit::CodeComplete(
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
if (!getPreambleFile(this).empty()) {
std::string CompleteFilePath(File);
llvm::sys::fs::UniqueID CompleteFileID;
if (!llvm::sys::fs::getUniqueID(CompleteFilePath, CompleteFileID)) {
auto VFS = FileMgr.getVirtualFileSystem();
auto CompleteFileStatus = VFS->status(CompleteFilePath);
if (CompleteFileStatus) {
llvm::sys::fs::UniqueID CompleteFileID = CompleteFileStatus->getUniqueID();
std::string MainPath(OriginalSourceFile);
llvm::sys::fs::UniqueID MainID;
if (!llvm::sys::fs::getUniqueID(MainPath, MainID)) {
auto MainStatus = VFS->status(MainPath);
if (MainStatus) {
llvm::sys::fs::UniqueID MainID = MainStatus->getUniqueID();
if (CompleteFileID == MainID && Line > 1)
OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(
PCHContainerOps, Inv, false, Line - 1);
PCHContainerOps, Inv, VFS, false, Line - 1);
}
}
}

View File

@ -534,6 +534,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.DisableLLVMPasses = Args.hasArg(OPT_disable_llvm_passes);
Opts.DisableLifetimeMarkers = Args.hasArg(OPT_disable_lifetimemarkers);
Opts.DisableO0ImplyOptNone = Args.hasArg(OPT_disable_O0_optnone);
Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables);
Opts.UseRegisterSizedBitfieldAccess = Args.hasArg(
@ -1087,6 +1088,9 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Opts.SpellCheckingLimit = getLastArgIntValue(
Args, OPT_fspell_checking_limit,
DiagnosticOptions::DefaultSpellCheckingLimit, Diags);
Opts.SnippetLineLimit = getLastArgIntValue(
Args, OPT_fcaret_diagnostics_max_lines,
DiagnosticOptions::DefaultSnippetLineLimit, Diags);
Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop,
DiagnosticOptions::DefaultTabStop, Diags);
if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
@ -2747,15 +2751,22 @@ void BuryPointer(const void *Ptr) {
IntrusiveRefCntPtr<vfs::FileSystem>
createVFSFromCompilerInvocation(const CompilerInvocation &CI,
DiagnosticsEngine &Diags) {
if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
return vfs::getRealFileSystem();
return createVFSFromCompilerInvocation(CI, Diags, vfs::getRealFileSystem());
}
IntrusiveRefCntPtr<vfs::OverlayFileSystem>
Overlay(new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
IntrusiveRefCntPtr<vfs::FileSystem>
createVFSFromCompilerInvocation(const CompilerInvocation &CI,
DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<vfs::FileSystem> BaseFS) {
if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
return BaseFS;
IntrusiveRefCntPtr<vfs::OverlayFileSystem> Overlay(
new vfs::OverlayFileSystem(BaseFS));
// earlier vfs files are on the bottom
for (const std::string &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
llvm::MemoryBuffer::getFile(File);
BaseFS->getBufferForFile(File);
if (!Buffer) {
Diags.Report(diag::err_missing_vfs_overlay_file) << File;
return IntrusiveRefCntPtr<vfs::FileSystem>();

View File

@ -52,6 +52,8 @@ std::unique_ptr<CompilerInvocation> clang::createInvocationFromCommandLine(
TheDriver.setCheckInputsExist(false);
std::unique_ptr<driver::Compilation> C(TheDriver.BuildCompilation(Args));
if (!C)
return nullptr;
// Just print the cc1 options if -### was present.
if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) {

View File

@ -252,7 +252,8 @@ static SourceLocation ReadOriginalFileName(CompilerInstance &CI,
if (AddLineNote)
CI.getSourceManager().AddLineNote(
LineNoLoc, LineNo, SourceMgr.getLineTableFilenameID(InputFile));
LineNoLoc, LineNo, SourceMgr.getLineTableFilenameID(InputFile), false,
false, SrcMgr::C_User);
return T.getLocation();
}

View File

@ -535,7 +535,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
if (LangOpts.ConceptsTS)
Builder.defineMacro("__cpp_experimental_concepts", "1");
if (LangOpts.CoroutinesTS)
Builder.defineMacro("__cpp_coroutines", "1");
Builder.defineMacro("__cpp_coroutines", "201703L");
}
static void InitializePredefinedMacros(const TargetInfo &TI,

View File

@ -928,6 +928,56 @@ void TextDiagnostic::emitBuildingModuleLocation(SourceLocation Loc,
OS << "While building module '" << ModuleName << "':\n";
}
/// \brief Find the suitable set of lines to show to include a set of ranges.
static llvm::Optional<std::pair<unsigned, unsigned>>
findLinesForRange(const CharSourceRange &R, FileID FID,
const SourceManager &SM) {
if (!R.isValid()) return None;
SourceLocation Begin = R.getBegin();
SourceLocation End = R.getEnd();
if (SM.getFileID(Begin) != FID || SM.getFileID(End) != FID)
return None;
return std::make_pair(SM.getExpansionLineNumber(Begin),
SM.getExpansionLineNumber(End));
}
/// Add as much of range B into range A as possible without exceeding a maximum
/// size of MaxRange. Ranges are inclusive.
static std::pair<unsigned, unsigned>
maybeAddRange(std::pair<unsigned, unsigned> A, std::pair<unsigned, unsigned> B,
unsigned MaxRange) {
// If A is already the maximum size, we're done.
unsigned Slack = MaxRange - (A.second - A.first + 1);
if (Slack == 0)
return A;
// Easy case: merge succeeds within MaxRange.
unsigned Min = std::min(A.first, B.first);
unsigned Max = std::max(A.second, B.second);
if (Max - Min + 1 <= MaxRange)
return {Min, Max};
// If we can't reach B from A within MaxRange, there's nothing to do.
// Don't add lines to the range that contain nothing interesting.
if ((B.first > A.first && B.first - A.first + 1 > MaxRange) ||
(B.second < A.second && A.second - B.second + 1 > MaxRange))
return A;
// Otherwise, expand A towards B to produce a range of size MaxRange. We
// attempt to expand by the same amount in both directions if B strictly
// contains A.
// Expand downwards by up to half the available amount, then upwards as
// much as possible, then downwards as much as possible.
A.second = std::min(A.second + (Slack + 1) / 2, Max);
Slack = MaxRange - (A.second - A.first + 1);
A.first = std::max(Min + Slack, A.first) - Slack;
A.second = std::min(A.first + MaxRange - 1, Max);
return A;
}
/// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo.
static void highlightRange(const CharSourceRange &R,
unsigned LineNo, FileID FID,
@ -990,9 +1040,12 @@ static void highlightRange(const CharSourceRange &R,
EndColNo = map.startOfPreviousColumn(EndColNo);
// If the start/end passed each other, then we are trying to highlight a
// range that just exists in whitespace, which must be some sort of other
// bug.
assert(StartColNo <= EndColNo && "Trying to highlight whitespace??");
// range that just exists in whitespace. That most likely means we have
// a multi-line highlighting range that covers a blank line.
if (StartColNo > EndColNo) {
assert(StartLineNo != EndLineNo && "trying to highlight whitespace");
StartColNo = EndColNo;
}
}
assert(StartColNo <= map.getSourceLine().size() && "Invalid range!");
@ -1103,7 +1156,7 @@ void TextDiagnostic::emitSnippetAndCaret(
// Decompose the location into a FID/Offset pair.
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
FileID FID = LocInfo.first;
unsigned FileOffset = LocInfo.second;
unsigned CaretFileOffset = LocInfo.second;
// Get information about the buffer it points into.
bool Invalid = false;
@ -1111,101 +1164,118 @@ void TextDiagnostic::emitSnippetAndCaret(
if (Invalid)
return;
const char *BufStart = BufData.data();
const char *BufEnd = BufStart + BufData.size();
unsigned CaretLineNo = SM.getLineNumber(FID, CaretFileOffset);
unsigned CaretColNo = SM.getColumnNumber(FID, CaretFileOffset);
unsigned LineNo = SM.getLineNumber(FID, FileOffset);
unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
// Arbitrarily stop showing snippets when the line is too long.
static const size_t MaxLineLengthToPrint = 4096;
if (ColNo > MaxLineLengthToPrint)
if (CaretColNo > MaxLineLengthToPrint)
return;
// Rewind from the current position to the start of the line.
const char *TokPtr = BufStart+FileOffset;
const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
// Compute the line end. Scan forward from the error position to the end of
// the line.
const char *LineEnd = TokPtr;
while (*LineEnd != '\n' && *LineEnd != '\r' && LineEnd != BufEnd)
++LineEnd;
// Arbitrarily stop showing snippets when the line is too long.
if (size_t(LineEnd - LineStart) > MaxLineLengthToPrint)
return;
// Trim trailing null-bytes.
StringRef Line(LineStart, LineEnd - LineStart);
while (Line.size() > ColNo && Line.back() == '\0')
Line = Line.drop_back();
// Copy the line of code into an std::string for ease of manipulation.
std::string SourceLine(Line.begin(), Line.end());
// Build the byte to column map.
const SourceColumnMap sourceColMap(SourceLine, DiagOpts->TabStop);
// Create a line for the caret that is filled with spaces that is the same
// number of columns as the line of source code.
std::string CaretLine(sourceColMap.columns(), ' ');
// Highlight all of the characters covered by Ranges with ~ characters.
// Find the set of lines to include.
const unsigned MaxLines = DiagOpts->SnippetLineLimit;
std::pair<unsigned, unsigned> Lines = {CaretLineNo, CaretLineNo};
for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
E = Ranges.end();
I != E; ++I)
highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM, LangOpts);
if (auto OptionalRange = findLinesForRange(*I, FID, SM))
Lines = maybeAddRange(Lines, *OptionalRange, MaxLines);
// Next, insert the caret itself.
ColNo = sourceColMap.byteToContainingColumn(ColNo-1);
if (CaretLine.size()<ColNo+1)
CaretLine.resize(ColNo+1, ' ');
CaretLine[ColNo] = '^';
for (unsigned LineNo = Lines.first; LineNo != Lines.second + 1; ++LineNo) {
const char *BufStart = BufData.data();
const char *BufEnd = BufStart + BufData.size();
std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
sourceColMap,
Hints, SM,
DiagOpts.get());
// Rewind from the current position to the start of the line.
const char *LineStart =
BufStart +
SM.getDecomposedLoc(SM.translateLineCol(FID, LineNo, 1)).second;
if (LineStart == BufEnd)
break;
// If the source line is too long for our terminal, select only the
// "interesting" source region within that line.
unsigned Columns = DiagOpts->MessageLength;
if (Columns)
selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
Columns, sourceColMap);
// Compute the line end.
const char *LineEnd = LineStart;
while (*LineEnd != '\n' && *LineEnd != '\r' && LineEnd != BufEnd)
++LineEnd;
// If we are in -fdiagnostics-print-source-range-info mode, we are trying
// to produce easily machine parsable output. Add a space before the
// source line and the caret to make it trivial to tell the main diagnostic
// line from what the user is intended to see.
if (DiagOpts->ShowSourceRanges) {
SourceLine = ' ' + SourceLine;
CaretLine = ' ' + CaretLine;
}
// Arbitrarily stop showing snippets when the line is too long.
// FIXME: Don't print any lines in this case.
if (size_t(LineEnd - LineStart) > MaxLineLengthToPrint)
return;
// Finally, remove any blank spaces from the end of CaretLine.
while (CaretLine[CaretLine.size()-1] == ' ')
CaretLine.erase(CaretLine.end()-1);
// Trim trailing null-bytes.
StringRef Line(LineStart, LineEnd - LineStart);
while (!Line.empty() && Line.back() == '\0' &&
(LineNo != CaretLineNo || Line.size() > CaretColNo))
Line = Line.drop_back();
// Emit what we have computed.
emitSnippet(SourceLine);
// Copy the line of code into an std::string for ease of manipulation.
std::string SourceLine(Line.begin(), Line.end());
if (DiagOpts->ShowColors)
OS.changeColor(caretColor, true);
OS << CaretLine << '\n';
if (DiagOpts->ShowColors)
OS.resetColor();
// Build the byte to column map.
const SourceColumnMap sourceColMap(SourceLine, DiagOpts->TabStop);
if (!FixItInsertionLine.empty()) {
if (DiagOpts->ShowColors)
// Print fixit line in color
OS.changeColor(fixitColor, false);
if (DiagOpts->ShowSourceRanges)
OS << ' ';
OS << FixItInsertionLine << '\n';
if (DiagOpts->ShowColors)
OS.resetColor();
// Create a line for the caret that is filled with spaces that is the same
// number of columns as the line of source code.
std::string CaretLine(sourceColMap.columns(), ' ');
// Highlight all of the characters covered by Ranges with ~ characters.
for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
E = Ranges.end();
I != E; ++I)
highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM, LangOpts);
// Next, insert the caret itself.
if (CaretLineNo == LineNo) {
CaretColNo = sourceColMap.byteToContainingColumn(CaretColNo - 1);
if (CaretLine.size() < CaretColNo + 1)
CaretLine.resize(CaretColNo + 1, ' ');
CaretLine[CaretColNo] = '^';
}
std::string FixItInsertionLine = buildFixItInsertionLine(
LineNo, sourceColMap, Hints, SM, DiagOpts.get());
// If the source line is too long for our terminal, select only the
// "interesting" source region within that line.
unsigned Columns = DiagOpts->MessageLength;
if (Columns)
selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
Columns, sourceColMap);
// If we are in -fdiagnostics-print-source-range-info mode, we are trying
// to produce easily machine parsable output. Add a space before the
// source line and the caret to make it trivial to tell the main diagnostic
// line from what the user is intended to see.
if (DiagOpts->ShowSourceRanges) {
SourceLine = ' ' + SourceLine;
CaretLine = ' ' + CaretLine;
}
// Finally, remove any blank spaces from the end of CaretLine.
while (!CaretLine.empty() && CaretLine[CaretLine.size() - 1] == ' ')
CaretLine.erase(CaretLine.end() - 1);
// Emit what we have computed.
emitSnippet(SourceLine);
if (!CaretLine.empty()) {
if (DiagOpts->ShowColors)
OS.changeColor(caretColor, true);
OS << CaretLine << '\n';
if (DiagOpts->ShowColors)
OS.resetColor();
}
if (!FixItInsertionLine.empty()) {
if (DiagOpts->ShowColors)
// Print fixit line in color
OS.changeColor(fixitColor, false);
if (DiagOpts->ShowSourceRanges)
OS << ' ';
OS << FixItInsertionLine << '\n';
if (DiagOpts->ShowColors)
OS.resetColor();
}
}
// Print out any parseable fixit information requested by the options.

View File

@ -7,6 +7,7 @@ set(files
avx2intrin.h
avx512bwintrin.h
avx512cdintrin.h
avx512vpopcntdqintrin.h
avx512dqintrin.h
avx512erintrin.h
avx512fintrin.h

View File

@ -12156,6 +12156,11 @@ static __inline__ void __ATTRS_o_ai vec_vsx_st(vector unsigned char __a,
#endif
#ifdef __VSX__
#define vec_xxpermdi __builtin_vsx_xxpermdi
#define vec_xxsldwi __builtin_vsx_xxsldwi
#endif
/* vec_xor */
#define __builtin_altivec_vxor vec_xor

View File

@ -0,0 +1,70 @@
/*===------------- avx512vpopcntdqintrin.h - AVX512VPOPCNTDQ 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 __IMMINTRIN_H
#error \
"Never use <avx512vpopcntdqintrin.h> directly; include <immintrin.h> instead."
#endif
#ifndef __AVX512VPOPCNTDQINTRIN_H
#define __AVX512VPOPCNTDQINTRIN_H
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, __target__("avx512vpopcntd" \
"q")))
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_popcnt_epi64(__m512i __A) {
return (__m512i)__builtin_ia32_vpopcntq_512((__v8di)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_popcnt_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
return (__m512i)__builtin_ia32_selectq_512(
(__mmask8)__U, (__v8di)_mm512_popcnt_epi64(__A), (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_popcnt_epi64(__mmask8 __U, __m512i __A) {
return _mm512_mask_popcnt_epi64((__m512i)_mm512_setzero_si512(), __U, __A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_popcnt_epi32(__m512i __A) {
return (__m512i)__builtin_ia32_vpopcntd_512((__v16si)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_popcnt_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
return (__m512i)__builtin_ia32_selectd_512(
(__mmask16)__U, (__v16si)_mm512_popcnt_epi32(__A), (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_popcnt_epi32(__mmask16 __U, __m512i __A) {
return _mm512_mask_popcnt_epi32((__m512i)_mm512_setzero_si512(), __U, __A);
}
#undef __DEFAULT_FN_ATTRS
#endif

View File

@ -146,6 +146,10 @@ _mm256_cvtph_ps(__m128i __a)
#include <avx512cdintrin.h>
#endif
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__AVX512VPOPCNTDQ__)
#include <avx512vpopcntdqintrin.h>
#endif
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__AVX512DQ__)
#include <avx512dqintrin.h>
#endif

View File

@ -254,6 +254,18 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
SymbolRoleSet Roles = getRolesForRef(E, Relations);
return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
Parent, ParentDC, Roles, Relations, E);
} else if (const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter()) {
// Class properties that are explicitly defined using @property
// declarations are represented implicitly as there is no ivar for class
// properties.
if (Getter->isClassMethod()) {
if (const auto *PD = Getter->getCanonicalDecl()->findPropertyDecl()) {
SmallVector<SymbolRelation, 2> Relations;
SymbolRoleSet Roles = getRolesForRef(E, Relations);
return IndexCtx.handleReference(PD, E->getLocation(), Parent,
ParentDC, Roles, Relations, E);
}
}
}
// No need to do a handleReference for the objc method, because there will

View File

@ -124,10 +124,16 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
TKind = FD->getTemplateSpecializationKind();
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
TKind = VD->getTemplateSpecializationKind();
} else if (isa<FieldDecl>(D)) {
if (const auto *Parent =
dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
TKind = Parent->getSpecializationKind();
} else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
if (RD->getInstantiatedFromMemberClass())
TKind = RD->getTemplateSpecializationKind();
} else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
if (ED->getInstantiatedFromMemberEnum())
TKind = ED->getTemplateSpecializationKind();
} else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) ||
isa<EnumConstantDecl>(D)) {
if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext()))
return isTemplateImplicitInstantiation(Parent);
}
switch (TKind) {
case TSK_Undeclared:
@ -155,6 +161,16 @@ bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
return true;
}
static const CXXRecordDecl *
getDeclContextForTemplateInstationPattern(const Decl *D) {
if (const auto *CTSD =
dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
return CTSD->getTemplateInstantiationPattern();
else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
return RD->getInstantiatedFromMemberClass();
return nullptr;
}
static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
if (const ClassTemplateSpecializationDecl *
SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
@ -163,15 +179,26 @@ static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
return FD->getTemplateInstantiationPattern();
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
return VD->getTemplateInstantiationPattern();
} else if (const auto *FD = dyn_cast<FieldDecl>(D)) {
if (const auto *Parent =
dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext())) {
const CXXRecordDecl *Pattern = Parent->getTemplateInstantiationPattern();
for (const NamedDecl *ND : Pattern->lookup(FD->getDeclName())) {
if (ND->isImplicit())
} else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
return RD->getInstantiatedFromMemberClass();
} else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
return ED->getInstantiatedFromMemberEnum();
} else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
const auto *ND = cast<NamedDecl>(D);
if (const CXXRecordDecl *Pattern =
getDeclContextForTemplateInstationPattern(ND)) {
for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
if (BaseND->isImplicit())
continue;
if (isa<FieldDecl>(ND))
return ND;
if (BaseND->getKind() == ND->getKind())
return BaseND;
}
}
} else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
return BaseECD;
}
}
}

View File

@ -563,7 +563,6 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
// Parse the suffix. At this point we can classify whether we have an FP or
// integer constant.
bool isFPConstant = isFloatingLiteral();
const char *ImaginarySuffixLoc = nullptr;
// Loop over all of the characters of the suffix. If we see something bad,
// we break out of the loop.
@ -660,7 +659,6 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
case 'J':
if (isImaginary) break; // Cannot be repeated.
isImaginary = true;
ImaginarySuffixLoc = s;
continue; // Success.
}
// If we reached here, there was an error or a ud-suffix.
@ -694,8 +692,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
}
if (isImaginary) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc,
ImaginarySuffixLoc - ThisTokBegin),
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin - ThisTokBegin),
diag::ext_imaginary_constant);
}
}

View File

@ -84,6 +84,90 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
return Context;
}
/// \brief Append to \p Paths the set of paths needed to get to the
/// subframework in which the given module lives.
static void appendSubframeworkPaths(Module *Mod,
SmallVectorImpl<char> &Path) {
// Collect the framework names from the given module to the top-level module.
SmallVector<StringRef, 2> Paths;
for (; Mod; Mod = Mod->Parent) {
if (Mod->IsFramework)
Paths.push_back(Mod->Name);
}
if (Paths.empty())
return;
// Add Frameworks/Name.framework for each subframework.
for (unsigned I = Paths.size() - 1; I != 0; --I)
llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
}
const FileEntry *
ModuleMap::resolveHeader(Module *M, Module::UnresolvedHeaderDirective Header,
SmallVectorImpl<char> &RelativePathName) {
if (llvm::sys::path::is_absolute(Header.FileName)) {
RelativePathName.clear();
RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
return SourceMgr.getFileManager().getFile(Header.FileName);
}
// Search for the header file within the module's home directory.
auto *Directory = M->Directory;
SmallString<128> FullPathName(Directory->getName());
unsigned FullPathLength = FullPathName.size();
if (M->isPartOfFramework()) {
appendSubframeworkPaths(M, RelativePathName);
unsigned RelativePathLength = RelativePathName.size();
// Check whether this file is in the public headers.
llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
llvm::sys::path::append(FullPathName, RelativePathName);
if (auto *File = SourceMgr.getFileManager().getFile(FullPathName))
return File;
// Check whether this file is in the private headers.
// Ideally, private modules in the form 'FrameworkName.Private' should
// be defined as 'module FrameworkName.Private', and not as
// 'framework module FrameworkName.Private', since a 'Private.Framework'
// does not usually exist. However, since both are currently widely used
// for private modules, make sure we find the right path in both cases.
if (M->IsFramework && M->Name == "Private")
RelativePathName.clear();
else
RelativePathName.resize(RelativePathLength);
FullPathName.resize(FullPathLength);
llvm::sys::path::append(RelativePathName, "PrivateHeaders",
Header.FileName);
llvm::sys::path::append(FullPathName, RelativePathName);
return SourceMgr.getFileManager().getFile(FullPathName);
}
// Lookup for normal headers.
llvm::sys::path::append(RelativePathName, Header.FileName);
llvm::sys::path::append(FullPathName, RelativePathName);
return SourceMgr.getFileManager().getFile(FullPathName);
}
const FileEntry *
ModuleMap::resolveAsBuiltinHeader(Module *M,
Module::UnresolvedHeaderDirective Header,
SmallVectorImpl<char> &BuiltinPathName) {
if (llvm::sys::path::is_absolute(Header.FileName) || M->isPartOfFramework() ||
!M->IsSystem || Header.IsUmbrella || !BuiltinIncludeDir ||
BuiltinIncludeDir == M->Directory || !isBuiltinHeader(Header.FileName))
return nullptr;
// This is a system module with a top-level header. This header
// may have a counterpart (or replacement) in the set of headers
// supplied by Clang. Find that builtin header.
llvm::sys::path::append(BuiltinPathName, BuiltinIncludeDir->getName(),
Header.FileName);
return SourceMgr.getFileManager().getFile(
StringRef(BuiltinPathName.data(), BuiltinPathName.size()));
}
ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
const LangOptions &LangOpts, const TargetInfo *Target,
HeaderSearch &HeaderInfo)
@ -1026,9 +1110,6 @@ namespace clang {
/// be resolved relative to.
const DirectoryEntry *Directory;
/// \brief The directory containing Clang-supplied headers.
const DirectoryEntry *BuiltinIncludeDir;
/// \brief Whether this module map is in a system header directory.
bool IsSystem;
@ -1087,12 +1168,10 @@ namespace clang {
ModuleMap &Map,
const FileEntry *ModuleMapFile,
const DirectoryEntry *Directory,
const DirectoryEntry *BuiltinIncludeDir,
bool IsSystem)
: L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
ModuleMapFile(ModuleMapFile), Directory(Directory),
BuiltinIncludeDir(BuiltinIncludeDir), IsSystem(IsSystem),
HadError(false), ActiveModule(nullptr)
IsSystem(IsSystem), HadError(false), ActiveModule(nullptr)
{
Tok.clear();
consumeToken();
@ -1772,25 +1851,6 @@ void ModuleMapParser::parseRequiresDecl() {
} while (true);
}
/// \brief Append to \p Paths the set of paths needed to get to the
/// subframework in which the given module lives.
static void appendSubframeworkPaths(Module *Mod,
SmallVectorImpl<char> &Path) {
// Collect the framework names from the given module to the top-level module.
SmallVector<StringRef, 2> Paths;
for (; Mod; Mod = Mod->Parent) {
if (Mod->IsFramework)
Paths.push_back(Mod->Name);
}
if (Paths.empty())
return;
// Add Frameworks/Name.framework for each subframework.
for (unsigned I = Paths.size() - 1; I != 0; --I)
llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
}
/// \brief Parse a header declaration.
///
/// header-declaration:
@ -1843,85 +1903,36 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
Module::UnresolvedHeaderDirective Header;
Header.FileName = Tok.getString();
Header.FileNameLoc = consumeToken();
Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
// Check whether we already have an umbrella.
if (LeadingToken == MMToken::UmbrellaKeyword && ActiveModule->Umbrella) {
if (Header.IsUmbrella && ActiveModule->Umbrella) {
Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
<< ActiveModule->getFullModuleName();
HadError = true;
return;
}
// Look for this file.
const FileEntry *File = nullptr;
const FileEntry *BuiltinFile = nullptr;
SmallString<128> RelativePathName;
if (llvm::sys::path::is_absolute(Header.FileName)) {
RelativePathName = Header.FileName;
File = SourceMgr.getFileManager().getFile(RelativePathName);
} else {
// Search for the header file within the search directory.
SmallString<128> FullPathName(Directory->getName());
unsigned FullPathLength = FullPathName.size();
// Look for this file by name if we don't have any stat information.
SmallString<128> RelativePathName, BuiltinPathName;
const FileEntry *File =
Map.resolveHeader(ActiveModule, Header, RelativePathName);
const FileEntry *BuiltinFile =
Map.resolveAsBuiltinHeader(ActiveModule, Header, BuiltinPathName);
if (ActiveModule->isPartOfFramework()) {
appendSubframeworkPaths(ActiveModule, RelativePathName);
unsigned RelativePathLength = RelativePathName.size();
// Check whether this file is in the public headers.
llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
llvm::sys::path::append(FullPathName, RelativePathName);
File = SourceMgr.getFileManager().getFile(FullPathName);
// Check whether this file is in the private headers.
if (!File) {
// Ideally, private modules in the form 'FrameworkName.Private' should
// be defined as 'module FrameworkName.Private', and not as
// 'framework module FrameworkName.Private', since a 'Private.Framework'
// does not usually exist. However, since both are currently widely used
// for private modules, make sure we find the right path in both cases.
if (ActiveModule->IsFramework && ActiveModule->Name == "Private")
RelativePathName.clear();
else
RelativePathName.resize(RelativePathLength);
FullPathName.resize(FullPathLength);
llvm::sys::path::append(RelativePathName, "PrivateHeaders",
Header.FileName);
llvm::sys::path::append(FullPathName, RelativePathName);
File = SourceMgr.getFileManager().getFile(FullPathName);
}
} else {
// Lookup for normal headers.
llvm::sys::path::append(RelativePathName, Header.FileName);
llvm::sys::path::append(FullPathName, RelativePathName);
File = SourceMgr.getFileManager().getFile(FullPathName);
// If this is a system module with a top-level header, this header
// may have a counterpart (or replacement) in the set of headers
// supplied by Clang. Find that builtin header.
if (ActiveModule->IsSystem && LeadingToken != MMToken::UmbrellaKeyword &&
BuiltinIncludeDir && BuiltinIncludeDir != Directory &&
ModuleMap::isBuiltinHeader(Header.FileName)) {
SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
llvm::sys::path::append(BuiltinPathName, Header.FileName);
BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
// If Clang supplies this header but the underlying system does not,
// just silently swap in our builtin version. Otherwise, we'll end
// up adding both (later).
if (BuiltinFile && !File) {
File = BuiltinFile;
RelativePathName = BuiltinPathName;
BuiltinFile = nullptr;
}
}
}
// If Clang supplies this header but the underlying system does not,
// just silently swap in our builtin version. Otherwise, we'll end
// up adding both (later).
if (BuiltinFile && !File) {
RelativePathName = BuiltinPathName;
File = BuiltinFile;
BuiltinFile = nullptr;
}
// FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
// Come up with a lazy way to do this.
if (File) {
if (LeadingToken == MMToken::UmbrellaKeyword) {
if (Header.IsUmbrella) {
const DirectoryEntry *UmbrellaDir = File->getDir();
if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash)
@ -1938,10 +1949,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
// If there is a builtin counterpart to this file, add it now so it can
// wrap the system header.
if (BuiltinFile) {
// FIXME: Taking the name from the FileEntry is unstable and can give
// different results depending on how we've previously named that file
// in this build.
Module::Header H = { BuiltinFile->getName(), BuiltinFile };
Module::Header H = { BuiltinPathName.str(), BuiltinFile };
Map.addHeader(ActiveModule, H, Role);
// If we have both a builtin and system version of the file, the
@ -1960,7 +1968,6 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
// If we find a module that has a missing header, we mark this module as
// unavailable and store the header directive for displaying diagnostics.
Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
ActiveModule->markUnavailable();
ActiveModule->MissingHeaders.push_back(Header);
}
@ -2555,7 +2562,7 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
Buffer->getBufferEnd());
SourceLocation Start = L.getSourceLocation();
ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
BuiltinIncludeDir, IsSystem);
IsSystem);
bool Result = Parser.parseModuleMapFile();
ParsedModuleMap[File] = Result;

View File

@ -1171,18 +1171,26 @@ void Preprocessor::HandleLineDirective() {
CheckEndOfDirective("line", true);
}
SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID);
// Take the file kind of the file containing the #line directive. #line
// directives are often used for generated sources from the same codebase, so
// the new file should generally be classified the same way as the current
// file. This is visible in GCC's pre-processed output, which rewrites #line
// to GNU line markers.
SrcMgr::CharacteristicKind FileKind =
SourceMgr.getFileCharacteristic(DigitTok.getLocation());
SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, false,
false, FileKind);
if (Callbacks)
Callbacks->FileChanged(CurPPLexer->getSourceLocation(),
PPCallbacks::RenameFile,
SrcMgr::C_User);
PPCallbacks::RenameFile, FileKind);
}
/// ReadLineMarkerFlags - Parse and validate any flags at the end of a GNU line
/// marker directive.
static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit,
bool &IsSystemHeader, bool &IsExternCHeader,
SrcMgr::CharacteristicKind &FileKind,
Preprocessor &PP) {
unsigned FlagVal;
Token FlagTok;
@ -1233,7 +1241,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit,
return true;
}
IsSystemHeader = true;
FileKind = SrcMgr::C_System;
PP.Lex(FlagTok);
if (FlagTok.is(tok::eod)) return false;
@ -1247,7 +1255,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit,
return true;
}
IsExternCHeader = true;
FileKind = SrcMgr::C_ExternCSystem;
PP.Lex(FlagTok);
if (FlagTok.is(tok::eod)) return false;
@ -1277,14 +1285,15 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) {
Lex(StrTok);
bool IsFileEntry = false, IsFileExit = false;
bool IsSystemHeader = false, IsExternCHeader = false;
int FilenameID = -1;
SrcMgr::CharacteristicKind FileKind = SrcMgr::C_User;
// If the StrTok is "eod", then it wasn't present. Otherwise, it must be a
// string followed by eod.
if (StrTok.is(tok::eod))
; // ok
else if (StrTok.isNot(tok::string_literal)) {
if (StrTok.is(tok::eod)) {
// Treat this like "#line NN", which doesn't change file characteristics.
FileKind = SourceMgr.getFileCharacteristic(DigitTok.getLocation());
} else if (StrTok.isNot(tok::string_literal)) {
Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
return DiscardUntilEndOfDirective();
} else if (StrTok.hasUDSuffix()) {
@ -1303,15 +1312,13 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) {
FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString());
// If a filename was present, read any flags that are present.
if (ReadLineMarkerFlags(IsFileEntry, IsFileExit,
IsSystemHeader, IsExternCHeader, *this))
if (ReadLineMarkerFlags(IsFileEntry, IsFileExit, FileKind, *this))
return;
}
// Create a line note with this information.
SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID,
IsFileEntry, IsFileExit,
IsSystemHeader, IsExternCHeader);
SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, IsFileEntry,
IsFileExit, FileKind);
// If the preprocessor has callbacks installed, notify them of the #line
// change. This is used so that the line marker comes out in -E mode for
@ -1322,11 +1329,6 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) {
Reason = PPCallbacks::EnterFile;
else if (IsFileExit)
Reason = PPCallbacks::ExitFile;
SrcMgr::CharacteristicKind FileKind = SrcMgr::C_User;
if (IsExternCHeader)
FileKind = SrcMgr::C_ExternCSystem;
else if (IsSystemHeader)
FileKind = SrcMgr::C_System;
Callbacks->FileChanged(CurPPLexer->getSourceLocation(), Reason, FileKind);
}

View File

@ -1125,6 +1125,7 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
.Case("attribute_overloadable", true)
.Case("attribute_unavailable_with_message", true)
.Case("attribute_unused_on_fields", true)
.Case("attribute_diagnose_if_objc", true)
.Case("blocks", LangOpts.Blocks)
.Case("c_thread_safety_attributes", true)
.Case("cxx_exceptions", LangOpts.CXXExceptions)

View File

@ -475,9 +475,9 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
// Emit a line marker. This will change any source locations from this point
// forward to realize they are in a system header.
// Create a line note with this information.
SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine()+1,
SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine() + 1,
FilenameID, /*IsEntry=*/false, /*IsExit=*/false,
/*IsSystem=*/true, /*IsExternC=*/false);
SrcMgr::C_System);
}
/// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.

View File

@ -2120,31 +2120,18 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) {
// Form a parsed representation of the template-id to be stored in the
// UnqualifiedId.
TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
// FIXME: Store name for literal operator too.
if (Id.getKind() == UnqualifiedId::IK_Identifier) {
TemplateId->Name = Id.Identifier;
TemplateId->Operator = OO_None;
TemplateId->TemplateNameLoc = Id.StartLocation;
} else {
TemplateId->Name = nullptr;
TemplateId->Operator = Id.OperatorFunctionId.Operator;
TemplateId->TemplateNameLoc = Id.StartLocation;
}
IdentifierInfo *TemplateII =
Id.getKind() == UnqualifiedId::IK_Identifier ? Id.Identifier : nullptr;
OverloadedOperatorKind OpKind = Id.getKind() == UnqualifiedId::IK_Identifier
? OO_None
: Id.OperatorFunctionId.Operator;
TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
SS, TemplateKWLoc, Id.StartLocation, TemplateII, OpKind, Template, TNK,
LAngleLoc, RAngleLoc, TemplateArgs, TemplateIds);
TemplateId->SS = SS;
TemplateId->TemplateKWLoc = TemplateKWLoc;
TemplateId->Template = Template;
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size();
Arg != ArgEnd; ++Arg)
Args[Arg] = TemplateArgs[Arg];
Id.setTemplateId(TemplateId);
return false;
}

View File

@ -1011,25 +1011,21 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// Build a template-id annotation token that can be processed
// later.
Tok.setKind(tok::annot_template_id);
TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
TemplateId->TemplateNameLoc = TemplateNameLoc;
if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) {
TemplateId->Name = TemplateName.Identifier;
TemplateId->Operator = OO_None;
} else {
TemplateId->Name = nullptr;
TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
}
TemplateId->SS = SS;
TemplateId->TemplateKWLoc = TemplateKWLoc;
TemplateId->Template = Template;
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
Args[Arg] = ParsedTemplateArgument(TemplateArgs[Arg]);
IdentifierInfo *TemplateII =
TemplateName.getKind() == UnqualifiedId::IK_Identifier
? TemplateName.Identifier
: nullptr;
OverloadedOperatorKind OpKind =
TemplateName.getKind() == UnqualifiedId::IK_Identifier
? OO_None
: TemplateName.OperatorFunctionId.Operator;
TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
SS, TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,
LAngleLoc, RAngleLoc, TemplateArgs, TemplateIds);
Tok.setAnnotationValue(TemplateId);
if (TemplateKWLoc.isValid())
Tok.setLocation(TemplateKWLoc);

View File

@ -542,6 +542,7 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
bool ReturnsVoid = false;
bool HasNoReturn = false;
bool IsCoroutine = S.getCurFunction() && S.getCurFunction()->isCoroutine();
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
@ -570,8 +571,13 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
// Short circuit for compilation speed.
if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
return;
SourceLocation LBrace = Body->getLocStart(), RBrace = Body->getLocEnd();
auto EmitDiag = [&](SourceLocation Loc, unsigned DiagID) {
if (IsCoroutine)
S.Diag(Loc, DiagID) << S.getCurFunction()->CoroutinePromise->getType();
else
S.Diag(Loc, DiagID);
};
// Either in a function body compound statement, or a function-try-block.
switch (CheckFallThrough(AC)) {
case UnknownFallThrough:
@ -579,15 +585,15 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
case MaybeFallThrough:
if (HasNoReturn)
S.Diag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
EmitDiag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
else if (!ReturnsVoid)
S.Diag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
EmitDiag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
break;
case AlwaysFallThrough:
if (HasNoReturn)
S.Diag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
EmitDiag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
else if (!ReturnsVoid)
S.Diag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
break;
case NeverFallThroughOrReturn:
if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
@ -2027,12 +2033,6 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
// Warning: check missing 'return'
if (P.enableCheckFallThrough) {
auto IsCoro = [&]() {
if (auto *FD = dyn_cast<FunctionDecl>(D))
if (FD->getBody() && isa<CoroutineBodyStmt>(FD->getBody()))
return true;
return false;
};
const CheckFallThroughDiagnostics &CD =
(isa<BlockDecl>(D)
? CheckFallThroughDiagnostics::MakeForBlock()
@ -2040,7 +2040,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
cast<CXXMethodDecl>(D)->getParent()->isLambda())
? CheckFallThroughDiagnostics::MakeForLambda()
: (IsCoro()
: (fscope->isCoroutine()
? CheckFallThroughDiagnostics::MakeForCoroutine(D)
: CheckFallThroughDiagnostics::MakeForFunction(D)));
CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC);

View File

@ -28,7 +28,6 @@ class CoroutineStmtBuilder : public CoroutineBodyStmt::CtorArgs {
sema::FunctionScopeInfo &Fn;
bool IsValid = true;
SourceLocation Loc;
QualType RetType;
SmallVector<Stmt *, 4> ParamMovesVector;
const bool IsPromiseDependentType;
CXXRecordDecl *PromiseRecordDecl = nullptr;
@ -61,6 +60,7 @@ class CoroutineStmtBuilder : public CoroutineBodyStmt::CtorArgs {
bool makeOnFallthrough();
bool makeOnException();
bool makeReturnObject();
bool makeGroDeclAndReturnStmt();
bool makeReturnOnAllocFailure();
bool makeParamMoves();
};

View File

@ -1696,6 +1696,9 @@ bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case PPC::BI__builtin_tabortdci:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31) ||
SemaBuiltinConstantArgRange(TheCall, 2, 0, 31);
case PPC::BI__builtin_vsx_xxpermdi:
case PPC::BI__builtin_vsx_xxsldwi:
return SemaBuiltinVSX(TheCall);
}
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}
@ -3892,6 +3895,65 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
return false;
}
// Customized Sema Checking for VSX builtins that have the following signature:
// vector [...] builtinName(vector [...], vector [...], const int);
// Which takes the same type of vectors (any legal vector type) for the first
// two arguments and takes compile time constant for the third argument.
// Example builtins are :
// vector double vec_xxpermdi(vector double, vector double, int);
// vector short vec_xxsldwi(vector short, vector short, int);
bool Sema::SemaBuiltinVSX(CallExpr *TheCall) {
unsigned ExpectedNumArgs = 3;
if (TheCall->getNumArgs() < ExpectedNumArgs)
return Diag(TheCall->getLocEnd(),
diag::err_typecheck_call_too_few_args_at_least)
<< 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs()
<< TheCall->getSourceRange();
if (TheCall->getNumArgs() > ExpectedNumArgs)
return Diag(TheCall->getLocEnd(),
diag::err_typecheck_call_too_many_args_at_most)
<< 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs()
<< TheCall->getSourceRange();
// Check the third argument is a compile time constant
llvm::APSInt Value;
if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context))
return Diag(TheCall->getLocStart(),
diag::err_vsx_builtin_nonconstant_argument)
<< 3 /* argument index */ << TheCall->getDirectCallee()
<< SourceRange(TheCall->getArg(2)->getLocStart(),
TheCall->getArg(2)->getLocEnd());
QualType Arg1Ty = TheCall->getArg(0)->getType();
QualType Arg2Ty = TheCall->getArg(1)->getType();
// Check the type of argument 1 and argument 2 are vectors.
SourceLocation BuiltinLoc = TheCall->getLocStart();
if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) ||
(!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) {
return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
<< TheCall->getDirectCallee()
<< SourceRange(TheCall->getArg(0)->getLocStart(),
TheCall->getArg(1)->getLocEnd());
}
// Check the first two arguments are the same type.
if (!Context.hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) {
return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
<< TheCall->getDirectCallee()
<< SourceRange(TheCall->getArg(0)->getLocStart(),
TheCall->getArg(1)->getLocEnd());
}
// When default clang type checking is turned off and the customized type
// checking is used, the returning type of the function must be explicitly
// set. Otherwise it is _Bool by default.
TheCall->setType(Arg1Ty);
return false;
}
/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector.
// This is declared to take (...), so we have to check everything.
ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
@ -3914,7 +3976,8 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
if (!LHSType->isVectorType() || !RHSType->isVectorType())
return ExprError(Diag(TheCall->getLocStart(),
diag::err_shufflevector_non_vector)
diag::err_vec_builtin_non_vector)
<< TheCall->getDirectCallee()
<< SourceRange(TheCall->getArg(0)->getLocStart(),
TheCall->getArg(1)->getLocEnd()));
@ -3928,12 +3991,14 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
if (!RHSType->hasIntegerRepresentation() ||
RHSType->getAs<VectorType>()->getNumElements() != numElements)
return ExprError(Diag(TheCall->getLocStart(),
diag::err_shufflevector_incompatible_vector)
diag::err_vec_builtin_incompatible_vector)
<< TheCall->getDirectCallee()
<< SourceRange(TheCall->getArg(1)->getLocStart(),
TheCall->getArg(1)->getLocEnd()));
} else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
return ExprError(Diag(TheCall->getLocStart(),
diag::err_shufflevector_incompatible_vector)
diag::err_vec_builtin_incompatible_vector)
<< TheCall->getDirectCallee()
<< SourceRange(TheCall->getArg(0)->getLocStart(),
TheCall->getArg(1)->getLocEnd()));
} else if (numElements != numResElements) {

View File

@ -23,14 +23,22 @@
using namespace clang;
using namespace sema;
static bool lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD,
SourceLocation Loc) {
static LookupResult lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD,
SourceLocation Loc, bool &Res) {
DeclarationName DN = S.PP.getIdentifierInfo(Name);
LookupResult LR(S, DN, Loc, Sema::LookupMemberName);
// Suppress diagnostics when a private member is selected. The same warnings
// will be produced again when building the call.
LR.suppressDiagnostics();
return S.LookupQualifiedName(LR, RD);
Res = S.LookupQualifiedName(LR, RD);
return LR;
}
static bool lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD,
SourceLocation Loc) {
bool Res;
lookupMember(S, Name, RD, Loc, Res);
return Res;
}
/// Look up the std::coroutine_traits<...>::promise_type for the given
@ -120,8 +128,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
return PromiseType;
}
/// Look up the std::coroutine_traits<...>::promise_type for the given
/// function type.
/// Look up the std::experimental::coroutine_handle<PromiseType>.
static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
SourceLocation Loc) {
if (PromiseType.isNull())
@ -314,6 +321,7 @@ static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType,
}
struct ReadySuspendResumeResult {
enum AwaitCallType { ACT_Ready, ACT_Suspend, ACT_Resume };
Expr *Results[3];
OpaqueValueExpr *OpaqueValue;
bool IsInvalid;
@ -359,7 +367,41 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
Calls.Results[I] = Result.get();
}
// Assume the calls are valid; all further checking should make them invalid.
Calls.IsInvalid = false;
using ACT = ReadySuspendResumeResult::AwaitCallType;
CallExpr *AwaitReady = cast<CallExpr>(Calls.Results[ACT::ACT_Ready]);
if (!AwaitReady->getType()->isDependentType()) {
// [expr.await]p3 [...]
// — await-ready is the expression e.await_ready(), contextually converted
// to bool.
ExprResult Conv = S.PerformContextuallyConvertToBool(AwaitReady);
if (Conv.isInvalid()) {
S.Diag(AwaitReady->getDirectCallee()->getLocStart(),
diag::note_await_ready_no_bool_conversion);
S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
<< AwaitReady->getDirectCallee() << E->getSourceRange();
Calls.IsInvalid = true;
}
Calls.Results[ACT::ACT_Ready] = Conv.get();
}
CallExpr *AwaitSuspend = cast<CallExpr>(Calls.Results[ACT::ACT_Suspend]);
if (!AwaitSuspend->getType()->isDependentType()) {
// [expr.await]p3 [...]
// - await-suspend is the expression e.await_suspend(h), which shall be
// a prvalue of type void or bool.
QualType RetType = AwaitSuspend->getType();
if (RetType != S.Context.BoolTy && RetType != S.Context.VoidTy) {
S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(),
diag::err_await_suspend_invalid_return_type)
<< RetType;
S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
<< AwaitSuspend->getDirectCallee();
Calls.IsInvalid = true;
}
}
return Calls;
}
@ -373,7 +415,6 @@ static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise,
if (PromiseRef.isInvalid())
return ExprError();
// Call 'yield_value', passing in E.
return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
}
@ -721,17 +762,19 @@ static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc,
void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
FunctionScopeInfo *Fn = getCurFunction();
assert(Fn && Fn->CoroutinePromise && "not a coroutine");
assert(Fn && Fn->isCoroutine() && "not a coroutine");
if (!Body) {
assert(FD->isInvalidDecl() &&
"a null body is only allowed for invalid declarations");
return;
}
// We have a function that uses coroutine keywords, but we failed to build
// the promise type.
if (!Fn->CoroutinePromise)
return FD->setInvalidDecl();
if (isa<CoroutineBodyStmt>(Body)) {
// FIXME(EricWF): Nothing todo. the body is already a transformed coroutine
// body statement.
// Nothing todo. the body is already a transformed coroutine body statement.
return;
}
@ -780,7 +823,8 @@ bool CoroutineStmtBuilder::buildDependentStatements() {
assert(!this->IsPromiseDependentType &&
"coroutine cannot have a dependent promise type");
this->IsValid = makeOnException() && makeOnFallthrough() &&
makeReturnOnAllocFailure() && makeNewAndDeleteExpr();
makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&
makeNewAndDeleteExpr();
return this->IsValid;
}
@ -857,15 +901,15 @@ bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
if (ReturnObjectOnAllocationFailure.isInvalid())
return false;
// FIXME: ActOnReturnStmt expects a scope that is inside of the function, due
// to CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent());
// S.getCurScope()->getFnParent() == nullptr at ActOnFinishFunctionBody when
// CoroutineBodyStmt is built. Figure it out and fix it.
// Use BuildReturnStmt here to unbreak sanitized tests. (Gor:3/27/2017)
StmtResult ReturnStmt =
S.BuildReturnStmt(Loc, ReturnObjectOnAllocationFailure.get());
if (ReturnStmt.isInvalid())
if (ReturnStmt.isInvalid()) {
S.Diag(Found.getFoundDecl()->getLocation(), diag::note_member_declared_here)
<< DN;
S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
<< Fn.getFirstCoroutineStmtKeyword();
return false;
}
this->ReturnStmtOnAllocFailure = ReturnStmt.get();
return true;
@ -991,13 +1035,32 @@ bool CoroutineStmtBuilder::makeOnFallthrough() {
// [dcl.fct.def.coroutine]/4
// The unqualified-ids 'return_void' and 'return_value' are looked up in
// the scope of class P. If both are found, the program is ill-formed.
const bool HasRVoid = lookupMember(S, "return_void", PromiseRecordDecl, Loc);
const bool HasRValue = lookupMember(S, "return_value", PromiseRecordDecl, Loc);
bool HasRVoid, HasRValue;
LookupResult LRVoid =
lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid);
LookupResult LRValue =
lookupMember(S, "return_value", PromiseRecordDecl, Loc, HasRValue);
StmtResult Fallthrough;
if (HasRVoid && HasRValue) {
// FIXME Improve this diagnostic
S.Diag(FD.getLocation(), diag::err_coroutine_promise_return_ill_formed)
S.Diag(FD.getLocation(),
diag::err_coroutine_promise_incompatible_return_functions)
<< PromiseRecordDecl;
S.Diag(LRVoid.getRepresentativeDecl()->getLocation(),
diag::note_member_first_declared_here)
<< LRVoid.getLookupName();
S.Diag(LRValue.getRepresentativeDecl()->getLocation(),
diag::note_member_first_declared_here)
<< LRValue.getLookupName();
return false;
} else if (!HasRVoid && !HasRValue) {
// FIXME: The PDTS currently specifies this case as UB, not ill-formed.
// However we still diagnose this as an error since until the PDTS is fixed.
S.Diag(FD.getLocation(),
diag::err_coroutine_promise_requires_return_function)
<< PromiseRecordDecl;
S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
<< PromiseRecordDecl;
return false;
} else if (HasRVoid) {
@ -1029,6 +1092,8 @@ bool CoroutineStmtBuilder::makeOnException() {
: diag::
warn_coroutine_promise_unhandled_exception_required_with_exceptions;
S.Diag(Loc, DiagID) << PromiseRecordDecl;
S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
<< PromiseRecordDecl;
return !RequireUnhandledException;
}
@ -1042,37 +1107,185 @@ bool CoroutineStmtBuilder::makeOnException() {
if (UnhandledException.isInvalid())
return false;
// Since the body of the coroutine will be wrapped in try-catch, it will
// be incompatible with SEH __try if present in a function.
if (!S.getLangOpts().Borland && Fn.FirstSEHTryLoc.isValid()) {
S.Diag(Fn.FirstSEHTryLoc, diag::err_seh_in_a_coroutine_with_cxx_exceptions);
S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
<< Fn.getFirstCoroutineStmtKeyword();
return false;
}
this->OnException = UnhandledException.get();
return true;
}
bool CoroutineStmtBuilder::makeReturnObject() {
// Build implicit 'p.get_return_object()' expression and form initialization
// of return type from it.
ExprResult ReturnObject =
buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", None);
if (ReturnObject.isInvalid())
return false;
QualType RetType = FD.getReturnType();
if (!RetType->isDependentType()) {
InitializedEntity Entity =
InitializedEntity::InitializeResult(Loc, RetType, false);
ReturnObject = S.PerformMoveOrCopyInitialization(Entity, nullptr, RetType,
ReturnObject.get());
if (ReturnObject.isInvalid())
return false;
}
ReturnObject = S.ActOnFinishFullExpr(ReturnObject.get(), Loc);
if (ReturnObject.isInvalid())
return false;
this->ReturnValue = ReturnObject.get();
return true;
}
static void noteMemberDeclaredHere(Sema &S, Expr *E, FunctionScopeInfo &Fn) {
if (auto *MbrRef = dyn_cast<CXXMemberCallExpr>(E)) {
auto *MethodDecl = MbrRef->getMethodDecl();
S.Diag(MethodDecl->getLocation(), diag::note_member_declared_here)
<< MethodDecl;
}
S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
<< Fn.getFirstCoroutineStmtKeyword();
}
bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
assert(!IsPromiseDependentType &&
"cannot make statement while the promise type is dependent");
assert(this->ReturnValue && "ReturnValue must be already formed");
QualType const GroType = this->ReturnValue->getType();
assert(!GroType->isDependentType() &&
"get_return_object type must no longer be dependent");
QualType const FnRetType = FD.getReturnType();
assert(!FnRetType->isDependentType() &&
"get_return_object type must no longer be dependent");
if (FnRetType->isVoidType()) {
ExprResult Res = S.ActOnFinishFullExpr(this->ReturnValue, Loc);
if (Res.isInvalid())
return false;
this->ResultDecl = Res.get();
return true;
}
if (GroType->isVoidType()) {
// Trigger a nice error message.
InitializedEntity Entity =
InitializedEntity::InitializeResult(Loc, FnRetType, false);
S.PerformMoveOrCopyInitialization(Entity, nullptr, FnRetType, ReturnValue);
noteMemberDeclaredHere(S, ReturnValue, Fn);
return false;
}
auto *GroDecl = VarDecl::Create(
S.Context, &FD, FD.getLocation(), FD.getLocation(),
&S.PP.getIdentifierTable().get("__coro_gro"), GroType,
S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None);
S.CheckVariableDeclarationType(GroDecl);
if (GroDecl->isInvalidDecl())
return false;
InitializedEntity Entity = InitializedEntity::InitializeVariable(GroDecl);
ExprResult Res = S.PerformMoveOrCopyInitialization(Entity, nullptr, GroType,
this->ReturnValue);
if (Res.isInvalid())
return false;
Res = S.ActOnFinishFullExpr(Res.get());
if (Res.isInvalid())
return false;
if (GroType == FnRetType) {
GroDecl->setNRVOVariable(true);
}
S.AddInitializerToDecl(GroDecl, Res.get(),
/*DirectInit=*/false);
S.FinalizeDeclaration(GroDecl);
// Form a declaration statement for the return declaration, so that AST
// visitors can more easily find it.
StmtResult GroDeclStmt =
S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(GroDecl), Loc, Loc);
if (GroDeclStmt.isInvalid())
return false;
this->ResultDecl = GroDeclStmt.get();
ExprResult declRef = S.BuildDeclRefExpr(GroDecl, GroType, VK_LValue, Loc);
if (declRef.isInvalid())
return false;
StmtResult ReturnStmt = S.BuildReturnStmt(Loc, declRef.get());
if (ReturnStmt.isInvalid()) {
noteMemberDeclaredHere(S, ReturnValue, Fn);
return false;
}
this->ReturnStmt = ReturnStmt.get();
return true;
}
// Create a static_cast\<T&&>(expr).
static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) {
if (T.isNull())
T = E->getType();
QualType TargetType = S.BuildReferenceType(
T, /*SpelledAsLValue*/ false, SourceLocation(), DeclarationName());
SourceLocation ExprLoc = E->getLocStart();
TypeSourceInfo *TargetLoc =
S.Context.getTrivialTypeSourceInfo(TargetType, ExprLoc);
return S
.BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E,
SourceRange(ExprLoc, ExprLoc), E->getSourceRange())
.get();
}
/// \brief Build a variable declaration for move parameter.
static VarDecl *buildVarDecl(Sema &S, SourceLocation Loc, QualType Type,
StringRef Name) {
DeclContext *DC = S.CurContext;
IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = S.Context.getTrivialTypeSourceInfo(Type, Loc);
VarDecl *Decl =
VarDecl::Create(S.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
Decl->setImplicit();
return Decl;
}
bool CoroutineStmtBuilder::makeParamMoves() {
// FIXME: Perform move-initialization of parameters into frame-local copies.
for (auto *paramDecl : FD.parameters()) {
auto Ty = paramDecl->getType();
if (Ty->isDependentType())
continue;
// No need to copy scalars, llvm will take care of them.
if (Ty->getAsCXXRecordDecl()) {
if (!paramDecl->getIdentifier())
continue;
ExprResult ParamRef =
S.BuildDeclRefExpr(paramDecl, paramDecl->getType(),
ExprValueKind::VK_LValue, Loc); // FIXME: scope?
if (ParamRef.isInvalid())
return false;
Expr *RCast = castForMoving(S, ParamRef.get());
auto D = buildVarDecl(S, Loc, Ty, paramDecl->getIdentifier()->getName());
S.AddInitializerToDecl(D, RCast, /*DirectInit=*/true);
// Convert decl to a statement.
StmtResult Stmt = S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(D), Loc, Loc);
if (Stmt.isInvalid())
return false;
ParamMovesVector.push_back(Stmt.get());
}
}
// Convert to ArrayRef in CtorArgs structure that builder inherits from.
ParamMoves = ParamMovesVector;
return true;
}

View File

@ -6516,7 +6516,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
diag::err_thread_non_global)
<< DeclSpec::getSpecifierName(TSCS);
else if (!Context.getTargetInfo().isTLSSupported()) {
if (getLangOpts().CUDA) {
if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) {
// Postpone error emission until we've collected attributes required to
// figure out whether it's a host or device variable and whether the
// error should be ignored.
@ -6578,8 +6578,11 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewVD, D);
if (getLangOpts().CUDA) {
if (EmitTLSUnsupportedError && DeclAttrsMatchCUDAMode(getLangOpts(), NewVD))
if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) {
if (EmitTLSUnsupportedError &&
((getLangOpts().CUDA && DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) ||
(getLangOpts().OpenMPIsDevice &&
NewVD->hasAttr<OMPDeclareTargetDeclAttr>())))
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_unsupported);
// CUDA B.2.5: "__shared__ and __constant__ variables have implied static
@ -7917,10 +7920,7 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
if (PT->isImageType())
return PtrKernelParam;
if (PT->isBooleanType())
return InvalidKernelParam;
if (PT->isEventT())
if (PT->isBooleanType() || PT->isEventT() || PT->isReserveIDT())
return InvalidKernelParam;
// OpenCL extension spec v1.2 s9.5:
@ -12176,7 +12176,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;
if (getLangOpts().CoroutinesTS && getCurFunction()->CoroutinePromise)
if (getLangOpts().CoroutinesTS && getCurFunction()->isCoroutine())
CheckCompletedCoroutineBody(FD, Body);
if (FD) {
@ -16097,7 +16097,8 @@ void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) {
void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
Module *Mod) {
// Bail if we're not allowed to implicitly import a module here.
if (isSFINAEContext() || !getLangOpts().ModulesErrorRecovery)
if (isSFINAEContext() || !getLangOpts().ModulesErrorRecovery ||
VisibleModules.isVisible(Mod))
return;
// Create the implicit import declaration.

View File

@ -238,7 +238,7 @@ static typename std::enable_if<std::is_base_of<clang::Attr, AttrInfo>::value,
getAttrName(const AttrInfo &Attr) {
return &Attr;
}
const IdentifierInfo *getAttrName(const clang::AttributeList &Attr) {
static const IdentifierInfo *getAttrName(const clang::AttributeList &Attr) {
return Attr.getName();
}
@ -949,7 +949,7 @@ static bool checkFunctionConditionAttr(Sema &S, Decl *D,
Msg = "<no message provided>";
SmallVector<PartialDiagnosticAt, 8> Diags;
if (!Cond->isValueDependent() &&
if (isa<FunctionDecl>(D) && !Cond->isValueDependent() &&
!Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D),
Diags)) {
S.Diag(Attr.getLoc(), diag::err_attr_cond_never_constant_expr)
@ -1037,10 +1037,11 @@ static void handleDiagnoseIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
auto *FD = cast<FunctionDecl>(D);
bool ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond);
bool ArgDependent = false;
if (const auto *FD = dyn_cast<FunctionDecl>(D))
ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond);
D->addAttr(::new (S.Context) DiagnoseIfAttr(
Attr.getRange(), S.Context, Cond, Msg, DiagType, ArgDependent, FD,
Attr.getRange(), S.Context, Cond, Msg, DiagType, ArgDependent, cast<NamedDecl>(D),
Attr.getAttributeSpellingListIndex()));
}
@ -7283,6 +7284,12 @@ class DiagnoseUnguardedAvailability
return true;
}
bool VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) {
SemaRef.Diag(E->getLocStart(), diag::warn_at_available_unchecked_use)
<< (!SemaRef.getLangOpts().ObjC1);
return true;
}
bool VisitTypeLoc(TypeLoc Ty);
};

View File

@ -10348,32 +10348,33 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
!Constructor->doesThisDeclarationHaveABody() &&
!Constructor->isDeleted()) &&
"DefineImplicitDefaultConstructor - call it for implicit default ctor");
if (Constructor->willHaveBody() || Constructor->isInvalidDecl())
return;
CXXRecordDecl *ClassDecl = Constructor->getParent();
assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
SynthesizedFunctionScope Scope(*this, Constructor);
DiagnosticErrorTrap Trap(Diags);
if (SetCtorInitializers(Constructor, /*AnyErrors=*/false) ||
Trap.hasErrorOccurred()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXDefaultConstructor << Context.getTagDeclType(ClassDecl);
Constructor->setInvalidDecl();
return;
}
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
Constructor->getType()->castAs<FunctionProtoType>());
MarkVTableUsed(CurrentLocation, ClassDecl);
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
if (SetCtorInitializers(Constructor, /*AnyErrors=*/false)) {
Constructor->setInvalidDecl();
return;
}
SourceLocation Loc = Constructor->getLocEnd().isValid()
? Constructor->getLocEnd()
: Constructor->getLocation();
Constructor->setBody(new (Context) CompoundStmt(Loc));
Constructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Constructor);
@ -10483,9 +10484,22 @@ void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation,
assert(Constructor->getInheritedConstructor() &&
!Constructor->doesThisDeclarationHaveABody() &&
!Constructor->isDeleted());
if (Constructor->isInvalidDecl())
if (Constructor->willHaveBody() || Constructor->isInvalidDecl())
return;
// Initializations are performed "as if by a defaulted default constructor",
// so enter the appropriate scope.
SynthesizedFunctionScope Scope(*this, Constructor);
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
Constructor->getType()->castAs<FunctionProtoType>());
MarkVTableUsed(CurrentLocation, ClassDecl);
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
ConstructorUsingShadowDecl *Shadow =
Constructor->getInheritedConstructor().getShadowDecl();
CXXConstructorDecl *InheritedCtor =
@ -10500,11 +10514,6 @@ void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation,
CXXRecordDecl *RD = Shadow->getParent();
SourceLocation InitLoc = Shadow->getLocation();
// Initializations are performed "as if by a defaulted default constructor",
// so enter the appropriate scope.
SynthesizedFunctionScope Scope(*this, Constructor);
DiagnosticErrorTrap Trap(Diags);
// Build explicit initializers for all base classes from which the
// constructor was inherited.
SmallVector<CXXCtorInitializer*, 8> Inits;
@ -10535,22 +10544,13 @@ void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation,
// We now proceed as if for a defaulted default constructor, with the relevant
// initializers replaced.
bool HadError = SetCtorInitializers(Constructor, /*AnyErrors*/false, Inits);
if (HadError || Trap.hasErrorOccurred()) {
Diag(CurrentLocation, diag::note_inhctor_synthesized_at) << RD;
if (SetCtorInitializers(Constructor, /*AnyErrors*/false, Inits)) {
Constructor->setInvalidDecl();
return;
}
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
Constructor->getType()->castAs<FunctionProtoType>());
Constructor->setBody(new (Context) CompoundStmt(InitLoc));
Constructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Constructor);
@ -10626,37 +10626,36 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
!Destructor->doesThisDeclarationHaveABody() &&
!Destructor->isDeleted()) &&
"DefineImplicitDestructor - call it for implicit default dtor");
if (Destructor->willHaveBody() || Destructor->isInvalidDecl())
return;
CXXRecordDecl *ClassDecl = Destructor->getParent();
assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
if (Destructor->isInvalidDecl())
return;
SynthesizedFunctionScope Scope(*this, Destructor);
DiagnosticErrorTrap Trap(Diags);
MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
Destructor->getParent());
if (CheckDestructor(Destructor) || Trap.hasErrorOccurred()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXDestructor << Context.getTagDeclType(ClassDecl);
Destructor->setInvalidDecl();
return;
}
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
Destructor->getType()->castAs<FunctionProtoType>());
MarkVTableUsed(CurrentLocation, ClassDecl);
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
Destructor->getParent());
if (CheckDestructor(Destructor)) {
Destructor->setInvalidDecl();
return;
}
SourceLocation Loc = Destructor->getLocEnd().isValid()
? Destructor->getLocEnd()
: Destructor->getLocation();
Destructor->setBody(new (Context) CompoundStmt(Loc));
Destructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Destructor);
@ -11224,8 +11223,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
/// Diagnose an implicit copy operation for a class which is odr-used, but
/// which is deprecated because the class has a user-declared copy constructor,
/// copy assignment operator, or destructor.
static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp,
SourceLocation UseLoc) {
static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp) {
assert(CopyOp->isImplicit());
CXXRecordDecl *RD = CopyOp->getParent();
@ -11264,10 +11262,6 @@ static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp,
diag::warn_deprecated_copy_operation)
<< RD << /*copy assignment*/!isa<CXXConstructorDecl>(CopyOp)
<< /*destructor*/isa<CXXDestructorDecl>(UserDeclaredOperation);
S.Diag(UseLoc, diag::note_member_synthesized_at)
<< (isa<CXXConstructorDecl>(CopyOp) ? Sema::CXXCopyConstructor
: Sema::CXXCopyAssignment)
<< RD;
}
}
@ -11279,25 +11273,31 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
!CopyAssignOperator->doesThisDeclarationHaveABody() &&
!CopyAssignOperator->isDeleted()) &&
"DefineImplicitCopyAssignment called for wrong function");
if (CopyAssignOperator->willHaveBody() || CopyAssignOperator->isInvalidDecl())
return;
CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent();
if (ClassDecl->isInvalidDecl() || CopyAssignOperator->isInvalidDecl()) {
if (ClassDecl->isInvalidDecl()) {
CopyAssignOperator->setInvalidDecl();
return;
}
SynthesizedFunctionScope Scope(*this, CopyAssignOperator);
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
CopyAssignOperator->getType()->castAs<FunctionProtoType>());
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
// C++11 [class.copy]p18:
// The [definition of an implicitly declared copy assignment operator] is
// deprecated if the class has a user-declared copy constructor or a
// user-declared destructor.
if (getLangOpts().CPlusPlus11 && CopyAssignOperator->isImplicit())
diagnoseDeprecatedCopyOperation(*this, CopyAssignOperator, CurrentLocation);
CopyAssignOperator->markUsed(Context);
SynthesizedFunctionScope Scope(*this, CopyAssignOperator);
DiagnosticErrorTrap Trap(Diags);
diagnoseDeprecatedCopyOperation(*this, CopyAssignOperator);
// C++0x [class.copy]p30:
// The implicitly-defined or explicitly-defaulted copy assignment operator
@ -11363,8 +11363,6 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
/*CopyingBaseSubobject=*/true,
/*Copying=*/true);
if (Copy.isInvalid()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
CopyAssignOperator->setInvalidDecl();
return;
}
@ -11390,8 +11388,6 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
<< Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
Invalid = true;
continue;
}
@ -11402,8 +11398,6 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
<< Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
Invalid = true;
continue;
}
@ -11436,8 +11430,6 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
/*CopyingBaseSubobject=*/false,
/*Copying=*/true);
if (Copy.isInvalid()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
CopyAssignOperator->setInvalidDecl();
return;
}
@ -11453,22 +11445,10 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
StmtResult Return = BuildReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
Invalid = true;
else {
else
Statements.push_back(Return.getAs<Stmt>());
if (Trap.hasErrorOccurred()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
Invalid = true;
}
}
}
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
CopyAssignOperator->getType()->castAs<FunctionProtoType>());
if (Invalid) {
CopyAssignOperator->setInvalidDecl();
return;
@ -11482,6 +11462,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
assert(!Body.isInvalid() && "Compound statement creation cannot fail");
}
CopyAssignOperator->setBody(Body.getAs<Stmt>());
CopyAssignOperator->markUsed(Context);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(CopyAssignOperator);
@ -11654,19 +11635,15 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
!MoveAssignOperator->doesThisDeclarationHaveABody() &&
!MoveAssignOperator->isDeleted()) &&
"DefineImplicitMoveAssignment called for wrong function");
if (MoveAssignOperator->willHaveBody() || MoveAssignOperator->isInvalidDecl())
return;
CXXRecordDecl *ClassDecl = MoveAssignOperator->getParent();
if (ClassDecl->isInvalidDecl() || MoveAssignOperator->isInvalidDecl()) {
if (ClassDecl->isInvalidDecl()) {
MoveAssignOperator->setInvalidDecl();
return;
}
MoveAssignOperator->markUsed(Context);
SynthesizedFunctionScope Scope(*this, MoveAssignOperator);
DiagnosticErrorTrap Trap(Diags);
// C++0x [class.copy]p28:
// The implicitly-defined or move assignment operator for a non-union class
// X performs memberwise move assignment of its subobjects. The direct base
@ -11679,6 +11656,16 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
// from a virtual base more than once.
checkMoveAssignmentForRepeatedMove(*this, ClassDecl, CurrentLocation);
SynthesizedFunctionScope Scope(*this, MoveAssignOperator);
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
MoveAssignOperator->getType()->castAs<FunctionProtoType>());
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
// The statements that form the synthesized function body.
SmallVector<Stmt*, 8> Statements;
@ -11743,8 +11730,6 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
/*CopyingBaseSubobject=*/true,
/*Copying=*/false);
if (Move.isInvalid()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
MoveAssignOperator->setInvalidDecl();
return;
}
@ -11770,8 +11755,6 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
<< Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
Invalid = true;
continue;
}
@ -11782,8 +11765,6 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
<< Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
Invalid = true;
continue;
}
@ -11819,8 +11800,6 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
/*CopyingBaseSubobject=*/false,
/*Copying=*/false);
if (Move.isInvalid()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
MoveAssignOperator->setInvalidDecl();
return;
}
@ -11837,22 +11816,10 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
StmtResult Return = BuildReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
Invalid = true;
else {
else
Statements.push_back(Return.getAs<Stmt>());
if (Trap.hasErrorOccurred()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
Invalid = true;
}
}
}
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
MoveAssignOperator->getType()->castAs<FunctionProtoType>());
if (Invalid) {
MoveAssignOperator->setInvalidDecl();
return;
@ -11866,6 +11833,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
assert(!Body.isInvalid() && "Compound statement creation cannot fail");
}
MoveAssignOperator->setBody(Body.getAs<Stmt>());
MoveAssignOperator->markUsed(Context);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(MoveAssignOperator);
@ -11952,30 +11920,37 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
}
void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *CopyConstructor) {
CXXConstructorDecl *CopyConstructor) {
assert((CopyConstructor->isDefaulted() &&
CopyConstructor->isCopyConstructor() &&
!CopyConstructor->doesThisDeclarationHaveABody() &&
!CopyConstructor->isDeleted()) &&
"DefineImplicitCopyConstructor - call it for implicit copy ctor");
if (CopyConstructor->willHaveBody() || CopyConstructor->isInvalidDecl())
return;
CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
SynthesizedFunctionScope Scope(*this, CopyConstructor);
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
CopyConstructor->getType()->castAs<FunctionProtoType>());
MarkVTableUsed(CurrentLocation, ClassDecl);
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
// C++11 [class.copy]p7:
// The [definition of an implicitly declared copy constructor] is
// deprecated if the class has a user-declared copy assignment operator
// or a user-declared destructor.
if (getLangOpts().CPlusPlus11 && CopyConstructor->isImplicit())
diagnoseDeprecatedCopyOperation(*this, CopyConstructor, CurrentLocation);
diagnoseDeprecatedCopyOperation(*this, CopyConstructor);
SynthesizedFunctionScope Scope(*this, CopyConstructor);
DiagnosticErrorTrap Trap(Diags);
if (SetCtorInitializers(CopyConstructor, /*AnyErrors=*/false) ||
Trap.hasErrorOccurred()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXCopyConstructor << Context.getTagDeclType(ClassDecl);
if (SetCtorInitializers(CopyConstructor, /*AnyErrors=*/false)) {
CopyConstructor->setInvalidDecl();
} else {
SourceLocation Loc = CopyConstructor->getLocEnd().isValid()
@ -11984,16 +11959,9 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
Sema::CompoundScopeRAII CompoundScope(*this);
CopyConstructor->setBody(
ActOnCompoundStmt(Loc, Loc, None, /*isStmtExpr=*/false).getAs<Stmt>());
CopyConstructor->markUsed(Context);
}
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
CopyConstructor->getType()->castAs<FunctionProtoType>());
CopyConstructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(CopyConstructor);
}
@ -12075,41 +12043,41 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
}
void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *MoveConstructor) {
CXXConstructorDecl *MoveConstructor) {
assert((MoveConstructor->isDefaulted() &&
MoveConstructor->isMoveConstructor() &&
!MoveConstructor->doesThisDeclarationHaveABody() &&
!MoveConstructor->isDeleted()) &&
"DefineImplicitMoveConstructor - call it for implicit move ctor");
if (MoveConstructor->willHaveBody() || MoveConstructor->isInvalidDecl())
return;
CXXRecordDecl *ClassDecl = MoveConstructor->getParent();
assert(ClassDecl && "DefineImplicitMoveConstructor - invalid constructor");
SynthesizedFunctionScope Scope(*this, MoveConstructor);
DiagnosticErrorTrap Trap(Diags);
if (SetCtorInitializers(MoveConstructor, /*AnyErrors=*/false) ||
Trap.hasErrorOccurred()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXMoveConstructor << Context.getTagDeclType(ClassDecl);
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
MoveConstructor->getType()->castAs<FunctionProtoType>());
MarkVTableUsed(CurrentLocation, ClassDecl);
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
if (SetCtorInitializers(MoveConstructor, /*AnyErrors=*/false)) {
MoveConstructor->setInvalidDecl();
} else {
} else {
SourceLocation Loc = MoveConstructor->getLocEnd().isValid()
? MoveConstructor->getLocEnd()
: MoveConstructor->getLocation();
Sema::CompoundScopeRAII CompoundScope(*this);
MoveConstructor->setBody(ActOnCompoundStmt(
Loc, Loc, None, /*isStmtExpr=*/ false).getAs<Stmt>());
MoveConstructor->markUsed(Context);
}
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
MoveConstructor->getType()->castAs<FunctionProtoType>());
MoveConstructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(MoveConstructor);
}
@ -12122,6 +12090,8 @@ bool Sema::isImplicitlyDeleted(FunctionDecl *FD) {
void Sema::DefineImplicitLambdaToFunctionPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv) {
SynthesizedFunctionScope Scope(*this, Conv);
CXXRecordDecl *Lambda = Conv->getParent();
CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
// If we are defining a specialization of a conversion to function-ptr
@ -12144,6 +12114,7 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
"Conversion operator must have a corresponding call operator");
CallOp = cast<CXXMethodDecl>(CallOpSpec);
}
// Mark the call operator referenced (and add to pending instantiations
// if necessary).
// For both the conversion and static-invoker template specializations
@ -12151,9 +12122,6 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
// to the PendingInstantiations.
MarkFunctionReferenced(CurrentLocation, CallOp);
SynthesizedFunctionScope Scope(*this, Conv);
DiagnosticErrorTrap Trap(Diags);
// Retrieve the static invoker...
CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker();
// ... and get the corresponding specialization for a generic lambda.
@ -12191,7 +12159,7 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Conv);
L->CompletedImplicitDefinition(Invoker);
}
}
}
@ -12202,10 +12170,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
{
assert(!Conv->getParent()->isGenericLambda());
Conv->markUsed(Context);
SynthesizedFunctionScope Scope(*this, Conv);
DiagnosticErrorTrap Trap(Diags);
// Copy-initialize the lambda object as needed to capture it.
Expr *This = ActOnCXXThis(CurrentLocation).get();
@ -12244,6 +12209,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
Conv->setBody(new (Context) CompoundStmt(Context, ReturnS,
Conv->getLocation(),
Conv->getLocation()));
Conv->markUsed(Context);
// We're done; notify the mutation listener, if any.
if (ASTMutationListener *L = getASTMutationListener()) {
@ -13971,6 +13937,11 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
MD->setDefaulted();
MD->setExplicitlyDefaulted();
// Unset that we will have a body for this function. We might not,
// if it turns out to be trivial, and we don't need this marking now
// that we've marked it as defaulted.
MD->setWillHaveBody(false);
// If this definition appears within the record, do the checking when
// the record is complete.
const FunctionDecl *Primary = MD;

View File

@ -366,8 +366,18 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD))
return true;
}
if (diagnoseArgIndependentDiagnoseIfAttrs(FD, Loc))
auto getReferencedObjCProp = [](const NamedDecl *D) ->
const ObjCPropertyDecl * {
if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->findPropertyDecl();
return nullptr;
};
if (const ObjCPropertyDecl *ObjCPDecl = getReferencedObjCProp(D)) {
if (diagnoseArgIndependentDiagnoseIfAttrs(ObjCPDecl, Loc))
return true;
} else if (diagnoseArgIndependentDiagnoseIfAttrs(D, Loc)) {
return true;
}
@ -15742,6 +15752,13 @@ ExprResult Sema::ActOnObjCAvailabilityCheckExpr(
if (Spec != AvailSpecs.end())
Version = Spec->getVersion();
// The use of `@available` in the enclosing function should be analyzed to
// warn when it's used inappropriately (i.e. not if(@available)).
if (getCurFunctionOrMethodDecl())
getEnclosingFunction()->HasPotentialAvailabilityViolations = true;
else if (getCurBlock() || getCurLambda())
getCurFunction()->HasPotentialAvailabilityViolations = true;
return new (Context)
ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy);
}

View File

@ -1591,6 +1591,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// its constexpr-ness, supressing diagnostics while doing so.
if (getLangOpts().CPlusPlus1z && !CallOperator->isInvalidDecl() &&
!CallOperator->isConstexpr() &&
!isa<CoroutineBodyStmt>(CallOperator->getBody()) &&
!Class->getDeclContext()->isDependentContext()) {
TentativeAnalysisScope DiagnosticScopeGuard(*this);
CallOperator->setConstexpr(

View File

@ -4929,8 +4929,6 @@ static NamedDecl *getDefinitionToImport(NamedDecl *D) {
void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
MissingImportKind MIK, bool Recover) {
assert(!isVisible(Decl) && "missing import for non-hidden decl?");
// Suggest importing a module providing the definition of this entity, if
// possible.
NamedDecl *Def = getDefinitionToImport(Decl);

View File

@ -6242,11 +6242,11 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
}
template <typename CheckFn>
static bool diagnoseDiagnoseIfAttrsWith(Sema &S, const FunctionDecl *FD,
static bool diagnoseDiagnoseIfAttrsWith(Sema &S, const NamedDecl *ND,
bool ArgDependent, SourceLocation Loc,
CheckFn &&IsSuccessful) {
SmallVector<const DiagnoseIfAttr *, 8> Attrs;
for (const auto *DIA : FD->specific_attrs<DiagnoseIfAttr>()) {
for (const auto *DIA : ND->specific_attrs<DiagnoseIfAttr>()) {
if (ArgDependent == DIA->getArgDependent())
Attrs.push_back(DIA);
}
@ -6293,16 +6293,16 @@ bool Sema::diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function,
// EvaluateWithSubstitution only cares about the position of each
// argument in the arg list, not the ParmVarDecl* it maps to.
if (!DIA->getCond()->EvaluateWithSubstitution(
Result, Context, DIA->getParent(), Args, ThisArg))
Result, Context, cast<FunctionDecl>(DIA->getParent()), Args, ThisArg))
return false;
return Result.isInt() && Result.getInt().getBoolValue();
});
}
bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const FunctionDecl *Function,
bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND,
SourceLocation Loc) {
return diagnoseDiagnoseIfAttrsWith(
*this, Function, /*ArgDependent=*/false, Loc,
*this, ND, /*ArgDependent=*/false, Loc,
[&](const DiagnoseIfAttr *DIA) {
bool Result;
return DIA->getCond()->EvaluateAsBooleanCondition(Result, Context) &&

View File

@ -197,6 +197,7 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
case DefaultTemplateArgumentChecking:
case DeclaringSpecialMember:
case DefiningSynthesizedFunction:
return false;
}
@ -624,6 +625,17 @@ void Sema::PrintInstantiationStack() {
diag::note_in_declaration_of_implicit_special_member)
<< cast<CXXRecordDecl>(Active->Entity) << Active->SpecialMember;
break;
case CodeSynthesisContext::DefiningSynthesizedFunction:
// FIXME: For synthesized members other than special members, produce a note.
auto *MD = dyn_cast<CXXMethodDecl>(Active->Entity);
auto CSM = MD ? getSpecialMember(MD) : CXXInvalid;
if (CSM != CXXInvalid) {
Diags.Report(Active->PointOfInstantiation,
diag::note_member_synthesized_at)
<< CSM << Context.getTagDeclType(MD->getParent());
}
break;
}
}
}
@ -666,6 +678,7 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
return Active->DeductionInfo;
case CodeSynthesisContext::DeclaringSpecialMember:
case CodeSynthesisContext::DefiningSynthesizedFunction:
// This happens in a context unrelated to template instantiation, so
// there is no SFINAE.
return None;

View File

@ -6945,6 +6945,19 @@ TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
if (DeallocRes.isInvalid())
return StmtError();
Builder.Deallocate = DeallocRes.get();
assert(S->getResultDecl() && "ResultDecl must already be built");
StmtResult ResultDecl = getDerived().TransformStmt(S->getResultDecl());
if (ResultDecl.isInvalid())
return StmtError();
Builder.ResultDecl = ResultDecl.get();
if (auto *ReturnStmt = S->getReturnStmt()) {
StmtResult Res = getDerived().TransformStmt(ReturnStmt);
if (Res.isInvalid())
return StmtError();
Builder.ReturnStmt = Res.get();
}
}
return getDerived().RebuildCoroutineBodyStmt(Builder);

View File

@ -116,7 +116,11 @@ CommonOptionsParser::CommonOptionsParser(
cl::HideUnrelatedOptions(Category);
Compilations.reset(FixedCompilationDatabase::loadFromCommandLine(argc, argv));
std::string ErrorMessage;
Compilations =
FixedCompilationDatabase::loadFromCommandLine(argc, argv, ErrorMessage);
if (!Compilations && !ErrorMessage.empty())
llvm::errs() << ErrorMessage;
cl::ParseCommandLineOptions(argc, argv, Overview);
cl::PrintOptionValues();
@ -125,7 +129,6 @@ CommonOptionsParser::CommonOptionsParser(
SourcePathList.empty())
return;
if (!Compilations) {
std::string ErrorMessage;
if (!BuildPath.empty()) {
Compilations =
CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage);

View File

@ -27,6 +27,7 @@
#include "llvm/Option/Arg.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <sstream>
#include <system_error>
using namespace clang;
@ -150,23 +151,21 @@ struct CompileJobAnalyzer {
// options.
class UnusedInputDiagConsumer : public DiagnosticConsumer {
public:
UnusedInputDiagConsumer() : Other(nullptr) {}
// Useful for debugging, chain diagnostics to another consumer after
// recording for our own purposes.
UnusedInputDiagConsumer(DiagnosticConsumer *Other) : Other(Other) {}
UnusedInputDiagConsumer(DiagnosticConsumer &Other) : Other(Other) {}
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) override {
if (Info.getID() == clang::diag::warn_drv_input_file_unused) {
// Arg 1 for this diagnostic is the option that didn't get used.
UnusedInputs.push_back(Info.getArgStdStr(0));
} else if (DiagLevel >= DiagnosticsEngine::Error) {
// If driver failed to create compilation object, show the diagnostics
// to user.
Other.HandleDiagnostic(DiagLevel, Info);
}
if (Other)
Other->HandleDiagnostic(DiagLevel, Info);
}
DiagnosticConsumer *Other;
DiagnosticConsumer &Other;
SmallVector<std::string, 2> UnusedInputs;
};
@ -205,9 +204,12 @@ struct MatchesAny {
/// \li false if \c Args cannot be used for compilation jobs (e.g.
/// contains an option like -E or -version).
static bool stripPositionalArgs(std::vector<const char *> Args,
std::vector<std::string> &Result) {
std::vector<std::string> &Result,
std::string &ErrorMsg) {
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
UnusedInputDiagConsumer DiagClient;
llvm::raw_string_ostream Output(ErrorMsg);
TextDiagnosticPrinter DiagnosticPrinter(Output, &*DiagOpts);
UnusedInputDiagConsumer DiagClient(DiagnosticPrinter);
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()),
&*DiagOpts, &DiagClient, false);
@ -245,6 +247,8 @@ static bool stripPositionalArgs(std::vector<const char *> Args,
const std::unique_ptr<driver::Compilation> Compilation(
NewDriver->BuildCompilation(Args));
if (!Compilation)
return false;
const driver::JobList &Jobs = Compilation->getJobs();
@ -258,8 +262,7 @@ static bool stripPositionalArgs(std::vector<const char *> Args,
}
if (CompileAnalyzer.Inputs.empty()) {
// No compile jobs found.
// FIXME: Emit a warning of some kind?
ErrorMsg = "warning: no compile jobs found\n";
return false;
}
@ -280,8 +283,14 @@ static bool stripPositionalArgs(std::vector<const char *> Args,
return true;
}
FixedCompilationDatabase *FixedCompilationDatabase::loadFromCommandLine(
int &Argc, const char *const *Argv, Twine Directory) {
std::unique_ptr<FixedCompilationDatabase>
FixedCompilationDatabase::loadFromCommandLine(int &Argc,
const char *const *Argv,
std::string &ErrorMsg,
Twine Directory) {
ErrorMsg.clear();
if (Argc == 0)
return nullptr;
const char *const *DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
if (DoubleDash == Argv + Argc)
return nullptr;
@ -289,9 +298,10 @@ FixedCompilationDatabase *FixedCompilationDatabase::loadFromCommandLine(
Argc = DoubleDash - Argv;
std::vector<std::string> StrippedArgs;
if (!stripPositionalArgs(CommandLine, StrippedArgs))
if (!stripPositionalArgs(CommandLine, StrippedArgs, ErrorMsg))
return nullptr;
return new FixedCompilationDatabase(Directory, StrippedArgs);
return std::unique_ptr<FixedCompilationDatabase>(
new FixedCompilationDatabase(Directory, StrippedArgs));
}
FixedCompilationDatabase::

View File

@ -260,6 +260,8 @@ bool ToolInvocation::run() {
Driver->setCheckInputsExist(false);
const std::unique_ptr<clang::driver::Compilation> Compilation(
Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
if (!Compilation)
return false;
const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
&Diagnostics, Compilation.get());
if (!CC1Args) {

View File

@ -167,7 +167,7 @@ namespace test3 {
Base2, // expected-error 2 {{base class 'test3::Base2' has private destructor}}
virtual Base3
{};
Derived3 d3; // expected-note {{implicit default constructor}}\
Derived3 d3; // expected-note 3{{implicit default constructor}}\
// expected-note{{implicit destructor}}}
#else
template <unsigned N> class Base { ~Base(); }; // expected-note 4{{declared private here}}

View File

@ -1,5 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s --check-prefix=ARM64
// REQUIRES: aarch64-registered-target,x86-registered-target
@ -60,6 +61,7 @@ SWIFTCALL void context_error_2(short s, CONTEXT int *self, ERROR float **error)
/********************************** LOWERING *********************************/
/*****************************************************************************/
typedef float float3 __attribute__((ext_vector_type(3)));
typedef float float4 __attribute__((ext_vector_type(4)));
typedef float float8 __attribute__((ext_vector_type(8)));
typedef double double2 __attribute__((ext_vector_type(2)));
@ -1005,3 +1007,10 @@ struct {
TEST(union_het_vecint)
// CHECK: define swiftcc void @return_union_het_vecint([[UNION:%.*]]* noalias sret
// CHECK: define swiftcc void @take_union_het_vecint([[UNION]]*
typedef struct {
float3 f3;
} struct_v1f3;
TEST(struct_v1f3)
// ARM64-LABEL: define swiftcc { <2 x float>, float } @return_struct_v1f3()
// ARM64-LABEL: define swiftcc void @take_struct_v1f3(<2 x float>, float)

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// Test new aarch64 intrinsics and types

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// Test new aarch64 intrinsics and types

View File

@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \
// RUN: -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// Test new aarch64 intrinsics and types

View File

@ -1,6 +1,6 @@
// REQUIRES: aarch64-registered-target
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \
// RUN: -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// Test new aarch64 intrinsics and types

View File

@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \
// RUN: -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// Test new aarch64 intrinsics and types

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -S -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// Test new aarch64 intrinsics and types

View File

@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \
// RUN: -fallow-half-arguments-and-returns -S -emit-llvm -o - %s \
// RUN: -fallow-half-arguments-and-returns -S -disable-O0-optnone -emit-llvm -o - %s \
// RUN: | opt -S -mem2reg \
// RUN: | FileCheck %s

Some files were not shown because too many files have changed in this diff Show More