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