blob: 9e101d16da9b8b25d7d6972a9f3e73866fb993d9 [file] [log] [blame]
Eli Bendersky7325e562014-09-03 15:27:03 +00001//===--- 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
Eli Bendersky7325e562014-09-03 15:27:03 +000014#include "clang/AST/ASTContext.h"
15#include "clang/AST/Decl.h"
Artem Belevich97c01c32016-02-02 22:29:48 +000016#include "clang/AST/ExprCXX.h"
Reid Klecknerbbc01782014-12-03 21:53:36 +000017#include "clang/Lex/Preprocessor.h"
Justin Lebarba122ab2016-03-30 23:30:21 +000018#include "clang/Sema/Lookup.h"
19#include "clang/Sema/Sema.h"
Eli Bendersky7325e562014-09-03 15:27:03 +000020#include "clang/Sema/SemaDiagnostic.h"
Justin Lebarba122ab2016-03-30 23:30:21 +000021#include "clang/Sema/Template.h"
Eli Bendersky9a220fc2014-09-29 20:38:29 +000022#include "llvm/ADT/Optional.h"
23#include "llvm/ADT/SmallVector.h"
Eli Bendersky7325e562014-09-03 15:27:03 +000024using namespace clang;
25
Justin Lebar67a78a62016-10-08 22:15:58 +000026void Sema::PushForceCUDAHostDevice() {
27 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
28 ForceCUDAHostDeviceDepth++;
29}
30
31bool 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
Eli Bendersky7325e562014-09-03 15:27:03 +000039ExprResult 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
57Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
Eli Bendersky9a220fc2014-09-29 20:38:29 +000058 if (D->hasAttr<CUDAInvalidTargetAttr>())
59 return CFT_InvalidTarget;
Eli Bendersky7325e562014-09-03 15:27:03 +000060
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;
Eli Benderskyf2787a02014-09-30 17:38:34 +000068 } 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;
Eli Bendersky7325e562014-09-03 15:27:03 +000074 }
75
76 return CFT_Host;
77}
78
Artem Belevich94a55e82015-09-22 17:22:59 +000079// * 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)
Justin Lebar39186472016-03-29 16:24:22 +000086// Preferences: N:native, SS:same side, HD:host-device, WS:wrong side, --:never.
Artem Belevich94a55e82015-09-22 17:22:59 +000087//
Artem Belevich18609102016-02-12 18:29:18 +000088// | 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) |
Artem Belevich94a55e82015-09-22 17:22:59 +0000106
107Sema::CUDAFunctionPreference
108Sema::IdentifyCUDAPreference(const FunctionDecl *Caller,
109 const FunctionDecl *Callee) {
Artem Belevich94a55e82015-09-22 17:22:59 +0000110 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
Artem Belevich18609102016-02-12 18:29:18 +0000127 // (b) Calling HostDevice is OK for everyone.
128 if (CalleeTarget == CFT_HostDevice)
129 return CFP_HostDevice;
130
131 // (c) Best case scenarios
Artem Belevich94a55e82015-09-22 17:22:59 +0000132 if (CalleeTarget == CallerTarget ||
133 (CallerTarget == CFT_Host && CalleeTarget == CFT_Global) ||
134 (CallerTarget == CFT_Global && CalleeTarget == CFT_Device))
Artem Belevich18609102016-02-12 18:29:18 +0000135 return CFP_Native;
Artem Belevich94a55e82015-09-22 17:22:59 +0000136
137 // (d) HostDevice behavior depends on compilation mode.
138 if (CallerTarget == CFT_HostDevice) {
Artem Belevich18609102016-02-12 18:29:18 +0000139 // 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
Justin Lebar25c4a812016-03-29 16:24:16 +0000145 // 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;
Artem Belevich94a55e82015-09-22 17:22:59 +0000150 }
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))
Artem Belevich18609102016-02-12 18:29:18 +0000156 return CFP_Never;
Artem Belevich94a55e82015-09-22 17:22:59 +0000157
158 llvm_unreachable("All cases should've been handled by now.");
159}
160
Richard Smithf75dcbe2016-10-11 00:21:10 +0000161void Sema::EraseUnwantedCUDAMatches(
162 const FunctionDecl *Caller,
163 SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) {
Artem Belevich94a55e82015-09-22 17:22:59 +0000164 if (Matches.size() <= 1)
165 return;
166
Richard Smithf75dcbe2016-10-11 00:21:10 +0000167 using Pair = std::pair<DeclAccessPair, FunctionDecl*>;
168
Justin Lebare6a2cc12016-03-22 00:09:25 +0000169 // Gets the CUDA function preference for a call from Caller to Match.
Richard Smithf75dcbe2016-10-11 00:21:10 +0000170 auto GetCFP = [&](const Pair &Match) {
171 return IdentifyCUDAPreference(Caller, Match.second);
Justin Lebare6a2cc12016-03-22 00:09:25 +0000172 };
173
Artem Belevich94a55e82015-09-22 17:22:59 +0000174 // Find the best call preference among the functions in Matches.
Richard Smithf75dcbe2016-10-11 00:21:10 +0000175 CUDAFunctionPreference BestCFP = GetCFP(*std::max_element(
Justin Lebare6a2cc12016-03-22 00:09:25 +0000176 Matches.begin(), Matches.end(),
Richard Smithf75dcbe2016-10-11 00:21:10 +0000177 [&](const Pair &M1, const Pair &M2) { return GetCFP(M1) < GetCFP(M2); }));
Artem Belevich94a55e82015-09-22 17:22:59 +0000178
179 // Erase all functions with lower priority.
Justin Lebare71c08f2016-07-12 23:23:13 +0000180 Matches.erase(
Richard Smithf75dcbe2016-10-11 00:21:10 +0000181 llvm::remove_if(
182 Matches, [&](const Pair &Match) { return GetCFP(Match) < BestCFP; }),
Justin Lebare71c08f2016-07-12 23:23:13 +0000183 Matches.end());
Artem Belevich94a55e82015-09-22 17:22:59 +0000184}
185
Eli Bendersky9a220fc2014-09-29 20:38:29 +0000186/// 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.
194static bool
195resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1,
196 Sema::CUDAFunctionTarget Target2,
197 Sema::CUDAFunctionTarget *ResolvedTarget) {
Justin Lebarc66a1062016-01-20 00:26:57 +0000198 // Only free functions and static member functions may be global.
199 assert(Target1 != Sema::CFT_Global);
200 assert(Target2 != Sema::CFT_Global);
Eli Bendersky9a220fc2014-09-29 20:38:29 +0000201
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
215bool 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}
Artem Belevich97c01c32016-02-02 22:29:48 +0000344
345bool 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.
Artem Belevich3650bbe2016-05-19 20:13:53 +0000367 // This will recursively check all base classes and member initializers
Artem Belevich97c01c32016-02-02 22:29:48 +0000368 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}
Justin Lebarba122ab2016-03-30 23:30:21 +0000378
Artem Belevich3650bbe2016-05-19 20:13:53 +0000379bool 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
Justin Lebarba122ab2016-03-30 23:30:21 +0000427// 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.
Justin Lebar67a78a62016-10-08 22:15:58 +0000434//
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).
Justin Lebarba122ab2016-03-30 23:30:21 +0000439void Sema::maybeAddCUDAHostDeviceAttrs(Scope *S, FunctionDecl *NewD,
440 const LookupResult &Previous) {
Justin Lebar9d4ed262016-09-30 23:57:38 +0000441 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
Justin Lebar67a78a62016-10-08 22:15:58 +0000442
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
Justin Lebarba122ab2016-03-30 23:30:21 +0000451 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}
Justin Lebar18e2d822016-08-15 23:00:49 +0000487
488bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) {
Justin Lebar9d4ed262016-09-30 23:57:38 +0000489 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
Justin Lebar18e2d822016-08-15 23:00:49 +0000490 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 }
Justin Lebar9fdb46e2016-10-08 01:07:11 +0000502
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) {
Justin Lebar18e2d822016-08-15 23:00:49 +0000509 // 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.
Justin Lebar26bb3112016-08-16 00:48:21 +0000511 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
Justin Lebar18e2d822016-08-15 23:00:49 +0000521 // 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}
Justin Lebar2a8db342016-09-28 22:45:54 +0000527
528bool 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}
Justin Lebarb17840d2016-09-28 22:45:58 +0000551
552bool 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}
Justin Lebar7ca116c2016-09-30 17:14:53 +0000571
572void Sema::CUDASetLambdaAttrs(CXXMethodDecl *Method) {
Justin Lebar9d4ed262016-09-30 23:57:38 +0000573 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
Justin Lebar7ca116c2016-09-30 17:14:53 +0000574 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 }
Justin Lebar7ca116c2016-09-30 17:14:53 +0000586}