[CUDA] Use only the GVALinkage on function definitions.
Summary:
Previously we'd look at the GVALinkage of whatever FunctionDecl you
happened to be calling.
This is not right. In the absence of the gnu_inline attribute, to be
handled separately, the function definition determines the function's
linkage. So we need to wait until we get a def before we can know
whether something is known-emitted.
Reviewers: tra
Subscribers: cfe-commits, rsmith
Differential Revision: https://reviews.llvm.org/D26268
llvm-svn: 286313
diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp
index fbaede1..d99f8e0 100644
--- a/clang/lib/Sema/SemaCUDA.cpp
+++ b/clang/lib/Sema/SemaCUDA.cpp
@@ -577,8 +577,22 @@
(T == Sema::CFT_Device || T == Sema::CFT_Global))
return false;
- // Externally-visible and similar functions are always emitted.
- if (!isDiscardableGVALinkage(S.getASTContext().GetGVALinkageForFunction(FD)))
+ // Check whether this function is externally visible -- if so, it's
+ // known-emitted.
+ //
+ // We have to check the GVA linkage of the function's *definition* -- if we
+ // only have a declaration, we don't know whether or not the function will be
+ // emitted, because (say) the definition could include "inline".
+ FunctionDecl *Def = FD->getDefinition();
+
+ // We may currently be parsing the body of FD, in which case
+ // FD->getDefinition() will be null, but we still want to treat FD as though
+ // it's a definition.
+ if (!Def && FD->willHaveBody())
+ Def = FD;
+
+ if (Def &&
+ !isDiscardableGVALinkage(S.getASTContext().GetGVALinkageForFunction(Def)))
return true;
// Otherwise, the function is known-emitted if it's in our set of