Vendor import of llvm-project branch release/21.x llvmorg-21.1.7-0-gcd708029e0b2, a.k.a. 21.1.7 release.

This commit is contained in:
Dimitry Andric
2025-12-27 23:21:13 +01:00
parent 7f920884cd
commit 294ba56980
328 changed files with 5969 additions and 2784 deletions
+15
View File
@@ -6953,6 +6953,21 @@ clang_getCursorUnaryOperatorKind(CXCursor cursor);
* @} * @}
*/ */
CINDEX_DEPRECATED
typedef void *CXRemapping;
CINDEX_DEPRECATED CINDEX_LINKAGE CXRemapping clang_getRemappings(const char *);
CINDEX_DEPRECATED CINDEX_LINKAGE CXRemapping
clang_getRemappingsFromFileList(const char **, unsigned);
CINDEX_DEPRECATED CINDEX_LINKAGE unsigned clang_remap_getNumFiles(CXRemapping);
CINDEX_DEPRECATED CINDEX_LINKAGE void
clang_remap_getFilenames(CXRemapping, unsigned, CXString *, CXString *);
CINDEX_DEPRECATED CINDEX_LINKAGE void clang_remap_dispose(CXRemapping);
LLVM_CLANG_C_EXTERN_C_END LLVM_CLANG_C_EXTERN_C_END
#endif #endif
+1 -1
View File
@@ -143,7 +143,7 @@ class APValue {
AddrLabelDiff AddrLabelDiff
}; };
class LValueBase { class alignas(uint64_t) LValueBase {
typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue, typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
DynamicAllocLValue> DynamicAllocLValue>
PtrTy; PtrTy;
+1 -2
View File
@@ -648,8 +648,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
bool containsNonRelocatablePointerAuth(QualType T) { bool containsNonRelocatablePointerAuth(QualType T) {
if (!isPointerAuthenticationAvailable()) if (!isPointerAuthenticationAvailable())
return false; return false;
return findPointerAuthContent(T) == return findPointerAuthContent(T) != PointerAuthContent::None;
PointerAuthContent::AddressDiscriminatedData;
} }
private: private:
+3 -3
View File
@@ -9417,9 +9417,9 @@ def NonStringDocs : Documentation {
let Category = DocCatDecl; let Category = DocCatDecl;
let Content = [{ let Content = [{
The ``nonstring`` attribute can be applied to the declaration of a variable or The ``nonstring`` attribute can be applied to the declaration of a variable or
a field whose type is a character array to specify that the character array is a field whose type is a character pointer or character array to specify that
not intended to behave like a null-terminated string. This will silence the buffer is not intended to behave like a null-terminated string. This will
diagnostics with code like: silence diagnostics with code like:
.. code-block:: c .. code-block:: c
@@ -507,6 +507,14 @@ def note_odr_number_of_bases : Note<
"class has %0 base %plural{1:class|:classes}0">; "class has %0 base %plural{1:class|:classes}0">;
def note_odr_enumerator : Note<"enumerator %0 with value %1 here">; def note_odr_enumerator : Note<"enumerator %0 with value %1 here">;
def note_odr_missing_enumerator : Note<"no corresponding enumerator here">; def note_odr_missing_enumerator : Note<"no corresponding enumerator here">;
def note_odr_incompatible_fixed_underlying_type : Note<
"enumeration %0 declared with incompatible fixed underlying types (%1 vs. "
"%2)">;
def note_odr_fixed_underlying_type : Note<
"enumeration %0 has fixed underlying type here">;
def note_odr_missing_fixed_underlying_type : Note<
"enumeration %0 missing fixed underlying type here">;
def err_odr_field_type_inconsistent : Error< def err_odr_field_type_inconsistent : Error<
"field %0 declared with incompatible types in different " "field %0 declared with incompatible types in different "
"translation units (%1 vs. %2)">; "translation units (%1 vs. %2)">;
@@ -624,6 +624,7 @@ def MissingFieldInitializers : DiagGroup<"missing-field-initializers",
def ModuleLock : DiagGroup<"module-lock">; def ModuleLock : DiagGroup<"module-lock">;
def ModuleBuild : DiagGroup<"module-build">; def ModuleBuild : DiagGroup<"module-build">;
def ModuleImport : DiagGroup<"module-import">; def ModuleImport : DiagGroup<"module-import">;
def ModuleValidation : DiagGroup<"module-validation">;
def ModuleConflict : DiagGroup<"module-conflict">; def ModuleConflict : DiagGroup<"module-conflict">;
def ModuleFileExtension : DiagGroup<"module-file-extension">; def ModuleFileExtension : DiagGroup<"module-file-extension">;
def ModuleIncludeDirectiveTranslation : DiagGroup<"module-include-translation">; def ModuleIncludeDirectiveTranslation : DiagGroup<"module-include-translation">;
@@ -82,6 +82,10 @@ def remark_module_import : Remark<
"importing module '%0'%select{| into '%3'}2 from '%1'">, "importing module '%0'%select{| into '%3'}2 from '%1'">,
ShowInSystemHeader, ShowInSystemHeader,
InGroup<ModuleImport>; InGroup<ModuleImport>;
def remark_module_validation : Remark<
"validating %0 input files in module '%1' from '%2'">,
ShowInSystemHeader,
InGroup<ModuleValidation>;
def err_imported_module_not_found : Error< def err_imported_module_not_found : Error<
"module '%0' in precompiled file '%1' %select{(imported by precompiled file '%2') |}4" "module '%0' in precompiled file '%1' %select{(imported by precompiled file '%2') |}4"
+6 -3
View File
@@ -147,14 +147,17 @@ FEATURE(type_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Type))
FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread)) FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow)) FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics) FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics &&
EXTENSION(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics) PP.getTargetInfo().getTriple().isOSDarwin())
FEATURE(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics &&
PP.getTargetInfo().getTriple().isOSDarwin())
FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls) FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls)
FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns) FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns)
FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination) FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination)
FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination) FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination)
FEATURE(ptrauth_type_info_vtable_pointer_discrimination, LangOpts.PointerAuthTypeInfoVTPtrDiscrimination) FEATURE(ptrauth_type_info_vtable_pointer_discrimination, LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)
FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls) FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls)
FEATURE(ptrauth_signed_block_descriptors, LangOpts.PointerAuthBlockDescriptorPointers)
FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFunctionTypeDiscrimination) FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFunctionTypeDiscrimination)
FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos) FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos)
FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini) FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini)
@@ -163,7 +166,7 @@ FEATURE(ptrauth_elf_got, LangOpts.PointerAuthELFGOT)
FEATURE(ptrauth_objc_isa, LangOpts.PointerAuthObjcIsa) FEATURE(ptrauth_objc_isa, LangOpts.PointerAuthObjcIsa)
FEATURE(ptrauth_objc_interface_sel, LangOpts.PointerAuthObjcInterfaceSel) FEATURE(ptrauth_objc_interface_sel, LangOpts.PointerAuthObjcInterfaceSel)
FEATURE(ptrauth_objc_signable_class, true) FEATURE(ptrauth_objc_signable_class, LangOpts.PointerAuthIntrinsics)
FEATURE(ptrauth_objc_method_list_pointer, LangOpts.PointerAuthCalls) FEATURE(ptrauth_objc_method_list_pointer, LangOpts.PointerAuthCalls)
EXTENSION(swiftcc, EXTENSION(swiftcc,
@@ -138,6 +138,8 @@ LANGOPT(PointerAuthObjcInterfaceSel, 1, 0, NotCompatible, "authentication of SEL
LANGOPT(PointerAuthObjcInterfaceSelKey, 16, 0, NotCompatible, "authentication key for SEL fields of ObjC interfaces") LANGOPT(PointerAuthObjcInterfaceSelKey, 16, 0, NotCompatible, "authentication key for SEL fields of ObjC interfaces")
LANGOPT(PointerAuthObjcClassROPointers, 1, 0, Benign, "class_ro_t pointer authentication") LANGOPT(PointerAuthObjcClassROPointers, 1, 0, Benign, "class_ro_t pointer authentication")
LANGOPT(PointerAuthBlockDescriptorPointers, 1, 0, NotCompatible, "enable signed block descriptors")
LANGOPT(DoubleSquareBracketAttributes, 1, 0, NotCompatible, "'[[]]' attributes extension for all language standard modes") LANGOPT(DoubleSquareBracketAttributes, 1, 0, NotCompatible, "'[[]]' attributes extension for all language standard modes")
LANGOPT(ExperimentalLateParseAttributes, 1, 0, NotCompatible, "experimental late parsing of attributes") LANGOPT(ExperimentalLateParseAttributes, 1, 0, NotCompatible, "experimental late parsing of attributes")
@@ -496,6 +498,8 @@ LANGOPT(CheckConstexprFunctionBodies, 1, 1, Benign,
LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C") LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C")
LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, "Experimental lifetime safety analysis for C++")
LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type") LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type")
#undef LANGOPT #undef LANGOPT
@@ -23,6 +23,10 @@
namespace clang { namespace clang {
/// Constant discriminator to be used with block descriptor pointers. The value
/// is ptrauth_string_discriminator("block_descriptor")
constexpr uint16_t BlockDescriptorConstantDiscriminator = 0xC0BB;
/// Constant discriminator to be used with function pointers in .init_array and /// Constant discriminator to be used with function pointers in .init_array and
/// .fini_array. The value is ptrauth_string_discriminator("init_fini") /// .fini_array. The value is ptrauth_string_discriminator("init_fini")
constexpr uint16_t InitFiniPointerConstantDiscriminator = 0xD9D4; constexpr uint16_t InitFiniPointerConstantDiscriminator = 0xD9D4;
@@ -223,6 +227,18 @@ struct PointerAuthOptions {
/// The ABI for function addresses in .init_array and .fini_array /// The ABI for function addresses in .init_array and .fini_array
PointerAuthSchema InitFiniPointers; PointerAuthSchema InitFiniPointers;
/// The ABI for block invocation function pointers.
PointerAuthSchema BlockInvocationFunctionPointers;
/// The ABI for block object copy/destroy function pointers.
PointerAuthSchema BlockHelperFunctionPointers;
/// The ABI for __block variable copy/destroy function pointers.
PointerAuthSchema BlockByrefHelperFunctionPointers;
/// The ABI for pointers to block descriptors.
PointerAuthSchema BlockDescriptorPointers;
/// The ABI for Objective-C method lists. /// The ABI for Objective-C method lists.
PointerAuthSchema ObjCMethodListFunctionPointers; PointerAuthSchema ObjCMethodListFunctionPointers;
File diff suppressed because it is too large Load Diff
+22 -1
View File
@@ -990,6 +990,13 @@ def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>,
Visibility<[ClangOption, CLOption, FlangOption]>, Visibility<[ClangOption, CLOption, FlangOption]>,
HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">, HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">,
Group<Link_Group>; Group<Link_Group>;
def Xthinlto_distributor_EQ : CommaJoined<["-"], "Xthinlto-distributor=">,
Flags<[LinkOption]>,
Visibility<[ClangOption, CLOption]>,
HelpText<"Pass <arg> to the ThinLTO distributor process. Can be specified "
"multiple times or with comma-separated values.">,
MetaVarName<"<arg>">,
Group<Link_Group>;
def Xoffload_linker : JoinedAndSeparate<["-"], "Xoffload-linker">, def Xoffload_linker : JoinedAndSeparate<["-"], "Xoffload-linker">,
Visibility<[ClangOption, FlangOption]>, Visibility<[ClangOption, FlangOption]>,
HelpText<"Pass <arg> to the offload linkers or the ones identified by -<triple>">, HelpText<"Pass <arg> to the offload linkers or the ones identified by -<triple>">,
@@ -1910,6 +1917,14 @@ defm bounds_safety : BoolFOption<
BothFlags<[], [CC1Option], BothFlags<[], [CC1Option],
" experimental bounds safety extension for C">>; " experimental bounds safety extension for C">>;
defm lifetime_safety : BoolFOption<
"experimental-lifetime-safety",
LangOpts<"EnableLifetimeSafety">, DefaultFalse,
PosFlag<SetTrue, [], [CC1Option], "Enable">,
NegFlag<SetFalse, [], [CC1Option], "Disable">,
BothFlags<[], [CC1Option],
" experimental lifetime safety for C++">>;
defm addrsig : BoolFOption<"addrsig", defm addrsig : BoolFOption<"addrsig",
CodeGenOpts<"Addrsig">, DefaultFalse, CodeGenOpts<"Addrsig">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">, PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">,
@@ -4249,7 +4264,12 @@ def ffinite_loops: Flag<["-"], "ffinite-loops">, Group<f_Group>,
def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group<f_Group>, def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group<f_Group>,
HelpText<"Do not assume that any loop is finite.">, HelpText<"Do not assume that any loop is finite.">,
Visibility<[ClangOption, CC1Option]>; Visibility<[ClangOption, CC1Option]>;
def fthinlto_distributor_EQ : Joined<["-"], "fthinlto-distributor=">,
Group<f_Group>,
HelpText<"Path to the ThinLTO distributor process. If specified, "
"ThinLTO backend compilations will be distributed by LLD">,
MetaVarName<"<path>">,
Visibility<[ClangOption, CLOption]>;
def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>, def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>,
HelpText<"Process trigraph sequences">, Visibility<[ClangOption, CC1Option]>; HelpText<"Process trigraph sequences">, Visibility<[ClangOption, CC1Option]>;
def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>, def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
@@ -4507,6 +4527,7 @@ defm aarch64_jump_table_hardening: OptInCC1FFlag<"aarch64-jump-table-hardening",
defm ptrauth_objc_isa : OptInCC1FFlag<"ptrauth-objc-isa", "Enable signing and authentication of Objective-C object's 'isa' field">; defm ptrauth_objc_isa : OptInCC1FFlag<"ptrauth-objc-isa", "Enable signing and authentication of Objective-C object's 'isa' field">;
defm ptrauth_objc_interface_sel : OptInCC1FFlag<"ptrauth-objc-interface-sel", "Enable signing and authentication of Objective-C object's 'SEL' fields">; defm ptrauth_objc_interface_sel : OptInCC1FFlag<"ptrauth-objc-interface-sel", "Enable signing and authentication of Objective-C object's 'SEL' fields">;
defm ptrauth_objc_class_ro : OptInCC1FFlag<"ptrauth-objc-class-ro", "Enable signing and authentication for ObjC class_ro pointers">; defm ptrauth_objc_class_ro : OptInCC1FFlag<"ptrauth-objc-class-ro", "Enable signing and authentication for ObjC class_ro pointers">;
defm ptrauth_block_descriptor_pointers : OptInCC1FFlag<"ptrauth-block-descriptor-pointers", "Enable signing and authentication of block descriptors">;
} }
def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>, def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
+11 -3
View File
@@ -4694,6 +4694,13 @@ struct FormatStyle {
/// <conditional-body> <conditional-body> /// <conditional-body> <conditional-body>
/// \endcode /// \endcode
bool AfterIfMacros; bool AfterIfMacros;
/// If ``true``, put a space between alternative operator ``not`` and the
/// opening parenthesis.
/// \code
/// true: false:
/// return not (a || b); vs. return not(a || b);
/// \endcode
bool AfterNot;
/// If ``true``, put a space between operator overloading and opening /// If ``true``, put a space between operator overloading and opening
/// parentheses. /// parentheses.
/// \code /// \code
@@ -4742,9 +4749,9 @@ struct FormatStyle {
: AfterControlStatements(false), AfterForeachMacros(false), : AfterControlStatements(false), AfterForeachMacros(false),
AfterFunctionDeclarationName(false), AfterFunctionDeclarationName(false),
AfterFunctionDefinitionName(false), AfterIfMacros(false), AfterFunctionDefinitionName(false), AfterIfMacros(false),
AfterOverloadedOperator(false), AfterPlacementOperator(true), AfterNot(false), AfterOverloadedOperator(false),
AfterRequiresInClause(false), AfterRequiresInExpression(false), AfterPlacementOperator(true), AfterRequiresInClause(false),
BeforeNonEmptyParentheses(false) {} AfterRequiresInExpression(false), BeforeNonEmptyParentheses(false) {}
bool operator==(const SpaceBeforeParensCustom &Other) const { bool operator==(const SpaceBeforeParensCustom &Other) const {
return AfterControlStatements == Other.AfterControlStatements && return AfterControlStatements == Other.AfterControlStatements &&
@@ -4753,6 +4760,7 @@ struct FormatStyle {
Other.AfterFunctionDeclarationName && Other.AfterFunctionDeclarationName &&
AfterFunctionDefinitionName == Other.AfterFunctionDefinitionName && AfterFunctionDefinitionName == Other.AfterFunctionDefinitionName &&
AfterIfMacros == Other.AfterIfMacros && AfterIfMacros == Other.AfterIfMacros &&
AfterNot == Other.AfterNot &&
AfterOverloadedOperator == Other.AfterOverloadedOperator && AfterOverloadedOperator == Other.AfterOverloadedOperator &&
AfterPlacementOperator == Other.AfterPlacementOperator && AfterPlacementOperator == Other.AfterPlacementOperator &&
AfterRequiresInClause == Other.AfterRequiresInClause && AfterRequiresInClause == Other.AfterRequiresInClause &&
-3
View File
@@ -143,9 +143,6 @@ class Lexer : public PreprocessorLexer {
/// True if this is the first time we're lexing the input file. /// True if this is the first time we're lexing the input file.
bool IsFirstTimeLexingFile; bool IsFirstTimeLexingFile;
/// True if current lexing token is the first pp-token.
bool IsFirstPPToken;
// NewLinePtr - A pointer to new line character '\n' being lexed. For '\r\n', // NewLinePtr - A pointer to new line character '\n' being lexed. For '\r\n',
// it also points to '\n.' // it also points to '\n.'
const char *NewLinePtr; const char *NewLinePtr;
@@ -0,0 +1,310 @@
//===--- NoTrivialPPDirectiveTracer.h ---------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the NoTrivialPPDirectiveTracer interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
#define LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
#include "clang/Lex/PPCallbacks.h"
namespace clang {
class Preprocessor;
/// Consider the following code:
///
/// # 1 __FILE__ 1 3
/// export module a;
///
/// According to the wording in
/// [P1857R3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1857r3.html):
///
/// A module directive may only appear as the first preprocessing tokens in a
/// file (excluding the global module fragment.)
///
/// and the wording in
/// [[cpp.pre]](https://eel.is/c++draft/cpp.pre#nt:module-file):
/// module-file:
/// pp-global-module-fragment[opt] pp-module group[opt]
/// pp-private-module-fragment[opt]
///
/// `#` is the first pp-token in the translation unit, and it was rejected by
/// clang, but they really should be exempted from this rule. The goal is to not
/// allow any preprocessor conditionals or most state changes, but these don't
/// fit that.
///
/// State change would mean most semantically observable preprocessor state,
/// particularly anything that is order dependent. Global flags like being a
/// system header/module shouldn't matter.
///
/// We should exempt a brunch of directives, even though it violates the current
/// standard wording.
///
/// This class used to trace 'no-trivial' pp-directives in main file, which may
/// change the preprocessing state.
///
/// FIXME: Once the wording of the standard is revised, we need to follow the
/// wording of the standard. Currently this is just a workaround
class NoTrivialPPDirectiveTracer : public PPCallbacks {
Preprocessor &PP;
/// Whether preprocessing main file. We only focus on the main file.
bool InMainFile = true;
/// Whether one or more conditional, include or other 'no-trivial'
/// pp-directives has seen before.
bool SeenNoTrivialPPDirective = false;
void setSeenNoTrivialPPDirective();
public:
NoTrivialPPDirectiveTracer(Preprocessor &P) : PP(P) {}
bool hasSeenNoTrivialPPDirective() const;
/// Callback invoked whenever the \p Lexer moves to a different file for
/// lexing. Unlike \p FileChanged line number directives and other related
/// pragmas do not trigger callbacks to \p LexedFileChanged.
///
/// \param FID The \p FileID that the \p Lexer moved to.
///
/// \param Reason Whether the \p Lexer entered a new file or exited one.
///
/// \param FileType The \p CharacteristicKind of the file the \p Lexer moved
/// to.
///
/// \param PrevFID The \p FileID the \p Lexer was using before the change.
///
/// \param Loc The location where the \p Lexer entered a new file from or the
/// location that the \p Lexer moved into after exiting a file.
void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
SrcMgr::CharacteristicKind FileType, FileID PrevFID,
SourceLocation Loc) override;
/// Callback invoked whenever an embed directive has been processed,
/// regardless of whether the embed will actually find a file.
///
/// \param HashLoc The location of the '#' that starts the embed directive.
///
/// \param FileName The name of the file being included, as written in the
/// source code.
///
/// \param IsAngled Whether the file name was enclosed in angle brackets;
/// otherwise, it was enclosed in quotes.
///
/// \param File The actual file that may be included by this embed directive.
///
/// \param Params The parameters used by the directive.
void EmbedDirective(SourceLocation HashLoc, StringRef FileName, bool IsAngled,
OptionalFileEntryRef File,
const LexEmbedParametersResult &Params) override {
setSeenNoTrivialPPDirective();
}
/// Callback invoked whenever an inclusion directive of
/// any kind (\c \#include, \c \#import, etc.) has been processed, regardless
/// of whether the inclusion will actually result in an inclusion.
///
/// \param HashLoc The location of the '#' that starts the inclusion
/// directive.
///
/// \param IncludeTok The token that indicates the kind of inclusion
/// directive, e.g., 'include' or 'import'.
///
/// \param FileName The name of the file being included, as written in the
/// source code.
///
/// \param IsAngled Whether the file name was enclosed in angle brackets;
/// otherwise, it was enclosed in quotes.
///
/// \param FilenameRange The character range of the quotes or angle brackets
/// for the written file name.
///
/// \param File The actual file that may be included by this inclusion
/// directive.
///
/// \param SearchPath Contains the search path which was used to find the file
/// in the file system. If the file was found via an absolute include path,
/// SearchPath will be empty. For framework includes, the SearchPath and
/// RelativePath will be split up. For example, if an include of "Some/Some.h"
/// is found via the framework path
/// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
/// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
/// "Some.h".
///
/// \param RelativePath The path relative to SearchPath, at which the include
/// file was found. This is equal to FileName except for framework includes.
///
/// \param SuggestedModule The module suggested for this header, if any.
///
/// \param ModuleImported Whether this include was translated into import of
/// \p SuggestedModule.
///
/// \param FileType The characteristic kind, indicates whether a file or
/// directory holds normal user code, system code, or system code which is
/// implicitly 'extern "C"' in C++ mode.
///
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange,
OptionalFileEntryRef File, StringRef SearchPath,
StringRef RelativePath, const Module *SuggestedModule,
bool ModuleImported,
SrcMgr::CharacteristicKind FileType) override {
setSeenNoTrivialPPDirective();
}
/// Callback invoked whenever there was an explicit module-import
/// syntax.
///
/// \param ImportLoc The location of import directive token.
///
/// \param Path The identifiers (and their locations) of the module
/// "path", e.g., "std.vector" would be split into "std" and "vector".
///
/// \param Imported The imported module; can be null if importing failed.
///
void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
const Module *Imported) override {
setSeenNoTrivialPPDirective();
}
/// Callback invoked when the end of the main file is reached.
///
/// No subsequent callbacks will be made.
void EndOfMainFile() override { setSeenNoTrivialPPDirective(); }
/// Callback invoked when start reading any pragma directive.
void PragmaDirective(SourceLocation Loc,
PragmaIntroducerKind Introducer) override {}
/// Called by Preprocessor::HandleMacroExpandedIdentifier when a
/// macro invocation is found.
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
SourceRange Range, const MacroArgs *Args) override;
/// Hook called whenever a macro definition is seen.
void MacroDefined(const Token &MacroNameTok,
const MacroDirective *MD) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever a macro \#undef is seen.
/// \param MacroNameTok The active Token
/// \param MD A MacroDefinition for the named macro.
/// \param Undef New MacroDirective if the macro was defined, null otherwise.
///
/// MD is released immediately following this callback.
void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
const MacroDirective *Undef) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever the 'defined' operator is seen.
/// \param MD The MacroDirective if the name was a macro, null otherwise.
void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
SourceRange Range) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#if is seen.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
/// \param ConditionValue The evaluated value of the condition.
///
// FIXME: better to pass in a list (or tree!) of Tokens.
void If(SourceLocation Loc, SourceRange ConditionRange,
ConditionValueKind ConditionValue) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#elif is seen.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
/// \param ConditionValue The evaluated value of the condition.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
// FIXME: better to pass in a list (or tree!) of Tokens.
void Elif(SourceLocation Loc, SourceRange ConditionRange,
ConditionValueKind ConditionValue, SourceLocation IfLoc) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#ifdef is seen.
/// \param Loc the source location of the directive.
/// \param MacroNameTok Information on the token being tested.
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#elifdef branch is taken.
/// \param Loc the source location of the directive.
/// \param MacroNameTok Information on the token being tested.
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#elifdef is skipped.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
// FIXME: better to pass in a list (or tree!) of Tokens.
void Elifdef(SourceLocation Loc, SourceRange ConditionRange,
SourceLocation IfLoc) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#ifndef is seen.
/// \param Loc the source location of the directive.
/// \param MacroNameTok Information on the token being tested.
/// \param MD The MacroDefiniton if the name was a macro, null otherwise.
void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#elifndef branch is taken.
/// \param Loc the source location of the directive.
/// \param MacroNameTok Information on the token being tested.
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#elifndef is skipped.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
// FIXME: better to pass in a list (or tree!) of Tokens.
void Elifndef(SourceLocation Loc, SourceRange ConditionRange,
SourceLocation IfLoc) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#else is seen.
/// \param Loc the source location of the directive.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
void Else(SourceLocation Loc, SourceLocation IfLoc) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#endif is seen.
/// \param Loc the source location of the directive.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
setSeenNoTrivialPPDirective();
}
};
} // namespace clang
#endif // LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
+12
View File
@@ -82,6 +82,7 @@ class PreprocessorLexer;
class PreprocessorOptions; class PreprocessorOptions;
class ScratchBuffer; class ScratchBuffer;
class TargetInfo; class TargetInfo;
class NoTrivialPPDirectiveTracer;
namespace Builtin { namespace Builtin {
class Context; class Context;
@@ -353,6 +354,11 @@ class Preprocessor {
/// First pp-token source location in current translation unit. /// First pp-token source location in current translation unit.
SourceLocation FirstPPTokenLoc; SourceLocation FirstPPTokenLoc;
/// A preprocessor directive tracer to trace whether the preprocessing
/// state changed. These changes would mean most semantically observable
/// preprocessor state, particularly anything that is order dependent.
NoTrivialPPDirectiveTracer *DirTracer = nullptr;
/// A position within a C++20 import-seq. /// A position within a C++20 import-seq.
class StdCXXImportSeq { class StdCXXImportSeq {
public: public:
@@ -609,6 +615,8 @@ class Preprocessor {
return State == NamedModuleImplementation && !getName().contains(':'); return State == NamedModuleImplementation && !getName().contains(':');
} }
bool isNotAModuleDecl() const { return State == NotAModuleDecl; }
StringRef getName() const { StringRef getName() const {
assert(isNamedModule() && "Can't get name from a non named module"); assert(isNamedModule() && "Can't get name from a non named module");
return Name; return Name;
@@ -3087,6 +3095,10 @@ class Preprocessor {
bool setDeserializedSafeBufferOptOutMap( bool setDeserializedSafeBufferOptOutMap(
const SmallVectorImpl<SourceLocation> &SrcLocSeqs); const SmallVectorImpl<SourceLocation> &SrcLocSeqs);
/// Whether we've seen pp-directives which may have changed the preprocessing
/// state.
bool hasSeenNoTrivialPPDirective() const;
private: private:
/// Helper functions to forward lexing to the actual lexer. They all share the /// Helper functions to forward lexing to the actual lexer. They all share the
/// same signature. /// same signature.
+9 -8
View File
@@ -86,12 +86,12 @@ class Token {
// macro stringizing or charizing operator. // macro stringizing or charizing operator.
CommaAfterElided = 0x200, // The comma following this token was elided (MS). CommaAfterElided = 0x200, // The comma following this token was elided (MS).
IsEditorPlaceholder = 0x400, // This identifier is a placeholder. IsEditorPlaceholder = 0x400, // This identifier is a placeholder.
IsReinjected = 0x800, // A phase 4 token that was produced before and
IsReinjected = 0x800, // A phase 4 token that was produced before and // re-added, e.g. via EnterTokenStream. Annotation
// re-added, e.g. via EnterTokenStream. Annotation // tokens are *not* reinjected.
// tokens are *not* reinjected. HasSeenNoTrivialPPDirective =
FirstPPToken = 0x1000, // This token is the first pp token in the 0x1000, // Whether we've seen any 'no-trivial' pp-directives before
// translation unit. // current position.
}; };
tok::TokenKind getKind() const { return Kind; } tok::TokenKind getKind() const { return Kind; }
@@ -321,8 +321,9 @@ class Token {
/// lexer uses identifier tokens to represent placeholders. /// lexer uses identifier tokens to represent placeholders.
bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); } bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); }
/// Returns true if this token is the first pp-token. bool hasSeenNoTrivialPPDirective() const {
bool isFirstPPToken() const { return getFlag(FirstPPToken); } return getFlag(HasSeenNoTrivialPPDirective);
}
}; };
/// Information about the conditional stack (\#if directives) /// Information about the conditional stack (\#if directives)
+3 -8
View File
@@ -350,11 +350,6 @@ class Sema;
LLVM_PREFERRED_TYPE(bool) LLVM_PREFERRED_TYPE(bool)
unsigned BindsToRvalue : 1; unsigned BindsToRvalue : 1;
/// Whether this was an identity conversion with qualification
/// conversion for the implicit object argument.
LLVM_PREFERRED_TYPE(bool)
unsigned IsImplicitObjectArgumentQualificationConversion : 1;
/// Whether this binds an implicit object argument to a /// Whether this binds an implicit object argument to a
/// non-static member function without a ref-qualifier. /// non-static member function without a ref-qualifier.
LLVM_PREFERRED_TYPE(bool) LLVM_PREFERRED_TYPE(bool)
@@ -453,11 +448,11 @@ class Sema;
#endif #endif
return true; return true;
} }
if (!C.hasSameType(getFromType(), getToType(2)))
return false;
if (BindsToRvalue && IsLvalueReference) if (BindsToRvalue && IsLvalueReference)
return false; return false;
if (IsImplicitObjectArgumentQualificationConversion) return true;
return C.hasSameUnqualifiedType(getFromType(), getToType(2));
return C.hasSameType(getFromType(), getToType(2));
} }
ImplicitConversionRank getRank() const; ImplicitConversionRank getRank() const;
+1 -1
View File
@@ -9836,7 +9836,7 @@ class Sema final : public SemaBase {
SourceLocation ModuleLoc, ModuleDeclKind MDK, SourceLocation ModuleLoc, ModuleDeclKind MDK,
ModuleIdPath Path, ModuleIdPath Partition, ModuleIdPath Path, ModuleIdPath Partition,
ModuleImportState &ImportState, ModuleImportState &ImportState,
bool IntroducerIsFirstPPToken); bool SeenNoTrivialPPDirective);
/// The parser has processed a global-module-fragment declaration that begins /// The parser has processed a global-module-fragment declaration that begins
/// the definition of the global module fragment of the current module unit. /// the definition of the global module fragment of the current module unit.
+4 -1
View File
@@ -1725,6 +1725,9 @@ ASTContext::PointerAuthContent ASTContext::findPointerAuthContent(QualType T) {
assert(isPointerAuthenticationAvailable()); assert(isPointerAuthenticationAvailable());
T = T.getCanonicalType(); T = T.getCanonicalType();
if (T->isDependentType())
return PointerAuthContent::None;
if (T.hasAddressDiscriminatedPointerAuth()) if (T.hasAddressDiscriminatedPointerAuth())
return PointerAuthContent::AddressDiscriminatedData; return PointerAuthContent::AddressDiscriminatedData;
const RecordDecl *RD = T->getAsRecordDecl(); const RecordDecl *RD = T->getAsRecordDecl();
@@ -3032,7 +3035,7 @@ bool ASTContext::hasUniqueObjectRepresentations(
return true; return true;
} }
// All other pointers (except __ptrauth pointers) are unique. // All other pointers are unique.
if (Ty->isPointerType()) if (Ty->isPointerType())
return !Ty.hasAddressDiscriminatedPointerAuth(); return !Ty.hasAddressDiscriminatedPointerAuth();
+69 -3
View File
@@ -456,7 +456,9 @@ CheckStructurallyEquivalentAttributes(StructuralEquivalenceContext &Context,
const Decl *D1, const Decl *D2, const Decl *D1, const Decl *D2,
const Decl *PrimaryDecl = nullptr) { const Decl *PrimaryDecl = nullptr) {
// If either declaration has an attribute on it, we treat the declarations // If either declaration has an attribute on it, we treat the declarations
// as not being structurally equivalent. // as not being structurally equivalent unless both declarations are implicit
// (ones generated by the compiler like __NSConstantString_tag).
//
// FIXME: this should be handled on a case-by-case basis via tablegen in // FIXME: this should be handled on a case-by-case basis via tablegen in
// Attr.td. There are multiple cases to consider: one declaration with the // Attr.td. There are multiple cases to consider: one declaration with the
// attribute, another without it; different attribute syntax|spellings for // attribute, another without it; different attribute syntax|spellings for
@@ -468,7 +470,7 @@ CheckStructurallyEquivalentAttributes(StructuralEquivalenceContext &Context,
D1Attr = *D1->getAttrs().begin(); D1Attr = *D1->getAttrs().begin();
if (D2->hasAttrs()) if (D2->hasAttrs())
D2Attr = *D2->getAttrs().begin(); D2Attr = *D2->getAttrs().begin();
if (D1Attr || D2Attr) { if ((D1Attr || D2Attr) && !D1->isImplicit() && !D2->isImplicit()) {
const auto *DiagnoseDecl = cast<TypeDecl>(PrimaryDecl ? PrimaryDecl : D2); const auto *DiagnoseDecl = cast<TypeDecl>(PrimaryDecl ? PrimaryDecl : D2);
Context.Diag2(DiagnoseDecl->getLocation(), Context.Diag2(DiagnoseDecl->getLocation(),
diag::warn_odr_tag_type_with_attributes) diag::warn_odr_tag_type_with_attributes)
@@ -873,7 +875,29 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
else if (T1->getTypeClass() == Type::FunctionNoProto && else if (T1->getTypeClass() == Type::FunctionNoProto &&
T2->getTypeClass() == Type::FunctionProto) T2->getTypeClass() == Type::FunctionProto)
TC = Type::FunctionNoProto; TC = Type::FunctionNoProto;
else else if (Context.LangOpts.C23 && !Context.StrictTypeSpelling &&
(T1->getTypeClass() == Type::Enum ||
T2->getTypeClass() == Type::Enum)) {
// In C23, if not being strict about token equivalence, we need to handle
// the case where one type is an enumeration and the other type is an
// integral type.
//
// C23 6.7.3.3p16: The enumerated type is compatible with the underlying
// type of the enumeration.
//
// Treat the enumeration as its underlying type and use the builtin type
// class comparison.
if (T1->getTypeClass() == Type::Enum) {
T1 = T1->getAs<EnumType>()->getDecl()->getIntegerType();
if (!T2->isBuiltinType() || T1.isNull()) // Sanity check
return false;
} else if (T2->getTypeClass() == Type::Enum) {
T2 = T2->getAs<EnumType>()->getDecl()->getIntegerType();
if (!T1->isBuiltinType() || T2.isNull()) // Sanity check
return false;
}
TC = Type::Builtin;
} else
return false; return false;
} }
@@ -2067,6 +2091,48 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
!CheckStructurallyEquivalentAttributes(Context, D1, D2)) !CheckStructurallyEquivalentAttributes(Context, D1, D2))
return false; return false;
// In C23, if one enumeration has a fixed underlying type, the other shall
// have a compatible fixed underlying type (6.2.7).
if (Context.LangOpts.C23) {
if (D1->isFixed() != D2->isFixed()) {
if (Context.Complain) {
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
<< Context.ToCtx.getTypeDeclType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag1(D1->getLocation(),
D1->isFixed()
? diag::note_odr_fixed_underlying_type
: diag::note_odr_missing_fixed_underlying_type)
<< D1;
Context.Diag2(D2->getLocation(),
D2->isFixed()
? diag::note_odr_fixed_underlying_type
: diag::note_odr_missing_fixed_underlying_type)
<< D2;
}
return false;
}
if (D1->isFixed()) {
assert(D2->isFixed() && "enums expected to have fixed underlying types");
if (!IsStructurallyEquivalent(Context, D1->getIntegerType(),
D2->getIntegerType())) {
if (Context.Complain) {
Context.Diag2(D2->getLocation(),
Context.getApplicableDiagnostic(
diag::err_odr_tag_type_inconsistent))
<< Context.ToCtx.getTypeDeclType(D2)
<< (&Context.FromCtx != &Context.ToCtx);
Context.Diag2(D2->getLocation(),
diag::note_odr_incompatible_fixed_underlying_type)
<< D2 << D2->getIntegerType() << D1->getIntegerType();
}
return false;
}
}
}
llvm::SmallVector<const EnumConstantDecl *, 8> D1Enums, D2Enums; llvm::SmallVector<const EnumConstantDecl *, 8> D1Enums, D2Enums;
auto CopyEnumerators = auto CopyEnumerators =
[](auto &&Range, llvm::SmallVectorImpl<const EnumConstantDecl *> &Cont) { [](auto &&Range, llvm::SmallVectorImpl<const EnumConstantDecl *> &Cont) {
+7
View File
@@ -1448,6 +1448,13 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().StructuralIfLiteral = false; data().StructuralIfLiteral = false;
} }
// If this type contains any address discriminated values we should
// have already indicated that the only special member functions that
// can possibly be trivial are the default constructor and destructor.
if (T.hasAddressDiscriminatedPointerAuth())
data().HasTrivialSpecialMembers &=
SMF_DefaultConstructor | SMF_Destructor;
// C++14 [meta.unary.prop]p4: // C++14 [meta.unary.prop]p4:
// T is a class type [...] with [...] no non-static data members other // T is a class type [...] with [...] no non-static data members other
// than subobjects of zero size // than subobjects of zero size
+21 -20
View File
@@ -4441,7 +4441,8 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
} }
} else if (!IsAccess) { } else if (!IsAccess) {
return CompleteObject(LVal.getLValueBase(), nullptr, BaseType); return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
} else if (IsConstant && Info.checkingPotentialConstantExpression() && } else if ((IsConstant || BaseType->isReferenceType()) &&
Info.checkingPotentialConstantExpression() &&
BaseType->isLiteralType(Info.Ctx) && !VD->hasDefinition()) { BaseType->isLiteralType(Info.Ctx) && !VD->hasDefinition()) {
// This variable might end up being constexpr. Don't diagnose it yet. // This variable might end up being constexpr. Don't diagnose it yet.
} else if (IsConstant) { } else if (IsConstant) {
@@ -4478,9 +4479,11 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
// a null BaseVal. Any constexpr-unknown variable seen here is an error: // a null BaseVal. Any constexpr-unknown variable seen here is an error:
// we can't access a constexpr-unknown object. // we can't access a constexpr-unknown object.
if (!BaseVal) { if (!BaseVal) {
Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1) if (!Info.checkingPotentialConstantExpression()) {
<< AK << VD; Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1)
Info.Note(VD->getLocation(), diag::note_declared_at); << AK << VD;
Info.Note(VD->getLocation(), diag::note_declared_at);
}
return CompleteObject(); return CompleteObject();
} }
} else if (DynamicAllocLValue DA = LVal.Base.dyn_cast<DynamicAllocLValue>()) { } else if (DynamicAllocLValue DA = LVal.Base.dyn_cast<DynamicAllocLValue>()) {
@@ -7906,8 +7909,9 @@ static bool checkBitCastConstexprEligibilityType(SourceLocation Loc,
// so its layout is unspecified. For now, we'll simply treat these cases // so its layout is unspecified. For now, we'll simply treat these cases
// as unsupported (this should only be possible with OpenCL bool vectors // as unsupported (this should only be possible with OpenCL bool vectors
// whose element count isn't a multiple of the byte size). // whose element count isn't a multiple of the byte size).
Info->FFDiag(Loc, diag::note_constexpr_bit_cast_invalid_vector) if (Info)
<< QualType(VTy, 0) << EltSize << NElts << Ctx.getCharWidth(); Info->FFDiag(Loc, diag::note_constexpr_bit_cast_invalid_vector)
<< QualType(VTy, 0) << EltSize << NElts << Ctx.getCharWidth();
return false; return false;
} }
@@ -7916,8 +7920,9 @@ static bool checkBitCastConstexprEligibilityType(SourceLocation Loc,
// The layout for x86_fp80 vectors seems to be handled very inconsistently // The layout for x86_fp80 vectors seems to be handled very inconsistently
// by both clang and LLVM, so for now we won't allow bit_casts involving // by both clang and LLVM, so for now we won't allow bit_casts involving
// it in a constexpr context. // it in a constexpr context.
Info->FFDiag(Loc, diag::note_constexpr_bit_cast_unsupported_type) if (Info)
<< EltTy; Info->FFDiag(Loc, diag::note_constexpr_bit_cast_unsupported_type)
<< EltTy;
return false; return false;
} }
} }
@@ -10929,10 +10934,6 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
bool ZeroInit = E->requiresZeroInitialization(); bool ZeroInit = E->requiresZeroInitialization();
if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) { if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) {
// If we've already performed zero-initialization, we're already done.
if (Result.hasValue())
return true;
if (ZeroInit) if (ZeroInit)
return ZeroInitialization(E, T); return ZeroInitialization(E, T);
@@ -14478,12 +14479,6 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK) if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK)
return false; return false;
// If we have Unknown pointers we should fail if they are not global values.
if (!(IsGlobalLValue(LHSValue.getLValueBase()) &&
IsGlobalLValue(RHSValue.getLValueBase())) &&
(LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown))
return false;
// Reject differing bases from the normal codepath; we special-case // Reject differing bases from the normal codepath; we special-case
// comparisons to null. // comparisons to null.
if (!HasSameBase(LHSValue, RHSValue)) { if (!HasSameBase(LHSValue, RHSValue)) {
@@ -14545,6 +14540,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
(LHSValue.Base && isZeroSized(RHSValue))) (LHSValue.Base && isZeroSized(RHSValue)))
return DiagComparison( return DiagComparison(
diag::note_constexpr_pointer_comparison_zero_sized); diag::note_constexpr_pointer_comparison_zero_sized);
if (LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown)
return DiagComparison(
diag::note_constexpr_pointer_comparison_unspecified);
// FIXME: Verify both variables are live.
return Success(CmpResult::Unequal, E); return Success(CmpResult::Unequal, E);
} }
@@ -14565,7 +14564,9 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) { if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) {
bool WasArrayIndex; bool WasArrayIndex;
unsigned Mismatch = FindDesignatorMismatch( unsigned Mismatch = FindDesignatorMismatch(
getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex); LHSValue.Base.isNull() ? QualType()
: getType(LHSValue.Base).getNonReferenceType(),
LHSDesignator, RHSDesignator, WasArrayIndex);
// At the point where the designators diverge, the comparison has a // At the point where the designators diverge, the comparison has a
// specified value if: // specified value if:
// - we are comparing array indices // - we are comparing array indices
@@ -14609,7 +14610,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
// compare pointers within the object in question; otherwise, the result // compare pointers within the object in question; otherwise, the result
// depends on where the object is located in memory. // depends on where the object is located in memory.
if (!LHSValue.Base.isNull() && IsRelational) { if (!LHSValue.Base.isNull() && IsRelational) {
QualType BaseTy = getType(LHSValue.Base); QualType BaseTy = getType(LHSValue.Base).getNonReferenceType();
if (BaseTy->isIncompleteType()) if (BaseTy->isIncompleteType())
return Error(E); return Error(E);
CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy); CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy);
+20
View File
@@ -2715,6 +2715,11 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const {
return false; return false;
QualType CanonicalType = getTypePtr()->CanonicalType; QualType CanonicalType = getTypePtr()->CanonicalType;
// Any type that is, or contains, address discriminated data is never POD.
if (const_cast<ASTContext&>(Context).containsAddressDiscriminatedPointerAuth(CanonicalType))
return false;
switch (CanonicalType->getTypeClass()) { switch (CanonicalType->getTypeClass()) {
// Everything not explicitly mentioned is not POD. // Everything not explicitly mentioned is not POD.
default: default:
@@ -2773,6 +2778,11 @@ bool QualType::isTrivialType(const ASTContext &Context) const {
if (CanonicalType->isDependentType()) if (CanonicalType->isDependentType())
return false; return false;
// Any type that is, or contains, address discriminated data is never a
// trivial type.
if (const_cast<ASTContext&>(Context).containsAddressDiscriminatedPointerAuth(CanonicalType))
return false;
// C++0x [basic.types]p9: // C++0x [basic.types]p9:
// Scalar types, trivial class types, arrays of such types, and // Scalar types, trivial class types, arrays of such types, and
// cv-qualified versions of these types are collectively called trivial // cv-qualified versions of these types are collectively called trivial
@@ -2870,6 +2880,12 @@ bool QualType::isBitwiseCloneableType(const ASTContext &Context) const {
if (CanonicalType->isIncompleteType()) if (CanonicalType->isIncompleteType())
return false; return false;
// Any type that is, or contains, address discriminated data is never
// bitwise clonable.
if (const_cast<ASTContext&>(Context).containsAddressDiscriminatedPointerAuth(CanonicalType))
return false;
const auto *RD = CanonicalType->getAsRecordDecl(); // struct/union/class const auto *RD = CanonicalType->getAsRecordDecl(); // struct/union/class
if (!RD) if (!RD)
return true; return true;
@@ -3115,6 +3131,10 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const {
if (BaseTy->isIncompleteType()) if (BaseTy->isIncompleteType())
return false; return false;
// Any type that is, or contains, address discriminated data is non-POD.
if (const_cast<ASTContext&>(Context).containsAddressDiscriminatedPointerAuth(*this))
return false;
// As an extension, Clang treats vector types as Scalar types. // As an extension, Clang treats vector types as Scalar types.
if (BaseTy->isScalarType() || BaseTy->isVectorType()) if (BaseTy->isScalarType() || BaseTy->isVectorType())
return true; return true;
+1 -1
View File
@@ -1331,7 +1331,7 @@ void ThreadSafetyAnalyzer::addLock(FactSet &FSet,
FSet.removeLock(FactMan, NegC); FSet.removeLock(FactMan, NegC);
} }
else { else {
if (inCurrentScope(*Entry) && !Entry->asserted()) if (inCurrentScope(*Entry) && !Entry->asserted() && !Entry->reentrant())
Handler.handleNegativeNotHeld(Entry->getKind(), Entry->toString(), Handler.handleNegativeNotHeld(Entry->getKind(), Entry->toString(),
NegC.toString(), Entry->loc()); NegC.toString(), Entry->loc());
} }
+3
View File
@@ -769,6 +769,9 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
case llvm::Triple::FreeBSD: case llvm::Triple::FreeBSD:
return std::make_unique<FreeBSDTargetInfo<LoongArch64TargetInfo>>(Triple, return std::make_unique<FreeBSDTargetInfo<LoongArch64TargetInfo>>(Triple,
Opts); Opts);
case llvm::Triple::OpenBSD:
return std::make_unique<OpenBSDTargetInfo<LoongArch64TargetInfo>>(Triple,
Opts);
default: default:
return std::make_unique<LoongArch64TargetInfo>(Triple, Opts); return std::make_unique<LoongArch64TargetInfo>(Triple, Opts);
} }
+2
View File
@@ -461,6 +461,8 @@ LoongArchTargetInfo::parseTargetAttr(StringRef Features) const {
case AttrFeatureKind::Feature: case AttrFeatureKind::Feature:
Ret.Features.push_back("+" + Value.str()); Ret.Features.push_back("+" + Value.str());
if (Value == "lasx")
Ret.Features.push_back("+lsx");
break; break;
} }
} }
+3 -3
View File
@@ -129,7 +129,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
LongWidth = LongAlign = 32; LongWidth = LongAlign = 32;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
PointerWidth = PointerAlign = 32; PointerWidth = PointerAlign = 32;
PtrDiffType = SignedInt; PtrDiffType = IntPtrType = SignedInt;
SizeType = UnsignedInt; SizeType = UnsignedInt;
SuitableAlign = 64; SuitableAlign = 64;
} }
@@ -155,7 +155,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
IntMaxType = Int64Type; IntMaxType = Int64Type;
LongWidth = LongAlign = 64; LongWidth = LongAlign = 64;
PointerWidth = PointerAlign = 64; PointerWidth = PointerAlign = 64;
PtrDiffType = SignedLong; PtrDiffType = IntPtrType = SignedLong;
SizeType = UnsignedLong; SizeType = UnsignedLong;
} }
@@ -165,7 +165,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
IntMaxType = Int64Type; IntMaxType = Int64Type;
LongWidth = LongAlign = 32; LongWidth = LongAlign = 32;
PointerWidth = PointerAlign = 32; PointerWidth = PointerAlign = 32;
PtrDiffType = SignedInt; PtrDiffType = IntPtrType = SignedInt;
SizeType = UnsignedInt; SizeType = UnsignedInt;
} }
+4
View File
@@ -174,6 +174,9 @@ class LLVM_LIBRARY_VISIBILITY DragonFlyBSDTargetInfo
DefineStd(Builder, "unix", Opts); DefineStd(Builder, "unix", Opts);
if (this->HasFloat128) if (this->HasFloat128)
Builder.defineMacro("__FLOAT128__"); Builder.defineMacro("__FLOAT128__");
if (Opts.C11)
Builder.defineMacro("__STDC_NO_THREADS__");
} }
public: public:
@@ -496,6 +499,7 @@ class LLVM_LIBRARY_VISIBILITY OpenBSDTargetInfo : public OSTargetInfo<Target> {
case llvm::Triple::sparcv9: case llvm::Triple::sparcv9:
this->MCountName = "_mcount"; this->MCountName = "_mcount";
break; break;
case llvm::Triple::loongarch64:
case llvm::Triple::riscv64: case llvm::Triple::riscv64:
break; break;
} }
+2
View File
@@ -649,6 +649,7 @@ class LLVM_LIBRARY_VISIBILITY CygwinX86_32TargetInfo : public X86_32TargetInfo {
: X86_32TargetInfo(Triple, Opts) { : X86_32TargetInfo(Triple, Opts) {
this->WCharType = TargetInfo::UnsignedShort; this->WCharType = TargetInfo::UnsignedShort;
this->WIntType = TargetInfo::UnsignedInt; this->WIntType = TargetInfo::UnsignedInt;
this->UseMicrosoftManglingForC = true;
DoubleAlign = LongLongAlign = 64; DoubleAlign = LongLongAlign = 64;
resetDataLayout("e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-" resetDataLayout("e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-"
"i128:128-f80:32-n8:16:32-a:0:32-S32", "i128:128-f80:32-n8:16:32-a:0:32-S32",
@@ -986,6 +987,7 @@ class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo {
: X86_64TargetInfo(Triple, Opts) { : X86_64TargetInfo(Triple, Opts) {
this->WCharType = TargetInfo::UnsignedShort; this->WCharType = TargetInfo::UnsignedShort;
this->WIntType = TargetInfo::UnsignedInt; this->WIntType = TargetInfo::UnsignedInt;
this->UseMicrosoftManglingForC = true;
} }
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
+5
View File
@@ -176,6 +176,11 @@ class Address {
static Address invalid() { return Address(nullptr); } static Address invalid() { return Address(nullptr); }
bool isValid() const { return Pointer.getPointer() != nullptr; } bool isValid() const { return Pointer.getPointer() != nullptr; }
llvm::Value *getPointerIfNotSigned() const {
assert(isValid() && "pointer isn't valid");
return !isSigned() ? Pointer.getPointer() : nullptr;
}
/// This function is used in situations where the caller is doing some sort of /// This function is used in situations where the caller is doing some sort of
/// opaque "laundering" of the pointer. /// opaque "laundering" of the pointer.
void replaceBasePointer(llvm::Value *P) { void replaceBasePointer(llvm::Value *P) {
+71 -28
View File
@@ -188,13 +188,14 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
// Optional copy/dispose helpers. // Optional copy/dispose helpers.
bool hasInternalHelper = false; bool hasInternalHelper = false;
if (blockInfo.NeedsCopyDispose) { if (blockInfo.NeedsCopyDispose) {
auto &Schema = CGM.getCodeGenOpts().PointerAuth.BlockHelperFunctionPointers;
// copy_func_helper_decl // copy_func_helper_decl
llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo); llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo);
elements.add(copyHelper); elements.addSignedPointer(copyHelper, Schema, GlobalDecl(), QualType());
// destroy_func_decl // destroy_func_decl
llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo); llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo);
elements.add(disposeHelper); elements.addSignedPointer(disposeHelper, Schema, GlobalDecl(), QualType());
if (cast<llvm::Function>(copyHelper->stripPointerCasts()) if (cast<llvm::Function>(copyHelper->stripPointerCasts())
->hasInternalLinkage() || ->hasInternalLinkage() ||
@@ -567,9 +568,8 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
info.CanBeGlobal = true; info.CanBeGlobal = true;
return; return;
} } else if (C.getLangOpts().ObjC &&
else if (C.getLangOpts().ObjC && CGM.getLangOpts().getGC() == LangOptions::NonGC)
CGM.getLangOpts().getGC() == LangOptions::NonGC)
info.HasCapturedVariableLayout = true; info.HasCapturedVariableLayout = true;
if (block->doesNotEscape()) if (block->doesNotEscape())
@@ -783,7 +783,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL; bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL;
auto GenVoidPtrTy = llvm::PointerType *GenVoidPtrTy =
IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy; IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy;
LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default; LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default;
auto GenVoidPtrSize = CharUnits::fromQuantity( auto GenVoidPtrSize = CharUnits::fromQuantity(
@@ -817,9 +817,6 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
: CGM.getNSConcreteStackBlock(); : CGM.getNSConcreteStackBlock();
isa = blockISA; isa = blockISA;
// Build the block descriptor.
descriptor = buildBlockDescriptor(CGM, blockInfo);
// Compute the initial on-stack block flags. // Compute the initial on-stack block flags.
if (!CGM.getCodeGenOpts().DisableBlockSignatureString) if (!CGM.getCodeGenOpts().DisableBlockSignatureString)
flags = BLOCK_HAS_SIGNATURE; flags = BLOCK_HAS_SIGNATURE;
@@ -833,6 +830,9 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
flags |= BLOCK_USE_STRET; flags |= BLOCK_USE_STRET;
if (blockInfo.NoEscape) if (blockInfo.NoEscape)
flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL; flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL;
// Build the block descriptor.
descriptor = buildBlockDescriptor(CGM, blockInfo);
} }
auto projectField = [&](unsigned index, const Twine &name) -> Address { auto projectField = [&](unsigned index, const Twine &name) -> Address {
@@ -883,11 +883,25 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()), llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()),
getIntSize(), "block.align"); getIntSize(), "block.align");
} }
addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
if (!IsOpenCL) if (!IsOpenCL) {
addHeaderField(descriptor, getPointerSize(), "block.descriptor"); llvm::Value *blockFnPtr =
else if (auto *Helper = llvm::ConstantExpr::getBitCast(InvokeFn, VoidPtrTy);
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { QualType type = blockInfo.getBlockExpr()
->getType()
->castAs<BlockPointerType>()
->getPointeeType();
addSignedHeaderField(
blockFnPtr,
CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers,
GlobalDecl(), type, getPointerSize(), "block.invoke");
addSignedHeaderField(
descriptor, CGM.getCodeGenOpts().PointerAuth.BlockDescriptorPointers,
GlobalDecl(), type, getPointerSize(), "block.descriptor");
} else if (auto *Helper =
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) { for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {
addHeaderField( addHeaderField(
I.first, I.first,
@@ -895,7 +909,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
CGM.getDataLayout().getTypeAllocSize(I.first->getType())), CGM.getDataLayout().getTypeAllocSize(I.first->getType())),
I.second); I.second);
} }
} } else
addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
} }
// Finally, capture all the values into the block. // Finally, capture all the values into the block.
@@ -1166,6 +1181,8 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
ASTContext &Ctx = getContext(); ASTContext &Ctx = getContext();
CallArgList Args; CallArgList Args;
llvm::Value *FuncPtr = nullptr;
if (getLangOpts().OpenCL) { if (getLangOpts().OpenCL) {
// For OpenCL, BlockPtr is already casted to generic block literal. // For OpenCL, BlockPtr is already casted to generic block literal.
@@ -1185,7 +1202,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
if (!isa<ParmVarDecl>(E->getCalleeDecl())) if (!isa<ParmVarDecl>(E->getCalleeDecl()))
Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee()); Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());
else { else {
llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2); FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr, Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr,
getPointerAlign()); getPointerAlign());
} }
@@ -1194,7 +1211,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
BlockPtr = BlockPtr =
Builder.CreatePointerCast(BlockPtr, UnqualPtrTy, "block.literal"); Builder.CreatePointerCast(BlockPtr, UnqualPtrTy, "block.literal");
// Get pointer to the block invoke function // Get pointer to the block invoke function
llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3); FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);
// First argument is a block literal casted to a void pointer // First argument is a block literal casted to a void pointer
BlockPtr = Builder.CreatePointerCast(BlockPtr, VoidPtrTy); BlockPtr = Builder.CreatePointerCast(BlockPtr, VoidPtrTy);
@@ -1211,7 +1228,15 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy); CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy);
// Prepare the callee. // Prepare the callee.
CGCallee Callee(CGCalleeInfo(), Func); CGPointerAuthInfo PointerAuth;
if (auto &AuthSchema =
CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers) {
assert(FuncPtr != nullptr && "Missing function pointer for AuthInfo");
PointerAuth =
EmitPointerAuthInfo(AuthSchema, FuncPtr, GlobalDecl(), FnType);
}
CGCallee Callee(CGCalleeInfo(), Func, PointerAuth);
// And call the block. // And call the block.
return EmitCall(FnInfo, Callee, ReturnValue, Args, CallOrInvoke); return EmitCall(FnInfo, Callee, ReturnValue, Args, CallOrInvoke);
@@ -1295,14 +1320,15 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
bool IsOpenCL = CGM.getLangOpts().OpenCL; bool IsOpenCL = CGM.getLangOpts().OpenCL;
bool IsWindows = CGM.getTarget().getTriple().isOSWindows(); bool IsWindows = CGM.getTarget().getTriple().isOSWindows();
auto &CGOPointerAuth = CGM.getCodeGenOpts().PointerAuth;
if (!IsOpenCL) { if (!IsOpenCL) {
// isa // isa
if (IsWindows) if (IsWindows)
fields.addNullPointer(CGM.Int8PtrPtrTy); fields.addNullPointer(CGM.Int8PtrPtrTy);
else else
fields.addSignedPointer(CGM.getNSConcreteGlobalBlock(), fields.addSignedPointer(CGM.getNSConcreteGlobalBlock(),
CGM.getCodeGenOpts().PointerAuth.ObjCIsaPointers, CGOPointerAuth.ObjCIsaPointers, GlobalDecl(),
GlobalDecl(), QualType()); QualType());
// __flags // __flags
BlockFlags flags = BLOCK_IS_GLOBAL; BlockFlags flags = BLOCK_IS_GLOBAL;
@@ -1321,11 +1347,20 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
} }
// Function // Function
fields.add(blockFn); if (auto &Schema = CGOPointerAuth.BlockInvocationFunctionPointers) {
QualType FnType = blockInfo.getBlockExpr()
->getType()
->castAs<BlockPointerType>()
->getPointeeType();
fields.addSignedPointer(blockFn, Schema, GlobalDecl(), FnType);
} else
fields.add(blockFn);
if (!IsOpenCL) { if (!IsOpenCL) {
// Descriptor // Descriptor
fields.add(buildBlockDescriptor(CGM, blockInfo)); llvm::Constant *Descriptor = buildBlockDescriptor(CGM, blockInfo);
fields.addSignedPointer(Descriptor, CGOPointerAuth.BlockDescriptorPointers,
GlobalDecl(), QualType());
} else if (auto *Helper = } else if (auto *Helper =
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
for (auto *I : Helper->getCustomFieldValues(CGM, blockInfo)) { for (auto *I : Helper->getCustomFieldValues(CGM, blockInfo)) {
@@ -1995,8 +2030,8 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
// it. It's not quite worth the annoyance to avoid creating it in the // it. It's not quite worth the annoyance to avoid creating it in the
// first place. // first place.
if (!needsEHCleanup(captureType.isDestructedType())) if (!needsEHCleanup(captureType.isDestructedType()))
if (auto *I = if (auto *I = cast_or_null<llvm::Instruction>(
cast_or_null<llvm::Instruction>(dstField.getBasePointer())) dstField.getPointerIfNotSigned()))
I->eraseFromParent(); I->eraseFromParent();
} }
break; break;
@@ -2730,8 +2765,16 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
unsigned nextHeaderIndex = 0; unsigned nextHeaderIndex = 0;
CharUnits nextHeaderOffset; CharUnits nextHeaderOffset;
auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize, auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize,
const Twine &name) { const Twine &name, bool isFunction = false) {
auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, name); auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, name);
if (isFunction) {
if (auto &Schema = CGM.getCodeGenOpts()
.PointerAuth.BlockByrefHelperFunctionPointers) {
auto PointerAuth = EmitPointerAuthInfo(
Schema, fieldAddr.emitRawPointer(*this), GlobalDecl(), QualType());
value = EmitPointerAuthSign(PointerAuth, value);
}
}
Builder.CreateStore(value, fieldAddr); Builder.CreateStore(value, fieldAddr);
nextHeaderIndex++; nextHeaderIndex++;
@@ -2814,10 +2857,10 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
storeHeaderField(V, getIntSize(), "byref.size"); storeHeaderField(V, getIntSize(), "byref.size");
if (helpers) { if (helpers) {
storeHeaderField(helpers->CopyHelper, getPointerSize(), storeHeaderField(helpers->CopyHelper, getPointerSize(), "byref.copyHelper",
"byref.copyHelper"); /*isFunction=*/true);
storeHeaderField(helpers->DisposeHelper, getPointerSize(), storeHeaderField(helpers->DisposeHelper, getPointerSize(),
"byref.disposeHelper"); "byref.disposeHelper", /*isFunction=*/true);
} }
if (ByRefHasLifetime && HasByrefExtendedLayout) { if (ByRefHasLifetime && HasByrefExtendedLayout) {
+12 -14
View File
@@ -4787,19 +4787,6 @@ struct DestroyUnpassedArg final : EHScopeStack::Cleanup {
} }
}; };
struct DisableDebugLocationUpdates {
CodeGenFunction &CGF;
bool disabledDebugInfo;
DisableDebugLocationUpdates(CodeGenFunction &CGF, const Expr *E) : CGF(CGF) {
if ((disabledDebugInfo = isa<CXXDefaultArgExpr>(E) && CGF.getDebugInfo()))
CGF.disableDebugInfo();
}
~DisableDebugLocationUpdates() {
if (disabledDebugInfo)
CGF.enableDebugInfo();
}
};
} // end anonymous namespace } // end anonymous namespace
RValue CallArg::getRValue(CodeGenFunction &CGF) const { RValue CallArg::getRValue(CodeGenFunction &CGF) const {
@@ -4836,7 +4823,9 @@ void CodeGenFunction::EmitWritebacks(const CallArgList &args) {
void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
QualType type) { QualType type) {
DisableDebugLocationUpdates Dis(*this, E); std::optional<DisableDebugLocationUpdates> Dis;
if (isa<CXXDefaultArgExpr>(E))
Dis.emplace(*this);
if (const ObjCIndirectCopyRestoreExpr *CRE = if (const ObjCIndirectCopyRestoreExpr *CRE =
dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) { dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) {
assert(getLangOpts().ObjCAutoRefCount); assert(getLangOpts().ObjCAutoRefCount);
@@ -6229,3 +6218,12 @@ RValue CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr,
return CGM.getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty, Slot); return CGM.getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty, Slot);
return CGM.getABIInfo().EmitVAArg(*this, VAListAddr, Ty, Slot); return CGM.getABIInfo().EmitVAArg(*this, VAListAddr, Ty, Slot);
} }
DisableDebugLocationUpdates::DisableDebugLocationUpdates(CodeGenFunction &CGF)
: CGF(CGF) {
CGF.disableDebugInfo();
}
DisableDebugLocationUpdates::~DisableDebugLocationUpdates() {
CGF.enableDebugInfo();
}
+6
View File
@@ -457,6 +457,12 @@ inline FnInfoOpts &operator&=(FnInfoOpts &A, FnInfoOpts B) {
return A; return A;
} }
struct DisableDebugLocationUpdates {
CodeGenFunction &CGF;
DisableDebugLocationUpdates(CodeGenFunction &CGF);
~DisableDebugLocationUpdates();
};
} // end namespace CodeGen } // end namespace CodeGen
} // end namespace clang } // end namespace clang
+9 -5
View File
@@ -707,11 +707,15 @@ struct GetReturnObjectManager {
Builder.CreateStore(Builder.getFalse(), GroActiveFlag); Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl); GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl);
auto *GroAlloca = dyn_cast_or_null<llvm::AllocaInst>(
GroEmission.getOriginalAllocatedAddress().getPointer()); if (!GroVarDecl->isNRVOVariable()) {
assert(GroAlloca && "expected alloca to be emitted"); // NRVO variables don't have allocas and won't have the same issue.
GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame, auto *GroAlloca = dyn_cast_or_null<llvm::AllocaInst>(
llvm::MDNode::get(CGF.CGM.getLLVMContext(), {})); GroEmission.getOriginalAllocatedAddress().getPointer());
assert(GroAlloca && "expected alloca to be emitted");
GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
llvm::MDNode::get(CGF.CGM.getLLVMContext(), {}));
}
// Remember the top of EHStack before emitting the cleanup. // Remember the top of EHStack before emitting the cleanup.
auto old_top = CGF.EHStack.stable_begin(); auto old_top = CGF.EHStack.stable_begin();
+6 -1
View File
@@ -170,6 +170,10 @@ void CGDebugInfo::addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction,
if (!Group || !CGM.getCodeGenOpts().DebugKeyInstructions) if (!Group || !CGM.getCodeGenOpts().DebugKeyInstructions)
return; return;
llvm::DISubprogram *SP = KeyInstruction->getFunction()->getSubprogram();
if (!SP || !SP->getKeyInstructionsEnabled())
return;
addInstSourceAtomMetadata(KeyInstruction, Group, /*Rank=*/1); addInstSourceAtomMetadata(KeyInstruction, Group, /*Rank=*/1);
llvm::Instruction *BackupI = llvm::Instruction *BackupI =
@@ -2641,7 +2645,8 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
// existing information in the DWARF. The type is assumed to be 'void *'. // existing information in the DWARF. The type is assumed to be 'void *'.
void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable, void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable,
const CXXRecordDecl *RD) { const CXXRecordDecl *RD) {
if (!CGM.getTarget().getCXXABI().isItaniumFamily()) if (!CGM.getTarget().getCXXABI().isItaniumFamily() ||
CGM.getTarget().getTriple().isOSBinFormatCOFF())
return; return;
ASTContext &Context = CGM.getContext(); ASTContext &Context = CGM.getContext();
+8 -1
View File
@@ -3314,7 +3314,14 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
auto *FD = LambdaCaptureFields.lookup(BD); auto *FD = LambdaCaptureFields.lookup(BD);
return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue); return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue);
} }
return EmitLValue(BD->getBinding()); // Suppress debug location updates when visiting the binding, since the
// binding may emit instructions that would otherwise be associated with the
// binding itself, rather than the expression referencing the binding. (this
// leads to jumpy debug stepping behavior where the location/debugger jump
// back to the binding declaration, then back to the expression referencing
// the binding)
DisableDebugLocationUpdates D(*this);
return EmitLValue(BD->getBinding(), NotKnownNonNull);
} }
// We can form DeclRefExprs naming GUID declarations when reconstituting // We can form DeclRefExprs naming GUID declarations when reconstituting
+2 -1
View File
@@ -2313,7 +2313,8 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr,
bool IsExact = !IsDynamicCastToVoid && bool IsExact = !IsDynamicCastToVoid &&
CGM.getCodeGenOpts().OptimizationLevel > 0 && CGM.getCodeGenOpts().OptimizationLevel > 0 &&
DestRecordTy->getAsCXXRecordDecl()->isEffectivelyFinal() && DestRecordTy->getAsCXXRecordDecl()->isEffectivelyFinal() &&
CGM.getCXXABI().shouldEmitExactDynamicCast(DestRecordTy); CGM.getCXXABI().shouldEmitExactDynamicCast(DestRecordTy) &&
!getLangOpts().PointerAuthCalls;
// C++ [expr.dynamic.cast]p4: // C++ [expr.dynamic.cast]p4:
// If the value of v is a null pointer value in the pointer case, the result // If the value of v is a null pointer value in the pointer case, the result
+4 -3
View File
@@ -873,8 +873,9 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
for (const BaseInfo &Base : Bases) { for (const BaseInfo &Base : Bases) {
bool IsPrimaryBase = Layout.getPrimaryBase() == Base.Decl; bool IsPrimaryBase = Layout.getPrimaryBase() == Base.Decl;
Build(Val.getStructBase(Base.Index), Base.Decl, IsPrimaryBase, if (!Build(Val.getStructBase(Base.Index), Base.Decl, IsPrimaryBase,
VTableClass, Offset + Base.Offset); VTableClass, Offset + Base.Offset))
return false;
} }
} }
@@ -1620,7 +1621,7 @@ llvm::Constant *ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *CE) {
if (CE->isGLValue()) if (CE->isGLValue())
RetType = CGM.getContext().getLValueReferenceType(RetType); RetType = CGM.getContext().getLValueReferenceType(RetType);
return emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType); return tryEmitAbstract(CE->getAPValueResult(), RetType);
} }
llvm::Constant * llvm::Constant *
+10 -1
View File
@@ -846,11 +846,13 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
if (HaveInsertPoint()) if (HaveInsertPoint())
EmitStopPoint(&S); EmitStopPoint(&S);
ApplyAtomGroup Grp(getDebugInfo());
EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel())); EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel()));
} }
void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
ApplyAtomGroup Grp(getDebugInfo());
if (const LabelDecl *Target = S.getConstantTarget()) { if (const LabelDecl *Target = S.getConstantTarget()) {
EmitBranchThroughCleanup(getJumpDestForLabel(Target)); EmitBranchThroughCleanup(getJumpDestForLabel(Target));
return; return;
@@ -869,6 +871,8 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB); cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB);
EmitBranch(IndGotoBB); EmitBranch(IndGotoBB);
if (CurBB && CurBB->getTerminator())
addInstToCurrentSourceAtom(CurBB->getTerminator(), nullptr);
} }
void CodeGenFunction::EmitIfStmt(const IfStmt &S) { void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
@@ -2672,6 +2676,9 @@ static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect,
llvm::ConstantAsMetadata::get(Loc))); llvm::ConstantAsMetadata::get(Loc)));
} }
// Make inline-asm calls Key for the debug info feature Key Instructions.
CGF.addInstToNewSourceAtom(&Result, nullptr);
if (!NoConvergent && CGF.getLangOpts().assumeFunctionsAreConvergent()) if (!NoConvergent && CGF.getLangOpts().assumeFunctionsAreConvergent())
// Conservatively, mark all inline asm blocks in CUDA or OpenCL as // Conservatively, mark all inline asm blocks in CUDA or OpenCL as
// convergent (meaning, they may call an intrinsically convergent op, such // convergent (meaning, they may call an intrinsically convergent op, such
@@ -2750,6 +2757,7 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
} }
} }
ApplyAtomGroup Grp(CGF.getDebugInfo());
LValue Dest = ResultRegDests[i]; LValue Dest = ResultRegDests[i];
// ResultTypeRequiresCast elements correspond to the first // ResultTypeRequiresCast elements correspond to the first
// ResultTypeRequiresCast.size() elements of RegResults. // ResultTypeRequiresCast.size() elements of RegResults.
@@ -2757,7 +2765,8 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
unsigned Size = CGF.getContext().getTypeSize(ResultRegQualTys[i]); unsigned Size = CGF.getContext().getTypeSize(ResultRegQualTys[i]);
Address A = Dest.getAddress().withElementType(ResultRegTypes[i]); Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
if (CGF.getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) { if (CGF.getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) {
Builder.CreateStore(Tmp, A); llvm::StoreInst *S = Builder.CreateStore(Tmp, A);
CGF.addInstToCurrentSourceAtom(S, S->getValueOperand());
continue; continue;
} }
+3 -2
View File
@@ -727,7 +727,7 @@ class CodeGenFunction : public CodeGenTypeCache {
}; };
/// Header for data within LifetimeExtendedCleanupStack. /// Header for data within LifetimeExtendedCleanupStack.
struct LifetimeExtendedCleanupHeader { struct alignas(uint64_t) LifetimeExtendedCleanupHeader {
/// The size of the following cleanup object. /// The size of the following cleanup object.
unsigned Size; unsigned Size;
/// The kind of cleanup to push. /// The kind of cleanup to push.
@@ -949,7 +949,8 @@ class CodeGenFunction : public CodeGenTypeCache {
LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size + LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size +
(Header.IsConditional ? sizeof(ActiveFlag) : 0)); (Header.IsConditional ? sizeof(ActiveFlag) : 0));
static_assert(sizeof(Header) % alignof(T) == 0, static_assert((alignof(LifetimeExtendedCleanupHeader) == alignof(T)) &&
(alignof(T) == alignof(RawAddress)),
"Cleanup will be allocated on misaligned address"); "Cleanup will be allocated on misaligned address");
char *Buffer = &LifetimeExtendedCleanupStack[OldSize]; char *Buffer = &LifetimeExtendedCleanupStack[OldSize];
new (Buffer) LifetimeExtendedCleanupHeader(Header); new (Buffer) LifetimeExtendedCleanupHeader(Header);
+1 -1
View File
@@ -143,7 +143,7 @@ class EHScopeStack {
/// ///
/// Cleanup implementations should generally be declared in an /// Cleanup implementations should generally be declared in an
/// anonymous namespace. /// anonymous namespace.
class Cleanup { class alignas(uint64_t) Cleanup {
// Anchor the construction vtable. // Anchor the construction vtable.
virtual void anchor(); virtual void anchor();
+945 -4
View File
@@ -20,6 +20,951 @@ using namespace clang;
using namespace CodeGen; using namespace CodeGen;
using namespace llvm; using namespace llvm;
// The 0th bit simulates the `vta` of RVV
// The 1st bit simulates the `vma` of RVV
static constexpr unsigned RVV_VTA = 0x1;
static constexpr unsigned RVV_VMA = 0x2;
// RISC-V Vector builtin helper functions are marked NOINLINE to prevent
// excessive inlining in CodeGenFunction::EmitRISCVBuiltinExpr's large switch
// statement, which would significantly increase compilation time.
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVVLEFFBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
if (IsMasked) {
// Move mask to right before vl.
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
IntrinsicTypes = {ResultType, Ops[4]->getType(), Ops[2]->getType()};
} else {
if (PolicyAttrs & RVV_VTA)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
IntrinsicTypes = {ResultType, Ops[3]->getType(), Ops[1]->getType()};
}
Value *NewVL = Ops[2];
Ops.erase(Ops.begin() + 2);
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
llvm::Value *V = Builder.CreateExtractValue(LoadValue, {0});
// Store new_vl.
clang::CharUnits Align;
if (IsMasked)
Align = CGM.getNaturalPointeeTypeAlignment(
E->getArg(E->getNumArgs() - 2)->getType());
else
Align = CGM.getNaturalPointeeTypeAlignment(E->getArg(1)->getType());
llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {1});
Builder.CreateStore(Val, Address(NewVL, Val->getType(), Align));
return V;
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVVSSEBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
if (IsMasked) {
// Builtin: (mask, ptr, stride, value, vl). Intrinsic: (value, ptr, stride,
// mask, vl)
std::swap(Ops[0], Ops[3]);
} else {
// Builtin: (ptr, stride, value, vl). Intrinsic: (value, ptr, stride, vl)
std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
}
if (IsMasked)
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[4]->getType()};
else
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()};
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVIndexedStoreBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
if (IsMasked) {
// Builtin: (mask, ptr, index, value, vl).
// Intrinsic: (value, ptr, index, mask, vl)
std::swap(Ops[0], Ops[3]);
} else {
// Builtin: (ptr, index, value, vl).
// Intrinsic: (value, ptr, index, vl)
std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
}
if (IsMasked)
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(),
Ops[4]->getType()};
else
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(),
Ops[3]->getType()};
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVPseudoUnaryBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
if (IsMasked) {
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
} else {
if (PolicyAttrs & RVV_VTA)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
}
auto ElemTy = cast<llvm::VectorType>(ResultType)->getElementType();
Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy));
if (IsMasked) {
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
// maskedoff, op1, op2, mask, vl, policy
IntrinsicTypes = {ResultType, ElemTy, Ops[4]->getType()};
} else {
// passthru, op1, op2, vl
IntrinsicTypes = {ResultType, ElemTy, Ops[3]->getType()};
}
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVPseudoVNotBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
if (IsMasked) {
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
} else {
if (PolicyAttrs & RVV_VTA)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
}
auto ElemTy = cast<llvm::VectorType>(ResultType)->getElementType();
Ops.insert(Ops.begin() + 2, llvm::Constant::getAllOnesValue(ElemTy));
if (IsMasked) {
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
// maskedoff, op1, po2, mask, vl, policy
IntrinsicTypes = {ResultType, ElemTy, Ops[4]->getType()};
} else {
// passthru, op1, op2, vl
IntrinsicTypes = {ResultType, ElemTy, Ops[3]->getType()};
}
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVPseudoMaskBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
// op1, vl
IntrinsicTypes = {ResultType, Ops[1]->getType()};
Ops.insert(Ops.begin() + 1, Ops[0]);
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVPseudoVFUnaryBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
if (IsMasked) {
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
Ops.insert(Ops.begin() + 2, Ops[1]);
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
// maskedoff, op1, op2, mask, vl
IntrinsicTypes = {ResultType, Ops[2]->getType(), Ops.back()->getType()};
} else {
if (PolicyAttrs & RVV_VTA)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
// op1, po2, vl
IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType()};
Ops.insert(Ops.begin() + 2, Ops[1]);
}
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVPseudoVWCVTBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
if (IsMasked) {
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
} else {
if (PolicyAttrs & RVV_VTA)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
}
auto ElemTy = cast<llvm::VectorType>(Ops[1]->getType())->getElementType();
Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy));
if (IsMasked) {
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
// maskedoff, op1, op2, mask, vl, policy
IntrinsicTypes = {ResultType, Ops[1]->getType(), ElemTy, Ops[4]->getType()};
} else {
// passtru, op1, op2, vl
IntrinsicTypes = {ResultType, Ops[1]->getType(), ElemTy, Ops[3]->getType()};
}
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVPseudoVNCVTBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
if (IsMasked) {
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
} else {
if (PolicyAttrs & RVV_VTA)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
}
Ops.insert(Ops.begin() + 2,
llvm::Constant::getNullValue(Ops.back()->getType()));
if (IsMasked) {
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
// maskedoff, op1, xlen, mask, vl
IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[4]->getType(),
Ops[4]->getType()};
} else {
// passthru, op1, xlen, vl
IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType(),
Ops[3]->getType()};
}
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVVlenbBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
LLVMContext &Context = CGM.getLLVMContext();
llvm::MDBuilder MDHelper(Context);
llvm::Metadata *OpsMD[] = {llvm::MDString::get(Context, "vlenb")};
llvm::MDNode *RegName = llvm::MDNode::get(Context, OpsMD);
llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
llvm::Function *F =
CGM.getIntrinsic(llvm::Intrinsic::read_register, {CGF->SizeTy});
return Builder.CreateCall(F, Metadata);
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVVsetvliBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::Function *F = CGM.getIntrinsic(ID, {ResultType});
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVVSEMaskBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
if (IsMasked) {
// Builtin: (mask, ptr, value, vl).
// Intrinsic: (value, ptr, mask, vl)
std::swap(Ops[0], Ops[2]);
} else {
// Builtin: (ptr, value, vl).
// Intrinsic: (value, ptr, vl)
std::swap(Ops[0], Ops[1]);
}
if (IsMasked)
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()};
else
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType()};
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVUnitStridedSegLoadTupleBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
bool NoPassthru =
(IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
(!IsMasked && (PolicyAttrs & RVV_VTA));
unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1;
if (IsMasked)
IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[0]->getType(),
Ops.back()->getType()};
else
IntrinsicTypes = {ResultType, Ops[Offset]->getType(),
Ops.back()->getType()};
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
if (NoPassthru)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
if (IsMasked)
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
if (ReturnValue.isNull())
return LoadValue;
return Builder.CreateStore(LoadValue, ReturnValue.getValue());
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVUnitStridedSegStoreTupleBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
// Masked
// Builtin: (mask, ptr, v_tuple, vl)
// Intrinsic: (tuple, ptr, mask, vl, SegInstSEW)
// Unmasked
// Builtin: (ptr, v_tuple, vl)
// Intrinsic: (tuple, ptr, vl, SegInstSEW)
if (IsMasked)
std::swap(Ops[0], Ops[2]);
else
std::swap(Ops[0], Ops[1]);
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
if (IsMasked)
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(),
Ops[3]->getType()};
else
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType()};
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVUnitStridedSegLoadFFTupleBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
bool NoPassthru =
(IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
(!IsMasked && (PolicyAttrs & RVV_VTA));
unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1;
if (IsMasked)
IntrinsicTypes = {ResultType, Ops.back()->getType(), Ops[Offset]->getType(),
Ops[0]->getType()};
else
IntrinsicTypes = {ResultType, Ops.back()->getType(),
Ops[Offset]->getType()};
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
if (NoPassthru)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
if (IsMasked)
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
Value *NewVL = Ops[2];
Ops.erase(Ops.begin() + 2);
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
// Get alignment from the new vl operand
clang::CharUnits Align =
CGM.getNaturalPointeeTypeAlignment(E->getArg(Offset + 1)->getType());
llvm::Value *ReturnTuple = Builder.CreateExtractValue(LoadValue, 0);
// Store new_vl
llvm::Value *V = Builder.CreateExtractValue(LoadValue, 1);
Builder.CreateStore(V, Address(NewVL, V->getType(), Align));
if (ReturnValue.isNull())
return ReturnTuple;
return Builder.CreateStore(ReturnTuple, ReturnValue.getValue());
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVStridedSegLoadTupleBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
bool NoPassthru =
(IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
(!IsMasked && (PolicyAttrs & RVV_VTA));
unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1;
if (IsMasked)
IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops.back()->getType(),
Ops[0]->getType()};
else
IntrinsicTypes = {ResultType, Ops[Offset]->getType(),
Ops.back()->getType()};
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
if (NoPassthru)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
if (IsMasked)
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
if (ReturnValue.isNull())
return LoadValue;
return Builder.CreateStore(LoadValue, ReturnValue.getValue());
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVStridedSegStoreTupleBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
// Masked
// Builtin: (mask, ptr, stride, v_tuple, vl)
// Intrinsic: (tuple, ptr, stride, mask, vl, SegInstSEW)
// Unmasked
// Builtin: (ptr, stride, v_tuple, vl)
// Intrinsic: (tuple, ptr, stride, vl, SegInstSEW)
if (IsMasked)
std::swap(Ops[0], Ops[3]);
else
std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
if (IsMasked)
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[4]->getType(),
Ops[3]->getType()};
else
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()};
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVAveragingBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
// LLVM intrinsic
// Unmasked: (passthru, op0, op1, round_mode, vl)
// Masked: (passthru, vector_in, vector_in/scalar_in, mask, vxrm, vl,
// policy)
bool HasMaskedOff =
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
(!IsMasked && PolicyAttrs & RVV_VTA));
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
if (!HasMaskedOff)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
if (IsMasked)
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
llvm::Function *F = CGM.getIntrinsic(
ID, {ResultType, Ops[2]->getType(), Ops.back()->getType()});
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVNarrowingClipBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
// LLVM intrinsic
// Unmasked: (passthru, op0, op1, round_mode, vl)
// Masked: (passthru, vector_in, vector_in/scalar_in, mask, vxrm, vl,
// policy)
bool HasMaskedOff =
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
(!IsMasked && PolicyAttrs & RVV_VTA));
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
if (!HasMaskedOff)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
if (IsMasked)
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
llvm::Function *F =
CGM.getIntrinsic(ID, {ResultType, Ops[1]->getType(), Ops[2]->getType(),
Ops.back()->getType()});
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVFloatingPointBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
// LLVM intrinsic
// Unmasked: (passthru, op0, op1, round_mode, vl)
// Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy)
bool HasMaskedOff =
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
(!IsMasked && PolicyAttrs & RVV_VTA));
bool HasRoundModeOp =
IsMasked ? (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5)
: (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4);
if (!HasRoundModeOp)
Ops.insert(Ops.end() - 1,
ConstantInt::get(Ops.back()->getType(), 7)); // frm
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
if (!HasMaskedOff)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
if (IsMasked)
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
llvm::Function *F = CGM.getIntrinsic(
ID, {ResultType, Ops[2]->getType(), Ops.back()->getType()});
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVWideningFloatingPointBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
// LLVM intrinsic
// Unmasked: (passthru, op0, op1, round_mode, vl)
// Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy)
bool HasMaskedOff =
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
(!IsMasked && PolicyAttrs & RVV_VTA));
bool HasRoundModeOp =
IsMasked ? (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5)
: (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4);
if (!HasRoundModeOp)
Ops.insert(Ops.end() - 1,
ConstantInt::get(Ops.back()->getType(), 7)); // frm
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
if (!HasMaskedOff)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
if (IsMasked)
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
llvm::Function *F =
CGM.getIntrinsic(ID, {ResultType, Ops[1]->getType(), Ops[2]->getType(),
Ops.back()->getType()});
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVIndexedSegLoadTupleBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 5> IntrinsicTypes;
bool NoPassthru =
(IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
(!IsMasked && (PolicyAttrs & RVV_VTA));
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
if (NoPassthru)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
if (IsMasked)
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
if (IsMasked)
IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType(),
Ops[3]->getType(), Ops[4]->getType()};
else
IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType(),
Ops[3]->getType()};
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
if (ReturnValue.isNull())
return LoadValue;
return Builder.CreateStore(LoadValue, ReturnValue.getValue());
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVIndexedSegStoreTupleBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 5> IntrinsicTypes;
// Masked
// Builtin: (mask, ptr, index, v_tuple, vl)
// Intrinsic: (tuple, ptr, index, mask, vl, SegInstSEW)
// Unmasked
// Builtin: (ptr, index, v_tuple, vl)
// Intrinsic: (tuple, ptr, index, vl, SegInstSEW)
if (IsMasked)
std::swap(Ops[0], Ops[3]);
else
std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
if (IsMasked)
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(),
Ops[3]->getType(), Ops[4]->getType()};
else
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(),
Ops[3]->getType()};
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVFMABuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
// LLVM intrinsic
// Unmasked: (vector_in, vector_in/scalar_in, vector_in, round_mode,
// vl, policy)
// Masked: (vector_in, vector_in/scalar_in, vector_in, mask, frm,
// vl, policy)
bool HasRoundModeOp = IsMasked ? Ops.size() == 6 : Ops.size() == 5;
if (!HasRoundModeOp)
Ops.insert(Ops.end() - 1,
ConstantInt::get(Ops.back()->getType(), 7)); // frm
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
llvm::Function *F = CGM.getIntrinsic(
ID, {ResultType, Ops[1]->getType(), Ops.back()->getType()});
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVWideningFMABuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
// LLVM intrinsic
// Unmasked: (vector_in, vector_in/scalar_in, vector_in, round_mode, vl,
// policy) Masked: (vector_in, vector_in/scalar_in, vector_in, mask, frm,
// vl, policy)
bool HasRoundModeOp = IsMasked ? Ops.size() == 6 : Ops.size() == 5;
if (!HasRoundModeOp)
Ops.insert(Ops.end() - 1,
ConstantInt::get(Ops.back()->getType(), 7)); // frm
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 4);
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
llvm::Function *F =
CGM.getIntrinsic(ID, {ResultType, Ops[1]->getType(), Ops[2]->getType(),
Ops.back()->getType()});
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVFloatingUnaryBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
// LLVM intrinsic
// Unmasked: (passthru, op0, round_mode, vl)
// Masked: (passthru, op0, mask, frm, vl, policy)
bool HasMaskedOff =
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
(!IsMasked && PolicyAttrs & RVV_VTA));
bool HasRoundModeOp =
IsMasked ? (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4)
: (HasMaskedOff ? Ops.size() == 4 : Ops.size() == 3);
if (!HasRoundModeOp)
Ops.insert(Ops.end() - 1,
ConstantInt::get(Ops.back()->getType(), 7)); // frm
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
if (!HasMaskedOff)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
if (IsMasked)
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
IntrinsicTypes = {ResultType, Ops.back()->getType()};
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVFloatingConvBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
// LLVM intrinsic
// Unmasked: (passthru, op0, frm, vl)
// Masked: (passthru, op0, mask, frm, vl, policy)
bool HasMaskedOff =
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
(!IsMasked && PolicyAttrs & RVV_VTA));
bool HasRoundModeOp =
IsMasked ? (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4)
: (HasMaskedOff ? Ops.size() == 4 : Ops.size() == 3);
if (!HasRoundModeOp)
Ops.insert(Ops.end() - 1,
ConstantInt::get(Ops.back()->getType(), 7)); // frm
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
if (!HasMaskedOff)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
if (IsMasked)
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
llvm::Function *F = CGM.getIntrinsic(
ID, {ResultType, Ops[1]->getType(), Ops.back()->getType()});
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVFloatingReductionBuiltin(
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
// LLVM intrinsic
// Unmasked: (passthru, op0, op1, round_mode, vl)
// Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy)
bool HasMaskedOff =
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
(!IsMasked && PolicyAttrs & RVV_VTA));
bool HasRoundModeOp =
IsMasked ? (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5)
: (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4);
if (!HasRoundModeOp)
Ops.insert(Ops.end() - 1,
ConstantInt::get(Ops.back()->getType(), 7)); // frm
if (IsMasked)
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
if (!HasMaskedOff)
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
llvm::Function *F = CGM.getIntrinsic(
ID, {ResultType, Ops[1]->getType(), Ops.back()->getType()});
return Builder.CreateCall(F, Ops, "");
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVReinterpretBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto &CGM = CGF->CGM;
if (ResultType->isIntOrIntVectorTy(1) ||
Ops[0]->getType()->isIntOrIntVectorTy(1)) {
assert(isa<ScalableVectorType>(ResultType) &&
isa<ScalableVectorType>(Ops[0]->getType()));
LLVMContext &Context = CGM.getLLVMContext();
ScalableVectorType *Boolean64Ty =
ScalableVectorType::get(llvm::Type::getInt1Ty(Context), 64);
if (ResultType->isIntOrIntVectorTy(1)) {
// Casting from m1 vector integer -> vector boolean
// Ex: <vscale x 8 x i8>
// --(bitcast)--------> <vscale x 64 x i1>
// --(vector_extract)-> <vscale x 8 x i1>
llvm::Value *BitCast = Builder.CreateBitCast(Ops[0], Boolean64Ty);
return Builder.CreateExtractVector(ResultType, BitCast,
ConstantInt::get(CGF->Int64Ty, 0));
} else {
// Casting from vector boolean -> m1 vector integer
// Ex: <vscale x 1 x i1>
// --(vector_insert)-> <vscale x 64 x i1>
// --(bitcast)-------> <vscale x 8 x i8>
llvm::Value *Boolean64Val = Builder.CreateInsertVector(
Boolean64Ty, llvm::PoisonValue::get(Boolean64Ty), Ops[0],
ConstantInt::get(CGF->Int64Ty, 0));
return Builder.CreateBitCast(Boolean64Val, ResultType);
}
}
return Builder.CreateBitCast(Ops[0], ResultType);
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVGetBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
auto *VecTy = cast<ScalableVectorType>(ResultType);
if (auto *OpVecTy = dyn_cast<ScalableVectorType>(Ops[0]->getType())) {
unsigned MaxIndex =
OpVecTy->getMinNumElements() / VecTy->getMinNumElements();
assert(isPowerOf2_32(MaxIndex));
// Mask to only valid indices.
Ops[1] = Builder.CreateZExt(Ops[1], Builder.getInt64Ty());
Ops[1] = Builder.CreateAnd(Ops[1], MaxIndex - 1);
Ops[1] =
Builder.CreateMul(Ops[1], ConstantInt::get(Ops[1]->getType(),
VecTy->getMinNumElements()));
return Builder.CreateExtractVector(ResultType, Ops[0], Ops[1]);
}
return Builder.CreateIntrinsic(
Intrinsic::riscv_tuple_extract, {ResultType, Ops[0]->getType()},
{Ops[0], Builder.CreateTrunc(Ops[1], Builder.getInt32Ty())});
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVSetBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
if (auto *ResVecTy = dyn_cast<ScalableVectorType>(ResultType)) {
auto *VecTy = cast<ScalableVectorType>(Ops[2]->getType());
unsigned MaxIndex =
ResVecTy->getMinNumElements() / VecTy->getMinNumElements();
assert(isPowerOf2_32(MaxIndex));
// Mask to only valid indices.
Ops[1] = Builder.CreateZExt(Ops[1], Builder.getInt64Ty());
Ops[1] = Builder.CreateAnd(Ops[1], MaxIndex - 1);
Ops[1] =
Builder.CreateMul(Ops[1], ConstantInt::get(Ops[1]->getType(),
VecTy->getMinNumElements()));
return Builder.CreateInsertVector(ResultType, Ops[0], Ops[2], Ops[1]);
}
return Builder.CreateIntrinsic(
Intrinsic::riscv_tuple_insert, {ResultType, Ops[2]->getType()},
{Ops[0], Ops[2], Builder.CreateTrunc(Ops[1], Builder.getInt32Ty())});
}
static LLVM_ATTRIBUTE_NOINLINE Value *
emitRVVCreateBuiltin(CodeGenFunction *CGF, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
auto &Builder = CGF->Builder;
llvm::Value *ReturnVector = llvm::PoisonValue::get(ResultType);
auto *VecTy = cast<ScalableVectorType>(Ops[0]->getType());
for (unsigned I = 0, N = Ops.size(); I < N; ++I) {
if (isa<ScalableVectorType>(ResultType)) {
llvm::Value *Idx = ConstantInt::get(Builder.getInt64Ty(),
VecTy->getMinNumElements() * I);
ReturnVector =
Builder.CreateInsertVector(ResultType, ReturnVector, Ops[I], Idx);
} else {
llvm::Value *Idx = ConstantInt::get(Builder.getInt32Ty(), I);
ReturnVector = Builder.CreateIntrinsic(Intrinsic::riscv_tuple_insert,
{ResultType, Ops[I]->getType()},
{ReturnVector, Ops[I], Idx});
}
}
return ReturnVector;
}
Value *CodeGenFunction::EmitRISCVCpuInit() { Value *CodeGenFunction::EmitRISCVCpuInit() {
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, {VoidPtrTy}, false); llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, {VoidPtrTy}, false);
llvm::FunctionCallee Func = llvm::FunctionCallee Func =
@@ -180,10 +1125,6 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
} }
Intrinsic::ID ID = Intrinsic::not_intrinsic; Intrinsic::ID ID = Intrinsic::not_intrinsic;
// The 0th bit simulates the `vta` of RVV
// The 1st bit simulates the `vma` of RVV
constexpr unsigned RVV_VTA = 0x1;
constexpr unsigned RVV_VMA = 0x2;
int PolicyAttrs = 0; int PolicyAttrs = 0;
bool IsMasked = false; bool IsMasked = false;
// This is used by segment load/store to determine it's llvm type. // This is used by segment load/store to determine it's llvm type.
+2
View File
@@ -75,6 +75,8 @@ TargetCodeGenInfo::~TargetCodeGenInfo() = default;
// If someone can figure out a general rule for this, that would be great. // If someone can figure out a general rule for this, that would be great.
// It's probably just doomed to be platform-dependent, though. // It's probably just doomed to be platform-dependent, though.
unsigned TargetCodeGenInfo::getSizeOfUnwindException() const { unsigned TargetCodeGenInfo::getSizeOfUnwindException() const {
if (getABIInfo().getContext().getLangOpts().hasSEHExceptions())
return getABIInfo().getDataLayout().getPointerSizeInBits() > 32 ? 64 : 48;
// Verified for: // Verified for:
// x86-64 FreeBSD, Linux, Darwin // x86-64 FreeBSD, Linux, Darwin
// x86-32 FreeBSD, Linux, Darwin // x86-32 FreeBSD, Linux, Darwin
+57 -68
View File
@@ -8,6 +8,7 @@
#include "ABIInfoImpl.h" #include "ABIInfoImpl.h"
#include "TargetInfo.h" #include "TargetInfo.h"
#include <algorithm>
using namespace clang; using namespace clang;
using namespace clang::CodeGen; using namespace clang::CodeGen;
@@ -109,7 +110,8 @@ class SparcV9ABIInfo : public ABIInfo {
SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {} SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
private: private:
ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit) const; ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit,
unsigned &RegOffset) const;
void computeInfo(CGFunctionInfo &FI) const override; void computeInfo(CGFunctionInfo &FI) const override;
RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
AggValueSlot Slot) const override; AggValueSlot Slot) const override;
@@ -222,127 +224,114 @@ class SparcV9ABIInfo : public ABIInfo {
}; };
} // end anonymous namespace } // end anonymous namespace
ABIArgInfo ABIArgInfo SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit,
SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const { unsigned &RegOffset) const {
if (Ty->isVoidType()) if (Ty->isVoidType())
return ABIArgInfo::getIgnore(); return ABIArgInfo::getIgnore();
uint64_t Size = getContext().getTypeSize(Ty); auto &Context = getContext();
auto &VMContext = getVMContext();
uint64_t Size = Context.getTypeSize(Ty);
unsigned Alignment = Context.getTypeAlign(Ty);
bool NeedPadding = (Alignment > 64) && (RegOffset % 2 != 0);
// Anything too big to fit in registers is passed with an explicit indirect // Anything too big to fit in registers is passed with an explicit indirect
// pointer / sret pointer. // pointer / sret pointer.
if (Size > SizeLimit) if (Size > SizeLimit) {
RegOffset += 1;
return getNaturalAlignIndirect( return getNaturalAlignIndirect(
Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),
/*ByVal=*/false); /*ByVal=*/false);
}
// Treat an enum type as its underlying type. // Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>()) if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType(); Ty = EnumTy->getDecl()->getIntegerType();
// Integer types smaller than a register are extended. // Integer types smaller than a register are extended.
if (Size < 64 && Ty->isIntegerType()) if (Size < 64 && Ty->isIntegerType()) {
RegOffset += 1;
return ABIArgInfo::getExtend(Ty); return ABIArgInfo::getExtend(Ty);
}
if (const auto *EIT = Ty->getAs<BitIntType>()) if (const auto *EIT = Ty->getAs<BitIntType>())
if (EIT->getNumBits() < 64) if (EIT->getNumBits() < 64) {
RegOffset += 1;
return ABIArgInfo::getExtend(Ty); return ABIArgInfo::getExtend(Ty);
}
// Other non-aggregates go in registers. // Other non-aggregates go in registers.
if (!isAggregateTypeForABI(Ty)) if (!isAggregateTypeForABI(Ty)) {
RegOffset += Size / 64;
return ABIArgInfo::getDirect(); return ABIArgInfo::getDirect();
}
// If a C++ object has either a non-trivial copy constructor or a non-trivial // If a C++ object has either a non-trivial copy constructor or a non-trivial
// destructor, it is passed with an explicit indirect pointer / sret pointer. // destructor, it is passed with an explicit indirect pointer / sret pointer.
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
RegOffset += 1;
return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
RAA == CGCXXABI::RAA_DirectInMemory); RAA == CGCXXABI::RAA_DirectInMemory);
}
// This is a small aggregate type that should be passed in registers. // This is a small aggregate type that should be passed in registers.
// Build a coercion type from the LLVM struct type. // Build a coercion type from the LLVM struct type.
llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty)); llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
if (!StrTy) if (!StrTy) {
RegOffset += Size / 64;
return ABIArgInfo::getDirect(); return ABIArgInfo::getDirect();
}
CoerceBuilder CB(getVMContext(), getDataLayout()); CoerceBuilder CB(VMContext, getDataLayout());
CB.addStruct(0, StrTy); CB.addStruct(0, StrTy);
// All structs, even empty ones, should take up a register argument slot, // All structs, even empty ones, should take up a register argument slot,
// so pin the minimum struct size to one bit. // so pin the minimum struct size to one bit.
CB.pad(llvm::alignTo( CB.pad(llvm::alignTo(
std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), uint64_t(1)), std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), uint64_t(1)),
64)); 64));
RegOffset += CB.Size / 64;
// If we're dealing with overaligned structs we may need to add a padding in
// the front, to preserve the correct register-memory mapping.
//
// See SCD 2.4.1, pages 3P-11 and 3P-12.
llvm::Type *Padding =
NeedPadding ? llvm::Type::getInt64Ty(VMContext) : nullptr;
RegOffset += NeedPadding ? 1 : 0;
// Try to use the original type for coercion. // Try to use the original type for coercion.
llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType(); llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType();
if (CB.InReg) ABIArgInfo AAI = ABIArgInfo::getDirect(CoerceTy, 0, Padding);
return ABIArgInfo::getDirectInReg(CoerceTy); AAI.setInReg(CB.InReg);
else return AAI;
return ABIArgInfo::getDirect(CoerceTy);
} }
RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty, AggValueSlot Slot) const { QualType Ty, AggValueSlot Slot) const {
ABIArgInfo AI = classifyType(Ty, 16 * 8);
llvm::Type *ArgTy = CGT.ConvertType(Ty);
if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
AI.setCoerceToType(ArgTy);
CharUnits SlotSize = CharUnits::fromQuantity(8); CharUnits SlotSize = CharUnits::fromQuantity(8);
auto TInfo = getContext().getTypeInfoInChars(Ty);
CGBuilderTy &Builder = CGF.Builder; // Zero-sized types have a width of one byte for parameter passing purposes.
Address Addr = Address(Builder.CreateLoad(VAListAddr, "ap.cur"), TInfo.Width = std::max(TInfo.Width, CharUnits::fromQuantity(1));
getVAListElementType(CGF), SlotSize);
llvm::Type *ArgPtrTy = CGF.UnqualPtrTy;
auto TypeInfo = getContext().getTypeInfoInChars(Ty); // Arguments bigger than 2*SlotSize bytes are passed indirectly.
return emitVoidPtrVAArg(CGF, VAListAddr, Ty,
Address ArgAddr = Address::invalid(); /*IsIndirect=*/TInfo.Width > 2 * SlotSize, TInfo,
CharUnits Stride; SlotSize,
switch (AI.getKind()) { /*AllowHigherAlign=*/true, Slot);
case ABIArgInfo::Expand:
case ABIArgInfo::CoerceAndExpand:
case ABIArgInfo::InAlloca:
llvm_unreachable("Unsupported ABI kind for va_arg");
case ABIArgInfo::Extend: {
Stride = SlotSize;
CharUnits Offset = SlotSize - TypeInfo.Width;
ArgAddr = Builder.CreateConstInBoundsByteGEP(Addr, Offset, "extend");
break;
}
case ABIArgInfo::Direct: {
auto AllocSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType());
Stride = CharUnits::fromQuantity(AllocSize).alignTo(SlotSize);
ArgAddr = Addr;
break;
}
case ABIArgInfo::Indirect:
case ABIArgInfo::IndirectAliased:
Stride = SlotSize;
ArgAddr = Addr.withElementType(ArgPtrTy);
ArgAddr = Address(Builder.CreateLoad(ArgAddr, "indirect.arg"), ArgTy,
TypeInfo.Align);
break;
case ABIArgInfo::Ignore:
return Slot.asRValue();
}
// Update VAList.
Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next");
Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr);
return CGF.EmitLoadOfAnyValue(
CGF.MakeAddrLValue(ArgAddr.withElementType(ArgTy), Ty), Slot);
} }
void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const { void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {
FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8); unsigned RetOffset = 0;
ABIArgInfo RetType = classifyType(FI.getReturnType(), 32 * 8, RetOffset);
FI.getReturnInfo() = RetType;
// Indirect returns will have its pointer passed as an argument.
unsigned ArgOffset = RetType.isIndirect() ? RetOffset : 0;
for (auto &I : FI.arguments()) for (auto &I : FI.arguments())
I.info = classifyType(I.type, 16 * 8); I.info = classifyType(I.type, 16 * 8, ArgOffset);
} }
namespace { namespace {
+21 -8
View File
@@ -837,17 +837,30 @@ void ToolChain::addFortranRuntimeLibs(const ArgList &Args,
void ToolChain::addFortranRuntimeLibraryPath(const llvm::opt::ArgList &Args, void ToolChain::addFortranRuntimeLibraryPath(const llvm::opt::ArgList &Args,
ArgStringList &CmdArgs) const { ArgStringList &CmdArgs) const {
// Default to the <driver-path>/../lib directory. This works fine on the auto AddLibSearchPathIfExists = [&](const Twine &Path) {
// platforms that we have tested so far. We will probably have to re-fine // Linker may emit warnings about non-existing directories
// this in the future. In particular, on some platforms, we may need to use if (!llvm::sys::fs::is_directory(Path))
// lib64 instead of lib. return;
if (getTriple().isKnownWindowsMSVCEnvironment())
CmdArgs.push_back(Args.MakeArgString("-libpath:" + Path));
else
CmdArgs.push_back(Args.MakeArgString("-L" + Path));
};
// Search for flang_rt.* at the same location as clang_rt.* with
// LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=0. On most platforms, flang_rt is
// located at the path returned by getRuntimePath() which is already added to
// the library search path. This exception is for Apple-Darwin.
AddLibSearchPathIfExists(getCompilerRTPath());
// Fall back to the non-resource directory <driver-path>/../lib. We will
// probably have to refine this in the future. In particular, on some
// platforms, we may need to use lib64 instead of lib.
SmallString<256> DefaultLibPath = SmallString<256> DefaultLibPath =
llvm::sys::path::parent_path(getDriver().Dir); llvm::sys::path::parent_path(getDriver().Dir);
llvm::sys::path::append(DefaultLibPath, "lib"); llvm::sys::path::append(DefaultLibPath, "lib");
if (getTriple().isKnownWindowsMSVCEnvironment()) AddLibSearchPathIfExists(DefaultLibPath);
CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath));
else
CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
} }
void ToolChain::addFlangRTLibPath(const ArgList &Args, void ToolChain::addFlangRTLibPath(const ArgList &Args,
@@ -467,3 +467,18 @@ void aarch64::setPAuthABIInTriple(const Driver &D, const ArgList &Args,
break; break;
} }
} }
/// Is the triple {aarch64.aarch64_be}-none-elf?
bool aarch64::isAArch64BareMetal(const llvm::Triple &Triple) {
if (Triple.getArch() != llvm::Triple::aarch64 &&
Triple.getArch() != llvm::Triple::aarch64_be)
return false;
if (Triple.getVendor() != llvm::Triple::UnknownVendor)
return false;
if (Triple.getOS() != llvm::Triple::UnknownOS)
return false;
return Triple.getEnvironmentName() == "elf";
}
@@ -30,6 +30,7 @@ std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args,
void setPAuthABIInTriple(const Driver &D, const llvm::opt::ArgList &Args, void setPAuthABIInTriple(const Driver &D, const llvm::opt::ArgList &Args,
llvm::Triple &triple); llvm::Triple &triple);
bool isAArch64BareMetal(const llvm::Triple &Triple);
} // end namespace aarch64 } // end namespace aarch64
} // end namespace target } // end namespace target
+28 -3
View File
@@ -23,7 +23,9 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
if (Triple.getArch() == llvm::Triple::sparcv9) { if (Triple.getArch() == llvm::Triple::sparcv9) {
const char *DefV9CPU; const char *DefV9CPU;
if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD()) if (Triple.isOSSolaris())
DefV9CPU = "-Av9b";
else if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD())
DefV9CPU = "-Av9a"; DefV9CPU = "-Av9a";
else else
DefV9CPU = "-Av9"; DefV9CPU = "-Av9";
@@ -35,6 +37,13 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
.Case("niagara4", "-Av9d") .Case("niagara4", "-Av9d")
.Default(DefV9CPU); .Default(DefV9CPU);
} else { } else {
const char *DefV8CPU;
if (Triple.isOSSolaris())
DefV8CPU = "-Av8plus";
else
DefV8CPU = "-Av8";
return llvm::StringSwitch<const char *>(Name) return llvm::StringSwitch<const char *>(Name)
.Case("v8", "-Av8") .Case("v8", "-Av8")
.Case("supersparc", "-Av8") .Case("supersparc", "-Av8")
@@ -70,7 +79,7 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
.Case("gr712rc", "-Aleon") .Case("gr712rc", "-Aleon")
.Case("leon4", "-Aleon") .Case("leon4", "-Aleon")
.Case("gr740", "-Aleon") .Case("gr740", "-Aleon")
.Default("-Av8"); .Default(DefV8CPU);
} }
} }
@@ -130,7 +139,8 @@ std::string sparc::getSparcTargetCPU(const Driver &D, const ArgList &Args,
return ""; return "";
} }
void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, void sparc::getSparcTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
std::vector<StringRef> &Features) { std::vector<StringRef> &Features) {
sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args); sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args);
if (FloatABI == sparc::FloatABI::Soft) if (FloatABI == sparc::FloatABI::Soft)
@@ -150,11 +160,22 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
Features.push_back("-popc"); Features.push_back("-popc");
} }
// Those OSes default to enabling VIS on 64-bit SPARC.
// See also the corresponding code for external assemblers in
// sparc::getSparcAsmModeForCPU().
bool IsSparcV9ATarget =
(Triple.getArch() == llvm::Triple::sparcv9) &&
(Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD());
bool IsSparcV9BTarget = Triple.isOSSolaris();
bool IsSparcV8PlusTarget =
Triple.getArch() == llvm::Triple::sparc && Triple.isOSSolaris();
if (Arg *A = Args.getLastArg(options::OPT_mvis, options::OPT_mno_vis)) { if (Arg *A = Args.getLastArg(options::OPT_mvis, options::OPT_mno_vis)) {
if (A->getOption().matches(options::OPT_mvis)) if (A->getOption().matches(options::OPT_mvis))
Features.push_back("+vis"); Features.push_back("+vis");
else else
Features.push_back("-vis"); Features.push_back("-vis");
} else if (IsSparcV9ATarget) {
Features.push_back("+vis");
} }
if (Arg *A = Args.getLastArg(options::OPT_mvis2, options::OPT_mno_vis2)) { if (Arg *A = Args.getLastArg(options::OPT_mvis2, options::OPT_mno_vis2)) {
@@ -162,6 +183,8 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
Features.push_back("+vis2"); Features.push_back("+vis2");
else else
Features.push_back("-vis2"); Features.push_back("-vis2");
} else if (IsSparcV9BTarget) {
Features.push_back("+vis2");
} }
if (Arg *A = Args.getLastArg(options::OPT_mvis3, options::OPT_mno_vis3)) { if (Arg *A = Args.getLastArg(options::OPT_mvis3, options::OPT_mno_vis3)) {
@@ -182,6 +205,8 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
if (Arg *A = Args.getLastArg(options::OPT_mv8plus, options::OPT_mno_v8plus)) { if (Arg *A = Args.getLastArg(options::OPT_mv8plus, options::OPT_mno_v8plus)) {
if (A->getOption().matches(options::OPT_mv8plus)) if (A->getOption().matches(options::OPT_mv8plus))
Features.push_back("+v8plus"); Features.push_back("+v8plus");
} else if (IsSparcV8PlusTarget) {
Features.push_back("+v8plus");
} }
if (Args.hasArg(options::OPT_ffixed_g1)) if (Args.hasArg(options::OPT_ffixed_g1))
+2 -1
View File
@@ -31,7 +31,8 @@ FloatABI getSparcFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
std::string getSparcTargetCPU(const Driver &D, const llvm::opt::ArgList &Args, std::string getSparcTargetCPU(const Driver &D, const llvm::opt::ArgList &Args,
const llvm::Triple &Triple); const llvm::Triple &Triple);
void getSparcTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, void getSparcTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features); std::vector<llvm::StringRef> &Features);
const char *getSparcAsmModeForCPU(llvm::StringRef Name, const char *getSparcAsmModeForCPU(llvm::StringRef Name,
const llvm::Triple &Triple); const llvm::Triple &Triple);
+4 -20
View File
@@ -12,6 +12,7 @@
#include "clang/Driver/CommonArgs.h" #include "clang/Driver/CommonArgs.h"
#include "clang/Driver/InputInfo.h" #include "clang/Driver/InputInfo.h"
#include "Arch/AArch64.h"
#include "Arch/ARM.h" #include "Arch/ARM.h"
#include "Arch/RISCV.h" #include "Arch/RISCV.h"
#include "clang/Driver/Compilation.h" #include "clang/Driver/Compilation.h"
@@ -31,21 +32,6 @@ using namespace clang::driver;
using namespace clang::driver::tools; using namespace clang::driver::tools;
using namespace clang::driver::toolchains; using namespace clang::driver::toolchains;
/// Is the triple {aarch64.aarch64_be}-none-elf?
static bool isAArch64BareMetal(const llvm::Triple &Triple) {
if (Triple.getArch() != llvm::Triple::aarch64 &&
Triple.getArch() != llvm::Triple::aarch64_be)
return false;
if (Triple.getVendor() != llvm::Triple::UnknownVendor)
return false;
if (Triple.getOS() != llvm::Triple::UnknownOS)
return false;
return Triple.getEnvironmentName() == "elf";
}
static bool isRISCVBareMetal(const llvm::Triple &Triple) { static bool isRISCVBareMetal(const llvm::Triple &Triple) {
if (!Triple.isRISCV()) if (!Triple.isRISCV())
return false; return false;
@@ -363,8 +349,9 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
} }
bool BareMetal::handlesTarget(const llvm::Triple &Triple) { bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
return arm::isARMEABIBareMetal(Triple) || isAArch64BareMetal(Triple) || return arm::isARMEABIBareMetal(Triple) ||
isRISCVBareMetal(Triple) || isPPCBareMetal(Triple); aarch64::isAArch64BareMetal(Triple) || isRISCVBareMetal(Triple) ||
isPPCBareMetal(Triple);
} }
Tool *BareMetal::buildLinker() const { Tool *BareMetal::buildLinker() const {
@@ -694,9 +681,6 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
NeedCRTs) NeedCRTs)
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(CRTEnd))); CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(CRTEnd)));
if (TC.getTriple().isRISCV())
CmdArgs.push_back("-X");
// The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf // The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
// and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and // and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
// arm*-*-*bsd). // arm*-*-*bsd).
-11
View File
@@ -1752,7 +1752,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
options::OPT_fno_ptrauth_objc_interface_sel); options::OPT_fno_ptrauth_objc_interface_sel);
Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_objc_class_ro, Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_objc_class_ro,
options::OPT_fno_ptrauth_objc_class_ro); options::OPT_fno_ptrauth_objc_class_ro);
if (Triple.getEnvironment() == llvm::Triple::PAuthTest) if (Triple.getEnvironment() == llvm::Triple::PAuthTest)
handlePAuthABI(Args, CmdArgs); handlePAuthABI(Args, CmdArgs);
@@ -2731,16 +2730,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
CmdArgs.push_back(MipsTargetFeature); CmdArgs.push_back(MipsTargetFeature);
} }
// Those OSes default to enabling VIS on 64-bit SPARC.
// See also the corresponding code for external assemblers in
// sparc::getSparcAsmModeForCPU().
bool IsSparcV9ATarget =
(C.getDefaultToolChain().getArch() == llvm::Triple::sparcv9) &&
(Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD());
if (IsSparcV9ATarget && SparcTargetFeatures.empty()) {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("+vis");
}
for (const char *Feature : SparcTargetFeatures) { for (const char *Feature : SparcTargetFeatures) {
CmdArgs.push_back("-target-feature"); CmdArgs.push_back("-target-feature");
CmdArgs.push_back(Feature); CmdArgs.push_back(Feature);
+24 -12
View File
@@ -547,15 +547,22 @@ const char *tools::getLDMOption(const llvm::Triple &T, const ArgList &Args) {
case llvm::Triple::aarch64: case llvm::Triple::aarch64:
if (T.isOSManagarm()) if (T.isOSManagarm())
return "aarch64managarm"; return "aarch64managarm";
else if (aarch64::isAArch64BareMetal(T))
return "aarch64elf";
return "aarch64linux"; return "aarch64linux";
case llvm::Triple::aarch64_be: case llvm::Triple::aarch64_be:
if (aarch64::isAArch64BareMetal(T))
return "aarch64elfb";
return "aarch64linuxb"; return "aarch64linuxb";
case llvm::Triple::arm: case llvm::Triple::arm:
case llvm::Triple::thumb: case llvm::Triple::thumb:
case llvm::Triple::armeb: case llvm::Triple::armeb:
case llvm::Triple::thumbeb: case llvm::Triple::thumbeb: {
return tools::arm::isARMBigEndian(T, Args) ? "armelfb_linux_eabi" bool IsBigEndian = tools::arm::isARMBigEndian(T, Args);
: "armelf_linux_eabi"; if (arm::isARMEABIBareMetal(T))
return IsBigEndian ? "armelfb" : "armelf";
return IsBigEndian ? "armelfb_linux_eabi" : "armelf_linux_eabi";
}
case llvm::Triple::m68k: case llvm::Triple::m68k:
return "m68kelf"; return "m68kelf";
case llvm::Triple::ppc: case llvm::Triple::ppc:
@@ -856,7 +863,7 @@ void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case llvm::Triple::sparc: case llvm::Triple::sparc:
case llvm::Triple::sparcel: case llvm::Triple::sparcel:
case llvm::Triple::sparcv9: case llvm::Triple::sparcv9:
sparc::getSparcTargetFeatures(D, Args, Features); sparc::getSparcTargetFeatures(D, Triple, Args, Features);
break; break;
case llvm::Triple::r600: case llvm::Triple::r600:
case llvm::Triple::amdgcn: case llvm::Triple::amdgcn:
@@ -1320,6 +1327,17 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
if (Args.hasArg(options::OPT_ftime_report)) if (Args.hasArg(options::OPT_ftime_report))
CmdArgs.push_back( CmdArgs.push_back(
Args.MakeArgString(Twine(PluginOptPrefix) + "-time-passes")); Args.MakeArgString(Twine(PluginOptPrefix) + "-time-passes"));
if (Arg *A = Args.getLastArg(options::OPT_fthinlto_distributor_EQ)) {
CmdArgs.push_back(
Args.MakeArgString("--thinlto-distributor=" + Twine(A->getValue())));
CmdArgs.push_back(
Args.MakeArgString("--thinlto-remote-compiler=" +
Twine(ToolChain.getDriver().getClangProgramPath())));
for (auto A : Args.getAllArgValues(options::OPT_Xthinlto_distributor_EQ))
CmdArgs.push_back(Args.MakeArgString("--thinlto-distributor-arg=" + A));
}
} }
void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC, void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
@@ -3247,14 +3265,8 @@ void tools::handleVectorizeSLPArgs(const ArgList &Args,
void tools::handleInterchangeLoopsArgs(const ArgList &Args, void tools::handleInterchangeLoopsArgs(const ArgList &Args,
ArgStringList &CmdArgs) { ArgStringList &CmdArgs) {
// FIXME: instead of relying on shouldEnableVectorizerAtOLevel, we may want to if (Args.hasFlag(options::OPT_floop_interchange,
// implement a separate function to infer loop interchange from opt level. options::OPT_fno_loop_interchange, false))
// For now, enable loop-interchange at the same opt levels as loop-vectorize.
bool EnableInterchange = shouldEnableVectorizerAtOLevel(Args, false);
OptSpecifier InterchangeAliasOption =
EnableInterchange ? options::OPT_O_Group : options::OPT_floop_interchange;
if (Args.hasFlag(options::OPT_floop_interchange, InterchangeAliasOption,
options::OPT_fno_loop_interchange, EnableInterchange))
CmdArgs.push_back("-floop-interchange"); CmdArgs.push_back("-floop-interchange");
} }
+31 -13
View File
@@ -3187,28 +3187,46 @@ void MachO::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
ToolChain::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind); ToolChain::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind);
// On arm64e, enable pointer authentication (for the return address and // On arm64e, we enable all the features required for the Darwin userspace
// indirect calls), as well as usage of the intrinsics. // ABI
if (getArchName() == "arm64e") { if (getTriple().isArm64e()) {
if (!DriverArgs.hasArg(options::OPT_fptrauth_returns, // Core platform ABI
options::OPT_fno_ptrauth_returns))
CC1Args.push_back("-fptrauth-returns");
if (!DriverArgs.hasArg(options::OPT_fptrauth_intrinsics,
options::OPT_fno_ptrauth_intrinsics))
CC1Args.push_back("-fptrauth-intrinsics");
if (!DriverArgs.hasArg(options::OPT_fptrauth_calls, if (!DriverArgs.hasArg(options::OPT_fptrauth_calls,
options::OPT_fno_ptrauth_calls)) options::OPT_fno_ptrauth_calls))
CC1Args.push_back("-fptrauth-calls"); CC1Args.push_back("-fptrauth-calls");
if (!DriverArgs.hasArg(options::OPT_fptrauth_returns,
options::OPT_fno_ptrauth_returns))
CC1Args.push_back("-fptrauth-returns");
if (!DriverArgs.hasArg(options::OPT_fptrauth_intrinsics,
options::OPT_fno_ptrauth_intrinsics))
CC1Args.push_back("-fptrauth-intrinsics");
if (!DriverArgs.hasArg(options::OPT_fptrauth_indirect_gotos, if (!DriverArgs.hasArg(options::OPT_fptrauth_indirect_gotos,
options::OPT_fno_ptrauth_indirect_gotos)) options::OPT_fno_ptrauth_indirect_gotos))
CC1Args.push_back("-fptrauth-indirect-gotos"); CC1Args.push_back("-fptrauth-indirect-gotos");
if (!DriverArgs.hasArg(options::OPT_fptrauth_auth_traps, if (!DriverArgs.hasArg(options::OPT_fptrauth_auth_traps,
options::OPT_fno_ptrauth_auth_traps)) options::OPT_fno_ptrauth_auth_traps))
CC1Args.push_back("-fptrauth-auth-traps"); CC1Args.push_back("-fptrauth-auth-traps");
// C++ v-table ABI
if (!DriverArgs.hasArg(
options::OPT_fptrauth_vtable_pointer_address_discrimination,
options::OPT_fno_ptrauth_vtable_pointer_address_discrimination))
CC1Args.push_back("-fptrauth-vtable-pointer-address-discrimination");
if (!DriverArgs.hasArg(
options::OPT_fptrauth_vtable_pointer_type_discrimination,
options::OPT_fno_ptrauth_vtable_pointer_type_discrimination))
CC1Args.push_back("-fptrauth-vtable-pointer-type-discrimination");
// Objective-C ABI
if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_isa,
options::OPT_fno_ptrauth_objc_isa))
CC1Args.push_back("-fptrauth-objc-isa");
if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_class_ro,
options::OPT_fno_ptrauth_objc_class_ro))
CC1Args.push_back("-fptrauth-objc-class-ro");
if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_interface_sel,
options::OPT_fno_ptrauth_objc_interface_sel))
CC1Args.push_back("-fptrauth-objc-interface-sel");
} }
} }
+1
View File
@@ -447,6 +447,7 @@ void Flang::addTargetOptions(const ArgList &Args,
// Add the target features. // Add the target features.
switch (TC.getArch()) { switch (TC.getArch()) {
default: default:
getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
break; break;
case llvm::Triple::aarch64: case llvm::Triple::aarch64:
getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
+9 -2
View File
@@ -85,11 +85,18 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
CmdArgs.push_back("-lmoldname"); CmdArgs.push_back("-lmoldname");
CmdArgs.push_back("-lmingwex"); CmdArgs.push_back("-lmingwex");
for (auto Lib : Args.getAllArgValues(options::OPT_l)) for (auto Lib : Args.getAllArgValues(options::OPT_l)) {
if (StringRef(Lib).starts_with("msvcr") || if (StringRef(Lib).starts_with("msvcr") ||
StringRef(Lib).starts_with("ucrt") || StringRef(Lib).starts_with("ucrt") ||
StringRef(Lib).starts_with("crtdll")) StringRef(Lib).starts_with("crtdll")) {
std::string CRTLib = (llvm::Twine("-l") + Lib).str();
// Respect the user's chosen crt variant, but still provide it
// again as the last linker argument, because some of the libraries
// we added above may depend on it.
CmdArgs.push_back(Args.MakeArgStringRef(CRTLib));
return; return;
}
}
CmdArgs.push_back("-lmsvcrt"); CmdArgs.push_back("-lmsvcrt");
} }
+1 -1
View File
@@ -161,7 +161,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Nopie || Profiling) if (Nopie || Profiling)
CmdArgs.push_back("-nopie"); CmdArgs.push_back("-nopie");
if (Triple.isRISCV64()) { if (Triple.isLoongArch64() || Triple.isRISCV64()) {
CmdArgs.push_back("-X"); CmdArgs.push_back("-X");
if (Args.hasArg(options::OPT_mno_relax)) if (Args.hasArg(options::OPT_mno_relax))
CmdArgs.push_back("--no-relax"); CmdArgs.push_back("--no-relax");
+10 -3
View File
@@ -411,7 +411,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
} }
if (CurrentState.BreakBeforeClosingBrace && if (CurrentState.BreakBeforeClosingBrace &&
(Current.closesBlockOrBlockTypeList(Style) || (Current.closesBlockOrBlockTypeList(Style) ||
(Current.is(tok::r_brace) && (Current.is(tok::r_brace) && Current.MatchingParen &&
Current.isBlockIndentedInitRBrace(Style)))) { Current.isBlockIndentedInitRBrace(Style)))) {
return true; return true;
} }
@@ -628,9 +628,16 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
// name. // name.
!Style.isJavaScript() && Previous.isNot(tok::kw_template) && !Style.isJavaScript() && Previous.isNot(tok::kw_template) &&
CurrentState.BreakBeforeParameter) { CurrentState.BreakBeforeParameter) {
for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous) for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous) {
if (Tok->FirstAfterPPLine || Tok->is(TT_LineComment)) if (Tok->is(TT_LineComment))
return false; return false;
if (Tok->is(TT_TemplateCloser)) {
Tok = Tok->MatchingParen;
assert(Tok);
}
if (Tok->FirstAfterPPLine)
return false;
}
return true; return true;
} }
+56 -38
View File
@@ -727,6 +727,7 @@ template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
IO.mapOptional("AfterFunctionDeclarationName", IO.mapOptional("AfterFunctionDeclarationName",
Spacing.AfterFunctionDeclarationName); Spacing.AfterFunctionDeclarationName);
IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros); IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
IO.mapOptional("AfterNot", Spacing.AfterNot);
IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator); IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator); IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator);
IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause); IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
@@ -1748,7 +1749,6 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.AttributeMacros.push_back("absl_nullable"); GoogleStyle.AttributeMacros.push_back("absl_nullable");
GoogleStyle.AttributeMacros.push_back("absl_nullability_unknown"); GoogleStyle.AttributeMacros.push_back("absl_nullability_unknown");
GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
GoogleStyle.DerivePointerAlignment = true;
GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false}, GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
{"^<.*\\.h>", 1, 0, false}, {"^<.*\\.h>", 1, 0, false},
@@ -1857,6 +1857,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
} else if (Language == FormatStyle::LK_ObjC) { } else if (Language == FormatStyle::LK_ObjC) {
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
GoogleStyle.ColumnLimit = 100; GoogleStyle.ColumnLimit = 100;
GoogleStyle.DerivePointerAlignment = true;
// "Regroup" doesn't work well for ObjC yet (main header heuristic, // "Regroup" doesn't work well for ObjC yet (main header heuristic,
// relationship between ObjC standard library headers and other heades, // relationship between ObjC standard library headers and other heades,
// #imports, etc.) // #imports, etc.)
@@ -2131,48 +2132,70 @@ std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
Input >> Styles; Input >> Styles;
if (Input.error()) if (Input.error())
return Input.error(); return Input.error();
if (Styles.empty())
return make_error_code(ParseError::Success);
for (unsigned i = 0; i < Styles.size(); ++i) { const auto StyleCount = Styles.size();
// Ensures that only the first configuration can skip the Language option.
if (Styles[i].Language == FormatStyle::LK_None && i != 0) // Start from the second style as (only) the first one may be the default.
for (unsigned I = 1; I < StyleCount; ++I) {
const auto Lang = Styles[I].Language;
if (Lang == FormatStyle::LK_None)
return make_error_code(ParseError::Error); return make_error_code(ParseError::Error);
// Ensure that each language is configured at most once. // Ensure that each language is configured at most once.
for (unsigned j = 0; j < i; ++j) { for (unsigned J = 0; J < I; ++J) {
if (Styles[i].Language == Styles[j].Language) { if (Lang == Styles[J].Language) {
LLVM_DEBUG(llvm::dbgs() LLVM_DEBUG(llvm::dbgs()
<< "Duplicate languages in the config file on positions " << "Duplicate languages in the config file on positions "
<< j << " and " << i << "\n"); << J << " and " << I << '\n');
return make_error_code(ParseError::Error); return make_error_code(ParseError::Error);
} }
} }
} }
// Look for a suitable configuration starting from the end, so we can
// find the configuration for the specific language first, and the default int LanguagePos = -1; // Position of the style for Language.
// configuration (which can only be at slot 0) after it. int CppPos = -1; // Position of the style for C++.
FormatStyle::FormatStyleSet StyleSet; int CPos = -1; // Position of the style for C.
bool LanguageFound = false;
for (const FormatStyle &Style : llvm::reverse(Styles)) { // Search Styles for Language and store the positions of C++ and C styles in
const auto Lang = Style.Language; // case Language is not found.
if (Lang != FormatStyle::LK_None) for (unsigned I = 0; I < StyleCount; ++I) {
StyleSet.Add(Style); const auto Lang = Styles[I].Language;
if (Lang == Language || if (Lang == Language) {
// For backward compatibility. LanguagePos = I;
(Lang == FormatStyle::LK_Cpp && Language == FormatStyle::LK_C)) { break;
LanguageFound = true;
} else if (IsDotHFile && Language == FormatStyle::LK_Cpp &&
(Lang == FormatStyle::LK_C || Lang == FormatStyle::LK_ObjC)) {
Language = Lang;
LanguageFound = true;
} }
if (Lang == FormatStyle::LK_Cpp)
CppPos = I;
else if (Lang == FormatStyle::LK_C)
CPos = I;
} }
if (!LanguageFound) {
if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None) // If Language is not found, use the default style if there is one. Otherwise,
// use the C style for C++ .h files and for backward compatibility, the C++
// style for .c files.
if (LanguagePos < 0) {
if (Styles[0].Language == FormatStyle::LK_None) // Default style.
LanguagePos = 0;
else if (IsDotHFile && Language == FormatStyle::LK_Cpp)
LanguagePos = CPos;
else if (!IsDotHFile && Language == FormatStyle::LK_C)
LanguagePos = CppPos;
if (LanguagePos < 0)
return make_error_code(ParseError::Unsuitable); return make_error_code(ParseError::Unsuitable);
FormatStyle DefaultStyle = Styles[0];
DefaultStyle.Language = Language;
StyleSet.Add(std::move(DefaultStyle));
} }
*Style = *StyleSet.Get(Language);
for (const auto &S : llvm::reverse(llvm::drop_begin(Styles)))
Style->StyleSet.Add(S);
*Style = Styles[LanguagePos];
if (LanguagePos == 0) {
if (Style->Language == FormatStyle::LK_None) // Default style.
Style->Language = Language;
Style->StyleSet.Add(*Style);
}
if (Style->InsertTrailingCommas != FormatStyle::TCS_None && if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&
Style->BinPackArguments) { Style->BinPackArguments) {
// See comment on FormatStyle::TSC_Wrapped. // See comment on FormatStyle::TSC_Wrapped.
@@ -2203,14 +2226,8 @@ FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
if (!Styles) if (!Styles)
return std::nullopt; return std::nullopt;
auto It = Styles->find(Language); auto It = Styles->find(Language);
if (It == Styles->end()) { if (It == Styles->end())
if (Language != FormatStyle::LK_C) return std::nullopt;
return std::nullopt;
// For backward compatibility.
It = Styles->find(FormatStyle::LK_Cpp);
if (It == Styles->end())
return std::nullopt;
}
FormatStyle Style = It->second; FormatStyle Style = It->second;
Style.StyleSet = *this; Style.StyleSet = *this;
return Style; return Style;
@@ -4042,6 +4059,7 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
switch (Style.Language) { switch (Style.Language) {
case FormatStyle::LK_C: case FormatStyle::LK_C:
LangOpts.C11 = 1; LangOpts.C11 = 1;
LangOpts.C23 = 1;
break; break;
case FormatStyle::LK_Cpp: case FormatStyle::LK_Cpp:
case FormatStyle::LK_ObjC: case FormatStyle::LK_ObjC:
+2 -1
View File
@@ -53,12 +53,13 @@ bool FormatToken::isTypeOrIdentifier(const LangOptions &LangOpts) const {
bool FormatToken::isBlockIndentedInitRBrace(const FormatStyle &Style) const { bool FormatToken::isBlockIndentedInitRBrace(const FormatStyle &Style) const {
assert(is(tok::r_brace)); assert(is(tok::r_brace));
assert(MatchingParen);
assert(MatchingParen->is(tok::l_brace));
if (!Style.Cpp11BracedListStyle || if (!Style.Cpp11BracedListStyle ||
Style.AlignAfterOpenBracket != FormatStyle::BAS_BlockIndent) { Style.AlignAfterOpenBracket != FormatStyle::BAS_BlockIndent) {
return false; return false;
} }
const auto *LBrace = MatchingParen; const auto *LBrace = MatchingParen;
assert(LBrace && LBrace->is(tok::l_brace));
if (LBrace->is(BK_BracedInit)) if (LBrace->is(BK_BracedInit))
return true; return true;
if (LBrace->Previous && LBrace->Previous->is(tok::equal)) if (LBrace->Previous && LBrace->Previous->is(tok::equal))
+1 -1
View File
@@ -55,7 +55,7 @@ namespace format {
TYPE(ConflictAlternative) \ TYPE(ConflictAlternative) \
TYPE(ConflictEnd) \ TYPE(ConflictEnd) \
TYPE(ConflictStart) \ TYPE(ConflictStart) \
/* l_brace of if/for/while */ \ /* l_brace of if/for/while/switch/catch */ \
TYPE(ControlStatementLBrace) \ TYPE(ControlStatementLBrace) \
TYPE(ControlStatementRBrace) \ TYPE(ControlStatementRBrace) \
TYPE(CppCastLParen) \ TYPE(CppCastLParen) \
+7 -6
View File
@@ -93,12 +93,6 @@ ArrayRef<FormatToken *> FormatTokenLexer::lex() {
auto &Tok = *Tokens.back(); auto &Tok = *Tokens.back();
const auto NewlinesBefore = Tok.NewlinesBefore; const auto NewlinesBefore = Tok.NewlinesBefore;
switch (FormatOff) { switch (FormatOff) {
case FO_CurrentLine:
if (NewlinesBefore == 0)
Tok.Finalized = true;
else
FormatOff = FO_None;
break;
case FO_NextLine: case FO_NextLine:
if (NewlinesBefore > 1) { if (NewlinesBefore > 1) {
FormatOff = FO_None; FormatOff = FO_None;
@@ -107,6 +101,13 @@ ArrayRef<FormatToken *> FormatTokenLexer::lex() {
FormatOff = FO_CurrentLine; FormatOff = FO_CurrentLine;
} }
break; break;
case FO_CurrentLine:
if (NewlinesBefore == 0) {
Tok.Finalized = true;
break;
}
FormatOff = FO_None;
[[fallthrough]];
default: default:
if (!FormattingDisabled && FormatOffRegex.match(Tok.TokenText)) { if (!FormattingDisabled && FormatOffRegex.match(Tok.TokenText)) {
if (Tok.is(tok::comment) && if (Tok.is(tok::comment) &&
@@ -45,15 +45,18 @@ std::pair<tooling::Replacements, unsigned>
IntegerLiteralSeparatorFixer::process(const Environment &Env, IntegerLiteralSeparatorFixer::process(const Environment &Env,
const FormatStyle &Style) { const FormatStyle &Style) {
switch (Style.Language) { switch (Style.Language) {
case FormatStyle::LK_Cpp:
case FormatStyle::LK_ObjC:
Separator = '\'';
break;
case FormatStyle::LK_CSharp: case FormatStyle::LK_CSharp:
case FormatStyle::LK_Java: case FormatStyle::LK_Java:
case FormatStyle::LK_JavaScript: case FormatStyle::LK_JavaScript:
Separator = '_'; Separator = '_';
break; break;
case FormatStyle::LK_Cpp:
case FormatStyle::LK_ObjC:
if (Style.Standard >= FormatStyle::LS_Cpp14) {
Separator = '\'';
break;
}
[[fallthrough]];
default: default:
return {}; return {};
} }
+43 -39
View File
@@ -829,11 +829,6 @@ class AnnotatingParser {
if (Parent && Parent->is(TT_PointerOrReference)) if (Parent && Parent->is(TT_PointerOrReference))
Parent->overwriteFixedType(TT_BinaryOperator); Parent->overwriteFixedType(TT_BinaryOperator);
} }
// An arrow after an ObjC method expression is not a lambda arrow.
if (CurrentToken->is(TT_ObjCMethodExpr) && CurrentToken->Next &&
CurrentToken->Next->is(TT_LambdaArrow)) {
CurrentToken->Next->overwriteFixedType(TT_Unknown);
}
Left->MatchingParen = CurrentToken; Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left; CurrentToken->MatchingParen = Left;
// FirstObjCSelectorName is set when a colon is found. This does // FirstObjCSelectorName is set when a colon is found. This does
@@ -2590,6 +2585,9 @@ class AnnotatingParser {
if (!Tok.Previous || Tok.isNot(tok::identifier) || Tok.is(TT_ClassHeadName)) if (!Tok.Previous || Tok.isNot(tok::identifier) || Tok.is(TT_ClassHeadName))
return false; return false;
if (Tok.endsSequence(Keywords.kw_final, TT_ClassHeadName))
return false;
if ((Style.isJavaScript() || Style.isJava()) && Tok.is(Keywords.kw_extends)) if ((Style.isJavaScript() || Style.isJava()) && Tok.is(Keywords.kw_extends))
return false; return false;
@@ -2996,14 +2994,18 @@ class AnnotatingParser {
const FormatToken *PrevToken = Tok.getPreviousNonComment(); const FormatToken *PrevToken = Tok.getPreviousNonComment();
if (!PrevToken) if (!PrevToken)
return TT_UnaryOperator; return TT_UnaryOperator;
if (PrevToken->is(TT_TypeName)) if (PrevToken->isTypeName(LangOpts))
return TT_PointerOrReference; return TT_PointerOrReference;
if (PrevToken->isPlacementOperator() && Tok.is(tok::ampamp)) if (PrevToken->isPlacementOperator() && Tok.is(tok::ampamp))
return TT_BinaryOperator; return TT_BinaryOperator;
const FormatToken *NextToken = Tok.getNextNonComment(); auto *NextToken = Tok.getNextNonComment();
if (!NextToken) if (!NextToken)
return TT_PointerOrReference; return TT_PointerOrReference;
if (NextToken->is(tok::greater)) {
NextToken->setFinalizedType(TT_TemplateCloser);
return TT_PointerOrReference;
}
if (InTemplateArgument && NextToken->is(tok::kw_noexcept)) if (InTemplateArgument && NextToken->is(tok::kw_noexcept))
return TT_BinaryOperator; return TT_BinaryOperator;
@@ -3112,7 +3114,7 @@ class AnnotatingParser {
// It's more likely that & represents operator& than an uninitialized // It's more likely that & represents operator& than an uninitialized
// reference. // reference.
if (Tok.is(tok::amp) && PrevToken && PrevToken->Tok.isAnyIdentifier() && if (Tok.is(tok::amp) && PrevToken->Tok.isAnyIdentifier() &&
IsChainedOperatorAmpOrMember(PrevToken->getPreviousNonComment()) && IsChainedOperatorAmpOrMember(PrevToken->getPreviousNonComment()) &&
NextToken && NextToken->Tok.isAnyIdentifier()) { NextToken && NextToken->Tok.isAnyIdentifier()) {
if (auto NextNext = NextToken->getNextNonComment(); if (auto NextNext = NextToken->getNextNonComment();
@@ -3773,18 +3775,12 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts,
if (Current.is(TT_FunctionDeclarationName)) if (Current.is(TT_FunctionDeclarationName))
return true; return true;
if (!Current.Tok.getIdentifierInfo()) if (!Current.isOneOf(tok::identifier, tok::kw_operator))
return false; return false;
const auto *Prev = Current.getPreviousNonComment(); const auto *Prev = Current.getPreviousNonComment();
assert(Prev); assert(Prev);
if (Prev->is(tok::coloncolon))
Prev = Prev->Previous;
if (!Prev)
return false;
const auto &Previous = *Prev; const auto &Previous = *Prev;
if (const auto *PrevPrev = Previous.getPreviousNonComment(); if (const auto *PrevPrev = Previous.getPreviousNonComment();
@@ -3833,6 +3829,8 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts,
// Find parentheses of parameter list. // Find parentheses of parameter list.
if (Current.is(tok::kw_operator)) { if (Current.is(tok::kw_operator)) {
if (Line.startsWith(tok::kw_friend))
return true;
if (Previous.Tok.getIdentifierInfo() && if (Previous.Tok.getIdentifierInfo() &&
!Previous.isOneOf(tok::kw_return, tok::kw_co_return)) { !Previous.isOneOf(tok::kw_return, tok::kw_co_return)) {
return true; return true;
@@ -3998,29 +3996,28 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
} }
} }
if (IsCpp &&
(LineIsFunctionDeclaration ||
(FirstNonComment && FirstNonComment->is(TT_CtorDtorDeclName))) &&
Line.endsWith(tok::semi, tok::r_brace)) {
auto *Tok = Line.Last->Previous;
while (Tok->isNot(tok::r_brace))
Tok = Tok->Previous;
if (auto *LBrace = Tok->MatchingParen; LBrace) {
assert(LBrace->is(tok::l_brace));
Tok->setBlockKind(BK_Block);
LBrace->setBlockKind(BK_Block);
LBrace->setFinalizedType(TT_FunctionLBrace);
}
}
if (IsCpp && SeenName && AfterLastAttribute &&
mustBreakAfterAttributes(*AfterLastAttribute, Style)) {
AfterLastAttribute->MustBreakBefore = true;
if (LineIsFunctionDeclaration)
Line.ReturnTypeWrapped = true;
}
if (IsCpp) { if (IsCpp) {
if ((LineIsFunctionDeclaration ||
(FirstNonComment && FirstNonComment->is(TT_CtorDtorDeclName))) &&
Line.endsWith(tok::semi, tok::r_brace)) {
auto *Tok = Line.Last->Previous;
while (Tok->isNot(tok::r_brace))
Tok = Tok->Previous;
if (auto *LBrace = Tok->MatchingParen; LBrace && LBrace->is(TT_Unknown)) {
assert(LBrace->is(tok::l_brace));
Tok->setBlockKind(BK_Block);
LBrace->setBlockKind(BK_Block);
LBrace->setFinalizedType(TT_FunctionLBrace);
}
}
if (SeenName && AfterLastAttribute &&
mustBreakAfterAttributes(*AfterLastAttribute, Style)) {
AfterLastAttribute->MustBreakBefore = true;
if (LineIsFunctionDeclaration)
Line.ReturnTypeWrapped = true;
}
if (!LineIsFunctionDeclaration) { if (!LineIsFunctionDeclaration) {
// Annotate */&/&& in `operator` function calls as binary operators. // Annotate */&/&& in `operator` function calls as binary operators.
for (const auto *Tok = FirstNonComment; Tok; Tok = Tok->Next) { for (const auto *Tok = FirstNonComment; Tok; Tok = Tok->Next) {
@@ -4066,6 +4063,11 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
} }
} }
if (First->is(TT_ElseLBrace)) {
First->CanBreakBefore = true;
First->MustBreakBefore = true;
}
bool InFunctionDecl = Line.MightBeFunctionDecl; bool InFunctionDecl = Line.MightBeFunctionDecl;
bool InParameterList = false; bool InParameterList = false;
for (auto *Current = First->Next; Current; Current = Current->Next) { for (auto *Current = First->Next; Current; Current = Current->Next) {
@@ -5474,7 +5476,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.TokenText == "!") if (Left.TokenText == "!")
return Style.SpaceAfterLogicalNot; return Style.SpaceAfterLogicalNot;
assert(Left.TokenText == "not"); assert(Left.TokenText == "not");
return Right.isOneOf(tok::coloncolon, TT_UnaryOperator); return Right.isOneOf(tok::coloncolon, TT_UnaryOperator) ||
(Right.is(tok::l_paren) && Style.SpaceBeforeParensOptions.AfterNot);
} }
// If the next token is a binary operator or a selector name, we have // If the next token is a binary operator or a selector name, we have
@@ -6266,7 +6269,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
} }
if (Right.is(tok::colon) && if (Right.is(tok::colon) &&
!Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon)) { !Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon,
TT_BitFieldColon)) {
return false; return false;
} }
if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) { if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
+13 -12
View File
@@ -2266,7 +2266,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
if (!tryToParseLambdaIntroducer()) if (!tryToParseLambdaIntroducer())
return false; return false;
bool SeenArrow = false; FormatToken *Arrow = nullptr;
bool InTemplateParameterList = false; bool InTemplateParameterList = false;
while (FormatTok->isNot(tok::l_brace)) { while (FormatTok->isNot(tok::l_brace)) {
@@ -2341,17 +2341,13 @@ bool UnwrappedLineParser::tryToParseLambda() {
case tok::ellipsis: case tok::ellipsis:
case tok::kw_true: case tok::kw_true:
case tok::kw_false: case tok::kw_false:
if (SeenArrow || InTemplateParameterList) { if (Arrow || InTemplateParameterList) {
nextToken(); nextToken();
break; break;
} }
return true; return true;
case tok::arrow: case tok::arrow:
// This might or might not actually be a lambda arrow (this could be an Arrow = FormatTok;
// ObjC method invocation followed by a dereferencing arrow). We might
// reset this back to TT_Unknown in TokenAnnotator.
FormatTok->setFinalizedType(TT_LambdaArrow);
SeenArrow = true;
nextToken(); nextToken();
break; break;
case tok::kw_requires: { case tok::kw_requires: {
@@ -2373,6 +2369,9 @@ bool UnwrappedLineParser::tryToParseLambda() {
FormatTok->setFinalizedType(TT_LambdaLBrace); FormatTok->setFinalizedType(TT_LambdaLBrace);
LSquare.setFinalizedType(TT_LambdaLSquare); LSquare.setFinalizedType(TT_LambdaLSquare);
if (Arrow)
Arrow->setFinalizedType(TT_LambdaArrow);
NestedLambdas.push_back(Line->SeenDecltypeAuto); NestedLambdas.push_back(Line->SeenDecltypeAuto);
parseChildBlock(); parseChildBlock();
assert(!NestedLambdas.empty()); assert(!NestedLambdas.empty());
@@ -2386,11 +2385,6 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
const FormatToken *LeftSquare = FormatTok; const FormatToken *LeftSquare = FormatTok;
nextToken(); nextToken();
if (Previous) { if (Previous) {
if (Previous->Tok.getIdentifierInfo() &&
!Previous->isOneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
tok::kw_co_return)) {
return false;
}
if (Previous->closesScope()) { if (Previous->closesScope()) {
// Not a potential C-style cast. // Not a potential C-style cast.
if (Previous->isNot(tok::r_paren)) if (Previous->isNot(tok::r_paren))
@@ -2400,6 +2394,13 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
// and `int (*)()`. // and `int (*)()`.
if (!BeforeRParen || !BeforeRParen->isOneOf(tok::greater, tok::r_paren)) if (!BeforeRParen || !BeforeRParen->isOneOf(tok::greater, tok::r_paren))
return false; return false;
} else if (Previous->is(tok::star)) {
Previous = Previous->getPreviousNonComment();
}
if (Previous && Previous->Tok.getIdentifierInfo() &&
!Previous->isOneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
tok::kw_co_return)) {
return false;
} }
} }
if (LeftSquare->isCppStructuredBinding(IsCpp)) if (LeftSquare->isCppStructuredBinding(IsCpp))
+15 -1
View File
@@ -1542,6 +1542,17 @@ void CompilerInvocation::setDefaultPointerAuthOptions(
Discrimination::Constant, InitFiniPointerConstantDiscriminator); Discrimination::Constant, InitFiniPointerConstantDiscriminator);
} }
Opts.BlockInvocationFunctionPointers =
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
Opts.BlockHelperFunctionPointers =
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
Opts.BlockByrefHelperFunctionPointers =
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
if (LangOpts.PointerAuthBlockDescriptorPointers)
Opts.BlockDescriptorPointers =
PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
BlockDescriptorConstantDiscriminator);
Opts.ObjCMethodListFunctionPointers = Opts.ObjCMethodListFunctionPointers =
PointerAuthSchema(Key::ASIA, true, Discrimination::None); PointerAuthSchema(Key::ASIA, true, Discrimination::None);
Opts.ObjCMethodListPointer = Opts.ObjCMethodListPointer =
@@ -3598,6 +3609,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts,
GenerateArg(Consumer, OPT_fptrauth_objc_interface_sel); GenerateArg(Consumer, OPT_fptrauth_objc_interface_sel);
if (Opts.PointerAuthObjcClassROPointers) if (Opts.PointerAuthObjcClassROPointers)
GenerateArg(Consumer, OPT_fptrauth_objc_class_ro); GenerateArg(Consumer, OPT_fptrauth_objc_class_ro);
if (Opts.PointerAuthBlockDescriptorPointers)
GenerateArg(Consumer, OPT_fptrauth_block_descriptor_pointers);
} }
static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
@@ -3621,7 +3634,8 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got); Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got);
Opts.AArch64JumpTableHardening = Opts.AArch64JumpTableHardening =
Args.hasArg(OPT_faarch64_jump_table_hardening); Args.hasArg(OPT_faarch64_jump_table_hardening);
Opts.PointerAuthBlockDescriptorPointers =
Args.hasArg(OPT_fptrauth_block_descriptor_pointers);
Opts.PointerAuthObjcIsa = Args.hasArg(OPT_fptrauth_objc_isa); Opts.PointerAuthObjcIsa = Args.hasArg(OPT_fptrauth_objc_isa);
Opts.PointerAuthObjcClassROPointers = Args.hasArg(OPT_fptrauth_objc_class_ro); Opts.PointerAuthObjcClassROPointers = Args.hasArg(OPT_fptrauth_objc_class_ro);
Opts.PointerAuthObjcInterfaceSel = Opts.PointerAuthObjcInterfaceSel =
+3
View File
@@ -1535,6 +1535,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
#undef TARGET_OS #undef TARGET_OS
} }
if (LangOpts.PointerAuthIntrinsics)
Builder.defineMacro("__PTRAUTH__");
// Get other target #defines. // Get other target #defines.
TI.getTargetDefines(LangOpts, Builder); TI.getTargetDefines(LangOpts, Builder);
} }
+6 -6
View File
@@ -197,7 +197,7 @@ _mm512_mask_dpwsud_epi32(__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
} }
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwsud_epi32( static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwsud_epi32(
__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { __mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
return (__m512i)__builtin_ia32_selectd_512( return (__m512i)__builtin_ia32_selectd_512(
(__mmask16)__U, (__v16si)_mm512_dpwsud_epi32(__A, __B, __C), (__mmask16)__U, (__v16si)_mm512_dpwsud_epi32(__A, __B, __C),
(__v16si)_mm512_setzero_si512()); (__v16si)_mm512_setzero_si512());
@@ -218,7 +218,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_dpwsuds_epi32(
} }
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwsuds_epi32( static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwsuds_epi32(
__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { __mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
return (__m512i)__builtin_ia32_selectd_512( return (__m512i)__builtin_ia32_selectd_512(
(__mmask16)__U, (__v16si)_mm512_dpwsuds_epi32(__A, __B, __C), (__mmask16)__U, (__v16si)_mm512_dpwsuds_epi32(__A, __B, __C),
(__v16si)_mm512_setzero_si512()); (__v16si)_mm512_setzero_si512());
@@ -239,7 +239,7 @@ _mm512_mask_dpwusd_epi32(__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
} }
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwusd_epi32( static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwusd_epi32(
__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { __mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
return (__m512i)__builtin_ia32_selectd_512( return (__m512i)__builtin_ia32_selectd_512(
(__mmask16)__U, (__v16si)_mm512_dpwusd_epi32(__A, __B, __C), (__mmask16)__U, (__v16si)_mm512_dpwusd_epi32(__A, __B, __C),
(__v16si)_mm512_setzero_si512()); (__v16si)_mm512_setzero_si512());
@@ -260,7 +260,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_dpwusds_epi32(
} }
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwusds_epi32( static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwusds_epi32(
__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { __mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
return (__m512i)__builtin_ia32_selectd_512( return (__m512i)__builtin_ia32_selectd_512(
(__mmask16)__U, (__v16si)_mm512_dpwusds_epi32(__A, __B, __C), (__mmask16)__U, (__v16si)_mm512_dpwusds_epi32(__A, __B, __C),
(__v16si)_mm512_setzero_si512()); (__v16si)_mm512_setzero_si512());
@@ -281,7 +281,7 @@ _mm512_mask_dpwuud_epi32(__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
} }
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwuud_epi32( static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwuud_epi32(
__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { __mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
return (__m512i)__builtin_ia32_selectd_512( return (__m512i)__builtin_ia32_selectd_512(
(__mmask16)__U, (__v16si)_mm512_dpwuud_epi32(__A, __B, __C), (__mmask16)__U, (__v16si)_mm512_dpwuud_epi32(__A, __B, __C),
(__v16si)_mm512_setzero_si512()); (__v16si)_mm512_setzero_si512());
@@ -302,7 +302,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_dpwuuds_epi32(
} }
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwuuds_epi32( static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwuuds_epi32(
__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { __mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
return (__m512i)__builtin_ia32_selectd_512( return (__m512i)__builtin_ia32_selectd_512(
(__mmask16)__U, (__v16si)_mm512_dpwuuds_epi32(__A, __B, __C), (__mmask16)__U, (__v16si)_mm512_dpwuuds_epi32(__A, __B, __C),
(__v16si)_mm512_setzero_si512()); (__v16si)_mm512_setzero_si512());
+18 -18
View File
@@ -519,34 +519,34 @@ _mm_maskz_min_pbh(__mmask8 __U, __m128bh __A, __m128bh __B) {
(__mmask8)__U, (__v8bf)_mm_min_pbh(__A, __B), (__v8bf)_mm_setzero_pbh()); (__mmask8)__U, (__v8bf)_mm_min_pbh(__A, __B), (__v8bf)_mm_setzero_pbh());
} }
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comieq_sbh(__m128bh A, static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comieq_sbh(__m128bh __A,
__m128bh B) { __m128bh __B) {
return __builtin_ia32_vcomisbf16eq((__v8bf)A, (__v8bf)B); return __builtin_ia32_vcomisbf16eq((__v8bf)__A, (__v8bf)__B);
} }
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comilt_sbh(__m128bh A, static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comilt_sbh(__m128bh __A,
__m128bh B) { __m128bh __B) {
return __builtin_ia32_vcomisbf16lt((__v8bf)A, (__v8bf)B); return __builtin_ia32_vcomisbf16lt((__v8bf)__A, (__v8bf)__B);
} }
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comile_sbh(__m128bh A, static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comile_sbh(__m128bh __A,
__m128bh B) { __m128bh __B) {
return __builtin_ia32_vcomisbf16le((__v8bf)A, (__v8bf)B); return __builtin_ia32_vcomisbf16le((__v8bf)__A, (__v8bf)__B);
} }
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comigt_sbh(__m128bh A, static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comigt_sbh(__m128bh __A,
__m128bh B) { __m128bh __B) {
return __builtin_ia32_vcomisbf16gt((__v8bf)A, (__v8bf)B); return __builtin_ia32_vcomisbf16gt((__v8bf)__A, (__v8bf)__B);
} }
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comige_sbh(__m128bh A, static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comige_sbh(__m128bh __A,
__m128bh B) { __m128bh __B) {
return __builtin_ia32_vcomisbf16ge((__v8bf)A, (__v8bf)B); return __builtin_ia32_vcomisbf16ge((__v8bf)__A, (__v8bf)__B);
} }
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comineq_sbh(__m128bh A, static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comineq_sbh(__m128bh __A,
__m128bh B) { __m128bh __B) {
return __builtin_ia32_vcomisbf16neq((__v8bf)A, (__v8bf)B); return __builtin_ia32_vcomisbf16neq((__v8bf)__A, (__v8bf)__B);
} }
#define _mm256_cmp_pbh_mask(__A, __B, __P) \ #define _mm256_cmp_pbh_mask(__A, __B, __P) \
+12 -12
View File
@@ -253,7 +253,7 @@ _mm_mask_dpwsud_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
} }
static __inline__ __m128i __DEFAULT_FN_ATTRS128 static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_dpwsud_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { _mm_maskz_dpwsud_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
return (__m128i)__builtin_ia32_selectd_128( return (__m128i)__builtin_ia32_selectd_128(
(__mmask8)__U, (__v4si)_mm_dpwsud_epi32(__A, __B, __C), (__mmask8)__U, (__v4si)_mm_dpwsud_epi32(__A, __B, __C),
(__v4si)_mm_setzero_si128()); (__v4si)_mm_setzero_si128());
@@ -266,7 +266,7 @@ _mm256_mask_dpwsud_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
} }
static __inline__ __m256i __DEFAULT_FN_ATTRS256 static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_dpwsud_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { _mm256_maskz_dpwsud_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
return (__m256i)__builtin_ia32_selectd_256( return (__m256i)__builtin_ia32_selectd_256(
(__mmask8)__U, (__v8si)_mm256_dpwsud_epi32(__A, __B, __C), (__mmask8)__U, (__v8si)_mm256_dpwsud_epi32(__A, __B, __C),
(__v8si)_mm256_setzero_si256()); (__v8si)_mm256_setzero_si256());
@@ -279,7 +279,7 @@ _mm_mask_dpwsuds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
} }
static __inline__ __m128i __DEFAULT_FN_ATTRS128 static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_dpwsuds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { _mm_maskz_dpwsuds_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
return (__m128i)__builtin_ia32_selectd_128( return (__m128i)__builtin_ia32_selectd_128(
(__mmask8)__U, (__v4si)_mm_dpwsuds_epi32(__A, __B, __C), (__mmask8)__U, (__v4si)_mm_dpwsuds_epi32(__A, __B, __C),
(__v4si)_mm_setzero_si128()); (__v4si)_mm_setzero_si128());
@@ -292,7 +292,7 @@ _mm256_mask_dpwsuds_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
} }
static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwsuds_epi32( static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwsuds_epi32(
__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { __mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
return (__m256i)__builtin_ia32_selectd_256( return (__m256i)__builtin_ia32_selectd_256(
(__mmask8)__U, (__v8si)_mm256_dpwsuds_epi32(__A, __B, __C), (__mmask8)__U, (__v8si)_mm256_dpwsuds_epi32(__A, __B, __C),
(__v8si)_mm256_setzero_si256()); (__v8si)_mm256_setzero_si256());
@@ -305,7 +305,7 @@ _mm_mask_dpwusd_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
} }
static __inline__ __m128i __DEFAULT_FN_ATTRS128 static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_dpwusd_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { _mm_maskz_dpwusd_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
return (__m128i)__builtin_ia32_selectd_128( return (__m128i)__builtin_ia32_selectd_128(
(__mmask8)__U, (__v4si)_mm_dpwusd_epi32(__A, __B, __C), (__mmask8)__U, (__v4si)_mm_dpwusd_epi32(__A, __B, __C),
(__v4si)_mm_setzero_si128()); (__v4si)_mm_setzero_si128());
@@ -318,7 +318,7 @@ _mm256_mask_dpwusd_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
} }
static __inline__ __m256i __DEFAULT_FN_ATTRS256 static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_dpwusd_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { _mm256_maskz_dpwusd_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
return (__m256i)__builtin_ia32_selectd_256( return (__m256i)__builtin_ia32_selectd_256(
(__mmask8)__U, (__v8si)_mm256_dpwusd_epi32(__A, __B, __C), (__mmask8)__U, (__v8si)_mm256_dpwusd_epi32(__A, __B, __C),
(__v8si)_mm256_setzero_si256()); (__v8si)_mm256_setzero_si256());
@@ -331,7 +331,7 @@ _mm_mask_dpwusds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
} }
static __inline__ __m128i __DEFAULT_FN_ATTRS128 static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_dpwusds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { _mm_maskz_dpwusds_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
return (__m128i)__builtin_ia32_selectd_128( return (__m128i)__builtin_ia32_selectd_128(
(__mmask8)__U, (__v4si)_mm_dpwusds_epi32(__A, __B, __C), (__mmask8)__U, (__v4si)_mm_dpwusds_epi32(__A, __B, __C),
(__v4si)_mm_setzero_si128()); (__v4si)_mm_setzero_si128());
@@ -344,7 +344,7 @@ _mm256_mask_dpwusds_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
} }
static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwusds_epi32( static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwusds_epi32(
__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { __mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
return (__m256i)__builtin_ia32_selectd_256( return (__m256i)__builtin_ia32_selectd_256(
(__mmask8)__U, (__v8si)_mm256_dpwusds_epi32(__A, __B, __C), (__mmask8)__U, (__v8si)_mm256_dpwusds_epi32(__A, __B, __C),
(__v8si)_mm256_setzero_si256()); (__v8si)_mm256_setzero_si256());
@@ -357,7 +357,7 @@ _mm_mask_dpwuud_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
} }
static __inline__ __m128i __DEFAULT_FN_ATTRS128 static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_dpwuud_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { _mm_maskz_dpwuud_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
return (__m128i)__builtin_ia32_selectd_128( return (__m128i)__builtin_ia32_selectd_128(
(__mmask8)__U, (__v4si)_mm_dpwuud_epi32(__A, __B, __C), (__mmask8)__U, (__v4si)_mm_dpwuud_epi32(__A, __B, __C),
(__v4si)_mm_setzero_si128()); (__v4si)_mm_setzero_si128());
@@ -370,7 +370,7 @@ _mm256_mask_dpwuud_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
} }
static __inline__ __m256i __DEFAULT_FN_ATTRS256 static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_dpwuud_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { _mm256_maskz_dpwuud_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
return (__m256i)__builtin_ia32_selectd_256( return (__m256i)__builtin_ia32_selectd_256(
(__mmask8)__U, (__v8si)_mm256_dpwuud_epi32(__A, __B, __C), (__mmask8)__U, (__v8si)_mm256_dpwuud_epi32(__A, __B, __C),
(__v8si)_mm256_setzero_si256()); (__v8si)_mm256_setzero_si256());
@@ -383,7 +383,7 @@ _mm_mask_dpwuuds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
} }
static __inline__ __m128i __DEFAULT_FN_ATTRS128 static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_dpwuuds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { _mm_maskz_dpwuuds_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
return (__m128i)__builtin_ia32_selectd_128( return (__m128i)__builtin_ia32_selectd_128(
(__mmask8)__U, (__v4si)_mm_dpwuuds_epi32(__A, __B, __C), (__mmask8)__U, (__v4si)_mm_dpwuuds_epi32(__A, __B, __C),
(__v4si)_mm_setzero_si128()); (__v4si)_mm_setzero_si128());
@@ -396,7 +396,7 @@ _mm256_mask_dpwuuds_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
} }
static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwuuds_epi32( static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwuuds_epi32(
__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { __mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
return (__m256i)__builtin_ia32_selectd_256( return (__m256i)__builtin_ia32_selectd_256(
(__mmask8)__U, (__v8si)_mm256_dpwuuds_epi32(__A, __B, __C), (__mmask8)__U, (__v8si)_mm256_dpwuuds_epi32(__A, __B, __C),
(__v8si)_mm256_setzero_si256()); (__v8si)_mm256_setzero_si256());
+10 -1
View File
@@ -697,7 +697,16 @@ template <typename _Tp> struct __remove_address_space<__constant _Tp> {
#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) #if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2)
// OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf // OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf
int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2))); #ifdef __OPENCL_CPP_VERSION__
#define CLINKAGE extern "C"
#else
#define CLINKAGE
#endif
CLINKAGE int printf(__constant const char *st, ...)
__attribute__((format(printf, 1, 2)));
#undef CLINKAGE
#endif #endif
#ifdef cl_intel_device_side_avc_motion_estimation #ifdef cl_intel_device_side_avc_motion_estimation
+2 -2
View File
@@ -95,7 +95,7 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
__ptrauth qualifier; the compiler will perform this check __ptrauth qualifier; the compiler will perform this check
automatically. */ automatically. */
#if __has_feature(ptrauth_intrinsics) #if __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__)
/* Strip the signature from a value without authenticating it. /* Strip the signature from a value without authenticating it.
@@ -388,6 +388,6 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
#define __ptrauth_objc_isa_uintptr #define __ptrauth_objc_isa_uintptr
#define __ptrauth_objc_super_pointer #define __ptrauth_objc_super_pointer
#endif /* __has_feature(ptrauth_intrinsics) */ #endif /* __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__) */
#endif /* __PTRAUTH_H */ #endif /* __PTRAUTH_H */
-9
View File
@@ -174,8 +174,6 @@ void Lexer::InitLexer(const char *BufStart, const char *BufPtr,
ExtendedTokenMode = 0; ExtendedTokenMode = 0;
NewLinePtr = nullptr; NewLinePtr = nullptr;
IsFirstPPToken = true;
} }
/// Lexer constructor - Create a new lexer object for the specified buffer /// Lexer constructor - Create a new lexer object for the specified buffer
@@ -3225,7 +3223,6 @@ std::optional<Token> Lexer::peekNextPPToken() {
bool atStartOfLine = IsAtStartOfLine; bool atStartOfLine = IsAtStartOfLine;
bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine; bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
bool leadingSpace = HasLeadingSpace; bool leadingSpace = HasLeadingSpace;
bool isFirstPPToken = IsFirstPPToken;
Token Tok; Token Tok;
Lex(Tok); Lex(Tok);
@@ -3236,7 +3233,6 @@ std::optional<Token> Lexer::peekNextPPToken() {
HasLeadingSpace = leadingSpace; HasLeadingSpace = leadingSpace;
IsAtStartOfLine = atStartOfLine; IsAtStartOfLine = atStartOfLine;
IsAtPhysicalStartOfLine = atPhysicalStartOfLine; IsAtPhysicalStartOfLine = atPhysicalStartOfLine;
IsFirstPPToken = isFirstPPToken;
// Restore the lexer back to non-skipping mode. // Restore the lexer back to non-skipping mode.
LexingRawMode = false; LexingRawMode = false;
@@ -3726,11 +3722,6 @@ bool Lexer::Lex(Token &Result) {
HasLeadingEmptyMacro = false; HasLeadingEmptyMacro = false;
} }
if (IsFirstPPToken) {
Result.setFlag(Token::FirstPPToken);
IsFirstPPToken = false;
}
bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine; bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
IsAtPhysicalStartOfLine = false; IsAtPhysicalStartOfLine = false;
bool isRawLex = isLexingRawMode(); bool isRawLex = isLexingRawMode();
+1 -1
View File
@@ -1467,7 +1467,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
if (s != PossibleNewDigitStart) if (s != PossibleNewDigitStart)
DigitsBegin = PossibleNewDigitStart; DigitsBegin = PossibleNewDigitStart;
else else
IsSingleZero = (s == ThisTokEnd); // Is the only thing we've seen a 0? IsSingleZero = (s == ThisTokBegin + 1);
if (s == ThisTokEnd) if (s == ThisTokEnd)
return; // Done, simple octal number like 01234 return; // Done, simple octal number like 01234
+37 -3
View File
@@ -43,6 +43,7 @@
#include "clang/Lex/MacroArgs.h" #include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h" #include "clang/Lex/MacroInfo.h"
#include "clang/Lex/ModuleLoader.h" #include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/NoTrivialPPDirectiveTracer.h"
#include "clang/Lex/Pragma.h" #include "clang/Lex/Pragma.h"
#include "clang/Lex/PreprocessingRecord.h" #include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/PreprocessorLexer.h" #include "clang/Lex/PreprocessorLexer.h"
@@ -247,8 +248,6 @@ void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const {
llvm::errs() << " [LeadingSpace]"; llvm::errs() << " [LeadingSpace]";
if (Tok.isExpandDisabled()) if (Tok.isExpandDisabled())
llvm::errs() << " [ExpandDisabled]"; llvm::errs() << " [ExpandDisabled]";
if (Tok.isFirstPPToken())
llvm::errs() << " [First pp-token]";
if (Tok.needsCleaning()) { if (Tok.needsCleaning()) {
const char *Start = SourceMgr.getCharacterData(Tok.getLocation()); const char *Start = SourceMgr.getCharacterData(Tok.getLocation());
llvm::errs() << " [UnClean='" << StringRef(Start, Tok.getLength()) llvm::errs() << " [UnClean='" << StringRef(Start, Tok.getLength())
@@ -577,8 +576,11 @@ void Preprocessor::EnterMainSourceFile() {
// export module M; // error: module declaration must occur // export module M; // error: module declaration must occur
// // at the start of the translation unit. // // at the start of the translation unit.
if (getLangOpts().CPlusPlusModules) { if (getLangOpts().CPlusPlusModules) {
auto Tracer = std::make_unique<NoTrivialPPDirectiveTracer>(*this);
DirTracer = Tracer.get();
addPPCallbacks(std::move(Tracer));
std::optional<Token> FirstPPTok = CurLexer->peekNextPPToken(); std::optional<Token> FirstPPTok = CurLexer->peekNextPPToken();
if (FirstPPTok && FirstPPTok->isFirstPPToken()) if (FirstPPTok)
FirstPPTokenLoc = FirstPPTok->getLocation(); FirstPPTokenLoc = FirstPPTok->getLocation();
} }
} }
@@ -940,6 +942,8 @@ void Preprocessor::Lex(Token &Result) {
StdCXXImportSeqState.handleHeaderName(); StdCXXImportSeqState.handleHeaderName();
break; break;
case tok::kw_export: case tok::kw_export:
if (hasSeenNoTrivialPPDirective())
Result.setFlag(Token::HasSeenNoTrivialPPDirective);
TrackGMFState.handleExport(); TrackGMFState.handleExport();
StdCXXImportSeqState.handleExport(); StdCXXImportSeqState.handleExport();
ModuleDeclState.handleExport(); ModuleDeclState.handleExport();
@@ -966,6 +970,8 @@ void Preprocessor::Lex(Token &Result) {
} }
break; break;
} else if (Result.getIdentifierInfo() == getIdentifierInfo("module")) { } else if (Result.getIdentifierInfo() == getIdentifierInfo("module")) {
if (hasSeenNoTrivialPPDirective())
Result.setFlag(Token::HasSeenNoTrivialPPDirective);
TrackGMFState.handleModule(StdCXXImportSeqState.afterTopLevelSeq()); TrackGMFState.handleModule(StdCXXImportSeqState.afterTopLevelSeq());
ModuleDeclState.handleModule(); ModuleDeclState.handleModule();
break; break;
@@ -1680,3 +1686,31 @@ const char *Preprocessor::getCheckPoint(FileID FID, const char *Start) const {
return nullptr; return nullptr;
} }
bool Preprocessor::hasSeenNoTrivialPPDirective() const {
return DirTracer && DirTracer->hasSeenNoTrivialPPDirective();
}
bool NoTrivialPPDirectiveTracer::hasSeenNoTrivialPPDirective() const {
return SeenNoTrivialPPDirective;
}
void NoTrivialPPDirectiveTracer::setSeenNoTrivialPPDirective() {
if (InMainFile && !SeenNoTrivialPPDirective)
SeenNoTrivialPPDirective = true;
}
void NoTrivialPPDirectiveTracer::LexedFileChanged(
FileID FID, LexedFileChangeReason Reason,
SrcMgr::CharacteristicKind FileType, FileID PrevFID, SourceLocation Loc) {
InMainFile = (FID == PP.getSourceManager().getMainFileID());
}
void NoTrivialPPDirectiveTracer::MacroExpands(const Token &MacroNameTok,
const MacroDefinition &MD,
SourceRange Range,
const MacroArgs *Args) {
// FIXME: Does only enable builtin macro expansion make sense?
if (!MD.getMacroInfo()->isBuiltinMacro())
setSeenNoTrivialPPDirective();
}
+2 -1
View File
@@ -3342,7 +3342,8 @@ ExprResult Parser::ParseBlockLiteralExpression() {
Actions.ActOnBlockError(CaretLoc, getCurScope()); Actions.ActOnBlockError(CaretLoc, getCurScope());
return ExprError(); return ExprError();
} }
EnterExpressionEvaluationContextForFunction PotentiallyEvaluated(
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
StmtResult Stmt(ParseCompoundStatementBody()); StmtResult Stmt(ParseCompoundStatementBody());
BlockScope.Exit(); BlockScope.Exit();
if (!Stmt.isInvalid()) if (!Stmt.isInvalid())
+5 -3
View File
@@ -2361,9 +2361,10 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) {
// Parse a global-module-fragment, if present. // Parse a global-module-fragment, if present.
if (getLangOpts().CPlusPlusModules && Tok.is(tok::semi)) { if (getLangOpts().CPlusPlusModules && Tok.is(tok::semi)) {
SourceLocation SemiLoc = ConsumeToken(); SourceLocation SemiLoc = ConsumeToken();
if (!Introducer.isFirstPPToken()) { if (ImportState != Sema::ModuleImportState::FirstDecl ||
Introducer.hasSeenNoTrivialPPDirective()) {
Diag(StartLoc, diag::err_global_module_introducer_not_at_start) Diag(StartLoc, diag::err_global_module_introducer_not_at_start)
<< SourceRange(StartLoc, SemiLoc); << SourceRange(StartLoc, SemiLoc);
return nullptr; return nullptr;
} }
if (MDK == Sema::ModuleDeclKind::Interface) { if (MDK == Sema::ModuleDeclKind::Interface) {
@@ -2418,7 +2419,8 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) {
ExpectAndConsumeSemi(diag::err_module_expected_semi); ExpectAndConsumeSemi(diag::err_module_expected_semi);
return Actions.ActOnModuleDecl(StartLoc, ModuleLoc, MDK, Path, Partition, return Actions.ActOnModuleDecl(StartLoc, ModuleLoc, MDK, Path, Partition,
ImportState, Introducer.isFirstPPToken()); ImportState,
Introducer.hasSeenNoTrivialPPDirective());
} }
Decl *Parser::ParseModuleImport(SourceLocation AtLoc, Decl *Parser::ParseModuleImport(SourceLocation AtLoc,
+5 -2
View File
@@ -503,8 +503,12 @@ static bool areAllValuesNoReturn(const VarDecl *VD, const CFGBlock &VarBlk,
TransferFunctions TF(VD); TransferFunctions TF(VD);
BackwardDataflowWorklist Worklist(*AC.getCFG(), AC); BackwardDataflowWorklist Worklist(*AC.getCFG(), AC);
llvm::DenseSet<const CFGBlock *> Visited;
Worklist.enqueueBlock(&VarBlk); Worklist.enqueueBlock(&VarBlk);
while (const CFGBlock *B = Worklist.dequeue()) { while (const CFGBlock *B = Worklist.dequeue()) {
if (Visited.contains(B))
continue;
Visited.insert(B);
// First check the current block. // First check the current block.
for (CFGBlock::const_reverse_iterator ri = B->rbegin(), re = B->rend(); for (CFGBlock::const_reverse_iterator ri = B->rbegin(), re = B->rend();
ri != re; ++ri) { ri != re; ++ri) {
@@ -2887,8 +2891,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
.setAlwaysAdd(Stmt::UnaryOperatorClass); .setAlwaysAdd(Stmt::UnaryOperatorClass);
} }
bool EnableLifetimeSafetyAnalysis = !Diags.isIgnored( bool EnableLifetimeSafetyAnalysis = S.getLangOpts().EnableLifetimeSafety;
diag::warn_experimental_lifetime_safety_dummy_warning, D->getBeginLoc());
// Install the logical handler. // Install the logical handler.
std::optional<LogicalErrorHandler> LEH; std::optional<LogicalErrorHandler> LEH;
if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) { if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
+8 -1
View File
@@ -12014,13 +12014,20 @@ static void DiagnoseMixedUnicodeImplicitConversion(Sema &S, const Type *Source,
SourceLocation CC) { SourceLocation CC) {
assert(Source->isUnicodeCharacterType() && Target->isUnicodeCharacterType() && assert(Source->isUnicodeCharacterType() && Target->isUnicodeCharacterType() &&
Source != Target); Source != Target);
// Lone surrogates have a distinct representation in UTF-32.
// Converting between UTF-16 and UTF-32 codepoints seems very widespread,
// so don't warn on such conversion.
if (Source->isChar16Type() && Target->isChar32Type())
return;
Expr::EvalResult Result; Expr::EvalResult Result;
if (E->EvaluateAsInt(Result, S.getASTContext(), Expr::SE_AllowSideEffects, if (E->EvaluateAsInt(Result, S.getASTContext(), Expr::SE_AllowSideEffects,
S.isConstantEvaluatedContext())) { S.isConstantEvaluatedContext())) {
llvm::APSInt Value(32); llvm::APSInt Value(32);
Value = Result.Val.getInt(); Value = Result.Val.getInt();
bool IsASCII = Value <= 0x7F; bool IsASCII = Value <= 0x7F;
bool IsBMP = Value <= 0xD7FF || (Value >= 0xE000 && Value <= 0xFFFF); bool IsBMP = Value <= 0xDFFF || (Value >= 0xE000 && Value <= 0xFFFF);
bool ConversionPreservesSemantics = bool ConversionPreservesSemantics =
IsASCII || (!Source->isChar8Type() && !Target->isChar8Type() && IsBMP); IsASCII || (!Source->isChar8Type() && !Target->isChar8Type() && IsBMP);
-4
View File
@@ -1097,10 +1097,6 @@ static bool CheckFunctionConstraintsWithoutInstantiation(
} }
Sema::ContextRAII SavedContext(SemaRef, FD); Sema::ContextRAII SavedContext(SemaRef, FD);
std::optional<Sema::CXXThisScopeRAII> ThisScope;
if (auto *Method = dyn_cast<CXXMethodDecl>(FD))
ThisScope.emplace(SemaRef, /*Record=*/Method->getParent(),
/*ThisQuals=*/Method->getMethodQualifiers());
return SemaRef.CheckConstraintSatisfaction( return SemaRef.CheckConstraintSatisfaction(
Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction); Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
} }
+9
View File
@@ -3267,6 +3267,14 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
if (isa<UsedAttr>(I) || isa<RetainAttr>(I)) if (isa<UsedAttr>(I) || isa<RetainAttr>(I))
continue; continue;
if (isa<InferredNoReturnAttr>(I)) {
if (auto *FD = dyn_cast<FunctionDecl>(New)) {
if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
continue; // Don't propagate inferred noreturn attributes to explicit
// specializations.
}
}
if (mergeDeclAttribute(*this, New, I, LocalAMK)) if (mergeDeclAttribute(*this, New, I, LocalAMK))
foundAny = true; foundAny = true;
} }
@@ -19643,6 +19651,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
Q && Q.isAddressDiscriminated()) { Q && Q.isAddressDiscriminated()) {
Record->setArgPassingRestrictions( Record->setArgPassingRestrictions(
RecordArgPassingKind::CanNeverPassInRegs); RecordArgPassingKind::CanNeverPassInRegs);
Record->setNonTrivialToPrimitiveCopy(true);
} }
} }
+10 -3
View File
@@ -1970,6 +1970,13 @@ void clang::inferNoReturnAttr(Sema &S, const Decl *D) {
if (!FD) if (!FD)
return; return;
// Skip explicit specializations here as they may have
// a user-provided definition that may deliberately differ from the primary
// template. If an explicit specialization truly never returns, the user
// should explicitly mark it with [[noreturn]].
if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
return;
auto *NonConstFD = const_cast<FunctionDecl *>(FD); auto *NonConstFD = const_cast<FunctionDecl *>(FD);
DiagnosticsEngine &Diags = S.getDiagnostics(); DiagnosticsEngine &Diags = S.getDiagnostics();
if (Diags.isIgnored(diag::warn_falloff_nonvoid, FD->getLocation()) && if (Diags.isIgnored(diag::warn_falloff_nonvoid, FD->getLocation()) &&
@@ -5011,10 +5018,10 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
static void handleNonStringAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleNonStringAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// This only applies to fields and variable declarations which have an array // This only applies to fields and variable declarations which have an array
// type. // type or pointer type, with character elements.
QualType QT = cast<ValueDecl>(D)->getType(); QualType QT = cast<ValueDecl>(D)->getType();
if (!QT->isArrayType() || if ((!QT->isArrayType() && !QT->isPointerType()) ||
!QT->getBaseElementTypeUnsafe()->isAnyCharacterType()) { !QT->getPointeeOrArrayElementType()->isAnyCharacterType()) {
S.Diag(D->getBeginLoc(), diag::warn_attribute_non_character_array) S.Diag(D->getBeginLoc(), diag::warn_attribute_non_character_array)
<< AL << AL.isRegularKeywordAttribute() << QT << AL.getRange(); << AL << AL.isRegularKeywordAttribute() << QT << AL.getRange();
return; return;
+4 -4
View File
@@ -9309,14 +9309,14 @@ AssignConvertType Sema::CheckAssignmentConstraints(QualType LHSType,
// If we have an atomic type, try a non-atomic assignment, then just add an // If we have an atomic type, try a non-atomic assignment, then just add an
// atomic qualification step. // atomic qualification step.
if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(LHSType)) { if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(LHSType)) {
AssignConvertType result = AssignConvertType Result =
CheckAssignmentConstraints(AtomicTy->getValueType(), RHS, Kind); CheckAssignmentConstraints(AtomicTy->getValueType(), RHS, Kind);
if (result != AssignConvertType::Compatible) if (!IsAssignConvertCompatible(Result))
return result; return Result;
if (Kind != CK_NoOp && ConvertRHS) if (Kind != CK_NoOp && ConvertRHS)
RHS = ImpCastExprToType(RHS.get(), AtomicTy->getValueType(), Kind); RHS = ImpCastExprToType(RHS.get(), AtomicTy->getValueType(), Kind);
Kind = CK_NonAtomicToAtomic; Kind = CK_NonAtomicToAtomic;
return AssignConvertType::Compatible; return Result;
} }
// If the left-hand side is a reference type, then we are in a // If the left-hand side is a reference type, then we are in a
+2
View File
@@ -347,6 +347,8 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II,
CheckTypenameType(ElaboratedTypeKeyword::None, SourceLocation(), CheckTypenameType(ElaboratedTypeKeyword::None, SourceLocation(),
SS.getWithLocInContext(Context), II, NameLoc, &TSI, SS.getWithLocInContext(Context), II, NameLoc, &TSI,
/*DeducedTSTContext=*/true); /*DeducedTSTContext=*/true);
if (T.isNull())
return ParsedType();
return CreateParsedType(T, TSI); return CreateParsedType(T, TSI);
} }
+4 -2
View File
@@ -264,10 +264,11 @@ Sema::DeclGroupPtrTy
Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
ModuleDeclKind MDK, ModuleIdPath Path, ModuleDeclKind MDK, ModuleIdPath Path,
ModuleIdPath Partition, ModuleImportState &ImportState, ModuleIdPath Partition, ModuleImportState &ImportState,
bool IntroducerIsFirstPPToken) { bool SeenNoTrivialPPDirective) {
assert(getLangOpts().CPlusPlusModules && assert(getLangOpts().CPlusPlusModules &&
"should only have module decl in standard C++ modules"); "should only have module decl in standard C++ modules");
bool IsFirstDecl = ImportState == ModuleImportState::FirstDecl;
bool SeenGMF = ImportState == ModuleImportState::GlobalFragment; bool SeenGMF = ImportState == ModuleImportState::GlobalFragment;
// If any of the steps here fail, we count that as invalidating C++20 // If any of the steps here fail, we count that as invalidating C++20
// module state; // module state;
@@ -335,7 +336,8 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
// In C++20, A module directive may only appear as the first preprocessing // In C++20, A module directive may only appear as the first preprocessing
// tokens in a file (excluding the global module fragment.). // tokens in a file (excluding the global module fragment.).
if (getLangOpts().CPlusPlusModules && !IntroducerIsFirstPPToken && !SeenGMF) { if (getLangOpts().CPlusPlusModules &&
(!IsFirstDecl || SeenNoTrivialPPDirective) && !SeenGMF) {
Diag(ModuleLoc, diag::err_module_decl_not_at_start); Diag(ModuleLoc, diag::err_module_decl_not_at_start);
SourceLocation BeginLoc = PP.getMainFileFirstPPTokenLoc(); SourceLocation BeginLoc = PP.getMainFileFirstPPTokenLoc();
Diag(BeginLoc, diag::note_global_module_introducer_missing) Diag(BeginLoc, diag::note_global_module_introducer_missing)
+1 -13
View File
@@ -245,7 +245,6 @@ void StandardConversionSequence::setAsIdentityConversion() {
IsLvalueReference = true; IsLvalueReference = true;
BindsToFunctionLvalue = false; BindsToFunctionLvalue = false;
BindsToRvalue = false; BindsToRvalue = false;
IsImplicitObjectArgumentQualificationConversion = false;
BindsImplicitObjectArgumentWithoutRefQualifier = false; BindsImplicitObjectArgumentWithoutRefQualifier = false;
ObjCLifetimeConversionBinding = false; ObjCLifetimeConversionBinding = false;
FromBracedInitList = false; FromBracedInitList = false;
@@ -5318,7 +5317,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
ICS.Standard.DirectBinding = BindsDirectly; ICS.Standard.DirectBinding = BindsDirectly;
ICS.Standard.IsLvalueReference = !isRValRef; ICS.Standard.IsLvalueReference = !isRValRef;
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
ICS.Standard.IsImplicitObjectArgumentQualificationConversion = false;
ICS.Standard.BindsToRvalue = InitCategory.isRValue(); ICS.Standard.BindsToRvalue = InitCategory.isRValue();
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = ICS.Standard.ObjCLifetimeConversionBinding =
@@ -5498,7 +5496,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
ICS.Standard.IsLvalueReference = !isRValRef; ICS.Standard.IsLvalueReference = !isRValRef;
ICS.Standard.BindsToFunctionLvalue = false; ICS.Standard.BindsToFunctionLvalue = false;
ICS.Standard.BindsToRvalue = true; ICS.Standard.BindsToRvalue = true;
ICS.Standard.IsImplicitObjectArgumentQualificationConversion = false;
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = false; ICS.Standard.ObjCLifetimeConversionBinding = false;
} else if (ICS.isUserDefined()) { } else if (ICS.isUserDefined()) {
@@ -5521,8 +5518,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
ICS.UserDefined.After.IsLvalueReference = !isRValRef; ICS.UserDefined.After.IsLvalueReference = !isRValRef;
ICS.UserDefined.After.BindsToFunctionLvalue = false; ICS.UserDefined.After.BindsToFunctionLvalue = false;
ICS.UserDefined.After.BindsToRvalue = !LValRefType; ICS.UserDefined.After.BindsToRvalue = !LValRefType;
ICS.UserDefined.After.IsImplicitObjectArgumentQualificationConversion =
false;
ICS.UserDefined.After.BindsImplicitObjectArgumentWithoutRefQualifier = false; ICS.UserDefined.After.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.UserDefined.After.ObjCLifetimeConversionBinding = false; ICS.UserDefined.After.ObjCLifetimeConversionBinding = false;
ICS.UserDefined.After.FromBracedInitList = false; ICS.UserDefined.After.FromBracedInitList = false;
@@ -5807,7 +5802,6 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
StandardConversionSequence &SCS = Result.isStandard() ? Result.Standard : StandardConversionSequence &SCS = Result.isStandard() ? Result.Standard :
Result.UserDefined.After; Result.UserDefined.After;
SCS.ReferenceBinding = true; SCS.ReferenceBinding = true;
SCS.IsImplicitObjectArgumentQualificationConversion = false;
SCS.IsLvalueReference = ToType->isLValueReferenceType(); SCS.IsLvalueReference = ToType->isLValueReferenceType();
SCS.BindsToRvalue = true; SCS.BindsToRvalue = true;
SCS.BindsToFunctionLvalue = false; SCS.BindsToFunctionLvalue = false;
@@ -6005,12 +5999,8 @@ static ImplicitConversionSequence TryObjectArgumentInitialization(
// affects the conversion rank. // affects the conversion rank.
QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType); QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType);
ImplicitConversionKind SecondKind; ImplicitConversionKind SecondKind;
bool IsQualificationConversion = false; if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
if (ImplicitParamType.getCanonicalType() == FromTypeCanon) {
SecondKind = ICK_Identity; SecondKind = ICK_Identity;
} else if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
SecondKind = ICK_Identity;
IsQualificationConversion = true;
} else if (S.IsDerivedFrom(Loc, FromType, ClassType)) { } else if (S.IsDerivedFrom(Loc, FromType, ClassType)) {
SecondKind = ICK_Derived_To_Base; SecondKind = ICK_Derived_To_Base;
} else if (!Method->isExplicitObjectMemberFunction()) { } else if (!Method->isExplicitObjectMemberFunction()) {
@@ -6051,8 +6041,6 @@ static ImplicitConversionSequence TryObjectArgumentInitialization(
ICS.Standard.setFromType(FromType); ICS.Standard.setFromType(FromType);
ICS.Standard.setAllToTypes(ImplicitParamType); ICS.Standard.setAllToTypes(ImplicitParamType);
ICS.Standard.ReferenceBinding = true; ICS.Standard.ReferenceBinding = true;
ICS.Standard.IsImplicitObjectArgumentQualificationConversion =
IsQualificationConversion;
ICS.Standard.DirectBinding = true; ICS.Standard.DirectBinding = true;
ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue; ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue;
ICS.Standard.BindsToFunctionLvalue = false; ICS.Standard.BindsToFunctionLvalue = false;
+5 -1
View File
@@ -2287,7 +2287,11 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
// we can diagnose if we don't see any variable declarations. This // we can diagnose if we don't see any variable declarations. This
// covers a case like declaring a typedef, function, or structure // covers a case like declaring a typedef, function, or structure
// type rather than a variable. // type rather than a variable.
NonVarSeen = DI; //
// Note, _Static_assert is acceptable because it does not declare an
// identifier at all, so "for object having" does not apply.
if (!isa<StaticAssertDecl>(DI))
NonVarSeen = DI;
} }
} }
// Diagnose if we saw a non-variable declaration but no variable // Diagnose if we saw a non-variable declaration but no variable
-2
View File
@@ -4749,8 +4749,6 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
EnterExpressionEvaluationContext EECtx{ EnterExpressionEvaluationContext EECtx{
*this, ExpressionEvaluationContext::Unevaluated, CSD}; *this, ExpressionEvaluationContext::Unevaluated, CSD};
ContextRAII CurContext(*this, CSD->getDeclContext(),
/*NewThisContext=*/false);
if (!AreArgsDependent && if (!AreArgsDependent &&
CheckConstraintSatisfaction( CheckConstraintSatisfaction(
NamedConcept, AssociatedConstraint(NamedConcept->getConstraintExpr()), NamedConcept, AssociatedConstraint(NamedConcept->getConstraintExpr()),
+18 -3
View File
@@ -5525,6 +5525,15 @@ static TemplateDeductionResult CheckDeductionConsistency(
// FIXME: A substitution can be incomplete on a non-structural part of the // FIXME: A substitution can be incomplete on a non-structural part of the
// type. Use the canonical type for now, until the TemplateInstantiator can // type. Use the canonical type for now, until the TemplateInstantiator can
// deal with that. // deal with that.
// Workaround: Implicit deduction guides use InjectedClassNameTypes, whereas
// the explicit guides don't. The substitution doesn't transform these types,
// so let it transform their specializations instead.
bool IsDeductionGuide = isa<CXXDeductionGuideDecl>(FTD->getTemplatedDecl());
if (IsDeductionGuide) {
if (auto *Injected = P->getAs<InjectedClassNameType>())
P = Injected->getInjectedSpecializationType();
}
QualType InstP = S.SubstType(P.getCanonicalType(), MLTAL, FTD->getLocation(), QualType InstP = S.SubstType(P.getCanonicalType(), MLTAL, FTD->getLocation(),
FTD->getDeclName(), &IsIncompleteSubstitution); FTD->getDeclName(), &IsIncompleteSubstitution);
if (InstP.isNull() && !IsIncompleteSubstitution) if (InstP.isNull() && !IsIncompleteSubstitution)
@@ -5539,9 +5548,15 @@ static TemplateDeductionResult CheckDeductionConsistency(
if (auto *PA = dyn_cast<PackExpansionType>(A); if (auto *PA = dyn_cast<PackExpansionType>(A);
PA && !isa<PackExpansionType>(InstP)) PA && !isa<PackExpansionType>(InstP))
A = PA->getPattern(); A = PA->getPattern();
if (!S.Context.hasSameType( auto T1 = S.Context.getUnqualifiedArrayType(InstP.getNonReferenceType());
S.Context.getUnqualifiedArrayType(InstP.getNonReferenceType()), auto T2 = S.Context.getUnqualifiedArrayType(A.getNonReferenceType());
S.Context.getUnqualifiedArrayType(A.getNonReferenceType()))) if (IsDeductionGuide) {
if (auto *Injected = T1->getAs<InjectedClassNameType>())
T1 = Injected->getInjectedSpecializationType();
if (auto *Injected = T2->getAs<InjectedClassNameType>())
T2 = Injected->getInjectedSpecializationType();
}
if (!S.Context.hasSameType(T1, T2))
return TemplateDeductionResult::NonDeducedMismatch; return TemplateDeductionResult::NonDeducedMismatch;
return TemplateDeductionResult::Success; return TemplateDeductionResult::Success;
} }
@@ -5685,7 +5685,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
}; };
Function->setDeclarationNameLoc(NameLocPointsToPattern()); Function->setDeclarationNameLoc(NameLocPointsToPattern());
EnterExpressionEvaluationContext EvalContext( EnterExpressionEvaluationContextForFunction EvalContext(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
Qualifiers ThisTypeQuals; Qualifiers ThisTypeQuals;
+4 -1
View File
@@ -1768,7 +1768,10 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT,
// Objective-C lifetime, this is a non-trivial assignment. // Objective-C lifetime, this is a non-trivial assignment.
if (LhsT.getNonReferenceType().hasNonTrivialObjCLifetime()) if (LhsT.getNonReferenceType().hasNonTrivialObjCLifetime())
return false; return false;
ASTContext &Context = Self.getASTContext();
if (Context.containsAddressDiscriminatedPointerAuth(LhsT) ||
Context.containsAddressDiscriminatedPointerAuth(RhsT))
return false;
return !Result.get()->hasNonTrivialCall(Self.Context); return !Result.get()->hasNonTrivialCall(Self.Context);
} }
+4
View File
@@ -3103,6 +3103,10 @@ ASTReader::ReadControlBlock(ModuleFile &F,
F.Kind == MK_ImplicitModule) F.Kind == MK_ImplicitModule)
N = ForceValidateUserInputs ? NumUserInputs : 0; N = ForceValidateUserInputs ? NumUserInputs : 0;
if (N != 0)
Diag(diag::remark_module_validation)
<< N << F.ModuleName << F.FileName;
for (unsigned I = 0; I < N; ++I) { for (unsigned I = 0; I < N; ++I) {
InputFile IF = getInputFile(F, I+1, Complain); InputFile IF = getInputFile(F, I+1, Complain);
if (!IF.getFile() || IF.isOutOfDate()) if (!IF.getFile() || IF.isOutOfDate())
+1 -2
View File
@@ -4340,8 +4340,7 @@ class ASTDeclContextNameLookupTrait
// parent of parent. We DON'T remove the enum constant from its parent. So // parent of parent. We DON'T remove the enum constant from its parent. So
// we don't need to care about merging problems here. // we don't need to care about merging problems here.
if (auto *ECD = dyn_cast<EnumConstantDecl>(D); if (auto *ECD = dyn_cast<EnumConstantDecl>(D);
ECD && DC.isFileContext() && ECD->getOwningModule() && ECD && DC.isFileContext() && ECD->getTopLevelOwningNamedModule()) {
ECD->getTopLevelOwningNamedModule()->isNamedModule()) {
if (llvm::all_of( if (llvm::all_of(
DC.noload_lookup( DC.noload_lookup(
cast<EnumDecl>(ECD->getDeclContext())->getDeclName()), cast<EnumDecl>(ECD->getDeclContext())->getDeclName()),
+3 -1
View File
@@ -34,8 +34,10 @@ class CrossProcessModuleCache : public ModuleCache {
} }
std::time_t getModuleTimestamp(StringRef ModuleFilename) override { std::time_t getModuleTimestamp(StringRef ModuleFilename) override {
std::string TimestampFilename =
serialization::ModuleFile::getTimestampFilename(ModuleFilename);
llvm::sys::fs::file_status Status; llvm::sys::fs::file_status Status;
if (llvm::sys::fs::status(ModuleFilename, Status) != std::error_code{}) if (llvm::sys::fs::status(TimestampFilename, Status) != std::error_code{})
return 0; return 0;
return llvm::sys::toTimeT(Status.getLastModificationTime()); return llvm::sys::toTimeT(Status.getLastModificationTime());
} }
@@ -45,7 +45,6 @@ void AssumeModelingChecker::checkPostStmt(const AttributedStmt *A,
continue; continue;
const auto *Assumption = AssumptionVal.getAsInteger(); const auto *Assumption = AssumptionVal.getAsInteger();
assert(Assumption && "We should know the exact outcome of an assume expr");
if (Assumption && Assumption->isZero()) { if (Assumption && Assumption->isZero()) {
C.addSink(); C.addSink();
} }
@@ -916,7 +916,8 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
QualType T = Ex->getTypeOfArgument(); QualType T = Ex->getTypeOfArgument();
for (ExplodedNode *N : CheckedSet) { for (ExplodedNode *N : CheckedSet) {
if (Ex->getKind() == UETT_SizeOf) { if (Ex->getKind() == UETT_SizeOf || Ex->getKind() == UETT_DataSizeOf ||
Ex->getKind() == UETT_CountOf) {
if (!T->isIncompleteType() && !T->isConstantSizeType()) { if (!T->isIncompleteType() && !T->isConstantSizeType()) {
assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
+22 -13
View File
@@ -71,21 +71,30 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
Bldr.takeNodes(Pred); Bldr.takeNodes(Pred);
assert(ThisRD); assert(ThisRD);
SVal V = Call.getArgSVal(0);
const Expr *VExpr = Call.getArgExpr(0);
// If the value being copied is not unknown, load from its location to get if (!ThisRD->isEmpty()) {
// an aggregate rvalue. SVal V = Call.getArgSVal(0);
if (std::optional<Loc> L = V.getAs<Loc>()) const Expr *VExpr = Call.getArgExpr(0);
V = Pred->getState()->getSVal(*L);
else
assert(V.isUnknownOrUndef());
ExplodedNodeSet Tmp; // If the value being copied is not unknown, load from its location to get
evalLocation(Tmp, CallExpr, VExpr, Pred, Pred->getState(), V, // an aggregate rvalue.
/*isLoad=*/true); if (std::optional<Loc> L = V.getAs<Loc>())
for (ExplodedNode *N : Tmp) V = Pred->getState()->getSVal(*L);
evalBind(Dst, CallExpr, N, ThisVal, V, true); else
assert(V.isUnknownOrUndef());
ExplodedNodeSet Tmp;
evalLocation(Tmp, CallExpr, VExpr, Pred, Pred->getState(), V,
/*isLoad=*/true);
for (ExplodedNode *N : Tmp)
evalBind(Dst, CallExpr, N, ThisVal, V, true);
} else {
// We can't copy empty classes because of empty base class optimization.
// In that case, copying the empty base class subobject would overwrite the
// object that it overlaps with - so let's not do that.
// See issue-157467.cpp for an example.
Dst.Add(Pred);
}
PostStmt PS(CallExpr, LCtx); PostStmt PS(CallExpr, LCtx);
for (ExplodedNode *N : Dst) { for (ExplodedNode *N : Dst) {
+2 -2
View File
@@ -264,7 +264,7 @@ END_COMPILERRT_OUTLINE_FUNCTION(NAME(LDNM))
NO_EXEC_STACK_DIRECTIVE NO_EXEC_STACK_DIRECTIVE
// GNU property note for BTI and PAC // GNU property note for BTI, PAC, and GCS
GNU_PROPERTY_BTI_PAC GNU_PROPERTY_BTI_PAC_GCS
#endif // defined(__aarch64__) || defined(__arm64ec__) #endif // defined(__aarch64__) || defined(__arm64ec__)
+2 -2
View File
@@ -371,5 +371,5 @@ END_COMPILERRT_FUNCTION(__arm_sme_restore)
NO_EXEC_STACK_DIRECTIVE NO_EXEC_STACK_DIRECTIVE
// GNU property note for BTI and PAC // GNU property note for BTI, PAC, and GCS
GNU_PROPERTY_BTI_PAC GNU_PROPERTY_BTI_PAC_GCS
+13 -5
View File
@@ -79,11 +79,12 @@
#define FUNC_ALIGN #define FUNC_ALIGN
#endif #endif
// BTI and PAC gnu property note // BTI, PAC, and GCS gnu property note
#define NT_GNU_PROPERTY_TYPE_0 5 #define NT_GNU_PROPERTY_TYPE_0 5
#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 #define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1 #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1
#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2 #define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2
#define GNU_PROPERTY_AARCH64_FEATURE_1_GCS 4
#if defined(__ARM_FEATURE_BTI_DEFAULT) #if defined(__ARM_FEATURE_BTI_DEFAULT)
#define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI #define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
@@ -97,6 +98,12 @@
#define PAC_FLAG 0 #define PAC_FLAG 0
#endif #endif
#if defined(__ARM_FEATURE_GCS_DEFAULT)
#define GCS_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_GCS
#else
#define GCS_FLAG 0
#endif
#define GNU_PROPERTY(type, value) \ #define GNU_PROPERTY(type, value) \
.pushsection .note.gnu.property, "a" SEPARATOR \ .pushsection .note.gnu.property, "a" SEPARATOR \
.p2align 3 SEPARATOR \ .p2align 3 SEPARATOR \
@@ -118,11 +125,12 @@
#define BTI_J #define BTI_J
#endif #endif
#if (BTI_FLAG | PAC_FLAG) != 0 #if (BTI_FLAG | PAC_FLAG | GCS_FLAG) != 0
#define GNU_PROPERTY_BTI_PAC \ #define GNU_PROPERTY_BTI_PAC_GCS \
GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, BTI_FLAG | PAC_FLAG) GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, \
BTI_FLAG | PAC_FLAG | GCS_FLAG)
#else #else
#define GNU_PROPERTY_BTI_PAC #define GNU_PROPERTY_BTI_PAC_GCS
#endif #endif
#if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM) #if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM)

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