update comments

Created using spr 1.3.6
This commit is contained in:
Steven Wu 2025-08-20 10:42:15 -07:00
commit fd9ca0bab8
115 changed files with 2717 additions and 830 deletions

View File

@ -6,7 +6,7 @@ add_subdirectory(support)
# Configure the Features.inc file. # Configure the Features.inc file.
if (NOT DEFINED CLANGD_BUILD_XPC) if (NOT DEFINED CLANGD_BUILD_XPC)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
set(CLANGD_BUILD_XPC_DEFAULT ON) set(CLANGD_BUILD_XPC_DEFAULT ON)
else () else ()
set(CLANGD_BUILD_XPC_DEFAULT OFF) set(CLANGD_BUILD_XPC_DEFAULT OFF)
@ -193,7 +193,7 @@ if(CLANGD_TIDY_CHECKS)
endif() endif()
add_subdirectory(refactor/tweaks) add_subdirectory(refactor/tweaks)
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
# FIXME: Make fuzzer not use linux-specific APIs, build it everywhere. # FIXME: Make fuzzer not use linux-specific APIs, build it everywhere.
add_subdirectory(fuzzer) add_subdirectory(fuzzer)
endif() endif()

View File

@ -731,6 +731,12 @@ TEST_F(TargetDeclTest, BuiltinTemplates) {
using type_pack_element = [[__type_pack_element]]<N, Pack...>; using type_pack_element = [[__type_pack_element]]<N, Pack...>;
)cpp"; )cpp";
EXPECT_DECLS("TemplateSpecializationTypeLoc", ); EXPECT_DECLS("TemplateSpecializationTypeLoc", );
Code = R"cpp(
template <template <class...> class Templ, class... Types>
using dedup_types = Templ<[[__builtin_dedup_pack]]<Types...>...>;
)cpp";
EXPECT_DECLS("TemplateSpecializationTypeLoc", );
} }
TEST_F(TargetDeclTest, MemberOfTemplate) { TEST_F(TargetDeclTest, MemberOfTemplate) {

View File

@ -35,7 +35,7 @@ if(WIN32)
endif() endif()
# The Python FFI interface is broken on AIX: https://bugs.python.org/issue38628. # The Python FFI interface is broken on AIX: https://bugs.python.org/issue38628.
if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") if("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
set(RUN_PYTHON_TESTS FALSE) set(RUN_PYTHON_TESTS FALSE)
endif() endif()

View File

@ -1810,6 +1810,37 @@ __make_integer_seq
This alias returns ``IntSeq`` instantiated with ``IntSeqT = T``and ``Ints`` being the pack ``0, ..., N - 1``. This alias returns ``IntSeq`` instantiated with ``IntSeqT = T``and ``Ints`` being the pack ``0, ..., N - 1``.
__builtin_dedup_pack
--------------------
.. code-block:: c++
template <class... Ts>
using __builtin_dedup_pack = ...;
This alias takes a template parameter pack ``Ts`` and produces a new unexpanded pack containing the unique types
from ``Ts``, with the order of the first occurrence of each type preserved.
It is useful in template metaprogramming to normalize type lists.
The resulting pack can be expanded in contexts like template argument lists or base specifiers.
**Example of Use**:
.. code-block:: c++
template <typename...> struct TypeList;
// The resulting type is TypeList<int, double, char>
template <typename ...ExtraTypes>
using MyTypeList = TypeList<__builtin_dedup_pack<int, double, int, char, double, ExtraTypes...>...>;
**Limitations**:
* This builtin can only be used inside a template.
* The resulting pack is currently only supported for expansion in template argument lists and base specifiers.
* This builtin cannot be assigned to a template template parameter.
Type Trait Primitives Type Trait Primitives
===================== =====================

View File

@ -145,6 +145,22 @@ Non-comprehensive list of changes in this release
correct method to check for these features is to test for the ``__PTRAUTH__`` correct method to check for these features is to test for the ``__PTRAUTH__``
macro. macro.
- Added a new builtin, ``__builtin_dedup_pack``, to remove duplicate types from a parameter pack.
This feature is particularly useful in template metaprogramming for normalizing type lists.
The builtin produces a new, unexpanded parameter pack that can be used in contexts like template
argument lists or base specifiers.
.. code-block:: c++
template <typename...> struct TypeList;
// The resulting type is TypeList<int, double, char>
using MyTypeList = TypeList<__builtin_dedup_pack<int, double, int, char, double>...>;
Currently, the use of ``__builtin_dedup_pack`` is limited to template arguments and base
specifiers, it also must be used within a template context.
New Compiler Flags New Compiler Flags
------------------ ------------------
- New option ``-fno-sanitize-annotate-debug-info-traps`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``). - New option ``-fno-sanitize-annotate-debug-info-traps`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
@ -329,6 +345,9 @@ AST Matchers
- Add a boolean member ``IgnoreSystemHeaders`` to ``MatchFinderOptions``. This - Add a boolean member ``IgnoreSystemHeaders`` to ``MatchFinderOptions``. This
allows it to ignore nodes in system headers when traversing the AST. allows it to ignore nodes in system headers when traversing the AST.
- ``hasConditionVariableStatement`` now supports ``for`` loop, ``while`` loop
and ``switch`` statements.
clang-format clang-format
------------ ------------
- Add ``SpaceInEmptyBraces`` option and set it to ``Always`` for WebKit style. - Add ``SpaceInEmptyBraces`` option and set it to ``Always`` for WebKit style.

View File

@ -230,6 +230,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
SubstTemplateTypeParmTypes; SubstTemplateTypeParmTypes;
mutable llvm::FoldingSet<SubstTemplateTypeParmPackType> mutable llvm::FoldingSet<SubstTemplateTypeParmPackType>
SubstTemplateTypeParmPackTypes; SubstTemplateTypeParmPackTypes;
mutable llvm::FoldingSet<SubstBuiltinTemplatePackType>
SubstBuiltinTemplatePackTypes;
mutable llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&> mutable llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&>
TemplateSpecializationTypes; TemplateSpecializationTypes;
mutable llvm::FoldingSet<ParenType> ParenTypes{GeneralTypesLog2InitSize}; mutable llvm::FoldingSet<ParenType> ParenTypes{GeneralTypesLog2InitSize};
@ -1895,6 +1897,7 @@ public:
QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl, QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl,
unsigned Index, bool Final, unsigned Index, bool Final,
const TemplateArgument &ArgPack); const TemplateArgument &ArgPack);
QualType getSubstBuiltinTemplatePack(const TemplateArgument &ArgPack);
QualType QualType
getTemplateTypeParmType(unsigned Depth, unsigned Index, getTemplateTypeParmType(unsigned Depth, unsigned Index,

View File

@ -1796,7 +1796,10 @@ public:
} }
BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; } BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; }
bool isPackProducingBuiltinTemplate() const;
}; };
bool isPackProducingBuiltinTemplateName(TemplateName N);
/// Provides information about an explicit instantiation of a variable or class /// Provides information about an explicit instantiation of a variable or class
/// template. /// template.

View File

@ -492,6 +492,8 @@ private:
bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
unsigned Count); unsigned Count);
bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
bool TraverseSubstPackTypeHelper(SubstPackType *T);
bool TraverseSubstPackTypeLocHelper(SubstPackTypeLoc TL);
bool TraverseRecordHelper(RecordDecl *D); bool TraverseRecordHelper(RecordDecl *D);
bool TraverseCXXRecordHelper(CXXRecordDecl *D); bool TraverseCXXRecordHelper(CXXRecordDecl *D);
bool TraverseDeclaratorHelper(DeclaratorDecl *D); bool TraverseDeclaratorHelper(DeclaratorDecl *D);
@ -1138,9 +1140,10 @@ DEF_TRAVERSE_TYPE(TemplateTypeParmType, {})
DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, {
TRY_TO(TraverseType(T->getReplacementType())); TRY_TO(TraverseType(T->getReplacementType()));
}) })
DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, { DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType,
TRY_TO(TraverseTemplateArgument(T->getArgumentPack())); { TRY_TO(TraverseSubstPackTypeHelper(T)); })
}) DEF_TRAVERSE_TYPE(SubstBuiltinTemplatePackType,
{ TRY_TO(TraverseSubstPackTypeHelper(T)); })
DEF_TRAVERSE_TYPE(AttributedType, DEF_TRAVERSE_TYPE(AttributedType,
{ TRY_TO(TraverseType(T->getModifiedType())); }) { TRY_TO(TraverseType(T->getModifiedType())); })
@ -1481,9 +1484,26 @@ DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {})
DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, {
TRY_TO(TraverseType(TL.getTypePtr()->getReplacementType())); TRY_TO(TraverseType(TL.getTypePtr()->getReplacementType()));
}) })
DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseSubstPackTypeLocHelper(
SubstPackTypeLoc TL) {
TRY_TO(TraverseTemplateArgument(TL.getTypePtr()->getArgumentPack())); TRY_TO(TraverseTemplateArgument(TL.getTypePtr()->getArgumentPack()));
}) return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseSubstPackTypeHelper(
SubstPackType *T) {
TRY_TO(TraverseTemplateArgument(T->getArgumentPack()));
return true;
}
DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType,
{ TRY_TO(TraverseSubstPackTypeLocHelper(TL)); })
DEF_TRAVERSE_TYPELOC(SubstBuiltinTemplatePackType,
{ TRY_TO(TraverseSubstPackTypeLocHelper(TL)); })
DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); })

View File

@ -2210,20 +2210,24 @@ protected:
unsigned PackIndex : 15; unsigned PackIndex : 15;
}; };
class SubstTemplateTypeParmPackTypeBitfields { class SubstPackTypeBitfields {
friend class SubstPackType;
friend class SubstTemplateTypeParmPackType; friend class SubstTemplateTypeParmPackType;
LLVM_PREFERRED_TYPE(TypeBitfields) LLVM_PREFERRED_TYPE(TypeBitfields)
unsigned : NumTypeBits; unsigned : NumTypeBits;
// The index of the template parameter this substitution represents.
unsigned Index : 16;
/// The number of template arguments in \c Arguments, which is /// The number of template arguments in \c Arguments, which is
/// expected to be able to hold at least 1024 according to [implimits]. /// expected to be able to hold at least 1024 according to [implimits].
/// However as this limit is somewhat easy to hit with template /// However as this limit is somewhat easy to hit with template
/// metaprogramming we'd prefer to keep it as large as possible. /// metaprogramming we'd prefer to keep it as large as possible.
unsigned NumArgs : 16; unsigned NumArgs : 16;
// The index of the template parameter this substitution represents.
// Only used by SubstTemplateTypeParmPackType. We keep it in the same
// class to avoid dealing with complexities of bitfields that go over
// the size of `unsigned`.
unsigned SubstTemplTypeParmPackIndex : 16;
}; };
class TemplateSpecializationTypeBitfields { class TemplateSpecializationTypeBitfields {
@ -2340,7 +2344,7 @@ protected:
VectorTypeBitfields VectorTypeBits; VectorTypeBitfields VectorTypeBits;
TemplateTypeParmTypeBitfields TemplateTypeParmTypeBits; TemplateTypeParmTypeBitfields TemplateTypeParmTypeBits;
SubstTemplateTypeParmTypeBitfields SubstTemplateTypeParmTypeBits; SubstTemplateTypeParmTypeBitfields SubstTemplateTypeParmTypeBits;
SubstTemplateTypeParmPackTypeBitfields SubstTemplateTypeParmPackTypeBits; SubstPackTypeBitfields SubstPackTypeBits;
TemplateSpecializationTypeBitfields TemplateSpecializationTypeBits; TemplateSpecializationTypeBitfields TemplateSpecializationTypeBits;
DependentTemplateSpecializationTypeBitfields DependentTemplateSpecializationTypeBitfields
DependentTemplateSpecializationTypeBits; DependentTemplateSpecializationTypeBits;
@ -6992,6 +6996,56 @@ public:
} }
}; };
/// Represents the result of substituting a set of types as a template argument
/// that needs to be expanded later.
///
/// These types are always dependent and produced depending on the situations:
/// - SubstTemplateTypeParmPack is an expansion that had to be delayed,
/// - SubstBuiltinTemplatePackType is an expansion from a builtin.
class SubstPackType : public Type, public llvm::FoldingSetNode {
friend class ASTContext;
/// A pointer to the set of template arguments that this
/// parameter pack is instantiated with.
const TemplateArgument *Arguments;
protected:
SubstPackType(TypeClass Derived, QualType Canon,
const TemplateArgument &ArgPack);
public:
unsigned getNumArgs() const { return SubstPackTypeBits.NumArgs; }
TemplateArgument getArgumentPack() const;
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
const TemplateArgument &ArgPack);
static bool classof(const Type *T) {
return T->getTypeClass() == SubstTemplateTypeParmPack ||
T->getTypeClass() == SubstBuiltinTemplatePack;
}
};
/// Represents the result of substituting a builtin template as a pack.
class SubstBuiltinTemplatePackType : public SubstPackType {
friend class ASTContext;
SubstBuiltinTemplatePackType(QualType Canon, const TemplateArgument &ArgPack);
public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
/// Mark that we reuse the Profile. We do not introduce new fields.
using SubstPackType::Profile;
static bool classof(const Type *T) {
return T->getTypeClass() == SubstBuiltinTemplatePack;
}
};
/// Represents the result of substituting a set of types for a template /// Represents the result of substituting a set of types for a template
/// type parameter pack. /// type parameter pack.
/// ///
@ -7004,7 +7058,7 @@ public:
/// that pack expansion (e.g., when all template parameters have corresponding /// that pack expansion (e.g., when all template parameters have corresponding
/// arguments), this type will be replaced with the \c SubstTemplateTypeParmType /// arguments), this type will be replaced with the \c SubstTemplateTypeParmType
/// at the current pack substitution index. /// at the current pack substitution index.
class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { class SubstTemplateTypeParmPackType : public SubstPackType {
friend class ASTContext; friend class ASTContext;
/// A pointer to the set of template arguments that this /// A pointer to the set of template arguments that this
@ -7030,21 +7084,17 @@ public:
/// Returns the index of the replaced parameter in the associated declaration. /// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getReplacedParameter()->getIndex()`. /// This should match the result of `getReplacedParameter()->getIndex()`.
unsigned getIndex() const { return SubstTemplateTypeParmPackTypeBits.Index; } unsigned getIndex() const {
return SubstPackTypeBits.SubstTemplTypeParmPackIndex;
}
// This substitution will be Final, which means the substitution will be fully // This substitution will be Final, which means the substitution will be fully
// sugared: it doesn't need to be resugared later. // sugared: it doesn't need to be resugared later.
bool getFinal() const; bool getFinal() const;
unsigned getNumArgs() const {
return SubstTemplateTypeParmPackTypeBits.NumArgs;
}
bool isSugared() const { return false; } bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); } QualType desugar() const { return QualType(this, 0); }
TemplateArgument getArgumentPack() const;
void Profile(llvm::FoldingSetNodeID &ID); void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, const Decl *AssociatedDecl, static void Profile(llvm::FoldingSetNodeID &ID, const Decl *AssociatedDecl,
unsigned Index, bool Final, unsigned Index, bool Final,
@ -7279,9 +7329,7 @@ public:
TemplateSpecializationTypeBits.NumArgs}; TemplateSpecializationTypeBits.NumArgs};
} }
bool isSugared() const { bool isSugared() const;
return !isDependentType() || isCurrentInstantiation() || isTypeAlias();
}
QualType desugar() const { QualType desugar() const {
return isTypeAlias() ? getAliasedType() : getCanonicalTypeInternal(); return isTypeAlias() ? getAliasedType() : getCanonicalTypeInternal();

View File

@ -989,12 +989,22 @@ class SubstTemplateTypeParmTypeLoc :
SubstTemplateTypeParmType> { SubstTemplateTypeParmType> {
}; };
/// Wrapper for substituted template type parameters. /// Abstract type representing delayed type pack expansions.
class SubstTemplateTypeParmPackTypeLoc : class SubstPackTypeLoc
public InheritingConcreteTypeLoc<TypeSpecTypeLoc, : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, SubstPackTypeLoc,
SubstTemplateTypeParmPackTypeLoc, SubstPackType> {};
SubstTemplateTypeParmPackType> {
}; /// Wrapper for substituted template type parameters.
class SubstTemplateTypeParmPackTypeLoc
: public InheritingConcreteTypeLoc<SubstPackTypeLoc,
SubstTemplateTypeParmPackTypeLoc,
SubstTemplateTypeParmPackType> {};
/// Wrapper for substituted template type parameters.
class SubstBuiltinTemplatePackTypeLoc
: public InheritingConcreteTypeLoc<SubstPackTypeLoc,
SubstBuiltinTemplatePackTypeLoc,
SubstBuiltinTemplatePackType> {};
struct AttributedLocInfo { struct AttributedLocInfo {
const Attr *TypeAttr; const Attr *TypeAttr;

View File

@ -820,6 +820,12 @@ let Class = PackExpansionType in {
}]>; }]>;
} }
let Class = SubstPackType in {
def : Property<"replacementPack", TemplateArgument> {
let Read = [{ node->getArgumentPack() }];
}
}
let Class = SubstTemplateTypeParmPackType in { let Class = SubstTemplateTypeParmPackType in {
def : Property<"associatedDecl", DeclRef> { def : Property<"associatedDecl", DeclRef> {
let Read = [{ node->getAssociatedDecl() }]; let Read = [{ node->getAssociatedDecl() }];
@ -827,12 +833,7 @@ let Class = SubstTemplateTypeParmPackType in {
def : Property<"Index", UInt32> { def : Property<"Index", UInt32> {
let Read = [{ node->getIndex() }]; let Read = [{ node->getIndex() }];
} }
def : Property<"Final", Bool> { def : Property<"Final", Bool> { let Read = [{ node->getFinal() }]; }
let Read = [{ node->getFinal() }];
}
def : Property<"replacementPack", TemplateArgument> {
let Read = [{ node->getArgumentPack() }];
}
def : Creator<[{ def : Creator<[{
return ctx.getSubstTemplateTypeParmPackType( return ctx.getSubstTemplateTypeParmPackType(
@ -840,6 +841,12 @@ let Class = SubstTemplateTypeParmPackType in {
}]>; }]>;
} }
let Class = SubstBuiltinTemplatePackType in {
def : Creator<[{
return ctx.getSubstBuiltinTemplatePack(replacementPack);
}]>;
}
let Class = BuiltinType in { let Class = BuiltinType in {
def : Property<"kind", BuiltinTypeKind> { def : Property<"kind", BuiltinTypeKind> {
let Read = [{ node->getKind() }]; let Read = [{ node->getKind() }];

View File

@ -5661,8 +5661,8 @@ AST_POLYMORPHIC_MATCHER_P(hasInitStatement,
return Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder); return Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder);
} }
/// Matches the condition expression of an if statement, for loop, /// Matches the condition expression of an if statement, for loop, while loop,
/// switch statement or conditional operator. /// do-while loop, switch statement or conditional operator.
/// ///
/// Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true)))) /// Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
/// \code /// \code
@ -5747,16 +5747,21 @@ AST_MATCHER_P(Decl, declaresSameEntityAsBoundNode, std::string, ID) {
}); });
} }
/// Matches the condition variable statement in an if statement. /// Matches the condition variable statement in an if statement, for loop,
/// while loop or switch statement.
/// ///
/// Given /// Given
/// \code /// \code
/// if (A* a = GetAPointer()) {} /// if (A* a = GetAPointer()) {}
/// for (; A* a = GetAPointer(); ) {}
/// \endcode /// \endcode
/// hasConditionVariableStatement(...) /// hasConditionVariableStatement(...)
/// matches 'A* a = GetAPointer()'. /// matches both 'A* a = GetAPointer()'.
AST_MATCHER_P(IfStmt, hasConditionVariableStatement, AST_POLYMORPHIC_MATCHER_P(hasConditionVariableStatement,
internal::Matcher<DeclStmt>, InnerMatcher) { AST_POLYMORPHIC_SUPPORTED_TYPES(IfStmt, ForStmt,
WhileStmt,
SwitchStmt),
internal::Matcher<DeclStmt>, InnerMatcher) {
const DeclStmt* const DeclarationStatement = const DeclStmt* const DeclarationStatement =
Node.getConditionVariableDeclStmt(); Node.getConditionVariableDeclStmt();
return DeclarationStatement != nullptr && return DeclarationStatement != nullptr &&

View File

@ -17,6 +17,7 @@
#include "clang/AST/Decl.h" #include "clang/AST/Decl.h"
#include "clang/AST/Type.h" #include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include <cassert> #include <cassert>
@ -152,6 +153,11 @@ public:
return {SyntheticFields.begin(), SyntheticFields.end()}; return {SyntheticFields.begin(), SyntheticFields.end()};
} }
/// Add a synthetic field, if none by that name is already present.
void addSyntheticField(llvm::StringRef Name, StorageLocation &Loc) {
SyntheticFields.insert({Name, &Loc});
}
/// Changes the child storage location for a field `D` of reference type. /// Changes the child storage location for a field `D` of reference type.
/// All other fields cannot change their storage location and always retain /// All other fields cannot change their storage location and always retain
/// the storage location passed to the `RecordStorageLocation` constructor. /// the storage location passed to the `RecordStorageLocation` constructor.
@ -164,6 +170,11 @@ public:
Children[&D] = Loc; Children[&D] = Loc;
} }
/// Add a child storage location for a field `D`, if not already present.
void addChild(const ValueDecl &D, StorageLocation *Loc) {
Children.insert({&D, Loc});
}
llvm::iterator_range<FieldToLoc::const_iterator> children() const { llvm::iterator_range<FieldToLoc::const_iterator> children() const {
return {Children.begin(), Children.end()}; return {Children.begin(), Children.end()};
} }

View File

@ -1632,6 +1632,13 @@ def DeviceKernel : DeclOrTypeAttr {
}]; }];
} }
def SYCLExternal : InheritableAttr {
let Spellings = [CXX11<"clang", "sycl_external">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let LangOpts = [SYCLHost, SYCLDevice];
let Documentation = [SYCLExternalDocs];
}
def SYCLKernelEntryPoint : InheritableAttr { def SYCLKernelEntryPoint : InheritableAttr {
let Spellings = [CXX11<"clang", "sycl_kernel_entry_point">]; let Spellings = [CXX11<"clang", "sycl_kernel_entry_point">];
let Args = [ let Args = [

View File

@ -476,6 +476,47 @@ The SYCL kernel in the previous code sample meets these expectations.
}]; }];
} }
def SYCLExternalDocs : Documentation {
let Category = DocCatFunction;
let Heading = "sycl_external";
let Content = [{
The ``sycl_external`` attribute indicates that a function defined in another
translation unit may be called by a device function defined in the current
translation unit or, if defined in the current translation unit, the function
may be called by device functions defined in other translation units.
The attribute is intended for use in the implementation of the ``SYCL_EXTERNAL``
macro as specified in section 5.10.1, "SYCL functions and member functions
linkage", of the SYCL 2020 specification.
The attribute only appertains to functions and only those that meet the
following requirements:
* Has external linkage
* Is not explicitly defined as deleted (the function may be an explicitly
defaulted function that is defined as deleted)
The attribute shall be present on the first declaration of a function and
may optionally be present on subsequent declarations.
When compiling for a SYCL device target that does not support the generic
address space, the function shall not specify a raw pointer or reference type
as the return type or as a parameter type.
See section 5.10, "SYCL offline linking", of the SYCL 2020 specification.
The following examples demonstrate the use of this attribute:
.. code-block:: c++
[[clang::sycl_external]] void Foo(); // Ok.
[[clang::sycl_external]] void Bar() { /* ... */ } // Ok.
[[clang::sycl_external]] extern void Baz(); // Ok.
[[clang::sycl_external]] static void Quux() { /* ... */ } // error: Quux() has internal linkage.
}];
}
def SYCLKernelEntryPointDocs : Documentation { def SYCLKernelEntryPointDocs : Documentation {
let Category = DocCatFunction; let Category = DocCatFunction;
let Content = [{ let Content = [{

View File

@ -62,3 +62,7 @@ def __builtin_common_type : CPlusPlusBuiltinTemplate<
// typename ...Operands> // typename ...Operands>
def __hlsl_spirv_type : HLSLBuiltinTemplate< def __hlsl_spirv_type : HLSLBuiltinTemplate<
[Uint32T, Uint32T, Uint32T, Class<"Operands", /*is_variadic=*/1>]>; [Uint32T, Uint32T, Uint32T, Class<"Operands", /*is_variadic=*/1>]>;
// template <class ...Args>
def __builtin_dedup_pack
: CPlusPlusBuiltinTemplate<[Class<"Args", /*is_variadic=*/1>]>;

View File

@ -652,6 +652,7 @@ def NonNull : DiagGroup<"nonnull">;
def NonPODVarargs : DiagGroup<"non-pod-varargs">; def NonPODVarargs : DiagGroup<"non-pod-varargs">;
def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>; def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>;
def : DiagGroup<"nonportable-cfstrings">; def : DiagGroup<"nonportable-cfstrings">;
def NonPortableSYCL : DiagGroup<"nonportable-sycl">;
def NonVirtualDtor : DiagGroup<"non-virtual-dtor">; def NonVirtualDtor : DiagGroup<"non-virtual-dtor">;
def GNUNullPointerArithmetic : DiagGroup<"gnu-null-pointer-arithmetic">; def GNUNullPointerArithmetic : DiagGroup<"gnu-null-pointer-arithmetic">;
def NullPointerArithmetic def NullPointerArithmetic

View File

@ -6074,6 +6074,13 @@ def warn_cxx23_pack_indexing : Warning<
def err_pack_outside_template : Error< def err_pack_outside_template : Error<
"pack declaration outside of template">; "pack declaration outside of template">;
def err_builtin_pack_outside_template
: Error<"%0 cannot be used outside of template">;
def err_unsupported_builtin_template_pack_expansion
: Error<"expansions of %0 are not supported here. Only expansions in "
"template arguments and class bases are supported">;
def err_fold_expression_packs_both_sides : Error< def err_fold_expression_packs_both_sides : Error<
"binary fold expression has unexpanded parameter packs in both operands">; "binary fold expression has unexpanded parameter packs in both operands">;
def err_fold_expression_empty : Error< def err_fold_expression_empty : Error<
@ -12951,6 +12958,17 @@ def err_sycl_special_type_num_init_method : Error<
"types with 'sycl_special_class' attribute must have one and only one '__init' " "types with 'sycl_special_class' attribute must have one and only one '__init' "
"method defined">; "method defined">;
// SYCL external attribute diagnostics
def err_sycl_external_invalid_linkage : Error<
"%0 can only be applied to functions with external linkage">;
def err_sycl_external_invalid_main : Error<
"%0 cannot be applied to the 'main' function">;
def err_sycl_external_invalid_deleted_function : Error<
"%0 cannot be applied to an explicitly deleted function">;
def warn_sycl_external_missing_on_first_decl : Warning<
"%0 attribute does not appear on the first declaration">,
InGroup<NonPortableSYCL>;
// SYCL kernel entry point diagnostics // SYCL kernel entry point diagnostics
def err_sycl_entry_point_invalid : Error< def err_sycl_entry_point_invalid : Error<
"the %0 attribute cannot be applied to a" "the %0 attribute cannot be applied to a"
@ -12965,7 +12983,7 @@ def err_sycl_kernel_name_conflict : Error<
"the %0 kernel name argument conflicts with a previous declaration">; "the %0 kernel name argument conflicts with a previous declaration">;
def warn_sycl_kernel_name_not_a_class_type : Warning< def warn_sycl_kernel_name_not_a_class_type : Warning<
"%0 is not a valid SYCL kernel name type; a non-union class type is required">, "%0 is not a valid SYCL kernel name type; a non-union class type is required">,
InGroup<DiagGroup<"nonportable-sycl">>, DefaultError; InGroup<NonPortableSYCL>, DefaultError;
def warn_sycl_entry_point_redundant_declaration : Warning< def warn_sycl_entry_point_redundant_declaration : Warning<
"redundant %0 attribute">, InGroup<RedundantAttribute>; "redundant %0 attribute">, InGroup<RedundantAttribute>;
def err_sycl_entry_point_after_definition : Error< def err_sycl_entry_point_after_definition : Error<

View File

@ -97,7 +97,9 @@ def HLSLAttributedResourceType : TypeNode<Type>;
def HLSLInlineSpirvType : TypeNode<Type>; def HLSLInlineSpirvType : TypeNode<Type>;
def TemplateTypeParmType : TypeNode<Type>, AlwaysDependent, LeafType; def TemplateTypeParmType : TypeNode<Type>, AlwaysDependent, LeafType;
def SubstTemplateTypeParmType : TypeNode<Type>, NeverCanonical; def SubstTemplateTypeParmType : TypeNode<Type>, NeverCanonical;
def SubstTemplateTypeParmPackType : TypeNode<Type>, AlwaysDependent; def SubstPackType : TypeNode<Type, 1>;
def SubstTemplateTypeParmPackType : TypeNode<SubstPackType>, AlwaysDependent;
def SubstBuiltinTemplatePackType : TypeNode<SubstPackType>, AlwaysDependent;
def TemplateSpecializationType : TypeNode<Type>, NeverCanonicalUnlessDependent; def TemplateSpecializationType : TypeNode<Type>, NeverCanonicalUnlessDependent;
def DeducedType : TypeNode<Type, 1>; def DeducedType : TypeNode<Type, 1>;
def AutoType : TypeNode<DeducedType>; def AutoType : TypeNode<DeducedType>;

View File

@ -228,7 +228,9 @@ void threadSafetyCleanup(BeforeSet *Cache);
// FIXME: No way to easily map from TemplateTypeParmTypes to // FIXME: No way to easily map from TemplateTypeParmTypes to
// TemplateTypeParmDecls, so we have this horrible PointerUnion. // TemplateTypeParmDecls, so we have this horrible PointerUnion.
typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType *, NamedDecl *>, typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType *, NamedDecl *,
const TemplateSpecializationType *,
const SubstBuiltinTemplatePackType *>,
SourceLocation> SourceLocation>
UnexpandedParameterPack; UnexpandedParameterPack;
@ -13497,8 +13499,6 @@ public:
~ArgPackSubstIndexRAII() { Self.ArgPackSubstIndex = OldSubstIndex; } ~ArgPackSubstIndexRAII() { Self.ArgPackSubstIndex = OldSubstIndex; }
}; };
friend class ArgumentPackSubstitutionRAII;
void pushCodeSynthesisContext(CodeSynthesisContext Ctx); void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
void popCodeSynthesisContext(); void popCodeSynthesisContext();
@ -14428,6 +14428,15 @@ public:
static void collectUnexpandedParameterPacks( static void collectUnexpandedParameterPacks(
Expr *E, SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); Expr *E, SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
/// Invoked when parsing a template argument.
///
/// \param Arg the template argument, which may already be invalid.
///
/// If it is followed by ellipsis, this function is called before
/// `ActOnPackExpansion`.
ParsedTemplateArgument
ActOnTemplateTemplateArgument(const ParsedTemplateArgument &Arg);
/// Invoked when parsing a template argument followed by an /// Invoked when parsing a template argument followed by an
/// ellipsis, which creates a pack expansion. /// ellipsis, which creates a pack expansion.
/// ///
@ -14515,7 +14524,8 @@ public:
bool CheckParameterPacksForExpansion( bool CheckParameterPacksForExpansion(
SourceLocation EllipsisLoc, SourceRange PatternRange, SourceLocation EllipsisLoc, SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded, ArrayRef<UnexpandedParameterPack> Unexpanded,
const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, const MultiLevelTemplateArgumentList &TemplateArgs,
bool FailOnPackProducingTemplates, bool &ShouldExpand,
bool &RetainExpansion, UnsignedOrNone &NumExpansions); bool &RetainExpansion, UnsignedOrNone &NumExpansions);
/// Determine the number of arguments in the given pack expansion /// Determine the number of arguments in the given pack expansion

View File

@ -71,12 +71,17 @@ inline std::pair<unsigned, unsigned> getDepthAndIndex(const NamedDecl *ND) {
} }
/// Retrieve the depth and index of an unexpanded parameter pack. /// Retrieve the depth and index of an unexpanded parameter pack.
inline std::pair<unsigned, unsigned> /// Returns nullopt when the unexpanded packs do not correspond to template
/// parameters, e.g. __builtin_dedup_types.
inline std::optional<std::pair<unsigned, unsigned>>
getDepthAndIndex(UnexpandedParameterPack UPP) { getDepthAndIndex(UnexpandedParameterPack UPP) {
if (const auto *TTP = dyn_cast<const TemplateTypeParmType *>(UPP.first)) if (const auto *TTP = dyn_cast<const TemplateTypeParmType *>(UPP.first))
return std::make_pair(TTP->getDepth(), TTP->getIndex()); return std::make_pair(TTP->getDepth(), TTP->getIndex());
if (isa<NamedDecl *>(UPP.first))
return getDepthAndIndex(cast<NamedDecl *>(UPP.first)); return getDepthAndIndex(cast<NamedDecl *>(UPP.first));
assert((isa<const TemplateSpecializationType *,
const SubstBuiltinTemplatePackType *>(UPP.first)));
return std::nullopt;
} }
class TypoCorrectionConsumer : public VisibleDeclConsumer { class TypoCorrectionConsumer : public VisibleDeclConsumer {

View File

@ -64,6 +64,7 @@ public:
void handleKernelAttr(Decl *D, const ParsedAttr &AL); void handleKernelAttr(Decl *D, const ParsedAttr &AL);
void handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL); void handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL);
void CheckSYCLExternalFunctionDecl(FunctionDecl *FD);
void CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD); void CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD);
StmtResult BuildSYCLKernelCallStmt(FunctionDecl *FD, CompoundStmt *Body); StmtResult BuildSYCLKernelCallStmt(FunctionDecl *FD, CompoundStmt *Body);
}; };

View File

@ -69,5 +69,6 @@ TYPE_BIT_CODE(ArrayParameter, ARRAY_PARAMETER, 58)
TYPE_BIT_CODE(HLSLAttributedResource, HLSLRESOURCE_ATTRIBUTED, 59) TYPE_BIT_CODE(HLSLAttributedResource, HLSLRESOURCE_ATTRIBUTED, 59)
TYPE_BIT_CODE(HLSLInlineSpirv, HLSL_INLINE_SPIRV, 60) TYPE_BIT_CODE(HLSLInlineSpirv, HLSL_INLINE_SPIRV, 60)
TYPE_BIT_CODE(PredefinedSugar, PREDEFINED_SUGAR, 61) TYPE_BIT_CODE(PredefinedSugar, PREDEFINED_SUGAR, 61)
TYPE_BIT_CODE(SubstBuiltinTemplatePack, SUBST_BUILTIN_TEMPLATE_PACK, 62)
#undef TYPE_BIT_CODE #undef TYPE_BIT_CODE

View File

@ -4306,6 +4306,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
case Type::DependentTemplateSpecialization: case Type::DependentTemplateSpecialization:
case Type::TemplateTypeParm: case Type::TemplateTypeParm:
case Type::SubstTemplateTypeParmPack: case Type::SubstTemplateTypeParmPack:
case Type::SubstBuiltinTemplatePack:
case Type::Auto: case Type::Auto:
case Type::DeducedTemplateSpecialization: case Type::DeducedTemplateSpecialization:
case Type::PackExpansion: case Type::PackExpansion:
@ -5848,7 +5849,6 @@ QualType ASTContext::getSubstTemplateTypeParmType(QualType Replacement,
return QualType(SubstParm, 0); return QualType(SubstParm, 0);
} }
/// Retrieve a
QualType QualType
ASTContext::getSubstTemplateTypeParmPackType(Decl *AssociatedDecl, ASTContext::getSubstTemplateTypeParmPackType(Decl *AssociatedDecl,
unsigned Index, bool Final, unsigned Index, bool Final,
@ -5887,6 +5887,34 @@ ASTContext::getSubstTemplateTypeParmPackType(Decl *AssociatedDecl,
return QualType(SubstParm, 0); return QualType(SubstParm, 0);
} }
QualType
ASTContext::getSubstBuiltinTemplatePack(const TemplateArgument &ArgPack) {
assert(llvm::all_of(ArgPack.pack_elements(),
[](const auto &P) {
return P.getKind() == TemplateArgument::Type;
}) &&
"Pack contains a non-type");
llvm::FoldingSetNodeID ID;
SubstBuiltinTemplatePackType::Profile(ID, ArgPack);
void *InsertPos = nullptr;
if (auto *T =
SubstBuiltinTemplatePackTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(T, 0);
QualType Canon;
TemplateArgument CanonArgPack = getCanonicalTemplateArgument(ArgPack);
if (!CanonArgPack.structurallyEquals(ArgPack))
Canon = getSubstBuiltinTemplatePack(CanonArgPack);
auto *PackType = new (*this, alignof(SubstBuiltinTemplatePackType))
SubstBuiltinTemplatePackType(Canon, ArgPack);
Types.push_back(PackType);
SubstBuiltinTemplatePackTypes.InsertNode(PackType, InsertPos);
return QualType(PackType, 0);
}
/// Retrieve the template type parameter type for a template /// Retrieve the template type parameter type for a template
/// parameter or parameter pack with the given depth, index, and (optionally) /// parameter or parameter pack with the given depth, index, and (optionally)
/// name. /// name.
@ -13099,6 +13127,14 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
if (D->hasAttr<WeakRefAttr>()) if (D->hasAttr<WeakRefAttr>())
return false; return false;
// SYCL device compilation requires that functions defined with the
// sycl_kernel_entry_point or sycl_external attributes be emitted. All
// other entities are emitted only if they are used by a function
// defined with one of those attributes.
if (LangOpts.SYCLIsDevice)
return isa<FunctionDecl>(D) && (D->hasAttr<SYCLKernelEntryPointAttr>() ||
D->hasAttr<SYCLExternalAttr>());
// Aliases and used decls are required. // Aliases and used decls are required.
if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>()) if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
return true; return true;
@ -13108,15 +13144,6 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
if (!FD->doesThisDeclarationHaveABody()) if (!FD->doesThisDeclarationHaveABody())
return FD->doesDeclarationForceExternallyVisibleDefinition(); return FD->doesDeclarationForceExternallyVisibleDefinition();
// Function definitions with the sycl_kernel_entry_point attribute are
// required during device compilation so that SYCL kernel caller offload
// entry points are emitted.
if (LangOpts.SYCLIsDevice && FD->hasAttr<SYCLKernelEntryPointAttr>())
return true;
// FIXME: Functions declared with SYCL_EXTERNAL are required during
// device compilation.
// Constructors and destructors are required. // Constructors and destructors are required.
if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>()) if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
return true; return true;
@ -14045,6 +14072,7 @@ static QualType getCommonNonSugarTypeNode(const ASTContext &Ctx, const Type *X,
SUGAR_FREE_TYPE(BitInt) SUGAR_FREE_TYPE(BitInt)
SUGAR_FREE_TYPE(ObjCInterface) SUGAR_FREE_TYPE(ObjCInterface)
SUGAR_FREE_TYPE(SubstTemplateTypeParmPack) SUGAR_FREE_TYPE(SubstTemplateTypeParmPack)
SUGAR_FREE_TYPE(SubstBuiltinTemplatePack)
SUGAR_FREE_TYPE(UnresolvedUsing) SUGAR_FREE_TYPE(UnresolvedUsing)
SUGAR_FREE_TYPE(HLSLAttributedResource) SUGAR_FREE_TYPE(HLSLAttributedResource)
SUGAR_FREE_TYPE(HLSLInlineSpirv) SUGAR_FREE_TYPE(HLSLInlineSpirv)

View File

@ -1842,6 +1842,14 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType(
*ReplacedOrErr, T->getIndex(), T->getFinal(), *ToArgumentPack); *ReplacedOrErr, T->getIndex(), T->getFinal(), *ToArgumentPack);
} }
ExpectedType ASTNodeImporter::VisitSubstBuiltinTemplatePackType(
const SubstBuiltinTemplatePackType *T) {
Expected<TemplateArgument> ToArgumentPack = import(T->getArgumentPack());
if (!ToArgumentPack)
return ToArgumentPack.takeError();
return Importer.getToContext().getSubstBuiltinTemplatePack(*ToArgumentPack);
}
ExpectedType ASTNodeImporter::VisitTemplateSpecializationType( ExpectedType ASTNodeImporter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) { const TemplateSpecializationType *T) {
auto ToTemplateOrErr = import(T->getTemplateName()); auto ToTemplateOrErr = import(T->getTemplateName());

View File

@ -1337,6 +1337,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break; break;
} }
case Type::SubstBuiltinTemplatePack: {
const auto *Subst1 = cast<SubstBuiltinTemplatePackType>(T1);
const auto *Subst2 = cast<SubstBuiltinTemplatePackType>(T2);
if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(),
Subst2->getArgumentPack()))
return false;
break;
}
case Type::SubstTemplateTypeParmPack: { case Type::SubstTemplateTypeParmPack: {
const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1); const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2); const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);

View File

@ -1830,6 +1830,7 @@ static bool interp__builtin_elementwise_countzeroes(InterpState &S,
assert(Call->getArg(1)->getType()->isVectorType() && assert(Call->getArg(1)->getType()->isVectorType() &&
ASTCtx.hasSameUnqualifiedType(Call->getArg(0)->getType(), ASTCtx.hasSameUnqualifiedType(Call->getArg(0)->getType(),
Call->getArg(1)->getType())); Call->getArg(1)->getType()));
(void)ASTCtx;
ZeroArg = S.Stk.pop<Pointer>(); ZeroArg = S.Stk.pop<Pointer>();
assert(ZeroArg.getFieldDesc()->isPrimitiveArray()); assert(ZeroArg.getFieldDesc()->isPrimitiveArray());
} }
@ -2728,6 +2729,8 @@ static bool interp__builtin_elementwise_fma(InterpState &S, CodePtr OpPC,
if (!Arg1Type->isVectorType()) { if (!Arg1Type->isVectorType()) {
assert(!Arg2Type->isVectorType()); assert(!Arg2Type->isVectorType());
assert(!Arg3Type->isVectorType()); assert(!Arg3Type->isVectorType());
(void)Arg2Type;
(void)Arg3Type;
const Floating &Z = S.Stk.pop<Floating>(); const Floating &Z = S.Stk.pop<Floating>();
const Floating &Y = S.Stk.pop<Floating>(); const Floating &Y = S.Stk.pop<Floating>();
@ -2753,6 +2756,7 @@ static bool interp__builtin_elementwise_fma(InterpState &S, CodePtr OpPC,
assert(NumElems == Arg2Type->castAs<VectorType>()->getNumElements() && assert(NumElems == Arg2Type->castAs<VectorType>()->getNumElements() &&
NumElems == Arg3Type->castAs<VectorType>()->getNumElements()); NumElems == Arg3Type->castAs<VectorType>()->getNumElements());
assert(ElemT->isRealFloatingType()); assert(ElemT->isRealFloatingType());
(void)ElemT;
const Pointer &VZ = S.Stk.pop<Pointer>(); const Pointer &VZ = S.Stk.pop<Pointer>();
const Pointer &VY = S.Stk.pop<Pointer>(); const Pointer &VY = S.Stk.pop<Pointer>();

View File

@ -307,8 +307,9 @@ bool TemplateDecl::hasAssociatedConstraints() const {
bool TemplateDecl::isTypeAlias() const { bool TemplateDecl::isTypeAlias() const {
switch (getKind()) { switch (getKind()) {
case TemplateDecl::TypeAliasTemplate: case TemplateDecl::TypeAliasTemplate:
case TemplateDecl::BuiltinTemplate:
return true; return true;
case TemplateDecl::BuiltinTemplate:
return !cast<BuiltinTemplateDecl>(this)->isPackProducingBuiltinTemplate();
default: default:
return false; return false;
}; };
@ -1598,6 +1599,16 @@ BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
createBuiltinTemplateParameterList(C, DC, BTK)), createBuiltinTemplateParameterList(C, DC, BTK)),
BTK(BTK) {} BTK(BTK) {}
bool BuiltinTemplateDecl::isPackProducingBuiltinTemplate() const {
return getBuiltinTemplateKind() == clang::BTK__builtin_dedup_pack;
}
bool clang::isPackProducingBuiltinTemplateName(TemplateName N) {
auto *T = dyn_cast_or_null<BuiltinTemplateDecl>(
N.getAsTemplateDecl(/*IgnoreDeduced=*/true));
return T && T->isPackProducingBuiltinTemplate();
}
TemplateParamObjectDecl *TemplateParamObjectDecl::Create(const ASTContext &C, TemplateParamObjectDecl *TemplateParamObjectDecl::Create(const ASTContext &C,
QualType T, QualType T,
const APValue &V) { const APValue &V) {

View File

@ -2444,6 +2444,13 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::CountAttributed: case Type::CountAttributed:
llvm_unreachable("type is illegal as a nested name specifier"); llvm_unreachable("type is illegal as a nested name specifier");
case Type::SubstBuiltinTemplatePack:
// FIXME: not clear how to mangle this!
// template <class T...> class A {
// template <class U...> void foo(__builtin_dedup_pack<T...>(*)(U) x...);
// };
Out << "_SUBSTBUILTINPACK_";
break;
case Type::SubstTemplateTypeParmPack: case Type::SubstTemplateTypeParmPack:
// FIXME: not clear how to mangle this! // FIXME: not clear how to mangle this!
// template <class T...> class A { // template <class T...> class A {
@ -3891,6 +3898,14 @@ void CXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T) {
Out << "_SUBSTPACK_"; Out << "_SUBSTPACK_";
} }
void CXXNameMangler::mangleType(const SubstBuiltinTemplatePackType *T) {
// FIXME: not clear how to mangle this!
// template <class T...> class A {
// template <class U...> void foo(__builtin_dedup_pack<T...>(*)(U) x...);
// };
Out << "_SUBSTBUILTINPACK_";
}
// <type> ::= P <type> # pointer-to // <type> ::= P <type> # pointer-to
void CXXNameMangler::mangleType(const PointerType *T) { void CXXNameMangler::mangleType(const PointerType *T) {
Out << 'P'; Out << 'P';

View File

@ -3383,6 +3383,11 @@ void MicrosoftCXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T,
Error(Range.getBegin(), "substituted parameter pack") << Range; Error(Range.getBegin(), "substituted parameter pack") << Range;
} }
void MicrosoftCXXNameMangler::mangleType(const SubstBuiltinTemplatePackType *T,
Qualifiers, SourceRange Range) {
Error(Range.getBegin(), "substituted builtin template pack") << Range;
}
// <type> ::= <pointer-type> // <type> ::= <pointer-type>
// <pointer-type> ::= E? <pointer-cvr-qualifiers> <cvr-qualifiers> <type> // <pointer-type> ::= E? <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
// # the E is required for 64-bit non-static pointers // # the E is required for 64-bit non-static pointers

View File

@ -4558,17 +4558,45 @@ void SubstTemplateTypeParmType::Profile(llvm::FoldingSetNodeID &ID,
ID.AddBoolean(Final); ID.AddBoolean(Final);
} }
SubstPackType::SubstPackType(TypeClass Derived, QualType Canon,
const TemplateArgument &ArgPack)
: Type(Derived, Canon,
TypeDependence::DependentInstantiation |
TypeDependence::UnexpandedPack),
Arguments(ArgPack.pack_begin()) {
assert(llvm::all_of(
ArgPack.pack_elements(),
[](auto &P) { return P.getKind() == TemplateArgument::Type; }) &&
"non-type argument to SubstPackType?");
SubstPackTypeBits.NumArgs = ArgPack.pack_size();
}
TemplateArgument SubstPackType::getArgumentPack() const {
return TemplateArgument(llvm::ArrayRef(Arguments, getNumArgs()));
}
void SubstPackType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getArgumentPack());
}
void SubstPackType::Profile(llvm::FoldingSetNodeID &ID,
const TemplateArgument &ArgPack) {
ID.AddInteger(ArgPack.pack_size());
for (const auto &P : ArgPack.pack_elements())
ID.AddPointer(P.getAsType().getAsOpaquePtr());
}
SubstTemplateTypeParmPackType::SubstTemplateTypeParmPackType( SubstTemplateTypeParmPackType::SubstTemplateTypeParmPackType(
QualType Canon, Decl *AssociatedDecl, unsigned Index, bool Final, QualType Canon, Decl *AssociatedDecl, unsigned Index, bool Final,
const TemplateArgument &ArgPack) const TemplateArgument &ArgPack)
: Type(SubstTemplateTypeParmPack, Canon, : SubstPackType(SubstTemplateTypeParmPack, Canon, ArgPack),
TypeDependence::DependentInstantiation |
TypeDependence::UnexpandedPack),
Arguments(ArgPack.pack_begin()),
AssociatedDeclAndFinal(AssociatedDecl, Final) { AssociatedDeclAndFinal(AssociatedDecl, Final) {
SubstTemplateTypeParmPackTypeBits.Index = Index;
SubstTemplateTypeParmPackTypeBits.NumArgs = ArgPack.pack_size();
assert(AssociatedDecl != nullptr); assert(AssociatedDecl != nullptr);
SubstPackTypeBits.SubstTemplTypeParmPackIndex = Index;
assert(getNumArgs() == ArgPack.pack_size() &&
"Parent bitfields in SubstPackType were overwritten."
"Check NumSubstPackTypeBits.");
} }
Decl *SubstTemplateTypeParmPackType::getAssociatedDecl() const { Decl *SubstTemplateTypeParmPackType::getAssociatedDecl() const {
@ -4588,10 +4616,6 @@ IdentifierInfo *SubstTemplateTypeParmPackType::getIdentifier() const {
return getReplacedParameter()->getIdentifier(); return getReplacedParameter()->getIdentifier();
} }
TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const {
return TemplateArgument(llvm::ArrayRef(Arguments, getNumArgs()));
}
void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) { void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getAssociatedDecl(), getIndex(), getFinal(), getArgumentPack()); Profile(ID, getAssociatedDecl(), getIndex(), getFinal(), getArgumentPack());
} }
@ -4603,11 +4627,13 @@ void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID,
ID.AddPointer(AssociatedDecl); ID.AddPointer(AssociatedDecl);
ID.AddInteger(Index); ID.AddInteger(Index);
ID.AddBoolean(Final); ID.AddBoolean(Final);
ID.AddInteger(ArgPack.pack_size()); SubstPackType::Profile(ID, ArgPack);
for (const auto &P : ArgPack.pack_elements())
ID.AddPointer(P.getAsType().getAsOpaquePtr());
} }
SubstBuiltinTemplatePackType::SubstBuiltinTemplatePackType(
QualType Canon, const TemplateArgument &ArgPack)
: SubstPackType(SubstBuiltinTemplatePack, Canon, ArgPack) {}
bool TemplateSpecializationType::anyDependentTemplateArguments( bool TemplateSpecializationType::anyDependentTemplateArguments(
const TemplateArgumentListInfo &Args, const TemplateArgumentListInfo &Args,
ArrayRef<TemplateArgument> Converted) { ArrayRef<TemplateArgument> Converted) {
@ -4631,18 +4657,28 @@ bool TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
return false; return false;
} }
static TypeDependence
getTemplateSpecializationTypeDependence(QualType Underlying, TemplateName T) {
TypeDependence D = Underlying.isNull()
? TypeDependence::DependentInstantiation
: toSemanticDependence(Underlying->getDependence());
D |= toTypeDependence(T.getDependence()) & TypeDependence::UnexpandedPack;
if (isPackProducingBuiltinTemplateName(T)) {
if (Underlying.isNull()) // Dependent, will produce a pack on substitution.
D |= TypeDependence::UnexpandedPack;
else
D |= (Underlying->getDependence() & TypeDependence::UnexpandedPack);
}
return D;
}
TemplateSpecializationType::TemplateSpecializationType( TemplateSpecializationType::TemplateSpecializationType(
ElaboratedTypeKeyword Keyword, TemplateName T, bool IsAlias, ElaboratedTypeKeyword Keyword, TemplateName T, bool IsAlias,
ArrayRef<TemplateArgument> Args, QualType Underlying) ArrayRef<TemplateArgument> Args, QualType Underlying)
: TypeWithKeyword( : TypeWithKeyword(Keyword, TemplateSpecialization,
Keyword, TemplateSpecialization, Underlying.isNull() ? QualType(this, 0)
Underlying.isNull() ? QualType(this, 0) : Underlying.getCanonicalType(),
: Underlying.getCanonicalType(), getTemplateSpecializationTypeDependence(Underlying, T)),
(Underlying.isNull()
? TypeDependence::DependentInstantiation
: toSemanticDependence(Underlying->getDependence())) |
(toTypeDependence(T.getDependence()) &
TypeDependence::UnexpandedPack)),
Template(T) { Template(T) {
TemplateSpecializationTypeBits.NumArgs = Args.size(); TemplateSpecializationTypeBits.NumArgs = Args.size();
TemplateSpecializationTypeBits.TypeAlias = IsAlias; TemplateSpecializationTypeBits.TypeAlias = IsAlias;
@ -4688,6 +4724,12 @@ QualType TemplateSpecializationType::getAliasedType() const {
return *reinterpret_cast<const QualType *>(template_arguments().end()); return *reinterpret_cast<const QualType *>(template_arguments().end());
} }
bool clang::TemplateSpecializationType::isSugared() const {
return !isDependentType() || isCurrentInstantiation() || isTypeAlias() ||
(isPackProducingBuiltinTemplateName(Template) &&
isa<SubstBuiltinTemplatePackType>(*getCanonicalTypeInternal()));
}
void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Ctx) { const ASTContext &Ctx) {
Profile(ID, Template, template_arguments(), Profile(ID, Template, template_arguments(),
@ -5103,6 +5145,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
case Type::UnaryTransform: case Type::UnaryTransform:
case Type::TemplateTypeParm: case Type::TemplateTypeParm:
case Type::SubstTemplateTypeParmPack: case Type::SubstTemplateTypeParmPack:
case Type::SubstBuiltinTemplatePack:
case Type::DependentName: case Type::DependentName:
case Type::DependentTemplateSpecialization: case Type::DependentTemplateSpecialization:
case Type::Auto: case Type::Auto:

View File

@ -232,6 +232,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::Enum: case Type::Enum:
case Type::TemplateTypeParm: case Type::TemplateTypeParm:
case Type::SubstTemplateTypeParmPack: case Type::SubstTemplateTypeParmPack:
case Type::SubstBuiltinTemplatePack:
case Type::DeducedTemplateSpecialization: case Type::DeducedTemplateSpecialization:
case Type::TemplateSpecialization: case Type::TemplateSpecialization:
case Type::InjectedClassName: case Type::InjectedClassName:
@ -1731,6 +1732,15 @@ void TypePrinter::printSubstTemplateTypeParmAfter(
printAfter(T->getReplacementType(), OS); printAfter(T->getReplacementType(), OS);
} }
void TypePrinter::printSubstBuiltinTemplatePackBefore(
const SubstBuiltinTemplatePackType *T, raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
OS << "type-pack";
}
void TypePrinter::printSubstBuiltinTemplatePackAfter(
const SubstBuiltinTemplatePackType *T, raw_ostream &OS) {}
void TypePrinter::printSubstTemplateTypeParmPackBefore( void TypePrinter::printSubstTemplateTypeParmPackBefore(
const SubstTemplateTypeParmPackType *T, const SubstTemplateTypeParmPackType *T,
raw_ostream &OS) { raw_ostream &OS) {

View File

@ -20,14 +20,17 @@
#include "clang/AST/OperationKinds.h" #include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h" #include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h" #include "clang/AST/StmtVisitor.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/FlowSensitive/ASTOps.h" #include "clang/Analysis/FlowSensitive/ASTOps.h"
#include "clang/Analysis/FlowSensitive/AdornedCFG.h" #include "clang/Analysis/FlowSensitive/AdornedCFG.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/NoopAnalysis.h" #include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
#include "clang/Analysis/FlowSensitive/RecordOps.h" #include "clang/Analysis/FlowSensitive/RecordOps.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "clang/Analysis/FlowSensitive/Value.h" #include "clang/Analysis/FlowSensitive/Value.h"
#include "clang/Basic/Builtins.h" #include "clang/Basic/Builtins.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h" #include "clang/Basic/OperatorKinds.h"
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include <assert.h> #include <assert.h>
@ -287,7 +290,7 @@ public:
} }
} }
void VisitImplicitCastExpr(const ImplicitCastExpr *S) { void VisitCastExpr(const CastExpr *S) {
const Expr *SubExpr = S->getSubExpr(); const Expr *SubExpr = S->getSubExpr();
assert(SubExpr != nullptr); assert(SubExpr != nullptr);
@ -317,6 +320,60 @@ public:
break; break;
} }
case CK_BaseToDerived: {
// This is a cast of (single-layer) pointer or reference to a record type.
// We should now model the fields for the derived type.
// Get the RecordStorageLocation for the record object underneath.
RecordStorageLocation *Loc = nullptr;
if (S->getType()->isPointerType()) {
auto *PV = Env.get<PointerValue>(*SubExpr);
assert(PV != nullptr);
if (PV == nullptr)
break;
Loc = cast<RecordStorageLocation>(&PV->getPointeeLoc());
} else {
assert(S->getType()->isRecordType());
if (SubExpr->isGLValue()) {
Loc = Env.get<RecordStorageLocation>(*SubExpr);
} else {
Loc = &Env.getResultObjectLocation(*SubExpr);
}
}
if (!Loc) {
// Nowhere to add children or propagate from, so we're done.
break;
}
// Get the derived record type underneath the reference or pointer.
QualType Derived = S->getType().getNonReferenceType();
if (Derived->isPointerType()) {
Derived = Derived->getPointeeType();
}
// Add children to the storage location for fields (including synthetic
// fields) of the derived type and initialize their values.
for (const FieldDecl *Field :
Env.getDataflowAnalysisContext().getModeledFields(Derived)) {
assert(Field != nullptr);
QualType FieldType = Field->getType();
if (FieldType->isReferenceType()) {
Loc->addChild(*Field, nullptr);
} else {
Loc->addChild(*Field, &Env.createStorageLocation(FieldType));
}
for (const auto &Entry :
Env.getDataflowAnalysisContext().getSyntheticFields(Derived)) {
Loc->addSyntheticField(Entry.getKey(),
Env.createStorageLocation(Entry.getValue()));
}
}
Env.initializeFieldsWithValues(*Loc, Derived);
// Fall through to propagate SubExpr's StorageLocation to the CastExpr.
[[fallthrough]];
}
case CK_IntegralCast: case CK_IntegralCast:
// FIXME: This cast creates a new integral value from the // FIXME: This cast creates a new integral value from the
// subexpression. But, because we don't model integers, we don't // subexpression. But, because we don't model integers, we don't
@ -324,10 +381,9 @@ public:
// modeling is added, then update this code to create a fresh location and // modeling is added, then update this code to create a fresh location and
// value. // value.
case CK_UncheckedDerivedToBase: case CK_UncheckedDerivedToBase:
case CK_DerivedToBase:
case CK_ConstructorConversion: case CK_ConstructorConversion:
case CK_UserDefinedConversion: case CK_UserDefinedConversion:
// FIXME: Add tests that excercise CK_UncheckedDerivedToBase,
// CK_ConstructorConversion, and CK_UserDefinedConversion.
case CK_NoOp: { case CK_NoOp: {
// FIXME: Consider making `Environment::getStorageLocation` skip noop // FIXME: Consider making `Environment::getStorageLocation` skip noop
// expressions (this and other similar expressions in the file) instead // expressions (this and other similar expressions in the file) instead
@ -684,15 +740,6 @@ public:
propagateValue(*SubExpr, *S, Env); propagateValue(*SubExpr, *S, Env);
} }
void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {
if (S->getCastKind() == CK_NoOp) {
const Expr *SubExpr = S->getSubExpr();
assert(SubExpr != nullptr);
propagateValueOrStorageLocation(*SubExpr, *S, Env);
}
}
void VisitConditionalOperator(const ConditionalOperator *S) { void VisitConditionalOperator(const ConditionalOperator *S) {
const Environment *TrueEnv = StmtToEnv.getEnvironment(*S->getTrueExpr()); const Environment *TrueEnv = StmtToEnv.getEnvironment(*S->getTrueExpr());
const Environment *FalseEnv = StmtToEnv.getEnvironment(*S->getFalseExpr()); const Environment *FalseEnv = StmtToEnv.getEnvironment(*S->getFalseExpr());

View File

@ -1310,6 +1310,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
} }
} }
Result = Actions.ActOnTemplateTemplateArgument(Result);
// If this is a pack expansion, build it as such. // If this is a pack expansion, build it as such.
if (EllipsisLoc.isValid() && !Result.isInvalid()) if (EllipsisLoc.isValid() && !Result.isInvalid())
Result = Actions.ActOnPackExpansion(Result, EllipsisLoc); Result = Actions.ActOnPackExpansion(Result, EllipsisLoc);

View File

@ -307,7 +307,8 @@ static UnsignedOrNone EvaluateFoldExpandedConstraintSize(
UnsignedOrNone NumExpansions = FE->getNumExpansions(); UnsignedOrNone NumExpansions = FE->getNumExpansions();
if (S.CheckParameterPacksForExpansion( if (S.CheckParameterPacksForExpansion(
FE->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL, FE->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL,
Expand, RetainExpansion, NumExpansions) || /*FailOnPackProducingTemplates=*/true, Expand, RetainExpansion,
NumExpansions) ||
!Expand || RetainExpansion) !Expand || RetainExpansion)
return std::nullopt; return std::nullopt;
@ -1696,11 +1697,13 @@ bool FoldExpandedConstraint::AreCompatibleForSubsumption(
Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(B.Pattern), BPacks); Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(B.Pattern), BPacks);
for (const UnexpandedParameterPack &APack : APacks) { for (const UnexpandedParameterPack &APack : APacks) {
std::pair<unsigned, unsigned> DepthAndIndex = getDepthAndIndex(APack); auto ADI = getDepthAndIndex(APack);
auto it = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) { if (!ADI)
return getDepthAndIndex(BPack) == DepthAndIndex; continue;
auto It = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
return getDepthAndIndex(BPack) == ADI;
}); });
if (it != BPacks.end()) if (It != BPacks.end())
return true; return true;
} }
return false; return false;

View File

@ -3115,6 +3115,10 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
cast<SYCLKernelEntryPointAttr>(NewAttribute)->setInvalidAttr(); cast<SYCLKernelEntryPointAttr>(NewAttribute)->setInvalidAttr();
++I; ++I;
continue; continue;
} else if (isa<SYCLExternalAttr>(NewAttribute)) {
// SYCLExternalAttr may be added after a definition.
++I;
continue;
} }
S.Diag(NewAttribute->getLocation(), S.Diag(NewAttribute->getLocation(),
@ -4140,6 +4144,18 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S,
diag::note_carries_dependency_missing_first_decl) << 0/*Function*/; diag::note_carries_dependency_missing_first_decl) << 0/*Function*/;
} }
// SYCL 2020 section 5.10.1, "SYCL functions and member functions linkage":
// When a function is declared with SYCL_EXTERNAL, that macro must be
// used on the first declaration of that function in the translation unit.
// Redeclarations of the function in the same translation unit may
// optionally use SYCL_EXTERNAL, but this is not required.
const SYCLExternalAttr *SEA = New->getAttr<SYCLExternalAttr>();
if (SEA && !Old->hasAttr<SYCLExternalAttr>()) {
Diag(SEA->getLocation(), diag::warn_sycl_external_missing_on_first_decl)
<< SEA;
Diag(Old->getLocation(), diag::note_previous_declaration);
}
// (C++98 8.3.5p3): // (C++98 8.3.5p3):
// All declarations for a function shall agree exactly in both the // All declarations for a function shall agree exactly in both the
// return type and the parameter-type-list. // return type and the parameter-type-list.
@ -12325,6 +12341,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (NewFD->hasAttr<SYCLKernelEntryPointAttr>()) if (NewFD->hasAttr<SYCLKernelEntryPointAttr>())
SYCL().CheckSYCLEntryPointFunctionDecl(NewFD); SYCL().CheckSYCLEntryPointFunctionDecl(NewFD);
if (NewFD->hasAttr<SYCLExternalAttr>())
SYCL().CheckSYCLExternalFunctionDecl(NewFD);
// Semantic checking for this function declaration (in isolation). // Semantic checking for this function declaration (in isolation).
if (getLangOpts().CPlusPlus) { if (getLangOpts().CPlusPlus) {
@ -12513,6 +12532,13 @@ void Sema::CheckMain(FunctionDecl *FD, const DeclSpec &DS) {
return; return;
} }
if (FD->hasAttr<SYCLExternalAttr>()) {
Diag(FD->getLocation(), diag::err_sycl_external_invalid_main)
<< FD->getAttr<SYCLExternalAttr>();
FD->setInvalidDecl();
return;
}
// Functions named main in hlsl are default entries, but don't have specific // Functions named main in hlsl are default entries, but don't have specific
// signatures they are required to conform to. // signatures they are required to conform to.
if (getLangOpts().HLSL) if (getLangOpts().HLSL)
@ -16351,6 +16377,14 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, bool IsInstantiation,
} }
} }
if (FD && !FD->isInvalidDecl() && FD->hasAttr<SYCLExternalAttr>()) {
SYCLExternalAttr *SEAttr = FD->getAttr<SYCLExternalAttr>();
if (FD->isDeletedAsWritten())
Diag(SEAttr->getLocation(),
diag::err_sycl_external_invalid_deleted_function)
<< SEAttr;
}
{ {
// Do not call PopExpressionEvaluationContext() if it is a lambda because // Do not call PopExpressionEvaluationContext() if it is a lambda because
// one is already popped when finishing the lambda in BuildLambdaExpr(). // one is already popped when finishing the lambda in BuildLambdaExpr().

View File

@ -7061,6 +7061,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_EnumExtensibility: case ParsedAttr::AT_EnumExtensibility:
handleEnumExtensibilityAttr(S, D, AL); handleEnumExtensibilityAttr(S, D, AL);
break; break;
case ParsedAttr::AT_SYCLExternal:
handleSimpleAttribute<SYCLExternalAttr>(S, D, AL);
break;
case ParsedAttr::AT_SYCLKernelEntryPoint: case ParsedAttr::AT_SYCLKernelEntryPoint:
S.SYCL().handleKernelEntryPointAttr(D, AL); S.SYCL().handleKernelEntryPointAttr(D, AL);
break; break;

View File

@ -18005,7 +18005,8 @@ DeclResult Sema::ActOnTemplatedFriendTag(
collectUnexpandedParameterPacks(QualifierLoc, Unexpanded); collectUnexpandedParameterPacks(QualifierLoc, Unexpanded);
unsigned FriendDeclDepth = TempParamLists.front()->getDepth(); unsigned FriendDeclDepth = TempParamLists.front()->getDepth();
for (UnexpandedParameterPack &U : Unexpanded) { for (UnexpandedParameterPack &U : Unexpanded) {
if (getDepthAndIndex(U).first >= FriendDeclDepth) { if (std::optional<std::pair<unsigned, unsigned>> DI = getDepthAndIndex(U);
DI && DI->first >= FriendDeclDepth) {
auto *ND = dyn_cast<NamedDecl *>(U.first); auto *ND = dyn_cast<NamedDecl *>(U.first);
if (!ND) if (!ND)
ND = cast<const TemplateTypeParmType *>(U.first)->getDecl(); ND = cast<const TemplateTypeParmType *>(U.first)->getDecl();

View File

@ -250,6 +250,23 @@ static bool CheckSYCLKernelName(Sema &S, SourceLocation Loc,
return false; return false;
} }
void SemaSYCL::CheckSYCLExternalFunctionDecl(FunctionDecl *FD) {
const auto *SEAttr = FD->getAttr<SYCLExternalAttr>();
assert(SEAttr && "Missing sycl_external attribute");
if (!FD->isInvalidDecl() && !FD->isTemplated()) {
if (!FD->isExternallyVisible())
if (!FD->isFunctionTemplateSpecialization() ||
FD->getTemplateSpecializationInfo()->isExplicitSpecialization())
Diag(SEAttr->getLocation(), diag::err_sycl_external_invalid_linkage)
<< SEAttr;
}
if (FD->isDeletedAsWritten()) {
Diag(SEAttr->getLocation(),
diag::err_sycl_external_invalid_deleted_function)
<< SEAttr;
}
}
void SemaSYCL::CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD) { void SemaSYCL::CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD) {
// Ensure that all attributes present on the declaration are consistent // Ensure that all attributes present on the declaration are consistent
// and warn about any redundant ones. // and warn about any redundant ones.

View File

@ -19,6 +19,7 @@
#include "clang/AST/ExprCXX.h" #include "clang/AST/ExprCXX.h"
#include "clang/AST/TemplateName.h" #include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h" #include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/AST/TypeVisitor.h" #include "clang/AST/TypeVisitor.h"
#include "clang/Basic/Builtins.h" #include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/DiagnosticSema.h"
@ -316,6 +317,12 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
} }
} }
if (isPackProducingBuiltinTemplateName(Template) &&
S->getTemplateParamParent() == nullptr)
Diag(Name.getBeginLoc(), diag::err_builtin_pack_outside_template) << TName;
// Recover by returning the template, even though we would never be able to
// substitute it.
TemplateResult = TemplateTy::make(Template); TemplateResult = TemplateTy::make(Template);
return TemplateKind; return TemplateKind;
} }
@ -3477,6 +3484,28 @@ static QualType checkBuiltinTemplateIdType(
return Context.getHLSLInlineSpirvType(Opcode, Size, Alignment, Operands); return Context.getHLSLInlineSpirvType(Opcode, Size, Alignment, Operands);
} }
case BTK__builtin_dedup_pack: {
assert(Converted.size() == 1 && "__builtin_dedup_pack should be given "
"a parameter pack");
TemplateArgument Ts = Converted[0];
// Delay the computation until we can compute the final result. We choose
// not to remove the duplicates upfront before substitution to keep the code
// simple.
if (Ts.isDependent())
return QualType();
assert(Ts.getKind() == clang::TemplateArgument::Pack);
llvm::SmallVector<TemplateArgument> OutArgs;
llvm::SmallDenseSet<QualType> Seen;
// Synthesize a new template argument list, removing duplicates.
for (auto T : Ts.getPackAsArray()) {
assert(T.getKind() == clang::TemplateArgument::Type);
if (!Seen.insert(T.getAsType().getCanonicalType()).second)
continue;
OutArgs.push_back(T);
}
return Context.getSubstBuiltinTemplatePack(
TemplateArgument::CreatePackCopy(Context, OutArgs));
}
} }
llvm_unreachable("unexpected BuiltinTemplateDecl!"); llvm_unreachable("unexpected BuiltinTemplateDecl!");
} }
@ -5839,6 +5868,29 @@ bool Sema::CheckTemplateArgumentList(
} }
} }
// Check for builtins producing template packs in this context, we do not
// support them yet.
if (const NonTypeTemplateParmDecl *NTTP =
dyn_cast<NonTypeTemplateParmDecl>(*Param);
NTTP && NTTP->isPackExpansion()) {
auto TL = NTTP->getTypeSourceInfo()
->getTypeLoc()
.castAs<PackExpansionTypeLoc>();
llvm::SmallVector<UnexpandedParameterPack> Unexpanded;
collectUnexpandedParameterPacks(TL.getPatternLoc(), Unexpanded);
for (const auto &UPP : Unexpanded) {
auto *TST = UPP.first.dyn_cast<const TemplateSpecializationType *>();
if (!TST)
continue;
assert(isPackProducingBuiltinTemplateName(TST->getTemplateName()));
// Expanding a built-in pack in this context is not yet supported.
Diag(TL.getEllipsisLoc(),
diag::err_unsupported_builtin_template_pack_expansion)
<< TST->getTemplateName();
return true;
}
}
if (ArgIdx < NumArgs) { if (ArgIdx < NumArgs) {
TemplateArgumentLoc &ArgLoc = NewArgs[ArgIdx]; TemplateArgumentLoc &ArgLoc = NewArgs[ArgIdx];
bool NonPackParameter = bool NonPackParameter =
@ -6296,6 +6348,11 @@ bool UnnamedLocalNoLinkageFinder::VisitSubstTemplateTypeParmPackType(
return false; return false;
} }
bool UnnamedLocalNoLinkageFinder::VisitSubstBuiltinTemplatePackType(
const SubstBuiltinTemplatePackType *) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType( bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType(
const TemplateSpecializationType*) { const TemplateSpecializationType*) {
return false; return false;

View File

@ -710,6 +710,9 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams,
// If the parameter is an alias template, there is nothing to deduce. // If the parameter is an alias template, there is nothing to deduce.
if (const auto *TD = TNP.getAsTemplateDecl(); TD && TD->isTypeAlias()) if (const auto *TD = TNP.getAsTemplateDecl(); TD && TD->isTypeAlias())
return TemplateDeductionResult::Success; return TemplateDeductionResult::Success;
// Pack-producing templates can only be matched after substitution.
if (isPackProducingBuiltinTemplateName(TNP))
return TemplateDeductionResult::Success;
// Check whether the template argument is a dependent template-id. // Check whether the template argument is a dependent template-id.
if (isa<TemplateSpecializationType>(A.getCanonicalType())) { if (isa<TemplateSpecializationType>(A.getCanonicalType())) {
@ -928,7 +931,11 @@ private:
S.collectUnexpandedParameterPacks(Pattern, Unexpanded); S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index; unsigned Depth, Index;
std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]); if (auto DI = getDepthAndIndex(Unexpanded[I]))
std::tie(Depth, Index) = *DI;
else
continue;
if (Depth == Info.getDeducedDepth()) if (Depth == Info.getDeducedDepth())
AddPack(Index); AddPack(Index);
} }
@ -936,7 +943,6 @@ private:
// Look for unexpanded packs in the pattern. // Look for unexpanded packs in the pattern.
Collect(Pattern); Collect(Pattern);
assert(!Packs.empty() && "Pack expansion without unexpanded packs?");
unsigned NumNamedPacks = Packs.size(); unsigned NumNamedPacks = Packs.size();
@ -1858,6 +1864,7 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
case Type::TemplateTypeParm: case Type::TemplateTypeParm:
case Type::SubstTemplateTypeParmPack: case Type::SubstTemplateTypeParmPack:
case Type::SubstBuiltinTemplatePack:
llvm_unreachable("Type nodes handled above"); llvm_unreachable("Type nodes handled above");
case Type::Auto: case Type::Auto:
@ -6967,7 +6974,12 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
= cast<SubstTemplateTypeParmPackType>(T); = cast<SubstTemplateTypeParmPackType>(T);
if (Subst->getReplacedParameter()->getDepth() == Depth) if (Subst->getReplacedParameter()->getDepth() == Depth)
Used[Subst->getIndex()] = true; Used[Subst->getIndex()] = true;
MarkUsedTemplateParameters(Ctx, Subst->getArgumentPack(), MarkUsedTemplateParameters(Ctx, Subst->getArgumentPack(), OnlyDeduced,
Depth, Used);
break;
}
case Type::SubstBuiltinTemplatePack: {
MarkUsedTemplateParameters(Ctx, cast<SubstPackType>(T)->getArgumentPack(),
OnlyDeduced, Depth, Used); OnlyDeduced, Depth, Used);
break; break;
} }

View File

@ -1459,6 +1459,7 @@ namespace {
bool TryExpandParameterPacks(SourceLocation EllipsisLoc, bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
SourceRange PatternRange, SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded, ArrayRef<UnexpandedParameterPack> Unexpanded,
bool FailOnPackProducingTemplates,
bool &ShouldExpand, bool &RetainExpansion, bool &ShouldExpand, bool &RetainExpansion,
UnsignedOrNone &NumExpansions) { UnsignedOrNone &NumExpansions) {
if (SemaRef.CurrentInstantiationScope && if (SemaRef.CurrentInstantiationScope &&
@ -1472,8 +1473,9 @@ namespace {
} }
return getSema().CheckParameterPacksForExpansion( return getSema().CheckParameterPacksForExpansion(
EllipsisLoc, PatternRange, Unexpanded, TemplateArgs, ShouldExpand, EllipsisLoc, PatternRange, Unexpanded, TemplateArgs,
RetainExpansion, NumExpansions); FailOnPackProducingTemplates, ShouldExpand, RetainExpansion,
NumExpansions);
} }
void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
@ -1515,6 +1517,21 @@ namespace {
} }
} }
MultiLevelTemplateArgumentList ForgetSubstitution() {
MultiLevelTemplateArgumentList New;
New.addOuterRetainedLevels(this->TemplateArgs.getNumLevels());
MultiLevelTemplateArgumentList Old =
const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs) =
std::move(New);
return Old;
}
void RememberSubstitution(MultiLevelTemplateArgumentList Old) {
const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs) =
std::move(Old);
}
TemplateArgument TemplateArgument
getTemplateArgumentPackPatternForRewrite(const TemplateArgument &TA) { getTemplateArgumentPackPatternForRewrite(const TemplateArgument &TA) {
if (TA.getKind() != TemplateArgument::Pack) if (TA.getKind() != TemplateArgument::Pack)
@ -1697,6 +1714,26 @@ namespace {
return inherited::TransformTemplateArgument(Input, Output, Uneval); return inherited::TransformTemplateArgument(Input, Output, Uneval);
} }
using TreeTransform::TransformTemplateSpecializationType;
QualType
TransformTemplateSpecializationType(TypeLocBuilder &TLB,
TemplateSpecializationTypeLoc TL) {
auto *T = TL.getTypePtr();
if (!getSema().ArgPackSubstIndex || !T->isSugared() ||
!isPackProducingBuiltinTemplateName(T->getTemplateName()))
return TreeTransform::TransformTemplateSpecializationType(TLB, TL);
// Look through sugar to get to the SubstBuiltinTemplatePackType that we
// need to substitute into.
// `TransformType` code below will handle picking the element from a pack
// with the index `ArgPackSubstIndex`.
// FIXME: add ability to represent sugarred type for N-th element of a
// builtin pack and produce the sugar here.
QualType R = TransformType(T->desugar());
TLB.pushTrivial(getSema().getASTContext(), R, TL.getBeginLoc());
return R;
}
UnsignedOrNone ComputeSizeOfPackExprWithoutSubstitution( UnsignedOrNone ComputeSizeOfPackExprWithoutSubstitution(
ArrayRef<TemplateArgument> PackArgs) { ArrayRef<TemplateArgument> PackArgs) {
// Don't do this when rewriting template parameters for CTAD: // Don't do this when rewriting template parameters for CTAD:
@ -1746,6 +1783,9 @@ namespace {
TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB, TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
SubstTemplateTypeParmPackTypeLoc TL, SubstTemplateTypeParmPackTypeLoc TL,
bool SuppressObjCLifetime); bool SuppressObjCLifetime);
QualType
TransformSubstBuiltinTemplatePackType(TypeLocBuilder &TLB,
SubstBuiltinTemplatePackTypeLoc TL);
CXXRecordDecl::LambdaDependencyKind CXXRecordDecl::LambdaDependencyKind
ComputeLambdaDependency(LambdaScopeInfo *LSI) { ComputeLambdaDependency(LambdaScopeInfo *LSI) {
@ -1983,6 +2023,7 @@ bool TemplateInstantiator::maybeInstantiateFunctionParameterToScope(
UnsignedOrNone NumExpansions = OrigNumExpansions; UnsignedOrNone NumExpansions = OrigNumExpansions;
if (TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(), if (TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
Pattern.getSourceRange(), Unexpanded, Pattern.getSourceRange(), Unexpanded,
/*FailOnPackProducingTemplates=*/true,
ShouldExpand, RetainExpansion, NumExpansions)) ShouldExpand, RetainExpansion, NumExpansions))
return true; return true;
@ -2719,6 +2760,17 @@ QualType TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
getPackIndex(Pack), Arg, TL.getNameLoc()); getPackIndex(Pack), Arg, TL.getNameLoc());
} }
QualType TemplateInstantiator::TransformSubstBuiltinTemplatePackType(
TypeLocBuilder &TLB, SubstBuiltinTemplatePackTypeLoc TL) {
if (!getSema().ArgPackSubstIndex)
return TreeTransform::TransformSubstBuiltinTemplatePackType(TLB, TL);
auto &Sema = getSema();
TemplateArgument Result = getPackSubstitutedTemplateArgument(
Sema, TL.getTypePtr()->getArgumentPack());
TLB.pushTrivial(Sema.getASTContext(), Result.getAsType(), TL.getBeginLoc());
return Result.getAsType();
}
static concepts::Requirement::SubstitutionDiagnostic * static concepts::Requirement::SubstitutionDiagnostic *
createSubstDiag(Sema &S, TemplateDeductionInfo &Info, createSubstDiag(Sema &S, TemplateDeductionInfo &Info,
Sema::EntityPrinter Printer) { Sema::EntityPrinter Printer) {
@ -3446,6 +3498,72 @@ bool Sema::SubstDefaultArgument(
return false; return false;
} }
// See TreeTransform::PreparePackForExpansion for the relevant comment.
// This function implements the same concept for base specifiers.
static bool
PreparePackForExpansion(Sema &S, const CXXBaseSpecifier &Base,
const MultiLevelTemplateArgumentList &TemplateArgs,
TypeSourceInfo *&Out, UnexpandedInfo &Info) {
SourceRange BaseSourceRange = Base.getSourceRange();
SourceLocation BaseEllipsisLoc = Base.getEllipsisLoc();
Info.Ellipsis = Base.getEllipsisLoc();
auto ComputeInfo = [&S, &TemplateArgs, BaseSourceRange, BaseEllipsisLoc](
TypeSourceInfo *BaseTypeInfo,
bool IsLateExpansionAttempt, UnexpandedInfo &Info) {
// This is a pack expansion. See whether we should expand it now, or
// wait until later.
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
S.collectUnexpandedParameterPacks(BaseTypeInfo->getTypeLoc(), Unexpanded);
if (IsLateExpansionAttempt) {
// Request expansion only when there is an opportunity to expand a pack
// that required a substituion first.
bool SawPackTypes =
llvm::any_of(Unexpanded, [](UnexpandedParameterPack P) {
return P.first.dyn_cast<const SubstBuiltinTemplatePackType *>();
});
if (!SawPackTypes) {
Info.Expand = false;
return false;
}
}
// Determine whether the set of unexpanded parameter packs can and should be
// expanded.
Info.Expand = false;
Info.RetainExpansion = false;
Info.NumExpansions = std::nullopt;
return S.CheckParameterPacksForExpansion(
BaseEllipsisLoc, BaseSourceRange, Unexpanded, TemplateArgs,
/*FailOnPackProducingTemplates=*/false, Info.Expand,
Info.RetainExpansion, Info.NumExpansions);
};
if (ComputeInfo(Base.getTypeSourceInfo(), false, Info))
return true;
if (Info.Expand) {
Out = Base.getTypeSourceInfo();
return false;
}
// The resulting base specifier will (still) be a pack expansion.
{
Sema::ArgPackSubstIndexRAII SubstIndex(S, std::nullopt);
Out = S.SubstType(Base.getTypeSourceInfo(), TemplateArgs,
BaseSourceRange.getBegin(), DeclarationName());
}
if (!Out->getType()->containsUnexpandedParameterPack())
return false;
// Some packs will learn their length after substitution.
// We may need to request their expansion.
if (ComputeInfo(Out, /*IsLateExpansionAttempt=*/true, Info))
return true;
if (Info.Expand)
Info.ExpandUnderForgetSubstitions = true;
return false;
}
bool bool
Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
CXXRecordDecl *Pattern, CXXRecordDecl *Pattern,
@ -3463,47 +3581,37 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
} }
SourceLocation EllipsisLoc; SourceLocation EllipsisLoc;
TypeSourceInfo *BaseTypeLoc; TypeSourceInfo *BaseTypeLoc = nullptr;
if (Base.isPackExpansion()) { if (Base.isPackExpansion()) {
// This is a pack expansion. See whether we should expand it now, or UnexpandedInfo Info;
// wait until later. if (PreparePackForExpansion(*this, Base, TemplateArgs, BaseTypeLoc,
SmallVector<UnexpandedParameterPack, 2> Unexpanded; Info)) {
collectUnexpandedParameterPacks(Base.getTypeSourceInfo()->getTypeLoc(),
Unexpanded);
bool ShouldExpand = false;
bool RetainExpansion = false;
UnsignedOrNone NumExpansions = std::nullopt;
if (CheckParameterPacksForExpansion(Base.getEllipsisLoc(),
Base.getSourceRange(),
Unexpanded,
TemplateArgs, ShouldExpand,
RetainExpansion,
NumExpansions)) {
Invalid = true; Invalid = true;
continue; continue;
} }
// If we should expand this pack expansion now, do so. // If we should expand this pack expansion now, do so.
if (ShouldExpand) { MultiLevelTemplateArgumentList EmptyList;
for (unsigned I = 0; I != *NumExpansions; ++I) { const MultiLevelTemplateArgumentList *ArgsForSubst = &TemplateArgs;
if (Info.ExpandUnderForgetSubstitions)
ArgsForSubst = &EmptyList;
if (Info.Expand) {
for (unsigned I = 0; I != *Info.NumExpansions; ++I) {
Sema::ArgPackSubstIndexRAII SubstIndex(*this, I); Sema::ArgPackSubstIndexRAII SubstIndex(*this, I);
TypeSourceInfo *BaseTypeLoc = SubstType(Base.getTypeSourceInfo(), TypeSourceInfo *Expanded =
TemplateArgs, SubstType(BaseTypeLoc, *ArgsForSubst,
Base.getSourceRange().getBegin(), Base.getSourceRange().getBegin(), DeclarationName());
DeclarationName()); if (!Expanded) {
if (!BaseTypeLoc) {
Invalid = true; Invalid = true;
continue; continue;
} }
if (CXXBaseSpecifier *InstantiatedBase if (CXXBaseSpecifier *InstantiatedBase = CheckBaseSpecifier(
= CheckBaseSpecifier(Instantiation, Instantiation, Base.getSourceRange(), Base.isVirtual(),
Base.getSourceRange(), Base.getAccessSpecifierAsWritten(), Expanded,
Base.isVirtual(), SourceLocation()))
Base.getAccessSpecifierAsWritten(),
BaseTypeLoc,
SourceLocation()))
InstantiatedBases.push_back(InstantiatedBase); InstantiatedBases.push_back(InstantiatedBase);
else else
Invalid = true; Invalid = true;
@ -3515,10 +3623,9 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
// The resulting base specifier will (still) be a pack expansion. // The resulting base specifier will (still) be a pack expansion.
EllipsisLoc = Base.getEllipsisLoc(); EllipsisLoc = Base.getEllipsisLoc();
Sema::ArgPackSubstIndexRAII SubstIndex(*this, std::nullopt); Sema::ArgPackSubstIndexRAII SubstIndex(*this, std::nullopt);
BaseTypeLoc = SubstType(Base.getTypeSourceInfo(), BaseTypeLoc =
TemplateArgs, SubstType(BaseTypeLoc, *ArgsForSubst,
Base.getSourceRange().getBegin(), Base.getSourceRange().getBegin(), DeclarationName());
DeclarationName());
} else { } else {
BaseTypeLoc = SubstType(Base.getTypeSourceInfo(), BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
TemplateArgs, TemplateArgs,

View File

@ -133,8 +133,9 @@ static void instantiateDependentAlignedAttr(
// FIXME: Use the actual location of the ellipsis. // FIXME: Use the actual location of the ellipsis.
SourceLocation EllipsisLoc = Aligned->getLocation(); SourceLocation EllipsisLoc = Aligned->getLocation();
if (S.CheckParameterPacksForExpansion(EllipsisLoc, Aligned->getRange(), if (S.CheckParameterPacksForExpansion(EllipsisLoc, Aligned->getRange(),
Unexpanded, TemplateArgs, Expand, Unexpanded, TemplateArgs,
RetainExpansion, NumExpansions)) /*FailOnPackProducingTemplates=*/true,
Expand, RetainExpansion, NumExpansions))
return; return;
if (!Expand) { if (!Expand) {
@ -1914,7 +1915,8 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
UnsignedOrNone NumExpansions = std::nullopt; UnsignedOrNone NumExpansions = std::nullopt;
if (SemaRef.CheckParameterPacksForExpansion( if (SemaRef.CheckParameterPacksForExpansion(
D->getEllipsisLoc(), D->getSourceRange(), Unexpanded, D->getEllipsisLoc(), D->getSourceRange(), Unexpanded,
TemplateArgs, ShouldExpand, RetainExpansion, NumExpansions)) TemplateArgs, /*FailOnPackProducingTemplates=*/true,
ShouldExpand, RetainExpansion, NumExpansions))
return nullptr; return nullptr;
assert(!RetainExpansion && assert(!RetainExpansion &&
@ -3464,10 +3466,11 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint()) cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint())
->getEllipsisLoc(), ->getEllipsisLoc(),
SourceRange(TC->getConceptNameLoc(), SourceRange(TC->getConceptNameLoc(),
TC->hasExplicitTemplateArgs() ? TC->hasExplicitTemplateArgs()
TC->getTemplateArgsAsWritten()->getRAngleLoc() : ? TC->getTemplateArgsAsWritten()->getRAngleLoc()
TC->getConceptNameInfo().getEndLoc()), : TC->getConceptNameInfo().getEndLoc()),
Unexpanded, TemplateArgs, Expand, RetainExpansion, NumExpanded)) Unexpanded, TemplateArgs, /*FailOnPackProducingTemplates=*/true,
Expand, RetainExpansion, NumExpanded))
return nullptr; return nullptr;
} }
} }
@ -3555,12 +3558,10 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
UnsignedOrNone OrigNumExpansions = UnsignedOrNone OrigNumExpansions =
Expansion.getTypePtr()->getNumExpansions(); Expansion.getTypePtr()->getNumExpansions();
UnsignedOrNone NumExpansions = OrigNumExpansions; UnsignedOrNone NumExpansions = OrigNumExpansions;
if (SemaRef.CheckParameterPacksForExpansion(Expansion.getEllipsisLoc(), if (SemaRef.CheckParameterPacksForExpansion(
Pattern.getSourceRange(), Expansion.getEllipsisLoc(), Pattern.getSourceRange(), Unexpanded,
Unexpanded, TemplateArgs, /*FailOnPackProducingTemplates=*/true, Expand,
TemplateArgs, RetainExpansion, NumExpansions))
Expand, RetainExpansion,
NumExpansions))
return nullptr; return nullptr;
if (Expand) { if (Expand) {
@ -3726,12 +3727,10 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
bool Expand = true; bool Expand = true;
bool RetainExpansion = false; bool RetainExpansion = false;
UnsignedOrNone NumExpansions = std::nullopt; UnsignedOrNone NumExpansions = std::nullopt;
if (SemaRef.CheckParameterPacksForExpansion(D->getLocation(), if (SemaRef.CheckParameterPacksForExpansion(
TempParams->getSourceRange(), D->getLocation(), TempParams->getSourceRange(), Unexpanded,
Unexpanded, TemplateArgs, /*FailOnPackProducingTemplates=*/true, Expand,
TemplateArgs, RetainExpansion, NumExpansions))
Expand, RetainExpansion,
NumExpansions))
return nullptr; return nullptr;
if (Expand) { if (Expand) {
@ -4003,8 +4002,9 @@ Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl(
bool RetainExpansion = false; bool RetainExpansion = false;
UnsignedOrNone NumExpansions = std::nullopt; UnsignedOrNone NumExpansions = std::nullopt;
if (SemaRef.CheckParameterPacksForExpansion( if (SemaRef.CheckParameterPacksForExpansion(
D->getEllipsisLoc(), D->getSourceRange(), Unexpanded, TemplateArgs, D->getEllipsisLoc(), D->getSourceRange(), Unexpanded, TemplateArgs,
Expand, RetainExpansion, NumExpansions)) /*FailOnPackProducingTemplates=*/true, Expand, RetainExpansion,
NumExpansions))
return nullptr; return nullptr;
// This declaration cannot appear within a function template signature, // This declaration cannot appear within a function template signature,
@ -6401,12 +6401,10 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
bool ShouldExpand = false; bool ShouldExpand = false;
bool RetainExpansion = false; bool RetainExpansion = false;
UnsignedOrNone NumExpansions = std::nullopt; UnsignedOrNone NumExpansions = std::nullopt;
if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(), if (CheckParameterPacksForExpansion(
BaseTL.getSourceRange(), Init->getEllipsisLoc(), BaseTL.getSourceRange(), Unexpanded,
Unexpanded, TemplateArgs, /*FailOnPackProducingTemplates=*/true, ShouldExpand,
TemplateArgs, ShouldExpand, RetainExpansion, NumExpansions)) {
RetainExpansion,
NumExpansions)) {
AnyErrors = true; AnyErrors = true;
New->setInvalidDecl(); New->setInvalidDecl();
continue; continue;

View File

@ -65,6 +65,41 @@ class CollectUnexpandedParameterPacksVisitor
Unexpanded.push_back({T, Loc}); Unexpanded.push_back({T, Loc});
} }
bool addUnexpanded(const SubstBuiltinTemplatePackType *T,
SourceLocation Loc = SourceLocation()) {
Unexpanded.push_back({T, Loc});
return true;
}
bool addUnexpanded(const TemplateSpecializationType *T,
SourceLocation Loc = SourceLocation()) {
assert(T->isCanonicalUnqualified() &&
isPackProducingBuiltinTemplateName(T->getTemplateName()));
Unexpanded.push_back({T, Loc});
return true;
}
/// Returns true iff it handled the traversal. On false, the callers must
/// traverse themselves.
bool
TryTraverseSpecializationProducingPacks(const TemplateSpecializationType *T,
SourceLocation Loc) {
if (!isPackProducingBuiltinTemplateName(T->getTemplateName()))
return false;
// Canonical types are inputs to the initial substitution. Report them and
// do not recurse any further.
if (T->isCanonicalUnqualified()) {
addUnexpanded(T, Loc);
return true;
}
// For sugared types, do not use the default traversal as it would be
// looking at (now irrelevant) template arguments. Instead, look at the
// result of substitution, it usually contains SubstPackType that needs to
// be expanded further.
DynamicRecursiveASTVisitor::TraverseType(T->desugar());
return true;
}
public: public:
explicit CollectUnexpandedParameterPacksVisitor( explicit CollectUnexpandedParameterPacksVisitor(
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
@ -123,6 +158,23 @@ class CollectUnexpandedParameterPacksVisitor
return DynamicRecursiveASTVisitor::TraverseTemplateName(Template); return DynamicRecursiveASTVisitor::TraverseTemplateName(Template);
} }
bool
TraverseTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc T,
bool TraverseQualifier) override {
if (TryTraverseSpecializationProducingPacks(T.getTypePtr(),
T.getBeginLoc()))
return true;
return DynamicRecursiveASTVisitor::TraverseTemplateSpecializationTypeLoc(
T, TraverseQualifier);
}
bool TraverseTemplateSpecializationType(TemplateSpecializationType *T,
bool TraverseQualfier) override {
if (TryTraverseSpecializationProducingPacks(T, SourceLocation()))
return true;
return DynamicRecursiveASTVisitor::TraverseTemplateSpecializationType(T);
}
/// Suppress traversal into Objective-C container literal /// Suppress traversal into Objective-C container literal
/// elements that are pack expansions. /// elements that are pack expansions.
bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) override { bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) override {
@ -325,6 +377,14 @@ class CollectUnexpandedParameterPacksVisitor
return DynamicRecursiveASTVisitor::TraverseUnresolvedLookupExpr(E); return DynamicRecursiveASTVisitor::TraverseUnresolvedLookupExpr(E);
} }
bool TraverseSubstBuiltinTemplatePackType(SubstBuiltinTemplatePackType *T,
bool TraverseQualifier) override {
addUnexpanded(T);
// Do not call into base implementation to supress traversal of the
// substituted types.
return true;
}
#ifndef NDEBUG #ifndef NDEBUG
bool TraverseFunctionParmPackExpr(FunctionParmPackExpr *) override { bool TraverseFunctionParmPackExpr(FunctionParmPackExpr *) override {
ContainsIntermediatePacks = true; ContainsIntermediatePacks = true;
@ -645,6 +705,23 @@ void Sema::collectUnexpandedParameterPacks(
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E); CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
} }
ParsedTemplateArgument
Sema::ActOnTemplateTemplateArgument(const ParsedTemplateArgument &Arg) {
if (Arg.isInvalid())
return Arg;
// We do not allow to reference builtin templates that produce multiple
// values, they would not have a well-defined semantics outside template
// arguments.
auto *T = dyn_cast_or_null<BuiltinTemplateDecl>(
Arg.getAsTemplate().get().getAsTemplateDecl());
if (T && T->isPackProducingBuiltinTemplate())
diagnoseMissingTemplateArguments(Arg.getAsTemplate().get(),
Arg.getNameLoc());
return Arg;
}
ParsedTemplateArgument ParsedTemplateArgument
Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
SourceLocation EllipsisLoc) { SourceLocation EllipsisLoc) {
@ -731,7 +808,7 @@ QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange,
if (!Pattern->containsUnexpandedParameterPack() && if (!Pattern->containsUnexpandedParameterPack() &&
!Pattern->getContainedDeducedType()) { !Pattern->getContainedDeducedType()) {
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< PatternRange; << PatternRange;
return QualType(); return QualType();
} }
@ -765,7 +842,8 @@ ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
bool Sema::CheckParameterPacksForExpansion( bool Sema::CheckParameterPacksForExpansion(
SourceLocation EllipsisLoc, SourceRange PatternRange, SourceLocation EllipsisLoc, SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded, ArrayRef<UnexpandedParameterPack> Unexpanded,
const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, const MultiLevelTemplateArgumentList &TemplateArgs,
bool FailOnPackProducingTemplates, bool &ShouldExpand,
bool &RetainExpansion, UnsignedOrNone &NumExpansions) { bool &RetainExpansion, UnsignedOrNone &NumExpansions) {
ShouldExpand = true; ShouldExpand = true;
RetainExpansion = false; RetainExpansion = false;
@ -781,12 +859,31 @@ bool Sema::CheckParameterPacksForExpansion(
IdentifierInfo *Name; IdentifierInfo *Name;
bool IsVarDeclPack = false; bool IsVarDeclPack = false;
FunctionParmPackExpr *BindingPack = nullptr; FunctionParmPackExpr *BindingPack = nullptr;
std::optional<unsigned> NumPrecomputedArguments;
if (const TemplateTypeParmType *TTP = if (auto *TTP = ParmPack.first.dyn_cast<const TemplateTypeParmType *>()) {
ParmPack.first.dyn_cast<const TemplateTypeParmType *>()) {
Depth = TTP->getDepth(); Depth = TTP->getDepth();
Index = TTP->getIndex(); Index = TTP->getIndex();
Name = TTP->getIdentifier(); Name = TTP->getIdentifier();
} else if (auto *TST =
ParmPack.first
.dyn_cast<const TemplateSpecializationType *>()) {
assert(isPackProducingBuiltinTemplateName(TST->getTemplateName()));
// Delay expansion, substitution is required to know the size.
ShouldExpand = false;
if (!FailOnPackProducingTemplates)
continue;
// It is not yet supported in certain contexts.
return Diag(PatternRange.getBegin().isValid() ? PatternRange.getBegin()
: EllipsisLoc,
diag::err_unsupported_builtin_template_pack_expansion)
<< TST->getTemplateName();
} else if (auto *S =
ParmPack.first
.dyn_cast<const SubstBuiltinTemplatePackType *>()) {
Name = nullptr;
NumPrecomputedArguments = S->getNumArgs();
} else { } else {
NamedDecl *ND = cast<NamedDecl *>(ParmPack.first); NamedDecl *ND = cast<NamedDecl *>(ParmPack.first);
if (isa<VarDecl>(ND)) if (isa<VarDecl>(ND))
@ -826,6 +923,8 @@ bool Sema::CheckParameterPacksForExpansion(
} }
} else if (BindingPack) { } else if (BindingPack) {
NewPackSize = BindingPack->getNumExpansions(); NewPackSize = BindingPack->getNumExpansions();
} else if (NumPrecomputedArguments) {
NewPackSize = *NumPrecomputedArguments;
} else { } else {
// If we don't have a template argument at this depth/index, then we // If we don't have a template argument at this depth/index, then we
// cannot expand the pack expansion. Make a note of this, but we still // cannot expand the pack expansion. Make a note of this, but we still
@ -967,6 +1066,21 @@ UnsignedOrNone Sema::getNumArgumentsInExpansionFromUnexpanded(
Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) { Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
Depth = TTP->getDepth(); Depth = TTP->getDepth();
Index = TTP->getIndex(); Index = TTP->getIndex();
} else if (auto *TST =
Unexpanded[I]
.first.dyn_cast<const TemplateSpecializationType *>()) {
// This is a dependent pack, we are not ready to expand it yet.
assert(isPackProducingBuiltinTemplateName(TST->getTemplateName()));
(void)TST;
return std::nullopt;
} else if (auto *PST =
Unexpanded[I]
.first
.dyn_cast<const SubstBuiltinTemplatePackType *>()) {
assert((!Result || *Result == PST->getNumArgs()) &&
"inconsistent pack sizes");
Result = PST->getNumArgs();
continue;
} else { } else {
NamedDecl *ND = cast<NamedDecl *>(Unexpanded[I].first); NamedDecl *ND = cast<NamedDecl *>(Unexpanded[I].first);
if (isa<VarDecl>(ND)) { if (isa<VarDecl>(ND)) {

View File

@ -45,6 +45,7 @@
#include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/SemaOpenMP.h"
#include "clang/Sema/SemaPseudoObject.h" #include "clang/Sema/SemaPseudoObject.h"
#include "clang/Sema/SemaSYCL.h" #include "clang/Sema/SemaSYCL.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include <algorithm> #include <algorithm>
@ -55,6 +56,17 @@ using namespace llvm::omp;
namespace clang { namespace clang {
using namespace sema; using namespace sema;
// This helper class is used to facilitate pack expansion during tree transform.
struct UnexpandedInfo {
SourceLocation Ellipsis;
UnsignedOrNone OrigNumExpansions = std::nullopt;
bool Expand = false;
bool RetainExpansion = false;
UnsignedOrNone NumExpansions = std::nullopt;
bool ExpandUnderForgetSubstitions = false;
};
/// A semantic tree transformation that allows one to transform one /// A semantic tree transformation that allows one to transform one
/// abstract syntax tree into another. /// abstract syntax tree into another.
/// ///
@ -292,6 +304,7 @@ public:
bool TryExpandParameterPacks(SourceLocation EllipsisLoc, bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
SourceRange PatternRange, SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded, ArrayRef<UnexpandedParameterPack> Unexpanded,
bool FailOnPackProducingTemplates,
bool &ShouldExpand, bool &RetainExpansion, bool &ShouldExpand, bool &RetainExpansion,
UnsignedOrNone &NumExpansions) { UnsignedOrNone &NumExpansions) {
ShouldExpand = false; ShouldExpand = false;
@ -314,6 +327,27 @@ public:
/// This routine is meant to be overridden by the template instantiator. /// This routine is meant to be overridden by the template instantiator.
void RememberPartiallySubstitutedPack(TemplateArgument Arg) { } void RememberPartiallySubstitutedPack(TemplateArgument Arg) { }
/// "Forget" the template substitution to allow transforming the AST without
/// any template instantiations. This is used to expand template packs when
/// their size is not known in advance (e.g. for builtins that produce type
/// packs).
MultiLevelTemplateArgumentList ForgetSubstitution() { return {}; }
void RememberSubstitution(MultiLevelTemplateArgumentList) {}
private:
struct ForgetSubstitutionRAII {
Derived &Self;
MultiLevelTemplateArgumentList Old;
public:
ForgetSubstitutionRAII(Derived &Self) : Self(Self) {
Old = Self.ForgetSubstitution();
}
~ForgetSubstitutionRAII() { Self.RememberSubstitution(std::move(Old)); }
};
public:
/// Note to the derived class when a function parameter pack is /// Note to the derived class when a function parameter pack is
/// being expanded. /// being expanded.
void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { } void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { }
@ -660,6 +694,19 @@ public:
TemplateArgumentListInfo &Outputs, TemplateArgumentListInfo &Outputs,
bool Uneval = false); bool Uneval = false);
/// Checks if the argument pack from \p In will need to be expanded and does
/// the necessary prework.
/// Whether the expansion is needed is captured in Info.Expand.
///
/// - When the expansion is required, \p Out will be a template pattern that
/// would need to be expanded.
/// - When the expansion must not happen, \p Out will be a pack that must be
/// returned to the outputs directly.
///
/// \return true iff the error occurred
bool PreparePackForExpansion(TemplateArgumentLoc In, bool Uneval,
TemplateArgumentLoc &Out, UnexpandedInfo &Info);
/// Fakes up a TemplateArgumentLoc for a given TemplateArgument. /// Fakes up a TemplateArgumentLoc for a given TemplateArgument.
void InventTemplateArgumentLoc(const TemplateArgument &Arg, void InventTemplateArgumentLoc(const TemplateArgument &Arg,
TemplateArgumentLoc &ArgLoc); TemplateArgumentLoc &ArgLoc);
@ -4461,11 +4508,10 @@ bool TreeTransform<Derived>::TransformExprs(Expr *const *Inputs,
bool RetainExpansion = false; bool RetainExpansion = false;
UnsignedOrNone OrigNumExpansions = Expansion->getNumExpansions(); UnsignedOrNone OrigNumExpansions = Expansion->getNumExpansions();
UnsignedOrNone NumExpansions = OrigNumExpansions; UnsignedOrNone NumExpansions = OrigNumExpansions;
if (getDerived().TryExpandParameterPacks(Expansion->getEllipsisLoc(), if (getDerived().TryExpandParameterPacks(
Pattern->getSourceRange(), Expansion->getEllipsisLoc(), Pattern->getSourceRange(),
Unexpanded, Unexpanded, /*FailOnPackProducingTemplates=*/true, Expand,
Expand, RetainExpansion, RetainExpansion, NumExpansions))
NumExpansions))
return true; return true;
if (!Expand) { if (!Expand) {
@ -5081,60 +5127,30 @@ bool TreeTransform<Derived>::TransformTemplateArguments(
} }
if (In.getArgument().isPackExpansion()) { if (In.getArgument().isPackExpansion()) {
// We have a pack expansion, for which we will be substituting into UnexpandedInfo Info;
// the pattern. TemplateArgumentLoc Prepared;
SourceLocation Ellipsis; if (PreparePackForExpansion(In, Uneval, Prepared, Info))
UnsignedOrNone OrigNumExpansions = std::nullopt;
TemplateArgumentLoc Pattern
= getSema().getTemplateArgumentPackExpansionPattern(
In, Ellipsis, OrigNumExpansions);
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
// Determine whether the set of unexpanded parameter packs can and should
// be expanded.
bool Expand = true;
bool RetainExpansion = false;
UnsignedOrNone NumExpansions = OrigNumExpansions;
if (getDerived().TryExpandParameterPacks(Ellipsis,
Pattern.getSourceRange(),
Unexpanded,
Expand,
RetainExpansion,
NumExpansions))
return true; return true;
if (!Info.Expand) {
if (!Expand) { Outputs.addArgument(Prepared);
// The transform has determined that we should perform a simple
// transformation on the pack expansion, producing another pack
// expansion.
TemplateArgumentLoc OutPattern;
Sema::ArgPackSubstIndexRAII SubstIndex(getSema(), std::nullopt);
if (getDerived().TransformTemplateArgument(Pattern, OutPattern, Uneval))
return true;
Out = getDerived().RebuildPackExpansion(OutPattern, Ellipsis,
NumExpansions);
if (Out.getArgument().isNull())
return true;
Outputs.addArgument(Out);
continue; continue;
} }
// The transform has determined that we should perform an elementwise // The transform has determined that we should perform an elementwise
// expansion of the pattern. Do so. // expansion of the pattern. Do so.
for (unsigned I = 0; I != *NumExpansions; ++I) { std::optional<ForgetSubstitutionRAII> ForgetSubst;
if (Info.ExpandUnderForgetSubstitions)
ForgetSubst.emplace(getDerived());
for (unsigned I = 0; I != *Info.NumExpansions; ++I) {
Sema::ArgPackSubstIndexRAII SubstIndex(getSema(), I); Sema::ArgPackSubstIndexRAII SubstIndex(getSema(), I);
if (getDerived().TransformTemplateArgument(Pattern, Out, Uneval)) TemplateArgumentLoc Out;
if (getDerived().TransformTemplateArgument(Prepared, Out, Uneval))
return true; return true;
if (Out.getArgument().containsUnexpandedParameterPack()) { if (Out.getArgument().containsUnexpandedParameterPack()) {
Out = getDerived().RebuildPackExpansion(Out, Ellipsis, Out = getDerived().RebuildPackExpansion(Out, Info.Ellipsis,
OrigNumExpansions); Info.OrigNumExpansions);
if (Out.getArgument().isNull()) if (Out.getArgument().isNull())
return true; return true;
} }
@ -5144,14 +5160,15 @@ bool TreeTransform<Derived>::TransformTemplateArguments(
// If we're supposed to retain a pack expansion, do so by temporarily // If we're supposed to retain a pack expansion, do so by temporarily
// forgetting the partially-substituted parameter pack. // forgetting the partially-substituted parameter pack.
if (RetainExpansion) { if (Info.RetainExpansion) {
ForgetPartiallySubstitutedPackRAII Forget(getDerived()); ForgetPartiallySubstitutedPackRAII Forget(getDerived());
if (getDerived().TransformTemplateArgument(Pattern, Out, Uneval)) TemplateArgumentLoc Out;
if (getDerived().TransformTemplateArgument(Prepared, Out, Uneval))
return true; return true;
Out = getDerived().RebuildPackExpansion(Out, Ellipsis, Out = getDerived().RebuildPackExpansion(Out, Info.Ellipsis,
OrigNumExpansions); Info.OrigNumExpansions);
if (Out.getArgument().isNull()) if (Out.getArgument().isNull())
return true; return true;
@ -5172,6 +5189,114 @@ bool TreeTransform<Derived>::TransformTemplateArguments(
} }
// FIXME: Find ways to reduce code duplication for pack expansions.
template <typename Derived>
bool TreeTransform<Derived>::PreparePackForExpansion(TemplateArgumentLoc In,
bool Uneval,
TemplateArgumentLoc &Out,
UnexpandedInfo &Info) {
auto ComputeInfo = [this](TemplateArgumentLoc Arg,
bool IsLateExpansionAttempt, UnexpandedInfo &Info,
TemplateArgumentLoc &Pattern) {
assert(Arg.getArgument().isPackExpansion());
// We have a pack expansion, for which we will be substituting into the
// pattern.
Pattern = getSema().getTemplateArgumentPackExpansionPattern(
Arg, Info.Ellipsis, Info.OrigNumExpansions);
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
if (IsLateExpansionAttempt) {
// Request expansion only when there is an opportunity to expand a pack
// that required a substituion first.
bool SawPackTypes =
llvm::any_of(Unexpanded, [](UnexpandedParameterPack P) {
return P.first.dyn_cast<const SubstBuiltinTemplatePackType *>();
});
if (!SawPackTypes) {
Info.Expand = false;
return false;
}
}
assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
// Determine whether the set of unexpanded parameter packs can and
// should be expanded.
Info.Expand = true;
Info.RetainExpansion = false;
Info.NumExpansions = Info.OrigNumExpansions;
return getDerived().TryExpandParameterPacks(
Info.Ellipsis, Pattern.getSourceRange(), Unexpanded,
/*FailOnPackProducingTemplates=*/false, Info.Expand,
Info.RetainExpansion, Info.NumExpansions);
};
TemplateArgumentLoc Pattern;
if (ComputeInfo(In, false, Info, Pattern))
return true;
if (Info.Expand) {
Out = Pattern;
return false;
}
// The transform has determined that we should perform a simple
// transformation on the pack expansion, producing another pack
// expansion.
TemplateArgumentLoc OutPattern;
std::optional<Sema::ArgPackSubstIndexRAII> SubstIndex(
std::in_place, getSema(), std::nullopt);
if (getDerived().TransformTemplateArgument(Pattern, OutPattern, Uneval))
return true;
Out = getDerived().RebuildPackExpansion(OutPattern, Info.Ellipsis,
Info.NumExpansions);
if (Out.getArgument().isNull())
return true;
SubstIndex.reset();
if (!OutPattern.getArgument().containsUnexpandedParameterPack())
return false;
// Some packs will learn their length after substitution, e.g.
// __builtin_dedup_pack<T,int> has size 1 or 2, depending on the substitution
// value of `T`.
//
// We only expand after we know sizes of all packs, check if this is the case
// or not. However, we avoid a full template substitution and only do
// expanstions after this point.
// E.g. when substituting template arguments of tuple with {T -> int} in the
// following example:
// template <class T>
// struct TupleWithInt {
// using type = std::tuple<__builtin_dedup_pack<T, int>...>;
// };
// TupleWithInt<int>::type y;
// At this point we will see the `__builtin_dedup_pack<int, int>` with a known
// lenght and run `ComputeInfo()` to provide the necessary information to our
// caller.
//
// Note that we may still have situations where builtin is not going to be
// expanded. For example:
// template <class T>
// struct Foo {
// template <class U> using tuple_with_t =
// std::tuple<__builtin_dedup_pack<T, U, int>...>; using type =
// tuple_with_t<short>;
// }
// Because the substitution into `type` happens in dependent context, `type`
// will be `tuple<builtin_dedup_pack<T, short, int>...>` after substitution
// and the caller will not be able to expand it.
ForgetSubstitutionRAII ForgetSubst(getDerived());
if (ComputeInfo(Out, true, Info, OutPattern))
return true;
if (!Info.Expand)
return false;
Out = OutPattern;
Info.ExpandUnderForgetSubstitions = true;
return false;
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Type transformation // Type transformation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -6182,12 +6307,10 @@ bool TreeTransform<Derived>::TransformFunctionTypeParams(
if (Unexpanded.size() > 0) { if (Unexpanded.size() > 0) {
OrigNumExpansions = ExpansionTL.getTypePtr()->getNumExpansions(); OrigNumExpansions = ExpansionTL.getTypePtr()->getNumExpansions();
NumExpansions = OrigNumExpansions; NumExpansions = OrigNumExpansions;
if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(), if (getDerived().TryExpandParameterPacks(
Pattern.getSourceRange(), ExpansionTL.getEllipsisLoc(), Pattern.getSourceRange(),
Unexpanded, Unexpanded, /*FailOnPackProducingTemplates=*/true,
ShouldExpand, ShouldExpand, RetainExpansion, NumExpansions)) {
RetainExpansion,
NumExpansions)) {
return true; return true;
} }
} else { } else {
@ -6293,11 +6416,10 @@ bool TreeTransform<Derived>::TransformFunctionTypeParams(
// Determine whether we should expand the parameter packs. // Determine whether we should expand the parameter packs.
bool ShouldExpand = false; bool ShouldExpand = false;
bool RetainExpansion = false; bool RetainExpansion = false;
if (getDerived().TryExpandParameterPacks(Loc, SourceRange(), if (getDerived().TryExpandParameterPacks(
Unexpanded, Loc, SourceRange(), Unexpanded,
ShouldExpand, /*FailOnPackProducingTemplates=*/true, ShouldExpand,
RetainExpansion, RetainExpansion, NumExpansions)) {
NumExpansions)) {
return true; return true;
} }
@ -6594,8 +6716,9 @@ bool TreeTransform<Derived>::TransformExceptionSpec(
// FIXME: Track the location of the ellipsis (and track source location // FIXME: Track the location of the ellipsis (and track source location
// information for the types in the exception specification in general). // information for the types in the exception specification in general).
if (getDerived().TryExpandParameterPacks( if (getDerived().TryExpandParameterPacks(
Loc, SourceRange(), Unexpanded, Expand, Loc, SourceRange(), Unexpanded,
RetainExpansion, NumExpansions)) /*FailOnPackProducingTemplates=*/true, Expand, RetainExpansion,
NumExpansions))
return true; return true;
if (!Expand) { if (!Expand) {
@ -6907,9 +7030,10 @@ TreeTransform<Derived>::TransformPackIndexingType(TypeLocBuilder &TLB,
bool ShouldExpand = true; bool ShouldExpand = true;
bool RetainExpansion = false; bool RetainExpansion = false;
UnsignedOrNone NumExpansions = std::nullopt; UnsignedOrNone NumExpansions = std::nullopt;
if (getDerived().TryExpandParameterPacks(TL.getEllipsisLoc(), SourceRange(), if (getDerived().TryExpandParameterPacks(
Unexpanded, ShouldExpand, TL.getEllipsisLoc(), SourceRange(), Unexpanded,
RetainExpansion, NumExpansions)) /*FailOnPackProducingTemplates=*/true, ShouldExpand,
RetainExpansion, NumExpansions))
return QualType(); return QualType();
if (!ShouldExpand) { if (!ShouldExpand) {
Sema::ArgPackSubstIndexRAII SubstIndex(getSema(), std::nullopt); Sema::ArgPackSubstIndexRAII SubstIndex(getSema(), std::nullopt);
@ -7131,6 +7255,11 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
return Result; return Result;
} }
template <typename Derived>
QualType TreeTransform<Derived>::TransformSubstBuiltinTemplatePackType(
TypeLocBuilder &TLB, SubstBuiltinTemplatePackTypeLoc TL) {
return TransformTypeSpecType(TLB, TL);
}
template<typename Derived> template<typename Derived>
QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmPackType( QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmPackType(
@ -7857,8 +7986,9 @@ TreeTransform<Derived>::TransformObjCObjectType(TypeLocBuilder &TLB,
bool RetainExpansion = false; bool RetainExpansion = false;
UnsignedOrNone NumExpansions = PackExpansion->getNumExpansions(); UnsignedOrNone NumExpansions = PackExpansion->getNumExpansions();
if (getDerived().TryExpandParameterPacks( if (getDerived().TryExpandParameterPacks(
PackExpansionLoc.getEllipsisLoc(), PatternLoc.getSourceRange(), PackExpansionLoc.getEllipsisLoc(), PatternLoc.getSourceRange(),
Unexpanded, Expand, RetainExpansion, NumExpansions)) Unexpanded, /*FailOnPackProducingTemplates=*/true, Expand,
RetainExpansion, NumExpansions))
return QualType(); return QualType();
if (!Expand) { if (!Expand) {
@ -14841,11 +14971,10 @@ TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) {
UnsignedOrNone OrigNumExpansions = UnsignedOrNone OrigNumExpansions =
ExpansionTL.getTypePtr()->getNumExpansions(); ExpansionTL.getTypePtr()->getNumExpansions();
UnsignedOrNone NumExpansions = OrigNumExpansions; UnsignedOrNone NumExpansions = OrigNumExpansions;
if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(), if (getDerived().TryExpandParameterPacks(
PatternTL.getSourceRange(), ExpansionTL.getEllipsisLoc(), PatternTL.getSourceRange(),
Unexpanded, Unexpanded, /*FailOnPackProducingTemplates=*/true, Expand,
Expand, RetainExpansion, RetainExpansion, NumExpansions))
NumExpansions))
return ExprError(); return ExprError();
if (!Expand) { if (!Expand) {
@ -15419,8 +15548,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
ExpansionTL.getTypePtr()->getNumExpansions(); ExpansionTL.getTypePtr()->getNumExpansions();
UnsignedOrNone NumExpansions = OrigNumExpansions; UnsignedOrNone NumExpansions = OrigNumExpansions;
if (getDerived().TryExpandParameterPacks( if (getDerived().TryExpandParameterPacks(
ExpansionTL.getEllipsisLoc(), ExpansionTL.getEllipsisLoc(), OldVD->getInit()->getSourceRange(),
OldVD->getInit()->getSourceRange(), Unexpanded, Expand, Unexpanded, /*FailOnPackProducingTemplates=*/true, Expand,
RetainExpansion, NumExpansions)) RetainExpansion, NumExpansions))
return ExprError(); return ExprError();
assert(!RetainExpansion && "Should not need to retain expansion after a " assert(!RetainExpansion && "Should not need to retain expansion after a "
@ -15580,11 +15709,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
bool ShouldExpand = false; bool ShouldExpand = false;
bool RetainExpansion = false; bool RetainExpansion = false;
UnsignedOrNone NumExpansions = std::nullopt; UnsignedOrNone NumExpansions = std::nullopt;
if (getDerived().TryExpandParameterPacks(C->getEllipsisLoc(), if (getDerived().TryExpandParameterPacks(
C->getLocation(), C->getEllipsisLoc(), C->getLocation(), Unexpanded,
Unexpanded, /*FailOnPackProducingTemplates=*/true, ShouldExpand,
ShouldExpand, RetainExpansion, RetainExpansion, NumExpansions)) {
NumExpansions)) {
Invalid = true; Invalid = true;
continue; continue;
} }
@ -16098,10 +16226,10 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
bool ShouldExpand = false; bool ShouldExpand = false;
bool RetainExpansion = false; bool RetainExpansion = false;
UnsignedOrNone NumExpansions = std::nullopt; UnsignedOrNone NumExpansions = std::nullopt;
if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(), if (getDerived().TryExpandParameterPacks(
Unexpanded, E->getOperatorLoc(), E->getPackLoc(), Unexpanded,
ShouldExpand, RetainExpansion, /*FailOnPackProducingTemplates=*/true, ShouldExpand,
NumExpansions)) RetainExpansion, NumExpansions))
return ExprError(); return ExprError();
// If we need to expand the pack, build a template argument from it and // If we need to expand the pack, build a template argument from it and
@ -16218,7 +16346,8 @@ TreeTransform<Derived>::TransformPackIndexingExpr(PackIndexingExpr *E) {
NumExpansions = std::nullopt; NumExpansions = std::nullopt;
if (getDerived().TryExpandParameterPacks( if (getDerived().TryExpandParameterPacks(
E->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded, E->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded,
ShouldExpand, RetainExpansion, NumExpansions)) /*FailOnPackProducingTemplates=*/true, ShouldExpand,
RetainExpansion, NumExpansions))
return true; return true;
if (!ShouldExpand) { if (!ShouldExpand) {
Sema::ArgPackSubstIndexRAII SubstIndex(getSema(), std::nullopt); Sema::ArgPackSubstIndexRAII SubstIndex(getSema(), std::nullopt);
@ -16324,11 +16453,10 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
bool RetainExpansion = false; bool RetainExpansion = false;
UnsignedOrNone OrigNumExpansions = E->getNumExpansions(), UnsignedOrNone OrigNumExpansions = E->getNumExpansions(),
NumExpansions = OrigNumExpansions; NumExpansions = OrigNumExpansions;
if (getDerived().TryExpandParameterPacks(E->getEllipsisLoc(), if (getDerived().TryExpandParameterPacks(
Pattern->getSourceRange(), E->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded,
Unexpanded, /*FailOnPackProducingTemplates=*/true, Expand, RetainExpansion,
Expand, RetainExpansion, NumExpansions))
NumExpansions))
return true; return true;
if (!Expand) { if (!Expand) {
@ -16562,9 +16690,10 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral(
UnsignedOrNone NumExpansions = OrigNumExpansions; UnsignedOrNone NumExpansions = OrigNumExpansions;
SourceRange PatternRange(OrigElement.Key->getBeginLoc(), SourceRange PatternRange(OrigElement.Key->getBeginLoc(),
OrigElement.Value->getEndLoc()); OrigElement.Value->getEndLoc());
if (getDerived().TryExpandParameterPacks(OrigElement.EllipsisLoc, if (getDerived().TryExpandParameterPacks(
PatternRange, Unexpanded, Expand, OrigElement.EllipsisLoc, PatternRange, Unexpanded,
RetainExpansion, NumExpansions)) /*FailOnPackProducingTemplates=*/true, Expand, RetainExpansion,
NumExpansions))
return ExprError(); return ExprError();
if (!Expand) { if (!Expand) {

View File

@ -7500,6 +7500,11 @@ void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc(
TL.setNameLoc(readSourceLocation()); TL.setNameLoc(readSourceLocation());
} }
void TypeLocReader::VisitSubstBuiltinTemplatePackTypeLoc(
SubstBuiltinTemplatePackTypeLoc TL) {
TL.setNameLoc(readSourceLocation());
}
void TypeLocReader::VisitTemplateSpecializationTypeLoc( void TypeLocReader::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) { TemplateSpecializationTypeLoc TL) {
SourceLocation ElaboratedKeywordLoc = readSourceLocation(); SourceLocation ElaboratedKeywordLoc = readSourceLocation();

View File

@ -627,6 +627,11 @@ void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc(
addSourceLocation(TL.getNameLoc()); addSourceLocation(TL.getNameLoc());
} }
void TypeLocWriter::VisitSubstBuiltinTemplatePackTypeLoc(
SubstBuiltinTemplatePackTypeLoc TL) {
addSourceLocation(TL.getNameLoc());
}
void TypeLocWriter::VisitTemplateSpecializationTypeLoc( void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) { TemplateSpecializationTypeLoc TL) {
addSourceLocation(TL.getElaboratedKeywordLoc()); addSourceLocation(TL.getElaboratedKeywordLoc());
@ -1060,6 +1065,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(TYPE_PACK_EXPANSION); RECORD(TYPE_PACK_EXPANSION);
RECORD(TYPE_ATTRIBUTED); RECORD(TYPE_ATTRIBUTED);
RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK); RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK);
RECORD(TYPE_SUBST_BUILTIN_TEMPLATE_PACK);
RECORD(TYPE_AUTO); RECORD(TYPE_AUTO);
RECORD(TYPE_UNARY_TRANSFORM); RECORD(TYPE_UNARY_TRANSFORM);
RECORD(TYPE_ATOMIC); RECORD(TYPE_ATOMIC);

View File

@ -1,33 +1,36 @@
// RUN: %clang_cc1 -O1 -triple spirv64 -fsycl-is-device %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -O1 -triple spirv64 -fsycl-is-device -x c++ %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -O1 -triple spirv64 -cl-std=CL3.0 -x cl %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -O1 -triple spirv64 -cl-std=CL3.0 -x cl %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -O1 -triple spirv32 -cl-std=CL3.0 -x cl %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -O1 -triple spirv32 -cl-std=CL3.0 -x cl %s -emit-llvm -o - | FileCheck %s
// CHECK: spir_func noundef ptr @test_cast_to_private( #ifdef __SYCL_DEVICE_ONLY__
// CHECK-SAME: ptr addrspace(4) noundef readnone [[P:%.*]] #define SYCL_EXTERNAL [[clang::sycl_external]]
#else
#define SYCL_EXTERNAL
#endif
// CHECK: spir_func noundef ptr @{{.*}}test_cast_to_private{{.*}}(ptr addrspace(4) noundef readnone [[P:%.*]]
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[SPV_CAST:%.*]] = tail call noundef ptr @llvm.spv.generic.cast.to.ptr.explicit.p0(ptr addrspace(4) %p) // CHECK-NEXT: [[SPV_CAST:%.*]] = tail call noundef ptr @llvm.spv.generic.cast.to.ptr.explicit.p0(ptr addrspace(4) %p)
// CHECK-NEXT: ret ptr [[SPV_CAST]] // CHECK-NEXT: ret ptr [[SPV_CAST]]
// //
__attribute__((opencl_private)) int* test_cast_to_private(int* p) { SYCL_EXTERNAL __attribute__((opencl_private)) int* test_cast_to_private(int* p) {
return __builtin_spirv_generic_cast_to_ptr_explicit(p, 7); return __builtin_spirv_generic_cast_to_ptr_explicit(p, 7);
} }
// CHECK: spir_func noundef ptr addrspace(1) @test_cast_to_global( // CHECK: spir_func noundef ptr addrspace(1) @{{.*}}test_cast_to_global{{.*}}(ptr addrspace(4) noundef readnone [[P:%.*]]
// CHECK-SAME: ptr addrspace(4) noundef readnone [[P:%.*]]
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[SPV_CAST:%.*]] = tail call noundef ptr addrspace(1) @llvm.spv.generic.cast.to.ptr.explicit.p1(ptr addrspace(4) %p) // CHECK-NEXT: [[SPV_CAST:%.*]] = tail call noundef ptr addrspace(1) @llvm.spv.generic.cast.to.ptr.explicit.p1(ptr addrspace(4) %p)
// CHECK-NEXT: ret ptr addrspace(1) [[SPV_CAST]] // CHECK-NEXT: ret ptr addrspace(1) [[SPV_CAST]]
// //
__attribute__((opencl_global)) int* test_cast_to_global(int* p) { SYCL_EXTERNAL __attribute__((opencl_global)) int* test_cast_to_global(int* p) {
return __builtin_spirv_generic_cast_to_ptr_explicit(p, 5); return __builtin_spirv_generic_cast_to_ptr_explicit(p, 5);
} }
// CHECK: spir_func noundef ptr addrspace(3) @test_cast_to_local( // CHECK: spir_func noundef ptr addrspace(3) @{{.*}}test_cast_to_local{{.*}}(ptr addrspace(4) noundef readnone [[P:%.*]]
// CHECK-SAME: ptr addrspace(4) noundef readnone [[P:%.*]]
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[SPV_CAST:%.*]] = tail call noundef ptr addrspace(3) @llvm.spv.generic.cast.to.ptr.explicit.p3(ptr addrspace(4) %p) // CHECK-NEXT: [[SPV_CAST:%.*]] = tail call noundef ptr addrspace(3) @llvm.spv.generic.cast.to.ptr.explicit.p3(ptr addrspace(4) %p)
// CHECK-NEXT: ret ptr addrspace(3) [[SPV_CAST]] // CHECK-NEXT: ret ptr addrspace(3) [[SPV_CAST]]
// //
__attribute__((opencl_local)) int* test_cast_to_local(int* p) { SYCL_EXTERNAL __attribute__((opencl_local)) int* test_cast_to_local(int* p) {
return __builtin_spirv_generic_cast_to_ptr_explicit(p, 4); return __builtin_spirv_generic_cast_to_ptr_explicit(p, 4);
} }

View File

@ -1,106 +1,106 @@
// RUN: %clang_cc1 -O1 -triple spirv64 -fsycl-is-device %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK64 // RUN: %clang_cc1 -O1 -triple spirv64 -fsycl-is-device -x c++ %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK64
// RUN: %clang_cc1 -O1 -triple spirv64 -cl-std=CL3.0 -x cl %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK64 // RUN: %clang_cc1 -O1 -triple spirv64 -cl-std=CL3.0 -x cl %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK64
// RUN: %clang_cc1 -O1 -triple spirv32 -cl-std=CL3.0 -x cl %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK32 // RUN: %clang_cc1 -O1 -triple spirv32 -cl-std=CL3.0 -x cl %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK32
// CHECK: @test_num_workgroups( // CHECK: @{{.*}}test_num_workgroups{{.*}}(
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK64-NEXT: tail call i64 @llvm.spv.num.workgroups.i64(i32 0) // CHECK64-NEXT: tail call i64 @llvm.spv.num.workgroups.i64(i32 0)
// CHECK32-NEXT: tail call i32 @llvm.spv.num.workgroups.i32(i32 0) // CHECK32-NEXT: tail call i32 @llvm.spv.num.workgroups.i32(i32 0)
// //
unsigned int test_num_workgroups() { [[clang::sycl_external]] unsigned int test_num_workgroups() {
return __builtin_spirv_num_workgroups(0); return __builtin_spirv_num_workgroups(0);
} }
// CHECK: @test_workgroup_size( // CHECK: @{{.*}}test_workgroup_size{{.*}}(
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK64-NEXT: tail call i64 @llvm.spv.workgroup.size.i64(i32 0) // CHECK64-NEXT: tail call i64 @llvm.spv.workgroup.size.i64(i32 0)
// CHECK32-NEXT: tail call i32 @llvm.spv.workgroup.size.i32(i32 0) // CHECK32-NEXT: tail call i32 @llvm.spv.workgroup.size.i32(i32 0)
// //
unsigned int test_workgroup_size() { [[clang::sycl_external]] unsigned int test_workgroup_size() {
return __builtin_spirv_workgroup_size(0); return __builtin_spirv_workgroup_size(0);
} }
// CHECK: @test_workgroup_id( // CHECK: @{{.*}}test_workgroup_id{{.*}}(
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK64-NEXT: tail call i64 @llvm.spv.group.id.i64(i32 0) // CHECK64-NEXT: tail call i64 @llvm.spv.group.id.i64(i32 0)
// CHECK32-NEXT: tail call i32 @llvm.spv.group.id.i32(i32 0) // CHECK32-NEXT: tail call i32 @llvm.spv.group.id.i32(i32 0)
// //
unsigned int test_workgroup_id() { [[clang::sycl_external]] unsigned int test_workgroup_id() {
return __builtin_spirv_workgroup_id(0); return __builtin_spirv_workgroup_id(0);
} }
// CHECK: @test_local_invocation_id( // CHECK: @{{.*}}test_local_invocation_id{{.*}}(
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK64-NEXT: tail call i64 @llvm.spv.thread.id.in.group.i64(i32 0) // CHECK64-NEXT: tail call i64 @llvm.spv.thread.id.in.group.i64(i32 0)
// CHECK32-NEXT: tail call i32 @llvm.spv.thread.id.in.group.i32(i32 0) // CHECK32-NEXT: tail call i32 @llvm.spv.thread.id.in.group.i32(i32 0)
// //
unsigned int test_local_invocation_id() { [[clang::sycl_external]] unsigned int test_local_invocation_id() {
return __builtin_spirv_local_invocation_id(0); return __builtin_spirv_local_invocation_id(0);
} }
// CHECK: @test_global_invocation_id( // CHECK: @{{.*}}test_global_invocation_id{{.*}}(
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK64-NEXT: tail call i64 @llvm.spv.thread.id.i64(i32 0) // CHECK64-NEXT: tail call i64 @llvm.spv.thread.id.i64(i32 0)
// CHECK32-NEXT: tail call i32 @llvm.spv.thread.id.i32(i32 0) // CHECK32-NEXT: tail call i32 @llvm.spv.thread.id.i32(i32 0)
// //
unsigned int test_global_invocation_id() { [[clang::sycl_external]] unsigned int test_global_invocation_id() {
return __builtin_spirv_global_invocation_id(0); return __builtin_spirv_global_invocation_id(0);
} }
// CHECK: @test_global_size( // CHECK: @{{.*}}test_global_size{{.*}}(
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK64-NEXT: tail call i64 @llvm.spv.global.size.i64(i32 0) // CHECK64-NEXT: tail call i64 @llvm.spv.global.size.i64(i32 0)
// CHECK32-NEXT: tail call i32 @llvm.spv.global.size.i32(i32 0) // CHECK32-NEXT: tail call i32 @llvm.spv.global.size.i32(i32 0)
// //
unsigned int test_global_size() { [[clang::sycl_external]] unsigned int test_global_size() {
return __builtin_spirv_global_size(0); return __builtin_spirv_global_size(0);
} }
// CHECK: @test_global_offset( // CHECK: @{{.*}}test_global_offset{{.*}}(
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK64-NEXT: tail call i64 @llvm.spv.global.offset.i64(i32 0) // CHECK64-NEXT: tail call i64 @llvm.spv.global.offset.i64(i32 0)
// CHECK32-NEXT: tail call i32 @llvm.spv.global.offset.i32(i32 0) // CHECK32-NEXT: tail call i32 @llvm.spv.global.offset.i32(i32 0)
// //
unsigned int test_global_offset() { [[clang::sycl_external]] unsigned int test_global_offset() {
return __builtin_spirv_global_offset(0); return __builtin_spirv_global_offset(0);
} }
// CHECK: @test_subgroup_size( // CHECK: @{{.*}}test_subgroup_size{{.*}}(
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: tail call i32 @llvm.spv.subgroup.size() // CHECK-NEXT: tail call i32 @llvm.spv.subgroup.size()
// //
unsigned int test_subgroup_size() { [[clang::sycl_external]] unsigned int test_subgroup_size() {
return __builtin_spirv_subgroup_size(); return __builtin_spirv_subgroup_size();
} }
// CHECK: @test_subgroup_max_size( // CHECK: @{{.*}}test_subgroup_max_size{{.*}}(
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: tail call i32 @llvm.spv.subgroup.max.size() // CHECK-NEXT: tail call i32 @llvm.spv.subgroup.max.size()
// //
unsigned int test_subgroup_max_size() { [[clang::sycl_external]] unsigned int test_subgroup_max_size() {
return __builtin_spirv_subgroup_max_size(); return __builtin_spirv_subgroup_max_size();
} }
// CHECK: @test_num_subgroups( // CHECK: @{{.*}}test_num_subgroups{{.*}}(
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: tail call i32 @llvm.spv.num.subgroups() // CHECK-NEXT: tail call i32 @llvm.spv.num.subgroups()
// //
unsigned int test_num_subgroups() { [[clang::sycl_external]] unsigned int test_num_subgroups() {
return __builtin_spirv_num_subgroups(); return __builtin_spirv_num_subgroups();
} }
// CHECK: @test_subgroup_id( // CHECK: @{{.*}}test_subgroup_id{{.*}}(
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: tail call i32 @llvm.spv.subgroup.id() // CHECK-NEXT: tail call i32 @llvm.spv.subgroup.id()
// //
unsigned int test_subgroup_id() { [[clang::sycl_external]] unsigned int test_subgroup_id() {
return __builtin_spirv_subgroup_id(); return __builtin_spirv_subgroup_id();
} }
// CHECK: @test_subgroup_local_invocation_id( // CHECK: @{{.*}}test_subgroup_local_invocation_id{{.*}}(
// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: tail call i32 @llvm.spv.subgroup.local.invocation.id() // CHECK-NEXT: tail call i32 @llvm.spv.subgroup.local.invocation.id()
// //
unsigned int test_subgroup_local_invocation_id() { [[clang::sycl_external]] unsigned int test_subgroup_local_invocation_id() {
return __builtin_spirv_subgroup_local_invocation_id(); return __builtin_spirv_subgroup_local_invocation_id();
} }

View File

@ -1,143 +1,143 @@
// RUN: %clang_cc1 -triple spir64 -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -triple spir64 -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
void bar(int &Data) {} void bar(int &Data) {}
// CHECK: define{{.*}} spir_func void @[[RAW_REF:[a-zA-Z0-9_]+]](ptr addrspace(4) noundef align 4 dereferenceable(4) % // CHECK-DAG: define{{.*}} spir_func void @[[RAW_REF:[a-zA-Z0-9_]+]](ptr addrspace(4) noundef align 4 dereferenceable(4) %
void bar2(int &Data) {} void bar2(int &Data) {}
// CHECK: define{{.*}} spir_func void @[[RAW_REF2:[a-zA-Z0-9_]+]](ptr addrspace(4) noundef align 4 dereferenceable(4) % // CHECK-DAG: define{{.*}} spir_func void @[[RAW_REF2:[a-zA-Z0-9_]+]](ptr addrspace(4) noundef align 4 dereferenceable(4) %
void bar(__attribute__((opencl_local)) int &Data) {} void bar(__attribute__((opencl_local)) int &Data) {}
// CHECK: define{{.*}} spir_func void [[LOC_REF:@[a-zA-Z0-9_]+]](ptr addrspace(3) noundef align 4 dereferenceable(4) % // CHECK-DAG: define{{.*}} spir_func void [[LOC_REF:@[a-zA-Z0-9_]+]](ptr addrspace(3) noundef align 4 dereferenceable(4) %
void foo(int *Data) {} void foo(int *Data) {}
// CHECK: define{{.*}} spir_func void @[[RAW_PTR:[a-zA-Z0-9_]+]](ptr addrspace(4) noundef % // CHECK-DAG: define{{.*}} spir_func void @[[RAW_PTR:[a-zA-Z0-9_]+]](ptr addrspace(4) noundef %
void foo2(int *Data) {} void foo2(int *Data) {}
// CHECK: define{{.*}} spir_func void @[[RAW_PTR2:[a-zA-Z0-9_]+]](ptr addrspace(4) noundef % // CHECK-DAG: define{{.*}} spir_func void @[[RAW_PTR2:[a-zA-Z0-9_]+]](ptr addrspace(4) noundef %
void foo(__attribute__((opencl_local)) int *Data) {} void foo(__attribute__((opencl_local)) int *Data) {}
// CHECK: define{{.*}} spir_func void [[LOC_PTR:@[a-zA-Z0-9_]+]](ptr addrspace(3) noundef % // CHECK-DAG: define{{.*}} spir_func void [[LOC_PTR:@[a-zA-Z0-9_]+]](ptr addrspace(3) noundef %
template <typename T> template <typename T>
void tmpl(T t) {} void tmpl(T t) {}
// See Check Lines below. // See Check Lines below.
void usages() { [[clang::sycl_external]] void usages() {
int *NoAS; int *NoAS;
// CHECK: [[NoAS:%[a-zA-Z0-9]+]] = alloca ptr addrspace(4) // CHECK-DAG: [[NoAS:%[a-zA-Z0-9]+]] = alloca ptr addrspace(4)
__attribute__((opencl_global)) int *GLOB; __attribute__((opencl_global)) int *GLOB;
// CHECK: [[GLOB:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1) // CHECK-DAG: [[GLOB:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1)
__attribute__((opencl_local)) int *LOC; __attribute__((opencl_local)) int *LOC;
// CHECK: [[LOC:%[a-zA-Z0-9]+]] = alloca ptr addrspace(3) // CHECK-DAG: [[LOC:%[a-zA-Z0-9]+]] = alloca ptr addrspace(3)
__attribute__((opencl_private)) int *PRIV; __attribute__((opencl_private)) int *PRIV;
// CHECK: [[PRIV:%[a-zA-Z0-9]+]] = alloca ptr // CHECK-DAG: [[PRIV:%[a-zA-Z0-9]+]] = alloca ptr
__attribute__((opencl_global_device)) int *GLOBDEVICE; __attribute__((opencl_global_device)) int *GLOBDEVICE;
// CHECK: [[GLOB_DEVICE:%[a-zA-Z0-9]+]] = alloca ptr addrspace(5) // CHECK-DAG: [[GLOB_DEVICE:%[a-zA-Z0-9]+]] = alloca ptr addrspace(5)
__attribute__((opencl_global_host)) int *GLOBHOST; __attribute__((opencl_global_host)) int *GLOBHOST;
// CHECK: [[GLOB_HOST:%[a-zA-Z0-9]+]] = alloca ptr addrspace(6) // CHECK-DAG: [[GLOB_HOST:%[a-zA-Z0-9]+]] = alloca ptr addrspace(6)
// CHECK: [[NoAS]].ascast = addrspacecast ptr [[NoAS]] to ptr addrspace(4) // CHECK-DAG: [[NoAS]].ascast = addrspacecast ptr [[NoAS]] to ptr addrspace(4)
// CHECK: [[GLOB]].ascast = addrspacecast ptr [[GLOB]] to ptr addrspace(4) // CHECK-DAG: [[GLOB]].ascast = addrspacecast ptr [[GLOB]] to ptr addrspace(4)
// CHECK: [[LOC]].ascast = addrspacecast ptr [[LOC]] to ptr addrspace(4) // CHECK-DAG: [[LOC]].ascast = addrspacecast ptr [[LOC]] to ptr addrspace(4)
// CHECK: [[PRIV]].ascast = addrspacecast ptr [[PRIV]] to ptr addrspace(4) // CHECK-DAG: [[PRIV]].ascast = addrspacecast ptr [[PRIV]] to ptr addrspace(4)
LOC = nullptr; LOC = nullptr;
// CHECK: store ptr addrspace(3) null, ptr addrspace(4) [[LOC]].ascast, align 8 // CHECK-DAG: store ptr addrspace(3) null, ptr addrspace(4) [[LOC]].ascast, align 8
GLOB = nullptr; GLOB = nullptr;
// CHECK: store ptr addrspace(1) null, ptr addrspace(4) [[GLOB]].ascast, align 8 // CHECK-DAG: store ptr addrspace(1) null, ptr addrspace(4) [[GLOB]].ascast, align 8
// Explicit conversions // Explicit conversions
// From named address spaces to default address space // From named address spaces to default address space
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr addrspace(4) [[GLOB]].ascast // CHECK-DAG: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr addrspace(4) [[GLOB]].ascast
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr addrspace(4) // CHECK-DAG: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr addrspace(4)
// CHECK: store ptr addrspace(4) [[GLOB_CAST]], ptr addrspace(4) [[NoAS]].ascast // CHECK-DAG: store ptr addrspace(4) [[GLOB_CAST]], ptr addrspace(4) [[NoAS]].ascast
NoAS = (int *)GLOB; NoAS = (int *)GLOB;
// CHECK: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr addrspace(4) [[LOC]].ascast // CHECK-DAG: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr addrspace(4) [[LOC]].ascast
// CHECK: [[LOC_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD]] to ptr addrspace(4) // CHECK-DAG: [[LOC_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD]] to ptr addrspace(4)
// CHECK: store ptr addrspace(4) [[LOC_CAST]], ptr addrspace(4) [[NoAS]].ascast // CHECK-DAG: store ptr addrspace(4) [[LOC_CAST]], ptr addrspace(4) [[NoAS]].ascast
NoAS = (int *)LOC; NoAS = (int *)LOC;
// CHECK: [[PRIV_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr addrspace(4) [[PRIV]].ascast // CHECK-DAG: [[PRIV_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr addrspace(4) [[PRIV]].ascast
// CHECK: [[PRIV_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[PRIV_LOAD]] to ptr addrspace(4) // CHECK-DAG: [[PRIV_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[PRIV_LOAD]] to ptr addrspace(4)
// CHECK: store ptr addrspace(4) [[PRIV_CAST]], ptr addrspace(4) [[NoAS]].ascast // CHECK-DAG: store ptr addrspace(4) [[PRIV_CAST]], ptr addrspace(4) [[NoAS]].ascast
NoAS = (int *)PRIV; NoAS = (int *)PRIV;
// From default address space to named address space // From default address space to named address space
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(4) [[NoAS_LOAD]] to ptr addrspace(1) // CHECK-DAG: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(4) [[NoAS_LOAD]] to ptr addrspace(1)
// CHECK: store ptr addrspace(1) [[NoAS_CAST]], ptr addrspace(4) [[GLOB]].ascast // CHECK-DAG: store ptr addrspace(1) [[NoAS_CAST]], ptr addrspace(4) [[GLOB]].ascast
GLOB = (__attribute__((opencl_global)) int *)NoAS; GLOB = (__attribute__((opencl_global)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(4) [[NoAS_LOAD]] to ptr addrspace(3) // CHECK-DAG: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(4) [[NoAS_LOAD]] to ptr addrspace(3)
// CHECK: store ptr addrspace(3) [[NoAS_CAST]], ptr addrspace(4) [[LOC]].ascast // CHECK-DAG: store ptr addrspace(3) [[NoAS_CAST]], ptr addrspace(4) [[LOC]].ascast
LOC = (__attribute__((opencl_local)) int *)NoAS; LOC = (__attribute__((opencl_local)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(4) [[NoAS_LOAD]] to ptr // CHECK-DAG: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(4) [[NoAS_LOAD]] to ptr
// CHECK: store ptr [[NoAS_CAST]], ptr addrspace(4) [[PRIV]].ascast // CHECK-DAG: store ptr [[NoAS_CAST]], ptr addrspace(4) [[PRIV]].ascast
PRIV = (__attribute__((opencl_private)) int *)NoAS; PRIV = (__attribute__((opencl_private)) int *)NoAS;
// From opencl_global_[host/device] address spaces to opencl_global // From opencl_global_[host/device] address spaces to opencl_global
// CHECK: [[GLOBDEVICE_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(5), ptr addrspace(4) [[GLOB_DEVICE]].ascast // CHECK-DAG: [[GLOBDEVICE_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(5), ptr addrspace(4) [[GLOB_DEVICE]].ascast
// CHECK: [[GLOBDEVICE_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(5) [[GLOBDEVICE_LOAD]] to ptr addrspace(1) // CHECK-DAG: [[GLOBDEVICE_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(5) [[GLOBDEVICE_LOAD]] to ptr addrspace(1)
// CHECK: store ptr addrspace(1) [[GLOBDEVICE_CAST]], ptr addrspace(4) [[GLOB]].ascast // CHECK-DAG: store ptr addrspace(1) [[GLOBDEVICE_CAST]], ptr addrspace(4) [[GLOB]].ascast
GLOB = (__attribute__((opencl_global)) int *)GLOBDEVICE; GLOB = (__attribute__((opencl_global)) int *)GLOBDEVICE;
// CHECK: [[GLOBHOST_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(6), ptr addrspace(4) [[GLOB_HOST]].ascast // CHECK-DAG: [[GLOBHOST_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(6), ptr addrspace(4) [[GLOB_HOST]].ascast
// CHECK: [[GLOBHOST_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(6) [[GLOBHOST_LOAD]] to ptr addrspace(1) // CHECK-DAG: [[GLOBHOST_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(6) [[GLOBHOST_LOAD]] to ptr addrspace(1)
// CHECK: store ptr addrspace(1) [[GLOBHOST_CAST]], ptr addrspace(4) [[GLOB]].ascast // CHECK-DAG: store ptr addrspace(1) [[GLOBHOST_CAST]], ptr addrspace(4) [[GLOB]].ascast
GLOB = (__attribute__((opencl_global)) int *)GLOBHOST; GLOB = (__attribute__((opencl_global)) int *)GLOBHOST;
bar(*GLOB); bar(*GLOB);
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr addrspace(4) [[GLOB]].ascast // CHECK-DAG: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr addrspace(4) [[GLOB]].ascast
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr addrspace(4) // CHECK-DAG: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr addrspace(4)
// CHECK: call spir_func void @[[RAW_REF]](ptr addrspace(4) noundef align 4 dereferenceable(4) [[GLOB_CAST]]) // CHECK-DAG: call spir_func void @[[RAW_REF]](ptr addrspace(4) noundef align 4 dereferenceable(4) [[GLOB_CAST]])
bar2(*GLOB); bar2(*GLOB);
// CHECK: [[GLOB_LOAD2:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr addrspace(4) [[GLOB]].ascast // CHECK-DAG: [[GLOB_LOAD2:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr addrspace(4) [[GLOB]].ascast
// CHECK: [[GLOB_CAST2:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD2]] to ptr addrspace(4) // CHECK-DAG: [[GLOB_CAST2:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD2]] to ptr addrspace(4)
// CHECK: call spir_func void @[[RAW_REF2]](ptr addrspace(4) noundef align 4 dereferenceable(4) [[GLOB_CAST2]]) // CHECK-DAG: call spir_func void @[[RAW_REF2]](ptr addrspace(4) noundef align 4 dereferenceable(4) [[GLOB_CAST2]])
bar(*LOC); bar(*LOC);
// CHECK: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr addrspace(4) [[LOC]].ascast // CHECK-DAG: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr addrspace(4) [[LOC]].ascast
// CHECK: call spir_func void [[LOC_REF]](ptr addrspace(3) noundef align 4 dereferenceable(4) [[LOC_LOAD]]) // CHECK-DAG: call spir_func void [[LOC_REF]](ptr addrspace(3) noundef align 4 dereferenceable(4) [[LOC_LOAD]])
bar2(*LOC); bar2(*LOC);
// CHECK: [[LOC_LOAD2:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr addrspace(4) [[LOC]].ascast // CHECK-DAG: [[LOC_LOAD2:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr addrspace(4) [[LOC]].ascast
// CHECK: [[LOC_CAST2:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD2]] to ptr addrspace(4) // CHECK-DAG: [[LOC_CAST2:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD2]] to ptr addrspace(4)
// CHECK: call spir_func void @[[RAW_REF2]](ptr addrspace(4) noundef align 4 dereferenceable(4) [[LOC_CAST2]]) // CHECK-DAG: call spir_func void @[[RAW_REF2]](ptr addrspace(4) noundef align 4 dereferenceable(4) [[LOC_CAST2]])
bar(*NoAS); bar(*NoAS);
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast
// CHECK: call spir_func void @[[RAW_REF]](ptr addrspace(4) noundef align 4 dereferenceable(4) [[NoAS_LOAD]]) // CHECK-DAG: call spir_func void @[[RAW_REF]](ptr addrspace(4) noundef align 4 dereferenceable(4) [[NoAS_LOAD]])
bar2(*NoAS); bar2(*NoAS);
// CHECK: [[NoAS_LOAD2:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast // CHECK-DAG: [[NoAS_LOAD2:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast
// CHECK: call spir_func void @[[RAW_REF2]](ptr addrspace(4) noundef align 4 dereferenceable(4) [[NoAS_LOAD2]]) // CHECK-DAG: call spir_func void @[[RAW_REF2]](ptr addrspace(4) noundef align 4 dereferenceable(4) [[NoAS_LOAD2]])
foo(GLOB); foo(GLOB);
// CHECK: [[GLOB_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr addrspace(4) [[GLOB]].ascast // CHECK-DAG: [[GLOB_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr addrspace(4) [[GLOB]].ascast
// CHECK: [[GLOB_CAST3:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD3]] to ptr addrspace(4) // CHECK-DAG: [[GLOB_CAST3:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD3]] to ptr addrspace(4)
// CHECK: call spir_func void @[[RAW_PTR]](ptr addrspace(4) noundef [[GLOB_CAST3]]) // CHECK-DAG: call spir_func void @[[RAW_PTR]](ptr addrspace(4) noundef [[GLOB_CAST3]])
foo2(GLOB); foo2(GLOB);
// CHECK: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr addrspace(4) [[GLOB]].ascast // CHECK-DAG: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr addrspace(4) [[GLOB]].ascast
// CHECK: [[GLOB_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD4]] to ptr addrspace(4) // CHECK-DAG: [[GLOB_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD4]] to ptr addrspace(4)
// CHECK: call spir_func void @[[RAW_PTR2]](ptr addrspace(4) noundef [[GLOB_CAST4]]) // CHECK-DAG: call spir_func void @[[RAW_PTR2]](ptr addrspace(4) noundef [[GLOB_CAST4]])
foo(LOC); foo(LOC);
// CHECK: [[LOC_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr addrspace(4) [[LOC]].ascast // CHECK-DAG: [[LOC_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr addrspace(4) [[LOC]].ascast
// CHECK: call spir_func void [[LOC_PTR]](ptr addrspace(3) noundef [[LOC_LOAD3]]) // CHECK-DAG: call spir_func void [[LOC_PTR]](ptr addrspace(3) noundef [[LOC_LOAD3]])
foo2(LOC); foo2(LOC);
// CHECK: [[LOC_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr addrspace(4) [[LOC]].ascast // CHECK-DAG: [[LOC_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr addrspace(4) [[LOC]].ascast
// CHECK: [[LOC_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD4]] to ptr addrspace(4) // CHECK-DAG: [[LOC_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD4]] to ptr addrspace(4)
// CHECK: call spir_func void @[[RAW_PTR2]](ptr addrspace(4) noundef [[LOC_CAST4]]) // CHECK-DAG: call spir_func void @[[RAW_PTR2]](ptr addrspace(4) noundef [[LOC_CAST4]])
foo(NoAS); foo(NoAS);
// CHECK: [[NoAS_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast // CHECK-DAG: [[NoAS_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast
// CHECK: call spir_func void @[[RAW_PTR]](ptr addrspace(4) noundef [[NoAS_LOAD3]]) // CHECK-DAG: call spir_func void @[[RAW_PTR]](ptr addrspace(4) noundef [[NoAS_LOAD3]])
foo2(NoAS); foo2(NoAS);
// CHECK: [[NoAS_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast // CHECK-DAG: [[NoAS_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast
// CHECK: call spir_func void @[[RAW_PTR2]](ptr addrspace(4) noundef [[NoAS_LOAD4]]) // CHECK-DAG: call spir_func void @[[RAW_PTR2]](ptr addrspace(4) noundef [[NoAS_LOAD4]])
// Ensure that we still get 3 different template instantiations. // Ensure that we still get 3 different template instantiations.
tmpl(GLOB); tmpl(GLOB);
// CHECK: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr addrspace(4) [[GLOB]].ascast // CHECK-DAG: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr addrspace(4) [[GLOB]].ascast
// CHECK: call spir_func void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef [[GLOB_LOAD4]]) // CHECK-DAG: call spir_func void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef [[GLOB_LOAD4]])
tmpl(LOC); tmpl(LOC);
// CHECK: [[LOC_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr addrspace(4) [[LOC]].ascast // CHECK-DAG: [[LOC_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr addrspace(4) [[LOC]].ascast
// CHECK: call spir_func void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef [[LOC_LOAD5]]) // CHECK-DAG: call spir_func void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef [[LOC_LOAD5]])
tmpl(PRIV); tmpl(PRIV);
// CHECK: [[PRIV_LOAD5:%[a-zA-Z0-9]+]] = load ptr, ptr addrspace(4) [[PRIV]].ascast // CHECK-DAG: [[PRIV_LOAD5:%[a-zA-Z0-9]+]] = load ptr, ptr addrspace(4) [[PRIV]].ascast
// CHECK: call spir_func void @_Z4tmplIPU3AS0iEvT_(ptr noundef [[PRIV_LOAD5]]) // CHECK-DAG: call spir_func void @_Z4tmplIPU3AS0iEvT_(ptr noundef [[PRIV_LOAD5]])
tmpl(NoAS); tmpl(NoAS);
// CHECK: [[NoAS_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast // CHECK-DAG: [[NoAS_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(4), ptr addrspace(4) [[NoAS]].ascast
// CHECK: call spir_func void @_Z4tmplIPiEvT_(ptr addrspace(4) noundef [[NoAS_LOAD5]]) // CHECK-DAG: call spir_func void @_Z4tmplIPiEvT_(ptr addrspace(4) noundef [[NoAS_LOAD5]])
} }
// CHECK: define linkonce_odr spir_func void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef % // CHECK-DAG: define linkonce_odr spir_func void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef %
// CHECK: define linkonce_odr spir_func void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef % // CHECK-DAG: define linkonce_odr spir_func void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef %
// CHECK: define linkonce_odr spir_func void @_Z4tmplIPU3AS0iEvT_(ptr noundef % // CHECK-DAG: define linkonce_odr spir_func void @_Z4tmplIPU3AS0iEvT_(ptr noundef %
// CHECK: define linkonce_odr spir_func void @_Z4tmplIPiEvT_(ptr addrspace(4) noundef % // CHECK-DAG: define linkonce_odr spir_func void @_Z4tmplIPiEvT_(ptr addrspace(4) noundef %

View File

@ -85,7 +85,7 @@
// CHECK-NEXT: store ptr addrspace(4) addrspacecast (ptr addrspace(1) @.str.1 to ptr addrspace(4)), ptr addrspace(4) [[SELECT_STR_TRIVIAL2_ASCAST]], align 8 // CHECK-NEXT: store ptr addrspace(4) addrspacecast (ptr addrspace(1) @.str.1 to ptr addrspace(4)), ptr addrspace(4) [[SELECT_STR_TRIVIAL2_ASCAST]], align 8
// CHECK-NEXT: ret void // CHECK-NEXT: ret void
// //
void test() { [[clang::sycl_external]] void test() {
static const int foo = 0x42; static const int foo = 0x42;

View File

@ -18,7 +18,7 @@ void foo(int *);
// X86: declare void @_Z3fooPU9SYprivatei(ptr noundef) #1 // X86: declare void @_Z3fooPU9SYprivatei(ptr noundef) #1
// X86: declare void @_Z3fooPi(ptr noundef) #1 // X86: declare void @_Z3fooPi(ptr noundef) #1
void test() { [[clang::sycl_external]] void test() {
__attribute__((opencl_global)) int *glob; __attribute__((opencl_global)) int *glob;
__attribute__((opencl_local)) int *loc; __attribute__((opencl_local)) int *loc;
__attribute__((opencl_private)) int *priv; __attribute__((opencl_private)) int *priv;

View File

@ -1,128 +1,128 @@
// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
void bar(int &Data) {} void bar(int &Data) {}
// CHECK: define dso_local void @[[RAW_REF:[a-zA-Z0-9_]+]](ptr noundef nonnull align 4 dereferenceable(4) % // CHECK-DAG: define {{.*}} void @[[RAW_REF:[a-zA-Z0-9_]+]](ptr noundef nonnull align 4 dereferenceable(4) %
void bar2(int &Data) {} void bar2(int &Data) {}
// CHECK: define dso_local void @[[RAW_REF2:[a-zA-Z0-9_]+]](ptr noundef nonnull align 4 dereferenceable(4) % // CHECK-DAG: define {{.*}} void @[[RAW_REF2:[a-zA-Z0-9_]+]](ptr noundef nonnull align 4 dereferenceable(4) %
void bar(__attribute__((opencl_local)) int &Data) {} void bar(__attribute__((opencl_local)) int &Data) {}
// CHECK: define dso_local void @[[LOCAL_REF:[a-zA-Z0-9_]+]](ptr addrspace(3) noundef align 4 dereferenceable(4) % // CHECK-DAG: define {{.*}} void @[[LOCAL_REF:[a-zA-Z0-9_]+]](ptr addrspace(3) noundef align 4 dereferenceable(4) %
void foo(int *Data) {} void foo(int *Data) {}
// CHECK: define dso_local void @[[RAW_PTR:[a-zA-Z0-9_]+]](ptr noundef % // CHECK-DAG: define {{.*}} void @[[RAW_PTR:[a-zA-Z0-9_]+]](ptr noundef %
void foo2(int *Data) {} void foo2(int *Data) {}
// CHECK: define dso_local void @[[RAW_PTR2:[a-zA-Z0-9_]+]](ptr noundef % // CHECK-DAG: define {{.*}} void @[[RAW_PTR2:[a-zA-Z0-9_]+]](ptr noundef %
void foo(__attribute__((opencl_local)) int *Data) {} void foo(__attribute__((opencl_local)) int *Data) {}
// CHECK: define dso_local void @[[LOC_PTR:[a-zA-Z0-9_]+]](ptr addrspace(3) noundef % // CHECK-DAG: define {{.*}} void @[[LOC_PTR:[a-zA-Z0-9_]+]](ptr addrspace(3) noundef %
template <typename T> template <typename T>
void tmpl(T t); void tmpl(T t) {}
// See Check Lines below. // See Check Lines below.
void usages() { [[clang::sycl_external]] void usages() {
int *NoAS; int *NoAS;
// CHECK: [[NoAS:%[a-zA-Z0-9]+]] = alloca ptr, align 8, addrspace(5) // CHECK-DAG: [[NoAS:%[a-zA-Z0-9]+]] = alloca ptr, align 8, addrspace(5)
__attribute__((opencl_global)) int *GLOB; __attribute__((opencl_global)) int *GLOB;
// CHECK: [[GLOB:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8, addrspace(5) // CHECK-DAG: [[GLOB:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8, addrspace(5)
__attribute__((opencl_local)) int *LOC; __attribute__((opencl_local)) int *LOC;
// CHECK: [[LOC:%[a-zA-Z0-9]+]] = alloca ptr addrspace(3), align 4, addrspace(5) // CHECK-DAG: [[LOC:%[a-zA-Z0-9]+]] = alloca ptr addrspace(3), align 4, addrspace(5)
__attribute__((opencl_private)) int *PRIV; __attribute__((opencl_private)) int *PRIV;
// CHECK: [[PRIV:%[a-zA-Z0-9]+]] = alloca ptr addrspace(5), align 4, addrspace(5) // CHECK-DAG: [[PRIV:%[a-zA-Z0-9]+]] = alloca ptr addrspace(5), align 4, addrspace(5)
__attribute__((opencl_global_device)) int *GLOBDEVICE; __attribute__((opencl_global_device)) int *GLOBDEVICE;
// CHECK: [[GLOB_DEVICE:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8, addrspace(5) // CHECK-DAG: [[GLOB_DEVICE:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8, addrspace(5)
__attribute__((opencl_global_host)) int *GLOBHOST; __attribute__((opencl_global_host)) int *GLOBHOST;
// CHECK: [[GLOB_HOST:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8, addrspace(5) // CHECK-DAG: [[GLOB_HOST:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8, addrspace(5)
LOC = nullptr; LOC = nullptr;
// CHECK: store ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)), ptr [[LOC]].ascast, align 4 // CHECK-DAG: store ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)), ptr [[LOC]].ascast, align 4
GLOB = nullptr; GLOB = nullptr;
// CHECK: store ptr addrspace(1) null, ptr [[GLOB]].ascast, align 8 // CHECK-DAG: store ptr addrspace(1) null, ptr [[GLOB]].ascast, align 8
NoAS = (int *)GLOB; NoAS = (int *)GLOB;
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8 // CHECK-DAG: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr // CHECK-DAG: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr
// CHECK: store ptr [[GLOB_CAST]], ptr [[NoAS]].ascast, align 8 // CHECK-DAG: store ptr [[GLOB_CAST]], ptr [[NoAS]].ascast, align 8
NoAS = (int *)LOC; NoAS = (int *)LOC;
// CHECK: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4 // CHECK-DAG: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4
// CHECK: [[LOC_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD]] to ptr // CHECK-DAG: [[LOC_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD]] to ptr
// CHECK: store ptr [[LOC_CAST]], ptr [[NoAS]].ascast, align 8 // CHECK-DAG: store ptr [[LOC_CAST]], ptr [[NoAS]].ascast, align 8
NoAS = (int *)PRIV; NoAS = (int *)PRIV;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(5), ptr [[PRIV]].ascast, align 4 // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(5), ptr [[PRIV]].ascast, align 4
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(5) [[NoAS_LOAD]] to ptr // CHECK-DAG: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(5) [[NoAS_LOAD]] to ptr
// CHECK: store ptr %5, ptr [[NoAS]].ascast, align 8 // CHECK-DAG: store ptr %5, ptr [[NoAS]].ascast, align 8
GLOB = (__attribute__((opencl_global)) int *)NoAS; GLOB = (__attribute__((opencl_global)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8 // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr %6 to ptr addrspace(1) // CHECK-DAG: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr %6 to ptr addrspace(1)
// CHECK: store ptr addrspace(1) %7, ptr [[GLOB]].ascast, align 8 // CHECK-DAG: store ptr addrspace(1) %7, ptr [[GLOB]].ascast, align 8
LOC = (__attribute__((opencl_local)) int *)NoAS; LOC = (__attribute__((opencl_local)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8 // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[NoAS_LOAD]] to ptr addrspace(3) // CHECK-DAG: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[NoAS_LOAD]] to ptr addrspace(3)
// CHECK: store ptr addrspace(3) %9, ptr [[LOC]].ascast, align 4 // CHECK-DAG: store ptr addrspace(3) %9, ptr [[LOC]].ascast, align 4
PRIV = (__attribute__((opencl_private)) int *)NoAS; PRIV = (__attribute__((opencl_private)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8 // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[NoAS_LOAD]] to ptr addrspace(5) // CHECK-DAG: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[NoAS_LOAD]] to ptr addrspace(5)
// CHECK: store ptr addrspace(5) [[NoAS_CAST]], ptr [[PRIV]].ascast, align 4 // CHECK-DAG: store ptr addrspace(5) [[NoAS_CAST]], ptr [[PRIV]].ascast, align 4
GLOB = (__attribute__((opencl_global)) int *)GLOBDEVICE; GLOB = (__attribute__((opencl_global)) int *)GLOBDEVICE;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]]DEVICE.ascast, align 8 // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]]DEVICE.ascast, align 8
// CHECK: store ptr addrspace(1) [[NoAS_LOAD]], ptr [[GLOB]].ascast, align 8 // CHECK-DAG: store ptr addrspace(1) [[NoAS_LOAD]], ptr [[GLOB]].ascast, align 8
GLOB = (__attribute__((opencl_global)) int *)GLOBHOST; GLOB = (__attribute__((opencl_global)) int *)GLOBHOST;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]]HOST.ascast, align 8 // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]]HOST.ascast, align 8
// CHECK: tore ptr addrspace(1) [[NoAS_LOAD]], ptr [[GLOB]].ascast, align 8 // CHECK-DAG: tore ptr addrspace(1) [[NoAS_LOAD]], ptr [[GLOB]].ascast, align 8
bar(*GLOB); bar(*GLOB);
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8 // CHECK-DAG: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr // CHECK-DAG: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr
// CHECK: call void @[[RAW_REF]](ptr noundef nonnull align 4 dereferenceable(4) [[GLOB_CAST]]) // CHECK-DAG: call void @[[RAW_REF]](ptr noundef nonnull align 4 dereferenceable(4) [[GLOB_CAST]])
bar2(*GLOB); bar2(*GLOB);
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8 // CHECK-DAG: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr // CHECK-DAG: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr
// CHECK: call void @[[RAW_REF2]](ptr noundef nonnull align 4 dereferenceable(4) [[GLOB_CAST]]) // CHECK-DAG: call void @[[RAW_REF2]](ptr noundef nonnull align 4 dereferenceable(4) [[GLOB_CAST]])
bar(*LOC); bar(*LOC);
// CHECK: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4 // CHECK-DAG: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4
// CHECK: call void @_Z3barRU3AS3i(ptr addrspace(3) noundef align 4 dereferenceable(4) [[LOC_LOAD]]) // CHECK-DAG: call void @_Z3barRU3AS3i(ptr addrspace(3) noundef align 4 dereferenceable(4) [[LOC_LOAD]])
bar2(*LOC); bar2(*LOC);
// CHECK: [[LOC_LOAD2:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4 // CHECK-DAG: [[LOC_LOAD2:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4
// CHECK: [[LOC_CAST2:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD2]] to ptr // CHECK-DAG: [[LOC_CAST2:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD2]] to ptr
// CHECK: call void @_Z4bar2Ri(ptr noundef nonnull align 4 dereferenceable(4) [[LOC_CAST2]]) // CHECK-DAG: call void @_Z4bar2Ri(ptr noundef nonnull align 4 dereferenceable(4) [[LOC_CAST2]])
bar(*NoAS); bar(*NoAS);
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8 // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: call void @_Z3barRi(ptr noundef nonnull align 4 dereferenceable(4) [[NoAS_LOAD]]) // CHECK-DAG: call void @_Z3barRi(ptr noundef nonnull align 4 dereferenceable(4) [[NoAS_LOAD]])
bar2(*NoAS); bar2(*NoAS);
// CHECK: [[NoAS_LOAD2:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8 // CHECK-DAG: [[NoAS_LOAD2:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: call void @_Z4bar2Ri(ptr noundef nonnull align 4 dereferenceable(4) [[NoAS_LOAD2]]) // CHECK-DAG: call void @_Z4bar2Ri(ptr noundef nonnull align 4 dereferenceable(4) [[NoAS_LOAD2]])
foo(GLOB); foo(GLOB);
// CHECK: [[GLOB_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8 // CHECK-DAG: [[GLOB_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8
// CHECK: [[GLOB_CAST3:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD3]] to ptr // CHECK-DAG: [[GLOB_CAST3:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD3]] to ptr
// CHECK: call void @[[RAW_PTR]](ptr noundef [[GLOB_CAST3]]) // CHECK-DAG: call void @[[RAW_PTR]](ptr noundef [[GLOB_CAST3]])
foo2(GLOB); foo2(GLOB);
// CHECK: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8 // CHECK-DAG: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8
// CHECK: [[GLOB_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD4]] to ptr // CHECK-DAG: [[GLOB_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD4]] to ptr
// CHECK: call void @[[RAW_PTR2]](ptr noundef [[GLOB_CAST4]]) // CHECK-DAG: call void @[[RAW_PTR2]](ptr noundef [[GLOB_CAST4]])
foo(LOC); foo(LOC);
// CHECK: [[LOC_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4 // CHECK-DAG: [[LOC_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4
// CHECK: call void @[[LOC_PTR]](ptr addrspace(3) noundef [[LOC_LOAD3]]) // CHECK-DAG: call void @[[LOC_PTR]](ptr addrspace(3) noundef [[LOC_LOAD3]])
foo2(LOC); foo2(LOC);
// CHECK: [[LOC_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4 // CHECK-DAG: [[LOC_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4
// CHECK: [[LOC_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD4]] to ptr // CHECK-DAG: [[LOC_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD4]] to ptr
// CHECK: call void @[[RAW_PTR2]](ptr noundef [[LOC_CAST4]]) // CHECK-DAG: call void @[[RAW_PTR2]](ptr noundef [[LOC_CAST4]])
foo(NoAS); foo(NoAS);
// CHECK: [[NoAS_LOAD3:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8 // CHECK-DAG: [[NoAS_LOAD3:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: call void @[[RAW_PTR]](ptr noundef [[NoAS_LOAD3]]) // CHECK-DAG: call void @[[RAW_PTR]](ptr noundef [[NoAS_LOAD3]])
foo2(NoAS); foo2(NoAS);
// CHECK: [[NoAS_LOAD4:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8 // CHECK-DAG: [[NoAS_LOAD4:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: call void @[[RAW_PTR2]](ptr noundef [[NoAS_LOAD4]]) // CHECK-DAG: call void @[[RAW_PTR2]](ptr noundef [[NoAS_LOAD4]])
// Ensure that we still get 3 different template instantiations. // Ensure that we still get 3 different template instantiations.
tmpl(GLOB); tmpl(GLOB);
// CHECK: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8 // CHECK-DAG: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]].ascast, align 8
// CHECK: call void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef [[GLOB_LOAD4]]) // CHECK-DAG: call void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef [[GLOB_LOAD4]])
tmpl(LOC); tmpl(LOC);
// CHECK: [[LOC_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4 // CHECK-DAG: [[LOC_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]].ascast, align 4
// CHECK: call void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef [[LOC_LOAD5]]) // CHECK-DAG: call void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef [[LOC_LOAD5]])
tmpl(PRIV); tmpl(PRIV);
// CHECK: [[PRIV_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(5), ptr [[PRIV]].ascast, align 4 // CHECK-DAG: [[PRIV_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(5), ptr [[PRIV]].ascast, align 4
// CHECK: call void @_Z4tmplIPU3AS5iEvT_(ptr addrspace(5) noundef [[PRIV_LOAD5]]) // CHECK-DAG: call void @_Z4tmplIPU3AS5iEvT_(ptr addrspace(5) noundef [[PRIV_LOAD5]])
tmpl(NoAS); tmpl(NoAS);
// CHECK: [[NoAS_LOAD5:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8 // CHECK-DAG: [[NoAS_LOAD5:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]].ascast, align 8
// CHECK: call void @_Z4tmplIPiEvT_(ptr noundef [[NoAS_LOAD5]]) // CHECK-DAG: call void @_Z4tmplIPiEvT_(ptr noundef [[NoAS_LOAD5]])
} }
// CHECK: declare void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef) // CHECK-DAG: define linkonce_odr void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef %
// CHECK: declare void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef) // CHECK-DAG: define linkonce_odr void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef %
// CHECK: declare void @_Z4tmplIPU3AS5iEvT_(ptr addrspace(5) noundef) // CHECK-DAG: define linkonce_odr void @_Z4tmplIPU3AS5iEvT_(ptr addrspace(5) noundef %
// CHECK: declare void @_Z4tmplIPiEvT_(ptr noundef) // CHECK-DAG: define linkonce_odr void @_Z4tmplIPiEvT_(ptr noundef %

View File

@ -1,122 +1,122 @@
// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
void bar(int &Data) {} void bar(int &Data) {}
// CHECK: define dso_local void @[[RAW_REF:[a-zA-Z0-9_]+]](ptr noundef nonnull align 4 dereferenceable(4) % // CHECK-DAG: define {{.*}} void @[[RAW_REF:[a-zA-Z0-9_]+]](ptr noundef nonnull align 4 dereferenceable(4) %
void bar2(int &Data) {} void bar2(int &Data) {}
// CHECK: define dso_local void @[[RAW_REF2:[a-zA-Z0-9_]+]](ptr noundef nonnull align 4 dereferenceable(4) % // CHECK-DAG: define {{.*}} void @[[RAW_REF2:[a-zA-Z0-9_]+]](ptr noundef nonnull align 4 dereferenceable(4) %
void bar(__attribute__((opencl_local)) int &Data) {} void bar(__attribute__((opencl_local)) int &Data) {}
// CHECK: define dso_local void @[[LOCAL_REF:[a-zA-Z0-9_]+]](ptr addrspace(3) noundef align 4 dereferenceable(4) % // CHECK-DAG: define {{.*}} void @[[LOCAL_REF:[a-zA-Z0-9_]+]](ptr addrspace(3) noundef align 4 dereferenceable(4) %
void foo(int *Data) {} void foo(int *Data) {}
// CHECK: define dso_local void @[[RAW_PTR:[a-zA-Z0-9_]+]](ptr noundef % // CHECK-DAG: define {{.*}} void @[[RAW_PTR:[a-zA-Z0-9_]+]](ptr noundef %
void foo2(int *Data) {} void foo2(int *Data) {}
// CHECK: define dso_local void @[[RAW_PTR2:[a-zA-Z0-9_]+]](ptr noundef % // CHECK-DAG: define {{.*}} void @[[RAW_PTR2:[a-zA-Z0-9_]+]](ptr noundef %
void foo(__attribute__((opencl_local)) int *Data) {} void foo(__attribute__((opencl_local)) int *Data) {}
// CHECK: define dso_local void @[[LOC_PTR:[a-zA-Z0-9_]+]](ptr addrspace(3) noundef % // CHECK-DAG: define {{.*}} void @[[LOC_PTR:[a-zA-Z0-9_]+]](ptr addrspace(3) noundef %
template <typename T> template <typename T>
void tmpl(T t); void tmpl(T t);
// See Check Lines below. // See Check Lines below.
void usages() { [[clang::sycl_external]] void usages() {
int *NoAS; int *NoAS;
// CHECK: [[NoAS:%[a-zA-Z0-9]+]] = alloca ptr, align 8 // CHECK-DAG: [[NoAS:%[a-zA-Z0-9]+]] = alloca ptr, align 8
__attribute__((opencl_global)) int *GLOB; __attribute__((opencl_global)) int *GLOB;
// CHECK: [[GLOB:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8 // CHECK-DAG: [[GLOB:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8
__attribute__((opencl_local)) int *LOC; __attribute__((opencl_local)) int *LOC;
// CHECK: [[LOC:%[a-zA-Z0-9]+]] = alloca ptr addrspace(3), align 8 // CHECK-DAG: [[LOC:%[a-zA-Z0-9]+]] = alloca ptr addrspace(3), align 8
__attribute__((opencl_private)) int *PRIV; __attribute__((opencl_private)) int *PRIV;
// CHECK: [[PRIV:%[a-zA-Z0-9]+]] = alloca ptr, align 8 // CHECK-DAG: [[PRIV:%[a-zA-Z0-9]+]] = alloca ptr, align 8
__attribute__((opencl_global_device)) int *GLOBDEVICE; __attribute__((opencl_global_device)) int *GLOBDEVICE;
// CHECK: [[GLOB_DEVICE:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8 // CHECK-DAG: [[GLOB_DEVICE:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8
__attribute__((opencl_global_host)) int *GLOBHOST; __attribute__((opencl_global_host)) int *GLOBHOST;
// CHECK: [[GLOB_HOST:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8 // CHECK-DAG: [[GLOB_HOST:%[a-zA-Z0-9]+]] = alloca ptr addrspace(1), align 8
LOC = nullptr; LOC = nullptr;
// CHECK: store ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)), ptr [[LOC]], align 8 // CHECK-DAG: store ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)), ptr [[LOC]], align 8
GLOB = nullptr; GLOB = nullptr;
// CHECK: store ptr addrspace(1) null, ptr [[GLOB]], align 8 // CHECK-DAG: store ptr addrspace(1) null, ptr [[GLOB]], align 8
NoAS = (int *)GLOB; NoAS = (int *)GLOB;
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8 // CHECK-DAG: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr // CHECK-DAG: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr
// CHECK: store ptr [[GLOB_CAST]], ptr [[NoAS]], align 8 // CHECK-DAG: store ptr [[GLOB_CAST]], ptr [[NoAS]], align 8
NoAS = (int *)LOC; NoAS = (int *)LOC;
// CHECK: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8 // CHECK-DAG: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8
// CHECK: [[LOC_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD]] to ptr // CHECK-DAG: [[LOC_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD]] to ptr
// CHECK: store ptr [[LOC_CAST]], ptr [[NoAS]], align 8 // CHECK-DAG: store ptr [[LOC_CAST]], ptr [[NoAS]], align 8
NoAS = (int *)PRIV; NoAS = (int *)PRIV;
// CHECK: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[PRIV]], align 8 // CHECK-DAG: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[PRIV]], align 8
// CHECK: store ptr [[LOC_LOAD]], ptr [[NoAS]], align 8 // CHECK-DAG: store ptr [[LOC_LOAD]], ptr [[NoAS]], align 8
GLOB = (__attribute__((opencl_global)) int *)NoAS; GLOB = (__attribute__((opencl_global)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8 // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[NoAS_LOAD]] to ptr addrspace(1) // CHECK-DAG: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[NoAS_LOAD]] to ptr addrspace(1)
// CHECK: store ptr addrspace(1) [[NoAS_CAST]], ptr [[GLOB]], align 8 // CHECK-DAG: store ptr addrspace(1) [[NoAS_CAST]], ptr [[GLOB]], align 8
LOC = (__attribute__((opencl_local)) int *)NoAS; LOC = (__attribute__((opencl_local)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8 // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[NoAS_LOAD]] to ptr addrspace(3) // CHECK-DAG: [[NoAS_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr [[NoAS_LOAD]] to ptr addrspace(3)
// CHECK: store ptr addrspace(3) [[NoAS_CAST]], ptr [[LOC]], align 8 // CHECK-DAG: store ptr addrspace(3) [[NoAS_CAST]], ptr [[LOC]], align 8
PRIV = (__attribute__((opencl_private)) int *)NoAS; PRIV = (__attribute__((opencl_private)) int *)NoAS;
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8 // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: store ptr [[NoAS_LOAD]], ptr [[PRIV]], align 8 // CHECK-DAG: store ptr [[NoAS_LOAD]], ptr [[PRIV]], align 8
GLOB = (__attribute__((opencl_global)) int *)GLOBDEVICE; GLOB = (__attribute__((opencl_global)) int *)GLOBDEVICE;
// CHECK: [[GLOBDEVICE_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB_DEVICE]], align 8 // CHECK-DAG: [[GLOBDEVICE_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB_DEVICE]], align 8
// CHECK: store ptr addrspace(1) [[GLOBDEVICE_LOAD]], ptr %GLOB, align 8 // CHECK-DAG: store ptr addrspace(1) [[GLOBDEVICE_LOAD]], ptr %GLOB, align 8
GLOB = (__attribute__((opencl_global)) int *)GLOBHOST; GLOB = (__attribute__((opencl_global)) int *)GLOBHOST;
// CHECK: [[GLOB_HOST_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB_HOST]], align 8 // CHECK-DAG: [[GLOB_HOST_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB_HOST]], align 8
// CHECK: store ptr addrspace(1) [[GLOB_HOST_LOAD]], ptr [[GLOB]], align 8 // CHECK-DAG: store ptr addrspace(1) [[GLOB_HOST_LOAD]], ptr [[GLOB]], align 8
bar(*GLOB); bar(*GLOB);
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8 // CHECK-DAG: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr // CHECK-DAG: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr
// CHECK: call void @[[RAW_REF]](ptr noundef nonnull align 4 dereferenceable(4) [[GLOB_CAST]]) // CHECK-DAG: call void @[[RAW_REF]](ptr noundef nonnull align 4 dereferenceable(4) [[GLOB_CAST]])
bar2(*GLOB); bar2(*GLOB);
// CHECK: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8 // CHECK-DAG: [[GLOB_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8
// CHECK: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr // CHECK-DAG: [[GLOB_CAST:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD]] to ptr
// CHECK: call void @[[RAW_REF2]](ptr noundef nonnull align 4 dereferenceable(4) [[GLOB_CAST]]) // CHECK-DAG: call void @[[RAW_REF2]](ptr noundef nonnull align 4 dereferenceable(4) [[GLOB_CAST]])
bar(*LOC); bar(*LOC);
// CHECK: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8 // CHECK-DAG: [[LOC_LOAD:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8
// CHECK: call void @[[LOCAL_REF]](ptr addrspace(3) noundef align 4 dereferenceable(4) [[LOC_LOAD]]) // CHECK-DAG: call void @[[LOCAL_REF]](ptr addrspace(3) noundef align 4 dereferenceable(4) [[LOC_LOAD]])
bar2(*LOC); bar2(*LOC);
// CHECK: [[LOC_LOAD2:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8 // CHECK-DAG: [[LOC_LOAD2:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8
// CHECK: [[LOC_CAST2:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD2]] to ptr // CHECK-DAG: [[LOC_CAST2:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD2]] to ptr
// CHECK: call void @[[RAW_REF2]](ptr noundef nonnull align 4 dereferenceable(4) [[LOC_CAST2]]) // CHECK-DAG: call void @[[RAW_REF2]](ptr noundef nonnull align 4 dereferenceable(4) [[LOC_CAST2]])
bar(*NoAS); bar(*NoAS);
// CHECK: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8 // CHECK-DAG: [[NoAS_LOAD:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: call void @[[RAW_REF]](ptr noundef nonnull align 4 dereferenceable(4) [[NoAS_LOAD]]) // CHECK-DAG: call void @[[RAW_REF]](ptr noundef nonnull align 4 dereferenceable(4) [[NoAS_LOAD]])
bar2(*NoAS); bar2(*NoAS);
// CHECK: [[NoAS_LOAD2:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8 // CHECK-DAG: [[NoAS_LOAD2:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: call void @[[RAW_REF2]](ptr noundef nonnull align 4 dereferenceable(4) [[NoAS_LOAD2]]) // CHECK-DAG: call void @[[RAW_REF2]](ptr noundef nonnull align 4 dereferenceable(4) [[NoAS_LOAD2]])
foo(GLOB); foo(GLOB);
// CHECK: [[GLOB_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8 // CHECK-DAG: [[GLOB_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8
// CHECK: [[GLOB_CAST3:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD3]] to ptr // CHECK-DAG: [[GLOB_CAST3:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD3]] to ptr
// CHECK: call void @[[RAW_PTR]](ptr noundef [[GLOB_CAST3]]) // CHECK-DAG: call void @[[RAW_PTR]](ptr noundef [[GLOB_CAST3]])
foo2(GLOB); foo2(GLOB);
// CHECK: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8 // CHECK-DAG: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8
// CHECK: [[GLOB_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD4]] to ptr // CHECK-DAG: [[GLOB_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(1) [[GLOB_LOAD4]] to ptr
// CHECK: call void @[[RAW_PTR2]](ptr noundef [[GLOB_CAST4]]) // CHECK-DAG: call void @[[RAW_PTR2]](ptr noundef [[GLOB_CAST4]])
foo(LOC); foo(LOC);
// CHECK: [[LOC_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8 // CHECK-DAG: [[LOC_LOAD3:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8
// CHECK: call void @[[LOC_PTR]](ptr addrspace(3) noundef [[LOC_LOAD3]]) // CHECK-DAG: call void @[[LOC_PTR]](ptr addrspace(3) noundef [[LOC_LOAD3]])
foo2(LOC); foo2(LOC);
// CHECK: [[LOC_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8 // CHECK-DAG: [[LOC_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8
// CHECK: [[LOC_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD4]] to ptr // CHECK-DAG: [[LOC_CAST4:%[a-zA-Z0-9]+]] = addrspacecast ptr addrspace(3) [[LOC_LOAD4]] to ptr
// CHECK: call void @[[RAW_PTR2]](ptr noundef [[LOC_CAST4]]) // CHECK-DAG: call void @[[RAW_PTR2]](ptr noundef [[LOC_CAST4]])
foo(NoAS); foo(NoAS);
// CHECK: [[NoAS_LOAD3:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8 // CHECK-DAG: [[NoAS_LOAD3:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: call void @[[RAW_PTR]](ptr noundef [[NoAS_LOAD3]]) // CHECK-DAG: call void @[[RAW_PTR]](ptr noundef [[NoAS_LOAD3]])
foo2(NoAS); foo2(NoAS);
// CHECK: [[NoAS_LOAD4:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8 // CHECK-DAG: [[NoAS_LOAD4:%[a-zA-Z0-9]+]] = load ptr, ptr [[NoAS]], align 8
// CHECK: call void @[[RAW_PTR2]](ptr noundef [[NoAS_LOAD4]]) // CHECK-DAG: call void @[[RAW_PTR2]](ptr noundef [[NoAS_LOAD4]])
tmpl(GLOB); tmpl(GLOB);
// CHECK: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8 // CHECK-DAG: [[GLOB_LOAD4:%[a-zA-Z0-9]+]] = load ptr addrspace(1), ptr [[GLOB]], align 8
// CHECK: call void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef [[GLOB_LOAD4]]) // CHECK-DAG: call void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef [[GLOB_LOAD4]])
tmpl(LOC); tmpl(LOC);
// CHECK: [[LOC_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8 // CHECK-DAG: [[LOC_LOAD5:%[a-zA-Z0-9]+]] = load ptr addrspace(3), ptr [[LOC]], align 8
// CHECK: call void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef [[LOC_LOAD5]]) // CHECK-DAG: call void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef [[LOC_LOAD5]])
tmpl(PRIV); tmpl(PRIV);
// CHECK: [[PRIV_LOAD5:%[a-zA-Z0-9]+]] = load ptr, ptr [[PRIV]], align 8 // CHECK-DAG: [[PRIV_LOAD5:%[a-zA-Z0-9]+]] = load ptr, ptr [[PRIV]], align 8
// CHECK: call void @_Z4tmplIPiEvT_(ptr noundef [[PRIV_LOAD5]]) // CHECK-DAG: call void @_Z4tmplIPiEvT_(ptr noundef [[PRIV_LOAD5]])
tmpl(NoAS); tmpl(NoAS);
// CHECK: %33 = load ptr, ptr %NoAS, align 8 // CHECK-DAG: %33 = load ptr, ptr %NoAS, align 8
// CHECK: call void @_Z4tmplIPiEvT_(ptr noundef %33) // CHECK-DAG: call void @_Z4tmplIPiEvT_(ptr noundef %33)
} }
// CHECK: declare void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef) // CHECK-DAG: void @_Z4tmplIPU3AS1iEvT_(ptr addrspace(1) noundef
// CHECK: declare void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef) // CHECK-DAG: void @_Z4tmplIPU3AS3iEvT_(ptr addrspace(3) noundef
// CHECK: declare void @_Z4tmplIPiEvT_(ptr noundef) // CHECK-DAG: void @_Z4tmplIPiEvT_(ptr noundef

View File

@ -18,7 +18,7 @@ KERNEL void parallel_for(const KernelType &KernelFunc) {
KernelFunc(); KernelFunc();
} }
void my_kernel(int my_param) { [[clang::sycl_external]] void my_kernel(int my_param) {
int my_local = 0; int my_local = 0;
my_local = my_param; my_local = my_param;
} }

View File

@ -9,7 +9,7 @@ struct HasField {
int *a; int *a;
}; };
void foo(int *b) { [[clang::sycl_external]] void foo(int *b) {
struct HasField f; struct HasField f;
// CHECK: %[[A:.+]] = getelementptr inbounds nuw %struct.HasField, ptr addrspace(4) %{{.+}} // CHECK: %[[A:.+]] = getelementptr inbounds nuw %struct.HasField, ptr addrspace(4) %{{.+}}
// CHECK: %[[CALL:.+]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p1(ptr addrspace(4) %[[A]], ptr addrspace(1) [[ANNOT]] // CHECK: %[[CALL:.+]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p1(ptr addrspace(4) %[[A]], ptr addrspace(1) [[ANNOT]]

View File

@ -5,11 +5,11 @@
int foo(); int foo();
// CHECK-LABEL: define dso_local spir_func void @_Z3barv( // CHECK-LABEL: define dso_local spir_func void @_Z3barv(
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { // CHECK-SAME: ) #[[ATTR2:[0-9]+]] {
// CHECK-NEXT: entry: // CHECK-NEXT: entry:
// CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[A_ASCAST:%.*]] = addrspacecast ptr [[A]] to ptr addrspace(4) // CHECK-NEXT: [[A_ASCAST:%.*]] = addrspacecast ptr [[A]] to ptr addrspace(4)
// CHECK-NEXT: [[CALL:%.*]] = call spir_func noundef i32 @_Z3foov() #[[ATTR1:[0-9]+]] // CHECK-NEXT: [[CALL:%.*]] = call spir_func noundef i32 @_Z3foov() #[[ATTR3:[0-9]+]]
// CHECK-NEXT: store i32 [[CALL]], ptr addrspace(4) [[A_ASCAST]], align 4 // CHECK-NEXT: store i32 [[CALL]], ptr addrspace(4) [[A_ASCAST]], align 4
// CHECK-NEXT: ret void // CHECK-NEXT: ret void
// //
@ -18,7 +18,7 @@ void bar() {
} }
// CHECK-LABEL: define dso_local spir_func noundef i32 @_Z3foov( // CHECK-LABEL: define dso_local spir_func noundef i32 @_Z3foov(
// CHECK-SAME: ) #[[ATTR0]] { // CHECK-SAME: ) #[[ATTR2]] {
// CHECK-NEXT: entry: // CHECK-NEXT: entry:
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr [[RETVAL]] to ptr addrspace(4) // CHECK-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr [[RETVAL]] to ptr addrspace(4)
@ -29,21 +29,10 @@ int foo() {
} }
template <typename Name, typename Func> template <typename Name, typename Func>
__attribute__((sycl_kernel)) void kernel_single_task(const Func &kernelFunc) { [[clang::sycl_kernel_entry_point(Name)]] void kernel_single_task(const Func &kernelFunc) {
kernelFunc(); kernelFunc();
} }
// CHECK-LABEL: define dso_local noundef i32 @main(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON:%.*]], align 1
// CHECK-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr [[RETVAL]] to ptr addrspace(4)
// CHECK-NEXT: [[REF_TMP_ASCAST:%.*]] = addrspacecast ptr [[REF_TMP]] to ptr addrspace(4)
// CHECK-NEXT: store i32 0, ptr addrspace(4) [[RETVAL_ASCAST]], align 4
// CHECK-NEXT: call spir_func void @_Z18kernel_single_taskIZ4mainE11fake_kernelZ4mainEUlvE_EvRKT0_(ptr addrspace(4) noundef align 1 dereferenceable(1) [[REF_TMP_ASCAST]]) #[[ATTR1]]
// CHECK-NEXT: ret i32 0
//
int main() { int main() {
kernel_single_task<class fake_kernel>([] { bar(); }); kernel_single_task<class fake_kernel>([] { bar(); });
return 0; return 0;
@ -52,5 +41,5 @@ int main() {
// CHECK: attributes #0 = { convergent mustprogress noinline norecurse nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } // CHECK: attributes #0 = { convergent mustprogress noinline norecurse nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
// CHECK: attributes #1 = { convergent nounwind } // CHECK: attributes #1 = { convergent nounwind }
//. //.
// CHECK: !0 = !{i32 1, !"wchar_size", i32 4} // CHECK: !{{[0-9]+}} = !{i32 1, !"wchar_size", i32 4}
//. //.

View File

@ -8,7 +8,7 @@ __attribute__((sycl_kernel)) void kernel_single_task(const Func &kernelFunc) {
} }
// CHECK: define dso_local spir_func{{.*}}invoke_function{{.*}}(ptr noundef %fptr, ptr addrspace(4) noundef %ptr) // CHECK: define dso_local spir_func{{.*}}invoke_function{{.*}}(ptr noundef %fptr, ptr addrspace(4) noundef %ptr)
void invoke_function(int (*fptr)(), int *ptr) {} [[clang::sycl_external]] void invoke_function(int (*fptr)(), int *ptr) {}
int f() { return 0; } int f() { return 0; }

View File

@ -100,11 +100,8 @@ int main() {
// Verify that SYCL kernel caller functions are emitted for each device target. // Verify that SYCL kernel caller functions are emitted for each device target.
// //
// FIXME: The following set of matches are used to skip over the declaration of // main() shouldn't be emitted in device code.
// main(). main() shouldn't be emitted in device code, but that pruning isn't // CHECK-NOT: @main()
// performed yet.
// CHECK-DEVICE: Function Attrs: convergent mustprogress noinline norecurse nounwind optnone
// CHECK-DEVICE-NEXT: define {{[a-z_ ]*}}noundef i32 @main() #0
// IR for the SYCL kernel caller function generated for // IR for the SYCL kernel caller function generated for
// single_purpose_kernel_task with single_purpose_kernel_name as the SYCL kernel // single_purpose_kernel_task with single_purpose_kernel_name as the SYCL kernel

View File

@ -0,0 +1,85 @@
// RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-unknown -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
// This test code generation when sycl_external attribute is used
// Function defined and not used - symbols emitted
[[clang::sycl_external]] int square(int x) { return x*x; }
// CHECK: define dso_local spir_func noundef i32 @_Z6squarei
// Function defined and used - symbols emitted
[[clang::sycl_external]] int squareUsed(int x) { return x*x; }
// CHECK: define dso_local spir_func noundef i32 @_Z10squareUsedi
// FIXME: Constexpr function defined and not used - symbols emitted
[[clang::sycl_external]] constexpr int squareInlined(int x) { return x*x; }
// CHECK: define linkonce_odr spir_func noundef i32 @_Z13squareInlinedi
// Function declared but not defined or used - no symbols emitted
[[clang::sycl_external]] int declOnly();
// CHECK-NOT: define {{.*}} i32 @_Z8declOnlyv
// CHECK-NOT: declare {{.*}} i32 @_Z8declOnlyv
// Function declared and used in host but not defined - no symbols emitted
[[clang::sycl_external]] void declUsedInHost(int y);
// Function declared and used in device but not defined - emit external reference
[[clang::sycl_external]] void declUsedInDevice(int y);
// CHECK: define dso_local spir_func void @_Z9deviceUsev
[[clang::sycl_external]] void deviceUse() { declUsedInDevice(3); }
// CHECK: declare spir_func void @_Z16declUsedInDevicei
// Function declared with the attribute and later defined - definition emitted
[[clang::sycl_external]] int func1(int arg);
int func1(int arg) { return arg; }
// CHECK: define dso_local spir_func noundef i32 @_Z5func1i
class A {
// Unused defaulted special member functions - no symbols emitted
[[clang::sycl_external]] A& operator=(A& a) = default;
};
class B {
[[clang::sycl_external]] virtual void BFunc1WithAttr() { int i = 1; }
// CHECK: define linkonce_odr spir_func void @_ZN1B14BFunc1WithAttrEv
virtual void BFunc2NoAttr() { int i = 2; }
};
class C {
// Special member function defined - definition emitted
[[clang::sycl_external]] ~C() {}
// CHECK: define linkonce_odr spir_func void @_ZN1CD1Ev
};
// Function reachable from an unused function - definition emitted
int ret1() { return 1; }
[[clang::sycl_external]] int withAttr() { return ret1(); }
// CHECK: define dso_local spir_func noundef i32 @_Z8withAttrv
// CHECK: define dso_local spir_func noundef i32 @_Z4ret1v
template <typename T>
[[clang::sycl_external]] void tFunc1(T arg) {}
// Explicit specialization defined - symbols emitted
template<>
[[clang::sycl_external]] void tFunc1<int>(int arg) {}
// CHECK: define dso_local spir_func void @_Z6tFunc1IiEvT_
template <typename T>
[[clang::sycl_external]] void tFunc2(T arg) {}
template void tFunc2<int>(int arg);
// CHECK: define weak_odr spir_func void @_Z6tFunc2IiEvT_
template<> void tFunc2<char>(char arg) {}
// CHECK: define dso_local spir_func void @_Z6tFunc2IcEvT_
template<> [[clang::sycl_external]] void tFunc2<long>(long arg) {}
// CHECK: define dso_local spir_func void @_Z6tFunc2IlEvT_
// Functions defined without the sycl_external attribute that are used
// in host code, but not in device code are not emitted.
int squareNoAttr(int x) { return x*x; }
// CHECK-NOT: define {{.*}} i32 @_Z12squareNoAttri
int main() {
declUsedInHost(4);
int i = squareUsed(5);
int j = squareNoAttr(6);
return 0;
}

View File

@ -1,22 +1,22 @@
// RUN: %clang_cc1 -triple spir64-unknown-unknown-sycldevice -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -triple x86_64-linux-pc -fsycl-is-host -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
// CHECK: @[[LAMBDA_KERNEL3:[^\w]+]] = private unnamed_addr addrspace(1) constant [[LAMBDA_K3_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ4mainEUlPZ4mainEUlvE_E_\00" // CHECK: @[[LAMBDA_KERNEL3:[^\w]+]] = private unnamed_addr constant [[LAMBDA_K3_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ4mainEUlPZ4mainEUlvE_E_\00"
// CHECK: @[[INT1:[^\w]+]] = private unnamed_addr addrspace(1) constant [[INT_SIZE:\[[0-9]+ x i8\]]] c"_ZTSi\00" // CHECK: @[[INT1:[^\w]+]] = private unnamed_addr constant [[INT_SIZE:\[[0-9]+ x i8\]]] c"_ZTSi\00"
// CHECK: @[[STRING:[^\w]+]] = private unnamed_addr addrspace(1) constant [[STRING_SIZE:\[[0-9]+ x i8\]]] c"_ZTSAppL_ZZ4mainE1jE_i\00", // CHECK: @[[STRING:[^\w]+]] = private unnamed_addr constant [[STRING_SIZE:\[[0-9]+ x i8\]]] c"_ZTSAppL_ZZ4mainE1jE_i\00",
// CHECK: @[[INT2:[^\w]+]] = private unnamed_addr addrspace(1) constant [[INT_SIZE]] c"_ZTSi\00" // CHECK: @[[INT2:[^\w]+]] = private unnamed_addr constant [[INT_SIZE]] c"_ZTSi\00"
// CHECK: @[[LAMBDA_X:[^\w]+]] = private unnamed_addr addrspace(1) constant [[LAMBDA_X_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE_\00" // CHECK: @[[LAMBDA_X:[^\w]+]] = private unnamed_addr constant [[LAMBDA_X_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE_\00"
// CHECK: @[[MACRO_X:[^\w]+]] = private unnamed_addr addrspace(1) constant [[MACRO_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE0_\00" // CHECK: @[[MACRO_X:[^\w]+]] = private unnamed_addr constant [[MACRO_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE0_\00"
// CHECK: @[[MACRO_Y:[^\w]+]] = private unnamed_addr addrspace(1) constant [[MACRO_SIZE]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE1_\00" // CHECK: @[[MACRO_Y:[^\w]+]] = private unnamed_addr constant [[MACRO_SIZE]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE1_\00"
// CHECK: @{{.*}} = private unnamed_addr addrspace(1) constant [32 x i8] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE2_\00", align 1 // CHECK: @{{.*}} = private unnamed_addr constant [32 x i8] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE2_\00", align 1
// CHECK: @{{.*}} = private unnamed_addr addrspace(1) constant [32 x i8] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE3_\00", align 1 // CHECK: @{{.*}} = private unnamed_addr constant [32 x i8] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE3_\00", align 1
// CHECK: @[[MACRO_MACRO_X:[^\w]+]] = private unnamed_addr addrspace(1) constant [[MACRO_MACRO_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE4_\00" // CHECK: @[[MACRO_MACRO_X:[^\w]+]] = private unnamed_addr constant [[MACRO_MACRO_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE4_\00"
// CHECK: @[[MACRO_MACRO_Y:[^\w]+]] = private unnamed_addr addrspace(1) constant [[MACRO_MACRO_SIZE]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE5_\00" // CHECK: @[[MACRO_MACRO_Y:[^\w]+]] = private unnamed_addr constant [[MACRO_MACRO_SIZE]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE5_\00"
// CHECK: @[[INT3:[^\w]+]] = private unnamed_addr addrspace(1) constant [[INT_SIZE]] c"_ZTSi\00" // CHECK: @[[INT3:[^\w]+]] = private unnamed_addr constant [[INT_SIZE]] c"_ZTSi\00"
// CHECK: @[[LAMBDA:[^\w]+]] = private unnamed_addr addrspace(1) constant [[LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE_\00" // CHECK: @[[LAMBDA:[^\w]+]] = private unnamed_addr constant [[LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE_\00"
// CHECK: @[[LAMBDA_IN_DEP_INT:[^\w]+]] = private unnamed_addr addrspace(1) constant [[DEP_INT_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ28lambda_in_dependent_functionIiEvvEUlvE_\00", // CHECK: @[[LAMBDA_IN_DEP_INT:[^\w]+]] = private unnamed_addr constant [[DEP_INT_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ28lambda_in_dependent_functionIiEvvEUlvE_\00",
// CHECK: @[[LAMBDA_IN_DEP_X:[^\w]+]] = private unnamed_addr addrspace(1) constant [[DEP_LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ28lambda_in_dependent_functionIZZ4mainENKUlvE0_clEvEUlvE_EvvEUlvE_\00", // CHECK: @[[LAMBDA_IN_DEP_X:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ28lambda_in_dependent_functionIZZ4mainENKUlvE0_clEvEUlvE_EvvEUlvE_\00",
// CHECK: @[[LAMBDA_NO_DEP:[^\w]+]] = private unnamed_addr addrspace(1) constant [[NO_DEP_LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ13lambda_no_depIidEvT_T0_EUlidE_\00", // CHECK: @[[LAMBDA_NO_DEP:[^\w]+]] = private unnamed_addr constant [[NO_DEP_LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ13lambda_no_depIidEvT_T0_EUlidE_\00",
// CHECK: @[[LAMBDA_TWO_DEP:[^\w]+]] = private unnamed_addr addrspace(1) constant [[DEP_LAMBDA1_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ14lambda_two_depIZZ4mainENKUlvE0_clEvEUliE_ZZ4mainENKS0_clEvEUldE_EvvEUlvE_\00", // CHECK: @[[LAMBDA_TWO_DEP:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA1_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ14lambda_two_depIZZ4mainENKUlvE0_clEvEUliE_ZZ4mainENKS0_clEvEUldE_EvvEUlvE_\00",
// CHECK: @[[LAMBDA_TWO_DEP2:[^\w]+]] = private unnamed_addr addrspace(1) constant [[DEP_LAMBDA2_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ14lambda_two_depIZZ4mainENKUlvE0_clEvEUldE_ZZ4mainENKS0_clEvEUliE_EvvEUlvE_\00", // CHECK: @[[LAMBDA_TWO_DEP2:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA2_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ14lambda_two_depIZZ4mainENKUlvE0_clEvEUldE_ZZ4mainENKS0_clEvEUliE_EvvEUlvE_\00",
extern "C" void puts(const char *) {} extern "C" void puts(const char *) {}
@ -65,95 +65,105 @@ template <typename KernelName, typename KernelType>
kernelFunc(); kernelFunc();
} }
template<typename KernelType>
void unnamed_kernel_single_task(KernelType kernelFunc) {
kernel_single_task<KernelType>(kernelFunc);
}
template <typename KernelName, typename KernelType>
void not_kernel_single_task(KernelType kernelFunc) {
kernelFunc();
}
int main() { int main() {
kernel_single_task<class kernel2>(func<Derp>); not_kernel_single_task<class kernel2>(func<Derp>);
// CHECK: call spir_func void @_Z18kernel_single_taskIZ4mainE7kernel2PFPKcvEEvT0_(ptr noundef @_Z4funcI4DerpEDTu33__builtin_sycl_unique_stable_nameDtsrT_3strEEEv) // CHECK: call void @_Z22not_kernel_single_taskIZ4mainE7kernel2PFPKcvEEvT0_(ptr noundef @_Z4funcI4DerpEDTu33__builtin_sycl_unique_stable_nameDtsrT_3strEEEv)
auto l1 = []() { return 1; }; auto l1 = []() { return 1; };
auto l2 = [](decltype(l1) *l = nullptr) { return 2; }; auto l2 = [](decltype(l1) *l = nullptr) { return 2; };
kernel_single_task<class kernel3>(l2); kernel_single_task<decltype(l2)>(l2);
puts(__builtin_sycl_unique_stable_name(decltype(l2))); puts(__builtin_sycl_unique_stable_name(decltype(l2)));
// CHECK: call spir_func void @_Z18kernel_single_taskIZ4mainE7kernel3Z4mainEUlPZ4mainEUlvE_E_EvT0_ // CHECK: call void @_Z18kernel_single_taskIZ4mainEUlPZ4mainEUlvE_E_S2_EvT0_
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[LAMBDA_KERNEL3]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[LAMBDA_KERNEL3]])
constexpr const char str[] = "lalala"; constexpr const char str[] = "lalala";
static_assert(__builtin_strcmp(__builtin_sycl_unique_stable_name(decltype(str)), "_ZTSA7_Kc\0") == 0, "unexpected mangling"); static_assert(__builtin_strcmp(__builtin_sycl_unique_stable_name(decltype(str)), "_ZTSA7_Kc\0") == 0, "unexpected mangling");
int i = 0; int i = 0;
puts(__builtin_sycl_unique_stable_name(decltype(i++))); puts(__builtin_sycl_unique_stable_name(decltype(i++)));
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[INT1]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[INT1]])
// FIXME: Ensure that j is incremented because VLAs are terrible. // FIXME: Ensure that j is incremented because VLAs are terrible.
int j = 55; int j = 55;
puts(__builtin_sycl_unique_stable_name(int[++j])); puts(__builtin_sycl_unique_stable_name(int[++j]));
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[STRING]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[STRING]])
// CHECK: define internal spir_func void @_Z18kernel_single_taskIZ4mainE7kernel2PFPKcvEEvT0_ // CHECK: define internal void @_Z22not_kernel_single_taskIZ4mainE7kernel2PFPKcvEEvT0_
// CHECK: declare spir_func noundef ptr addrspace(4) @_Z4funcI4DerpEDTu33__builtin_sycl_unique_stable_nameDtsrT_3strEEEv // CHECK: declare noundef ptr @_Z4funcI4DerpEDTu33__builtin_sycl_unique_stable_nameDtsrT_3strEEEv
// CHECK: define internal spir_func void @_Z18kernel_single_taskIZ4mainE7kernel3Z4mainEUlPZ4mainEUlvE_E_EvT0_ // CHECK: define internal void @_Z18kernel_single_taskIZ4mainEUlPZ4mainEUlvE_E_S2_EvT0_
// CHECK: define internal spir_func void @_Z18kernel_single_taskIZ4mainE6kernelZ4mainEUlvE0_EvT0_ // CHECK: define internal void @_Z18kernel_single_taskIZ4mainEUlvE0_S0_EvT0_
kernel_single_task<class kernel>( unnamed_kernel_single_task(
[]() { []() {
puts(__builtin_sycl_unique_stable_name(int)); puts(__builtin_sycl_unique_stable_name(int));
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[INT2]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[INT2]])
auto x = []() {}; auto x = []() {};
puts(__builtin_sycl_unique_stable_name(decltype(x))); puts(__builtin_sycl_unique_stable_name(decltype(x)));
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[LAMBDA_X]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[LAMBDA_X]])
DEF_IN_MACRO(); DEF_IN_MACRO();
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[MACRO_X]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[MACRO_X]])
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[MACRO_Y]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[MACRO_Y]])
MACRO_CALLS_MACRO(); MACRO_CALLS_MACRO();
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[MACRO_MACRO_X]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[MACRO_MACRO_X]])
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[MACRO_MACRO_Y]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[MACRO_MACRO_Y]])
template_param<int>(); template_param<int>();
// CHECK: call spir_func void @_Z14template_paramIiEvv // CHECK: call void @_Z14template_paramIiEvv
template_param<decltype(x)>(); template_param<decltype(x)>();
// CHECK: call spir_func void @_Z14template_paramIZZ4mainENKUlvE0_clEvEUlvE_Evv // CHECK: call void @_Z14template_paramIZZ4mainENKUlvE0_clEvEUlvE_Evv
lambda_in_dependent_function<int>(); lambda_in_dependent_function<int>();
// CHECK: call spir_func void @_Z28lambda_in_dependent_functionIiEvv // CHECK: call void @_Z28lambda_in_dependent_functionIiEvv
lambda_in_dependent_function<decltype(x)>(); lambda_in_dependent_function<decltype(x)>();
// CHECK: call spir_func void @_Z28lambda_in_dependent_functionIZZ4mainENKUlvE0_clEvEUlvE_Evv // CHECK: call void @_Z28lambda_in_dependent_functionIZZ4mainENKUlvE0_clEvEUlvE_Evv
lambda_no_dep<int, double>(3, 5.5); lambda_no_dep<int, double>(3, 5.5);
// CHECK: call spir_func void @_Z13lambda_no_depIidEvT_T0_(i32 noundef 3, double noundef 5.500000e+00) // CHECK: call void @_Z13lambda_no_depIidEvT_T0_(i32 noundef 3, double noundef 5.500000e+00)
int a = 5; int a = 5;
double b = 10.7; double b = 10.7;
auto y = [](int a) { return a; }; auto y = [](int a) { return a; };
auto z = [](double b) { return b; }; auto z = [](double b) { return b; };
lambda_two_dep<decltype(y), decltype(z)>(); lambda_two_dep<decltype(y), decltype(z)>();
// CHECK: call spir_func void @_Z14lambda_two_depIZZ4mainENKUlvE0_clEvEUliE_ZZ4mainENKS0_clEvEUldE_Evv // CHECK: call void @_Z14lambda_two_depIZZ4mainENKUlvE0_clEvEUliE_ZZ4mainENKS0_clEvEUldE_Evv
lambda_two_dep<decltype(z), decltype(y)>(); lambda_two_dep<decltype(z), decltype(y)>();
// CHECK: call spir_func void @_Z14lambda_two_depIZZ4mainENKUlvE0_clEvEUldE_ZZ4mainENKS0_clEvEUliE_Evv // CHECK: call void @_Z14lambda_two_depIZZ4mainENKUlvE0_clEvEUldE_ZZ4mainENKS0_clEvEUliE_Evv
}); });
} }
// CHECK: define linkonce_odr spir_func void @_Z14template_paramIiEvv // CHECK: define linkonce_odr void @_Z14template_paramIiEvv
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[INT3]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[INT3]])
// CHECK: define internal spir_func void @_Z14template_paramIZZ4mainENKUlvE0_clEvEUlvE_Evv // CHECK: define internal void @_Z14template_paramIZZ4mainENKUlvE0_clEvEUlvE_Evv
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[LAMBDA]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[LAMBDA]])
// CHECK: define linkonce_odr spir_func void @_Z28lambda_in_dependent_functionIiEvv // CHECK: define linkonce_odr void @_Z28lambda_in_dependent_functionIiEvv
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[LAMBDA_IN_DEP_INT]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[LAMBDA_IN_DEP_INT]])
// CHECK: define internal spir_func void @_Z28lambda_in_dependent_functionIZZ4mainENKUlvE0_clEvEUlvE_Evv // CHECK: define internal void @_Z28lambda_in_dependent_functionIZZ4mainENKUlvE0_clEvEUlvE_Evv
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[LAMBDA_IN_DEP_X]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[LAMBDA_IN_DEP_X]])
// CHECK: define linkonce_odr spir_func void @_Z13lambda_no_depIidEvT_T0_(i32 noundef %a, double noundef %b) // CHECK: define linkonce_odr void @_Z13lambda_no_depIidEvT_T0_(i32 noundef %a, double noundef %b)
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[LAMBDA_NO_DEP]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[LAMBDA_NO_DEP]])
// CHECK: define internal spir_func void @_Z14lambda_two_depIZZ4mainENKUlvE0_clEvEUliE_ZZ4mainENKS0_clEvEUldE_Evv // CHECK: define internal void @_Z14lambda_two_depIZZ4mainENKUlvE0_clEvEUliE_ZZ4mainENKS0_clEvEUldE_Evv
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[LAMBDA_TWO_DEP]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[LAMBDA_TWO_DEP]])
// CHECK: define internal spir_func void @_Z14lambda_two_depIZZ4mainENKUlvE0_clEvEUldE_ZZ4mainENKS0_clEvEUliE_Evv // CHECK: define internal void @_Z14lambda_two_depIZZ4mainENKUlvE0_clEvEUldE_ZZ4mainENKS0_clEvEUliE_Evv
// CHECK: call spir_func void @puts(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @[[LAMBDA_TWO_DEP2]] to ptr addrspace(4))) // CHECK: call void @puts(ptr noundef @[[LAMBDA_TWO_DEP2]])

View File

@ -15,7 +15,7 @@
// NV: call noundef ptr @_Z42__spirv_GenericCastToPtrExplicit_ToPrivatePvi // NV: call noundef ptr @_Z42__spirv_GenericCastToPtrExplicit_ToPrivatePvi
// NV: addrspacecast ptr %{{.*}} to ptr addrspace(1) // NV: addrspacecast ptr %{{.*}} to ptr addrspace(1)
// NV: addrspacecast ptr %{{.*}} to ptr addrspace(3) // NV: addrspacecast ptr %{{.*}} to ptr addrspace(3)
void test_cast(int* p) { [[clang::sycl_external]] void test_cast(int* p) {
__spirv_GenericCastToPtrExplicit_ToGlobal(p, 5); __spirv_GenericCastToPtrExplicit_ToGlobal(p, 5);
__spirv_GenericCastToPtrExplicit_ToLocal(p, 4); __spirv_GenericCastToPtrExplicit_ToLocal(p, 4);
__spirv_GenericCastToPtrExplicit_ToPrivate(p, 7); __spirv_GenericCastToPtrExplicit_ToPrivate(p, 7);

View File

@ -80,7 +80,7 @@
// NV: call noundef i32 @_Z25__spirv_BuiltInSubgroupIdv() #2 // NV: call noundef i32 @_Z25__spirv_BuiltInSubgroupIdv() #2
// NV: call noundef i32 @_Z40__spirv_BuiltInSubgroupLocalInvocationIdv() #2 // NV: call noundef i32 @_Z40__spirv_BuiltInSubgroupLocalInvocationIdv() #2
void test_id_and_range() { [[clang::sycl_external]] void test_id_and_range() {
__spirv_BuiltInNumWorkgroups(0); __spirv_BuiltInNumWorkgroups(0);
__spirv_BuiltInNumWorkgroups(1); __spirv_BuiltInNumWorkgroups(1);
__spirv_BuiltInNumWorkgroups(2); __spirv_BuiltInNumWorkgroups(2);

View File

@ -14,3 +14,13 @@ using TypePackElement = __type_pack_element<i, T...>;
template <int i> template <int i>
struct X; struct X;
using X0 = X<0>;
template <int I>
using SameAsX = X<I>;
template <template <class...> class Templ, class...Types>
using TypePackDedup = Templ<__builtin_dedup_pack<Types...>...>;
template <class ...Ts>
struct TypeList {};

View File

@ -1,9 +1,11 @@
// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s -Xcc -DSEQ | FileCheck --check-prefix=CHECK-SEQ %s // RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s -Xcc -DSEQ | FileCheck --check-prefix=CHECK-SEQ %s
// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s -Xcc -DPACK | FileCheck --check-prefix=CHECK-PACK %s // RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s -Xcc -DPACK | FileCheck --check-prefix=CHECK-PACK %s
// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s -Xcc -DPACK -Xcc -DSEQ | FileCheck --check-prefixes=CHECK-SEQ,CHECK-PACK %s // RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s -Xcc -DDEDUP | FileCheck --check-prefix=CHECK-DEDUP %s
// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s -Xcc -DPACK -Xcc -DSEQ -Xcc -DDEDUP | FileCheck --check-prefixes=CHECK-SEQ,CHECK-PACK,CHECK-DEDUP %s
// CHECK-SEQ: BuiltinTemplateDecl {{.+}} <<invalid sloc>> <invalid sloc> implicit __make_integer_seq{{$}} // CHECK-SEQ: BuiltinTemplateDecl {{.+}} <<invalid sloc>> <invalid sloc> implicit __make_integer_seq{{$}}
// CHECK-PACK: BuiltinTemplateDecl {{.+}} <<invalid sloc>> <invalid sloc> implicit __type_pack_element{{$}} // CHECK-PACK: BuiltinTemplateDecl {{.+}} <<invalid sloc>> <invalid sloc> implicit __type_pack_element{{$}}
// CHECK-DEDUP: BuiltinTemplateDecl {{.+}} <<invalid sloc>> <invalid sloc> implicit __builtin_dedup_pack{{$}}
void expr() { void expr() {
#ifdef SEQ #ifdef SEQ
@ -20,4 +22,12 @@ void expr() {
static_assert(__is_same(TypePackElement<0, X<0>, X<1>>, X<0>), ""); static_assert(__is_same(TypePackElement<0, X<0>, X<1>>, X<0>), "");
static_assert(__is_same(TypePackElement<1, X<0>, X<1>>, X<1>), ""); static_assert(__is_same(TypePackElement<1, X<0>, X<1>>, X<1>), "");
#endif #endif
#ifdef DEDUP
static_assert(__is_same(TypePackDedup<TypeList>, TypeList<>), "");
static_assert(__is_same(TypePackDedup<TypeList, int, double, int>, TypeList<int, double>), "");
static_assert(!__is_same(TypePackDedup<TypeList, int, double, int>, TypeList<double, int>), "");
static_assert(__is_same(TypePackDedup<TypeList, X<0>, X<1>, X<1>, X<2>, X<0>>, TypeList<X<0>, X<1>, X<2>>), "");
static_assert(__is_same(TypePackDedup<TypeList, X0, SameAsX<1>, X<1>, X<0>>, TypeList<X<0>,X<1>>), "");
#endif
} }

View File

@ -182,6 +182,7 @@
// CHECK-NEXT: ReturnTypestate (SubjectMatchRule_function, SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: ReturnTypestate (SubjectMatchRule_function, SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: ReturnsNonNull (SubjectMatchRule_objc_method, SubjectMatchRule_function) // CHECK-NEXT: ReturnsNonNull (SubjectMatchRule_objc_method, SubjectMatchRule_function)
// CHECK-NEXT: ReturnsTwice (SubjectMatchRule_function) // CHECK-NEXT: ReturnsTwice (SubjectMatchRule_function)
// CHECK-NEXT: SYCLExternal (SubjectMatchRule_function)
// CHECK-NEXT: SYCLKernelEntryPoint (SubjectMatchRule_function) // CHECK-NEXT: SYCLKernelEntryPoint (SubjectMatchRule_function)
// CHECK-NEXT: SYCLSpecialClass (SubjectMatchRule_record) // CHECK-NEXT: SYCLSpecialClass (SubjectMatchRule_record)
// CHECK-NEXT: ScopedLockable (SubjectMatchRule_record) // CHECK-NEXT: ScopedLockable (SubjectMatchRule_record)

View File

@ -0,0 +1,20 @@
// RUN: %clang_cc1 -std=c++14 -x c++-header %s -emit-pch -o %t.pch
// RUN: %clang_cc1 -std=c++14 -x c++ /dev/null -include-pch %t.pch
// RUN: %clang_cc1 -std=c++14 -x c++-header %s -emit-pch -fpch-instantiate-templates -o %t.pch
// RUN: %clang_cc1 -std=c++14 -x c++ /dev/null -include-pch %t.pch
template <template <class...> class Templ, class...Types>
using TypePackDedup = Templ<__builtin_dedup_pack<Types...>...>;
template <class ...Ts>
struct TypeList {};
template <int i>
struct X {};
void fn1() {
TypeList<int, double> l1 = TypePackDedup<TypeList, int, double, int>{};
TypeList<> l2 = TypePackDedup<TypeList>{};
TypeList<X<0>, X<1>> x1 = TypePackDedup<TypeList, X<0>, X<1>, X<0>, X<1>>{};
}

View File

@ -1,5 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s
// XFAIL: asserts
template <class> struct Pair; template <class> struct Pair;
template <class...> struct Tuple { template <class...> struct Tuple {

View File

@ -0,0 +1,36 @@
// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -std=c++17 -verify %s
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -std=c++17 -verify %s
// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -std=c++20 -verify %s
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -std=c++20 -verify %s
// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -std=c++23 -verify %s
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -std=c++23 -verify %s
// expected-error@+1{{'clang::sycl_external' attribute only applies to functions}}
[[clang::sycl_external]] int bad1;
// expected-error@+2{{'clang::sycl_external' attribute only applies to functions}}
struct s {
[[clang::sycl_external]] int bad2;
};
// expected-error@+1{{'clang::sycl_external' attribute only applies to functions}}
namespace [[clang::sycl_external]] bad3 {}
// expected-error@+1{{'clang::sycl_external' attribute only applies to functions}}
struct [[clang::sycl_external]] bad4;
// expected-error@+1{{'clang::sycl_external' attribute only applies to functions}}
enum [[clang::sycl_external]] bad5 {};
// expected-error@+1{{'clang::sycl_external' attribute only applies to functions}}
int bad6(void (fp [[clang::sycl_external]])());
// expected-error@+1{{'clang::sycl_external' attribute only applies to functions}}
[[clang::sycl_external]];
#if __cplusplus >= 202002L
// expected-error@+2{{'clang::sycl_external' attribute only applies to functions}}
template<typename>
concept bad8 [[clang::sycl_external]] = true;
#endif

View File

@ -0,0 +1,14 @@
// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify %s
// FIXME-expected-error@+1{{'clang::sycl_external' attribute takes no arguments}}
[[clang::sycl_external()]] void bad1();
// expected-error@+1{{expected expression}}
[[clang::sycl_external(,)]] void bad2();
// expected-error@+1{{'clang::sycl_external' attribute takes no arguments}}
[[clang::sycl_external(3)]] void bad3();
// expected-error@+1{{expected expression}}
[[clang::sycl_external(4,)]] void bad4();

View File

@ -0,0 +1,15 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// These tests validate that the sycl_external attribute is ignored when SYCL
// support is not enabled.
// expected-warning@+1{{'clang::sycl_external' attribute ignored}}
[[clang::sycl_external]] void bar() {}
// expected-warning@+1{{'clang::sycl_external' attribute ignored}}
[[clang::sycl_external]] int a;
// expected-warning@+2{{'clang::sycl_external' attribute ignored}}
template<typename T>
[[clang::sycl_external]] void ft(T) {}
template void ft(int);

View File

@ -0,0 +1,154 @@
// RUN: %clang_cc1 -fsycl-is-host -std=c++17 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsycl-is-device -std=c++17 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsycl-is-host -std=c++20 -fsyntax-only -verify -DCPP20 %s
// RUN: %clang_cc1 -fsycl-is-device -std=c++20 -fsyntax-only -verify -DCPP20 %s
// Semantic tests for the sycl_external attribute.
// expected-error@+1{{'clang::sycl_external' can only be applied to functions with external linkage}}
[[clang::sycl_external]]
static void func1() {}
// expected-error@+2{{'clang::sycl_external' can only be applied to functions with external linkage}}
namespace {
[[clang::sycl_external]]
void func2() {}
}
// expected-error@+2{{'clang::sycl_external' can only be applied to functions with external linkage}}
namespace { struct S4 {}; }
[[clang::sycl_external]] void func4(S4) {}
// expected-error@+3{{'clang::sycl_external' can only be applied to functions with external linkage}}
namespace { struct S5 {}; }
template<typename> [[clang::sycl_external]] void func5();
template<> [[clang::sycl_external]] void func5<S5>() {}
namespace { struct S6 {}; }
template<typename>
[[clang::sycl_external]] void func6() {}
template void func6<S6>();
// FIXME: C++23 [temp.expl.spec]p12 states:
// ... Similarly, attributes appearing in the declaration of a template
// have no effect on an explicit specialization of that template.
// Clang currently instantiates and propagates attributes from a function
// template to its explicit specializations resulting in the following
// spurious error.
// expected-error@+3{{'clang::sycl_external' can only be applied to functions with external linkage}}
namespace { struct S7 {}; }
template<typename>
[[clang::sycl_external]] void func7();
template<> void func7<S7>() {}
// FIXME: The explicit function template specialization appears to trigger
// instantiation of a declaration from the primary template without the
// attribute leading to a spurious diagnostic that the sycl_external
// attribute is not present on the first declaration.
namespace { struct S8 {}; }
template<typename>
void func8();
template<> [[clang::sycl_external]] void func8<S8>() {}
// expected-warning@-1{{'clang::sycl_external' attribute does not appear on the first declaration}}
// expected-error@-2{{'clang::sycl_external' can only be applied to functions with external linkage}}
// expected-note@-3{{previous declaration is here}}
namespace { struct S9 {}; }
struct T9 {
using type = S9;
};
template<typename>
[[clang::sycl_external]] void func9() {}
template<typename T>
[[clang::sycl_external]] void test_func9() {
func9<typename T::type>();
}
template void test_func9<T9>();
// The first declaration of a SYCL external function is required to have this attribute.
// expected-note@+1{{previous declaration is here}}
int foo();
// expected-warning@+1{{'clang::sycl_external' attribute does not appear on the first declaration}}
[[clang::sycl_external]] int foo();
// expected-note@+1{{previous declaration is here}}
void goo();
// expected-warning@+1{{'clang::sycl_external' attribute does not appear on the first declaration}}
[[clang::sycl_external]] void goo();
void goo() {}
// expected-note@+1{{previous declaration is here}}
void hoo() {}
// expected-warning@+1{{'clang::sycl_external' attribute does not appear on the first declaration}}
[[clang::sycl_external]] void hoo();
// expected-note@+1{{previous declaration is here}}
void joo();
void use_joo() {
joo();
}
// expected-warning@+1{{'clang::sycl_external' attribute does not appear on the first declaration}}
[[clang::sycl_external]] void joo();
// Subsequent declarations of a SYCL external function may optionally specify this attribute.
[[clang::sycl_external]] int boo();
[[clang::sycl_external]] int boo(); // OK
int boo(); // OK
class C {
[[clang::sycl_external]] void member();
};
// expected-error@+1{{'clang::sycl_external' cannot be applied to the 'main' function}}
[[clang::sycl_external]] int main()
{
return 0;
}
// expected-error@+2{{'clang::sycl_external' cannot be applied to an explicitly deleted function}}
class D {
[[clang::sycl_external]] void mdel() = delete;
};
// expected-error@+1{{'clang::sycl_external' cannot be applied to an explicitly deleted function}}
[[clang::sycl_external]] void del() = delete;
struct NonCopyable {
~NonCopyable() = delete;
[[clang::sycl_external]] NonCopyable(const NonCopyable&) = default;
};
class A {
[[clang::sycl_external]]
A() {}
[[clang::sycl_external]] void mf() {}
[[clang::sycl_external]] static void smf();
};
class B {
public:
[[clang::sycl_external]] virtual void foo() {}
[[clang::sycl_external]] virtual void bar() = 0;
};
[[clang::sycl_external]] void B::bar() {}
[[clang::sycl_external]] constexpr int square(int x);
// Devices that do not support the generic address space shall not specify
// a raw pointer or reference type as the return type or as a parameter type.
[[clang::sycl_external]] int *fun0();
[[clang::sycl_external]] int &fun1();
[[clang::sycl_external]] int &&fun2();
[[clang::sycl_external]] void fun3(int *);
[[clang::sycl_external]] void fun4(int &);
[[clang::sycl_external]] void fun5(int &&);
template<typename T>
[[clang::sycl_external]] void fun6(T) {}
template void fun6(int *);
template<> [[clang::sycl_external]] void fun6<long*>(long *) {}
#if CPP20
[[clang::sycl_external]] consteval int func();
#endif

View File

@ -0,0 +1,226 @@
// RUN: %clang_cc1 %s -verify
template <typename...> struct TypeList;
// === Check results of the builtin.
template <class>
struct TemplateWrapper {
static_assert(__is_same( // expected-error {{static assertion contains an unexpanded parameter pack}}
TypeList<__builtin_dedup_pack<int, int*, int, double, float>>,
TypeList<int, int*, double, float>));
};
template <template<typename ...> typename Templ, typename ...Types>
struct Dependent {
using empty_list = Templ<__builtin_dedup_pack<>...>;
using same = Templ<__builtin_dedup_pack<Types...>...>;
using twice = Templ<__builtin_dedup_pack<Types..., Types...>...>;
using dep_only_types = TypeList<__builtin_dedup_pack<Types...>...>;
using dep_only_template = Templ<__builtin_dedup_pack<int, double, int>...>;
};
// Check the reverse condition to make sure we see an error and not accidentally produced dependent expression.
static_assert(!__is_same(Dependent<TypeList>::empty_list, TypeList<>)); // expected-error {{static assertion failed}}
static_assert(!__is_same(Dependent<TypeList>::same, TypeList<>)); // expected-error {{static assertion failed}}
static_assert(!__is_same(Dependent<TypeList>::twice, TypeList<>)); // expected-error {{static assertion failed}}
static_assert(!__is_same(Dependent<TypeList>::dep_only_types, TypeList<>)); // expected-error {{static assertion failed}}
static_assert(!__is_same(Dependent<TypeList>::dep_only_template, TypeList<int, double>)); // expected-error {{static assertion failed}}
static_assert(!__is_same(Dependent<TypeList, int*, double*, int*>::empty_list, TypeList<>)); // expected-error {{static assertion failed}}
static_assert(!__is_same(Dependent<TypeList, int*, double*, int*>::same, TypeList<int*, double*>)); // expected-error {{static assertion failed}}
static_assert(!__is_same(Dependent<TypeList, int*, double*, int*>::twice, TypeList<int*, double*>)); // expected-error {{static assertion failed}}
static_assert(!__is_same(Dependent<TypeList, int*, double*, int*>::dep_only_types, TypeList<int*, double*>)); // expected-error {{static assertion failed}}
static_assert(!__is_same(Dependent<TypeList, int*, double*, int*>::dep_only_template, TypeList<int, double>)); // expected-error {{static assertion failed}}
template <class ...T>
using Twice = TypeList<T..., T...>;
template <class>
struct TwiceTemplateWrapper {
static_assert(!__is_same(Twice<__builtin_dedup_pack<int, double, int>...>, TypeList<int, double, int, double>)); // expected-error {{static assertion failed}}
};
template struct TwiceTemplateWrapper<int>; // expected-note {{in instantiation of template class 'TwiceTemplateWrapper<int>' requested here}}
template <int...> struct IntList;
// Wrong kinds of template arguments.
template <class> struct IntListTemplateWrapper {
IntList<__builtin_dedup_pack<int>...>* wrong_template; // expected-error {{template argument for non-type template parameter must be an expression}}
// expected-note@-4 {{template parameter is declared here}}
TypeList<__builtin_dedup_pack<1, 2, 3>...>* wrong_template_args; // expected-error {{template argument for template type parameter must be a type}}
// expected-note@* {{template parameter from hidden source}}
__builtin_dedup_pack<> not_enough_args; // expected-error {{data member type contains an unexpanded parameter pack}}
// expected-note@* {{template declaration from hidden source}}
__builtin_dedup_pack missing_template_args; // expected-error {{use of template '__builtin_dedup_pack' requires template arguments}}
};
// Make sure various canonical / non-canonical type representations do not affect results
// of the deduplication and the qualifiers do end up creating different types when C++ requires it.
using Int = int;
using CInt = const Int;
using IntArray = Int[10];
using CIntArray = Int[10];
using IntPtr = int*;
using CIntPtr = const int*;
template <class>
struct Foo {
static_assert(
!__is_same( // expected-error {{static assertion failed}}
// expected-note@* {{in instantiation of template class 'Foo<int>'}}
TypeList<__builtin_dedup_pack<
Int, int,
const int, const Int, CInt, const CInt,
IntArray, Int[10], int[10],
const IntArray, const int[10], CIntArray, const CIntArray,
IntPtr, int*,
const IntPtr, int* const,
CIntPtr, const int*,
const IntPtr*, int*const*,
CIntPtr*, const int**,
const CIntPtr*, const int* const*
>...>,
TypeList<int, const int, int[10], const int [10], int*, int* const, const int*, int*const *, const int**, const int*const*>),
"");
};
template struct Foo<int>;
// === Show an error when packs are used in non-template contexts.
static_assert(!__is_same(TypeList<__builtin_dedup_pack<int>...>, TypeList<int>)); // expected-error {{outside}}
// Non-dependent uses in template are fine, though.
template <class T>
struct NonDepInTemplate {
static_assert(!__is_same(TypeList<__builtin_dedup_pack<int>...>, TypeList<int>)); // expected-error {{static assertion failed}}
};
template struct NonDepInTemplate<int>; // expected-note {{requested here}}
template <template<class...> class T = __builtin_dedup_pack> // expected-error {{use of template '__builtin_dedup_pack' requires template arguments}}
// expected-note@* {{template declaration from hidden source}}
struct UseAsTemplate;
template <template<class...> class>
struct AcceptsTemplateArg;
template <class>
struct UseAsTemplateWrapper {
AcceptsTemplateArg<__builtin_dedup_pack>* a; // expected-error {{use of template '__builtin_dedup_pack' requires template arguments}}
// expected-note@* {{template declaration from hidden source}}
};
// === Check how expansions in various contexts behave.
// The following cases are not supported yet, should produce an error.
template <class... T>
struct DedupBases : __builtin_dedup_pack<T...>... {};
struct Base1 {
int a1;
};
struct Base2 {
int a2;
};
static_assert(DedupBases<Base1, Base1, Base2, Base1, Base2, Base2>{1, 2}.a1 != 1); // expected-error {{static assertion failed}} \
// expected-note {{}}
static_assert(DedupBases<Base1, Base1, Base2, Base1, Base2, Base2>{1, 2}.a2 != 2); // expected-error {{static assertion failed}} \
// expected-note {{}}
template <class ...T>
constexpr int dedup_params(__builtin_dedup_pack<T...>... as) {
return (as + ...);
}
static_assert(dedup_params<int, int, short, int, short, short>(1, 2)); // expected-error {{no matching function}} \
// expected-note@-3 {{expansions of '__builtin_dedup_pack' are not supported here}}
template <class ...T>
constexpr int dedup_params_into_type_list(TypeList<__builtin_dedup_pack<T...>...> *, T... as) {
return (as + ...);
}
static_assert(dedup_params_into_type_list(static_cast<TypeList<int,short,long>*>(nullptr), 1, short(1), 1, 1l, 1l) != 5); // expected-error {{static assertion failed}} \
// expected-note {{expression evaluates}}
template <class T, __builtin_dedup_pack<T, int>...> // expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here}}
struct InTemplateParams {};
InTemplateParams<int> itp1;
InTemplateParams<int, 1, 2, 3, 4, 5> itp2;
template <class T>
struct DeepTemplateParams {
template <__builtin_dedup_pack<T, int>...> // expected-error {{expansions of '__builtin_dedup_pack' are not supported here}}
struct Templ {};
};
DeepTemplateParams<int>::Templ<> dtp1; // expected-note {{requested here}} \
// expected-error {{no template named 'Templ'}}
template <class ...T>
struct MemInitializers : T... {
MemInitializers() : __builtin_dedup_pack<T...>()... {} // expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here.}}
};
MemInitializers<> mi1; // expected-note {{in instantiation of member function}}
MemInitializers<Base1, Base2> mi2; // expected-note {{in instantiation of member function}}
template <class ...T>
constexpr int dedup_in_expressions() {
// counts the number of unique Ts.
return ((1 + __builtin_dedup_pack<T...>()) + ...); // expected-error {{expansions of '__builtin_dedup_pack' are not supported here.}} \
// expected-note@+3 {{in instantiation of function template specialization}}
}
static_assert(dedup_in_expressions<int, int, short, double, int, short, double, int>() == 3); // expected-error {{not an integral constant expression}}
template <class ...T>
void in_exception_spec() throw(__builtin_dedup_pack<T...>...); // expected-error{{C++17 does not allow dynamic exception specifications}} \
// expected-note {{use 'noexcept}} \
// expected-error{{expansions of '__builtin_dedup_pack' are not supported here.}}
void test_in_exception_spec() {
in_exception_spec<int, double, int>(); // expected-note {{instantiation of exception specification}}
}
template <class ...T>
constexpr bool in_type_trait = __is_trivially_constructible(int, __builtin_dedup_pack<T...>...); // expected-error{{expansions of '__builtin_dedup_pack' are not supported here.}}
static_assert(in_type_trait<int, int, int>); // expected-note{{in instantiation of variable template specialization}}
template <class ...T>
struct InFriends {
friend __builtin_dedup_pack<T>...; // expected-warning {{variadic 'friend' declarations are a C++2c extension}} \
// expected-error 2 {{expansions of '__builtin_dedup_pack' are not supported here.}} \
// expected-note@* 2 {{in instantiation of template class}}
};
struct Friend1 {};
struct Friend2 {};
InFriends<> if1;
InFriends<Friend1, Friend2> if2;
template <class ...T>
struct InUsingDecl {
using __builtin_dedup_pack<T...>::func...; // expected-error 2 {{expansions of '__builtin_dedup_pack' are not supported here.}}
};
struct WithFunc1 { void func(); };
struct WithFunc2 { void func(int); };
InUsingDecl<> iu1; // expected-note {{in instantiation of template class}}
InUsingDecl<WithFunc1, WithFunc2> iu2; // expected-note {{in instantiation of template class}}
// Note: produces parsing errors and does not construct pack indexing.
// Keep this commented out until the parser supports this.
//
// template <class ...T>
// struct InPackIndexing {
//
// using type = __builtin_dedup_pack<T...>...[0];
// };
// static_assert(__is_same(InPackIndexing<int, int>, int));
template <class ...T>
struct LambdaInitCaptures {
static constexpr int test() {
[...foos=__builtin_dedup_pack<T...>()]{}; // expected-warning {{initialized lambda pack captures are a C++20 extension}} \
// expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here.}}
return 3;
}
};
static_assert(LambdaInitCaptures<>::test() == 3); // expected-note {{in instantiation of member function}}
static_assert(LambdaInitCaptures<int, int, int>::test() == 3); // expected-note {{in instantiation of member function}}
template <class ...T>
struct alignas(__builtin_dedup_pack<T...>...) AlignAs {}; // expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here.}}
AlignAs<> aa1; // expected-note {{in instantiation of template class}}
AlignAs<int, double> aa2; // expected-note {{in instantiation of template class}}

View File

@ -1900,6 +1900,7 @@ DEFAULT_TYPELOC_IMPL(Record, TagType)
DEFAULT_TYPELOC_IMPL(Enum, TagType) DEFAULT_TYPELOC_IMPL(Enum, TagType)
DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParm, Type) DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParm, Type)
DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParmPack, Type) DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParmPack, Type)
DEFAULT_TYPELOC_IMPL(SubstBuiltinTemplatePack, Type)
DEFAULT_TYPELOC_IMPL(Auto, Type) DEFAULT_TYPELOC_IMPL(Auto, Type)
DEFAULT_TYPELOC_IMPL(BitInt, Type) DEFAULT_TYPELOC_IMPL(BitInt, Type)
DEFAULT_TYPELOC_IMPL(DependentBitInt, Type) DEFAULT_TYPELOC_IMPL(DependentBitInt, Type)

View File

@ -93,7 +93,7 @@ if(MSVC)
set(LLVM_EXPORTED_SYMBOL_FILE) set(LLVM_EXPORTED_SYMBOL_FILE)
endif() endif()
if (UNIX AND NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX" AND NOT CYGWIN) if (UNIX AND NOT APPLE AND NOT "${CMAKE_SYSTEM_NAME}" MATCHES "AIX" AND NOT CYGWIN)
set(LLVM_EXPORTED_SYMBOL_FILE) set(LLVM_EXPORTED_SYMBOL_FILE)
set(USE_VERSION_SCRIPT ${LLVM_HAVE_LINK_VERSION_SCRIPT}) set(USE_VERSION_SCRIPT ${LLVM_HAVE_LINK_VERSION_SCRIPT})
endif() endif()
@ -125,7 +125,7 @@ else()
set(output_name "clang") set(output_name "clang")
endif() endif()
if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") if (UNIX AND "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
set(CMAKE_AIX_EXPORT_ALL_SYMBOLS OFF) set(CMAKE_AIX_EXPORT_ALL_SYMBOLS OFF)
# libclang requires headers which need _ALL_SOURCE to build on AIX # libclang requires headers which need _ALL_SOURCE to build on AIX
remove_definitions("-D_XOPEN_SOURCE=700") remove_definitions("-D_XOPEN_SOURCE=700")
@ -186,7 +186,7 @@ if(ENABLE_SHARED)
endif() endif()
endif() endif()
if (USE_VERSION_SCRIPT) if (USE_VERSION_SCRIPT)
if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS") if ("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS")
include(CheckLinkerFlag) include(CheckLinkerFlag)
# The Solaris 11.4 linker supports a subset of GNU ld version scripts, # The Solaris 11.4 linker supports a subset of GNU ld version scripts,
# but requires a special option to enable it. # but requires a special option to enable it.

View File

@ -1183,6 +1183,39 @@ TEST_P(ASTMatchersTest, AsmStatement) {
EXPECT_TRUE(matches("void foo() { __asm(\"mov al, 2\"); }", asmStmt())); EXPECT_TRUE(matches("void foo() { __asm(\"mov al, 2\"); }", asmStmt()));
} }
TEST_P(ASTMatchersTest, HasConditionVariableStatement) {
if (!GetParam().isCXX()) {
// FIXME: Add a test for `hasConditionVariableStatement()` that does not
// depend on C++.
return;
}
StatementMatcher IfCondition =
ifStmt(hasConditionVariableStatement(declStmt()));
EXPECT_TRUE(matches("void x() { if (int* a = 0) {} }", IfCondition));
EXPECT_TRUE(notMatches("void x() { if (true) {} }", IfCondition));
EXPECT_TRUE(notMatches("void x() { int x; if ((x = 42)) {} }", IfCondition));
StatementMatcher SwitchCondition =
switchStmt(hasConditionVariableStatement(declStmt()));
EXPECT_TRUE(matches("void x() { switch (int a = 0) {} }", SwitchCondition));
if (GetParam().isCXX17OrLater()) {
EXPECT_TRUE(
notMatches("void x() { switch (int a = 0; a) {} }", SwitchCondition));
}
StatementMatcher ForCondition =
forStmt(hasConditionVariableStatement(declStmt()));
EXPECT_TRUE(matches("void x() { for (; int a = 0; ) {} }", ForCondition));
EXPECT_TRUE(notMatches("void x() { for (int a = 0; ; ) {} }", ForCondition));
EXPECT_TRUE(matches("void x() { while (int a = 0) {} }",
whileStmt(hasConditionVariableStatement(declStmt()))));
}
TEST_P(ASTMatchersTest, HasCondition) { TEST_P(ASTMatchersTest, HasCondition) {
if (!GetParam().isCXX()) { if (!GetParam().isCXX()) {
// FIXME: Add a test for `hasCondition()` that does not depend on C++. // FIXME: Add a test for `hasCondition()` that does not depend on C++.

View File

@ -5142,21 +5142,6 @@ TEST(ForEachLambdaCapture, MatchExplicitCapturesOnly) {
matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 1))); matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 1)));
} }
TEST(HasConditionVariableStatement, DoesNotMatchCondition) {
EXPECT_TRUE(notMatches(
"void x() { if(true) {} }",
ifStmt(hasConditionVariableStatement(declStmt()))));
EXPECT_TRUE(notMatches(
"void x() { int x; if((x = 42)) {} }",
ifStmt(hasConditionVariableStatement(declStmt()))));
}
TEST(HasConditionVariableStatement, MatchesConditionVariables) {
EXPECT_TRUE(matches(
"void x() { if(int* a = 0) {} }",
ifStmt(hasConditionVariableStatement(declStmt()))));
}
TEST(ForEach, BindsOneNode) { TEST(ForEach, BindsOneNode) {
EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; };", EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; };",
recordDecl(hasName("C"), forEach(fieldDecl(hasName("x")).bind("x"))), recordDecl(hasName("C"), forEach(fieldDecl(hasName("x")).bind("x"))),

View File

@ -9,17 +9,25 @@
#include "TestingSupport.h" #include "TestingSupport.h"
#include "clang/AST/ASTContext.h" #include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h" #include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/OperationKinds.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/NoopAnalysis.h" #include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
#include "clang/Analysis/FlowSensitive/RecordOps.h" #include "clang/Analysis/FlowSensitive/RecordOps.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "clang/Analysis/FlowSensitive/Value.h" #include "clang/Analysis/FlowSensitive/Value.h"
#include "clang/Basic/LangStandard.h" #include "clang/Basic/LangStandard.h"
#include "clang/Testing/TestAST.h" #include "clang/Testing/TestAST.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Testing/Support/Error.h" #include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
@ -27,6 +35,7 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <utility> #include <utility>
#include <vector>
namespace clang { namespace clang {
namespace dataflow { namespace dataflow {
@ -3541,7 +3550,7 @@ TEST(TransferTest, ResultObjectLocationDontVisitUnevaluatedContexts) {
testFunction(Code, "noexceptTarget"); testFunction(Code, "noexceptTarget");
} }
TEST(TransferTest, StaticCast) { TEST(TransferTest, StaticCastNoOp) {
std::string Code = R"( std::string Code = R"(
void target(int Foo) { void target(int Foo) {
int Bar = static_cast<int>(Foo); int Bar = static_cast<int>(Foo);
@ -3561,6 +3570,13 @@ TEST(TransferTest, StaticCast) {
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
ASSERT_THAT(BarDecl, NotNull()); ASSERT_THAT(BarDecl, NotNull());
const auto *Cast = ast_matchers::selectFirst<CXXStaticCastExpr>(
"cast",
ast_matchers::match(ast_matchers::cxxStaticCastExpr().bind("cast"),
ASTCtx));
ASSERT_THAT(Cast, NotNull());
ASSERT_EQ(Cast->getCastKind(), CK_NoOp);
const auto *FooVal = Env.getValue(*FooDecl); const auto *FooVal = Env.getValue(*FooDecl);
const auto *BarVal = Env.getValue(*BarDecl); const auto *BarVal = Env.getValue(*BarDecl);
EXPECT_TRUE(isa<IntegerValue>(FooVal)); EXPECT_TRUE(isa<IntegerValue>(FooVal));
@ -3569,6 +3585,268 @@ TEST(TransferTest, StaticCast) {
}); });
} }
TEST(TransferTest, StaticCastBaseToDerived) {
std::string Code = R"cc(
struct Base {
char C;
};
struct Intermediate : public Base {
bool B;
};
struct Derived : public Intermediate {
int I;
};
Base& getBaseRef();
void target(Base* BPtr) {
Derived* DPtr = static_cast<Derived*>(BPtr);
DPtr->C;
DPtr->B;
DPtr->I;
Derived& DRef = static_cast<Derived&>(*BPtr);
DRef.C;
DRef.B;
DRef.I;
Derived& DRefFromFunc = static_cast<Derived&>(getBaseRef());
DRefFromFunc.C;
DRefFromFunc.B;
DRefFromFunc.I;
// [[p]]
}
)cc";
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
const ValueDecl *BPtrDecl = findValueDecl(ASTCtx, "BPtr");
ASSERT_THAT(BPtrDecl, NotNull());
const ValueDecl *DPtrDecl = findValueDecl(ASTCtx, "DPtr");
ASSERT_THAT(DPtrDecl, NotNull());
const ValueDecl *DRefDecl = findValueDecl(ASTCtx, "DRef");
ASSERT_THAT(DRefDecl, NotNull());
const ValueDecl *DRefFromFuncDecl =
findValueDecl(ASTCtx, "DRefFromFunc");
ASSERT_THAT(DRefFromFuncDecl, NotNull());
const auto *Cast = ast_matchers::selectFirst<CXXStaticCastExpr>(
"cast",
ast_matchers::match(ast_matchers::cxxStaticCastExpr().bind("cast"),
ASTCtx));
ASSERT_THAT(Cast, NotNull());
ASSERT_EQ(Cast->getCastKind(), CK_BaseToDerived);
EXPECT_EQ(Env.getValue(*BPtrDecl), Env.getValue(*DPtrDecl));
EXPECT_EQ(&Env.get<PointerValue>(*BPtrDecl)->getPointeeLoc(),
Env.getStorageLocation(*DRefDecl));
// For DRefFromFunc, not crashing when analyzing the field accesses is
// enough.
});
}
TEST(TransferTest, ExplicitDerivedToBaseCast) {
std::string Code = R"cc(
struct Base {};
struct Derived : public Base {};
void target(Derived D) {
(Base*)&D;
// [[p]]
}
)cc";
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
auto *Cast = ast_matchers::selectFirst<ImplicitCastExpr>(
"cast", ast_matchers::match(
ast_matchers::implicitCastExpr().bind("cast"), ASTCtx));
ASSERT_THAT(Cast, NotNull());
ASSERT_EQ(Cast->getCastKind(), CK_DerivedToBase);
auto *AddressOf = ast_matchers::selectFirst<UnaryOperator>(
"addressof",
ast_matchers::match(ast_matchers::unaryOperator().bind("addressof"),
ASTCtx));
ASSERT_THAT(AddressOf, NotNull());
ASSERT_EQ(AddressOf->getOpcode(), UO_AddrOf);
EXPECT_EQ(Env.getValue(*Cast), Env.getValue(*AddressOf));
});
}
TEST(TransferTest, ConstructorConversion) {
std::string Code = R"cc(
struct Base {};
struct Derived : public Base {};
void target(Derived D) {
Base B = (Base)D;
// [[p]]
}
)cc";
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
auto *Cast = ast_matchers::selectFirst<CStyleCastExpr>(
"cast", ast_matchers::match(
ast_matchers::cStyleCastExpr().bind("cast"), ASTCtx));
ASSERT_THAT(Cast, NotNull());
ASSERT_EQ(Cast->getCastKind(), CK_ConstructorConversion);
auto &DLoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "D");
auto &BLoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "B");
EXPECT_NE(&BLoc, &DLoc);
});
}
TEST(TransferTest, UserDefinedConversion) {
std::string Code = R"cc(
struct To {};
struct From {
operator To();
};
void target(From F) {
To T = (To)F;
// [[p]]
}
)cc";
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
auto *Cast = ast_matchers::selectFirst<ImplicitCastExpr>(
"cast", ast_matchers::match(
ast_matchers::implicitCastExpr().bind("cast"), ASTCtx));
ASSERT_THAT(Cast, NotNull());
ASSERT_EQ(Cast->getCastKind(), CK_UserDefinedConversion);
auto &FLoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "F");
auto &TLoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "T");
EXPECT_NE(&TLoc, &FLoc);
});
}
TEST(TransferTest, ImplicitUncheckedDerivedToBaseCast) {
std::string Code = R"cc(
struct Base {
void method();
};
struct Derived : public Base {};
void target(Derived D) {
D.method();
// [[p]]
}
)cc";
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
auto *Cast = ast_matchers::selectFirst<ImplicitCastExpr>(
"cast", ast_matchers::match(
ast_matchers::implicitCastExpr().bind("cast"), ASTCtx));
ASSERT_THAT(Cast, NotNull());
ASSERT_EQ(Cast->getCastKind(), CK_UncheckedDerivedToBase);
auto &DLoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "D");
EXPECT_EQ(Env.getStorageLocation(*Cast), &DLoc);
});
}
TEST(TransferTest, ImplicitDerivedToBaseCast) {
std::string Code = R"cc(
struct Base {};
struct Derived : public Base {};
void target() {
Base* B = new Derived();
// [[p]]
}
)cc";
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
auto *Cast = ast_matchers::selectFirst<ImplicitCastExpr>(
"cast", ast_matchers::match(
ast_matchers::implicitCastExpr().bind("cast"), ASTCtx));
ASSERT_THAT(Cast, NotNull());
ASSERT_EQ(Cast->getCastKind(), CK_DerivedToBase);
auto *New = ast_matchers::selectFirst<CXXNewExpr>(
"new", ast_matchers::match(ast_matchers::cxxNewExpr().bind("new"),
ASTCtx));
ASSERT_THAT(New, NotNull());
EXPECT_EQ(Env.getValue(*Cast), Env.getValue(*New));
});
}
TEST(TransferTest, ReinterpretCast) {
std::string Code = R"cc(
struct S {
int I;
};
void target(unsigned char* Bytes) {
S& SRef = reinterpret_cast<S&>(Bytes);
SRef.I;
S* SPtr = reinterpret_cast<S*>(Bytes);
SPtr->I;
// [[p]]
}
)cc";
runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
&Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
const ValueDecl *I = findValueDecl(ASTCtx, "I");
ASSERT_THAT(I, NotNull());
// No particular knowledge of I's value is modeled, but for both casts,
// the fields of S are modeled.
{
auto &Loc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "SRef");
std::vector<const ValueDecl *> Children;
for (const auto &Entry : Loc.children()) {
Children.push_back(Entry.getFirst());
}
EXPECT_THAT(Children, UnorderedElementsAre(I));
}
{
auto &Loc = cast<RecordStorageLocation>(
getValueForDecl<PointerValue>(ASTCtx, Env, "SPtr").getPointeeLoc());
std::vector<const ValueDecl *> Children;
for (const auto &Entry : Loc.children()) {
Children.push_back(Entry.getFirst());
}
EXPECT_THAT(Children, UnorderedElementsAre(I));
}
});
}
TEST(TransferTest, IntegralCast) { TEST(TransferTest, IntegralCast) {
std::string Code = R"( std::string Code = R"(
void target(int Foo) { void target(int Foo) {

View File

@ -204,7 +204,7 @@ check_library_exists(stdc++ __cxa_throw "" COMPILER_RT_HAS_LIBSTDCXX)
llvm_check_compiler_linker_flag(C "-Wl,-z,text" COMPILER_RT_HAS_Z_TEXT) llvm_check_compiler_linker_flag(C "-Wl,-z,text" COMPILER_RT_HAS_Z_TEXT)
llvm_check_compiler_linker_flag(C "-fuse-ld=lld" COMPILER_RT_HAS_FUSE_LD_LLD_FLAG) llvm_check_compiler_linker_flag(C "-fuse-ld=lld" COMPILER_RT_HAS_FUSE_LD_LLD_FLAG)
if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS" AND LLVM_LINKER_IS_SOLARISLD) if("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS" AND LLVM_LINKER_IS_SOLARISLD)
set(VERS_COMPAT_OPTION "-Wl,-z,gnu-version-script-compat") set(VERS_COMPAT_OPTION "-Wl,-z,gnu-version-script-compat")
llvm_check_compiler_linker_flag(C "${VERS_COMPAT_OPTION}" COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT) llvm_check_compiler_linker_flag(C "${VERS_COMPAT_OPTION}" COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT)
endif() endif()

View File

@ -282,7 +282,7 @@ else()
endif() endif()
# On AIX, we only need the static libraries. # On AIX, we only need the static libraries.
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX") if (NOT "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
foreach(arch ${ASAN_SUPPORTED_ARCH}) foreach(arch ${ASAN_SUPPORTED_ARCH})
if (COMPILER_RT_HAS_VERSION_SCRIPT) if (COMPILER_RT_HAS_VERSION_SCRIPT)
if(WIN32) if(WIN32)
@ -392,7 +392,7 @@ add_compiler_rt_resource_file(asan_ignorelist asan_ignorelist.txt asan)
# On AIX, static sanitizer libraries are not added to the DSO, so we need to put # On AIX, static sanitizer libraries are not added to the DSO, so we need to put
# asan.link_with_main_exec.txt and asan_cxx.link_with_main_exec.txt to the build # asan.link_with_main_exec.txt and asan_cxx.link_with_main_exec.txt to the build
# and install dir for use in resolving undefined sanitizer symbols at runtime. # and install dir for use in resolving undefined sanitizer symbols at runtime.
if (${CMAKE_SYSTEM_NAME} MATCHES "AIX") if ("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
foreach(arch ${ASAN_SUPPORTED_ARCH}) foreach(arch ${ASAN_SUPPORTED_ARCH})
add_compiler_rt_cfg(asan_symbols_${arch} asan.link_with_main_exec.txt asan ${arch}) add_compiler_rt_cfg(asan_symbols_${arch} asan.link_with_main_exec.txt asan ${arch})
add_compiler_rt_cfg(asan_cxx_symbols_${arch} asan_cxx.link_with_main_exec.txt asan ${arch}) add_compiler_rt_cfg(asan_cxx_symbols_${arch} asan_cxx.link_with_main_exec.txt asan ${arch})

View File

@ -113,7 +113,7 @@ option(LIBCXX_ENABLE_MONOTONIC_CLOCK
# #
# TODO TZDB make the default always ON when most platforms ship with the IANA # TODO TZDB make the default always ON when most platforms ship with the IANA
# database. # database.
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
set(ENABLE_TIME_ZONE_DATABASE_DEFAULT ON) set(ENABLE_TIME_ZONE_DATABASE_DEFAULT ON)
else() else()
set(ENABLE_TIME_ZONE_DATABASE_DEFAULT OFF) set(ENABLE_TIME_ZONE_DATABASE_DEFAULT OFF)
@ -159,7 +159,7 @@ set(LIBCXX_TEST_PARAMS "" CACHE STRING
"A list of parameters to run the Lit test suite with.") "A list of parameters to run the Lit test suite with.")
# TODO: Figure out how to build GoogleBenchmark on those platforms, and how to build when exceptions or RTTI is disabled # TODO: Figure out how to build GoogleBenchmark on those platforms, and how to build when exceptions or RTTI is disabled
if (WIN32 OR MINGW OR ANDROID OR ${CMAKE_SYSTEM_NAME} MATCHES "AIX" if (WIN32 OR MINGW OR ANDROID OR "${CMAKE_SYSTEM_NAME}" MATCHES "AIX"
OR NOT LIBCXX_ENABLE_LOCALIZATION OR NOT LIBCXX_ENABLE_LOCALIZATION
OR NOT LIBCXX_ENABLE_THREADS OR NOT LIBCXX_ENABLE_THREADS
OR NOT LIBCXX_ENABLE_FILESYSTEM OR NOT LIBCXX_ENABLE_FILESYSTEM
@ -466,7 +466,7 @@ include(HandleLibcxxFlags)
# 'config-ix' use them during feature checks. It also adds them to both # 'config-ix' use them during feature checks. It also adds them to both
# 'LIBCXX_COMPILE_FLAGS' and 'LIBCXX_LINK_FLAGS' # 'LIBCXX_COMPILE_FLAGS' and 'LIBCXX_LINK_FLAGS'
if (${CMAKE_SYSTEM_NAME} MATCHES "AIX") if ("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
add_flags_if_supported("-mdefault-visibility-export-mapping=explicit") add_flags_if_supported("-mdefault-visibility-export-mapping=explicit")
set(CMAKE_AIX_EXPORT_ALL_SYMBOLS OFF) set(CMAKE_AIX_EXPORT_ALL_SYMBOLS OFF)
endif() endif()

View File

@ -244,7 +244,7 @@ include(HandleLibcxxabiFlags)
#=============================================================================== #===============================================================================
# Configure target flags # Configure target flags
if (${CMAKE_SYSTEM_NAME} MATCHES "AIX") if ("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
add_flags_if_supported("-mdefault-visibility-export-mapping=explicit") add_flags_if_supported("-mdefault-visibility-export-mapping=explicit")
set(CMAKE_AIX_EXPORT_ALL_SYMBOLS OFF) set(CMAKE_AIX_EXPORT_ALL_SYMBOLS OFF)
endif() endif()
@ -458,7 +458,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBCXXABI_C_FLAGS}")
# On AIX, avoid picking up VMX extensions(i.e. vec_malloc) which would change # On AIX, avoid picking up VMX extensions(i.e. vec_malloc) which would change
# the default alignment of the allocators here. # the default alignment of the allocators here.
if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") if (UNIX AND "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
add_definitions("-D_XOPEN_SOURCE=700") add_definitions("-D_XOPEN_SOURCE=700")
endif() endif()

View File

@ -37,7 +37,7 @@ else()
endif() endif()
if (LIBCXXABI_ENABLE_THREADS AND (UNIX OR FUCHSIA) AND NOT (APPLE OR CYGWIN) if (LIBCXXABI_ENABLE_THREADS AND (UNIX OR FUCHSIA) AND NOT (APPLE OR CYGWIN)
AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "AIX")) AND NOT ("${CMAKE_SYSTEM_NAME}" MATCHES "AIX"))
list(APPEND LIBCXXABI_SOURCES list(APPEND LIBCXXABI_SOURCES
cxa_thread_atexit.cpp cxa_thread_atexit.cpp
) )

View File

@ -6,7 +6,7 @@ set(LIBUNWIND_CXX_SOURCES
Unwind-seh.cpp Unwind-seh.cpp
) )
if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") if("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
list(APPEND LIBUNWIND_CXX_SOURCES list(APPEND LIBUNWIND_CXX_SOURCES
Unwind_AIXExtras.cpp Unwind_AIXExtras.cpp
) )

View File

@ -7,7 +7,7 @@ if (APPLE AND LLVM_ENABLE_LOCAL_SUBMODULE_VISIBILITY)
endif() endif()
endif() endif()
if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") if (UNIX AND "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
add_definitions("-D_ALL_SOURCE") add_definitions("-D_ALL_SOURCE")
endif() endif()

View File

@ -2,7 +2,7 @@ set(FBSDKERNEL_LIBS)
if(FBSDVMCore_FOUND) if(FBSDVMCore_FOUND)
list(APPEND FBSDKERNEL_LIBS fbsdvmcore) list(APPEND FBSDKERNEL_LIBS fbsdvmcore)
endif() endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") if("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
list(APPEND FBSDKERNEL_LIBS kvm) list(APPEND FBSDKERNEL_LIBS kvm)
endif() endif()

View File

@ -11,7 +11,7 @@ if(APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_BINARY_DIR}/lldb-Info.plist") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_BINARY_DIR}/lldb-Info.plist")
endif() endif()
if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") if (UNIX AND "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
remove_definitions("-D_XOPEN_SOURCE=700") remove_definitions("-D_XOPEN_SOURCE=700")
add_definitions("-D_ALL_SOURCE") add_definitions("-D_ALL_SOURCE")
endif() endif()

View File

@ -110,7 +110,7 @@ endif()
# one for llvm+clang+... using the same sources. # one for llvm+clang+... using the same sources.
# These projects will be included when "all" is included in LLVM_ENABLE_PROJECTS. # These projects will be included when "all" is included in LLVM_ENABLE_PROJECTS.
set(LLVM_ALL_PROJECTS "bolt;clang;clang-tools-extra;compiler-rt;cross-project-tests;libclc;lld;lldb;mlir;openmp;polly") set(LLVM_ALL_PROJECTS "bolt;clang;clang-tools-extra;compiler-rt;cross-project-tests;libclc;lld;lldb;mlir;openmp;polly")
if (${CMAKE_SYSTEM_NAME} MATCHES "AIX") if ("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
# Disallow 'openmp' as a LLVM PROJECT on AIX as the supported way is to use # Disallow 'openmp' as a LLVM PROJECT on AIX as the supported way is to use
# LLVM_ENABLE_RUNTIMES. # LLVM_ENABLE_RUNTIMES.
list(REMOVE_ITEM LLVM_ALL_PROJECTS openmp) list(REMOVE_ITEM LLVM_ALL_PROJECTS openmp)
@ -682,7 +682,7 @@ if (NOT CMAKE_SYSTEM_NAME MATCHES "OS390")
option(LLVM_ENABLE_PIC "Build Position-Independent Code" ON) option(LLVM_ENABLE_PIC "Build Position-Independent Code" ON)
endif() endif()
option(LLVM_ENABLE_MODULES "Compile with C++ modules enabled." OFF) option(LLVM_ENABLE_MODULES "Compile with C++ modules enabled." OFF)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
option(LLVM_ENABLE_MODULE_DEBUGGING "Compile with -gmodules." ON) option(LLVM_ENABLE_MODULE_DEBUGGING "Compile with -gmodules." ON)
else() else()
option(LLVM_ENABLE_MODULE_DEBUGGING "Compile with -gmodules." OFF) option(LLVM_ENABLE_MODULE_DEBUGGING "Compile with -gmodules." OFF)
@ -786,7 +786,7 @@ option(LLVM_USE_SPLIT_DWARF
# Define an option controlling whether we should build for 32-bit on 64-bit # Define an option controlling whether we should build for 32-bit on 64-bit
# platforms, where supported. # platforms, where supported.
if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT (WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "AIX")) if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT (WIN32 OR "${CMAKE_SYSTEM_NAME}" MATCHES "AIX"))
# TODO: support other platforms and toolchains. # TODO: support other platforms and toolchains.
option(LLVM_BUILD_32_BITS "Build 32 bits executables and libraries." OFF) option(LLVM_BUILD_32_BITS "Build 32 bits executables and libraries." OFF)
endif() endif()
@ -1257,7 +1257,7 @@ endif()
# Build with _XOPEN_SOURCE on AIX, as stray macros in _ALL_SOURCE mode tend to # Build with _XOPEN_SOURCE on AIX, as stray macros in _ALL_SOURCE mode tend to
# break things. In this case we need to enable the large-file API as well. # break things. In this case we need to enable the large-file API as well.
if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") if (UNIX AND "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
add_compile_definitions(_XOPEN_SOURCE=700) add_compile_definitions(_XOPEN_SOURCE=700)
add_compile_definitions(_LARGE_FILE_API) add_compile_definitions(_LARGE_FILE_API)
add_compile_options(-pthread) add_compile_options(-pthread)
@ -1285,7 +1285,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "OS390")
endif() endif()
# Build with _FILE_OFFSET_BITS=64 on Solaris to match g++ >= 9. # Build with _FILE_OFFSET_BITS=64 on Solaris to match g++ >= 9.
if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "SunOS") if (UNIX AND "${CMAKE_SYSTEM_NAME}" MATCHES "SunOS")
add_compile_definitions(_FILE_OFFSET_BITS=64) add_compile_definitions(_FILE_OFFSET_BITS=64)
endif() endif()
@ -1303,10 +1303,10 @@ if(LLVM_TARGET_IS_CROSSCOMPILE_HOST)
# (this is a variable that CrossCompile sets on recursive invocations) # (this is a variable that CrossCompile sets on recursive invocations)
endif() endif()
if( ${CMAKE_SYSTEM_NAME} MATCHES SunOS ) if( "${CMAKE_SYSTEM_NAME}" MATCHES SunOS )
# special hack for Solaris to handle crazy system sys/regset.h # special hack for Solaris to handle crazy system sys/regset.h
include_directories("${LLVM_MAIN_INCLUDE_DIR}/llvm/Support/Solaris") include_directories("${LLVM_MAIN_INCLUDE_DIR}/llvm/Support/Solaris")
endif( ${CMAKE_SYSTEM_NAME} MATCHES SunOS ) endif( "${CMAKE_SYSTEM_NAME}" MATCHES SunOS )
# Make sure we don't get -rdynamic in every binary. For those that need it, # Make sure we don't get -rdynamic in every binary. For those that need it,
# use EXPORT_SYMBOLS argument. # use EXPORT_SYMBOLS argument.

View File

@ -69,14 +69,14 @@ endif()
# Do checks with _XOPEN_SOURCE and large-file API on AIX, because we will build # Do checks with _XOPEN_SOURCE and large-file API on AIX, because we will build
# with those too. # with those too.
if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") if (UNIX AND "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_XOPEN_SOURCE=700") list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_XOPEN_SOURCE=700")
list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_LARGE_FILE_API") list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_LARGE_FILE_API")
endif() endif()
# Do checks with _FILE_OFFSET_BITS=64 on Solaris, because we will build # Do checks with _FILE_OFFSET_BITS=64 on Solaris, because we will build
# with those too. # with those too.
if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "SunOS") if (UNIX AND "${CMAKE_SYSTEM_NAME}" MATCHES "SunOS")
list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_FILE_OFFSET_BITS=64") list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_FILE_OFFSET_BITS=64")
endif() endif()
@ -122,7 +122,7 @@ if(APPLE)
HAVE_CRASHREPORTER_INFO) HAVE_CRASHREPORTER_INFO)
endif() endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
check_include_file(linux/magic.h HAVE_LINUX_MAGIC_H) check_include_file(linux/magic.h HAVE_LINUX_MAGIC_H)
if(NOT HAVE_LINUX_MAGIC_H) if(NOT HAVE_LINUX_MAGIC_H)
# older kernels use split files # older kernels use split files
@ -411,7 +411,7 @@ endif()
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") if (UNIX AND "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
# The st_mtim.tv_nsec member of a `stat` structure is not reliable on some AIX # The st_mtim.tv_nsec member of a `stat` structure is not reliable on some AIX
# environments. # environments.
set(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 0) set(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 0)

View File

@ -99,7 +99,7 @@ function(llvm_update_compile_flags name)
endfunction() endfunction()
function(add_llvm_symbol_exports target_name export_file) function(add_llvm_symbol_exports target_name export_file)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
set(native_export_file "${target_name}.exports") set(native_export_file "${target_name}.exports")
add_custom_command(OUTPUT ${native_export_file} add_custom_command(OUTPUT ${native_export_file}
COMMAND sed -e "s/^/_/" < ${export_file} > ${native_export_file} COMMAND sed -e "s/^/_/" < ${export_file} > ${native_export_file}
@ -108,7 +108,7 @@ function(add_llvm_symbol_exports target_name export_file)
COMMENT "Creating export file for ${target_name}") COMMENT "Creating export file for ${target_name}")
set_property(TARGET ${target_name} APPEND_STRING PROPERTY set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-exported_symbols_list,\"${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}\"") LINK_FLAGS " -Wl,-exported_symbols_list,\"${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}\"")
elseif(${CMAKE_SYSTEM_NAME} MATCHES "AIX") elseif("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
# FIXME: `-Wl,-bE:` bypasses whatever handling there is in the build # FIXME: `-Wl,-bE:` bypasses whatever handling there is in the build
# compiler driver to defer to the specified export list. # compiler driver to defer to the specified export list.
set(native_export_file "${export_file}") set(native_export_file "${export_file}")
@ -268,7 +268,7 @@ if (NOT DEFINED LLVM_LINKER_DETECTED AND NOT WIN32)
endif() endif()
endif() endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
include(CheckLinkerFlag) include(CheckLinkerFlag)
# Linkers that support Darwin allow a setting to internalize all symbol exports, # Linkers that support Darwin allow a setting to internalize all symbol exports,
# aiding in reducing binary size and often is applicable for executables. # aiding in reducing binary size and often is applicable for executables.
@ -315,11 +315,11 @@ function(add_link_opts target_name)
# linker in a context where the optimizations are not important. # linker in a context where the optimizations are not important.
if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
if(NOT LLVM_NO_DEAD_STRIP) if(NOT LLVM_NO_DEAD_STRIP)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
# ld64's implementation of -dead_strip breaks tools that use plugins. # ld64's implementation of -dead_strip breaks tools that use plugins.
set_property(TARGET ${target_name} APPEND_STRING PROPERTY set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-dead_strip") LINK_FLAGS " -Wl,-dead_strip")
elseif(${CMAKE_SYSTEM_NAME} MATCHES "SunOS" AND LLVM_LINKER_IS_SOLARISLD) elseif("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS" AND LLVM_LINKER_IS_SOLARISLD)
# Support for ld -z discard-unused=sections was only added in # Support for ld -z discard-unused=sections was only added in
# Solaris 11.4. GNU ld ignores it, but warns every time. # Solaris 11.4. GNU ld ignores it, but warns every time.
check_linker_flag(CXX "-Wl,-z,discard-unused=sections" LINKER_SUPPORTS_Z_DISCARD_UNUSED) check_linker_flag(CXX "-Wl,-z,discard-unused=sections" LINKER_SUPPORTS_Z_DISCARD_UNUSED)
@ -333,7 +333,7 @@ function(add_link_opts target_name)
LINK_FLAGS " -Wl,--gc-sections") LINK_FLAGS " -Wl,--gc-sections")
endif() endif()
else() #LLVM_NO_DEAD_STRIP else() #LLVM_NO_DEAD_STRIP
if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") if("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
set_property(TARGET ${target_name} APPEND_STRING PROPERTY set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-bnogc") LINK_FLAGS " -Wl,-bnogc")
endif() endif()
@ -345,7 +345,7 @@ function(add_link_opts target_name)
LINK_FLAGS " -Wl,-no_warn_duplicate_libraries") LINK_FLAGS " -Wl,-no_warn_duplicate_libraries")
endif() endif()
if(ARG_SUPPORT_PLUGINS AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") if(ARG_SUPPORT_PLUGINS AND "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
set_property(TARGET ${target_name} APPEND_STRING PROPERTY set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-brtl") LINK_FLAGS " -Wl,-brtl")
endif() endif()
@ -667,7 +667,7 @@ function(llvm_add_library name)
# that are used across shared objects which we can't hide. # that are used across shared objects which we can't hide.
if (LLVM_BUILD_LLVM_DYLIB_VIS AND NOT BUILD_SHARED_LIBS AND NOT APPLE AND if (LLVM_BUILD_LLVM_DYLIB_VIS AND NOT BUILD_SHARED_LIBS AND NOT APPLE AND
(NOT (WIN32 OR CYGWIN) OR ((MINGW OR CYGWIN) AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")) AND (NOT (WIN32 OR CYGWIN) OR ((MINGW OR CYGWIN) AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")) AND
NOT (${CMAKE_SYSTEM_NAME} MATCHES "AIX") AND NOT ("${CMAKE_SYSTEM_NAME}" MATCHES "AIX") AND
NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET) NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET)
set_target_properties(${name} PROPERTIES set_target_properties(${name} PROPERTIES
@ -1094,7 +1094,7 @@ macro(add_llvm_executable name)
llvm_update_compile_flags(${name}) llvm_update_compile_flags(${name})
endif() endif()
if (ARG_SUPPORT_PLUGINS AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX") if (ARG_SUPPORT_PLUGINS AND NOT "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
set(LLVM_NO_DEAD_STRIP On) set(LLVM_NO_DEAD_STRIP On)
endif() endif()
@ -1417,7 +1417,7 @@ function(export_executable_symbols target)
# CMake doesn't set CMAKE_EXE_EXPORTS_${lang}_FLAG on Solaris, so # CMake doesn't set CMAKE_EXE_EXPORTS_${lang}_FLAG on Solaris, so
# ENABLE_EXPORTS has no effect. While Solaris ld defaults to -rdynamic # ENABLE_EXPORTS has no effect. While Solaris ld defaults to -rdynamic
# behaviour, GNU ld needs it. # behaviour, GNU ld needs it.
if (APPLE OR ${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") if (APPLE OR "${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
set_property(TARGET ${target} APPEND_STRING PROPERTY set_property(TARGET ${target} APPEND_STRING PROPERTY
LINK_FLAGS " -rdynamic") LINK_FLAGS " -rdynamic")
endif() endif()
@ -2540,7 +2540,7 @@ function(llvm_setup_rpath name)
if (APPLE) if (APPLE)
set(_install_name_dir INSTALL_NAME_DIR "@rpath") set(_install_name_dir INSTALL_NAME_DIR "@rpath")
set(_install_rpath "@loader_path/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir}) set(_install_rpath "@loader_path/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir})
elseif(${CMAKE_SYSTEM_NAME} MATCHES "AIX" AND BUILD_SHARED_LIBS) elseif("${CMAKE_SYSTEM_NAME}" MATCHES "AIX" AND BUILD_SHARED_LIBS)
# $ORIGIN is not interpreted at link time by aix ld. # $ORIGIN is not interpreted at link time by aix ld.
# Since BUILD_SHARED_LIBS is only recommended for use by developers, # Since BUILD_SHARED_LIBS is only recommended for use by developers,
# hardcode the rpath to build/install lib dir first in this mode. # hardcode the rpath to build/install lib dir first in this mode.
@ -2549,7 +2549,7 @@ function(llvm_setup_rpath name)
elseif(UNIX) elseif(UNIX)
set(_build_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir}) set(_build_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir})
set(_install_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}") set(_install_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}")
if(${CMAKE_SYSTEM_NAME} MATCHES "(FreeBSD|DragonFly)") if("${CMAKE_SYSTEM_NAME}" MATCHES "(FreeBSD|DragonFly)")
set_property(TARGET ${name} APPEND_STRING PROPERTY set_property(TARGET ${name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-z,origin ") LINK_FLAGS " -Wl,-z,origin ")
endif() endif()
@ -2567,7 +2567,7 @@ function(llvm_setup_rpath name)
# On AIX, the tool chain doesn't support modifying rpaths/libpaths for XCOFF # On AIX, the tool chain doesn't support modifying rpaths/libpaths for XCOFF
# on install at the moment, so BUILD_WITH_INSTALL_RPATH is required. # on install at the moment, so BUILD_WITH_INSTALL_RPATH is required.
if("${CMAKE_BUILD_RPATH}" STREQUAL "") if("${CMAKE_BUILD_RPATH}" STREQUAL "")
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin|AIX") if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin|AIX")
set_property(TARGET ${name} PROPERTY BUILD_WITH_INSTALL_RPATH ON) set_property(TARGET ${name} PROPERTY BUILD_WITH_INSTALL_RPATH ON)
else() else()
set_property(TARGET ${name} APPEND PROPERTY BUILD_RPATH "${_build_rpath}") set_property(TARGET ${name} APPEND PROPERTY BUILD_RPATH "${_build_rpath}")

View File

@ -228,7 +228,7 @@ if(WIN32 OR CYGWIN)
elseif(FUCHSIA OR UNIX) elseif(FUCHSIA OR UNIX)
set(LLVM_ON_WIN32 0) set(LLVM_ON_WIN32 0)
set(LLVM_ON_UNIX 1) set(LLVM_ON_UNIX 1)
if(APPLE OR ${CMAKE_SYSTEM_NAME} MATCHES "AIX") if(APPLE OR "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
set(LLVM_HAVE_LINK_VERSION_SCRIPT 0) set(LLVM_HAVE_LINK_VERSION_SCRIPT 0)
else() else()
set(LLVM_HAVE_LINK_VERSION_SCRIPT 1) set(LLVM_HAVE_LINK_VERSION_SCRIPT 1)
@ -249,7 +249,7 @@ set(EXEEXT ${CMAKE_EXECUTABLE_SUFFIX})
set(LTDL_SHLIB_EXT ${CMAKE_SHARED_LIBRARY_SUFFIX}) set(LTDL_SHLIB_EXT ${CMAKE_SHARED_LIBRARY_SUFFIX})
# We use *.dylib rather than *.so on darwin, but we stick with *.so on AIX. # We use *.dylib rather than *.so on darwin, but we stick with *.so on AIX.
if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") if("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
set(LLVM_PLUGIN_EXT ${CMAKE_SHARED_MODULE_SUFFIX}) set(LLVM_PLUGIN_EXT ${CMAKE_SHARED_MODULE_SUFFIX})
else() else()
set(LLVM_PLUGIN_EXT ${CMAKE_SHARED_LIBRARY_SUFFIX}) set(LLVM_PLUGIN_EXT ${CMAKE_SHARED_LIBRARY_SUFFIX})
@ -260,7 +260,7 @@ if(APPLE)
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-flat_namespace -Wl,-undefined -Wl,dynamic_lookup") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-flat_namespace -Wl,-undefined -Wl,dynamic_lookup")
endif() endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
# RHEL7 has ar and ranlib being non-deterministic by default. The D flag forces determinism, # RHEL7 has ar and ranlib being non-deterministic by default. The D flag forces determinism,
# however only GNU version of ar and ranlib (2.27) have this option. # however only GNU version of ar and ranlib (2.27) have this option.
# RHEL DTS7 is also affected by this, which uses GNU binutils 2.28 # RHEL DTS7 is also affected by this, which uses GNU binutils 2.28
@ -292,7 +292,7 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
endif() endif()
endif() endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") if("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
# -fPIC does not enable the large code model for GCC on AIX but does for XL. # -fPIC does not enable the large code model for GCC on AIX but does for XL.
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
append("-mcmodel=large" CMAKE_CXX_FLAGS CMAKE_C_FLAGS) append("-mcmodel=large" CMAKE_CXX_FLAGS CMAKE_C_FLAGS)
@ -328,7 +328,7 @@ endif()
# by dlclose(). We need that since the CLI API relies on cross-references # by dlclose(). We need that since the CLI API relies on cross-references
# between global objects which became horribly broken when one of the libraries # between global objects which became horribly broken when one of the libraries
# is unloaded. # is unloaded.
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,nodelete") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,nodelete")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,nodelete") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,nodelete")
endif() endif()
@ -454,13 +454,13 @@ if( LLVM_ENABLE_PIC )
# to SEGV (GCC PR target/96607). # to SEGV (GCC PR target/96607).
# clang with -O3 -fPIC generates code that SEGVs. # clang with -O3 -fPIC generates code that SEGVs.
# Both can be worked around by compiling with -O instead. # Both can be worked around by compiling with -O instead.
if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS" AND LLVM_NATIVE_ARCH STREQUAL "Sparc") if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS" AND LLVM_NATIVE_ARCH STREQUAL "Sparc")
llvm_replace_compiler_option(CMAKE_CXX_FLAGS_RELEASE "-O[23]" "-O") llvm_replace_compiler_option(CMAKE_CXX_FLAGS_RELEASE "-O[23]" "-O")
llvm_replace_compiler_option(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O[23]" "-O") llvm_replace_compiler_option(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O[23]" "-O")
endif() endif()
endif() endif()
if((NOT (${CMAKE_SYSTEM_NAME} MATCHES "AIX")) AND if((NOT ("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")) AND
(NOT (WIN32 OR CYGWIN) OR ((MINGW OR CYGWIN) AND CMAKE_CXX_COMPILER_ID MATCHES "Clang"))) (NOT (WIN32 OR CYGWIN) OR ((MINGW OR CYGWIN) AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")))
# GCC for MinGW does nothing about -fvisibility-inlines-hidden, but warns # GCC for MinGW does nothing about -fvisibility-inlines-hidden, but warns
# about use of the attributes. As long as we don't use the attributes (to # about use of the attributes. As long as we don't use the attributes (to
@ -708,7 +708,7 @@ endif ()
if ( LLVM_COMPILER_IS_GCC_COMPATIBLE AND LLVM_ENABLE_MODULES ) if ( LLVM_COMPILER_IS_GCC_COMPATIBLE AND LLVM_ENABLE_MODULES )
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(module_flags "-fmodules -fmodules-cache-path=${PROJECT_BINARY_DIR}/module.cache") set(module_flags "-fmodules -fmodules-cache-path=${PROJECT_BINARY_DIR}/module.cache")
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
# On Darwin -fmodules does not imply -fcxx-modules. # On Darwin -fmodules does not imply -fcxx-modules.
set(module_flags "${module_flags} -fcxx-modules") set(module_flags "${module_flags} -fcxx-modules")
endif() endif()
@ -1123,7 +1123,7 @@ endif()
# But MinSizeRel seems to add that automatically, so maybe disable these # But MinSizeRel seems to add that automatically, so maybe disable these
# flags instead if LLVM_NO_DEAD_STRIP is set. # flags instead if LLVM_NO_DEAD_STRIP is set.
if(NOT CYGWIN AND NOT MSVC) if(NOT CYGWIN AND NOT MSVC)
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Darwin" AND
NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
if (CMAKE_CXX_COMPILER_ID MATCHES "XL") if (CMAKE_CXX_COMPILER_ID MATCHES "XL")
append("-qfuncsect" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) append("-qfuncsect" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
@ -1315,9 +1315,14 @@ endif()
# linking (due to incompatibility). With MSVC, note that the plugin has to # linking (due to incompatibility). With MSVC, note that the plugin has to
# explicitly link against (exactly one) tool so we can't unilaterally turn on # explicitly link against (exactly one) tool so we can't unilaterally turn on
# LLVM_ENABLE_PLUGINS when it's enabled. # LLVM_ENABLE_PLUGINS when it's enabled.
if("${CMAKE_SYSTEM_NAME}" MATCHES AIX)
set(LLVM_EXPORT_SYMBOLS_FOR_PLUGINS_OPTION OFF)
else()
set(LLVM_EXPORT_SYMBOLS_FOR_PLUGINS_OPTION ON)
endif()
CMAKE_DEPENDENT_OPTION(LLVM_EXPORT_SYMBOLS_FOR_PLUGINS CMAKE_DEPENDENT_OPTION(LLVM_EXPORT_SYMBOLS_FOR_PLUGINS
"Export symbols from LLVM tools so that plugins can import them" OFF "Export symbols from LLVM tools so that plugins can import them" OFF
"NOT ${CMAKE_SYSTEM_NAME} MATCHES AIX" ${LLVM_EXPORT_SYMBOLS_FOR_PLUGINS_AIX_default}) "LLVM_EXPORT_SYMBOLS_FOR_PLUGINS_OPTION" ${LLVM_EXPORT_SYMBOLS_FOR_PLUGINS_AIX_default})
if(BUILD_SHARED_LIBS AND LLVM_EXPORT_SYMBOLS_FOR_PLUGINS) if(BUILD_SHARED_LIBS AND LLVM_EXPORT_SYMBOLS_FOR_PLUGINS)
message(FATAL_ERROR "BUILD_SHARED_LIBS not compatible with LLVM_EXPORT_SYMBOLS_FOR_PLUGINS") message(FATAL_ERROR "BUILD_SHARED_LIBS not compatible with LLVM_EXPORT_SYMBOLS_FOR_PLUGINS")
endif() endif()

View File

@ -37,8 +37,6 @@ namespace llvm::cas {
/// in the same process since file locks will misbehave. Clients should /// in the same process since file locks will misbehave. Clients should
/// coordinate (somehow). /// coordinate (somehow).
/// ///
/// \note Currently we allocate the whole file without sparseness on Windows.
///
/// Provides 8-byte alignment for all allocations. /// Provides 8-byte alignment for all allocations.
class MappedFileRegionBumpPtr { class MappedFileRegionBumpPtr {
public: public:
@ -97,13 +95,6 @@ public:
MappedFileRegionBumpPtr &operator=(const MappedFileRegionBumpPtr &) = delete; MappedFileRegionBumpPtr &operator=(const MappedFileRegionBumpPtr &) = delete;
private: private:
// The file size increment to extend the storage size.
// The minimum increment is a page, but allocate more to amortize the cost.
static constexpr int64_t Increment = 4 * 1024 * 1024; // 4 MB
// Extend the AllocatedSize to be enough to hold NewEnd.
Error extendSpaceImpl(int64_t NewEnd);
void destroyImpl(); void destroyImpl();
void moveImpl(MappedFileRegionBumpPtr &RHS) { void moveImpl(MappedFileRegionBumpPtr &RHS) {
std::swap(Region, RHS.Region); std::swap(Region, RHS.Region);

View File

@ -1103,6 +1103,7 @@ def OMP_Target : Directive<[Spelling<"target">]> {
let allowedClauses = [ let allowedClauses = [
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_InReduction, 50>, VersionedClause<OMPC_InReduction, 50>,
@ -1115,7 +1116,6 @@ def OMP_Target : Directive<[Spelling<"target">]> {
let allowedOnceClauses = [ let allowedOnceClauses = [
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
VersionedClause<OMPC_NoWait>, VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_OMPX_Bare>, VersionedClause<OMPC_OMPX_Bare>,
@ -1258,6 +1258,7 @@ def OMP_TaskYield : Directive<[Spelling<"taskyield">]> {
def OMP_Teams : Directive<[Spelling<"teams">]> { def OMP_Teams : Directive<[Spelling<"teams">]> {
let allowedClauses = [ let allowedClauses = [
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_OMPX_Attribute>, VersionedClause<OMPC_OMPX_Attribute>,
VersionedClause<OMPC_Private>, VersionedClause<OMPC_Private>,
@ -1266,7 +1267,6 @@ def OMP_Teams : Directive<[Spelling<"teams">]> {
]; ];
let allowedOnceClauses = [ let allowedOnceClauses = [
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_If, 52>, VersionedClause<OMPC_If, 52>,
VersionedClause<OMPC_NumTeams>, VersionedClause<OMPC_NumTeams>,
VersionedClause<OMPC_ThreadLimit>, VersionedClause<OMPC_ThreadLimit>,
@ -1520,6 +1520,7 @@ def OMP_target_loop : Directive<[Spelling<"target loop">]> {
let allowedClauses = [ let allowedClauses = [
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_IsDevicePtr>, VersionedClause<OMPC_IsDevicePtr>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
@ -1535,7 +1536,6 @@ def OMP_target_loop : Directive<[Spelling<"target loop">]> {
let allowedOnceClauses = [ let allowedOnceClauses = [
VersionedClause<OMPC_Bind, 50>, VersionedClause<OMPC_Bind, 50>,
VersionedClause<OMPC_Collapse>, VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_Order>, VersionedClause<OMPC_Order>,
VersionedClause<OMPC_ThreadLimit>, VersionedClause<OMPC_ThreadLimit>,
VersionedClause<OMPC_OMPX_DynCGroupMem>, VersionedClause<OMPC_OMPX_DynCGroupMem>,
@ -1982,6 +1982,7 @@ def OMP_TargetParallel : Directive<[Spelling<"target parallel">]> {
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -1997,7 +1998,6 @@ def OMP_TargetParallel : Directive<[Spelling<"target parallel">]> {
let allowedOnceClauses = [ let allowedOnceClauses = [
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NumThreads>, VersionedClause<OMPC_NumThreads>,
VersionedClause<OMPC_OMPX_DynCGroupMem>, VersionedClause<OMPC_OMPX_DynCGroupMem>,
VersionedClause<OMPC_ProcBind>, VersionedClause<OMPC_ProcBind>,
@ -2011,6 +2011,7 @@ def OMP_TargetParallelDo : Directive<[Spelling<"target parallel do">]> {
VersionedClause<OMPC_Allocator>, VersionedClause<OMPC_Allocator>,
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2027,7 +2028,6 @@ def OMP_TargetParallelDo : Directive<[Spelling<"target parallel do">]> {
VersionedClause<OMPC_Collapse>, VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NoWait>, VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_NumThreads>, VersionedClause<OMPC_NumThreads>,
VersionedClause<OMPC_Order, 50>, VersionedClause<OMPC_Order, 50>,
@ -2049,6 +2049,7 @@ def OMP_TargetParallelDoSimd
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2070,9 +2071,6 @@ def OMP_TargetParallelDoSimd
VersionedClause<OMPC_SimdLen>, VersionedClause<OMPC_SimdLen>,
VersionedClause<OMPC_UsesAllocators>, VersionedClause<OMPC_UsesAllocators>,
]; ];
let allowedOnceClauses = [
VersionedClause<OMPC_DynGroupprivate, 61>,
];
let leafConstructs = [OMP_Target, OMP_Parallel, OMP_Do, OMP_Simd]; let leafConstructs = [OMP_Target, OMP_Parallel, OMP_Do, OMP_Simd];
let category = CA_Executable; let category = CA_Executable;
let languages = [L_Fortran]; let languages = [L_Fortran];
@ -2085,6 +2083,7 @@ def OMP_TargetParallelFor : Directive<[Spelling<"target parallel for">]> {
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2105,7 +2104,6 @@ def OMP_TargetParallelFor : Directive<[Spelling<"target parallel for">]> {
VersionedClause<OMPC_UsesAllocators, 50>, VersionedClause<OMPC_UsesAllocators, 50>,
]; ];
let allowedOnceClauses = [ let allowedOnceClauses = [
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_OMPX_DynCGroupMem>, VersionedClause<OMPC_OMPX_DynCGroupMem>,
VersionedClause<OMPC_ThreadLimit, 51>, VersionedClause<OMPC_ThreadLimit, 51>,
]; ];
@ -2123,6 +2121,7 @@ def OMP_TargetParallelForSimd
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2146,7 +2145,6 @@ def OMP_TargetParallelForSimd
VersionedClause<OMPC_UsesAllocators, 50>, VersionedClause<OMPC_UsesAllocators, 50>,
]; ];
let allowedOnceClauses = [ let allowedOnceClauses = [
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_OMPX_DynCGroupMem>, VersionedClause<OMPC_OMPX_DynCGroupMem>,
VersionedClause<OMPC_ThreadLimit, 51>, VersionedClause<OMPC_ThreadLimit, 51>,
]; ];
@ -2159,6 +2157,7 @@ def OMP_target_parallel_loop : Directive<[Spelling<"target parallel loop">]> {
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2176,7 +2175,6 @@ def OMP_target_parallel_loop : Directive<[Spelling<"target parallel loop">]> {
VersionedClause<OMPC_Collapse>, VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NoWait>, VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_NumThreads>, VersionedClause<OMPC_NumThreads>,
VersionedClause<OMPC_OMPX_DynCGroupMem>, VersionedClause<OMPC_OMPX_DynCGroupMem>,
@ -2192,6 +2190,7 @@ def OMP_TargetSimd : Directive<[Spelling<"target simd">]> {
VersionedClause<OMPC_Aligned>, VersionedClause<OMPC_Aligned>,
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2211,7 +2210,6 @@ def OMP_TargetSimd : Directive<[Spelling<"target simd">]> {
VersionedClause<OMPC_Collapse>, VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NumThreads>, VersionedClause<OMPC_NumThreads>,
VersionedClause<OMPC_OMPX_DynCGroupMem>, VersionedClause<OMPC_OMPX_DynCGroupMem>,
VersionedClause<OMPC_Order, 50>, VersionedClause<OMPC_Order, 50>,
@ -2228,6 +2226,7 @@ def OMP_TargetTeams : Directive<[Spelling<"target teams">]> {
let allowedClauses = [ let allowedClauses = [
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2243,7 +2242,6 @@ def OMP_TargetTeams : Directive<[Spelling<"target teams">]> {
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NoWait>, VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_NumTeams>, VersionedClause<OMPC_NumTeams>,
VersionedClause<OMPC_OMPX_DynCGroupMem>, VersionedClause<OMPC_OMPX_DynCGroupMem>,
@ -2258,6 +2256,7 @@ def OMP_TargetTeamsDistribute
let allowedClauses = [ let allowedClauses = [
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2276,7 +2275,6 @@ def OMP_TargetTeamsDistribute
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DistSchedule>, VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NoWait>, VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_NumTeams>, VersionedClause<OMPC_NumTeams>,
VersionedClause<OMPC_OMPX_DynCGroupMem>, VersionedClause<OMPC_OMPX_DynCGroupMem>,
@ -2291,6 +2289,7 @@ def OMP_TargetTeamsDistributeParallelDo
let allowedClauses = [ let allowedClauses = [
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2309,7 +2308,6 @@ def OMP_TargetTeamsDistributeParallelDo
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DistSchedule>, VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NoWait>, VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_NumTeams>, VersionedClause<OMPC_NumTeams>,
VersionedClause<OMPC_NumThreads>, VersionedClause<OMPC_NumThreads>,
@ -2329,6 +2327,7 @@ def OMP_TargetTeamsDistributeParallelDoSimd
VersionedClause<OMPC_Aligned>, VersionedClause<OMPC_Aligned>,
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2348,7 +2347,6 @@ def OMP_TargetTeamsDistributeParallelDoSimd
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DistSchedule>, VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NoWait>, VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_NumTeams>, VersionedClause<OMPC_NumTeams>,
VersionedClause<OMPC_NumThreads>, VersionedClause<OMPC_NumThreads>,
@ -2374,6 +2372,7 @@ def OMP_TargetTeamsDistributeParallelFor
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DistSchedule>, VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2394,7 +2393,6 @@ def OMP_TargetTeamsDistributeParallelFor
VersionedClause<OMPC_UsesAllocators, 50>, VersionedClause<OMPC_UsesAllocators, 50>,
]; ];
let allowedOnceClauses = [ let allowedOnceClauses = [
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_OMPX_DynCGroupMem>, VersionedClause<OMPC_OMPX_DynCGroupMem>,
]; ];
let leafConstructs = let leafConstructs =
@ -2413,6 +2411,7 @@ def OMP_TargetTeamsDistributeParallelForSimd
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DistSchedule>, VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2437,7 +2436,6 @@ def OMP_TargetTeamsDistributeParallelForSimd
VersionedClause<OMPC_UsesAllocators, 50>, VersionedClause<OMPC_UsesAllocators, 50>,
]; ];
let allowedOnceClauses = [ let allowedOnceClauses = [
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_OMPX_DynCGroupMem>, VersionedClause<OMPC_OMPX_DynCGroupMem>,
]; ];
let leafConstructs = let leafConstructs =
@ -2451,6 +2449,7 @@ def OMP_TargetTeamsDistributeSimd
VersionedClause<OMPC_Aligned>, VersionedClause<OMPC_Aligned>,
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2470,7 +2469,6 @@ def OMP_TargetTeamsDistributeSimd
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DistSchedule>, VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NoWait>, VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_NumTeams>, VersionedClause<OMPC_NumTeams>,
VersionedClause<OMPC_OMPX_DynCGroupMem>, VersionedClause<OMPC_OMPX_DynCGroupMem>,
@ -2488,6 +2486,7 @@ def OMP_target_teams_loop : Directive<[Spelling<"target teams loop">]> {
VersionedClause<OMPC_DefaultMap>, VersionedClause<OMPC_DefaultMap>,
VersionedClause<OMPC_Depend>, VersionedClause<OMPC_Depend>,
VersionedClause<OMPC_Device>, VersionedClause<OMPC_Device>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_HasDeviceAddr, 51>, VersionedClause<OMPC_HasDeviceAddr, 51>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
@ -2504,7 +2503,6 @@ def OMP_target_teams_loop : Directive<[Spelling<"target teams loop">]> {
VersionedClause<OMPC_Bind, 50>, VersionedClause<OMPC_Bind, 50>,
VersionedClause<OMPC_Collapse>, VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NoWait>, VersionedClause<OMPC_NoWait>,
VersionedClause<OMPC_NumTeams>, VersionedClause<OMPC_NumTeams>,
VersionedClause<OMPC_OMPX_DynCGroupMem>, VersionedClause<OMPC_OMPX_DynCGroupMem>,
@ -2553,6 +2551,7 @@ def OMP_TeamsDistribute : Directive<[Spelling<"teams distribute">]> {
VersionedClause<OMPC_Collapse>, VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_DistSchedule>, VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_LastPrivate>, VersionedClause<OMPC_LastPrivate>,
VersionedClause<OMPC_NumTeams>, VersionedClause<OMPC_NumTeams>,
@ -2563,7 +2562,6 @@ def OMP_TeamsDistribute : Directive<[Spelling<"teams distribute">]> {
VersionedClause<OMPC_ThreadLimit>, VersionedClause<OMPC_ThreadLimit>,
]; ];
let allowedOnceClauses = [ let allowedOnceClauses = [
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
VersionedClause<OMPC_Order, 50>, VersionedClause<OMPC_Order, 50>,
]; ];
@ -2575,6 +2573,7 @@ def OMP_TeamsDistributeParallelDo
let allowedClauses = [ let allowedClauses = [
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Copyin>, VersionedClause<OMPC_Copyin>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
VersionedClause<OMPC_LastPrivate>, VersionedClause<OMPC_LastPrivate>,
@ -2587,7 +2586,6 @@ def OMP_TeamsDistributeParallelDo
VersionedClause<OMPC_Collapse>, VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_DistSchedule>, VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NumTeams>, VersionedClause<OMPC_NumTeams>,
VersionedClause<OMPC_NumThreads>, VersionedClause<OMPC_NumThreads>,
VersionedClause<OMPC_Order, 50>, VersionedClause<OMPC_Order, 50>,
@ -2604,6 +2602,7 @@ def OMP_TeamsDistributeParallelDoSimd
let allowedClauses = [ let allowedClauses = [
VersionedClause<OMPC_Aligned>, VersionedClause<OMPC_Aligned>,
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
VersionedClause<OMPC_LastPrivate>, VersionedClause<OMPC_LastPrivate>,
@ -2617,7 +2616,6 @@ def OMP_TeamsDistributeParallelDoSimd
VersionedClause<OMPC_Collapse>, VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_DistSchedule>, VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NumTeams>, VersionedClause<OMPC_NumTeams>,
VersionedClause<OMPC_NumThreads>, VersionedClause<OMPC_NumThreads>,
VersionedClause<OMPC_Order, 50>, VersionedClause<OMPC_Order, 50>,
@ -2640,6 +2638,7 @@ def OMP_TeamsDistributeParallelFor
VersionedClause<OMPC_Copyin>, VersionedClause<OMPC_Copyin>,
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_DistSchedule>, VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
VersionedClause<OMPC_LastPrivate>, VersionedClause<OMPC_LastPrivate>,
@ -2654,9 +2653,6 @@ def OMP_TeamsDistributeParallelFor
VersionedClause<OMPC_Shared>, VersionedClause<OMPC_Shared>,
VersionedClause<OMPC_ThreadLimit>, VersionedClause<OMPC_ThreadLimit>,
]; ];
let allowedOnceClauses = [
VersionedClause<OMPC_DynGroupprivate, 61>,
];
let leafConstructs = [OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_For]; let leafConstructs = [OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_For];
let category = CA_Executable; let category = CA_Executable;
let languages = [L_C]; let languages = [L_C];
@ -2669,6 +2665,7 @@ def OMP_TeamsDistributeParallelForSimd
VersionedClause<OMPC_Collapse>, VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_DistSchedule>, VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_If>, VersionedClause<OMPC_If>,
VersionedClause<OMPC_LastPrivate>, VersionedClause<OMPC_LastPrivate>,
@ -2687,9 +2684,6 @@ def OMP_TeamsDistributeParallelForSimd
VersionedClause<OMPC_SimdLen>, VersionedClause<OMPC_SimdLen>,
VersionedClause<OMPC_ThreadLimit>, VersionedClause<OMPC_ThreadLimit>,
]; ];
let allowedOnceClauses = [
VersionedClause<OMPC_DynGroupprivate, 61>,
];
let leafConstructs = let leafConstructs =
[OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_For, OMP_Simd]; [OMP_Teams, OMP_Distribute, OMP_Parallel, OMP_For, OMP_Simd];
let category = CA_Executable; let category = CA_Executable;
@ -2699,6 +2693,7 @@ def OMP_TeamsDistributeSimd : Directive<[Spelling<"teams distribute simd">]> {
let allowedClauses = [ let allowedClauses = [
VersionedClause<OMPC_Aligned>, VersionedClause<OMPC_Aligned>,
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_If, 50>, VersionedClause<OMPC_If, 50>,
VersionedClause<OMPC_LastPrivate>, VersionedClause<OMPC_LastPrivate>,
@ -2713,7 +2708,6 @@ def OMP_TeamsDistributeSimd : Directive<[Spelling<"teams distribute simd">]> {
VersionedClause<OMPC_Collapse>, VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_DistSchedule>, VersionedClause<OMPC_DistSchedule>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NumTeams>, VersionedClause<OMPC_NumTeams>,
VersionedClause<OMPC_Order, 50>, VersionedClause<OMPC_Order, 50>,
VersionedClause<OMPC_SafeLen>, VersionedClause<OMPC_SafeLen>,
@ -2726,6 +2720,7 @@ def OMP_TeamsDistributeSimd : Directive<[Spelling<"teams distribute simd">]> {
def OMP_teams_loop : Directive<[Spelling<"teams loop">]> { def OMP_teams_loop : Directive<[Spelling<"teams loop">]> {
let allowedClauses = [ let allowedClauses = [
VersionedClause<OMPC_Allocate>, VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_FirstPrivate>, VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_LastPrivate>, VersionedClause<OMPC_LastPrivate>,
VersionedClause<OMPC_OMPX_Attribute>, VersionedClause<OMPC_OMPX_Attribute>,
@ -2737,7 +2732,6 @@ def OMP_teams_loop : Directive<[Spelling<"teams loop">]> {
VersionedClause<OMPC_Bind, 50>, VersionedClause<OMPC_Bind, 50>,
VersionedClause<OMPC_Collapse>, VersionedClause<OMPC_Collapse>,
VersionedClause<OMPC_Default>, VersionedClause<OMPC_Default>,
VersionedClause<OMPC_DynGroupprivate, 61>,
VersionedClause<OMPC_NumTeams>, VersionedClause<OMPC_NumTeams>,
VersionedClause<OMPC_Order>, VersionedClause<OMPC_Order>,
VersionedClause<OMPC_ThreadLimit>, VersionedClause<OMPC_ThreadLimit>,

View File

@ -20,12 +20,14 @@
/// and across multiple processes without locking for every read. Our current /// and across multiple processes without locking for every read. Our current
/// implementation strategy is: /// implementation strategy is:
/// ///
/// 1. Use \c ftruncate (\c sys::fs::resize_file) to grow the file to its max /// 1. Use \c sys::fs::resize_file_sparse to grow the file to its max size
/// size (typically several GB). Many modern filesystems will create a sparse /// (typically several GB). If the file system doesn't support sparse file,
/// file, so that the trailing unused pages do not take space on disk. /// this may return a fully allocated file.
/// 2. Call \c mmap (\c sys::fs::mapped_file_region) /// 2. Call \c sys::fs::mapped_file_region to map the entire file.
/// 3. [Automatic as part of 2.] /// 3. [Automatic as part of 2.]
/// 4. [Automatic as part of 2.] /// 4. If supported, use \c fallocate or similiar APIs to ensure the file system
/// storage for the sparse file so we won't end up with partial file if the
/// disk is out of space.
/// ///
/// Additionally, we attempt to resize the file to its actual data size when /// Additionally, we attempt to resize the file to its actual data size when
/// closing the mapping, if this is the only concurrent instance. This is done /// closing the mapping, if this is the only concurrent instance. This is done
@ -160,9 +162,7 @@ Expected<MappedFileRegionBumpPtr> MappedFileRegionBumpPtr::create(
if (FileSize->Size < Capacity) { if (FileSize->Size < Capacity) {
// We are initializing the file; it may be empty, or may have been shrunk // We are initializing the file; it may be empty, or may have been shrunk
// during a previous close. // during a previous close.
// FIXME: Detect a case where someone opened it with a smaller capacity. // TODO: Detect a case where someone opened it with a smaller capacity.
// FIXME: On Windows we should use FSCTL_SET_SPARSE and FSCTL_SET_ZERO_DATA
// to make this a sparse region, if supported.
assert(InitLock.Locked == sys::fs::LockKind::Exclusive); assert(InitLock.Locked == sys::fs::LockKind::Exclusive);
if (std::error_code EC = sys::fs::resize_file_sparse(FD, Capacity)) if (std::error_code EC = sys::fs::resize_file_sparse(FD, Capacity))
return createFileError(Result.Path, EC); return createFileError(Result.Path, EC);

View File

@ -62,7 +62,7 @@ elseif( CMAKE_HOST_UNIX )
if( UNIX AND NOT (BEOS OR HAIKU) ) if( UNIX AND NOT (BEOS OR HAIKU) )
set(system_libs ${system_libs} m) set(system_libs ${system_libs} m)
endif() endif()
if( UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "SunOS" ) if( UNIX AND "${CMAKE_SYSTEM_NAME}" MATCHES "SunOS" )
set(system_libs ${system_libs} kstat socket) set(system_libs ${system_libs} kstat socket)
endif() endif()
if( FUCHSIA ) if( FUCHSIA )
@ -130,7 +130,7 @@ endif()
# unistd.h and it is guarded by _ALL_SOURCE, so we remove the _XOPEN_SOURCE # unistd.h and it is guarded by _ALL_SOURCE, so we remove the _XOPEN_SOURCE
# guard here. We should remove the guards all together once AIX cleans up # guard here. We should remove the guards all together once AIX cleans up
# the system headers. # the system headers.
if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") if (UNIX AND "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
remove_definitions("-D_XOPEN_SOURCE=700") remove_definitions("-D_XOPEN_SOURCE=700")
endif() endif()

View File

@ -24,7 +24,7 @@ add_llvm_component_library(LLVMTarget
# that are used across shared objects which we can't hide. # that are used across shared objects which we can't hide.
if (NOT BUILD_SHARED_LIBS AND NOT APPLE AND if (NOT BUILD_SHARED_LIBS AND NOT APPLE AND
(NOT (WIN32 OR CYGWIN) OR ((MINGW OR CYGWIN) AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")) AND (NOT (WIN32 OR CYGWIN) OR ((MINGW OR CYGWIN) AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")) AND
NOT (${CMAKE_SYSTEM_NAME} MATCHES "AIX") AND NOT ("${CMAKE_SYSTEM_NAME}" MATCHES "AIX") AND
NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET) NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET)
# Set default visibility to hidden, so we don't export all the Target classes # Set default visibility to hidden, so we don't export all the Target classes
# in libLLVM.so. # in libLLVM.so.

View File

@ -110,8 +110,6 @@ RISCVMoveMerge::mergePairedInsns(MachineBasicBlock::iterator I,
MachineBasicBlock::iterator NextI = next_nodbg(I, E); MachineBasicBlock::iterator NextI = next_nodbg(I, E);
DestSourcePair FirstPair = TII->isCopyInstrImpl(*I).value(); DestSourcePair FirstPair = TII->isCopyInstrImpl(*I).value();
DestSourcePair PairedRegs = TII->isCopyInstrImpl(*Paired).value(); DestSourcePair PairedRegs = TII->isCopyInstrImpl(*Paired).value();
Register ARegInFirstPair = MoveFromSToA ? FirstPair.Destination->getReg()
: FirstPair.Source->getReg();
if (NextI == Paired) if (NextI == Paired)
NextI = next_nodbg(NextI, E); NextI = next_nodbg(NextI, E);
@ -130,7 +128,6 @@ RISCVMoveMerge::mergePairedInsns(MachineBasicBlock::iterator I,
// //
// mv a0, s2 // mv a0, s2
// mv a1, s1 => cm.mva01s s2,s1 // mv a1, s1 => cm.mva01s s2,s1
bool StartWithX10 = ARegInFirstPair == RISCV::X10;
unsigned Opcode; unsigned Opcode;
if (MoveFromSToA) { if (MoveFromSToA) {
// We are moving one of the copies earlier so its kill flag may become // We are moving one of the copies earlier so its kill flag may become
@ -141,12 +138,16 @@ RISCVMoveMerge::mergePairedInsns(MachineBasicBlock::iterator I,
PairedSource.setIsKill(false); PairedSource.setIsKill(false);
Opcode = getMoveFromSToAOpcode(*ST); Opcode = getMoveFromSToAOpcode(*ST);
Sreg1 = StartWithX10 ? FirstPair.Source : &PairedSource; Sreg1 = FirstPair.Source;
Sreg2 = StartWithX10 ? &PairedSource : FirstPair.Source; Sreg2 = &PairedSource;
if (FirstPair.Destination->getReg() != RISCV::X10)
std::swap(Sreg1, Sreg2);
} else { } else {
Opcode = getMoveFromAToSOpcode(*ST); Opcode = getMoveFromAToSOpcode(*ST);
Sreg1 = StartWithX10 ? FirstPair.Destination : PairedRegs.Destination; Sreg1 = FirstPair.Destination;
Sreg2 = StartWithX10 ? PairedRegs.Destination : FirstPair.Destination; Sreg2 = PairedRegs.Destination;
if (FirstPair.Source->getReg() != RISCV::X10)
std::swap(Sreg1, Sreg2);
} }
BuildMI(*I->getParent(), I, DL, TII->get(Opcode)).add(*Sreg1).add(*Sreg2); BuildMI(*I->getParent(), I, DL, TII->get(Opcode)).add(*Sreg1).add(*Sreg2);

View File

@ -23185,43 +23185,51 @@ static SDValue LowerVectorAllEqual(const SDLoc &DL, SDValue LHS, SDValue RHS,
// Check whether an AND/OR'd reduction tree is PTEST-able, or if we can fallback // Check whether an AND/OR'd reduction tree is PTEST-able, or if we can fallback
// to CMP(MOVMSK(PCMPEQB(X,Y))). // to CMP(MOVMSK(PCMPEQB(X,Y))).
static SDValue MatchVectorAllEqualTest(SDValue LHS, SDValue RHS, static SDValue MatchVectorAllEqualTest(SDValue OrigLHS, SDValue OrigRHS,
ISD::CondCode CC, const SDLoc &DL, ISD::CondCode CC, const SDLoc &DL,
const X86Subtarget &Subtarget, const X86Subtarget &Subtarget,
SelectionDAG &DAG, SelectionDAG &DAG,
X86::CondCode &X86CC) { X86::CondCode &X86CC) {
assert((CC == ISD::SETEQ || CC == ISD::SETNE) && "Unsupported ISD::CondCode"); SDValue Op = OrigLHS;
bool CmpNull = isNullConstant(RHS); bool CmpNull;
bool CmpAllOnes = isAllOnesConstant(RHS); APInt Mask;
if (!CmpNull && !CmpAllOnes) if (CC == ISD::SETEQ || CC == ISD::SETNE) {
return SDValue(); CmpNull = isNullConstant(OrigRHS);
if (!CmpNull && !isAllOnesConstant(OrigRHS))
return SDValue();
SDValue Op = LHS; if (!Subtarget.hasSSE2() || !Op->hasOneUse())
if (!Subtarget.hasSSE2() || !Op->hasOneUse()) return SDValue();
return SDValue();
// Check whether we're masking/truncating an OR-reduction result, in which // Check whether we're masking/truncating an OR-reduction result, in which
// case track the masked bits. // case track the masked bits.
// TODO: Add CmpAllOnes support. // TODO: Add CmpAllOnes support.
APInt Mask = APInt::getAllOnes(Op.getScalarValueSizeInBits()); Mask = APInt::getAllOnes(Op.getScalarValueSizeInBits());
if (CmpNull) { if (CmpNull) {
switch (Op.getOpcode()) { switch (Op.getOpcode()) {
case ISD::TRUNCATE: { case ISD::TRUNCATE: {
SDValue Src = Op.getOperand(0); SDValue Src = Op.getOperand(0);
Mask = APInt::getLowBitsSet(Src.getScalarValueSizeInBits(), Mask = APInt::getLowBitsSet(Src.getScalarValueSizeInBits(),
Op.getScalarValueSizeInBits()); Op.getScalarValueSizeInBits());
Op = Src; Op = Src;
break; break;
} }
case ISD::AND: { case ISD::AND: {
if (auto *Cst = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { if (auto *Cst = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
Mask = Cst->getAPIntValue(); Mask = Cst->getAPIntValue();
Op = Op.getOperand(0); Op = Op.getOperand(0);
}
break;
}
} }
break;
}
} }
} else if (CC == ISD::SETGT && isAllOnesConstant(OrigRHS)) {
CC = ISD::SETEQ;
CmpNull = true;
Mask = APInt::getSignMask(Op.getScalarValueSizeInBits());
} else {
return SDValue();
} }
ISD::NodeType LogicOp = CmpNull ? ISD::OR : ISD::AND; ISD::NodeType LogicOp = CmpNull ? ISD::OR : ISD::AND;
@ -56274,14 +56282,16 @@ static SDValue combineSetCC(SDNode *N, SelectionDAG &DAG,
if (SDValue V = combineVectorSizedSetCCEquality(VT, LHS, RHS, CC, DL, DAG, if (SDValue V = combineVectorSizedSetCCEquality(VT, LHS, RHS, CC, DL, DAG,
Subtarget)) Subtarget))
return V; return V;
}
if (VT == MVT::i1) { if (VT == MVT::i1) {
X86::CondCode X86CC; X86::CondCode X86CC;
if (SDValue V = if (SDValue V =
MatchVectorAllEqualTest(LHS, RHS, CC, DL, Subtarget, DAG, X86CC)) MatchVectorAllEqualTest(LHS, RHS, CC, DL, Subtarget, DAG, X86CC))
return DAG.getNode(ISD::TRUNCATE, DL, VT, getSETCC(X86CC, V, DL, DAG)); return DAG.getNode(ISD::TRUNCATE, DL, VT, getSETCC(X86CC, V, DL, DAG));
} }
if (CC == ISD::SETNE || CC == ISD::SETEQ) {
if (OpVT.isScalarInteger()) { if (OpVT.isScalarInteger()) {
// cmpeq(or(X,Y),X) --> cmpeq(and(~X,Y),0) // cmpeq(or(X,Y),X) --> cmpeq(and(~X,Y),0)
// cmpne(or(X,Y),X) --> cmpne(and(~X,Y),0) // cmpne(or(X,Y),X) --> cmpne(and(~X,Y),0)

View File

@ -9,7 +9,7 @@ if (HAS_WERROR_GLOBAL_CTORS AND NOT LLVM_HAS_NOGLOBAL_CTOR_MUTEX)
endif() endif()
# Solaris code uses kstat, so specify dependency explicitly for shared builds. # Solaris code uses kstat, so specify dependency explicitly for shared builds.
if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS") if ("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS")
set(system_libs kstat) set(system_libs kstat)
endif() endif()

View File

@ -903,6 +903,95 @@ define i1 @mask_v8i32(<8 x i32> %a0) {
ret i1 %3 ret i1 %3
} }
define i1 @mask_v8i32_2(<8 x i32> %a0) {
; SSE2-LABEL: mask_v8i32_2:
; SSE2: # %bb.0:
; SSE2-NEXT: por %xmm1, %xmm0
; SSE2-NEXT: pslld $1, %xmm0
; SSE2-NEXT: movmskps %xmm0, %eax
; SSE2-NEXT: testl %eax, %eax
; SSE2-NEXT: sete %al
; SSE2-NEXT: retq
;
; SSE41-LABEL: mask_v8i32_2:
; SSE41: # %bb.0:
; SSE41-NEXT: por %xmm1, %xmm0
; SSE41-NEXT: ptest {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
; SSE41-NEXT: sete %al
; SSE41-NEXT: retq
;
; AVX1-LABEL: mask_v8i32_2:
; AVX1: # %bb.0:
; AVX1-NEXT: vptest {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0
; AVX1-NEXT: sete %al
; AVX1-NEXT: vzeroupper
; AVX1-NEXT: retq
;
; AVX2-LABEL: mask_v8i32_2:
; AVX2: # %bb.0:
; AVX2-NEXT: vpbroadcastq {{.*#+}} ymm1 = [4611686019501129728,4611686019501129728,4611686019501129728,4611686019501129728]
; AVX2-NEXT: vptest %ymm1, %ymm0
; AVX2-NEXT: sete %al
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
;
; AVX512-LABEL: mask_v8i32_2:
; AVX512: # %bb.0:
; AVX512-NEXT: vpbroadcastq {{.*#+}} ymm1 = [4611686019501129728,4611686019501129728,4611686019501129728,4611686019501129728]
; AVX512-NEXT: vptest %ymm1, %ymm0
; AVX512-NEXT: sete %al
; AVX512-NEXT: vzeroupper
; AVX512-NEXT: retq
%1 = call i32 @llvm.vector.reduce.or.v8i32(<8 x i32> %a0)
%2 = and i32 %1, 1073741824
%3 = icmp eq i32 %2, 0
ret i1 %3
}
define i1 @signtest_v8i32(<8 x i32> %a0) {
; SSE2-LABEL: signtest_v8i32:
; SSE2: # %bb.0:
; SSE2-NEXT: orps %xmm1, %xmm0
; SSE2-NEXT: movmskps %xmm0, %eax
; SSE2-NEXT: testl %eax, %eax
; SSE2-NEXT: sete %al
; SSE2-NEXT: retq
;
; SSE41-LABEL: signtest_v8i32:
; SSE41: # %bb.0:
; SSE41-NEXT: por %xmm1, %xmm0
; SSE41-NEXT: ptest {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
; SSE41-NEXT: sete %al
; SSE41-NEXT: retq
;
; AVX1-LABEL: signtest_v8i32:
; AVX1: # %bb.0:
; AVX1-NEXT: vptest {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0
; AVX1-NEXT: sete %al
; AVX1-NEXT: vzeroupper
; AVX1-NEXT: retq
;
; AVX2-LABEL: signtest_v8i32:
; AVX2: # %bb.0:
; AVX2-NEXT: vpbroadcastq {{.*#+}} ymm1 = [9223372039002259456,9223372039002259456,9223372039002259456,9223372039002259456]
; AVX2-NEXT: vptest %ymm1, %ymm0
; AVX2-NEXT: sete %al
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
;
; AVX512-LABEL: signtest_v8i32:
; AVX512: # %bb.0:
; AVX512-NEXT: vpbroadcastq {{.*#+}} ymm1 = [9223372039002259456,9223372039002259456,9223372039002259456,9223372039002259456]
; AVX512-NEXT: vptest %ymm1, %ymm0
; AVX512-NEXT: sete %al
; AVX512-NEXT: vzeroupper
; AVX512-NEXT: retq
%1 = call i32 @llvm.vector.reduce.or.v8i32(<8 x i32> %a0)
%2 = icmp sgt i32 %1, -1
ret i1 %2
}
define i1 @trunc_v16i16(<16 x i16> %a0) { define i1 @trunc_v16i16(<16 x i16> %a0) {
; SSE2-LABEL: trunc_v16i16: ; SSE2-LABEL: trunc_v16i16:
; SSE2: # %bb.0: ; SSE2: # %bb.0:
@ -1073,11 +1162,11 @@ define i32 @mask_v3i1(<3 x i32> %a, <3 x i32> %b) {
; SSE2-NEXT: movd %xmm0, %eax ; SSE2-NEXT: movd %xmm0, %eax
; SSE2-NEXT: orl %ecx, %eax ; SSE2-NEXT: orl %ecx, %eax
; SSE2-NEXT: testb $1, %al ; SSE2-NEXT: testb $1, %al
; SSE2-NEXT: je .LBB27_2 ; SSE2-NEXT: je .LBB29_2
; SSE2-NEXT: # %bb.1: ; SSE2-NEXT: # %bb.1:
; SSE2-NEXT: xorl %eax, %eax ; SSE2-NEXT: xorl %eax, %eax
; SSE2-NEXT: retq ; SSE2-NEXT: retq
; SSE2-NEXT: .LBB27_2: ; SSE2-NEXT: .LBB29_2:
; SSE2-NEXT: movl $1, %eax ; SSE2-NEXT: movl $1, %eax
; SSE2-NEXT: retq ; SSE2-NEXT: retq
; ;
@ -1092,11 +1181,11 @@ define i32 @mask_v3i1(<3 x i32> %a, <3 x i32> %b) {
; SSE41-NEXT: pextrd $2, %xmm1, %eax ; SSE41-NEXT: pextrd $2, %xmm1, %eax
; SSE41-NEXT: orl %ecx, %eax ; SSE41-NEXT: orl %ecx, %eax
; SSE41-NEXT: testb $1, %al ; SSE41-NEXT: testb $1, %al
; SSE41-NEXT: je .LBB27_2 ; SSE41-NEXT: je .LBB29_2
; SSE41-NEXT: # %bb.1: ; SSE41-NEXT: # %bb.1:
; SSE41-NEXT: xorl %eax, %eax ; SSE41-NEXT: xorl %eax, %eax
; SSE41-NEXT: retq ; SSE41-NEXT: retq
; SSE41-NEXT: .LBB27_2: ; SSE41-NEXT: .LBB29_2:
; SSE41-NEXT: movl $1, %eax ; SSE41-NEXT: movl $1, %eax
; SSE41-NEXT: retq ; SSE41-NEXT: retq
; ;
@ -1111,11 +1200,11 @@ define i32 @mask_v3i1(<3 x i32> %a, <3 x i32> %b) {
; AVX1OR2-NEXT: vpextrd $2, %xmm0, %eax ; AVX1OR2-NEXT: vpextrd $2, %xmm0, %eax
; AVX1OR2-NEXT: orl %ecx, %eax ; AVX1OR2-NEXT: orl %ecx, %eax
; AVX1OR2-NEXT: testb $1, %al ; AVX1OR2-NEXT: testb $1, %al
; AVX1OR2-NEXT: je .LBB27_2 ; AVX1OR2-NEXT: je .LBB29_2
; AVX1OR2-NEXT: # %bb.1: ; AVX1OR2-NEXT: # %bb.1:
; AVX1OR2-NEXT: xorl %eax, %eax ; AVX1OR2-NEXT: xorl %eax, %eax
; AVX1OR2-NEXT: retq ; AVX1OR2-NEXT: retq
; AVX1OR2-NEXT: .LBB27_2: ; AVX1OR2-NEXT: .LBB29_2:
; AVX1OR2-NEXT: movl $1, %eax ; AVX1OR2-NEXT: movl $1, %eax
; AVX1OR2-NEXT: retq ; AVX1OR2-NEXT: retq
; ;
@ -1130,12 +1219,12 @@ define i32 @mask_v3i1(<3 x i32> %a, <3 x i32> %b) {
; AVX512F-NEXT: korw %k0, %k1, %k0 ; AVX512F-NEXT: korw %k0, %k1, %k0
; AVX512F-NEXT: kmovw %k0, %eax ; AVX512F-NEXT: kmovw %k0, %eax
; AVX512F-NEXT: testb $1, %al ; AVX512F-NEXT: testb $1, %al
; AVX512F-NEXT: je .LBB27_2 ; AVX512F-NEXT: je .LBB29_2
; AVX512F-NEXT: # %bb.1: ; AVX512F-NEXT: # %bb.1:
; AVX512F-NEXT: xorl %eax, %eax ; AVX512F-NEXT: xorl %eax, %eax
; AVX512F-NEXT: vzeroupper ; AVX512F-NEXT: vzeroupper
; AVX512F-NEXT: retq ; AVX512F-NEXT: retq
; AVX512F-NEXT: .LBB27_2: ; AVX512F-NEXT: .LBB29_2:
; AVX512F-NEXT: movl $1, %eax ; AVX512F-NEXT: movl $1, %eax
; AVX512F-NEXT: vzeroupper ; AVX512F-NEXT: vzeroupper
; AVX512F-NEXT: retq ; AVX512F-NEXT: retq
@ -1151,12 +1240,12 @@ define i32 @mask_v3i1(<3 x i32> %a, <3 x i32> %b) {
; AVX512BW-NEXT: korw %k0, %k1, %k0 ; AVX512BW-NEXT: korw %k0, %k1, %k0
; AVX512BW-NEXT: kmovd %k0, %eax ; AVX512BW-NEXT: kmovd %k0, %eax
; AVX512BW-NEXT: testb $1, %al ; AVX512BW-NEXT: testb $1, %al
; AVX512BW-NEXT: je .LBB27_2 ; AVX512BW-NEXT: je .LBB29_2
; AVX512BW-NEXT: # %bb.1: ; AVX512BW-NEXT: # %bb.1:
; AVX512BW-NEXT: xorl %eax, %eax ; AVX512BW-NEXT: xorl %eax, %eax
; AVX512BW-NEXT: vzeroupper ; AVX512BW-NEXT: vzeroupper
; AVX512BW-NEXT: retq ; AVX512BW-NEXT: retq
; AVX512BW-NEXT: .LBB27_2: ; AVX512BW-NEXT: .LBB29_2:
; AVX512BW-NEXT: movl $1, %eax ; AVX512BW-NEXT: movl $1, %eax
; AVX512BW-NEXT: vzeroupper ; AVX512BW-NEXT: vzeroupper
; AVX512BW-NEXT: retq ; AVX512BW-NEXT: retq
@ -1170,11 +1259,11 @@ define i32 @mask_v3i1(<3 x i32> %a, <3 x i32> %b) {
; AVX512BWVL-NEXT: korw %k0, %k1, %k0 ; AVX512BWVL-NEXT: korw %k0, %k1, %k0
; AVX512BWVL-NEXT: kmovd %k0, %eax ; AVX512BWVL-NEXT: kmovd %k0, %eax
; AVX512BWVL-NEXT: testb $1, %al ; AVX512BWVL-NEXT: testb $1, %al
; AVX512BWVL-NEXT: je .LBB27_2 ; AVX512BWVL-NEXT: je .LBB29_2
; AVX512BWVL-NEXT: # %bb.1: ; AVX512BWVL-NEXT: # %bb.1:
; AVX512BWVL-NEXT: xorl %eax, %eax ; AVX512BWVL-NEXT: xorl %eax, %eax
; AVX512BWVL-NEXT: retq ; AVX512BWVL-NEXT: retq
; AVX512BWVL-NEXT: .LBB27_2: ; AVX512BWVL-NEXT: .LBB29_2:
; AVX512BWVL-NEXT: movl $1, %eax ; AVX512BWVL-NEXT: movl $1, %eax
; AVX512BWVL-NEXT: retq ; AVX512BWVL-NEXT: retq
%1 = icmp ne <3 x i32> %a, %b %1 = icmp ne <3 x i32> %a, %b

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