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
251 changed files with 5069 additions and 1338 deletions

View File

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

View File

@ -1963,6 +1963,47 @@ TypeKind.DEPENDENTSIZEDARRAY = TypeKind(116)
TypeKind.MEMBERPOINTER = TypeKind(117) TypeKind.MEMBERPOINTER = TypeKind(117)
TypeKind.AUTO = TypeKind(118) TypeKind.AUTO = TypeKind(118)
TypeKind.ELABORATED = TypeKind(119) 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): class RefQualifierKind(BaseEnumeration):
"""Describes a specific ref-qualifier of a type.""" """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 blocks
The "blocks" language feature is available. The "blocks" language feature is available.
coroutines
Support for the coroutines TS is available.
cplusplus cplusplus
C++ support is available. C++ support is available.

View File

@ -32,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/ */
#define CINDEX_VERSION_MAJOR 0 #define CINDEX_VERSION_MAJOR 0
#define CINDEX_VERSION_MINOR 39 #define CINDEX_VERSION_MINOR 40
#define CINDEX_VERSION_ENCODE(major, minor) ( \ #define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \ ((major) * 10000) \
@ -3076,7 +3076,52 @@ enum CXTypeKind {
* *
* E.g., struct S, or via a qualified name, e.g., N::M::type, or both. * 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 @@ public:
} }
Designator *getDesignator(unsigned Idx) { return &designators()[Idx]; } Designator *getDesignator(unsigned Idx) { return &designators()[Idx]; }
const Designator *getDesignator(unsigned Idx) const {
return &designators()[Idx];
}
void setDesignators(const ASTContext &C, const Designator *Desigs, void setDesignators(const ASTContext &C, const Designator *Desigs,
unsigned NumDesigs); unsigned NumDesigs);

View File

@ -308,7 +308,9 @@ class CoroutineBodyStmt final
OnFallthrough, ///< Handler for control flow falling off the body. OnFallthrough, ///< Handler for control flow falling off the body.
Allocate, ///< Coroutine frame memory allocation. Allocate, ///< Coroutine frame memory allocation.
Deallocate, ///< Coroutine frame memory deallocation. 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. ReturnStmtOnAllocFailure, ///< Return statement if allocation failed.
FirstParamMove ///< First offset for move construction of parameter copies. FirstParamMove ///< First offset for move construction of parameter copies.
}; };
@ -332,7 +334,9 @@ public:
Stmt *OnFallthrough = nullptr; Stmt *OnFallthrough = nullptr;
Expr *Allocate = nullptr; Expr *Allocate = nullptr;
Expr *Deallocate = nullptr; Expr *Deallocate = nullptr;
Stmt *ReturnValue = nullptr; Expr *ReturnValue = nullptr;
Stmt *ResultDecl = nullptr;
Stmt *ReturnStmt = nullptr;
Stmt *ReturnStmtOnAllocFailure = nullptr; Stmt *ReturnStmtOnAllocFailure = nullptr;
ArrayRef<Stmt *> ParamMoves; ArrayRef<Stmt *> ParamMoves;
}; };
@ -381,10 +385,11 @@ public:
Expr *getDeallocate() const { Expr *getDeallocate() const {
return cast_or_null<Expr>(getStoredStmts()[SubStmt::Deallocate]); return cast_or_null<Expr>(getStoredStmts()[SubStmt::Deallocate]);
} }
Expr *getReturnValueInit() const { 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 { Stmt *getReturnStmtOnAllocFailure() const {
return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure]; 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, class FunctionArgument<string name, bit opt = 0, bit fake = 0> : Argument<name,
opt, opt,
fake>; 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 TypeArgument<string name, bit opt = 0> : Argument<name, opt>;
class UnsignedArgument<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>; class VariadicUnsignedArgument<string name> : Argument<name, 1>;
@ -1819,14 +1822,14 @@ def Unavailable : InheritableAttr {
def DiagnoseIf : InheritableAttr { def DiagnoseIf : InheritableAttr {
let Spellings = [GNU<"diagnose_if">]; let Spellings = [GNU<"diagnose_if">];
let Subjects = SubjectList<[Function]>; let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty]>;
let Args = [ExprArgument<"Cond">, StringArgument<"Message">, let Args = [ExprArgument<"Cond">, StringArgument<"Message">,
EnumArgument<"DiagnosticType", EnumArgument<"DiagnosticType",
"DiagnosticType", "DiagnosticType",
["error", "warning"], ["error", "warning"],
["DT_Error", "DT_Warning"]>, ["DT_Error", "DT_Warning"]>,
BoolArgument<"ArgDependent", 0, /*fake*/ 1>, BoolArgument<"ArgDependent", 0, /*fake*/ 1>,
FunctionArgument<"Parent", 0, /*fake*/ 1>]; NamedArgument<"Parent", 0, /*fake*/ 1>];
let DuplicatesAllowedWhileMerging = 1; let DuplicatesAllowedWhileMerging = 1;
let LateParsed = 1; let LateParsed = 1;
let AdditionalMembers = [{ let AdditionalMembers = [{

View File

@ -36,6 +36,7 @@ BUILTIN(__builtin_amdgcn_workitem_id_z, "Ui", "nc")
// Instruction builtins. // Instruction builtins.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
BUILTIN(__builtin_amdgcn_s_getreg, "UiIi", "n") 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_waitcnt, "vIi", "n")
BUILTIN(__builtin_amdgcn_s_sendmsg, "vIiUi", "n") BUILTIN(__builtin_amdgcn_s_sendmsg, "vIiUi", "n")
BUILTIN(__builtin_amdgcn_s_sendmsghalt, "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_insertword, "V16UcV4UiV16UcIi", "")
BUILTIN(__builtin_vsx_extractuword, "V2ULLiV16UcIi", "") BUILTIN(__builtin_vsx_extractuword, "V2ULLiV16UcIi", "")
BUILTIN(__builtin_vsx_xxpermdi, "v.", "t")
BUILTIN(__builtin_vsx_xxsldwi, "v.", "t")
// HTM builtins // HTM builtins
BUILTIN(__builtin_tbegin, "UiUIi", "") BUILTIN(__builtin_tbegin, "UiUIi", "")
BUILTIN(__builtin_tend, "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_vplzcntd_512_mask, "V16iV16iV16iUs", "", "avx512cd")
TARGET_BUILTIN(__builtin_ia32_vplzcntq_512_mask, "V8LLiV8LLiV8LLiUc", "", "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_vpermi2varhi128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
TARGET_BUILTIN(__builtin_ia32_vpermi2varhi256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw") TARGET_BUILTIN(__builtin_ia32_vpermi2varhi256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
TARGET_BUILTIN(__builtin_ia32_vpermt2varhi128_mask, "V8sV8sV8sV8sUc", "", "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) VALUE_DIAGOPT(ConstexprBacktraceLimit, 32, DefaultConstexprBacktraceLimit)
/// Limit number of times to perform spell checking. /// Limit number of times to perform spell checking.
VALUE_DIAGOPT(SpellCheckingLimit, 32, DefaultSpellCheckingLimit) 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. VALUE_DIAGOPT(TabStop, 32, DefaultTabStop) /// The distance between tab stops.
/// Column limit for formatting message diagnostics, or 0 if unused. /// Column limit for formatting message diagnostics, or 0 if unused.

View File

@ -63,11 +63,15 @@ public:
enum TextDiagnosticFormat { Clang, MSVC, Vi }; enum TextDiagnosticFormat { Clang, MSVC, Vi };
// Default values. // Default values.
enum { DefaultTabStop = 8, MaxTabStop = 100, enum {
DefaultTabStop = 8,
MaxTabStop = 100,
DefaultMacroBacktraceLimit = 6, DefaultMacroBacktraceLimit = 6,
DefaultTemplateBacktraceLimit = 10, DefaultTemplateBacktraceLimit = 10,
DefaultConstexprBacktraceLimit = 10, DefaultConstexprBacktraceLimit = 10,
DefaultSpellCheckingLimit = 50 }; DefaultSpellCheckingLimit = 50,
DefaultSnippetLineLimit = 1,
};
// Define simple diagnostic options (with no accessors). // Define simple diagnostic options (with no accessors).
#define DIAGOPT(Name, Bits, Default) unsigned Name : Bits; #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< def err_falloff_nonvoid_block : Error<
"control reaches end of non-void block">; "control reaches end of non-void block">;
def warn_maybe_falloff_nonvoid_coroutine : Warning< 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>; InGroup<ReturnType>;
def warn_falloff_nonvoid_coroutine : Warning< 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>; InGroup<ReturnType>;
def warn_suggest_noreturn_function : Warning< def warn_suggest_noreturn_function : Warning<
"%select{function|method}0 %1 could be declared with attribute 'noreturn'">, "%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_bitfield_decl : Note<"bit-field is declared here">;
def note_implicit_param_decl : Note<"%0 is an implicit parameter">; def note_implicit_param_decl : Note<"%0 is an implicit parameter">;
def note_member_synthesized_at : Note< def note_member_synthesized_at : Note<
"implicit %select{default constructor|copy constructor|move constructor|copy " "in implicit %select{default constructor|copy constructor|move constructor|"
"assignment operator|move assignment operator|destructor}0 for %1 first " "copy assignment operator|move assignment operator|destructor}0 for %1 "
"required here">; "first required here">;
def note_inhctor_synthesized_at : Note<
"inherited constructor for %0 first required here">;
def err_missing_default_ctor : Error< def err_missing_default_ctor : Error<
"%select{constructor for %1 must explicitly initialize the|" "%select{constructor for %1 must explicitly initialize the|"
"implicit default 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" "|types and namespaces"
"|Objective-C interfaces" "|Objective-C interfaces"
"|methods and properties" "|methods and properties"
"|functions, methods, and properties"
"|struct or union" "|struct or union"
"|struct, union or class" "|struct, union or class"
"|types" "|types"
@ -2883,6 +2882,10 @@ def warn_partial_message : Warning<"%0 is partial: %1">,
def warn_partial_fwdclass_message : Warning< def warn_partial_fwdclass_message : Warning<
"%0 may be partial because the receiver type is unknown">, "%0 may be partial because the receiver type is unknown">,
InGroup<UnguardedAvailability>, DefaultIgnore; 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 // Thread Safety Attributes
def warn_invalid_capability_name : Warning< def warn_invalid_capability_name : Warning<
@ -6298,6 +6301,8 @@ def warn_ambiguous_suitable_delete_function_found : Warning<
InGroup<DiagGroup<"ambiguous-delete">>; InGroup<DiagGroup<"ambiguous-delete">>;
def note_member_declared_here : Note< def note_member_declared_here : Note<
"member %0 declared here">; "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 err_decrement_bool : Error<"cannot decrement expression of type bool">;
def warn_increment_bool : Warning< def warn_increment_bool : Warning<
"incrementing expression of type bool is deprecated and " "incrementing expression of type bool is deprecated and "
@ -8009,10 +8014,13 @@ def err_block_on_nonlocal : Error<
def err_block_on_vm : Error< def err_block_on_vm : Error<
"__block attribute not allowed on declaration with a variably modified type">; "__block attribute not allowed on declaration with a variably modified type">;
def err_shufflevector_non_vector : Error< def err_vec_builtin_non_vector : Error<
"first two arguments to __builtin_shufflevector must be vectors">; "first two arguments to %0 must be vectors">;
def err_shufflevector_incompatible_vector : Error< def err_vec_builtin_incompatible_vector : Error<
"first two arguments to __builtin_shufflevector must have the same type">; "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< def err_shufflevector_nonconstant_argument : Error<
"index for __builtin_shufflevector must be a constant integer">; "index for __builtin_shufflevector must be a constant integer">;
def err_shufflevector_argument_too_large : Error< 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< def note_redefinition_modules_same_file : Note<
"'%0' included multiple times, additional include site in header from module '%1'">; "'%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< def note_redefinition_include_same_file : Note<
"'%0' included multiple times, additional include site here">; "'%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< def err_coroutine_type_missing_specialization : Error<
"this function cannot be a coroutine: missing definition of " "this function cannot be a coroutine: missing definition of "
"specialization %q0">; "specialization %q0">;
def err_coroutine_promise_return_ill_formed : Error< def err_coroutine_promise_incompatible_return_functions : Error<
"%0 declares both 'return_value' and 'return_void'">; "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< def note_coroutine_promise_implicit_await_transform_required_here : Note<
"call to 'await_transform' implicitly required by 'co_await' here">; "call to 'await_transform' implicitly required by 'co_await' here">;
def note_coroutine_promise_suspend_implicitly_required : Note< def note_coroutine_promise_suspend_implicitly_required : Note<
@ -8958,11 +8966,19 @@ def warn_coroutine_promise_unhandled_exception_required_with_exceptions : Warnin
InGroup<CoroutineMissingUnhandledException>; InGroup<CoroutineMissingUnhandledException>;
def err_coroutine_promise_get_return_object_on_allocation_failure : Error< def err_coroutine_promise_get_return_object_on_allocation_failure : Error<
"%0: 'get_return_object_on_allocation_failure()' must be a static member function">; "%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< def err_coroutine_promise_new_requires_nothrow : Error<
"%0 is required to have a non-throwing noexcept specification when the promise " "%0 is required to have a non-throwing noexcept specification when the promise "
"type declares 'get_return_object_on_allocation_failure()'">; "type declares 'get_return_object_on_allocation_failure()'">;
def note_coroutine_promise_call_implicitly_required : Note< def note_coroutine_promise_call_implicitly_required : Note<
"call to %0 implicitly required by coroutine function here">; "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 { let CategoryName = "Documentation Issue" in {

View File

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

View File

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

View File

@ -26,13 +26,21 @@ enum TemplateNameKind {
TNK_Function_template, TNK_Function_template,
/// The name refers to a template whose specialization produces a /// The name refers to a template whose specialization produces a
/// type. The template itself could be a class template, template /// 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, TNK_Type_template,
/// The name refers to a variable template whose specialization produces a /// The name refers to a variable template whose specialization produces a
/// variable. /// variable.
TNK_Var_template, TNK_Var_template,
/// The name refers to a dependent template name. Whether the /// The name refers to a dependent template name:
/// template name is assumed to refer to a type template or a /// \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 /// function template depends on the context in which the template
/// name occurs. /// name occurs.
TNK_Dependent_template_name TNK_Dependent_template_name

View File

@ -37,6 +37,7 @@ public:
NONE, NONE,
ALWAYS, ALWAYS,
NEVER, NEVER,
ALWAYS_ARG1,
}; };
ImbueAttribute shouldImbueFunction(StringRef FunctionName) const; 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">, def disable_lifetimemarkers : Flag<["-"], "disable-lifetime-markers">,
HelpText<"Disable lifetime-markers emission even when optimizations are " HelpText<"Disable lifetime-markers emission even when optimizations are "
"enabled">; "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">, def disable_red_zone : Flag<["-"], "disable-red-zone">,
HelpText<"Do not emit code that uses the red zone.">; HelpText<"Do not emit code that uses the red zone.">;
def dwarf_column_info : Flag<["-"], "dwarf-column-info">, 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).">; 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>">, 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).">; 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>">, def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">,
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
def verify : Flag<["-"], "verify">, 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 : Separate<["-"], "arch">, Flags<[DriverOption]>;
def arch__only : Separate<["-"], "arch_only">; def arch__only : Separate<["-"], "arch_only">;
def a : Joined<["-"], "a">; def a : Joined<["-"], "a">;
def autocomplete : Joined<["--"], "autocomplete=">;
def bind__at__load : Flag<["-"], "bind_at_load">; def bind__at__load : Flag<["-"], "bind_at_load">;
def bundle__loader : Separate<["-"], "bundle_loader">; def bundle__loader : Separate<["-"], "bundle_loader">;
def bundle : Flag<["-"], "bundle">; 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_avx2 : Flag<["-"], "mno-avx2">, Group<m_x86_Features_Group>;
def mno_avx512f : Flag<["-"], "mno-avx512f">, 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_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_avx512er : Flag<["-"], "mno-avx512er">, Group<m_x86_Features_Group>;
def mno_avx512pf : Flag<["-"], "mno-avx512pf">, 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>; 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 mavx2 : Flag<["-"], "mavx2">, Group<m_x86_Features_Group>;
def mavx512f : Flag<["-"], "mavx512f">, Group<m_x86_Features_Group>; def mavx512f : Flag<["-"], "mavx512f">, Group<m_x86_Features_Group>;
def mavx512cd : Flag<["-"], "mavx512cd">, 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 mavx512er : Flag<["-"], "mavx512er">, Group<m_x86_Features_Group>;
def mavx512pf : Flag<["-"], "mavx512pf">, Group<m_x86_Features_Group>; def mavx512pf : Flag<["-"], "mavx512pf">, Group<m_x86_Features_Group>;
def mavx512dq : Flag<["-"], "mavx512dq">, Group<m_x86_Features_Group>; def mavx512dq : Flag<["-"], "mavx512dq">, Group<m_x86_Features_Group>;

View File

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

View File

@ -59,6 +59,10 @@ class TargetInfo;
class FrontendAction; class FrontendAction;
class ASTDeserializationListener; class ASTDeserializationListener;
namespace vfs {
class FileSystem;
}
/// \brief Utility class for loading a ASTContext from an AST file. /// \brief Utility class for loading a ASTContext from an AST file.
/// ///
class ASTUnit : public ModuleLoader { class ASTUnit : public ModuleLoader {
@ -420,7 +424,8 @@ private:
explicit ASTUnit(bool MainFileIsAST); explicit ASTUnit(bool MainFileIsAST);
bool Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, 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 { struct ComputedPreamble {
llvm::MemoryBuffer *Buffer; llvm::MemoryBuffer *Buffer;
@ -434,11 +439,13 @@ private:
PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {} PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {}
}; };
ComputedPreamble ComputePreamble(CompilerInvocation &Invocation, ComputedPreamble ComputePreamble(CompilerInvocation &Invocation,
unsigned MaxLines); unsigned MaxLines,
IntrusiveRefCntPtr<vfs::FileSystem> VFS);
std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble( std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble(
std::shared_ptr<PCHContainerOperations> PCHContainerOps, std::shared_ptr<PCHContainerOperations> PCHContainerOps,
const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild = true, const CompilerInvocation &PreambleInvocationIn,
IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild = true,
unsigned MaxLines = 0); unsigned MaxLines = 0);
void RealizeTopLevelDeclsFromPreamble(); void RealizeTopLevelDeclsFromPreamble();
@ -731,11 +738,17 @@ private:
/// of this translation unit should be precompiled, to improve the performance /// of this translation unit should be precompiled, to improve the performance
/// of reparsing. Set to zero to disable preambles. /// 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 /// \returns \c true if a catastrophic failure occurred (which means that the
/// \c ASTUnit itself is invalid), or \c false otherwise. /// \c ASTUnit itself is invalid), or \c false otherwise.
bool LoadFromCompilerInvocation( bool LoadFromCompilerInvocation(
std::shared_ptr<PCHContainerOperations> PCHContainerOps, std::shared_ptr<PCHContainerOperations> PCHContainerOps,
unsigned PrecompilePreambleAfterNParses); unsigned PrecompilePreambleAfterNParses,
IntrusiveRefCntPtr<vfs::FileSystem> VFS);
public: public:
@ -826,6 +839,11 @@ public:
/// (e.g. because the PCH could not be loaded), this accepts the ASTUnit /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
/// mainly to allow the caller to see the diagnostics. /// 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 // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
// shouldn't need to specify them at construction time. // shouldn't need to specify them at construction time.
static ASTUnit *LoadFromCommandLine( static ASTUnit *LoadFromCommandLine(
@ -842,15 +860,23 @@ public:
bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false, bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false,
bool UserFilesAreVolatile = false, bool ForSerialization = false, bool UserFilesAreVolatile = false, bool ForSerialization = false,
llvm::Optional<StringRef> ModuleFormat = llvm::None, 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 /// \brief Reparse the source files using the same command-line options that
/// were originally used to produce this translation unit. /// 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 /// \returns True if a failure occurred that causes the ASTUnit not to
/// contain any translation-unit information, false otherwise. /// contain any translation-unit information, false otherwise.
bool Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, 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 /// \brief Perform code completion at the given file, line, and
/// column within this translation unit. /// 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 ///< the pristine IR generated by the
///< frontend. ///< frontend.
CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any lifetime markers 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 CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental
///< pass manager. ///< pass manager.
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled. CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.

View File

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

View File

@ -257,6 +257,23 @@ private:
/// resolved. /// resolved.
Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const; 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. /// \brief Looks up the modules that \p File corresponds to.
/// ///
/// If \p File represents a builtin header within Clang's builtin include /// If \p File represents a builtin header within Clang's builtin include

View File

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

View File

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

View File

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

View File

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

View File

@ -60,16 +60,6 @@ struct CompileCommand {
/// The output file associated with the command. /// The output file associated with the command.
std::string Output; 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. /// \brief Interface for compilation databases.
@ -186,9 +176,10 @@ public:
/// the number of arguments before "--", if "--" was found in the argument /// the number of arguments before "--", if "--" was found in the argument
/// list. /// list.
/// \param Argv Points to the command line arguments. /// \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. /// \param Directory The base directory used in the FixedCompilationDatabase.
static FixedCompilationDatabase *loadFromCommandLine(int &Argc, static std::unique_ptr<FixedCompilationDatabase> loadFromCommandLine(
const char *const *Argv, int &Argc, const char *const *Argv, std::string &ErrorMsg,
Twine Directory = "."); Twine Directory = ".");
/// \brief Constructs a compilation data base from a specified directory /// \brief Constructs a compilation data base from a specified directory

View File

@ -274,9 +274,17 @@ void Decl::setLexicalDeclContext(DeclContext *DC) {
} else { } else {
getMultipleDC()->LexicalDC = DC; getMultipleDC()->LexicalDC = DC;
} }
Hidden = cast<Decl>(DC)->Hidden;
if (Hidden && !isFromASTFile() && hasLocalOwningModuleStorage()) // 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()); setLocalOwningModule(cast<Decl>(DC)->getOwningModule());
}
assert((!Hidden || getOwningModule()) &&
"hidden declaration has no owning module");
} }
void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC, void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
@ -440,7 +448,7 @@ const Attr *Decl::getDefiningAttr() const {
return nullptr; return nullptr;
} }
StringRef getRealizedPlatform(const AvailabilityAttr *A, static StringRef getRealizedPlatform(const AvailabilityAttr *A,
const ASTContext &Context) { const ASTContext &Context) {
// Check if this is an App Extension "platform", and if so chop off // Check if this is an App Extension "platform", and if so chop off
// the suffix for matching with the actual platform. // the suffix for matching with the actual platform.

View File

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

View File

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

View File

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

View File

@ -92,6 +92,8 @@ Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
IsAutosynthesized = false; IsAutosynthesized = false;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Stmt *Body = FD->getBody(); Stmt *Body = FD->getBody();
if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
Body = CoroBody->getBody();
if (Manager && Manager->synthesizeBodies()) { if (Manager && Manager->synthesizeBodies()) {
Stmt *SynthesizedBody = Stmt *SynthesizedBody =
getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(FD); 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) bool HasFeature = llvm::StringSwitch<bool>(Feature)
.Case("altivec", LangOpts.AltiVec) .Case("altivec", LangOpts.AltiVec)
.Case("blocks", LangOpts.Blocks) .Case("blocks", LangOpts.Blocks)
.Case("coroutines", LangOpts.CoroutinesTS)
.Case("cplusplus", LangOpts.CPlusPlus) .Case("cplusplus", LangOpts.CPlusPlus)
.Case("cplusplus11", LangOpts.CPlusPlus11) .Case("cplusplus11", LangOpts.CPlusPlus11)
.Case("freestanding", LangOpts.Freestanding) .Case("freestanding", LangOpts.Freestanding)

View File

@ -183,48 +183,22 @@ unsigned LineTableInfo::getLineTableFilenameID(StringRef Name) {
return IterBool.first->second; return IterBool.first->second;
} }
/// AddLineNote - Add a line note to the line table that indicates that there /// Add a line note to the line table that indicates that there is a \#line or
/// is a \#line at the specified FID/Offset location which changes the presumed /// GNU line marker at the specified FID/Offset location which changes the
/// location to LineNo/FilenameID. /// presumed location to LineNo/FilenameID. If EntryExit is 0, then this doesn't
void LineTableInfo::AddLineNote(FileID FID, unsigned Offset, /// change the presumed \#include stack. If it is 1, this is a file entry, if
unsigned LineNo, int FilenameID) { /// it is 2 then this is a file exit. FileKind specifies whether this is a
std::vector<LineEntry> &Entries = LineEntries[FID]; /// system header or extern C system header.
void LineTableInfo::AddLineNote(FileID FID, unsigned Offset, unsigned LineNo,
assert((Entries.empty() || Entries.back().FileOffset < Offset) && int FilenameID, unsigned EntryExit,
"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,
SrcMgr::CharacteristicKind FileKind) { SrcMgr::CharacteristicKind FileKind) {
assert(FilenameID != -1 && "Unspecified filename should use other accessor");
std::vector<LineEntry> &Entries = LineEntries[FID]; 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) && assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
"Adding line entries out of order!"); "Adding line entries out of order!");
@ -281,40 +255,13 @@ unsigned SourceManager::getLineTableFilenameID(StringRef Name) {
return getLineTable().getLineTableFilenameID(Name); return getLineTable().getLineTableFilenameID(Name);
} }
/// AddLineNote - Add a line note to the line table for the FileID and offset /// 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 /// specified by Loc. If FilenameID is -1, it is considered to be
/// unspecified. /// 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, void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
int FilenameID, bool IsFileEntry, int FilenameID, bool IsFileEntry,
bool IsFileExit, bool IsSystemHeader, bool IsFileExit,
bool IsExternCHeader) { SrcMgr::CharacteristicKind FileKind) {
// 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);
}
std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
bool Invalid = false; bool Invalid = false;
@ -329,14 +276,6 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
(void) getLineTable(); (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; unsigned EntryExit = 0;
if (IsFileEntry) if (IsFileEntry)
EntryExit = 1; EntryExit = 1;

View File

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

View File

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

View File

@ -7332,10 +7332,12 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
AVX512PF, AVX512PF,
AVX512VBMI, AVX512VBMI,
AVX512IFMA, AVX512IFMA,
AVX512VPOPCNTDQ,
MAX MAX
}; };
X86Features Feature = StringSwitch<X86Features>(FeatureStr) X86Features Feature =
StringSwitch<X86Features>(FeatureStr)
.Case("cmov", X86Features::CMOV) .Case("cmov", X86Features::CMOV)
.Case("mmx", X86Features::MMX) .Case("mmx", X86Features::MMX)
.Case("popcnt", X86Features::POPCNT) .Case("popcnt", X86Features::POPCNT)
@ -7364,6 +7366,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
.Case("avx512pf", X86Features::AVX512PF) .Case("avx512pf", X86Features::AVX512PF)
.Case("avx512vbmi", X86Features::AVX512VBMI) .Case("avx512vbmi", X86Features::AVX512VBMI)
.Case("avx512ifma", X86Features::AVX512IFMA) .Case("avx512ifma", X86Features::AVX512IFMA)
.Case("avx512vpopcntdq", X86Features::AVX512VPOPCNTDQ)
.Default(X86Features::MAX); .Default(X86Features::MAX);
assert(Feature != X86Features::MAX && "Invalid feature!"); assert(Feature != X86Features::MAX && "Invalid feature!");
@ -7517,7 +7520,12 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_storesd128_mask: { case X86::BI__builtin_ia32_storesd128_mask: {
return EmitX86MaskedStore(*this, Ops, 16); 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_cvtmask2b128:
case X86::BI__builtin_ia32_cvtmask2b256: case X86::BI__builtin_ia32_cvtmask2b256:
case X86::BI__builtin_ia32_cvtmask2b512: case X86::BI__builtin_ia32_cvtmask2b512:
@ -8442,6 +8450,80 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(F, Ops); 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 "CodeGenFunction.h"
#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/ScopeExit.h"
#include "clang/AST/StmtCXX.h" #include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtVisitor.h"
using namespace clang; using namespace clang;
using namespace CodeGen; using namespace CodeGen;
@ -57,6 +59,15 @@ struct clang::CodeGen::CGCoroData {
// builtin. // builtin.
llvm::CallInst *CoroId = nullptr; 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 // If coro.id came from the builtin, remember the expression to give better
// diagnostic. If CoroIdExpr is nullptr, the coro.id was created by // diagnostic. If CoroIdExpr is nullptr, the coro.id was created by
// EmitCoroutineBody. // EmitCoroutineBody.
@ -142,6 +153,20 @@ static RValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro,
AwaitKind Kind, AggValueSlot aggSlot, AwaitKind Kind, AggValueSlot aggSlot,
bool ignoreResult) { bool ignoreResult) {
auto *E = S.getCommonExpr(); 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 = auto Binder =
CodeGenFunction::OpaqueValueMappingData::bind(CGF, S.getOpaqueValue(), E); CodeGenFunction::OpaqueValueMappingData::bind(CGF, S.getOpaqueValue(), E);
auto UnbindOnExit = llvm::make_scope_exit([&] { Binder.unbind(CGF); }); auto UnbindOnExit = llvm::make_scope_exit([&] { Binder.unbind(CGF); });
@ -215,7 +240,67 @@ void CodeGenFunction::EmitCoreturnStmt(CoreturnStmt const &S) {
EmitBranchThroughCleanup(CurCoro.Data->FinalJD); 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. // belongs to. That information is passed in a funclet bundle.
static SmallVector<llvm::OperandBundleDef, 1> static SmallVector<llvm::OperandBundleDef, 1>
getBundlesForCoroEnd(CodeGenFunction &CGF) { getBundlesForCoroEnd(CodeGenFunction &CGF) {
@ -257,24 +342,135 @@ namespace {
struct CallCoroDelete final : public EHScopeStack::Cleanup { struct CallCoroDelete final : public EHScopeStack::Cleanup {
Stmt *Deallocate; Stmt *Deallocate;
// TODO: Wrap deallocate in if(coro.free(...)) Deallocate. // Emit "if (coro.free(CoroId, CoroBegin)) Deallocate;"
void Emit(CodeGenFunction &CGF, Flags) override {
// Note: That deallocation will be emitted twice: once for a normal exit and // 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 // once for exceptional exit. This usage is safe because Deallocate does not
// contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr() // contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr()
// builds a single call to a deallocation function which is safe to emit // builds a single call to a deallocation function which is safe to emit
// multiple times. // multiple times.
void Emit(CodeGenFunction &CGF, Flags) override {
// 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); 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) {} 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) { void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy()); auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
auto &TI = CGM.getContext().getTargetInfo(); auto &TI = CGM.getContext().getTargetInfo();
unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth(); 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 *FinalBB = createBasicBlock("coro.final");
auto *RetBB = createBasicBlock("coro.ret"); auto *RetBB = createBasicBlock("coro.ret");
@ -284,12 +480,20 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
createCoroData(*this, CurCoro, CoroId); createCoroData(*this, CurCoro, CoroId);
CurCoro.Data->SuspendBB = RetBB; 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 *AllocateCall = EmitScalarExpr(S.getAllocate());
auto *AllocOrInvokeContBB = Builder.GetInsertBlock();
// Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided. // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided.
if (auto *RetOnAllocFailure = S.getReturnStmtOnAllocFailure()) { if (auto *RetOnAllocFailure = S.getReturnStmtOnAllocFailure()) {
auto *RetOnFailureBB = createBasicBlock("coro.ret.on.failure"); auto *RetOnFailureBB = createBasicBlock("coro.ret.on.failure");
auto *InitBB = createBasicBlock("coro.init");
// See if allocation was successful. // See if allocation was successful.
auto *NullPtr = llvm::ConstantPointerNull::get(Int8PtrTy); auto *NullPtr = llvm::ConstantPointerNull::get(Int8PtrTy);
@ -299,40 +503,96 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
// If not, return OnAllocFailure object. // If not, return OnAllocFailure object.
EmitBlock(RetOnFailureBB); EmitBlock(RetOnFailureBB);
EmitStmt(RetOnAllocFailure); EmitStmt(RetOnAllocFailure);
}
else {
Builder.CreateBr(InitBB);
}
EmitBlock(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); CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB);
{ {
ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap);
CodeGenFunction::RunCleanupsScope ResumeScope(*this); CodeGenFunction::RunCleanupsScope ResumeScope(*this);
EHStack.pushCleanup<CallCoroDelete>(NormalAndEHCleanup, S.getDeallocate()); 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()); 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); EHStack.pushCleanup<CallCoroEnd>(EHCleanup);
CurCoro.Data->CurrentAwaitKind = AwaitKind::Init;
EmitStmt(S.getInitSuspendStmt());
CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB); CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
// FIXME: Emit initial suspend and more before the body.
CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal; 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. // See if we need to generate final suspend.
const bool CanFallthrough = Builder.GetInsertBlock(); const bool CanFallthrough = Builder.GetInsertBlock();
const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0; const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0;
if (CanFallthrough || HasCoreturns) { if (CanFallthrough || HasCoreturns) {
EmitBlock(FinalBB); 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); 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); llvm::Function *CoroEnd = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
Builder.CreateCall(CoroEnd, {NullPtr, Builder.getFalse()}); 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. // Emit coroutine intrinsic and patch up arguments of the token type.
@ -342,6 +602,17 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E,
switch (IID) { switch (IID) {
default: default:
break; 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 // 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 // returned by earlier call to @llvm.coro.id. Since we cannot represent it in
// builtins, we patch it up here. // builtins, we patch it up here.
@ -368,10 +639,22 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E,
llvm::Value *F = CGM.getIntrinsic(IID); llvm::Value *F = CGM.getIntrinsic(IID);
llvm::CallInst *Call = Builder.CreateCall(F, Args); 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 // 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. // coro.alloc, coro.begin and coro.free intrinsics to refer to it.
if (IID == llvm::Intrinsic::coro_id) { if (IID == llvm::Intrinsic::coro_id) {
createCoroData(*this, CurCoro, Call, E); 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); 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); Load->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
} }
if (TBAAInfo) { if (TBAAInfo) {
llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, bool MayAlias = BaseInfo.getMayAlias();
TBAAOffset); llvm::MDNode *TBAA = MayAlias
if (TBAAPath) ? CGM.getTBAAInfo(getContext().CharTy)
CGM.DecorateInstructionWithTBAA(Load, TBAAPath, : CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, TBAAOffset);
false /*ConvertTypeToTag*/); if (TBAA)
CGM.DecorateInstructionWithTBAA(Load, TBAA, MayAlias);
} }
if (EmitScalarRangeCheck(Load, Ty, Loc)) { if (EmitScalarRangeCheck(Load, Ty, Loc)) {
@ -1522,11 +1523,12 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,
Store->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node); Store->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
} }
if (TBAAInfo) { if (TBAAInfo) {
llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, bool MayAlias = BaseInfo.getMayAlias();
TBAAOffset); llvm::MDNode *TBAA = MayAlias
if (TBAAPath) ? CGM.getTBAAInfo(getContext().CharTy)
CGM.DecorateInstructionWithTBAA(Store, TBAAPath, : CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, TBAAOffset);
false /*ConvertTypeToTag*/); if (TBAA)
CGM.DecorateInstructionWithTBAA(Store, TBAA, MayAlias);
} }
} }
@ -3535,6 +3537,11 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
getFieldAlignmentSource(BaseInfo.getAlignmentSource()); getFieldAlignmentSource(BaseInfo.getAlignmentSource());
LValueBaseInfo FieldBaseInfo(fieldAlignSource, BaseInfo.getMayAlias()); 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()) { if (field->isBitField()) {
const CGRecordLayout &RL = const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(field->getParent()); CGM.getTypes().getCGRecordLayout(field->getParent());
@ -3556,11 +3563,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
return LValue::MakeBitfield(Addr, Info, fieldType, FieldBaseInfo); return LValue::MakeBitfield(Addr, Info, fieldType, FieldBaseInfo);
} }
const RecordDecl *rec = field->getParent();
QualType type = field->getType(); QualType type = field->getType();
bool mayAlias = rec->hasAttr<MayAliasAttr>();
Address addr = base.getAddress(); Address addr = base.getAddress();
unsigned cvr = base.getVRQualifiers(); unsigned cvr = base.getVRQualifiers();
bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA; bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA;

View File

@ -760,6 +760,7 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule()); IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule());
CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo); CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
Fn->removeFnAttr(llvm::Attribute::NoInline); Fn->removeFnAttr(llvm::Attribute::NoInline);
Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
Fn->addFnAttr(llvm::Attribute::AlwaysInline); Fn->addFnAttr(llvm::Attribute::AlwaysInline);
CodeGenFunction CGF(CGM); CodeGenFunction CGF(CGM);
// Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
@ -2903,6 +2904,19 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
Desc); Desc);
CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, 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; return RegFn;
} }
@ -3502,6 +3516,7 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap, CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
TaskPrivatesMapFnInfo); TaskPrivatesMapFnInfo);
TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
CodeGenFunction CGF(CGM); CodeGenFunction CGF(CGM);
CGF.disableDebugInfo(); CGF.disableDebugInfo();

View File

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

View File

@ -400,8 +400,11 @@ void CodeGenModule::Release() {
} }
if (OpenMPRuntime) if (OpenMPRuntime)
if (llvm::Function *OpenMPRegistrationFunction = if (llvm::Function *OpenMPRegistrationFunction =
OpenMPRuntime->emitRegistrationFunction()) OpenMPRuntime->emitRegistrationFunction()) {
AddGlobalCtor(OpenMPRegistrationFunction, 0); auto ComdatKey = OpenMPRegistrationFunction->hasComdat() ?
OpenMPRegistrationFunction : nullptr;
AddGlobalCtor(OpenMPRegistrationFunction, 0, ComdatKey);
}
if (PGOReader) { if (PGOReader) {
getModule().setProfileSummary(PGOReader->getSummary().getMD(VMContext)); getModule().setProfileSummary(PGOReader->getSummary().getMD(VMContext));
if (PGOStats.hasDiagnostics()) if (PGOStats.hasDiagnostics())
@ -904,7 +907,16 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
return; 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); B.addAttribute(llvm::Attribute::OptimizeNone);
// OptimizeNone implies noinline; we should not be inlining such functions. // OptimizeNone implies noinline; we should not be inlining such functions.
@ -958,6 +970,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
// function. // function.
if (!D->hasAttr<OptimizeNoneAttr>()) { if (!D->hasAttr<OptimizeNoneAttr>()) {
if (D->hasAttr<ColdAttr>()) { if (D->hasAttr<ColdAttr>()) {
if (!ShouldAddOptNone)
B.addAttribute(llvm::Attribute::OptimizeForSize); B.addAttribute(llvm::Attribute::OptimizeForSize);
B.addAttribute(llvm::Attribute::Cold); B.addAttribute(llvm::Attribute::Cold);
} }
@ -1508,6 +1521,10 @@ bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
case ImbueAttr::ALWAYS: case ImbueAttr::ALWAYS:
Fn->addFnAttr("function-instrument", "xray-always"); Fn->addFnAttr("function-instrument", "xray-always");
break; break;
case ImbueAttr::ALWAYS_ARG1:
Fn->addFnAttr("function-instrument", "xray-always");
Fn->addFnAttr("xray-log-args", "1");
break;
case ImbueAttr::NEVER: case ImbueAttr::NEVER:
Fn->addFnAttr("function-instrument", "xray-never"); Fn->addFnAttr("function-instrument", "xray-never");
break; break;

View File

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

View File

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

View File

@ -22,6 +22,7 @@
#include "ToolChains/FreeBSD.h" #include "ToolChains/FreeBSD.h"
#include "ToolChains/Fuchsia.h" #include "ToolChains/Fuchsia.h"
#include "ToolChains/Gnu.h" #include "ToolChains/Gnu.h"
#include "ToolChains/BareMetal.h"
#include "ToolChains/Haiku.h" #include "ToolChains/Haiku.h"
#include "ToolChains/Hexagon.h" #include "ToolChains/Hexagon.h"
#include "ToolChains/Lanai.h" #include "ToolChains/Lanai.h"
@ -598,6 +599,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
bool CCCPrintPhases; bool CCCPrintPhases;
InputArgList Args = ParseArgStrings(ArgList.slice(1)); InputArgList Args = ParseArgStrings(ArgList.slice(1));
if (Diags.hasErrorOccurred())
return nullptr;
// Silence driver warnings if requested // Silence driver warnings if requested
Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w)); Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w));
@ -1216,6 +1219,13 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false; 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)) { if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {
ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs()); ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs());
switch (RLT) { switch (RLT) {
@ -3819,6 +3829,8 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
if (Target.getVendor() == llvm::Triple::Myriad) if (Target.getVendor() == llvm::Triple::Myriad)
TC = llvm::make_unique<toolchains::MyriadToolChain>(*this, Target, TC = llvm::make_unique<toolchains::MyriadToolChain>(*this, Target,
Args); Args);
else if (toolchains::BareMetal::handlesTarget(Target))
TC = llvm::make_unique<toolchains::BareMetal>(*this, Target, Args);
else if (Target.isOSBinFormatELF()) else if (Target.isOSBinFormatELF())
TC = llvm::make_unique<toolchains::Generic_ELF>(*this, Target, Args); TC = llvm::make_unique<toolchains::Generic_ELF>(*this, Target, Args);
else if (Target.isOSBinFormatMachO()) 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; 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) { static llvm::StringRef getGCCToolchainDir(const ArgList &Args) {
const Arg *A = Args.getLastArg(clang::driver::options::OPT_gcc_toolchain); const Arg *A = Args.getLastArg(clang::driver::options::OPT_gcc_toolchain);
if (A) 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); 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; } bool Linux::HasNativeLLVMSupport() const { return true; }
Tool *Linux::buildLinker() const { return new tools::gnutools::Linker(*this); } 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: default:
D.Diag(clang::diag::err_target_unsupported_arch) D.Diag(clang::diag::err_target_unsupported_arch)
<< Triple.getArchName() << "myriad"; << Triple.getArchName() << "myriad";
LLVM_FALLTHROUGH;
case llvm::Triple::sparc: case llvm::Triple::sparc:
case llvm::Triple::sparcel: case llvm::Triple::sparcel:
case llvm::Triple::shave: case llvm::Triple::shave:

View File

@ -54,11 +54,12 @@ static bool startsNextParameter(const FormatToken &Current,
const FormatStyle &Style) { const FormatStyle &Style) {
const FormatToken &Previous = *Current.Previous; const FormatToken &Previous = *Current.Previous;
if (Current.is(TT_CtorInitializerComma) && if (Current.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializersBeforeComma) Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma)
return true; return true;
return Previous.is(tok::comma) && !Current.isTrailingComment() && return Previous.is(tok::comma) && !Current.isTrailingComment() &&
((Previous.isNot(TT_CtorInitializerComma) || ((Previous.isNot(TT_CtorInitializerComma) ||
!Style.BreakConstructorInitializersBeforeComma) && Style.BreakConstructorInitializers !=
FormatStyle::BCIS_BeforeComma) &&
(Previous.isNot(TT_InheritanceComma) || (Previous.isNot(TT_InheritanceComma) ||
!Style.BreakBeforeInheritanceComma)); !Style.BreakBeforeInheritanceComma));
} }
@ -178,13 +179,20 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
getLengthToMatchingParen(Previous) + State.Column - 1 > getLengthToMatchingParen(Previous) + State.Column - 1 >
getColumnLimit(State)) getColumnLimit(State))
return true; 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) || getColumnLimit(State) ||
State.Stack.back().BreakBeforeParameter) && State.Stack.back().BreakBeforeParameter) &&
((Style.AllowShortFunctionsOnASingleLine != FormatStyle::SFS_All) || (Style.AllowShortFunctionsOnASingleLine != FormatStyle::SFS_All ||
Style.BreakConstructorInitializersBeforeComma || Style.ColumnLimit != 0)) Style.BreakConstructorInitializers != FormatStyle::BCIS_BeforeColon ||
Style.ColumnLimit != 0))
return true; return true;
if (Current.is(TT_ObjCMethodExpr) && !Previous.is(TT_SelectorName) && if (Current.is(TT_ObjCMethodExpr) && !Previous.is(TT_SelectorName) &&
State.Line->startsWith(TT_ObjCMethodSpecifier)) State.Line->startsWith(TT_ObjCMethodSpecifier))
return true; return true;
@ -207,7 +215,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
// ... // ...
// }.bind(...)); // }.bind(...));
// FIXME: We should find a more generic solution to this problem. // 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)) Style.Language == FormatStyle::LK_JavaScript))
return true; return true;
@ -455,6 +463,11 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
!Previous.is(TT_OverloadedOperator)) || !Previous.is(TT_OverloadedOperator)) ||
(Previous.is(tok::colon) && Previous.is(TT_ObjCMethodExpr)))) { (Previous.is(tok::colon) && Previous.is(TT_ObjCMethodExpr)))) {
State.Stack.back().LastSpace = State.Column; 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, } else if ((Previous.isOneOf(TT_BinaryOperator, TT_ConditionalExpr,
TT_CtorInitializerColon)) && TT_CtorInitializerColon)) &&
((Previous.getPrecedence() != prec::Assignment && ((Previous.getPrecedence() != prec::Assignment &&
@ -614,7 +627,7 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
State.Stack[i].BreakBeforeParameter = true; State.Stack[i].BreakBeforeParameter = true;
if (PreviousNonComment && if (PreviousNonComment &&
!PreviousNonComment->isOneOf(tok::comma, tok::semi) && !PreviousNonComment->isOneOf(tok::comma, tok::colon, tok::semi) &&
(PreviousNonComment->isNot(TT_TemplateCloser) || (PreviousNonComment->isNot(TT_TemplateCloser) ||
Current.NestingLevel != 0) && Current.NestingLevel != 0) &&
!PreviousNonComment->isOneOf( !PreviousNonComment->isOneOf(
@ -676,7 +689,18 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return State.Stack[State.Stack.size() - 2].LastSpace; return State.Stack[State.Stack.size() - 2].LastSpace;
return State.FirstIndent; 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; return State.Stack[State.Stack.size() - 2].LastSpace;
if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope()) if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope())
return State.Stack[State.Stack.size() - 2].LastSpace; return State.Stack[State.Stack.size() - 2].LastSpace;
@ -750,6 +774,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return ContinuationIndent; return ContinuationIndent;
if (NextNonComment->is(TT_CtorInitializerComma)) if (NextNonComment->is(TT_CtorInitializerComma))
return State.Stack.back().Indent; 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, if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
TT_InheritanceComma)) TT_InheritanceComma))
return State.FirstIndent + Style.ConstructorInitializerIndentWidth; return State.FirstIndent + Style.ConstructorInitializerIndentWidth;
@ -810,19 +837,29 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
State.FirstIndent + Style.ContinuationIndentWidth; 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: // Indent 2 from the column, so:
// SomeClass::SomeClass() // SomeClass::SomeClass()
// : First(...), ... // : First(...), ...
// Next(...) // Next(...)
// ^ line up here. // ^ line up here.
State.Stack.back().Indent = 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; State.Stack.back().NestedBlockIndent = State.Stack.back().Indent;
if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine) if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
State.Stack.back().AvoidBinPacking = true; State.Stack.back().AvoidBinPacking = true;
State.Stack.back().BreakBeforeParameter = false; 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)) if (Current.is(TT_InheritanceColon))
State.Stack.back().Indent = State.Stack.back().Indent =
State.FirstIndent + Style.ContinuationIndentWidth; 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 <> template <>
struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> { struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) { static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
@ -304,8 +312,19 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
IO.mapOptional("BreakBeforeTernaryOperators", IO.mapOptional("BreakBeforeTernaryOperators",
Style.BreakBeforeTernaryOperators); Style.BreakBeforeTernaryOperators);
bool BreakConstructorInitializersBeforeComma = false;
IO.mapOptional("BreakConstructorInitializersBeforeComma", 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", IO.mapOptional("BreakAfterJavaFieldAnnotations",
Style.BreakAfterJavaFieldAnnotations); Style.BreakAfterJavaFieldAnnotations);
IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals); IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
@ -537,7 +556,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.BraceWrapping = {false, false, false, false, false, false, LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
false, false, false, false, false}; false, false, false, false, false};
LLVMStyle.BreakAfterJavaFieldAnnotations = false; LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializersBeforeComma = false; LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakBeforeInheritanceComma = false; LLVMStyle.BreakBeforeInheritanceComma = false;
LLVMStyle.BreakStringLiterals = true; LLVMStyle.BreakStringLiterals = true;
LLVMStyle.ColumnLimit = 80; LLVMStyle.ColumnLimit = 80;
@ -694,7 +713,7 @@ FormatStyle getMozillaStyle() {
MozillaStyle.BinPackParameters = false; MozillaStyle.BinPackParameters = false;
MozillaStyle.BinPackArguments = false; MozillaStyle.BinPackArguments = false;
MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
MozillaStyle.BreakConstructorInitializersBeforeComma = true; MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
MozillaStyle.BreakBeforeInheritanceComma = true; MozillaStyle.BreakBeforeInheritanceComma = true;
MozillaStyle.ConstructorInitializerIndentWidth = 2; MozillaStyle.ConstructorInitializerIndentWidth = 2;
MozillaStyle.ContinuationIndentWidth = 2; MozillaStyle.ContinuationIndentWidth = 2;
@ -717,7 +736,7 @@ FormatStyle getWebKitStyle() {
Style.AlignTrailingComments = false; Style.AlignTrailingComments = false;
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
Style.BreakBeforeBraces = FormatStyle::BS_WebKit; Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
Style.BreakConstructorInitializersBeforeComma = true; Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
Style.Cpp11BracedListStyle = false; Style.Cpp11BracedListStyle = false;
Style.ColumnLimit = 0; Style.ColumnLimit = 0;
Style.FixNamespaceComments = false; Style.FixNamespaceComments = false;
@ -1891,6 +1910,9 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges, ArrayRef<tooling::Range> Ranges,
StringRef FileName) { 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 = std::unique_ptr<Environment> Env =
Environment::CreateVirtualEnvironment(Code, FileName, Ranges); Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
Cleaner Clean(*Env, Style); Cleaner Clean(*Env, Style);

View File

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

View File

@ -90,6 +90,21 @@ namespace {
/// \brief Erase temporary files and the preamble file. /// \brief Erase temporary files and the preamble file.
void Cleanup(); 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() { 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 /// \returns True if a failure occurred that causes the ASTUnit not to
/// contain any translation-unit information, false otherwise. /// contain any translation-unit information, false otherwise.
bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, 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(); SavedMainFileBuffer.reset();
if (!Invocation) if (!Invocation)
@ -1028,6 +1044,12 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// Create the compiler instance to use for building the AST. // Create the compiler instance to use for building the AST.
std::unique_ptr<CompilerInstance> Clang( std::unique_ptr<CompilerInstance> Clang(
new CompilerInstance(std::move(PCHContainerOps))); 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. // Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> 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 corresponds to the main file along with a pair (bytes, start-of-line)
/// that describes the preamble. /// that describes the preamble.
ASTUnit::ComputedPreamble ASTUnit::ComputedPreamble
ASTUnit::ComputePreamble(CompilerInvocation &Invocation, unsigned MaxLines) { ASTUnit::ComputePreamble(CompilerInvocation &Invocation, unsigned MaxLines,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
FrontendOptions &FrontendOpts = Invocation.getFrontendOpts(); FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
PreprocessorOptions &PreprocessorOpts = Invocation.getPreprocessorOpts(); PreprocessorOptions &PreprocessorOpts = Invocation.getPreprocessorOpts();
@ -1180,16 +1203,19 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation, unsigned MaxLines) {
llvm::MemoryBuffer *Buffer = nullptr; llvm::MemoryBuffer *Buffer = nullptr;
std::unique_ptr<llvm::MemoryBuffer> BufferOwner; std::unique_ptr<llvm::MemoryBuffer> BufferOwner;
std::string MainFilePath(FrontendOpts.Inputs[0].getFile()); std::string MainFilePath(FrontendOpts.Inputs[0].getFile());
llvm::sys::fs::UniqueID MainFileID; auto MainFileStatus = VFS->status(MainFilePath);
if (!llvm::sys::fs::getUniqueID(MainFilePath, MainFileID)) { if (MainFileStatus) {
llvm::sys::fs::UniqueID MainFileID = MainFileStatus->getUniqueID();
// Check whether there is a file-file remapping of the main file // Check whether there is a file-file remapping of the main file
for (const auto &RF : PreprocessorOpts.RemappedFiles) { for (const auto &RF : PreprocessorOpts.RemappedFiles) {
std::string MPath(RF.first); std::string MPath(RF.first);
llvm::sys::fs::UniqueID MID; auto MPathStatus = VFS->status(MPath);
if (!llvm::sys::fs::getUniqueID(MPath, MID)) { if (MPathStatus) {
llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();
if (MainFileID == MID) { if (MainFileID == MID) {
// We found a remapping. Try to load the resulting, remapped source. // We found a remapping. Try to load the resulting, remapped source.
BufferOwner = getBufferForFile(RF.second); BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second));
if (!BufferOwner) if (!BufferOwner)
return ComputedPreamble(nullptr, nullptr, 0, true); return ComputedPreamble(nullptr, nullptr, 0, true);
} }
@ -1200,8 +1226,9 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation, unsigned MaxLines) {
// file-file remapping. // file-file remapping.
for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) { for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {
std::string MPath(RB.first); std::string MPath(RB.first);
llvm::sys::fs::UniqueID MID; auto MPathStatus = VFS->status(MPath);
if (!llvm::sys::fs::getUniqueID(MPath, MID)) { if (MPathStatus) {
llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();
if (MainFileID == MID) { if (MainFileID == MID) {
// We found a remapping. // We found a remapping.
BufferOwner.reset(); BufferOwner.reset();
@ -1213,7 +1240,7 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation, unsigned MaxLines) {
// If the main source file was not remapped, load it now. // If the main source file was not remapped, load it now.
if (!Buffer && !BufferOwner) { if (!Buffer && !BufferOwner) {
BufferOwner = getBufferForFile(FrontendOpts.Inputs[0].getFile()); BufferOwner = valueOrNull(VFS->getBufferForFile(FrontendOpts.Inputs[0].getFile()));
if (!BufferOwner) if (!BufferOwner)
return ComputedPreamble(nullptr, nullptr, 0, true); return ComputedPreamble(nullptr, nullptr, 0, true);
} }
@ -1324,8 +1351,10 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts,
std::unique_ptr<llvm::MemoryBuffer> std::unique_ptr<llvm::MemoryBuffer>
ASTUnit::getMainBufferWithPrecompiledPreamble( ASTUnit::getMainBufferWithPrecompiledPreamble(
std::shared_ptr<PCHContainerOperations> PCHContainerOps, std::shared_ptr<PCHContainerOperations> PCHContainerOps,
const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild, const CompilerInvocation &PreambleInvocationIn,
IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild,
unsigned MaxLines) { unsigned MaxLines) {
assert(VFS && "VFS is null");
auto PreambleInvocation = auto PreambleInvocation =
std::make_shared<CompilerInvocation>(PreambleInvocationIn); std::make_shared<CompilerInvocation>(PreambleInvocationIn);
@ -1333,7 +1362,8 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
PreprocessorOptions &PreprocessorOpts PreprocessorOptions &PreprocessorOpts
= PreambleInvocation->getPreprocessorOpts(); = PreambleInvocation->getPreprocessorOpts();
ComputedPreamble NewPreamble = ComputePreamble(*PreambleInvocation, MaxLines); ComputedPreamble NewPreamble =
ComputePreamble(*PreambleInvocation, MaxLines, VFS);
if (!NewPreamble.Size) { if (!NewPreamble.Size) {
// We couldn't find a preamble in the main source. Clear out the current // We couldn't find a preamble in the main source. Clear out the current
@ -1369,7 +1399,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
break; break;
vfs::Status Status; 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 // If we can't stat the file we're remapping to, assume that something
// horrible happened. // horrible happened.
AnyFileChanged = true; AnyFileChanged = true;
@ -1386,7 +1416,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
break; break;
vfs::Status Status; vfs::Status Status;
if (FileMgr->getNoncachedStatValue(RB.first, Status)) { if (!moveOnNoError(VFS->status(RB.first), Status)) {
AnyFileChanged = true; AnyFileChanged = true;
break; break;
} }
@ -1401,7 +1431,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
!AnyFileChanged && F != FEnd; !AnyFileChanged && F != FEnd;
++F) { ++F) {
vfs::Status Status; 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. // If we can't stat the file, assume that something horrible happened.
AnyFileChanged = true; AnyFileChanged = true;
break; break;
@ -1546,8 +1576,8 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
TopLevelDeclsInPreamble.clear(); TopLevelDeclsInPreamble.clear();
PreambleDiagnostics.clear(); PreambleDiagnostics.clear();
IntrusiveRefCntPtr<vfs::FileSystem> VFS = VFS = createVFSFromCompilerInvocation(Clang->getInvocation(),
createVFSFromCompilerInvocation(Clang->getInvocation(), getDiagnostics()); getDiagnostics(), VFS);
if (!VFS) if (!VFS)
return nullptr; return nullptr;
@ -1863,10 +1893,13 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
bool ASTUnit::LoadFromCompilerInvocation( bool ASTUnit::LoadFromCompilerInvocation(
std::shared_ptr<PCHContainerOperations> PCHContainerOps, std::shared_ptr<PCHContainerOperations> PCHContainerOps,
unsigned PrecompilePreambleAfterNParses) { unsigned PrecompilePreambleAfterNParses,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
if (!Invocation) if (!Invocation)
return true; return true;
assert(VFS && "VFS is null");
// We'll manage file buffers ourselves. // We'll manage file buffers ourselves.
Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true; Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true;
Invocation->getFrontendOpts().DisableFree = false; Invocation->getFrontendOpts().DisableFree = false;
@ -1877,7 +1910,7 @@ bool ASTUnit::LoadFromCompilerInvocation(
if (PrecompilePreambleAfterNParses > 0) { if (PrecompilePreambleAfterNParses > 0) {
PreambleRebuildCounter = PrecompilePreambleAfterNParses; PreambleRebuildCounter = PrecompilePreambleAfterNParses;
OverrideMainBuffer = OverrideMainBuffer =
getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation); getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);
getDiagnostics().Reset(); getDiagnostics().Reset();
ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
} }
@ -1889,7 +1922,7 @@ bool ASTUnit::LoadFromCompilerInvocation(
llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer> llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer>
MemBufferCleanup(OverrideMainBuffer.get()); 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( std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
@ -1923,7 +1956,8 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
DiagCleanup(Diags.get()); DiagCleanup(Diags.get());
if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps), if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
PrecompilePreambleAfterNParses)) PrecompilePreambleAfterNParses,
AST->FileMgr->getVirtualFileSystem()))
return nullptr; return nullptr;
return AST; return AST;
} }
@ -1938,7 +1972,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies, bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies,
bool UserFilesAreVolatile, bool ForSerialization, 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"); assert(Diags.get() && "no DiagnosticsEngine was provided");
SmallVector<StoredDiagnostic, 4> StoredDiagnostics; SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
@ -1979,8 +2014,9 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
ConfigureDiags(Diags, *AST, CaptureDiagnostics); ConfigureDiags(Diags, *AST, CaptureDiagnostics);
AST->Diagnostics = Diags; AST->Diagnostics = Diags;
AST->FileSystemOpts = CI->getFileSystemOpts(); AST->FileSystemOpts = CI->getFileSystemOpts();
IntrusiveRefCntPtr<vfs::FileSystem> VFS = if (!VFS)
createVFSFromCompilerInvocation(*CI, *Diags); VFS = vfs::getRealFileSystem();
VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
if (!VFS) if (!VFS)
return nullptr; return nullptr;
AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS); AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
@ -2006,7 +2042,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
ASTUnitCleanup(AST.get()); ASTUnitCleanup(AST.get());
if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps), if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
PrecompilePreambleAfterNParses)) { PrecompilePreambleAfterNParses,
VFS)) {
// Some error occurred, if caller wants to examine diagnostics, pass it the // Some error occurred, if caller wants to examine diagnostics, pass it the
// ASTUnit. // ASTUnit.
if (ErrAST) { if (ErrAST) {
@ -2020,10 +2057,16 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
} }
bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
ArrayRef<RemappedFile> RemappedFiles) { ArrayRef<RemappedFile> RemappedFiles,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
if (!Invocation) if (!Invocation)
return true; return true;
if (!VFS) {
assert(FileMgr && "FileMgr is null on Reparse call");
VFS = FileMgr->getVirtualFileSystem();
}
clearFileLevelDecls(); clearFileLevelDecls();
SimpleTimer ParsingTimer(WantTiming); SimpleTimer ParsingTimer(WantTiming);
@ -2045,7 +2088,8 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
if (!getPreambleFile(this).empty() || PreambleRebuildCounter > 0) if (!getPreambleFile(this).empty() || PreambleRebuildCounter > 0)
OverrideMainBuffer = OverrideMainBuffer =
getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation); getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);
// Clear out the diagnostics state. // Clear out the diagnostics state.
FileMgr.reset(); FileMgr.reset();
@ -2056,7 +2100,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// Parse the sources // Parse the sources
bool Result = 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 // If we're caching global code-completion results, and the top-level
// declarations have changed, clear out the code-completion cache. // declarations have changed, clear out the code-completion cache.
@ -2414,15 +2458,19 @@ void ASTUnit::CodeComplete(
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
if (!getPreambleFile(this).empty()) { if (!getPreambleFile(this).empty()) {
std::string CompleteFilePath(File); 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); std::string MainPath(OriginalSourceFile);
llvm::sys::fs::UniqueID MainID; auto MainStatus = VFS->status(MainPath);
if (!llvm::sys::fs::getUniqueID(MainPath, MainID)) { if (MainStatus) {
llvm::sys::fs::UniqueID MainID = MainStatus->getUniqueID();
if (CompleteFileID == MainID && Line > 1) if (CompleteFileID == MainID && Line > 1)
OverrideMainBuffer = getMainBufferWithPrecompiledPreamble( 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.DisableLLVMPasses = Args.hasArg(OPT_disable_llvm_passes);
Opts.DisableLifetimeMarkers = Args.hasArg(OPT_disable_lifetimemarkers); Opts.DisableLifetimeMarkers = Args.hasArg(OPT_disable_lifetimemarkers);
Opts.DisableO0ImplyOptNone = Args.hasArg(OPT_disable_O0_optnone);
Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone); Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables); Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables);
Opts.UseRegisterSizedBitfieldAccess = Args.hasArg( Opts.UseRegisterSizedBitfieldAccess = Args.hasArg(
@ -1087,6 +1088,9 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Opts.SpellCheckingLimit = getLastArgIntValue( Opts.SpellCheckingLimit = getLastArgIntValue(
Args, OPT_fspell_checking_limit, Args, OPT_fspell_checking_limit,
DiagnosticOptions::DefaultSpellCheckingLimit, Diags); DiagnosticOptions::DefaultSpellCheckingLimit, Diags);
Opts.SnippetLineLimit = getLastArgIntValue(
Args, OPT_fcaret_diagnostics_max_lines,
DiagnosticOptions::DefaultSnippetLineLimit, Diags);
Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop, Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop,
DiagnosticOptions::DefaultTabStop, Diags); DiagnosticOptions::DefaultTabStop, Diags);
if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) { if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
@ -2747,15 +2751,22 @@ void BuryPointer(const void *Ptr) {
IntrusiveRefCntPtr<vfs::FileSystem> IntrusiveRefCntPtr<vfs::FileSystem>
createVFSFromCompilerInvocation(const CompilerInvocation &CI, createVFSFromCompilerInvocation(const CompilerInvocation &CI,
DiagnosticsEngine &Diags) { DiagnosticsEngine &Diags) {
if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty()) return createVFSFromCompilerInvocation(CI, Diags, vfs::getRealFileSystem());
return vfs::getRealFileSystem(); }
IntrusiveRefCntPtr<vfs::OverlayFileSystem> IntrusiveRefCntPtr<vfs::FileSystem>
Overlay(new vfs::OverlayFileSystem(vfs::getRealFileSystem())); 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 // earlier vfs files are on the bottom
for (const std::string &File : CI.getHeaderSearchOpts().VFSOverlayFiles) { for (const std::string &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer = llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
llvm::MemoryBuffer::getFile(File); BaseFS->getBufferForFile(File);
if (!Buffer) { if (!Buffer) {
Diags.Report(diag::err_missing_vfs_overlay_file) << File; Diags.Report(diag::err_missing_vfs_overlay_file) << File;
return IntrusiveRefCntPtr<vfs::FileSystem>(); return IntrusiveRefCntPtr<vfs::FileSystem>();

View File

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

View File

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

View File

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

View File

@ -928,6 +928,56 @@ void TextDiagnostic::emitBuildingModuleLocation(SourceLocation Loc,
OS << "While building module '" << ModuleName << "':\n"; 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. /// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo.
static void highlightRange(const CharSourceRange &R, static void highlightRange(const CharSourceRange &R,
unsigned LineNo, FileID FID, unsigned LineNo, FileID FID,
@ -990,9 +1040,12 @@ static void highlightRange(const CharSourceRange &R,
EndColNo = map.startOfPreviousColumn(EndColNo); EndColNo = map.startOfPreviousColumn(EndColNo);
// If the start/end passed each other, then we are trying to highlight a // 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 // range that just exists in whitespace. That most likely means we have
// bug. // a multi-line highlighting range that covers a blank line.
assert(StartColNo <= EndColNo && "Trying to highlight whitespace??"); if (StartColNo > EndColNo) {
assert(StartLineNo != EndLineNo && "trying to highlight whitespace");
StartColNo = EndColNo;
}
} }
assert(StartColNo <= map.getSourceLine().size() && "Invalid range!"); assert(StartColNo <= map.getSourceLine().size() && "Invalid range!");
@ -1103,7 +1156,7 @@ void TextDiagnostic::emitSnippetAndCaret(
// Decompose the location into a FID/Offset pair. // Decompose the location into a FID/Offset pair.
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
FileID FID = LocInfo.first; FileID FID = LocInfo.first;
unsigned FileOffset = LocInfo.second; unsigned CaretFileOffset = LocInfo.second;
// Get information about the buffer it points into. // Get information about the buffer it points into.
bool Invalid = false; bool Invalid = false;
@ -1111,34 +1164,48 @@ void TextDiagnostic::emitSnippetAndCaret(
if (Invalid) if (Invalid)
return; return;
const char *BufStart = BufData.data(); unsigned CaretLineNo = SM.getLineNumber(FID, CaretFileOffset);
const char *BufEnd = BufStart + BufData.size(); 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. // Arbitrarily stop showing snippets when the line is too long.
static const size_t MaxLineLengthToPrint = 4096; static const size_t MaxLineLengthToPrint = 4096;
if (ColNo > MaxLineLengthToPrint) if (CaretColNo > MaxLineLengthToPrint)
return; return;
// Rewind from the current position to the start of the line. // Find the set of lines to include.
const char *TokPtr = BufStart+FileOffset; const unsigned MaxLines = DiagOpts->SnippetLineLimit;
const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based. std::pair<unsigned, unsigned> Lines = {CaretLineNo, CaretLineNo};
for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
E = Ranges.end();
I != E; ++I)
if (auto OptionalRange = findLinesForRange(*I, FID, SM))
Lines = maybeAddRange(Lines, *OptionalRange, MaxLines);
// Compute the line end. Scan forward from the error position to the end of for (unsigned LineNo = Lines.first; LineNo != Lines.second + 1; ++LineNo) {
// the line. const char *BufStart = BufData.data();
const char *LineEnd = TokPtr; const char *BufEnd = BufStart + BufData.size();
// 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;
// Compute the line end.
const char *LineEnd = LineStart;
while (*LineEnd != '\n' && *LineEnd != '\r' && LineEnd != BufEnd) while (*LineEnd != '\n' && *LineEnd != '\r' && LineEnd != BufEnd)
++LineEnd; ++LineEnd;
// Arbitrarily stop showing snippets when the line is too long. // 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) if (size_t(LineEnd - LineStart) > MaxLineLengthToPrint)
return; return;
// Trim trailing null-bytes. // Trim trailing null-bytes.
StringRef Line(LineStart, LineEnd - LineStart); StringRef Line(LineStart, LineEnd - LineStart);
while (Line.size() > ColNo && Line.back() == '\0') while (!Line.empty() && Line.back() == '\0' &&
(LineNo != CaretLineNo || Line.size() > CaretColNo))
Line = Line.drop_back(); Line = Line.drop_back();
// Copy the line of code into an std::string for ease of manipulation. // Copy the line of code into an std::string for ease of manipulation.
@ -1158,15 +1225,15 @@ void TextDiagnostic::emitSnippetAndCaret(
highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM, LangOpts); highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM, LangOpts);
// Next, insert the caret itself. // Next, insert the caret itself.
ColNo = sourceColMap.byteToContainingColumn(ColNo-1); if (CaretLineNo == LineNo) {
if (CaretLine.size()<ColNo+1) CaretColNo = sourceColMap.byteToContainingColumn(CaretColNo - 1);
CaretLine.resize(ColNo+1, ' '); if (CaretLine.size() < CaretColNo + 1)
CaretLine[ColNo] = '^'; CaretLine.resize(CaretColNo + 1, ' ');
CaretLine[CaretColNo] = '^';
}
std::string FixItInsertionLine = buildFixItInsertionLine(LineNo, std::string FixItInsertionLine = buildFixItInsertionLine(
sourceColMap, LineNo, sourceColMap, Hints, SM, DiagOpts.get());
Hints, SM,
DiagOpts.get());
// If the source line is too long for our terminal, select only the // If the source line is too long for our terminal, select only the
// "interesting" source region within that line. // "interesting" source region within that line.
@ -1185,17 +1252,19 @@ void TextDiagnostic::emitSnippetAndCaret(
} }
// Finally, remove any blank spaces from the end of CaretLine. // Finally, remove any blank spaces from the end of CaretLine.
while (CaretLine[CaretLine.size()-1] == ' ') while (!CaretLine.empty() && CaretLine[CaretLine.size() - 1] == ' ')
CaretLine.erase(CaretLine.end()-1); CaretLine.erase(CaretLine.end() - 1);
// Emit what we have computed. // Emit what we have computed.
emitSnippet(SourceLine); emitSnippet(SourceLine);
if (!CaretLine.empty()) {
if (DiagOpts->ShowColors) if (DiagOpts->ShowColors)
OS.changeColor(caretColor, true); OS.changeColor(caretColor, true);
OS << CaretLine << '\n'; OS << CaretLine << '\n';
if (DiagOpts->ShowColors) if (DiagOpts->ShowColors)
OS.resetColor(); OS.resetColor();
}
if (!FixItInsertionLine.empty()) { if (!FixItInsertionLine.empty()) {
if (DiagOpts->ShowColors) if (DiagOpts->ShowColors)
@ -1207,6 +1276,7 @@ void TextDiagnostic::emitSnippetAndCaret(
if (DiagOpts->ShowColors) if (DiagOpts->ShowColors)
OS.resetColor(); OS.resetColor();
} }
}
// Print out any parseable fixit information requested by the options. // Print out any parseable fixit information requested by the options.
emitParseableFixits(Hints, SM); emitParseableFixits(Hints, SM);

View File

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

View File

@ -12156,6 +12156,11 @@ static __inline__ void __ATTRS_o_ai vec_vsx_st(vector unsigned char __a,
#endif #endif
#ifdef __VSX__
#define vec_xxpermdi __builtin_vsx_xxpermdi
#define vec_xxsldwi __builtin_vsx_xxsldwi
#endif
/* vec_xor */ /* vec_xor */
#define __builtin_altivec_vxor 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> #include <avx512cdintrin.h>
#endif #endif
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__AVX512VPOPCNTDQ__)
#include <avx512vpopcntdqintrin.h>
#endif
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__AVX512DQ__) #if !defined(_MSC_VER) || __has_feature(modules) || defined(__AVX512DQ__)
#include <avx512dqintrin.h> #include <avx512dqintrin.h>
#endif #endif

View File

@ -254,6 +254,18 @@ public:
SymbolRoleSet Roles = getRolesForRef(E, Relations); SymbolRoleSet Roles = getRolesForRef(E, Relations);
return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
Parent, ParentDC, Roles, Relations, E); 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 // 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(); TKind = FD->getTemplateSpecializationKind();
} else if (auto *VD = dyn_cast<VarDecl>(D)) { } else if (auto *VD = dyn_cast<VarDecl>(D)) {
TKind = VD->getTemplateSpecializationKind(); TKind = VD->getTemplateSpecializationKind();
} else if (isa<FieldDecl>(D)) { } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
if (const auto *Parent = if (RD->getInstantiatedFromMemberClass())
dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext())) TKind = RD->getTemplateSpecializationKind();
TKind = Parent->getSpecializationKind(); } 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) { switch (TKind) {
case TSK_Undeclared: case TSK_Undeclared:
@ -155,6 +161,16 @@ bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
return true; 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) { static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
if (const ClassTemplateSpecializationDecl * if (const ClassTemplateSpecializationDecl *
SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
@ -163,15 +179,26 @@ static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
return FD->getTemplateInstantiationPattern(); return FD->getTemplateInstantiationPattern();
} else if (auto *VD = dyn_cast<VarDecl>(D)) { } else if (auto *VD = dyn_cast<VarDecl>(D)) {
return VD->getTemplateInstantiationPattern(); return VD->getTemplateInstantiationPattern();
} else if (const auto *FD = dyn_cast<FieldDecl>(D)) { } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
if (const auto *Parent = return RD->getInstantiatedFromMemberClass();
dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext())) { } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
const CXXRecordDecl *Pattern = Parent->getTemplateInstantiationPattern(); return ED->getInstantiatedFromMemberEnum();
for (const NamedDecl *ND : Pattern->lookup(FD->getDeclName())) { } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
if (ND->isImplicit()) const auto *ND = cast<NamedDecl>(D);
if (const CXXRecordDecl *Pattern =
getDeclContextForTemplateInstationPattern(ND)) {
for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
if (BaseND->isImplicit())
continue; continue;
if (isa<FieldDecl>(ND)) if (BaseND->getKind() == ND->getKind())
return ND; 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 // Parse the suffix. At this point we can classify whether we have an FP or
// integer constant. // integer constant.
bool isFPConstant = isFloatingLiteral(); bool isFPConstant = isFloatingLiteral();
const char *ImaginarySuffixLoc = nullptr;
// Loop over all of the characters of the suffix. If we see something bad, // Loop over all of the characters of the suffix. If we see something bad,
// we break out of the loop. // we break out of the loop.
@ -660,7 +659,6 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
case 'J': case 'J':
if (isImaginary) break; // Cannot be repeated. if (isImaginary) break; // Cannot be repeated.
isImaginary = true; isImaginary = true;
ImaginarySuffixLoc = s;
continue; // Success. continue; // Success.
} }
// If we reached here, there was an error or a ud-suffix. // If we reached here, there was an error or a ud-suffix.
@ -694,8 +692,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
} }
if (isImaginary) { if (isImaginary) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin - ThisTokBegin),
ImaginarySuffixLoc - ThisTokBegin),
diag::ext_imaginary_constant); diag::ext_imaginary_constant);
} }
} }

View File

@ -84,6 +84,90 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
return Context; 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, ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
const LangOptions &LangOpts, const TargetInfo *Target, const LangOptions &LangOpts, const TargetInfo *Target,
HeaderSearch &HeaderInfo) HeaderSearch &HeaderInfo)
@ -1026,9 +1110,6 @@ namespace clang {
/// be resolved relative to. /// be resolved relative to.
const DirectoryEntry *Directory; const DirectoryEntry *Directory;
/// \brief The directory containing Clang-supplied headers.
const DirectoryEntry *BuiltinIncludeDir;
/// \brief Whether this module map is in a system header directory. /// \brief Whether this module map is in a system header directory.
bool IsSystem; bool IsSystem;
@ -1087,12 +1168,10 @@ namespace clang {
ModuleMap &Map, ModuleMap &Map,
const FileEntry *ModuleMapFile, const FileEntry *ModuleMapFile,
const DirectoryEntry *Directory, const DirectoryEntry *Directory,
const DirectoryEntry *BuiltinIncludeDir,
bool IsSystem) bool IsSystem)
: L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
ModuleMapFile(ModuleMapFile), Directory(Directory), ModuleMapFile(ModuleMapFile), Directory(Directory),
BuiltinIncludeDir(BuiltinIncludeDir), IsSystem(IsSystem), IsSystem(IsSystem), HadError(false), ActiveModule(nullptr)
HadError(false), ActiveModule(nullptr)
{ {
Tok.clear(); Tok.clear();
consumeToken(); consumeToken();
@ -1772,25 +1851,6 @@ void ModuleMapParser::parseRequiresDecl() {
} while (true); } 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. /// \brief Parse a header declaration.
/// ///
/// header-declaration: /// header-declaration:
@ -1843,85 +1903,36 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
Module::UnresolvedHeaderDirective Header; Module::UnresolvedHeaderDirective Header;
Header.FileName = Tok.getString(); Header.FileName = Tok.getString();
Header.FileNameLoc = consumeToken(); Header.FileNameLoc = consumeToken();
Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
// Check whether we already have an umbrella. // 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) Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
<< ActiveModule->getFullModuleName(); << ActiveModule->getFullModuleName();
HadError = true; HadError = true;
return; return;
} }
// Look for this file. // Look for this file by name if we don't have any stat information.
const FileEntry *File = nullptr; SmallString<128> RelativePathName, BuiltinPathName;
const FileEntry *BuiltinFile = nullptr; const FileEntry *File =
SmallString<128> RelativePathName; Map.resolveHeader(ActiveModule, Header, RelativePathName);
if (llvm::sys::path::is_absolute(Header.FileName)) { const FileEntry *BuiltinFile =
RelativePathName = Header.FileName; Map.resolveAsBuiltinHeader(ActiveModule, Header, BuiltinPathName);
File = SourceMgr.getFileManager().getFile(RelativePathName);
} else {
// Search for the header file within the search directory.
SmallString<128> FullPathName(Directory->getName());
unsigned FullPathLength = FullPathName.size();
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, // If Clang supplies this header but the underlying system does not,
// just silently swap in our builtin version. Otherwise, we'll end // just silently swap in our builtin version. Otherwise, we'll end
// up adding both (later). // up adding both (later).
if (BuiltinFile && !File) { if (BuiltinFile && !File) {
File = BuiltinFile;
RelativePathName = BuiltinPathName; RelativePathName = BuiltinPathName;
File = BuiltinFile;
BuiltinFile = nullptr; BuiltinFile = nullptr;
} }
}
}
}
// FIXME: We shouldn't be eagerly stat'ing every file named in a module map. // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
// Come up with a lazy way to do this. // Come up with a lazy way to do this.
if (File) { if (File) {
if (LeadingToken == MMToken::UmbrellaKeyword) { if (Header.IsUmbrella) {
const DirectoryEntry *UmbrellaDir = File->getDir(); const DirectoryEntry *UmbrellaDir = File->getDir();
if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) { if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash) 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 // If there is a builtin counterpart to this file, add it now so it can
// wrap the system header. // wrap the system header.
if (BuiltinFile) { if (BuiltinFile) {
// FIXME: Taking the name from the FileEntry is unstable and can give Module::Header H = { BuiltinPathName.str(), BuiltinFile };
// different results depending on how we've previously named that file
// in this build.
Module::Header H = { BuiltinFile->getName(), BuiltinFile };
Map.addHeader(ActiveModule, H, Role); Map.addHeader(ActiveModule, H, Role);
// If we have both a builtin and system version of the file, the // 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 // If we find a module that has a missing header, we mark this module as
// unavailable and store the header directive for displaying diagnostics. // unavailable and store the header directive for displaying diagnostics.
Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
ActiveModule->markUnavailable(); ActiveModule->markUnavailable();
ActiveModule->MissingHeaders.push_back(Header); ActiveModule->MissingHeaders.push_back(Header);
} }
@ -2555,7 +2562,7 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
Buffer->getBufferEnd()); Buffer->getBufferEnd());
SourceLocation Start = L.getSourceLocation(); SourceLocation Start = L.getSourceLocation();
ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
BuiltinIncludeDir, IsSystem); IsSystem);
bool Result = Parser.parseModuleMapFile(); bool Result = Parser.parseModuleMapFile();
ParsedModuleMap[File] = Result; ParsedModuleMap[File] = Result;

View File

@ -1171,18 +1171,26 @@ void Preprocessor::HandleLineDirective() {
CheckEndOfDirective("line", true); 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) if (Callbacks)
Callbacks->FileChanged(CurPPLexer->getSourceLocation(), Callbacks->FileChanged(CurPPLexer->getSourceLocation(),
PPCallbacks::RenameFile, PPCallbacks::RenameFile, FileKind);
SrcMgr::C_User);
} }
/// ReadLineMarkerFlags - Parse and validate any flags at the end of a GNU line /// ReadLineMarkerFlags - Parse and validate any flags at the end of a GNU line
/// marker directive. /// marker directive.
static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit,
bool &IsSystemHeader, bool &IsExternCHeader, SrcMgr::CharacteristicKind &FileKind,
Preprocessor &PP) { Preprocessor &PP) {
unsigned FlagVal; unsigned FlagVal;
Token FlagTok; Token FlagTok;
@ -1233,7 +1241,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit,
return true; return true;
} }
IsSystemHeader = true; FileKind = SrcMgr::C_System;
PP.Lex(FlagTok); PP.Lex(FlagTok);
if (FlagTok.is(tok::eod)) return false; if (FlagTok.is(tok::eod)) return false;
@ -1247,7 +1255,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit,
return true; return true;
} }
IsExternCHeader = true; FileKind = SrcMgr::C_ExternCSystem;
PP.Lex(FlagTok); PP.Lex(FlagTok);
if (FlagTok.is(tok::eod)) return false; if (FlagTok.is(tok::eod)) return false;
@ -1277,14 +1285,15 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) {
Lex(StrTok); Lex(StrTok);
bool IsFileEntry = false, IsFileExit = false; bool IsFileEntry = false, IsFileExit = false;
bool IsSystemHeader = false, IsExternCHeader = false;
int FilenameID = -1; int FilenameID = -1;
SrcMgr::CharacteristicKind FileKind = SrcMgr::C_User;
// If the StrTok is "eod", then it wasn't present. Otherwise, it must be a // If the StrTok is "eod", then it wasn't present. Otherwise, it must be a
// string followed by eod. // string followed by eod.
if (StrTok.is(tok::eod)) if (StrTok.is(tok::eod)) {
; // ok // Treat this like "#line NN", which doesn't change file characteristics.
else if (StrTok.isNot(tok::string_literal)) { FileKind = SourceMgr.getFileCharacteristic(DigitTok.getLocation());
} else if (StrTok.isNot(tok::string_literal)) {
Diag(StrTok, diag::err_pp_linemarker_invalid_filename); Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
return DiscardUntilEndOfDirective(); return DiscardUntilEndOfDirective();
} else if (StrTok.hasUDSuffix()) { } else if (StrTok.hasUDSuffix()) {
@ -1303,15 +1312,13 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) {
FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString()); FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString());
// If a filename was present, read any flags that are present. // If a filename was present, read any flags that are present.
if (ReadLineMarkerFlags(IsFileEntry, IsFileExit, if (ReadLineMarkerFlags(IsFileEntry, IsFileExit, FileKind, *this))
IsSystemHeader, IsExternCHeader, *this))
return; return;
} }
// Create a line note with this information. // Create a line note with this information.
SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, IsFileEntry,
IsFileEntry, IsFileExit, IsFileExit, FileKind);
IsSystemHeader, IsExternCHeader);
// If the preprocessor has callbacks installed, notify them of the #line // 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 // 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; Reason = PPCallbacks::EnterFile;
else if (IsFileExit) else if (IsFileExit)
Reason = PPCallbacks::ExitFile; 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); 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_overloadable", true)
.Case("attribute_unavailable_with_message", true) .Case("attribute_unavailable_with_message", true)
.Case("attribute_unused_on_fields", true) .Case("attribute_unused_on_fields", true)
.Case("attribute_diagnose_if_objc", true)
.Case("blocks", LangOpts.Blocks) .Case("blocks", LangOpts.Blocks)
.Case("c_thread_safety_attributes", true) .Case("c_thread_safety_attributes", true)
.Case("cxx_exceptions", LangOpts.CXXExceptions) .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 // Emit a line marker. This will change any source locations from this point
// forward to realize they are in a system header. // forward to realize they are in a system header.
// Create a line note with this information. // 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, FilenameID, /*IsEntry=*/false, /*IsExit=*/false,
/*IsSystem=*/true, /*IsExternC=*/false); SrcMgr::C_System);
} }
/// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah. /// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.

View File

@ -2120,30 +2120,17 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) { Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) {
// Form a parsed representation of the template-id to be stored in the // Form a parsed representation of the template-id to be stored in the
// UnqualifiedId. // UnqualifiedId.
TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
// FIXME: Store name for literal operator too. // FIXME: Store name for literal operator too.
if (Id.getKind() == UnqualifiedId::IK_Identifier) { IdentifierInfo *TemplateII =
TemplateId->Name = Id.Identifier; Id.getKind() == UnqualifiedId::IK_Identifier ? Id.Identifier : nullptr;
TemplateId->Operator = OO_None; OverloadedOperatorKind OpKind = Id.getKind() == UnqualifiedId::IK_Identifier
TemplateId->TemplateNameLoc = Id.StartLocation; ? OO_None
} else { : Id.OperatorFunctionId.Operator;
TemplateId->Name = nullptr;
TemplateId->Operator = Id.OperatorFunctionId.Operator;
TemplateId->TemplateNameLoc = Id.StartLocation;
}
TemplateId->SS = SS; TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
TemplateId->TemplateKWLoc = TemplateKWLoc; SS, TemplateKWLoc, Id.StartLocation, TemplateII, OpKind, Template, TNK,
TemplateId->Template = Template; LAngleLoc, RAngleLoc, TemplateArgs, TemplateIds);
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); Id.setTemplateId(TemplateId);
return false; 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 // Build a template-id annotation token that can be processed
// later. // later.
Tok.setKind(tok::annot_template_id); Tok.setKind(tok::annot_template_id);
TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds); IdentifierInfo *TemplateII =
TemplateId->TemplateNameLoc = TemplateNameLoc; TemplateName.getKind() == UnqualifiedId::IK_Identifier
if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) { ? TemplateName.Identifier
TemplateId->Name = TemplateName.Identifier; : nullptr;
TemplateId->Operator = OO_None;
} else { OverloadedOperatorKind OpKind =
TemplateId->Name = nullptr; TemplateName.getKind() == UnqualifiedId::IK_Identifier
TemplateId->Operator = TemplateName.OperatorFunctionId.Operator; ? OO_None
} : TemplateName.OperatorFunctionId.Operator;
TemplateId->SS = SS;
TemplateId->TemplateKWLoc = TemplateKWLoc; TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
TemplateId->Template = Template; SS, TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,
TemplateId->Kind = TNK; LAngleLoc, RAngleLoc, TemplateArgs, TemplateIds);
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]);
Tok.setAnnotationValue(TemplateId); Tok.setAnnotationValue(TemplateId);
if (TemplateKWLoc.isValid()) if (TemplateKWLoc.isValid())
Tok.setLocation(TemplateKWLoc); Tok.setLocation(TemplateKWLoc);

View File

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

View File

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

View File

@ -1696,6 +1696,9 @@ bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case PPC::BI__builtin_tabortdci: case PPC::BI__builtin_tabortdci:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31) || return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31) ||
SemaBuiltinConstantArgRange(TheCall, 2, 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); return SemaBuiltinConstantArgRange(TheCall, i, l, u);
} }
@ -3892,6 +3895,65 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
return false; 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. /// SemaBuiltinShuffleVector - Handle __builtin_shufflevector.
// This is declared to take (...), so we have to check everything. // This is declared to take (...), so we have to check everything.
ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
@ -3914,7 +3976,8 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
if (!LHSType->isVectorType() || !RHSType->isVectorType()) if (!LHSType->isVectorType() || !RHSType->isVectorType())
return ExprError(Diag(TheCall->getLocStart(), return ExprError(Diag(TheCall->getLocStart(),
diag::err_shufflevector_non_vector) diag::err_vec_builtin_non_vector)
<< TheCall->getDirectCallee()
<< SourceRange(TheCall->getArg(0)->getLocStart(), << SourceRange(TheCall->getArg(0)->getLocStart(),
TheCall->getArg(1)->getLocEnd())); TheCall->getArg(1)->getLocEnd()));
@ -3928,12 +3991,14 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
if (!RHSType->hasIntegerRepresentation() || if (!RHSType->hasIntegerRepresentation() ||
RHSType->getAs<VectorType>()->getNumElements() != numElements) RHSType->getAs<VectorType>()->getNumElements() != numElements)
return ExprError(Diag(TheCall->getLocStart(), return ExprError(Diag(TheCall->getLocStart(),
diag::err_shufflevector_incompatible_vector) diag::err_vec_builtin_incompatible_vector)
<< TheCall->getDirectCallee()
<< SourceRange(TheCall->getArg(1)->getLocStart(), << SourceRange(TheCall->getArg(1)->getLocStart(),
TheCall->getArg(1)->getLocEnd())); TheCall->getArg(1)->getLocEnd()));
} else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
return ExprError(Diag(TheCall->getLocStart(), return ExprError(Diag(TheCall->getLocStart(),
diag::err_shufflevector_incompatible_vector) diag::err_vec_builtin_incompatible_vector)
<< TheCall->getDirectCallee()
<< SourceRange(TheCall->getArg(0)->getLocStart(), << SourceRange(TheCall->getArg(0)->getLocStart(),
TheCall->getArg(1)->getLocEnd())); TheCall->getArg(1)->getLocEnd()));
} else if (numElements != numResElements) { } else if (numElements != numResElements) {

View File

@ -23,14 +23,22 @@
using namespace clang; using namespace clang;
using namespace sema; using namespace sema;
static bool lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD, static LookupResult lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD,
SourceLocation Loc) { SourceLocation Loc, bool &Res) {
DeclarationName DN = S.PP.getIdentifierInfo(Name); DeclarationName DN = S.PP.getIdentifierInfo(Name);
LookupResult LR(S, DN, Loc, Sema::LookupMemberName); LookupResult LR(S, DN, Loc, Sema::LookupMemberName);
// Suppress diagnostics when a private member is selected. The same warnings // Suppress diagnostics when a private member is selected. The same warnings
// will be produced again when building the call. // will be produced again when building the call.
LR.suppressDiagnostics(); 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 /// 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; return PromiseType;
} }
/// Look up the std::coroutine_traits<...>::promise_type for the given /// Look up the std::experimental::coroutine_handle<PromiseType>.
/// function type.
static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType, static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
SourceLocation Loc) { SourceLocation Loc) {
if (PromiseType.isNull()) if (PromiseType.isNull())
@ -314,6 +321,7 @@ static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType,
} }
struct ReadySuspendResumeResult { struct ReadySuspendResumeResult {
enum AwaitCallType { ACT_Ready, ACT_Suspend, ACT_Resume };
Expr *Results[3]; Expr *Results[3];
OpaqueValueExpr *OpaqueValue; OpaqueValueExpr *OpaqueValue;
bool IsInvalid; bool IsInvalid;
@ -359,7 +367,41 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
Calls.Results[I] = Result.get(); Calls.Results[I] = Result.get();
} }
// Assume the calls are valid; all further checking should make them invalid.
Calls.IsInvalid = false; 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; return Calls;
} }
@ -373,7 +415,6 @@ static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise,
if (PromiseRef.isInvalid()) if (PromiseRef.isInvalid())
return ExprError(); return ExprError();
// Call 'yield_value', passing in E.
return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args); 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) { void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
FunctionScopeInfo *Fn = getCurFunction(); FunctionScopeInfo *Fn = getCurFunction();
assert(Fn && Fn->CoroutinePromise && "not a coroutine"); assert(Fn && Fn->isCoroutine() && "not a coroutine");
if (!Body) { if (!Body) {
assert(FD->isInvalidDecl() && assert(FD->isInvalidDecl() &&
"a null body is only allowed for invalid declarations"); "a null body is only allowed for invalid declarations");
return; 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)) { if (isa<CoroutineBodyStmt>(Body)) {
// FIXME(EricWF): Nothing todo. the body is already a transformed coroutine // Nothing todo. the body is already a transformed coroutine body statement.
// body statement.
return; return;
} }
@ -780,7 +823,8 @@ bool CoroutineStmtBuilder::buildDependentStatements() {
assert(!this->IsPromiseDependentType && assert(!this->IsPromiseDependentType &&
"coroutine cannot have a dependent promise type"); "coroutine cannot have a dependent promise type");
this->IsValid = makeOnException() && makeOnFallthrough() && this->IsValid = makeOnException() && makeOnFallthrough() &&
makeReturnOnAllocFailure() && makeNewAndDeleteExpr(); makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&
makeNewAndDeleteExpr();
return this->IsValid; return this->IsValid;
} }
@ -857,15 +901,15 @@ bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
if (ReturnObjectOnAllocationFailure.isInvalid()) if (ReturnObjectOnAllocationFailure.isInvalid())
return false; 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 = StmtResult ReturnStmt =
S.BuildReturnStmt(Loc, ReturnObjectOnAllocationFailure.get()); 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; return false;
}
this->ReturnStmtOnAllocFailure = ReturnStmt.get(); this->ReturnStmtOnAllocFailure = ReturnStmt.get();
return true; return true;
@ -991,13 +1035,32 @@ bool CoroutineStmtBuilder::makeOnFallthrough() {
// [dcl.fct.def.coroutine]/4 // [dcl.fct.def.coroutine]/4
// The unqualified-ids 'return_void' and 'return_value' are looked up in // 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. // the scope of class P. If both are found, the program is ill-formed.
const bool HasRVoid = lookupMember(S, "return_void", PromiseRecordDecl, Loc); bool HasRVoid, HasRValue;
const bool HasRValue = lookupMember(S, "return_value", PromiseRecordDecl, Loc); LookupResult LRVoid =
lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid);
LookupResult LRValue =
lookupMember(S, "return_value", PromiseRecordDecl, Loc, HasRValue);
StmtResult Fallthrough; StmtResult Fallthrough;
if (HasRVoid && HasRValue) { if (HasRVoid && HasRValue) {
// FIXME Improve this diagnostic // 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; << PromiseRecordDecl;
return false; return false;
} else if (HasRVoid) { } else if (HasRVoid) {
@ -1029,6 +1092,8 @@ bool CoroutineStmtBuilder::makeOnException() {
: diag:: : diag::
warn_coroutine_promise_unhandled_exception_required_with_exceptions; warn_coroutine_promise_unhandled_exception_required_with_exceptions;
S.Diag(Loc, DiagID) << PromiseRecordDecl; S.Diag(Loc, DiagID) << PromiseRecordDecl;
S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
<< PromiseRecordDecl;
return !RequireUnhandledException; return !RequireUnhandledException;
} }
@ -1042,37 +1107,185 @@ bool CoroutineStmtBuilder::makeOnException() {
if (UnhandledException.isInvalid()) if (UnhandledException.isInvalid())
return false; 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(); this->OnException = UnhandledException.get();
return true; return true;
} }
bool CoroutineStmtBuilder::makeReturnObject() { bool CoroutineStmtBuilder::makeReturnObject() {
// Build implicit 'p.get_return_object()' expression and form initialization // Build implicit 'p.get_return_object()' expression and form initialization
// of return type from it. // of return type from it.
ExprResult ReturnObject = ExprResult ReturnObject =
buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", None); buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", None);
if (ReturnObject.isInvalid()) if (ReturnObject.isInvalid())
return false; 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(); this->ReturnValue = ReturnObject.get();
return true; 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() { 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; return true;
} }

View File

@ -6516,7 +6516,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
diag::err_thread_non_global) diag::err_thread_non_global)
<< DeclSpec::getSpecifierName(TSCS); << DeclSpec::getSpecifierName(TSCS);
else if (!Context.getTargetInfo().isTLSSupported()) { else if (!Context.getTargetInfo().isTLSSupported()) {
if (getLangOpts().CUDA) { if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) {
// Postpone error emission until we've collected attributes required to // Postpone error emission until we've collected attributes required to
// figure out whether it's a host or device variable and whether the // figure out whether it's a host or device variable and whether the
// error should be ignored. // error should be ignored.
@ -6578,8 +6578,11 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// Handle attributes prior to checking for duplicates in MergeVarDecl // Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewVD, D); ProcessDeclAttributes(S, NewVD, D);
if (getLangOpts().CUDA) { if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) {
if (EmitTLSUnsupportedError && DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) if (EmitTLSUnsupportedError &&
((getLangOpts().CUDA && DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) ||
(getLangOpts().OpenMPIsDevice &&
NewVD->hasAttr<OMPDeclareTargetDeclAttr>())))
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_unsupported); diag::err_thread_unsupported);
// CUDA B.2.5: "__shared__ and __constant__ variables have implied static // 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()) if (PT->isImageType())
return PtrKernelParam; return PtrKernelParam;
if (PT->isBooleanType()) if (PT->isBooleanType() || PT->isEventT() || PT->isReserveIDT())
return InvalidKernelParam;
if (PT->isEventT())
return InvalidKernelParam; return InvalidKernelParam;
// OpenCL extension spec v1.2 s9.5: // 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 WP = AnalysisWarnings.getDefaultPolicy();
sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr; sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;
if (getLangOpts().CoroutinesTS && getCurFunction()->CoroutinePromise) if (getLangOpts().CoroutinesTS && getCurFunction()->isCoroutine())
CheckCompletedCoroutineBody(FD, Body); CheckCompletedCoroutineBody(FD, Body);
if (FD) { if (FD) {
@ -16097,7 +16097,8 @@ void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) {
void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc, void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
Module *Mod) { Module *Mod) {
// Bail if we're not allowed to implicitly import a module here. // Bail if we're not allowed to implicitly import a module here.
if (isSFINAEContext() || !getLangOpts().ModulesErrorRecovery) if (isSFINAEContext() || !getLangOpts().ModulesErrorRecovery ||
VisibleModules.isVisible(Mod))
return; return;
// Create the implicit import declaration. // 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) { getAttrName(const AttrInfo &Attr) {
return &Attr; return &Attr;
} }
const IdentifierInfo *getAttrName(const clang::AttributeList &Attr) { static const IdentifierInfo *getAttrName(const clang::AttributeList &Attr) {
return Attr.getName(); return Attr.getName();
} }
@ -949,7 +949,7 @@ static bool checkFunctionConditionAttr(Sema &S, Decl *D,
Msg = "<no message provided>"; Msg = "<no message provided>";
SmallVector<PartialDiagnosticAt, 8> Diags; SmallVector<PartialDiagnosticAt, 8> Diags;
if (!Cond->isValueDependent() && if (isa<FunctionDecl>(D) && !Cond->isValueDependent() &&
!Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D), !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D),
Diags)) { Diags)) {
S.Diag(Attr.getLoc(), diag::err_attr_cond_never_constant_expr) 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; return;
} }
auto *FD = cast<FunctionDecl>(D); bool ArgDependent = false;
bool ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond); if (const auto *FD = dyn_cast<FunctionDecl>(D))
ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond);
D->addAttr(::new (S.Context) DiagnoseIfAttr( 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())); Attr.getAttributeSpellingListIndex()));
} }
@ -7283,6 +7284,12 @@ public:
return true; 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); bool VisitTypeLoc(TypeLoc Ty);
}; };

View File

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

View File

@ -366,8 +366,18 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD)) if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD))
return true; 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; return true;
} }
@ -15742,6 +15752,13 @@ ExprResult Sema::ActOnObjCAvailabilityCheckExpr(
if (Spec != AvailSpecs.end()) if (Spec != AvailSpecs.end())
Version = Spec->getVersion(); 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) return new (Context)
ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy); 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. // its constexpr-ness, supressing diagnostics while doing so.
if (getLangOpts().CPlusPlus1z && !CallOperator->isInvalidDecl() && if (getLangOpts().CPlusPlus1z && !CallOperator->isInvalidDecl() &&
!CallOperator->isConstexpr() && !CallOperator->isConstexpr() &&
!isa<CoroutineBodyStmt>(CallOperator->getBody()) &&
!Class->getDeclContext()->isDependentContext()) { !Class->getDeclContext()->isDependentContext()) {
TentativeAnalysisScope DiagnosticScopeGuard(*this); TentativeAnalysisScope DiagnosticScopeGuard(*this);
CallOperator->setConstexpr( CallOperator->setConstexpr(

View File

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

View File

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

View File

@ -197,6 +197,7 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
case DefaultTemplateArgumentChecking: case DefaultTemplateArgumentChecking:
case DeclaringSpecialMember: case DeclaringSpecialMember:
case DefiningSynthesizedFunction:
return false; return false;
} }
@ -624,6 +625,17 @@ void Sema::PrintInstantiationStack() {
diag::note_in_declaration_of_implicit_special_member) diag::note_in_declaration_of_implicit_special_member)
<< cast<CXXRecordDecl>(Active->Entity) << Active->SpecialMember; << cast<CXXRecordDecl>(Active->Entity) << Active->SpecialMember;
break; 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; return Active->DeductionInfo;
case CodeSynthesisContext::DeclaringSpecialMember: case CodeSynthesisContext::DeclaringSpecialMember:
case CodeSynthesisContext::DefiningSynthesizedFunction:
// This happens in a context unrelated to template instantiation, so // This happens in a context unrelated to template instantiation, so
// there is no SFINAE. // there is no SFINAE.
return None; return None;

View File

@ -6945,6 +6945,19 @@ TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
if (DeallocRes.isInvalid()) if (DeallocRes.isInvalid())
return StmtError(); return StmtError();
Builder.Deallocate = DeallocRes.get(); 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); return getDerived().RebuildCoroutineBodyStmt(Builder);

View File

@ -116,7 +116,11 @@ CommonOptionsParser::CommonOptionsParser(
cl::HideUnrelatedOptions(Category); 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::ParseCommandLineOptions(argc, argv, Overview);
cl::PrintOptionValues(); cl::PrintOptionValues();
@ -125,7 +129,6 @@ CommonOptionsParser::CommonOptionsParser(
SourcePathList.empty()) SourcePathList.empty())
return; return;
if (!Compilations) { if (!Compilations) {
std::string ErrorMessage;
if (!BuildPath.empty()) { if (!BuildPath.empty()) {
Compilations = Compilations =
CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage); CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage);

View File

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

View File

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

View File

@ -167,7 +167,7 @@ namespace test3 {
Base2, // expected-error 2 {{base class 'test3::Base2' has private destructor}} Base2, // expected-error 2 {{base class 'test3::Base2' has private destructor}}
virtual Base3 virtual Base3
{}; {};
Derived3 d3; // expected-note {{implicit default constructor}}\ Derived3 d3; // expected-note 3{{implicit default constructor}}\
// expected-note{{implicit destructor}}} // expected-note{{implicit destructor}}}
#else #else
template <unsigned N> class Base { ~Base(); }; // expected-note 4{{declared private here}} 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 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
// 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 // 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 *********************************/ /********************************** LOWERING *********************************/
/*****************************************************************************/ /*****************************************************************************/
typedef float float3 __attribute__((ext_vector_type(3)));
typedef float float4 __attribute__((ext_vector_type(4))); typedef float float4 __attribute__((ext_vector_type(4)));
typedef float float8 __attribute__((ext_vector_type(8))); typedef float float8 __attribute__((ext_vector_type(8)));
typedef double double2 __attribute__((ext_vector_type(2))); typedef double double2 __attribute__((ext_vector_type(2)));
@ -1005,3 +1007,10 @@ struct {
TEST(union_het_vecint) TEST(union_het_vecint)
// CHECK: define swiftcc void @return_union_het_vecint([[UNION:%.*]]* noalias sret // CHECK: define swiftcc void @return_union_het_vecint([[UNION:%.*]]* noalias sret
// CHECK: define swiftcc void @take_union_het_vecint([[UNION]]* // 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 // 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 // Test new aarch64 intrinsics and types

View File

@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \ // 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 // Test new aarch64 intrinsics and types

View File

@ -1,6 +1,6 @@
// REQUIRES: aarch64-registered-target // REQUIRES: aarch64-registered-target
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \ // 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 // Test new aarch64 intrinsics and types

View File

@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \ // 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 // 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 // Test new aarch64 intrinsics and types

View File

@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \ // 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: | opt -S -mem2reg \
// RUN: | FileCheck %s // RUN: | FileCheck %s

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