summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaCUDA.cpp
diff options
context:
space:
mode:
authorJustin Lebar <jlebar@google.com>2016-08-15 23:00:49 +0000
committerJustin Lebar <jlebar@google.com>2016-08-15 23:00:49 +0000
commit18e2d82297ec692c015bd1f22758913b6dd3c508 (patch)
tree923142378f859b0b69127c1da2fcecc9d3ca9339 /clang/lib/Sema/SemaCUDA.cpp
parenta7b04a589e9dd0b27cb84da4ee85801e23ba5de5 (diff)
downloadbcm5719-llvm-18e2d82297ec692c015bd1f22758913b6dd3c508.tar.gz
bcm5719-llvm-18e2d82297ec692c015bd1f22758913b6dd3c508.zip
[CUDA] Raise an error if a wrong-side call is codegen'ed.
Summary: Some function calls in CUDA are allowed to appear in semantically-correct programs but are an error if they're ever codegen'ed. Specifically, a host+device function may call a host function, but it's an error if such a function is ever codegen'ed in device mode (and vice versa). Previously, clang made no attempt to catch these errors. For the most part, they would be caught by ptxas, and reported as "call to unknown function 'foo'". Now we catch these errors and report them the same as we report other illegal calls (e.g. a call from a host function to a device function). This has a small change in error-message behavior for calls that were previously disallowed (e.g. calls from a host to a device function). Previously, we'd catch disallowed calls fairly early, before doing additional semantic checking e.g. of the call's arguments. Now we catch these illegal calls at the very end of our semantic checks, so we'll only emit a "illegal CUDA call" error if the call is otherwise well-formed. Reviewers: tra, rnk Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D23242 llvm-svn: 278759
Diffstat (limited to 'clang/lib/Sema/SemaCUDA.cpp')
-rw-r--r--clang/lib/Sema/SemaCUDA.cpp30
1 files changed, 30 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp
index 90af6d5a927..4f370d389c6 100644
--- a/clang/lib/Sema/SemaCUDA.cpp
+++ b/clang/lib/Sema/SemaCUDA.cpp
@@ -480,3 +480,33 @@ void Sema::maybeAddCUDAHostDeviceAttrs(Scope *S, FunctionDecl *NewD,
NewD->addAttr(CUDAHostAttr::CreateImplicit(Context));
NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context));
}
+
+bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) {
+ assert(getLangOpts().CUDA &&
+ "Should only be called during CUDA compilation.");
+ assert(Callee && "Callee may not be null.");
+ FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext);
+ if (!Caller)
+ return true;
+
+ Sema::CUDAFunctionPreference Pref = IdentifyCUDAPreference(Caller, Callee);
+ if (Pref == Sema::CFP_Never) {
+ Diag(Loc, diag::err_ref_bad_target) << IdentifyCUDATarget(Callee) << Callee
+ << IdentifyCUDATarget(Caller);
+ Diag(Callee->getLocation(), diag::note_previous_decl) << Callee;
+ return false;
+ }
+ if (Pref == Sema::CFP_WrongSide) {
+ // We have to do this odd dance to create our PartialDiagnostic because we
+ // want its storage to be allocated with operator new, not in an arena.
+ PartialDiagnostic PD{PartialDiagnostic::NullDiagnostic()};
+ PD.Reset(diag::err_ref_bad_target);
+ PD << IdentifyCUDATarget(Callee) << Callee << IdentifyCUDATarget(Caller);
+ Caller->addDeferredDiag({Loc, std::move(PD)});
+ Diag(Callee->getLocation(), diag::note_previous_decl) << Callee;
+ // This is not immediately an error, so return true. The deferred errors
+ // will be emitted if and when Caller is codegen'ed.
+ return true;
+ }
+ return true;
+}
OpenPOWER on IntegriCloud