update comments
Created using spr 1.3.6
This commit is contained in:
commit
fd9ca0bab8
@ -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()
|
||||||
|
@ -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) {
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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,
|
||||||
|
@ -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.
|
||||||
|
@ -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())); })
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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() }];
|
||||||
|
@ -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 &&
|
||||||
|
@ -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()};
|
||||||
}
|
}
|
||||||
|
@ -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 = [
|
||||||
|
@ -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 = [{
|
||||||
|
@ -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>]>;
|
||||||
|
@ -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
|
||||||
|
@ -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<
|
||||||
|
@ -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>;
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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());
|
||||||
|
@ -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);
|
||||||
|
@ -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>();
|
||||||
|
@ -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) {
|
||||||
|
@ -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';
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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) {
|
||||||
|
@ -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());
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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().
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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)) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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 %
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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 %
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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]]
|
||||||
|
@ -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}
|
||||||
//.
|
//.
|
||||||
|
@ -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; }
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
85
clang/test/CodeGenSYCL/sycl-external-attr.cpp
Normal file
85
clang/test/CodeGenSYCL/sycl-external-attr.cpp
Normal 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;
|
||||||
|
}
|
@ -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]])
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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 {};
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
20
clang/test/PCH/dedup_types.cpp
Normal file
20
clang/test/PCH/dedup_types.cpp
Normal 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>>{};
|
||||||
|
}
|
@ -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 {
|
||||||
|
36
clang/test/SemaSYCL/sycl-external-attr-appertainment.cpp
Normal file
36
clang/test/SemaSYCL/sycl-external-attr-appertainment.cpp
Normal 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
|
14
clang/test/SemaSYCL/sycl-external-attr-grammar.cpp
Normal file
14
clang/test/SemaSYCL/sycl-external-attr-grammar.cpp
Normal 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();
|
15
clang/test/SemaSYCL/sycl-external-attr-ignored.cpp
Normal file
15
clang/test/SemaSYCL/sycl-external-attr-ignored.cpp
Normal 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);
|
154
clang/test/SemaSYCL/sycl-external-attr.cpp
Normal file
154
clang/test/SemaSYCL/sycl-external-attr.cpp
Normal 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
|
226
clang/test/SemaTemplate/dedup-types-builtin.cpp
Normal file
226
clang/test/SemaTemplate/dedup-types-builtin.cpp
Normal 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}}
|
||||||
|
|
@ -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)
|
||||||
|
@ -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.
|
||||||
|
@ -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++.
|
||||||
|
@ -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"))),
|
||||||
|
@ -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) {
|
||||||
|
@ -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()
|
||||||
|
@ -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})
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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}")
|
||||||
|
@ -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()
|
||||||
|
@ -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);
|
||||||
|
@ -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>,
|
||||||
|
@ -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);
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user