@@ -791,6 +791,16 @@ template <typename T> using bind_param_t = typename bind_param<T>::type;
791
791
class KernelObjVisitor {
792
792
Sema &SemaRef;
793
793
794
+ template <typename ParentTy, typename ... Handlers>
795
+ void VisitUnionImpl (const CXXRecordDecl *Owner, ParentTy &Parent,
796
+ const CXXRecordDecl *Wrapper, Handlers &... handlers) {
797
+ (void )std::initializer_list<int >{
798
+ (handlers.enterUnion (Owner, Parent), 0 )...};
799
+ VisitRecordHelper (Wrapper, Wrapper->fields (), handlers...);
800
+ (void )std::initializer_list<int >{
801
+ (handlers.leaveUnion (Owner, Parent), 0 )...};
802
+ }
803
+
794
804
public:
795
805
KernelObjVisitor (Sema &S) : SemaRef(S) {}
796
806
@@ -867,65 +877,9 @@ class KernelObjVisitor {
867
877
template <typename ParentTy, typename ... Handlers>
868
878
void VisitRecord (const CXXRecordDecl *Owner, ParentTy &Parent,
869
879
const CXXRecordDecl *Wrapper, Handlers &... handlers);
870
-
871
- // Base case, only calls these when filtered.
872
- template <typename ... FilteredHandlers, typename ParentTy>
873
- std::enable_if_t <(sizeof ...(FilteredHandlers) > 0 )>
874
- VisitUnion (FilteredHandlers &... handlers, const CXXRecordDecl *Owner,
875
- ParentTy &Parent, const CXXRecordDecl *Wrapper) {
876
- (void )std::initializer_list<int >{
877
- (handlers.enterUnion (Owner, Parent), 0 )...};
878
- VisitRecordHelper (Wrapper, Wrapper->fields (), handlers...);
879
- (void )std::initializer_list<int >{
880
- (handlers.leaveUnion (Owner, Parent), 0 )...};
881
- }
882
-
883
- // Handle empty base case.
884
- template <typename ParentTy>
880
+ template <typename ParentTy, typename ... Handlers>
885
881
void VisitUnion (const CXXRecordDecl *Owner, ParentTy &Parent,
886
- const CXXRecordDecl *Wrapper) {}
887
-
888
- template <typename ... FilteredHandlers, typename ParentTy,
889
- typename CurHandler, typename ... Handlers>
890
- std::enable_if_t <!CurHandler::VisitUnionBody &&
891
- (sizeof ...(FilteredHandlers) > 0 )>
892
- VisitUnion (FilteredHandlers &... filtered_handlers,
893
- const CXXRecordDecl *Owner, ParentTy &Parent,
894
- const CXXRecordDecl *Wrapper, CurHandler &cur_handler,
895
- Handlers &... handlers) {
896
- VisitUnion<FilteredHandlers...>(filtered_handlers..., Owner, Parent,
897
- Wrapper, handlers...);
898
- }
899
-
900
- template <typename ... FilteredHandlers, typename ParentTy,
901
- typename CurHandler, typename ... Handlers>
902
- std::enable_if_t <CurHandler::VisitUnionBody &&
903
- (sizeof ...(FilteredHandlers) > 0 )>
904
- VisitUnion (FilteredHandlers &... filtered_handlers,
905
- const CXXRecordDecl *Owner, ParentTy &Parent,
906
- const CXXRecordDecl *Wrapper, CurHandler &cur_handler,
907
- Handlers &... handlers) {
908
- VisitUnion<FilteredHandlers..., CurHandler>(
909
- filtered_handlers..., cur_handler, Owner, Parent, Wrapper, handlers...);
910
- }
911
-
912
- // Add overloads without having filtered-handlers
913
- // to handle leading-empty argument packs.
914
- template <typename ParentTy, typename CurHandler, typename ... Handlers>
915
- std::enable_if_t <!CurHandler::VisitUnionBody>
916
- VisitUnion (const CXXRecordDecl *Owner, ParentTy &Parent,
917
- const CXXRecordDecl *Wrapper, CurHandler &cur_handler,
918
- Handlers &... handlers) {
919
- VisitUnion (Owner, Parent, Wrapper, handlers...);
920
- }
921
-
922
- template <typename ParentTy, typename CurHandler, typename ... Handlers>
923
- std::enable_if_t <CurHandler::VisitUnionBody>
924
- VisitUnion (const CXXRecordDecl *Owner, ParentTy &Parent,
925
- const CXXRecordDecl *Wrapper, CurHandler &cur_handler,
926
- Handlers &... handlers) {
927
- VisitUnion<CurHandler>(cur_handler, Owner, Parent, Wrapper, handlers...);
928
- }
882
+ const CXXRecordDecl *Wrapper, Handlers &... handlers);
929
883
930
884
template <typename ... Handlers>
931
885
void VisitRecordHelper (const CXXRecordDecl *Owner,
@@ -1050,11 +1004,7 @@ void KernelObjVisitor::VisitRecord(const CXXRecordDecl *Owner, ParentTy &Parent,
1050
1004
1051
1005
// A base type that the SYCL OpenCL Kernel construction task uses to implement
1052
1006
// individual tasks.
1053
- class SyclKernelFieldHandler {
1054
- protected:
1055
- Sema &SemaRef;
1056
- SyclKernelFieldHandler (Sema &S) : SemaRef(S) {}
1057
-
1007
+ class SyclKernelFieldHandlerBase {
1058
1008
public:
1059
1009
static constexpr const bool VisitUnionBody = false ;
1060
1010
// Mark these virtual so that we can use override in the implementer classes,
@@ -1118,9 +1068,53 @@ class SyclKernelFieldHandler {
1118
1068
virtual bool nextElement (QualType) { return true ; }
1119
1069
virtual bool leaveArray (FieldDecl *, QualType, int64_t ) { return true ; }
1120
1070
1121
- virtual ~SyclKernelFieldHandler () = default ;
1071
+ virtual ~SyclKernelFieldHandlerBase () = default ;
1072
+ };
1073
+
1074
+ // A class to act as the direct base for all the SYCL OpenCL Kernel construction
1075
+ // tasks that contains a reference to Sema (and potentially any other
1076
+ // universally required data).
1077
+ class SyclKernelFieldHandler : public SyclKernelFieldHandlerBase {
1078
+ protected:
1079
+ Sema &SemaRef;
1080
+ SyclKernelFieldHandler (Sema &S) : SemaRef(S) {}
1122
1081
};
1123
1082
1083
+ // A class to represent the 'do nothing' case for filtering purposes.
1084
+ class SyclEmptyHandler final : public SyclKernelFieldHandlerBase {};
1085
+ SyclEmptyHandler GlobalEmptyHandler;
1086
+
1087
+ template <bool Keep, typename H> struct HandlerFilter ;
1088
+ template <typename H> struct HandlerFilter <true , H> {
1089
+ H &Handler;
1090
+ HandlerFilter (H &Handler) : Handler(Handler) {}
1091
+ };
1092
+ template <typename H> struct HandlerFilter <false , H> {
1093
+ SyclEmptyHandler &Handler = GlobalEmptyHandler;
1094
+ HandlerFilter (H &Handler) {}
1095
+ };
1096
+
1097
+ template <bool B, bool ... Rest> struct AnyTrue ;
1098
+
1099
+ template <bool B> struct AnyTrue <B> { static constexpr bool Value = B; };
1100
+
1101
+ template <bool B, bool ... Rest> struct AnyTrue {
1102
+ static constexpr bool Value = B || AnyTrue<Rest...>::Value;
1103
+ };
1104
+
1105
+ template <typename ParentTy, typename ... Handlers>
1106
+ void KernelObjVisitor::VisitUnion (const CXXRecordDecl *Owner, ParentTy &Parent,
1107
+ const CXXRecordDecl *Wrapper,
1108
+ Handlers &... handlers) {
1109
+ // Don't continue descending if none of the handlers 'care'. This could be 'if
1110
+ // constexpr' starting in C++17. Until then, we have to count on the
1111
+ // optimizer to realize "if (false)" is a dead branch.
1112
+ if (AnyTrue<Handlers::VisitUnionBody...>::Value)
1113
+ VisitUnionImpl (
1114
+ Owner, Parent, Wrapper,
1115
+ HandlerFilter<Handlers::VisitUnionBody, Handlers>(handlers).Handler ...);
1116
+ }
1117
+
1124
1118
// A type to check the validity of all of the argument types.
1125
1119
class SyclKernelFieldChecker : public SyclKernelFieldHandler {
1126
1120
bool IsInvalid = false ;
0 commit comments