blob: 2a66124080430d964d4cecdf333d0b8b87c5e740 [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 &&
Justin Lebar0254c462016-10-12 01:30:08 +0000123 (CallerTarget == CFT_Global || CallerTarget == CFT_Device))
Artem Belevich94a55e82015-09-22 17:22:59 +0000124 return CFP_Never;
125
Artem Belevich18609102016-02-12 18:29:18 +0000126 // (b) Calling HostDevice is OK for everyone.
127 if (CalleeTarget == CFT_HostDevice)
128 return CFP_HostDevice;
129
130 // (c) Best case scenarios
Artem Belevich94a55e82015-09-22 17:22:59 +0000131 if (CalleeTarget == CallerTarget ||
132 (CallerTarget == CFT_Host && CalleeTarget == CFT_Global) ||
133 (CallerTarget == CFT_Global && CalleeTarget == CFT_Device))
Artem Belevich18609102016-02-12 18:29:18 +0000134 return CFP_Native;
Artem Belevich94a55e82015-09-22 17:22:59 +0000135
136 // (d) HostDevice behavior depends on compilation mode.
137 if (CallerTarget == CFT_HostDevice) {
Artem Belevich18609102016-02-12 18:29:18 +0000138 // 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
Justin Lebar25c4a812016-03-29 16:24:16 +0000144 // 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;
Artem Belevich94a55e82015-09-22 17:22:59 +0000149 }
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))
Artem Belevich18609102016-02-12 18:29:18 +0000155 return CFP_Never;
Artem Belevich94a55e82015-09-22 17:22:59 +0000156
157 llvm_unreachable("All cases should've been handled by now.");
158}
159
Richard Smithf75dcbe2016-10-11 00:21:10 +0000160void Sema::EraseUnwantedCUDAMatches(
161 const FunctionDecl *Caller,
162 SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) {
Artem Belevich94a55e82015-09-22 17:22:59 +0000163 if (Matches.size() <= 1)
164 return;
165
Richard Smithf75dcbe2016-10-11 00:21:10 +0000166 using Pair = std::pair<DeclAccessPair, FunctionDecl*>;
167
Justin Lebare6a2cc12016-03-22 00:09:25 +0000168 // Gets the CUDA function preference for a call from Caller to Match.
Richard Smithf75dcbe2016-10-11 00:21:10 +0000169 auto GetCFP = [&](const Pair &Match) {
170 return IdentifyCUDAPreference(Caller, Match.second);
Justin Lebare6a2cc12016-03-22 00:09:25 +0000171 };
172
Artem Belevich94a55e82015-09-22 17:22:59 +0000173 // Find the best call preference among the functions in Matches.
Richard Smithf75dcbe2016-10-11 00:21:10 +0000174 CUDAFunctionPreference BestCFP = GetCFP(*std::max_element(
Justin Lebare6a2cc12016-03-22 00:09:25 +0000175 Matches.begin(), Matches.end(),
Richard Smithf75dcbe2016-10-11 00:21:10 +0000176 [&](const Pair &M1, const Pair &M2) { return GetCFP(M1) < GetCFP(M2); }));
Artem Belevich94a55e82015-09-22 17:22:59 +0000177
178 // Erase all functions with lower priority.
Justin Lebare71c08f2016-07-12 23:23:13 +0000179 Matches.erase(
Richard Smithf75dcbe2016-10-11 00:21:10 +0000180 llvm::remove_if(
181 Matches, [&](const Pair &Match) { return GetCFP(Match) < BestCFP; }),
Justin Lebare71c08f2016-07-12 23:23:13 +0000182 Matches.end());
Artem Belevich94a55e82015-09-22 17:22:59 +0000183}
184
Eli Bendersky9a220fc2014-09-29 20:38:29 +0000185/// 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.
193static bool
194resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1,
195 Sema::CUDAFunctionTarget Target2,
196 Sema::CUDAFunctionTarget *ResolvedTarget) {
Justin Lebarc66a1062016-01-20 00:26:57 +0000197 // Only free functions and static member functions may be global.
198 assert(Target1 != Sema::CFT_Global);
199 assert(Target2 != Sema::CFT_Global);
Eli Bendersky9a220fc2014-09-29 20:38:29 +0000200
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
214bool 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}
Artem Belevich97c01c32016-02-02 22:29:48 +0000343
344bool 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.
Artem Belevich3650bbe2016-05-19 20:13:53 +0000366 // This will recursively check all base classes and member initializers
Artem Belevich97c01c32016-02-02 22:29:48 +0000367 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}
Justin Lebarba122ab2016-03-30 23:30:21 +0000377
Artem Belevich3650bbe2016-05-19 20:13:53 +0000378bool 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
Justin Lebarba122ab2016-03-30 23:30:21 +0000426// 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.
Justin Lebar67a78a62016-10-08 22:15:58 +0000433//
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).
Justin Lebarba122ab2016-03-30 23:30:21 +0000438void Sema::maybeAddCUDAHostDeviceAttrs(Scope *S, FunctionDecl *NewD,
439 const LookupResult &Previous) {
Justin Lebar9d4ed262016-09-30 23:57:38 +0000440 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
Justin Lebar67a78a62016-10-08 22:15:58 +0000441
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
Justin Lebarba122ab2016-03-30 23:30:21 +0000450 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}
Justin Lebar18e2d822016-08-15 23:00:49 +0000486
487bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) {
Justin Lebar9d4ed262016-09-30 23:57:38 +0000488 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
Justin Lebar18e2d822016-08-15 23:00:49 +0000489 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 }
Justin Lebar9fdb46e2016-10-08 01:07:11 +0000501
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) {
Justin Lebar18e2d822016-08-15 23:00:49 +0000508 // 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.
Justin Lebar26bb3112016-08-16 00:48:21 +0000510 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
Justin Lebar18e2d822016-08-15 23:00:49 +0000520 // 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}
Justin Lebar2a8db342016-09-28 22:45:54 +0000526
527bool 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}
Justin Lebarb17840d2016-09-28 22:45:58 +0000550
551bool 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}
Justin Lebar7ca116c2016-09-30 17:14:53 +0000570
571void Sema::CUDASetLambdaAttrs(CXXMethodDecl *Method) {
Justin Lebar9d4ed262016-09-30 23:57:38 +0000572 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
Justin Lebar7ca116c2016-09-30 17:14:53 +0000573 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 }
Justin Lebar7ca116c2016-09-30 17:14:53 +0000585}