clang  20.0.0git
SemaCUDA.cpp
Go to the documentation of this file.
1 //===--- SemaCUDA.cpp - Semantic Analysis for CUDA constructs -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file implements semantic analysis for CUDA constructs.
10 ///
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/Sema/SemaCUDA.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/ExprCXX.h"
17 #include "clang/Basic/Cuda.h"
18 #include "clang/Basic/TargetInfo.h"
19 #include "clang/Lex/Preprocessor.h"
20 #include "clang/Sema/Lookup.h"
21 #include "clang/Sema/ScopeInfo.h"
22 #include "clang/Sema/Sema.h"
25 #include "clang/Sema/Template.h"
26 #include "llvm/ADT/STLForwardCompat.h"
27 #include "llvm/ADT/SmallVector.h"
28 #include <optional>
29 using namespace clang;
30 
32 
33 template <typename AttrT> static bool hasExplicitAttr(const VarDecl *D) {
34  if (!D)
35  return false;
36  if (auto *A = D->getAttr<AttrT>())
37  return !A->isImplicit();
38  return false;
39 }
40 
42  assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
43  ForceHostDeviceDepth++;
44 }
45 
47  assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
48  if (ForceHostDeviceDepth == 0)
49  return false;
50  ForceHostDeviceDepth--;
51  return true;
52 }
53 
55  MultiExprArg ExecConfig,
56  SourceLocation GGGLoc) {
58  if (!ConfigDecl)
59  return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)
61  QualType ConfigQTy = ConfigDecl->getType();
62 
63  DeclRefExpr *ConfigDR = new (getASTContext()) DeclRefExpr(
64  getASTContext(), ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc);
65  SemaRef.MarkFunctionReferenced(LLLLoc, ConfigDecl);
66 
67  return SemaRef.BuildCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr,
68  /*IsExecConfig=*/true);
69 }
70 
72  bool HasHostAttr = false;
73  bool HasDeviceAttr = false;
74  bool HasGlobalAttr = false;
75  bool HasInvalidTargetAttr = false;
76  for (const ParsedAttr &AL : Attrs) {
77  switch (AL.getKind()) {
78  case ParsedAttr::AT_CUDAGlobal:
79  HasGlobalAttr = true;
80  break;
81  case ParsedAttr::AT_CUDAHost:
82  HasHostAttr = true;
83  break;
84  case ParsedAttr::AT_CUDADevice:
85  HasDeviceAttr = true;
86  break;
87  case ParsedAttr::AT_CUDAInvalidTarget:
88  HasInvalidTargetAttr = true;
89  break;
90  default:
91  break;
92  }
93  }
94 
95  if (HasInvalidTargetAttr)
97 
98  if (HasGlobalAttr)
100 
101  if (HasHostAttr && HasDeviceAttr)
103 
104  if (HasDeviceAttr)
106 
108 }
109 
110 template <typename A>
111 static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr) {
112  return D->hasAttrs() && llvm::any_of(D->getAttrs(), [&](Attr *Attribute) {
113  return isa<A>(Attribute) &&
114  !(IgnoreImplicitAttr && Attribute->isImplicit());
115  });
116 }
117 
120  : S(S_) {
122  assert(K == SemaCUDA::CTCK_InitGlobalVar);
123  auto *VD = dyn_cast_or_null<VarDecl>(D);
124  if (VD && VD->hasGlobalStorage() && !VD->isStaticLocal()) {
126  if ((hasAttr<CUDADeviceAttr>(VD, /*IgnoreImplicit=*/true) &&
127  !hasAttr<CUDAHostAttr>(VD, /*IgnoreImplicit=*/true)) ||
128  hasAttr<CUDASharedAttr>(VD, /*IgnoreImplicit=*/true) ||
129  hasAttr<CUDAConstantAttr>(VD, /*IgnoreImplicit=*/true))
131  S.CurCUDATargetCtx = {Target, K, VD};
132  }
133 }
134 
135 /// IdentifyTarget - Determine the CUDA compilation target for this function
137  bool IgnoreImplicitHDAttr) {
138  // Code that lives outside a function gets the target from CurCUDATargetCtx.
139  if (D == nullptr)
140  return CurCUDATargetCtx.Target;
141 
142  if (D->hasAttr<CUDAInvalidTargetAttr>())
144 
145  if (D->hasAttr<CUDAGlobalAttr>())
147 
148  if (hasAttr<CUDADeviceAttr>(D, IgnoreImplicitHDAttr)) {
149  if (hasAttr<CUDAHostAttr>(D, IgnoreImplicitHDAttr))
152  } else if (hasAttr<CUDAHostAttr>(D, IgnoreImplicitHDAttr)) {
154  } else if ((D->isImplicit() || !D->isUserProvided()) &&
155  !IgnoreImplicitHDAttr) {
156  // Some implicit declarations (like intrinsic functions) are not marked.
157  // Set the most lenient target on them for maximal flexibility.
159  }
160 
162 }
163 
164 /// IdentifyTarget - Determine the CUDA compilation target for this variable.
166  if (Var->hasAttr<HIPManagedAttr>())
167  return CVT_Unified;
168  // Only constexpr and const variabless with implicit constant attribute
169  // are emitted on both sides. Such variables are promoted to device side
170  // only if they have static constant intializers on device side.
171  if ((Var->isConstexpr() || Var->getType().isConstQualified()) &&
172  Var->hasAttr<CUDAConstantAttr>() &&
173  !hasExplicitAttr<CUDAConstantAttr>(Var))
174  return CVT_Both;
175  if (Var->hasAttr<CUDADeviceAttr>() || Var->hasAttr<CUDAConstantAttr>() ||
176  Var->hasAttr<CUDASharedAttr>() ||
179  return CVT_Device;
180  // Function-scope static variable without explicit device or constant
181  // attribute are emitted
182  // - on both sides in host device functions
183  // - on device side in device or global functions
184  if (auto *FD = dyn_cast<FunctionDecl>(Var->getDeclContext())) {
185  switch (IdentifyTarget(FD)) {
187  return CVT_Both;
190  return CVT_Device;
191  default:
192  return CVT_Host;
193  }
194  }
195  return CVT_Host;
196 }
197 
198 // * CUDA Call preference table
199 //
200 // F - from,
201 // T - to
202 // Ph - preference in host mode
203 // Pd - preference in device mode
204 // H - handled in (x)
205 // Preferences: N:native, SS:same side, HD:host-device, WS:wrong side, --:never.
206 //
207 // | F | T | Ph | Pd | H |
208 // |----+----+-----+-----+-----+
209 // | d | d | N | N | (c) |
210 // | d | g | -- | -- | (a) |
211 // | d | h | -- | -- | (e) |
212 // | d | hd | HD | HD | (b) |
213 // | g | d | N | N | (c) |
214 // | g | g | -- | -- | (a) |
215 // | g | h | -- | -- | (e) |
216 // | g | hd | HD | HD | (b) |
217 // | h | d | -- | -- | (e) |
218 // | h | g | N | N | (c) |
219 // | h | h | N | N | (c) |
220 // | h | hd | HD | HD | (b) |
221 // | hd | d | WS | SS | (d) |
222 // | hd | g | SS | -- |(d/a)|
223 // | hd | h | SS | WS | (d) |
224 // | hd | hd | HD | HD | (b) |
225 //
226 // In combined SYCL - CUDA mode
227 // Sh - SYCL is host
228 // Sd - SYCL is device
229 //
230 // Priority order: N, SS, HD, WS, --
231 //
232 // | | | host | cuda-dev | sycl-dev | |
233 // | F | T | Ph - Sh | Pd - Sh | Ph - Sd | H |
234 // |----+----+----------+------------+-----------+-----+
235 // | d | d | N | N | N | (c) |
236 // | d | g | -- | -- | -- | (a) |
237 // | d | h | -- | -- | -- | (e) |
238 // | d | hd | HD | HD | HD | (b) |
239 // | g | d | N | N | N | (c) |
240 // | g | g | -- | -- | -- | (a) |
241 // | g | h | -- | -- | -- | (e) |
242 // | g | hd | HD | HD | HD | (c) |
243 // | h | d | HD(y) | WS(v) | N(x) | ( ) |
244 // | h | g | N | N | N | (c) |
245 // | h | h | N | N | SS(p) | ( ) |
246 // | h | hd | HD | HD | HD | ( ) |
247 // | hd | d | HD(y) | SS | N(x) | ( ) |
248 // | hd | g | SS | -- | --(z) |(d/a)|
249 // | hd | h | SS | WS | SS | (d) |
250 // | hd | hd | HD | HD | HD | (b) |
251 
254  const FunctionDecl *Callee) {
255  assert(Callee && "Callee must be valid.");
256 
257  // Treat ctor/dtor as host device function in device var initializer to allow
258  // trivial ctor/dtor without device attr to be used. Non-trivial ctor/dtor
259  // will be diagnosed by checkAllowedInitializer.
260  if (Caller == nullptr && CurCUDATargetCtx.Kind == CTCK_InitGlobalVar &&
262  (isa<CXXConstructorDecl>(Callee) || isa<CXXDestructorDecl>(Callee)))
263  return CFP_HostDevice;
264 
265  CUDAFunctionTarget CallerTarget = IdentifyTarget(Caller);
266  CUDAFunctionTarget CalleeTarget = IdentifyTarget(Callee);
267 
268  // Pd - Sh -> CUDA device compilation for SYCL+CUDA
269  if (getLangOpts().SYCLIsHost && getLangOpts().CUDA &&
270  getLangOpts().CUDAIsDevice) {
271  // (v) allows a __host__ function to call a __device__ one. This is allowed
272  // for sycl-device compilation, since a regular function (implicitly
273  // __host__) called by a SYCL kernel could end up calling a __device__ one.
274  // In any case, __host__ functions are not emitted by the cuda-dev
275  // compilation. So, this doesn't introduce any error.
276  if (CallerTarget == CUDAFunctionTarget::Host &&
277  CalleeTarget == CUDAFunctionTarget::Device)
278  return CFP_WrongSide;
279  }
280 
281  // Ph - Sd -> SYCL device compilation for SYCL+CUDA
282  if (getLangOpts().SYCLIsDevice && getLangOpts().CUDA &&
283  !getLangOpts().CUDAIsDevice) {
284  // (x), and (p) prefer __device__ function in SYCL-device compilation.
285  // (x) allows to pick a __device__ function.
286  if ((CallerTarget == CUDAFunctionTarget::Host ||
287  CallerTarget == CUDAFunctionTarget::HostDevice) &&
288  CalleeTarget == CUDAFunctionTarget::Device)
289  return CFP_Native;
290  // (p) lowers the preference of __host__ functions for favoring __device__
291  // ones.
292  if (CallerTarget == CUDAFunctionTarget::Host &&
293  CalleeTarget == CUDAFunctionTarget::Host)
294  return CFP_SameSide;
295 
296  // (z)
297  if (CallerTarget == CUDAFunctionTarget::HostDevice &&
298  CalleeTarget == CUDAFunctionTarget::Global)
299  return CFP_Never;
300  }
301 
302  // Ph - Sh -> host compilation for SYCL+CUDA
303  if (getLangOpts().SYCLIsHost && getLangOpts().CUDA &&
304  !getLangOpts().CUDAIsDevice) {
305  // (y) allows __host__ and __host__ __device__ functions to call a
306  // __device__ one. This could happen, if a __device__ function is defined
307  // without having a corresponding __host__. In this case, a dummy __host__
308  // function is generated. This dummy function is required since the lambda
309  // that forms the SYCL kernel (having host device attr.) needs to be
310  // compiled also for the host. (CallerTarget == CUDAFunctionTarget::Host) is added in case a
311  // regular function (implicitly __host__) is called by a SYCL kernel lambda.
312  if ((CallerTarget == CUDAFunctionTarget::Host || CallerTarget == CUDAFunctionTarget::HostDevice) &&
313  CalleeTarget == CUDAFunctionTarget::Device)
314  return CFP_HostDevice;
315  }
316 
317  // If one of the targets is invalid, the check always fails, no matter what
318  // the other target is.
319  if (CallerTarget == CUDAFunctionTarget::InvalidTarget ||
320  CalleeTarget == CUDAFunctionTarget::InvalidTarget)
321  return CFP_Never;
322 
323  // (a) Can't call global from some contexts until we support CUDA's
324  // dynamic parallelism.
325  if (CalleeTarget == CUDAFunctionTarget::Global &&
326  (CallerTarget == CUDAFunctionTarget::Global ||
327  CallerTarget == CUDAFunctionTarget::Device))
328  return CFP_Never;
329 
330  // (b) Calling HostDevice is OK for everyone.
331  if (CalleeTarget == CUDAFunctionTarget::HostDevice)
332  return CFP_HostDevice;
333 
334  // (c) Best case scenarios
335  if (CalleeTarget == CallerTarget ||
336  (CallerTarget == CUDAFunctionTarget::Host &&
337  CalleeTarget == CUDAFunctionTarget::Global) ||
338  (CallerTarget == CUDAFunctionTarget::Global &&
339  CalleeTarget == CUDAFunctionTarget::Device))
340  return CFP_Native;
341 
342  // HipStdPar mode is special, in that assessing whether a device side call to
343  // a host target is deferred to a subsequent pass, and cannot unambiguously be
344  // adjudicated in the AST, hence we optimistically allow them to pass here.
345  if (getLangOpts().HIPStdPar &&
346  (CallerTarget == CUDAFunctionTarget::Global ||
347  CallerTarget == CUDAFunctionTarget::Device ||
348  CallerTarget == CUDAFunctionTarget::HostDevice) &&
349  CalleeTarget == CUDAFunctionTarget::Host)
350  return CFP_HostDevice;
351 
352  // (d) HostDevice behavior depends on compilation mode.
353  if (CallerTarget == CUDAFunctionTarget::HostDevice) {
354  // It's OK to call a compilation-mode matching function from an HD one.
355  if ((getLangOpts().CUDAIsDevice &&
356  CalleeTarget == CUDAFunctionTarget::Device) ||
357  (!getLangOpts().CUDAIsDevice &&
358  (CalleeTarget == CUDAFunctionTarget::Host ||
359  CalleeTarget == CUDAFunctionTarget::Global)))
360  return CFP_SameSide;
361 
362  // Calls from HD to non-mode-matching functions (i.e., to host functions
363  // when compiling in device mode or to device functions when compiling in
364  // host mode) are allowed at the sema level, but eventually rejected if
365  // they're ever codegened. TODO: Reject said calls earlier.
366  return CFP_WrongSide;
367  }
368 
369  // (e) Calling across device/host boundary is not something you should do.
370  if ((CallerTarget == CUDAFunctionTarget::Host &&
371  CalleeTarget == CUDAFunctionTarget::Device) ||
372  (CallerTarget == CUDAFunctionTarget::Device &&
373  CalleeTarget == CUDAFunctionTarget::Host) ||
374  (CallerTarget == CUDAFunctionTarget::Global &&
375  CalleeTarget == CUDAFunctionTarget::Host))
376  return CFP_Never;
377 
378  llvm_unreachable("All cases should've been handled by now.");
379 }
380 
381 template <typename AttrT> static bool hasImplicitAttr(const FunctionDecl *D) {
382  if (!D)
383  return false;
384  if (auto *A = D->getAttr<AttrT>())
385  return A->isImplicit();
386  return D->isImplicit();
387 }
388 
390  bool IsImplicitDevAttr = hasImplicitAttr<CUDADeviceAttr>(D);
391  bool IsImplicitHostAttr = hasImplicitAttr<CUDAHostAttr>(D);
392  return IsImplicitDevAttr && IsImplicitHostAttr;
393 }
394 
396  const FunctionDecl *Caller,
397  SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) {
398  if (Matches.size() <= 1)
399  return;
400 
401  using Pair = std::pair<DeclAccessPair, FunctionDecl*>;
402 
403  // Gets the CUDA function preference for a call from Caller to Match.
404  auto GetCFP = [&](const Pair &Match) {
405  return IdentifyPreference(Caller, Match.second);
406  };
407 
408  // Find the best call preference among the functions in Matches.
409  CUDAFunctionPreference BestCFP = GetCFP(*std::max_element(
410  Matches.begin(), Matches.end(),
411  [&](const Pair &M1, const Pair &M2) { return GetCFP(M1) < GetCFP(M2); }));
412 
413  // Erase all functions with lower priority.
414  llvm::erase_if(Matches,
415  [&](const Pair &Match) { return GetCFP(Match) < BestCFP; });
416 }
417 
418 /// When an implicitly-declared special member has to invoke more than one
419 /// base/field special member, conflicts may occur in the targets of these
420 /// members. For example, if one base's member __host__ and another's is
421 /// __device__, it's a conflict.
422 /// This function figures out if the given targets \param Target1 and
423 /// \param Target2 conflict, and if they do not it fills in
424 /// \param ResolvedTarget with a target that resolves for both calls.
425 /// \return true if there's a conflict, false otherwise.
426 static bool
428  CUDAFunctionTarget Target2,
429  CUDAFunctionTarget *ResolvedTarget) {
430  // Only free functions and static member functions may be global.
431  assert(Target1 != CUDAFunctionTarget::Global);
432  assert(Target2 != CUDAFunctionTarget::Global);
433 
434  if (Target1 == CUDAFunctionTarget::HostDevice) {
435  *ResolvedTarget = Target2;
436  } else if (Target2 == CUDAFunctionTarget::HostDevice) {
437  *ResolvedTarget = Target1;
438  } else if (Target1 != Target2) {
439  return true;
440  } else {
441  *ResolvedTarget = Target1;
442  }
443 
444  return false;
445 }
446 
449  CXXMethodDecl *MemberDecl,
450  bool ConstRHS,
451  bool Diagnose) {
452  // If the defaulted special member is defined lexically outside of its
453  // owning class, or the special member already has explicit device or host
454  // attributes, do not infer.
455  bool InClass = MemberDecl->getLexicalParent() == MemberDecl->getParent();
456  bool HasH = MemberDecl->hasAttr<CUDAHostAttr>();
457  bool HasD = MemberDecl->hasAttr<CUDADeviceAttr>();
458  bool HasExplicitAttr =
459  (HasD && !MemberDecl->getAttr<CUDADeviceAttr>()->isImplicit()) ||
460  (HasH && !MemberDecl->getAttr<CUDAHostAttr>()->isImplicit());
461  if (!InClass || HasExplicitAttr)
462  return false;
463 
464  std::optional<CUDAFunctionTarget> InferredTarget;
465 
466  // We're going to invoke special member lookup; mark that these special
467  // members are called from this one, and not from its caller.
468  Sema::ContextRAII MethodContext(SemaRef, MemberDecl);
469 
470  // Look for special members in base classes that should be invoked from here.
471  // Infer the target of this member base on the ones it should call.
472  // Skip direct and indirect virtual bases for abstract classes.
474  for (const auto &B : ClassDecl->bases()) {
475  if (!B.isVirtual()) {
476  Bases.push_back(&B);
477  }
478  }
479 
480  if (!ClassDecl->isAbstract()) {
481  llvm::append_range(Bases, llvm::make_pointer_range(ClassDecl->vbases()));
482  }
483 
484  for (const auto *B : Bases) {
485  const RecordType *BaseType = B->getType()->getAs<RecordType>();
486  if (!BaseType) {
487  continue;
488  }
489 
490  CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
492  SemaRef.LookupSpecialMember(BaseClassDecl, CSM,
493  /* ConstArg */ ConstRHS,
494  /* VolatileArg */ false,
495  /* RValueThis */ false,
496  /* ConstThis */ false,
497  /* VolatileThis */ false);
498 
499  if (!SMOR.getMethod())
500  continue;
501 
502  CUDAFunctionTarget BaseMethodTarget = IdentifyTarget(SMOR.getMethod());
503  if (!InferredTarget) {
504  InferredTarget = BaseMethodTarget;
505  } else {
506  bool ResolutionError = resolveCalleeCUDATargetConflict(
507  *InferredTarget, BaseMethodTarget, &*InferredTarget);
508  if (ResolutionError) {
509  if (Diagnose) {
510  Diag(ClassDecl->getLocation(),
511  diag::note_implicit_member_target_infer_collision)
512  << (unsigned)CSM << llvm::to_underlying(*InferredTarget)
513  << llvm::to_underlying(BaseMethodTarget);
514  }
515  MemberDecl->addAttr(
516  CUDAInvalidTargetAttr::CreateImplicit(getASTContext()));
517  return true;
518  }
519  }
520  }
521 
522  // Same as for bases, but now for special members of fields.
523  for (const auto *F : ClassDecl->fields()) {
524  if (F->isInvalidDecl()) {
525  continue;
526  }
527 
528  const RecordType *FieldType =
529  getASTContext().getBaseElementType(F->getType())->getAs<RecordType>();
530  if (!FieldType) {
531  continue;
532  }
533 
534  CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(FieldType->getDecl());
536  SemaRef.LookupSpecialMember(FieldRecDecl, CSM,
537  /* ConstArg */ ConstRHS && !F->isMutable(),
538  /* VolatileArg */ false,
539  /* RValueThis */ false,
540  /* ConstThis */ false,
541  /* VolatileThis */ false);
542 
543  if (!SMOR.getMethod())
544  continue;
545 
546  CUDAFunctionTarget FieldMethodTarget = IdentifyTarget(SMOR.getMethod());
547  if (!InferredTarget) {
548  InferredTarget = FieldMethodTarget;
549  } else {
550  bool ResolutionError = resolveCalleeCUDATargetConflict(
551  *InferredTarget, FieldMethodTarget, &*InferredTarget);
552  if (ResolutionError) {
553  if (Diagnose) {
554  Diag(ClassDecl->getLocation(),
555  diag::note_implicit_member_target_infer_collision)
556  << (unsigned)CSM << llvm::to_underlying(*InferredTarget)
557  << llvm::to_underlying(FieldMethodTarget);
558  }
559  MemberDecl->addAttr(
560  CUDAInvalidTargetAttr::CreateImplicit(getASTContext()));
561  return true;
562  }
563  }
564  }
565 
566 
567  // If no target was inferred, mark this member as __host__ __device__;
568  // it's the least restrictive option that can be invoked from any target.
569  bool NeedsH = true, NeedsD = true;
570  if (InferredTarget) {
571  if (*InferredTarget == CUDAFunctionTarget::Device)
572  NeedsH = false;
573  else if (*InferredTarget == CUDAFunctionTarget::Host)
574  NeedsD = false;
575  }
576 
577  // We either setting attributes first time, or the inferred ones must match
578  // previously set ones.
579  if (NeedsD && !HasD)
580  MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext()));
581  if (NeedsH && !HasH)
582  MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(getASTContext()));
583 
584  return false;
585 }
586 
588  if (!CD->isDefined() && CD->isTemplateInstantiation())
590 
591  // (E.2.3.1, CUDA 7.5) A constructor for a class type is considered
592  // empty at a point in the translation unit, if it is either a
593  // trivial constructor
594  if (CD->isTrivial())
595  return true;
596 
597  // ... or it satisfies all of the following conditions:
598  // The constructor function has been defined.
599  // The constructor function has no parameters,
600  // and the function body is an empty compound statement.
601  if (!(CD->hasTrivialBody() && CD->getNumParams() == 0))
602  return false;
603 
604  // Its class has no virtual functions and no virtual base classes.
605  if (CD->getParent()->isDynamicClass())
606  return false;
607 
608  // Union ctor does not call ctors of its data members.
609  if (CD->getParent()->isUnion())
610  return true;
611 
612  // The only form of initializer allowed is an empty constructor.
613  // This will recursively check all base classes and member initializers
614  if (!llvm::all_of(CD->inits(), [&](const CXXCtorInitializer *CI) {
615  if (const CXXConstructExpr *CE =
616  dyn_cast<CXXConstructExpr>(CI->getInit()))
617  return isEmptyConstructor(Loc, CE->getConstructor());
618  return false;
619  }))
620  return false;
621 
622  return true;
623 }
624 
626  // No destructor -> no problem.
627  if (!DD)
628  return true;
629 
630  if (!DD->isDefined() && DD->isTemplateInstantiation())
632 
633  // (E.2.3.1, CUDA 7.5) A destructor for a class type is considered
634  // empty at a point in the translation unit, if it is either a
635  // trivial constructor
636  if (DD->isTrivial())
637  return true;
638 
639  // ... or it satisfies all of the following conditions:
640  // The destructor function has been defined.
641  // and the function body is an empty compound statement.
642  if (!DD->hasTrivialBody())
643  return false;
644 
645  const CXXRecordDecl *ClassDecl = DD->getParent();
646 
647  // Its class has no virtual functions and no virtual base classes.
648  if (ClassDecl->isDynamicClass())
649  return false;
650 
651  // Union does not have base class and union dtor does not call dtors of its
652  // data members.
653  if (DD->getParent()->isUnion())
654  return true;
655 
656  // Only empty destructors are allowed. This will recursively check
657  // destructors for all base classes...
658  if (!llvm::all_of(ClassDecl->bases(), [&](const CXXBaseSpecifier &BS) {
659  if (CXXRecordDecl *RD = BS.getType()->getAsCXXRecordDecl())
660  return isEmptyDestructor(Loc, RD->getDestructor());
661  return true;
662  }))
663  return false;
664 
665  // ... and member fields.
666  if (!llvm::all_of(ClassDecl->fields(), [&](const FieldDecl *Field) {
667  if (CXXRecordDecl *RD = Field->getType()
668  ->getBaseElementTypeUnsafe()
669  ->getAsCXXRecordDecl())
670  return isEmptyDestructor(Loc, RD->getDestructor());
671  return true;
672  }))
673  return false;
674 
675  return true;
676 }
677 
678 namespace {
679 enum CUDAInitializerCheckKind {
680  CICK_DeviceOrConstant, // Check initializer for device/constant variable
681  CICK_Shared, // Check initializer for shared variable
682 };
683 
684 bool IsDependentVar(VarDecl *VD) {
685  if (VD->getType()->isDependentType())
686  return true;
687  if (const auto *Init = VD->getInit())
688  return Init->isValueDependent();
689  return false;
690 }
691 
692 // Check whether a variable has an allowed initializer for a CUDA device side
693 // variable with global storage. \p VD may be a host variable to be checked for
694 // potential promotion to device side variable.
695 //
696 // CUDA/HIP allows only empty constructors as initializers for global
697 // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all
698 // __shared__ variables whether they are local or not (they all are implicitly
699 // static in CUDA). One exception is that CUDA allows constant initializers
700 // for __constant__ and __device__ variables.
701 bool HasAllowedCUDADeviceStaticInitializer(SemaCUDA &S, VarDecl *VD,
702  CUDAInitializerCheckKind CheckKind) {
703  assert(!VD->isInvalidDecl() && VD->hasGlobalStorage());
704  assert(!IsDependentVar(VD) && "do not check dependent var");
705  const Expr *Init = VD->getInit();
706  auto IsEmptyInit = [&](const Expr *Init) {
707  if (!Init)
708  return true;
709  if (const auto *CE = dyn_cast<CXXConstructExpr>(Init)) {
710  return S.isEmptyConstructor(VD->getLocation(), CE->getConstructor());
711  }
712  return false;
713  };
714  auto IsConstantInit = [&](const Expr *Init) {
715  assert(Init);
717  /*NoWronSidedVars=*/true);
718  return Init->isConstantInitializer(S.getASTContext(),
719  VD->getType()->isReferenceType());
720  };
721  auto HasEmptyDtor = [&](VarDecl *VD) {
722  if (const auto *RD = VD->getType()->getAsCXXRecordDecl())
723  return S.isEmptyDestructor(VD->getLocation(), RD->getDestructor());
724  return true;
725  };
726  if (CheckKind == CICK_Shared)
727  return IsEmptyInit(Init) && HasEmptyDtor(VD);
728  return S.getLangOpts().GPUAllowDeviceInit ||
729  ((IsEmptyInit(Init) || IsConstantInit(Init)) && HasEmptyDtor(VD));
730 }
731 } // namespace
732 
734  // Return early if VD is inside a non-instantiated template function since
735  // the implicit constructor is not defined yet.
736  if (const FunctionDecl *FD =
737  dyn_cast_or_null<FunctionDecl>(VD->getDeclContext()))
738  if (FD->isDependentContext())
739  return;
740 
741  // Do not check dependent variables since the ctor/dtor/initializer are not
742  // determined. Do it after instantiation.
743  if (VD->isInvalidDecl() || !VD->hasInit() || !VD->hasGlobalStorage() ||
744  IsDependentVar(VD))
745  return;
746  const Expr *Init = VD->getInit();
747  bool IsSharedVar = VD->hasAttr<CUDASharedAttr>();
748  bool IsDeviceOrConstantVar =
749  !IsSharedVar &&
750  (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>());
751  if (IsDeviceOrConstantVar || IsSharedVar) {
752  if (HasAllowedCUDADeviceStaticInitializer(
753  *this, VD, IsSharedVar ? CICK_Shared : CICK_DeviceOrConstant))
754  return;
755  Diag(VD->getLocation(),
756  IsSharedVar ? diag::err_shared_var_init : diag::err_dynamic_var_init)
757  << Init->getSourceRange();
758  VD->setInvalidDecl();
759  } else {
760  // This is a host-side global variable. Check that the initializer is
761  // callable from the host side.
762  const FunctionDecl *InitFn = nullptr;
763  if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init)) {
764  InitFn = CE->getConstructor();
765  } else if (const CallExpr *CE = dyn_cast<CallExpr>(Init)) {
766  InitFn = CE->getDirectCallee();
767  }
768  if (InitFn) {
769  CUDAFunctionTarget InitFnTarget = IdentifyTarget(InitFn);
770  if (InitFnTarget != CUDAFunctionTarget::Host &&
771  InitFnTarget != CUDAFunctionTarget::HostDevice) {
772  Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer)
773  << llvm::to_underlying(InitFnTarget) << InitFn;
774  Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn;
775  VD->setInvalidDecl();
776  }
777  }
778  }
779 }
780 
782  const FunctionDecl *Callee) {
783  FunctionDecl *Caller = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true);
784  if (!Caller)
785  return;
786 
787  if (!isImplicitHostDeviceFunction(Callee))
788  return;
789 
790  CUDAFunctionTarget CallerTarget = IdentifyTarget(Caller);
791 
792  // Record whether an implicit host device function is used on device side.
793  if (CallerTarget != CUDAFunctionTarget::Device &&
794  CallerTarget != CUDAFunctionTarget::Global &&
795  (CallerTarget != CUDAFunctionTarget::HostDevice ||
796  (isImplicitHostDeviceFunction(Caller) &&
797  !getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(Caller))))
798  return;
799 
801 }
802 
803 // With -fcuda-host-device-constexpr, an unattributed constexpr function is
804 // treated as implicitly __host__ __device__, unless:
805 // * it is a variadic function (device-side variadic functions are not
806 // allowed), or
807 // * a __device__ function with this signature was already declared, in which
808 // case in which case we output an error, unless the __device__ decl is in a
809 // system header, in which case we leave the constexpr function unattributed.
810 //
811 // In addition, all function decls are treated as __host__ __device__ when
812 // ForceHostDeviceDepth > 0 (corresponding to code within a
813 // #pragma clang force_cuda_host_device_begin/end
814 // pair).
816  const LookupResult &Previous) {
817  assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
818 
819  if (ForceHostDeviceDepth > 0) {
820  if (!NewD->hasAttr<CUDAHostAttr>())
821  NewD->addAttr(CUDAHostAttr::CreateImplicit(getASTContext()));
822  if (!NewD->hasAttr<CUDADeviceAttr>())
823  NewD->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext()));
824  return;
825  }
826 
827  // If a template function has no host/device/global attributes,
828  // make it implicitly host device function.
829  if (getLangOpts().OffloadImplicitHostDeviceTemplates &&
830  !NewD->hasAttr<CUDAHostAttr>() && !NewD->hasAttr<CUDADeviceAttr>() &&
831  !NewD->hasAttr<CUDAGlobalAttr>() &&
832  (NewD->getDescribedFunctionTemplate() ||
834  NewD->addAttr(CUDAHostAttr::CreateImplicit(getASTContext()));
835  NewD->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext()));
836  return;
837  }
838 
839  if (!getLangOpts().CUDAHostDeviceConstexpr || !NewD->isConstexpr() ||
840  NewD->isVariadic() || NewD->hasAttr<CUDAHostAttr>() ||
841  NewD->hasAttr<CUDADeviceAttr>() || NewD->hasAttr<CUDAGlobalAttr>())
842  return;
843 
844  // Is D a __device__ function with the same signature as NewD, ignoring CUDA
845  // attributes?
846  auto IsMatchingDeviceFn = [&](NamedDecl *D) {
847  if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(D))
848  D = Using->getTargetDecl();
849  FunctionDecl *OldD = D->getAsFunction();
850  return OldD && OldD->hasAttr<CUDADeviceAttr>() &&
851  !OldD->hasAttr<CUDAHostAttr>() &&
852  !SemaRef.IsOverload(NewD, OldD,
853  /* UseMemberUsingDeclRules = */ false,
854  /* ConsiderCudaAttrs = */ false);
855  };
856  auto It = llvm::find_if(Previous, IsMatchingDeviceFn);
857  if (It != Previous.end()) {
858  // We found a __device__ function with the same name and signature as NewD
859  // (ignoring CUDA attrs). This is an error unless that function is defined
860  // in a system header, in which case we simply return without making NewD
861  // host+device.
862  NamedDecl *Match = *It;
864  Diag(NewD->getLocation(),
865  diag::err_cuda_unattributed_constexpr_cannot_overload_device)
866  << NewD;
867  Diag(Match->getLocation(),
868  diag::note_cuda_conflicting_device_function_declared_here);
869  }
870  return;
871  }
872 
873  NewD->addAttr(CUDAHostAttr::CreateImplicit(getASTContext()));
874  NewD->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext()));
875 }
876 
877 // TODO: `__constant__` memory may be a limited resource for certain targets.
878 // A safeguard may be needed at the end of compilation pipeline if
879 // `__constant__` memory usage goes beyond limit.
881  // Do not promote dependent variables since the cotr/dtor/initializer are
882  // not determined. Do it after instantiation.
883  if (getLangOpts().CUDAIsDevice && !VD->hasAttr<CUDAConstantAttr>() &&
884  !VD->hasAttr<CUDASharedAttr>() &&
885  (VD->isFileVarDecl() || VD->isStaticDataMember()) &&
886  !IsDependentVar(VD) &&
887  ((VD->isConstexpr() || VD->getType().isConstQualified()) &&
888  HasAllowedCUDADeviceStaticInitializer(*this, VD,
889  CICK_DeviceOrConstant))) {
890  VD->addAttr(CUDAConstantAttr::CreateImplicit(getASTContext()));
891  }
892 }
893 
895  unsigned DiagID) {
896  assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
897  FunctionDecl *CurFunContext =
898  SemaRef.getCurFunctionDecl(/*AllowLambda=*/true);
899  SemaDiagnosticBuilder::Kind DiagKind = [&] {
900  if (!CurFunContext)
902  switch (CurrentTarget()) {
907  // An HD function counts as host code if we're compiling for host, and
908  // device code if we're compiling for device. Defer any errors in device
909  // mode until the function is known-emitted.
910  if (!getLangOpts().CUDAIsDevice)
913  getDiagnostics().getDiagnosticIDs()->isBuiltinNote(DiagID))
915  return (SemaRef.getEmissionStatus(CurFunContext) ==
919  default:
921  }
922  }();
923  return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, CurFunContext, SemaRef,
925 }
926 
928  unsigned DiagID) {
929  assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
930  FunctionDecl *CurFunContext =
931  SemaRef.getCurFunctionDecl(/*AllowLambda=*/true);
932  SemaDiagnosticBuilder::Kind DiagKind = [&] {
933  if (!CurFunContext)
935  switch (CurrentTarget()) {
939  // An HD function counts as host code if we're compiling for host, and
940  // device code if we're compiling for device. Defer any errors in device
941  // mode until the function is known-emitted.
942  if (getLangOpts().CUDAIsDevice)
945  getDiagnostics().getDiagnosticIDs()->isBuiltinNote(DiagID))
947  return (SemaRef.getEmissionStatus(CurFunContext) ==
951  default:
953  }
954  }();
955  return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, CurFunContext, SemaRef,
957 }
958 
960  assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
961  assert(Callee && "Callee may not be null.");
962 
963  const auto &ExprEvalCtx = SemaRef.currentEvaluationContext();
964  if (ExprEvalCtx.isUnevaluated() || ExprEvalCtx.isConstantEvaluated())
965  return true;
966 
967  // FIXME: Is bailing out early correct here? Should we instead assume that
968  // the caller is a global initializer?
969  FunctionDecl *Caller = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true);
970  if (!Caller)
971  return true;
972 
973  // If the caller is known-emitted, mark the callee as known-emitted.
974  // Otherwise, mark the call in our call graph so we can traverse it later.
975  bool CallerKnownEmitted = SemaRef.getEmissionStatus(Caller) ==
977  SemaDiagnosticBuilder::Kind DiagKind = [this, Caller, Callee,
978  CallerKnownEmitted] {
979  switch (IdentifyPreference(Caller, Callee)) {
980  case CFP_Never:
981  case CFP_WrongSide:
982  assert(Caller && "Never/wrongSide calls require a non-null caller");
983  // If we know the caller will be emitted, we know this wrong-side call
984  // will be emitted, so it's an immediate error. Otherwise, defer the
985  // error until we know the caller is emitted.
986  return CallerKnownEmitted
989  default:
991  }
992  }();
993 
994  if (DiagKind == SemaDiagnosticBuilder::K_Nop) {
995  // For -fgpu-rdc, keep track of external kernels used by host functions.
996  if (getLangOpts().CUDAIsDevice && getLangOpts().GPURelocatableDeviceCode &&
997  Callee->hasAttr<CUDAGlobalAttr>() && !Callee->isDefined() &&
998  (!Caller || (!Caller->getDescribedFunctionTemplate() &&
1002  return true;
1003  }
1004 
1005  // Avoid emitting this error twice for the same location. Using a hashtable
1006  // like this is unfortunate, but because we must continue parsing as normal
1007  // after encountering a deferred error, it's otherwise very tricky for us to
1008  // ensure that we only emit this deferred error once.
1009  if (!LocsWithCUDACallDiags.insert({Caller, Loc}).second)
1010  return true;
1011 
1012  SemaDiagnosticBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller,
1014  << llvm::to_underlying(IdentifyTarget(Callee)) << /*function*/ 0
1015  << Callee << llvm::to_underlying(IdentifyTarget(Caller));
1016  if (!Callee->getBuiltinID())
1017  SemaDiagnosticBuilder(DiagKind, Callee->getLocation(),
1018  diag::note_previous_decl, Caller, SemaRef,
1020  << Callee;
1021  return DiagKind != SemaDiagnosticBuilder::K_Immediate &&
1023 }
1024 
1025 // Check the wrong-sided reference capture of lambda for CUDA/HIP.
1026 // A lambda function may capture a stack variable by reference when it is
1027 // defined and uses the capture by reference when the lambda is called. When
1028 // the capture and use happen on different sides, the capture is invalid and
1029 // should be diagnosed.
1031  const sema::Capture &Capture) {
1032  // In host compilation we only need to check lambda functions emitted on host
1033  // side. In such lambda functions, a reference capture is invalid only
1034  // if the lambda structure is populated by a device function or kernel then
1035  // is passed to and called by a host function. However that is impossible,
1036  // since a device function or kernel can only call a device function, also a
1037  // kernel cannot pass a lambda back to a host function since we cannot
1038  // define a kernel argument type which can hold the lambda before the lambda
1039  // itself is defined.
1040  if (!getLangOpts().CUDAIsDevice)
1041  return;
1042 
1043  // File-scope lambda can only do init captures for global variables, which
1044  // results in passing by value for these global variables.
1045  FunctionDecl *Caller = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true);
1046  if (!Caller)
1047  return;
1048 
1049  // In device compilation, we only need to check lambda functions which are
1050  // emitted on device side. For such lambdas, a reference capture is invalid
1051  // only if the lambda structure is populated by a host function then passed
1052  // to and called in a device function or kernel.
1053  bool CalleeIsDevice = Callee->hasAttr<CUDADeviceAttr>();
1054  bool CallerIsHost =
1055  !Caller->hasAttr<CUDAGlobalAttr>() && !Caller->hasAttr<CUDADeviceAttr>();
1056  bool ShouldCheck = CalleeIsDevice && CallerIsHost;
1057  if (!ShouldCheck || !Capture.isReferenceCapture())
1058  return;
1059  auto DiagKind = SemaDiagnosticBuilder::K_Deferred;
1060  if (Capture.isVariableCapture() && !getLangOpts().HIPStdPar) {
1062  diag::err_capture_bad_target, Callee, SemaRef,
1064  << Capture.getVariable();
1065  } else if (Capture.isThisCapture()) {
1066  // Capture of this pointer is allowed since this pointer may be pointing to
1067  // managed memory which is accessible on both device and host sides. It only
1068  // results in invalid memory access if this pointer points to memory not
1069  // accessible on device side.
1071  diag::warn_maybe_capture_bad_target_this_ptr, Callee,
1073  }
1074 }
1075 
1077  assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
1078  if (Method->hasAttr<CUDAHostAttr>() || Method->hasAttr<CUDADeviceAttr>())
1079  return;
1080  Method->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext()));
1081  Method->addAttr(CUDAHostAttr::CreateImplicit(getASTContext()));
1082 }
1083 
1085  const LookupResult &Previous) {
1086  assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
1087  CUDAFunctionTarget NewTarget = IdentifyTarget(NewFD);
1088  for (NamedDecl *OldND : Previous) {
1089  FunctionDecl *OldFD = OldND->getAsFunction();
1090  if (!OldFD)
1091  continue;
1092 
1093  CUDAFunctionTarget OldTarget = IdentifyTarget(OldFD);
1094  // Don't allow HD and global functions to overload other functions with the
1095  // same signature. We allow overloading based on CUDA attributes so that
1096  // functions can have different implementations on the host and device, but
1097  // HD/global functions "exist" in some sense on both the host and device, so
1098  // should have the same implementation on both sides.
1099  if (NewTarget != OldTarget &&
1100  !SemaRef.IsOverload(NewFD, OldFD, /* UseMemberUsingDeclRules = */ false,
1101  /* ConsiderCudaAttrs = */ false)) {
1102  if ((NewTarget == CUDAFunctionTarget::HostDevice &&
1103  !(getLangOpts().OffloadImplicitHostDeviceTemplates &&
1105  OldTarget == CUDAFunctionTarget::Device)) ||
1106  (OldTarget == CUDAFunctionTarget::HostDevice &&
1107  !(getLangOpts().OffloadImplicitHostDeviceTemplates &&
1109  NewTarget == CUDAFunctionTarget::Device)) ||
1110  (NewTarget == CUDAFunctionTarget::Global) ||
1111  (OldTarget == CUDAFunctionTarget::Global)) {
1112  Diag(NewFD->getLocation(), diag::err_cuda_ovl_target)
1113  << llvm::to_underlying(NewTarget) << NewFD->getDeclName()
1114  << llvm::to_underlying(OldTarget) << OldFD;
1115  Diag(OldFD->getLocation(), diag::note_previous_declaration);
1116  NewFD->setInvalidDecl();
1117  break;
1118  }
1119  if ((NewTarget == CUDAFunctionTarget::Host &&
1120  OldTarget == CUDAFunctionTarget::Device) ||
1121  (NewTarget == CUDAFunctionTarget::Device &&
1122  OldTarget == CUDAFunctionTarget::Host)) {
1123  Diag(NewFD->getLocation(), diag::warn_offload_incompatible_redeclare)
1124  << llvm::to_underlying(NewTarget) << llvm::to_underlying(OldTarget);
1125  Diag(OldFD->getLocation(), diag::note_previous_declaration);
1126  }
1127  }
1128  }
1129 }
1130 
1131 template <typename AttrTy>
1133  const FunctionDecl &TemplateFD) {
1134  if (AttrTy *Attribute = TemplateFD.getAttr<AttrTy>()) {
1135  AttrTy *Clone = Attribute->clone(S.Context);
1136  Clone->setInherited(true);
1137  FD->addAttr(Clone);
1138  }
1139 }
1140 
1142  const FunctionTemplateDecl &TD) {
1143  const FunctionDecl &TemplateFD = *TD.getTemplatedDecl();
1144  copyAttrIfPresent<CUDAGlobalAttr>(SemaRef, FD, TemplateFD);
1145  copyAttrIfPresent<CUDAHostAttr>(SemaRef, FD, TemplateFD);
1146  copyAttrIfPresent<CUDADeviceAttr>(SemaRef, FD, TemplateFD);
1147 }
1148 
1149 std::string SemaCUDA::getConfigureFuncName() const {
1150  if (getLangOpts().OffloadViaLLVM)
1151  return "__llvmPushCallConfiguration";
1152 
1153  if (getLangOpts().HIP)
1154  return getLangOpts().HIPUseNewLaunchAPI ? "__hipPushCallConfiguration"
1155  : "hipConfigureCall";
1156 
1157  // New CUDA kernel launch sequence.
1158  if (CudaFeatureEnabled(getASTContext().getTargetInfo().getSDKVersion(),
1160  return "__cudaPushCallConfiguration";
1161 
1162  // Legacy CUDA kernel configuration call
1163  return "cudaConfigureCall";
1164 }
Defines the clang::ASTContext interface.
const Decl * D
Defines the clang::Expr interface and subclasses for C++ expressions.
llvm::MachO::Target Target
Definition: MachO.h:51
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:427
static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr)
Definition: SemaCUDA.cpp:111
static void copyAttrIfPresent(Sema &S, FunctionDecl *FD, const FunctionDecl &TemplateFD)
Definition: SemaCUDA.cpp:1132
static bool hasImplicitAttr(const FunctionDecl *D)
Definition: SemaCUDA.cpp:381
static bool hasExplicitAttr(const VarDecl *D)
Definition: SemaCUDA.cpp:33
This file declares semantic analysis for CUDA constructs.
SourceLocation Loc
Definition: SemaObjC.cpp:759
StateNode * Previous
FunctionDecl * getcudaConfigureCallDecl()
Definition: ASTContext.h:1476
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.
Definition: ASTContext.h:1204
GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const
llvm::DenseSet< const FunctionDecl * > CUDAImplicitHostDeviceFunUsedByDevice
Keep track of CUDA/HIP implicit host device functions used on device side in device compilation.
Definition: ASTContext.h:1208
Attr - This represents one attribute.
Definition: Attr.h:46
Represents a base class of a C++ class.
Definition: DeclCXX.h:146
Represents a call to a C++ constructor.
Definition: ExprCXX.h:1546
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2539
Represents a C++ base or member initializer.
Definition: DeclCXX.h:2304
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2803
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2064
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition: DeclCXX.h:2190
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
base_class_range bases()
Definition: DeclCXX.h:620
base_class_range vbases()
Definition: DeclCXX.h:637
bool isAbstract() const
Determine whether this class has a pure virtual function.
Definition: DeclCXX.h:1226
bool isDynamicClass() const
Definition: DeclCXX.h:586
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2882
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
Definition: DeclBase.h:2106
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1265
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
bool hasAttrs() const
Definition: DeclBase.h:525
void addAttr(Attr *A)
Definition: DeclBase.cpp:1013
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:600
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition: DeclBase.cpp:154
AttrVec & getAttrs()
Definition: DeclBase.h:531
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition: DeclBase.cpp:249
bool isInvalidDecl() const
Definition: DeclBase.h:595
SourceLocation getLocation() const
Definition: DeclBase.h:446
bool hasAttr() const
Definition: DeclBase.h:584
T * getAttr() const
Definition: DeclBase.h:580
DeclContext * getDeclContext()
Definition: DeclBase.h:455
This represents one expression.
Definition: Expr.h:110
Represents a member of a struct/union/class.
Definition: Decl.h:3031
Represents a function declaration or definition.
Definition: Decl.h:1933
bool hasTrivialBody() const
Returns whether the function has a trivial body that does not require any specific codegen.
Definition: Decl.cpp:3159
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
Definition: Decl.cpp:4044
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition: Decl.cpp:4032
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition: Decl.h:2303
bool isVariadic() const
Whether this function is variadic.
Definition: Decl.cpp:3081
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition: Decl.cpp:4096
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2396
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3682
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Definition: Decl.cpp:3195
Declaration of a template function.
Definition: DeclTemplate.h:957
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
Represents the results of name lookup.
Definition: Lookup.h:46
This represents a decl that may have a name.
Definition: Decl.h:249
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:315
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
A (possibly-)qualified type.
Definition: Type.h:941
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:7833
field_range fields() const
Definition: Decl.h:4352
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5975
RecordDecl * getDecl() const
Definition: Type.h:5985
decl_type * getFirstDecl()
Return the first declaration of this declaration or itself if this is the only declaration.
Definition: Redeclarable.h:217
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
A generic diagnostic builder for errors which may or may not be deferred.
Definition: SemaBase.h:175
@ K_Deferred
Create a deferred diagnostic, which is emitted only if the function it's attached to is codegen'ed.
Definition: SemaBase.h:189
@ K_ImmediateWithCallStack
Emit the diagnostic immediately, and, if it's a warning or error, also emit a call stack showing how ...
Definition: SemaBase.h:185
@ K_Immediate
Emit the diagnostic immediately (i.e., behave like Sema::Diag()).
Definition: SemaBase.h:181
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:64
@ CudaDevice
CUDA specific diagnostics.
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
const LangOptions & getLangOpts() const
Definition: SemaBase.cpp:11
DiagnosticsEngine & getDiagnostics() const
Definition: SemaBase.cpp:10
void PushForceHostDevice()
Increments our count of the number of times we've seen a pragma forcing functions to be host device.
Definition: SemaCUDA.cpp:41
void checkAllowedInitializer(VarDecl *VD)
Definition: SemaCUDA.cpp:733
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:781
std::string getConfigureFuncName() const
Returns the name of the launch configuration function.
Definition: SemaCUDA.cpp:1149
bool PopForceHostDevice()
Decrements our count of the number of times we've seen a pragma forcing functions to be host device.
Definition: SemaCUDA.cpp:46
CUDAFunctionTarget IdentifyTarget(const FunctionDecl *D, bool IgnoreImplicitHDAttr=false)
Determines whether the given function is a CUDA device/host/kernel/etc.
Definition: SemaCUDA.cpp:136
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:815
ExprResult ActOnExecConfigExpr(Scope *S, SourceLocation LLLLoc, MultiExprArg ExecConfig, SourceLocation GGGLoc)
Definition: SemaCUDA.cpp:54
bool isEmptyConstructor(SourceLocation Loc, CXXConstructorDecl *CD)
Definition: SemaCUDA.cpp:587
bool isEmptyDestructor(SourceLocation Loc, CXXDestructorDecl *CD)
Definition: SemaCUDA.cpp:625
void checkTargetOverload(FunctionDecl *NewFD, const LookupResult &Previous)
Check whether NewFD is a valid overload for CUDA.
Definition: SemaCUDA.cpp:1084
CUDAFunctionTarget CurrentTarget()
Gets the CUDA target for the current context.
Definition: SemaCUDA.h:152
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:927
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:447
struct clang::SemaCUDA::CUDATargetContext CurCUDATargetCtx
CUDATargetContextKind
Defines kinds of CUDA global host/device context where a function may be called.
Definition: SemaCUDA.h:129
@ CTCK_InitGlobalVar
Unknown context.
Definition: SemaCUDA.h:131
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:894
llvm::DenseSet< FunctionDeclAndLoc > LocsWithCUDACallDiags
FunctionDecls and SourceLocations for which CheckCall has emitted a (maybe deferred) "bad call" diagn...
Definition: SemaCUDA.h:73
bool CheckCall(SourceLocation Loc, FunctionDecl *Callee)
Check whether we're allowed to call Callee from the current context.
Definition: SemaCUDA.cpp:959
void inheritTargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD)
Copies target attributes from the template TD to the function FD.
Definition: SemaCUDA.cpp:1141
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:395
static bool isImplicitHostDeviceFunction(const FunctionDecl *D)
Definition: SemaCUDA.cpp:389
void CheckLambdaCapture(CXXMethodDecl *D, const sema::Capture &Capture)
Definition: SemaCUDA.cpp:1030
void MaybeAddConstantAttr(VarDecl *VD)
May add implicit CUDAConstantAttr attribute to VD, depending on VD and current compilation settings.
Definition: SemaCUDA.cpp:880
SemaCUDA(Sema &S)
Definition: SemaCUDA.cpp:31
void SetLambdaAttrs(CXXMethodDecl *Method)
Set device or host device attributes on the given lambda operator() method.
Definition: SemaCUDA.cpp:1076
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:253
@ CVT_Host
Emitted on device side with a shadow variable on host side.
Definition: SemaCUDA.h:120
@ CVT_Both
Emitted on host side only.
Definition: SemaCUDA.h:121
@ CVT_Unified
Emitted on both sides with different addresses.
Definition: SemaCUDA.h:122
A RAII object to temporarily push a declaration context.
Definition: Sema.h:3037
SpecialMemberOverloadResult - The overloading result for a special member function.
Definition: Sema.h:8988
CXXMethodDecl * getMethod() const
Definition: Sema.h:9000
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:493
bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs=true)
bool IsLastErrorImmediate
Is the last error level diagnostic immediate.
Definition: Sema.h:1025
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
Definition: Sema.cpp:1609
ASTContext & Context
Definition: Sema.h:962
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
Definition: SemaExpr.cpp:6474
const LangOptions & getLangOpts() const
Definition: Sema.h:553
const ExpressionEvaluationContextRecord & currentEvaluationContext() const
Definition: Sema.h:6475
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20348
SourceManager & getSourceManager() const
Definition: Sema.h:558
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, bool Recursive=false, bool DefinitionRequired=false, bool AtEndOfTU=false)
Instantiate the definition of the given function from its template.
ASTContext & getASTContext() const
Definition: Sema.h:560
SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMemberKind SM, bool ConstArg, bool VolatileArg, bool RValueThis, bool ConstThis, bool VolatileThis)
void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, bool MightBeOdrUse=true)
Mark a function referenced, and check whether it is odr-used (C++ [basic.def.odr]p2,...
Definition: SemaExpr.cpp:17928
Encodes a location in the source.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
bool isUnion() const
Definition: Decl.h:3768
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1882
bool isReferenceType() const
Definition: Type.h:8031
bool isCUDADeviceBuiltinSurfaceType() const
Check if the type is the CUDA device builtin surface type.
Definition: Type.cpp:5005
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2701
bool isCUDADeviceBuiltinTextureType() const
Check if the type is the CUDA device builtin texture type.
Definition: Type.cpp:5012
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8568
Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration ...
Definition: DeclCXX.h:3324
QualType getType() const
Definition: Decl.h:679
Represents a variable declaration or definition.
Definition: Decl.h:880
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition: Decl.h:1511
bool hasInit() const
Definition: Decl.cpp:2384
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition: Decl.h:1232
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1175
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
Definition: Decl.h:1291
const Expr * getInit() const
Definition: Decl.h:1317
bool isVariableCapture() const
Definition: ScopeInfo.h:650
SourceLocation getLocation() const
Retrieve the location at which this variable was captured.
Definition: ScopeInfo.h:686
bool isThisCapture() const
Definition: ScopeInfo.h:649
bool isReferenceCapture() const
Definition: ScopeInfo.h:655
ValueDecl * getVariable() const
Definition: ScopeInfo.h:675
Defines the clang::TargetInfo interface.
bool Init(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1745
The JSON file list parser is used to communicate input to InstallAPI.
@ GVA_StrongExternal
Definition: Linkage.h:76
CUDAFunctionTarget
Definition: Cuda.h:140
bool CudaFeatureEnabled(llvm::VersionTuple, CudaFeature)
Definition: Cuda.cpp:251
ExprResult ExprError()
Definition: Ownership.h:264
CXXSpecialMemberKind
Kinds of C++ special members.
Definition: Sema.h:403
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:139
SemaCUDA::CUDATargetContext SavedCtx
Definition: SemaCUDA.h:145
CUDATargetContextRAII(SemaCUDA &S_, SemaCUDA::CUDATargetContextKind K, Decl *D)
Definition: SemaCUDA.cpp:118
CUDATargetContextKind Kind
Definition: SemaCUDA.h:139