clang: lib/Sema/SemaCUDA.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
25#include "llvm/ADT/SmallVector.h"
26#include
27using namespace clang;
28
30
32 if (!D)
33 return false;
34 if (auto *A = D->getAttr())
35 return !A->isImplicit();
36 return false;
37}
38
40 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
41 ForceHostDeviceDepth++;
42}
43
45 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
46 if (ForceHostDeviceDepth == 0)
47 return false;
48 ForceHostDeviceDepth--;
49 return true;
50}
51
55 bool IsDeviceKernelCall = false;
59 IsDeviceKernelCall = true;
60 break;
63 IsDeviceKernelCall = true;
65 SemaRef.getCurFunctionDecl(true);
67
68
69
70 if (().GPURelocatableDeviceCode)
71 IsDeviceKernelCall = false;
72
73
75 IsDeviceKernelCall = false;
76 }
77 }
78 break;
79 default:
80 break;
81 }
82
85 Diag(LLLLoc, diag::err_cuda_device_kernel_launch_not_supported));
86
87 if (IsDeviceKernelCall && ().GPURelocatableDeviceCode)
89 Diag(LLLLoc, diag::err_cuda_device_kernel_launch_require_rdc));
90
94 if (!ConfigDecl)
95 return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)
98
99 if (IsDeviceKernelCall) {
101 if (!GetParamBuf)
102 return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)
104 }
105
107
110 SemaRef.MarkFunctionReferenced(LLLLoc, ConfigDecl);
111
112 if (IsDeviceKernelCall) {
114
115
116
117 llvm::APInt Zero(SemaRef.Context.getTypeSize(SemaRef.Context.IntTy), 0);
119 SemaRef.Context.IntTy, LLLLoc));
120
121
123 SemaRef.Context.IntTy, LLLLoc));
124
125 llvm::append_range(Args, ExecConfig);
126
127 if (Args.size() < 4) {
128 llvm::APInt One(SemaRef.Context.getTypeSize(SemaRef.Context.IntTy), 1);
130 SemaRef.Context.IntTy, LLLLoc));
131 }
132
133 if (Args.size() < 5)
135 SemaRef.Context.IntTy, LLLLoc));
136
137 if (Args.size() < 6)
139 SemaRef.Context.NullPtrTy, LLLLoc));
140 return SemaRef.BuildCallExpr(S, ConfigDR, LLLLoc, Args, GGGLoc, nullptr,
141 true);
142 }
143 return SemaRef.BuildCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr,
144 true);
145}
146
148 bool HasHostAttr = false;
149 bool HasDeviceAttr = false;
150 bool HasGlobalAttr = false;
151 bool HasInvalidTargetAttr = false;
153 switch (AL.getKind()) {
154 case ParsedAttr::AT_CUDAGlobal:
155 HasGlobalAttr = true;
156 break;
157 case ParsedAttr::AT_CUDAHost:
158 HasHostAttr = true;
159 break;
160 case ParsedAttr::AT_CUDADevice:
161 HasDeviceAttr = true;
162 break;
163 case ParsedAttr::AT_CUDAInvalidTarget:
164 HasInvalidTargetAttr = true;
165 break;
166 default:
167 break;
168 }
169 }
170
171 if (HasInvalidTargetAttr)
173
174 if (HasGlobalAttr)
176
177 if (HasHostAttr && HasDeviceAttr)
179
180 if (HasDeviceAttr)
182
184}
185
186template
187static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr) {
189 return isa(Attribute) &&
190 !(IgnoreImplicitAttr && Attribute->isImplicit());
191 });
192}
193
196 : S(S_) {
199 auto *VD = dyn_cast_or_null(D);
200 if (VD && VD->hasGlobalStorage() && !VD->isStaticLocal()) {
207 S.CurCUDATargetCtx = {Target, K, VD};
208 }
209}
210
211
213 bool IgnoreImplicitHDAttr) {
214
215 if (D == nullptr)
217
218
219
220
223
224 if (D->hasAttr())
226
227 if (D->hasAttr())
229
232
240 !IgnoreImplicitHDAttr) {
241
242
244 }
245
247}
248
249
251 if (Var->hasAttr())
253
254
255
257 Var->hasAttr() &&
260 if (Var->hasAttr() || Var->hasAttr() ||
261 Var->hasAttr() ||
265
266
267
268
269 if (auto *FD = dyn_cast(Var->getDeclContext())) {
276 default:
278 }
279 }
281}
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
314 assert(Callee && "Callee must be valid.");
315
316
317
318
323
326
327
328
332
333
334
339
340
343
344
345 if (CalleeTarget == CallerTarget ||
351
352
353
354
361
362
364
372
373
374
375
376
378 }
379
380
388
389 llvm_unreachable("All cases should've been handled by now.");
390}
391
393 if (!D)
394 return false;
395 if (auto *A = D->getAttr())
396 return A->isImplicit();
398}
399
403 return IsImplicitDevAttr && IsImplicitHostAttr;
404}
405
408 SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) {
409 if (Matches.size() <= 1)
410 return;
411
412 using Pair = std::pair<DeclAccessPair, FunctionDecl *>;
413
414
415 auto GetCFP = [&](const Pair &Match) {
417 };
418
419
421 GetCFP(*llvm::max_element(Matches, [&](const Pair &M1, const Pair &M2) {
422 return GetCFP(M1) < GetCFP(M2);
423 }));
424
425
426 llvm::erase_if(Matches,
427 [&](const Pair &Match) { return GetCFP(Match) < BestCFP; });
428}
429
430
431
432
433
434
435
436
437
438static bool
442
445
447 *ResolvedTarget = Target2;
449 *ResolvedTarget = Target1;
450 } else if (Target1 != Target2) {
451 return true;
452 } else {
453 *ResolvedTarget = Target1;
454 }
455
456 return false;
457}
458
462 bool ConstRHS,
463 bool Diagnose) {
464
465
466
467
468 bool IsExpVDtor = false;
470 if (auto *Spec = dyn_cast(ClassDecl)) {
474 }
475 }
476 if (IsExpVDtor)
477 SemaRef.DeclsToCheckForDeferredDiags.insert(MemberDecl);
478
479
480
481
483 bool HasH = MemberDecl->hasAttr();
484 bool HasD = MemberDecl->hasAttr();
485 bool HasExplicitAttr =
486 (HasD && !MemberDecl->getAttr()->isImplicit()) ||
487 (HasH && !MemberDecl->getAttr()->isImplicit());
488 if (!InClass || HasExplicitAttr)
489 return false;
490
491 std::optional InferredTarget;
492
493
494
496
497
498
499
501 for (const auto &B : ClassDecl->bases()) {
502 if (!B.isVirtual()) {
503 Bases.push_back(&B);
504 }
505 }
506
508 llvm::append_range(Bases, llvm::make_pointer_range(ClassDecl->vbases()));
509 }
510
511 for (const auto *B : Bases) {
512 auto *BaseClassDecl = B->getType()->getAsCXXRecordDecl();
513 if (!BaseClassDecl)
514 continue;
515
517 SemaRef.LookupSpecialMember(BaseClassDecl, CSM,
518 ConstRHS,
519 false,
520 false,
521 false,
522 false);
523
525 continue;
526
529
530 if (!InferredTarget) {
531 InferredTarget = BaseMethodTarget;
532 } else {
534 *InferredTarget, BaseMethodTarget, &*InferredTarget);
535 if (ResolutionError) {
536 if (Diagnose) {
538 diag::note_implicit_member_target_infer_collision)
539 << (unsigned)CSM << *InferredTarget << BaseMethodTarget;
540 }
542 CUDAInvalidTargetAttr::CreateImplicit(getASTContext()));
543 return true;
544 }
545 }
546 }
547
548
549 for (const auto *F : ClassDecl->fields()) {
550 if (F->isInvalidDecl()) {
551 continue;
552 }
553
554 auto *FieldRecDecl =
556 if (!FieldRecDecl)
557 continue;
558
560 SemaRef.LookupSpecialMember(FieldRecDecl, CSM,
561 ConstRHS && !F->isMutable(),
562 false,
563 false,
564 false,
565 false);
566
568 continue;
569
572
573 if (!InferredTarget) {
574 InferredTarget = FieldMethodTarget;
575 } else {
577 *InferredTarget, FieldMethodTarget, &*InferredTarget);
578 if (ResolutionError) {
579 if (Diagnose) {
581 diag::note_implicit_member_target_infer_collision)
582 << (unsigned)CSM << *InferredTarget << FieldMethodTarget;
583 }
585 CUDAInvalidTargetAttr::CreateImplicit(getASTContext()));
586 return true;
587 }
588 }
589 }
590
591
592
593 bool NeedsH = true, NeedsD = true;
594 if (InferredTarget) {
596 NeedsH = false;
598 NeedsD = false;
599 }
600
601
602
603 if (NeedsD && !HasD)
605 if (NeedsH && !HasH)
607
608 return false;
609}
610
614
615
616
617
619 return true;
620
621
622
623
624
626 return false;
627
628
630 return false;
631
632
634 return true;
635
636
637
639 if (const CXXConstructExpr *CE =
640 dyn_cast(CI->getInit()))
641 return isEmptyConstructor(Loc, CE->getConstructor());
642 return false;
643 }))
644 return false;
645
646 return true;
647}
648
650
651 if (!DD)
652 return true;
653
656
657
658
659
661 return true;
662
663
664
665
667 return false;
668
670
671
673 return false;
674
675
676
678 return true;
679
680
681
683 if (CXXRecordDecl *RD = BS.getType()->getAsCXXRecordDecl())
684 return isEmptyDestructor(Loc, RD->getDestructor());
685 return true;
686 }))
687 return false;
688
689
690 if (!llvm::all_of(ClassDecl->fields(), [&](const FieldDecl *Field) {
691 if (CXXRecordDecl *RD = Field->getType()
692 ->getBaseElementTypeUnsafe()
693 ->getAsCXXRecordDecl())
694 return isEmptyDestructor(Loc, RD->getDestructor());
695 return true;
696 }))
697 return false;
698
699 return true;
700}
701
702namespace {
703enum CUDAInitializerCheckKind {
704 CICK_DeviceOrConstant,
705 CICK_Shared,
706};
707
708bool IsDependentVar(VarDecl *VD) {
710 return true;
712 return Init->isValueDependent();
713 return false;
714}
715
716
717
718
719
720
721
722
723
724
725bool HasAllowedCUDADeviceStaticInitializer(SemaCUDA &S, VarDecl *VD,
726 CUDAInitializerCheckKind CheckKind) {
728 assert(!IsDependentVar(VD) && "do not check dependent var");
730 auto IsEmptyInit = [&](const Expr *Init) {
732 return true;
733 if (const auto *CE = dyn_cast(Init)) {
735 }
736 return false;
737 };
738 auto IsConstantInit = [&](const Expr *Init) {
739 assert(Init);
740 ASTContext::CUDAConstantEvalContextRAII EvalCtx(S.getASTContext(),
741 true);
744 };
745 auto HasEmptyDtor = [&](VarDecl *VD) {
748 return true;
749 };
750 if (CheckKind == CICK_Shared)
751 return IsEmptyInit(Init) && HasEmptyDtor(VD);
752 return S.getLangOpts().GPUAllowDeviceInit ||
753 ((IsEmptyInit(Init) || IsConstantInit(Init)) && HasEmptyDtor(VD));
754}
755}
756
758
759
761 dyn_cast_or_null(VD->getDeclContext());
763 return;
764
765 bool IsSharedVar = VD->hasAttr();
766 bool IsDeviceOrConstantVar =
767 !IsSharedVar &&
768 (VD->hasAttr() || VD->hasAttr());
769 if ((IsSharedVar || IsDeviceOrConstantVar) &&
771 Diag(VD->getLocation(), diag::err_cuda_address_space_gpuvar);
773 return;
774 }
775
776
778 IsDependentVar(VD))
779 return;
781 if (IsDeviceOrConstantVar || IsSharedVar) {
782 if (HasAllowedCUDADeviceStaticInitializer(
783 *this, VD, IsSharedVar ? CICK_Shared : CICK_DeviceOrConstant))
784 return;
786 IsSharedVar ? diag::err_shared_var_init : diag::err_dynamic_var_init)
787 << Init->getSourceRange();
789 } else {
790
791
794 InitFn = CE->getConstructor();
795 } else if (const CallExpr *CE = dyn_cast(Init)) {
796 InitFn = CE->getDirectCallee();
797 }
798 if (InitFn) {
802 Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer)
803 << InitFnTarget << InitFn;
804 Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn;
806 }
807 }
808 }
809}
810
814 if (!Caller)
815 return;
816
818 return;
819
821
822
827 ().CUDAImplicitHostDeviceFunUsedByDevice.count(Caller))))
828 return;
829
831}
832
833
834
835
836
837
838
839
840
841
842
843
844
847 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
848
849 if (ForceHostDeviceDepth > 0) {
850 if (!NewD->hasAttr())
852 if (!NewD->hasAttr())
854 return;
855 }
856
857
858
859 if (getLangOpts().OffloadImplicitHostDeviceTemplates &&
860 !NewD->hasAttr() && !NewD->hasAttr() &&
861 !NewD->hasAttr() &&
866 return;
867 }
868
871 NewD->hasAttr() || NewD->hasAttr())
872 return;
873
874
875
876 auto IsMatchingDeviceFn = [&](NamedDecl *D) {
877 if (UsingShadowDecl *Using = dyn_cast(D))
878 D = Using->getTargetDecl();
880 return OldD && OldD->hasAttr() &&
881 !OldD->hasAttr() &&
882 .IsOverload(NewD, OldD,
883 false,
884 false);
885 };
886 auto It = llvm::find_if(Previous, IsMatchingDeviceFn);
888
889
890
891
893 if (.getSourceManager().isInSystemHeader(Match->getLocation())) {
895 diag::err_cuda_unattributed_constexpr_cannot_overload_device)
896 << NewD;
898 diag::note_cuda_conflicting_device_function_declared_here);
899 }
900 return;
901 }
902
905}
906
907
908
909
911
912
913 if (getLangOpts().CUDAIsDevice && !VD->hasAttr() &&
914 !VD->hasAttr() &&
916 !IsDependentVar(VD) &&
918 HasAllowedCUDADeviceStaticInitializer(*this, VD,
919 CICK_DeviceOrConstant))) {
921 }
922}
923
925 unsigned DiagID) {
926 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
928 SemaRef.getCurFunctionDecl(true);
929 SemaDiagnosticBuilder::Kind DiagKind = [&] {
930 if (!CurFunContext)
931 return SemaDiagnosticBuilder::K_Nop;
935 return SemaDiagnosticBuilder::K_Immediate;
937
938
939
941 return SemaDiagnosticBuilder::K_Nop;
942 if (SemaRef.IsLastErrorImmediate &&
944 return SemaDiagnosticBuilder::K_Immediate;
945 return (SemaRef.getEmissionStatus(CurFunContext) ==
947 ? SemaDiagnosticBuilder::K_ImmediateWithCallStack
948 : SemaDiagnosticBuilder::K_Deferred;
949 default:
950 return SemaDiagnosticBuilder::K_Nop;
951 }
952 }();
954}
955
957 unsigned DiagID) {
958 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
960 SemaRef.getCurFunctionDecl(true);
961 SemaDiagnosticBuilder::Kind DiagKind = [&] {
962 if (!CurFunContext)
963 return SemaDiagnosticBuilder::K_Nop;
966 return SemaDiagnosticBuilder::K_Immediate;
968
969
970
972 return SemaDiagnosticBuilder::K_Nop;
973 if (SemaRef.IsLastErrorImmediate &&
975 return SemaDiagnosticBuilder::K_Immediate;
976 return (SemaRef.getEmissionStatus(CurFunContext) ==
978 ? SemaDiagnosticBuilder::K_ImmediateWithCallStack
979 : SemaDiagnosticBuilder::K_Deferred;
980 default:
981 return SemaDiagnosticBuilder::K_Nop;
982 }
983 }();
985}
986
988 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
989 assert(Callee && "Callee may not be null.");
990
991 const auto &ExprEvalCtx = SemaRef.currentEvaluationContext();
992 if (ExprEvalCtx.isUnevaluated() || ExprEvalCtx.isConstantEvaluated())
993 return true;
994
995
996
997
999 return true;
1000
1001
1002
1003 FunctionDecl *Caller = SemaRef.getCurFunctionDecl(true);
1004 if (!Caller)
1005 return true;
1006
1007
1008
1009 bool CallerKnownEmitted = SemaRef.getEmissionStatus(Caller) ==
1011 SemaDiagnosticBuilder::Kind DiagKind = [this, Caller, Callee,
1012 CallerKnownEmitted] {
1016 assert(Caller && "Never/wrongSide calls require a non-null caller");
1017
1018
1019
1020 return CallerKnownEmitted
1021 ? SemaDiagnosticBuilder::K_ImmediateWithCallStack
1022 : SemaDiagnosticBuilder::K_Deferred;
1023 default:
1024 return SemaDiagnosticBuilder::K_Nop;
1025 }
1026 }();
1027
1028 if (DiagKind == SemaDiagnosticBuilder::K_Nop) {
1029
1031 Callee->hasAttr() && !Callee->isDefined() &&
1033 getASTContext().GetGVALinkageForFunction(Caller) ==
1036 return true;
1037 }
1038
1039
1040
1041
1042
1044 return true;
1045
1048 << IdentifyTarget(Callee) << 0 << Callee
1050 if (!Callee->getBuiltinID())
1052 diag::note_previous_decl, Caller, SemaRef)
1053 << Callee;
1054 return DiagKind != SemaDiagnosticBuilder::K_Immediate &&
1055 DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack;
1056}
1057
1058
1059
1060
1061
1062
1065
1066
1067
1068
1069
1070
1071
1072
1074 return;
1075
1076
1077
1078 FunctionDecl *Caller = SemaRef.getCurFunctionDecl(true);
1079 if (!Caller)
1080 return;
1081
1082
1083
1084
1085
1086 bool CalleeIsDevice = Callee->hasAttr();
1087 bool CallerIsHost =
1088 !Caller->hasAttr() && !Caller->hasAttr();
1089 bool ShouldCheck = CalleeIsDevice && CallerIsHost;
1091 return;
1092 auto DiagKind = SemaDiagnosticBuilder::K_Deferred;
1095 diag::err_capture_bad_target, Callee, SemaRef)
1098
1099
1100
1101
1103 diag::warn_maybe_capture_bad_target_this_ptr, Callee,
1105 }
1106}
1107
1109 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
1110 if (Method->hasAttr() || Method->hasAttr())
1111 return;
1114}
1115
1118 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
1122 if (!OldFD)
1123 continue;
1124
1126
1127
1128
1129
1130
1131 if (NewTarget != OldTarget &&
1132 .IsOverload(NewFD, OldFD, false,
1133 false)) {
1135 !(getLangOpts().OffloadImplicitHostDeviceTemplates &&
1139 !(getLangOpts().OffloadImplicitHostDeviceTemplates &&
1145 << NewTarget << NewFD->getDeclName() << OldTarget << OldFD;
1146 Diag(OldFD->getLocation(), diag::note_previous_declaration);
1148 break;
1149 }
1154 Diag(NewFD->getLocation(), diag::warn_offload_incompatible_redeclare)
1155 << NewTarget << OldTarget;
1156 Diag(OldFD->getLocation(), diag::note_previous_declaration);
1157 }
1158 }
1159 }
1160}
1161
1162template
1165 if (AttrTy *Attribute = TemplateFD.getAttr()) {
1166 AttrTy *Clone = Attribute->clone(S.Context);
1167 Clone->setInherited(true);
1169 }
1170}
1171
1179
1182 return "__llvmPushCallConfiguration";
1183
1185 return getLangOpts().HIPUseNewLaunchAPI ? "__hipPushCallConfiguration"
1186 : "hipConfigureCall";
1187
1188
1191 return "__cudaPushCallConfiguration";
1192
1193
1194 return "cudaConfigureCall";
1195}
1196
1198 return "cudaGetParameterBuffer";
1199}
1200
1202 return "cudaLaunchDevice";
1203}
1204
1205
1206
1210 if (!LambdaInfo)
1211 return;
1212
1213 for (unsigned I = 0; I < Arguments.size(); ++I) {
1214 auto *DeclRef = dyn_cast(Arguments[I]);
1215 if (!DeclRef)
1216 continue;
1217 auto *Variable = dyn_cast(DeclRef->getDecl());
1218 if (!Variable || !Variable->isLocalVarDecl() || !Variable->isConstexpr())
1219 continue;
1220
1221 bool HostByValue = false, HostByRef = false;
1222 bool DeviceByValue = false, DeviceByRef = false;
1223
1226 if (!Callee || I >= Callee->getNumParams())
1227 continue;
1228
1232 continue;
1233
1238
1239 bool IsRef = Callee->getParamDecl(I)->getType()->isReferenceType();
1240 HostByValue |= CoversHost && !IsRef;
1241 HostByRef |= CoversHost && IsRef;
1242 DeviceByValue |= CoversDevice && !IsRef;
1243 DeviceByRef |= CoversDevice && IsRef;
1244 }
1245
1246 if ((HostByValue && DeviceByRef) || (HostByRef && DeviceByValue))
1248 }
1249}
Defines the clang::ASTContext interface.
static bool hasImplicitAttr(const ValueDecl *D)
Defines the clang::Expr interface and subclasses for C++ expressions.
FormatToken * Previous
The previous token in the unwrapped line.
Defines the clang::Preprocessor interface.
static bool resolveCalleeCUDATargetConflict(CUDAFunctionTarget Target1, CUDAFunctionTarget Target2, CUDAFunctionTarget *ResolvedTarget)
When an implicitly-declared special member has to invoke more than one base/field special member,...
Definition SemaCUDA.cpp:439
static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr)
Definition SemaCUDA.cpp:187
static void copyAttrIfPresent(Sema &S, FunctionDecl *FD, const FunctionDecl &TemplateFD)
Definition SemaCUDA.cpp:1163
static bool hasExplicitAttr(const VarDecl *D)
Definition SemaCUDA.cpp:31
This file declares semantic analysis for CUDA constructs.
FunctionDecl * getcudaGetParameterBufferDecl()
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
llvm::SetVector< const ValueDecl * > CUDAExternalDeviceDeclODRUsedByHost
Keep track of CUDA/HIP external kernels or device variables ODR-used by host code.
llvm::DenseSet< const FunctionDecl * > CUDAImplicitHostDeviceFunUsedByDevice
Keep track of CUDA/HIP implicit host device functions used on device side in device compilation.
FunctionDecl * getcudaConfigureCallDecl()
FunctionDecl * getcudaLaunchDeviceDecl()
Attr - This represents one attribute.
Represents a base class of a C++ class.
Represents a call to a C++ constructor.
Represents a C++ constructor within a class.
Represents a C++ base or member initializer.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
The null pointer literal (C++11 [lex.nullptr])
Represents a C++ struct/union/class.
base_class_range vbases()
bool isAbstract() const
Determine whether this class has a pure virtual function.
bool isDynamicClass() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
bool isInvalidDecl() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
This represents one expression.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
bool hasTrivialBody() const
Returns whether the function has a trivial body that does not require any specific codegen.
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
bool isVariadic() const
Whether this function is variadic.
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
bool isUserProvided() const
True if this method is user-declared and was not deleted or defaulted on its first declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Declaration of a template function.
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Represents the results of name lookup.
This represents a decl that may have a name.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
OverloadCandidateSet - A set of overload candidates, used in C++ overload resolution (C++ 13....
ParsedAttr - Represents a syntactic attribute.
A (possibly-)qualified type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
bool isConstQualified() const
Determine whether this type is const-qualified.
LangAS getAddressSpace() const
field_range fields() const
decl_type * getFirstDecl()
Return the first declaration of this declaration or itself if this is the only declaration.
Scope - A scope is a transient data structure that is used while parsing the program.
A generic diagnostic builder for errors which may or may not be deferred.
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
DiagnosticsEngine & getDiagnostics() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
std::string getLaunchDeviceFuncName() const
Return the name of the device kernel launch function.
Definition SemaCUDA.cpp:1201
void PushForceHostDevice()
Increments our count of the number of times we've seen a pragma forcing functions to be host device.
Definition SemaCUDA.cpp:39
void checkAllowedInitializer(VarDecl *VD)
Definition SemaCUDA.cpp:757
void RecordImplicitHostDeviceFuncUsedByDevice(const FunctionDecl *FD)
Record FD if it is a CUDA/HIP implicit host device function used on device side in device compilation...
Definition SemaCUDA.cpp:811
std::string getConfigureFuncName() const
Returns the name of the launch configuration function.
Definition SemaCUDA.cpp:1180
bool PopForceHostDevice()
Decrements our count of the number of times we've seen a pragma forcing functions to be host device.
Definition SemaCUDA.cpp:44
CUDAFunctionTarget IdentifyTarget(const FunctionDecl *D, bool IgnoreImplicitHDAttr=false)
Determines whether the given function is a CUDA device/host/kernel/etc.
Definition SemaCUDA.cpp:212
void maybeAddHostDeviceAttrs(FunctionDecl *FD, const LookupResult &Previous)
May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD, depending on FD and the current co...
Definition SemaCUDA.cpp:845
ExprResult ActOnExecConfigExpr(Scope *S, SourceLocation LLLLoc, MultiExprArg ExecConfig, SourceLocation GGGLoc)
Definition SemaCUDA.cpp:52
bool isEmptyConstructor(SourceLocation Loc, CXXConstructorDecl *CD)
Definition SemaCUDA.cpp:611
std::string getGetParameterBufferFuncName() const
Return the name of the parameter buffer allocation function for the device kernel launch.
Definition SemaCUDA.cpp:1197
bool isEmptyDestructor(SourceLocation Loc, CXXDestructorDecl *CD)
Definition SemaCUDA.cpp:649
void checkTargetOverload(FunctionDecl *NewFD, const LookupResult &Previous)
Check whether NewFD is a valid overload for CUDA.
Definition SemaCUDA.cpp:1116
CUDAFunctionTarget CurrentTarget()
Gets the CUDA target for the current context.
SemaDiagnosticBuilder DiagIfHostCode(SourceLocation Loc, unsigned DiagID)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
Definition SemaCUDA.cpp:956
bool inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, CXXSpecialMemberKind CSM, CXXMethodDecl *MemberDecl, bool ConstRHS, bool Diagnose)
Given a implicit special member, infer its CUDA target from the calls it needs to make to underlying ...
Definition SemaCUDA.cpp:459
struct clang::SemaCUDA::CUDATargetContext CurCUDATargetCtx
CUDATargetContextKind
Defines kinds of CUDA global host/device context where a function may be called.
@ CTCK_InitGlobalVar
Unknown context.
SemaDiagnosticBuilder DiagIfDeviceCode(SourceLocation Loc, unsigned DiagID)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
Definition SemaCUDA.cpp:924
llvm::DenseSet< FunctionDeclAndLoc > LocsWithCUDACallDiags
FunctionDecls and SourceLocations for which CheckCall has emitted a (maybe deferred) "bad call" diagn...
bool CheckCall(SourceLocation Loc, FunctionDecl *Callee)
Check whether we're allowed to call Callee from the current context.
Definition SemaCUDA.cpp:987
void inheritTargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD)
Copies target attributes from the template TD to the function FD.
Definition SemaCUDA.cpp:1172
static bool isImplicitHostDeviceFunction(const FunctionDecl *D)
Definition SemaCUDA.cpp:400
void CheckLambdaCapture(CXXMethodDecl *D, const sema::Capture &Capture)
Definition SemaCUDA.cpp:1063
void MaybeAddConstantAttr(VarDecl *VD)
May add implicit CUDAConstantAttr attribute to VD, depending on VD and current compilation settings.
Definition SemaCUDA.cpp:910
void EraseUnwantedMatches(const FunctionDecl *Caller, llvm::SmallVectorImpl< std::pair< DeclAccessPair, FunctionDecl * > > &Matches)
Finds a function in Matches with highest calling priority from Caller context and erases all function...
Definition SemaCUDA.cpp:406
SemaCUDA(Sema &S)
Definition SemaCUDA.cpp:29
void SetLambdaAttrs(CXXMethodDecl *Method)
Set device or host device attributes on the given lambda operator() method.
Definition SemaCUDA.cpp:1108
CUDAFunctionPreference IdentifyPreference(const FunctionDecl *Caller, const FunctionDecl *Callee)
Identifies relative preference of a given Caller/Callee combination, based on their host/device attri...
Definition SemaCUDA.cpp:312
void recordPotentialODRUsedVariable(MultiExprArg Args, OverloadCandidateSet &CandidateSet)
Record variables that are potentially ODR-used in CUDA/HIP.
Definition SemaCUDA.cpp:1207
@ CVT_Host
Emitted on device side with a shadow variable on host side.
@ CVT_Both
Emitted on host side only.
@ CVT_Unified
Emitted on both sides with different addresses.
SpecialMemberOverloadResult - The overloading result for a special member function.
CXXMethodDecl * getMethod() const
Sema - This implements semantic analysis and AST building for C.
Encodes a location in the source.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isReferenceType() const
bool isCUDADeviceBuiltinSurfaceType() const
Check if the type is the CUDA device builtin surface type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isCUDADeviceBuiltinTextureType() const
Check if the type is the CUDA device builtin texture type.
Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration ...
Represents a variable declaration or definition.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
bool isStaticDataMember() const
Determines whether this is a static data member.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
const Expr * getInit() const
ValueDecl * getVariable() const
bool isVariableCapture() const
SourceLocation getLocation() const
Retrieve the location at which this variable was captured.
bool isThisCapture() const
bool isReferenceCapture() const
llvm::SmallPtrSet< VarDecl *, 4 > CUDAPotentialODRUsedVars
Variables that are potentially ODR-used in CUDA/HIP.
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
bool isa(CodeGen::Address addr)
MutableArrayRef< Expr * > MultiExprArg
bool CudaFeatureEnabled(llvm::VersionTuple, CudaFeature)
CXXSpecialMemberKind
Kinds of C++ special members.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
@ TSK_ExplicitInstantiationDeclaration
This template specialization was instantiated from a template due to an explicit instantiation declar...
ActionResult< Expr * > ExprResult
OverloadCandidate - A single candidate in an overload set (C++ 13.3).