1 //===--- SemaCUDA.cpp - Semantic Analysis for CUDA constructs -------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// \brief This file implements semantic analysis for CUDA constructs.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/ExprCXX.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "clang/Sema/Lookup.h"
19 #include "clang/Sema/Sema.h"
20 #include "clang/Sema/SemaDiagnostic.h"
21 #include "clang/Sema/Template.h"
22 #include "llvm/ADT/Optional.h"
23 #include "llvm/ADT/SmallVector.h"
24 using namespace clang;
25 
26 void Sema::PushForceCUDAHostDevice() {
27   assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
28   ForceCUDAHostDeviceDepth++;
29 }
30 
31 bool Sema::PopForceCUDAHostDevice() {
32   assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
33   if (ForceCUDAHostDeviceDepth == 0)
34     return false;
35   ForceCUDAHostDeviceDepth--;
36   return true;
37 }
38 
39 ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
40                                          MultiExprArg ExecConfig,
41                                          SourceLocation GGGLoc) {
42   FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl();
43   if (!ConfigDecl)
44     return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)
45                      << "cudaConfigureCall");
46   QualType ConfigQTy = ConfigDecl->getType();
47 
48   DeclRefExpr *ConfigDR = new (Context)
49       DeclRefExpr(ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc);
50   MarkFunctionReferenced(LLLLoc, ConfigDecl);
51 
52   return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr,
53                        /*IsExecConfig=*/true);
54 }
55 
56 /// IdentifyCUDATarget - Determine the CUDA compilation target for this function
57 Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
58   if (D->hasAttr<CUDAInvalidTargetAttr>())
59     return CFT_InvalidTarget;
60 
61   if (D->hasAttr<CUDAGlobalAttr>())
62     return CFT_Global;
63 
64   if (D->hasAttr<CUDADeviceAttr>()) {
65     if (D->hasAttr<CUDAHostAttr>())
66       return CFT_HostDevice;
67     return CFT_Device;
68   } else if (D->hasAttr<CUDAHostAttr>()) {
69     return CFT_Host;
70   } else if (D->isImplicit()) {
71     // Some implicit declarations (like intrinsic functions) are not marked.
72     // Set the most lenient target on them for maximal flexibility.
73     return CFT_HostDevice;
74   }
75 
76   return CFT_Host;
77 }
78 
79 // * CUDA Call preference table
80 //
81 // F - from,
82 // T - to
83 // Ph - preference in host mode
84 // Pd - preference in device mode
85 // H  - handled in (x)
86 // Preferences: N:native, SS:same side, HD:host-device, WS:wrong side, --:never.
87 //
88 // | F  | T  | Ph  | Pd  |  H  |
89 // |----+----+-----+-----+-----+
90 // | d  | d  | N   | N   | (c) |
91 // | d  | g  | --  | --  | (a) |
92 // | d  | h  | --  | --  | (e) |
93 // | d  | hd | HD  | HD  | (b) |
94 // | g  | d  | N   | N   | (c) |
95 // | g  | g  | --  | --  | (a) |
96 // | g  | h  | --  | --  | (e) |
97 // | g  | hd | HD  | HD  | (b) |
98 // | h  | d  | --  | --  | (e) |
99 // | h  | g  | N   | N   | (c) |
100 // | h  | h  | N   | N   | (c) |
101 // | h  | hd | HD  | HD  | (b) |
102 // | hd | d  | WS  | SS  | (d) |
103 // | hd | g  | SS  | --  |(d/a)|
104 // | hd | h  | SS  | WS  | (d) |
105 // | hd | hd | HD  | HD  | (b) |
106 
107 Sema::CUDAFunctionPreference
108 Sema::IdentifyCUDAPreference(const FunctionDecl *Caller,
109                              const FunctionDecl *Callee) {
110   assert(Callee && "Callee must be valid.");
111   CUDAFunctionTarget CalleeTarget = IdentifyCUDATarget(Callee);
112   CUDAFunctionTarget CallerTarget =
113       (Caller != nullptr) ? IdentifyCUDATarget(Caller) : Sema::CFT_Host;
114 
115   // If one of the targets is invalid, the check always fails, no matter what
116   // the other target is.
117   if (CallerTarget == CFT_InvalidTarget || CalleeTarget == CFT_InvalidTarget)
118     return CFP_Never;
119 
120   // (a) Can't call global from some contexts until we support CUDA's
121   // dynamic parallelism.
122   if (CalleeTarget == CFT_Global &&
123       (CallerTarget == CFT_Global || CallerTarget == CFT_Device))
124     return CFP_Never;
125 
126   // (b) Calling HostDevice is OK for everyone.
127   if (CalleeTarget == CFT_HostDevice)
128     return CFP_HostDevice;
129 
130   // (c) Best case scenarios
131   if (CalleeTarget == CallerTarget ||
132       (CallerTarget == CFT_Host && CalleeTarget == CFT_Global) ||
133       (CallerTarget == CFT_Global && CalleeTarget == CFT_Device))
134     return CFP_Native;
135 
136   // (d) HostDevice behavior depends on compilation mode.
137   if (CallerTarget == CFT_HostDevice) {
138     // It's OK to call a compilation-mode matching function from an HD one.
139     if ((getLangOpts().CUDAIsDevice && CalleeTarget == CFT_Device) ||
140         (!getLangOpts().CUDAIsDevice &&
141          (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global)))
142       return CFP_SameSide;
143 
144     // Calls from HD to non-mode-matching functions (i.e., to host functions
145     // when compiling in device mode or to device functions when compiling in
146     // host mode) are allowed at the sema level, but eventually rejected if
147     // they're ever codegened.  TODO: Reject said calls earlier.
148     return CFP_WrongSide;
149   }
150 
151   // (e) Calling across device/host boundary is not something you should do.
152   if ((CallerTarget == CFT_Host && CalleeTarget == CFT_Device) ||
153       (CallerTarget == CFT_Device && CalleeTarget == CFT_Host) ||
154       (CallerTarget == CFT_Global && CalleeTarget == CFT_Host))
155     return CFP_Never;
156 
157   llvm_unreachable("All cases should've been handled by now.");
158 }
159 
160 void Sema::EraseUnwantedCUDAMatches(
161     const FunctionDecl *Caller,
162     SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) {
163   if (Matches.size() <= 1)
164     return;
165 
166   using Pair = std::pair<DeclAccessPair, FunctionDecl*>;
167 
168   // Gets the CUDA function preference for a call from Caller to Match.
169   auto GetCFP = [&](const Pair &Match) {
170     return IdentifyCUDAPreference(Caller, Match.second);
171   };
172 
173   // Find the best call preference among the functions in Matches.
174   CUDAFunctionPreference BestCFP = GetCFP(*std::max_element(
175       Matches.begin(), Matches.end(),
176       [&](const Pair &M1, const Pair &M2) { return GetCFP(M1) < GetCFP(M2); }));
177 
178   // Erase all functions with lower priority.
179   Matches.erase(
180       llvm::remove_if(
181           Matches, [&](const Pair &Match) { return GetCFP(Match) < BestCFP; }),
182       Matches.end());
183 }
184 
185 /// When an implicitly-declared special member has to invoke more than one
186 /// base/field special member, conflicts may occur in the targets of these
187 /// members. For example, if one base's member __host__ and another's is
188 /// __device__, it's a conflict.
189 /// This function figures out if the given targets \param Target1 and
190 /// \param Target2 conflict, and if they do not it fills in
191 /// \param ResolvedTarget with a target that resolves for both calls.
192 /// \return true if there's a conflict, false otherwise.
193 static bool
194 resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1,
195                                 Sema::CUDAFunctionTarget Target2,
196                                 Sema::CUDAFunctionTarget *ResolvedTarget) {
197   // Only free functions and static member functions may be global.
198   assert(Target1 != Sema::CFT_Global);
199   assert(Target2 != Sema::CFT_Global);
200 
201   if (Target1 == Sema::CFT_HostDevice) {
202     *ResolvedTarget = Target2;
203   } else if (Target2 == Sema::CFT_HostDevice) {
204     *ResolvedTarget = Target1;
205   } else if (Target1 != Target2) {
206     return true;
207   } else {
208     *ResolvedTarget = Target1;
209   }
210 
211   return false;
212 }
213 
214 bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
215                                                    CXXSpecialMember CSM,
216                                                    CXXMethodDecl *MemberDecl,
217                                                    bool ConstRHS,
218                                                    bool Diagnose) {
219   llvm::Optional<CUDAFunctionTarget> InferredTarget;
220 
221   // We're going to invoke special member lookup; mark that these special
222   // members are called from this one, and not from its caller.
223   ContextRAII MethodContext(*this, MemberDecl);
224 
225   // Look for special members in base classes that should be invoked from here.
226   // Infer the target of this member base on the ones it should call.
227   // Skip direct and indirect virtual bases for abstract classes.
228   llvm::SmallVector<const CXXBaseSpecifier *, 16> Bases;
229   for (const auto &B : ClassDecl->bases()) {
230     if (!B.isVirtual()) {
231       Bases.push_back(&B);
232     }
233   }
234 
235   if (!ClassDecl->isAbstract()) {
236     for (const auto &VB : ClassDecl->vbases()) {
237       Bases.push_back(&VB);
238     }
239   }
240 
241   for (const auto *B : Bases) {
242     const RecordType *BaseType = B->getType()->getAs<RecordType>();
243     if (!BaseType) {
244       continue;
245     }
246 
247     CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
248     Sema::SpecialMemberOverloadResult *SMOR =
249         LookupSpecialMember(BaseClassDecl, CSM,
250                             /* ConstArg */ ConstRHS,
251                             /* VolatileArg */ false,
252                             /* RValueThis */ false,
253                             /* ConstThis */ false,
254                             /* VolatileThis */ false);
255 
256     if (!SMOR || !SMOR->getMethod()) {
257       continue;
258     }
259 
260     CUDAFunctionTarget BaseMethodTarget = IdentifyCUDATarget(SMOR->getMethod());
261     if (!InferredTarget.hasValue()) {
262       InferredTarget = BaseMethodTarget;
263     } else {
264       bool ResolutionError = resolveCalleeCUDATargetConflict(
265           InferredTarget.getValue(), BaseMethodTarget,
266           InferredTarget.getPointer());
267       if (ResolutionError) {
268         if (Diagnose) {
269           Diag(ClassDecl->getLocation(),
270                diag::note_implicit_member_target_infer_collision)
271               << (unsigned)CSM << InferredTarget.getValue() << BaseMethodTarget;
272         }
273         MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context));
274         return true;
275       }
276     }
277   }
278 
279   // Same as for bases, but now for special members of fields.
280   for (const auto *F : ClassDecl->fields()) {
281     if (F->isInvalidDecl()) {
282       continue;
283     }
284 
285     const RecordType *FieldType =
286         Context.getBaseElementType(F->getType())->getAs<RecordType>();
287     if (!FieldType) {
288       continue;
289     }
290 
291     CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(FieldType->getDecl());
292     Sema::SpecialMemberOverloadResult *SMOR =
293         LookupSpecialMember(FieldRecDecl, CSM,
294                             /* ConstArg */ ConstRHS && !F->isMutable(),
295                             /* VolatileArg */ false,
296                             /* RValueThis */ false,
297                             /* ConstThis */ false,
298                             /* VolatileThis */ false);
299 
300     if (!SMOR || !SMOR->getMethod()) {
301       continue;
302     }
303 
304     CUDAFunctionTarget FieldMethodTarget =
305         IdentifyCUDATarget(SMOR->getMethod());
306     if (!InferredTarget.hasValue()) {
307       InferredTarget = FieldMethodTarget;
308     } else {
309       bool ResolutionError = resolveCalleeCUDATargetConflict(
310           InferredTarget.getValue(), FieldMethodTarget,
311           InferredTarget.getPointer());
312       if (ResolutionError) {
313         if (Diagnose) {
314           Diag(ClassDecl->getLocation(),
315                diag::note_implicit_member_target_infer_collision)
316               << (unsigned)CSM << InferredTarget.getValue()
317               << FieldMethodTarget;
318         }
319         MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context));
320         return true;
321       }
322     }
323   }
324 
325   if (InferredTarget.hasValue()) {
326     if (InferredTarget.getValue() == CFT_Device) {
327       MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
328     } else if (InferredTarget.getValue() == CFT_Host) {
329       MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
330     } else {
331       MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
332       MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
333     }
334   } else {
335     // If no target was inferred, mark this member as __host__ __device__;
336     // it's the least restrictive option that can be invoked from any target.
337     MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
338     MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
339   }
340 
341   return false;
342 }
343 
344 bool Sema::isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD) {
345   if (!CD->isDefined() && CD->isTemplateInstantiation())
346     InstantiateFunctionDefinition(Loc, CD->getFirstDecl());
347 
348   // (E.2.3.1, CUDA 7.5) A constructor for a class type is considered
349   // empty at a point in the translation unit, if it is either a
350   // trivial constructor
351   if (CD->isTrivial())
352     return true;
353 
354   // ... or it satisfies all of the following conditions:
355   // The constructor function has been defined.
356   // The constructor function has no parameters,
357   // and the function body is an empty compound statement.
358   if (!(CD->hasTrivialBody() && CD->getNumParams() == 0))
359     return false;
360 
361   // Its class has no virtual functions and no virtual base classes.
362   if (CD->getParent()->isDynamicClass())
363     return false;
364 
365   // The only form of initializer allowed is an empty constructor.
366   // This will recursively check all base classes and member initializers
367   if (!llvm::all_of(CD->inits(), [&](const CXXCtorInitializer *CI) {
368         if (const CXXConstructExpr *CE =
369                 dyn_cast<CXXConstructExpr>(CI->getInit()))
370           return isEmptyCudaConstructor(Loc, CE->getConstructor());
371         return false;
372       }))
373     return false;
374 
375   return true;
376 }
377 
378 bool Sema::isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *DD) {
379   // No destructor -> no problem.
380   if (!DD)
381     return true;
382 
383   if (!DD->isDefined() && DD->isTemplateInstantiation())
384     InstantiateFunctionDefinition(Loc, DD->getFirstDecl());
385 
386   // (E.2.3.1, CUDA 7.5) A destructor for a class type is considered
387   // empty at a point in the translation unit, if it is either a
388   // trivial constructor
389   if (DD->isTrivial())
390     return true;
391 
392   // ... or it satisfies all of the following conditions:
393   // The destructor function has been defined.
394   // and the function body is an empty compound statement.
395   if (!DD->hasTrivialBody())
396     return false;
397 
398   const CXXRecordDecl *ClassDecl = DD->getParent();
399 
400   // Its class has no virtual functions and no virtual base classes.
401   if (ClassDecl->isDynamicClass())
402     return false;
403 
404   // Only empty destructors are allowed. This will recursively check
405   // destructors for all base classes...
406   if (!llvm::all_of(ClassDecl->bases(), [&](const CXXBaseSpecifier &BS) {
407         if (CXXRecordDecl *RD = BS.getType()->getAsCXXRecordDecl())
408           return isEmptyCudaDestructor(Loc, RD->getDestructor());
409         return true;
410       }))
411     return false;
412 
413   // ... and member fields.
414   if (!llvm::all_of(ClassDecl->fields(), [&](const FieldDecl *Field) {
415         if (CXXRecordDecl *RD = Field->getType()
416                                     ->getBaseElementTypeUnsafe()
417                                     ->getAsCXXRecordDecl())
418           return isEmptyCudaDestructor(Loc, RD->getDestructor());
419         return true;
420       }))
421     return false;
422 
423   return true;
424 }
425 
426 // With -fcuda-host-device-constexpr, an unattributed constexpr function is
427 // treated as implicitly __host__ __device__, unless:
428 //  * it is a variadic function (device-side variadic functions are not
429 //    allowed), or
430 //  * a __device__ function with this signature was already declared, in which
431 //    case in which case we output an error, unless the __device__ decl is in a
432 //    system header, in which case we leave the constexpr function unattributed.
433 //
434 // In addition, all function decls are treated as __host__ __device__ when
435 // ForceCUDAHostDeviceDepth > 0 (corresponding to code within a
436 //   #pragma clang force_cuda_host_device_begin/end
437 // pair).
438 void Sema::maybeAddCUDAHostDeviceAttrs(Scope *S, FunctionDecl *NewD,
439                                        const LookupResult &Previous) {
440   assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
441 
442   if (ForceCUDAHostDeviceDepth > 0) {
443     if (!NewD->hasAttr<CUDAHostAttr>())
444       NewD->addAttr(CUDAHostAttr::CreateImplicit(Context));
445     if (!NewD->hasAttr<CUDADeviceAttr>())
446       NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context));
447     return;
448   }
449 
450   if (!getLangOpts().CUDAHostDeviceConstexpr || !NewD->isConstexpr() ||
451       NewD->isVariadic() || NewD->hasAttr<CUDAHostAttr>() ||
452       NewD->hasAttr<CUDADeviceAttr>() || NewD->hasAttr<CUDAGlobalAttr>())
453     return;
454 
455   // Is D a __device__ function with the same signature as NewD, ignoring CUDA
456   // attributes?
457   auto IsMatchingDeviceFn = [&](NamedDecl *D) {
458     if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(D))
459       D = Using->getTargetDecl();
460     FunctionDecl *OldD = D->getAsFunction();
461     return OldD && OldD->hasAttr<CUDADeviceAttr>() &&
462            !OldD->hasAttr<CUDAHostAttr>() &&
463            !IsOverload(NewD, OldD, /* UseMemberUsingDeclRules = */ false,
464                        /* ConsiderCudaAttrs = */ false);
465   };
466   auto It = llvm::find_if(Previous, IsMatchingDeviceFn);
467   if (It != Previous.end()) {
468     // We found a __device__ function with the same name and signature as NewD
469     // (ignoring CUDA attrs).  This is an error unless that function is defined
470     // in a system header, in which case we simply return without making NewD
471     // host+device.
472     NamedDecl *Match = *It;
473     if (!getSourceManager().isInSystemHeader(Match->getLocation())) {
474       Diag(NewD->getLocation(),
475            diag::err_cuda_unattributed_constexpr_cannot_overload_device)
476           << NewD->getName();
477       Diag(Match->getLocation(),
478            diag::note_cuda_conflicting_device_function_declared_here);
479     }
480     return;
481   }
482 
483   NewD->addAttr(CUDAHostAttr::CreateImplicit(Context));
484   NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context));
485 }
486 
487 bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) {
488   assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
489   assert(Callee && "Callee may not be null.");
490   FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext);
491   if (!Caller)
492     return true;
493 
494   Sema::CUDAFunctionPreference Pref = IdentifyCUDAPreference(Caller, Callee);
495   if (Pref == Sema::CFP_Never) {
496     Diag(Loc, diag::err_ref_bad_target) << IdentifyCUDATarget(Callee) << Callee
497                                         << IdentifyCUDATarget(Caller);
498     Diag(Callee->getLocation(), diag::note_previous_decl) << Callee;
499     return false;
500   }
501 
502   // Insert into LocsWithCUDADeferredDiags to avoid emitting duplicate deferred
503   // diagnostics for the same location.  Duplicate deferred diags are otherwise
504   // tricky to avoid, because, unlike with regular errors, sema checking
505   // proceeds unhindered when we omit a deferred diagnostic.
506   if (Pref == Sema::CFP_WrongSide &&
507       LocsWithCUDACallDeferredDiags.insert(Loc.getRawEncoding()).second) {
508     // We have to do this odd dance to create our PartialDiagnostic because we
509     // want its storage to be allocated with operator new, not in an arena.
510     PartialDiagnostic ErrPD{PartialDiagnostic::NullDiagnostic()};
511     ErrPD.Reset(diag::err_ref_bad_target);
512     ErrPD << IdentifyCUDATarget(Callee) << Callee << IdentifyCUDATarget(Caller);
513     Caller->addDeferredDiag({Loc, std::move(ErrPD)});
514 
515     PartialDiagnostic NotePD{PartialDiagnostic::NullDiagnostic()};
516     NotePD.Reset(diag::note_previous_decl);
517     NotePD << Callee;
518     Caller->addDeferredDiag({Callee->getLocation(), std::move(NotePD)});
519 
520     // This is not immediately an error, so return true.  The deferred errors
521     // will be emitted if and when Caller is codegen'ed.
522     return true;
523   }
524   return true;
525 }
526 
527 bool Sema::CheckCUDAExceptionExpr(SourceLocation Loc, StringRef ExprTy) {
528   assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
529   FunctionDecl *CurFn = dyn_cast<FunctionDecl>(CurContext);
530   if (!CurFn)
531     return true;
532   CUDAFunctionTarget Target = IdentifyCUDATarget(CurFn);
533 
534   // Raise an error immediately if this is a __global__ or __device__ function.
535   // If it's a __host__ __device__ function, enqueue a deferred error which will
536   // be emitted if the function is codegen'ed for device.
537   if (Target == CFT_Global || Target == CFT_Device) {
538     Diag(Loc, diag::err_cuda_device_exceptions) << ExprTy << Target << CurFn;
539     return false;
540   }
541   if (Target == CFT_HostDevice && getLangOpts().CUDAIsDevice) {
542     PartialDiagnostic ErrPD{PartialDiagnostic::NullDiagnostic()};
543     ErrPD.Reset(diag::err_cuda_device_exceptions);
544     ErrPD << ExprTy << Target << CurFn;
545     CurFn->addDeferredDiag({Loc, std::move(ErrPD)});
546     return false;
547   }
548   return true;
549 }
550 
551 bool Sema::CheckCUDAVLA(SourceLocation Loc) {
552   assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
553   FunctionDecl *CurFn = dyn_cast<FunctionDecl>(CurContext);
554   if (!CurFn)
555     return true;
556   CUDAFunctionTarget Target = IdentifyCUDATarget(CurFn);
557   if (Target == CFT_Global || Target == CFT_Device) {
558     Diag(Loc, diag::err_cuda_vla) << Target;
559     return false;
560   }
561   if (Target == CFT_HostDevice && getLangOpts().CUDAIsDevice) {
562     PartialDiagnostic ErrPD{PartialDiagnostic::NullDiagnostic()};
563     ErrPD.Reset(diag::err_cuda_vla);
564     ErrPD << Target;
565     CurFn->addDeferredDiag({Loc, std::move(ErrPD)});
566     return false;
567   }
568   return true;
569 }
570 
571 void Sema::CUDASetLambdaAttrs(CXXMethodDecl *Method) {
572   assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
573   if (Method->hasAttr<CUDAHostAttr>() || Method->hasAttr<CUDADeviceAttr>())
574     return;
575   FunctionDecl *CurFn = dyn_cast<FunctionDecl>(CurContext);
576   if (!CurFn)
577     return;
578   CUDAFunctionTarget Target = IdentifyCUDATarget(CurFn);
579   if (Target == CFT_Global || Target == CFT_Device) {
580     Method->addAttr(CUDADeviceAttr::CreateImplicit(Context));
581   } else if (Target == CFT_HostDevice) {
582     Method->addAttr(CUDADeviceAttr::CreateImplicit(Context));
583     Method->addAttr(CUDAHostAttr::CreateImplicit(Context));
584   }
585 }
586