[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
This revision was automatically updated to reflect the committed changes. Closed by commit rL288962: [CUDA] Improve target attribute checking for function templates. (authored by tra). Changed prior to commit: https://reviews.llvm.org/D25809?vs=80522=80635#toc Repository: rL LLVM https://reviews.llvm.org/D25809 Files: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/SemaCUDA.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaOverload.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/test/CodeGenCUDA/launch-bounds.cu cfe/trunk/test/SemaCUDA/function-overload.cu cfe/trunk/test/SemaCUDA/function-template-overload.cu cfe/trunk/test/SemaCUDA/target_attr_inheritance.cu Index: cfe/trunk/lib/Sema/SemaOverload.cpp === --- cfe/trunk/lib/Sema/SemaOverload.cpp +++ cfe/trunk/lib/Sema/SemaOverload.cpp @@ -580,6 +580,7 @@ case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: case Sema::TDK_MiscellaneousDeductionFailure: + case Sema::TDK_CUDATargetMismatch: Result.Data = nullptr; break; @@ -647,6 +648,7 @@ case Sema::TDK_TooFewArguments: case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_CUDATargetMismatch: break; case Sema::TDK_Inconsistent: @@ -689,6 +691,7 @@ case Sema::TDK_DeducedMismatch: case Sema::TDK_NonDeducedMismatch: case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_CUDATargetMismatch: return TemplateParameter(); case Sema::TDK_Incomplete: @@ -720,6 +723,7 @@ case Sema::TDK_Underqualified: case Sema::TDK_NonDeducedMismatch: case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_CUDATargetMismatch: return nullptr; case Sema::TDK_DeducedMismatch: @@ -747,6 +751,7 @@ case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_SubstitutionFailure: case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_CUDATargetMismatch: return nullptr; case Sema::TDK_Inconsistent: @@ -774,6 +779,7 @@ case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_SubstitutionFailure: case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_CUDATargetMismatch: return nullptr; case Sema::TDK_Inconsistent: @@ -1139,20 +1145,11 @@ CUDAFunctionTarget NewTarget = IdentifyCUDATarget(New), OldTarget = IdentifyCUDATarget(Old); -if (NewTarget == CFT_InvalidTarget || NewTarget == CFT_Global) +if (NewTarget == CFT_InvalidTarget) return false; assert((OldTarget != CFT_InvalidTarget) && "Unexpected invalid target."); -// Don't allow HD and global functions to overload other functions with the -// same signature. We allow overloading based on CUDA attributes so that -// functions can have different implementations on the host and device, but -// HD/global functions "exist" in some sense on both the host and device, so -// should have the same implementation on both sides. -if ((NewTarget == CFT_HostDevice) || (OldTarget == CFT_HostDevice) || -(NewTarget == CFT_Global) || (OldTarget == CFT_Global)) - return false; - // Allow overloading of functions with same signature and different CUDA // target attributes. return NewTarget != OldTarget; @@ -9713,6 +9710,10 @@ S.Diag(Templated->getLocation(), diag::note_ovl_candidate_bad_deduction); MaybeEmitInheritedConstructorNote(S, Found); return; + case Sema::TDK_CUDATargetMismatch: +S.Diag(Templated->getLocation(), + diag::note_cuda_ovl_candidate_target_mismatch); +return; } } @@ -9969,6 +9970,7 @@ case Sema::TDK_DeducedMismatch: case Sema::TDK_NonDeducedMismatch: case Sema::TDK_MiscellaneousDeductionFailure: + case Sema::TDK_CUDATargetMismatch: return 3; case Sema::TDK_InstantiationDepth: Index: cfe/trunk/lib/Sema/SemaTemplate.cpp === --- cfe/trunk/lib/Sema/SemaTemplate.cpp +++ cfe/trunk/lib/Sema/SemaTemplate.cpp @@ -7043,6 +7043,19 @@ continue; } + // Target attributes are part of function signature during cuda + // compilation, so deduced template must also have matching CUDA + // target. Given that regular template deduction does not take + // target attributes into account, we perform target match check + // here and reject candidates that have different target. + if (LangOpts.CUDA && + IdentifyCUDATarget(Specialization) != IdentifyCUDATarget(FD)) { +FailedCandidates.addCandidate().set( +I.getPair(), FunTmpl->getTemplatedDecl(), +MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info)); +continue; + } + // Record this candidate. if (ExplicitTemplateArgs) ConvertedTemplateArgs[Specialization] =
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
jlebar added a comment. > I've reverted to 75652 Did you forget to arc diff? Anyway if it's just that if statement, lgtm. https://reviews.llvm.org/D25809 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
tra added a comment. In https://reviews.llvm.org/D25809#615485, @jlebar wrote: > If you would like me to have another look at this, is it possible to make an > interdiff of your changes between this and the last version I reviewed? > phab's interdiff is useless because it straddles a rebase. I've reverted to 75652 which is the revision you've approved with a new if() to limit our overloading checks to FunctionDecls only. It's a the very end of SemaCUDA.cpp (line 864): https://reviews.llvm.org/differential/changeset/?ref=590934%2F556303=ignore-most https://reviews.llvm.org/D25809 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
jlebar added a comment. If you would like me to have another look at this, is it possible to make an interdiff of your changes between this and the last version I reviewed? phab's interdiff is useless because it straddles a rebase. https://reviews.llvm.org/D25809 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
jlebar added a comment. (Alternatively I'm happy not to have another look if you don't think you need it.) https://reviews.llvm.org/D25809 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
tra updated this revision to Diff 80522. tra added a comment. Removed HD overloading checks for using declarations. 'using' exposes number of issues with the way we handle overloading of HD functions vs H/D. The issues will be addressed in a separate patch. https://reviews.llvm.org/D25809 Files: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaCUDA.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp test/CodeGenCUDA/launch-bounds.cu test/SemaCUDA/function-overload.cu test/SemaCUDA/function-template-overload.cu test/SemaCUDA/target_attr_inheritance.cu Index: test/SemaCUDA/target_attr_inheritance.cu === --- test/SemaCUDA/target_attr_inheritance.cu +++ /dev/null @@ -1,29 +0,0 @@ -// Verifies correct inheritance of target attributes during template -// instantiation and specialization. - -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s - -#include "Inputs/cuda.h" - -// Function must inherit target attributes during instantiation, but not during -// specialization. -template __host__ __device__ T function_template(const T ); - -// Specialized functions have their own attributes. -// expected-note@+1 {{candidate function not viable: call to __host__ function from __device__ function}} -template <> __host__ float function_template(const float ); - -// expected-note@+1 {{candidate function not viable: call to __device__ function from __host__ function}} -template <> __device__ double function_template(const double ); - -__host__ void hf() { - function_template(1.0f); // OK. Specialization is __host__. - function_template(2.0); // expected-error {{no matching function for call to 'function_template'}} - function_template(1); // OK. Instantiated function template is HD. -} -__device__ void df() { - function_template(3.0f); // expected-error {{no matching function for call to 'function_template'}} - function_template(4.0); // OK. Specialization is __device__. - function_template(1); // OK. Instantiated function template is HD. -} Index: test/SemaCUDA/function-template-overload.cu === --- /dev/null +++ test/SemaCUDA/function-template-overload.cu @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s + +#include "Inputs/cuda.h" + +struct HType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'DType'}} +struct DType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'HType'}} +struct HDType {}; + +template __host__ HType overload_h_d(T a) { return HType(); } +// expected-note@-1 2 {{candidate template ignored: could not match 'HType' against 'DType'}} +// expected-note@-2 2 {{candidate template ignored: target attributes do not match}} +template __device__ DType overload_h_d(T a) { return DType(); } +// expected-note@-1 2 {{candidate template ignored: could not match 'DType' against 'HType'}} +// expected-note@-2 2 {{candidate template ignored: target attributes do not match}} + +// Check explicit instantiation. +template __device__ __host__ DType overload_h_d(int a); // There's no HD template... +// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}} +template __device__ __host__ HType overload_h_d(int a); // There's no HD template... +// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}} +template __device__ DType overload_h_d(int a); // OK. instantiates D +template __host__ HType overload_h_d(int a); // OK. instantiates H + +// Check explicit specialization. +template <> __device__ __host__ DType overload_h_d(long a); // There's no HD template... +// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}} +template <> __device__ __host__ HType overload_h_d(long a); // There's no HD template... +// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}} +template <> __device__ DType overload_h_d(long a); // OK. instantiates D +template <> __host__ HType overload_h_d(long a); // OK. instantiates H + + +// Can't overload HD template with H or D template, though functions are OK. +template __host__ __device__ HDType overload_hd(T a) { return HDType(); } +// expected-note@-1 {{previous declaration is here}} +// expected-note@-2 2 {{candidate template ignored: could not match 'HDType' against
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
jlebar added a comment. Is it possible to write a testcase for the using-declaration change? https://reviews.llvm.org/D25809 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
tra updated this revision to Diff 75816. tra added a comment. - handle using declarations found in the overload set we check. https://reviews.llvm.org/D25809 Files: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaCUDA.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp test/CodeGenCUDA/launch-bounds.cu test/SemaCUDA/function-overload.cu test/SemaCUDA/function-template-overload.cu test/SemaCUDA/target_attr_inheritance.cu Index: test/SemaCUDA/target_attr_inheritance.cu === --- test/SemaCUDA/target_attr_inheritance.cu +++ /dev/null @@ -1,29 +0,0 @@ -// Verifies correct inheritance of target attributes during template -// instantiation and specialization. - -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s - -#include "Inputs/cuda.h" - -// Function must inherit target attributes during instantiation, but not during -// specialization. -template __host__ __device__ T function_template(const T ); - -// Specialized functions have their own attributes. -// expected-note@+1 {{candidate function not viable: call to __host__ function from __device__ function}} -template <> __host__ float function_template(const float ); - -// expected-note@+1 {{candidate function not viable: call to __device__ function from __host__ function}} -template <> __device__ double function_template(const double ); - -__host__ void hf() { - function_template(1.0f); // OK. Specialization is __host__. - function_template(2.0); // expected-error {{no matching function for call to 'function_template'}} - function_template(1); // OK. Instantiated function template is HD. -} -__device__ void df() { - function_template(3.0f); // expected-error {{no matching function for call to 'function_template'}} - function_template(4.0); // OK. Specialization is __device__. - function_template(1); // OK. Instantiated function template is HD. -} Index: test/SemaCUDA/function-template-overload.cu === --- /dev/null +++ test/SemaCUDA/function-template-overload.cu @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s + +#include "Inputs/cuda.h" + +struct HType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'DType'}} +struct DType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'HType'}} +struct HDType {}; + +template __host__ HType overload_h_d(T a) { return HType(); } +// expected-note@-1 2 {{candidate template ignored: could not match 'HType' against 'DType'}} +// expected-note@-2 2 {{candidate template ignored: target attributes do not match}} +template __device__ DType overload_h_d(T a) { return DType(); } +// expected-note@-1 2 {{candidate template ignored: could not match 'DType' against 'HType'}} +// expected-note@-2 2 {{candidate template ignored: target attributes do not match}} + +// Check explicit instantiation. +template __device__ __host__ DType overload_h_d(int a); // There's no HD template... +// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}} +template __device__ __host__ HType overload_h_d(int a); // There's no HD template... +// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}} +template __device__ DType overload_h_d(int a); // OK. instantiates D +template __host__ HType overload_h_d(int a); // OK. instantiates H + +// Check explicit specialization. +template <> __device__ __host__ DType overload_h_d(long a); // There's no HD template... +// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}} +template <> __device__ __host__ HType overload_h_d(long a); // There's no HD template... +// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}} +template <> __device__ DType overload_h_d(long a); // OK. instantiates D +template <> __host__ HType overload_h_d(long a); // OK. instantiates H + + +// Can't overload HD template with H or D template, though functions are OK. +template __host__ __device__ HDType overload_hd(T a) { return HDType(); } +// expected-note@-1 {{previous declaration is here}} +// expected-note@-2 2 {{candidate template ignored: could not match 'HDType' against 'HType'}} +template __device__ HDType overload_hd(T a); +// expected-error@-1 {{__device__ function 'overload_hd' cannot overload __host__
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
tra added inline comments. Comment at: lib/Sema/SemaCUDA.cpp:791 + CUDAFunctionTarget NewTarget = IdentifyCUDATarget(NewFD); + for (auto OldND : Previous) { +FunctionDecl *OldFD = OldND->getAsFunction(); jlebar wrote: > tra wrote: > > jlebar wrote: > > > If this is just a Decl* or NamedDecl*, can we write out the type? > > I'm not sure what exactly you'd like to see. Diags will print out the line > > and target info for both sides. > > Could you give me example of existing diagnostics that would be similar to > > what you want? > Sorry, I just meant for you to change "auto" to the actual type. Ah! That would be `NamedDecl *` Done.. Comment at: lib/Sema/SemaTemplate.cpp:7047 + // target. Given that regular template deduction does not take + // it into account, we perform target match check here and + // reject candidates that have different target. jlebar wrote: > what is "it"? Do you mean "the function signature", or something else? it = "target attributes" https://reviews.llvm.org/D25809 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
tra updated this revision to Diff 75652. tra marked an inline comment as done. tra added a comment. Addressed remaining nits. https://reviews.llvm.org/D25809 Files: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaCUDA.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp test/CodeGenCUDA/launch-bounds.cu test/SemaCUDA/function-overload.cu test/SemaCUDA/function-template-overload.cu test/SemaCUDA/target_attr_inheritance.cu Index: test/SemaCUDA/target_attr_inheritance.cu === --- test/SemaCUDA/target_attr_inheritance.cu +++ /dev/null @@ -1,29 +0,0 @@ -// Verifies correct inheritance of target attributes during template -// instantiation and specialization. - -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s - -#include "Inputs/cuda.h" - -// Function must inherit target attributes during instantiation, but not during -// specialization. -template __host__ __device__ T function_template(const T ); - -// Specialized functions have their own attributes. -// expected-note@+1 {{candidate function not viable: call to __host__ function from __device__ function}} -template <> __host__ float function_template(const float ); - -// expected-note@+1 {{candidate function not viable: call to __device__ function from __host__ function}} -template <> __device__ double function_template(const double ); - -__host__ void hf() { - function_template(1.0f); // OK. Specialization is __host__. - function_template(2.0); // expected-error {{no matching function for call to 'function_template'}} - function_template(1); // OK. Instantiated function template is HD. -} -__device__ void df() { - function_template(3.0f); // expected-error {{no matching function for call to 'function_template'}} - function_template(4.0); // OK. Specialization is __device__. - function_template(1); // OK. Instantiated function template is HD. -} Index: test/SemaCUDA/function-template-overload.cu === --- /dev/null +++ test/SemaCUDA/function-template-overload.cu @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s + +#include "Inputs/cuda.h" + +struct HType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'DType'}} +struct DType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'HType'}} +struct HDType {}; + +template __host__ HType overload_h_d(T a) { return HType(); } +// expected-note@-1 2 {{candidate template ignored: could not match 'HType' against 'DType'}} +// expected-note@-2 2 {{candidate template ignored: target attributes do not match}} +template __device__ DType overload_h_d(T a) { return DType(); } +// expected-note@-1 2 {{candidate template ignored: could not match 'DType' against 'HType'}} +// expected-note@-2 2 {{candidate template ignored: target attributes do not match}} + +// Check explicit instantiation. +template __device__ __host__ DType overload_h_d(int a); // There's no HD template... +// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}} +template __device__ __host__ HType overload_h_d(int a); // There's no HD template... +// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}} +template __device__ DType overload_h_d(int a); // OK. instantiates D +template __host__ HType overload_h_d(int a); // OK. instantiates H + +// Check explicit specialization. +template <> __device__ __host__ DType overload_h_d(long a); // There's no HD template... +// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}} +template <> __device__ __host__ HType overload_h_d(long a); // There's no HD template... +// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}} +template <> __device__ DType overload_h_d(long a); // OK. instantiates D +template <> __host__ HType overload_h_d(long a); // OK. instantiates H + + +// Can't overload HD template with H or D template, though functions are OK. +template __host__ __device__ HDType overload_hd(T a) { return HDType(); } +// expected-note@-1 {{previous declaration is here}} +// expected-note@-2 2 {{candidate template ignored: could not match 'HDType' against 'HType'}} +template __device__ HDType overload_hd(T a); +// expected-error@-1 {{__device__ function 'overload_hd' cannot overload __host__
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
jlebar accepted this revision. jlebar added inline comments. This revision is now accepted and ready to land. Comment at: lib/Sema/SemaCUDA.cpp:87 + + if ((HasHostAttr && HasDeviceAttr) || ForceCUDAHostDeviceDepth > 0) +return CFT_HostDevice; tra wrote: > jlebar wrote: > > Checking ForceCUDAHostDeviceDepth here is...yeah. Especially because the > > other overload of this function doesn't do it. > > > > I know you get rid of it in the next patch, but how much work would it be > > to get rid of it here? It definitely makes this patch harder to check. > OK. Moved the check to the place where I use it. Thank you -- I appreciate that. :) Comment at: lib/Sema/SemaCUDA.cpp:791 + CUDAFunctionTarget NewTarget = IdentifyCUDATarget(NewFD); + for (auto OldND : Previous) { +FunctionDecl *OldFD = OldND->getAsFunction(); tra wrote: > jlebar wrote: > > If this is just a Decl* or NamedDecl*, can we write out the type? > I'm not sure what exactly you'd like to see. Diags will print out the line > and target info for both sides. > Could you give me example of existing diagnostics that would be similar to > what you want? Sorry, I just meant for you to change "auto" to the actual type. Comment at: lib/Sema/SemaCUDA.cpp:793 +FunctionDecl *OldFD = OldND->getAsFunction(); +if (!OldFD || OldFD->isFunctionTemplateSpecialization()) + continue; tra wrote: > jlebar wrote: > > Please add a comment explaining why we ignore template specializations. > That's another check that's no longer needed as the only template > instantiations/specializations that end up in the overload set are those that > were instantiated from templates with matching target. > Even better. :) Comment at: lib/Sema/SemaTemplate.cpp:7047 + // target. Given that regular template deduction does not take + // it into account, we perform target match check here and + // reject candidates that have different target. what is "it"? Do you mean "the function signature", or something else? https://reviews.llvm.org/D25809 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
tra updated this revision to Diff 75516. tra added a comment. removed pragma check from IdentifyCUDATarget for real. https://reviews.llvm.org/D25809 Files: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaCUDA.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp test/CodeGenCUDA/launch-bounds.cu test/SemaCUDA/function-overload.cu test/SemaCUDA/function-template-overload.cu test/SemaCUDA/target_attr_inheritance.cu Index: test/SemaCUDA/target_attr_inheritance.cu === --- test/SemaCUDA/target_attr_inheritance.cu +++ /dev/null @@ -1,29 +0,0 @@ -// Verifies correct inheritance of target attributes during template -// instantiation and specialization. - -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s - -#include "Inputs/cuda.h" - -// Function must inherit target attributes during instantiation, but not during -// specialization. -template __host__ __device__ T function_template(const T ); - -// Specialized functions have their own attributes. -// expected-note@+1 {{candidate function not viable: call to __host__ function from __device__ function}} -template <> __host__ float function_template(const float ); - -// expected-note@+1 {{candidate function not viable: call to __device__ function from __host__ function}} -template <> __device__ double function_template(const double ); - -__host__ void hf() { - function_template(1.0f); // OK. Specialization is __host__. - function_template(2.0); // expected-error {{no matching function for call to 'function_template'}} - function_template(1); // OK. Instantiated function template is HD. -} -__device__ void df() { - function_template(3.0f); // expected-error {{no matching function for call to 'function_template'}} - function_template(4.0); // OK. Specialization is __device__. - function_template(1); // OK. Instantiated function template is HD. -} Index: test/SemaCUDA/function-template-overload.cu === --- /dev/null +++ test/SemaCUDA/function-template-overload.cu @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s + +#include "Inputs/cuda.h" + +struct HType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'DType'}} +struct DType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'HType'}} +struct HDType {}; + +template __host__ HType overload_h_d(T a) { return HType(); } +// expected-note@-1 2 {{candidate template ignored: could not match 'HType' against 'DType'}} +// expected-note@-2 2 {{candidate template ignored: target attributes do not match}} +template __device__ DType overload_h_d(T a) { return DType(); } +// expected-note@-1 2 {{candidate template ignored: could not match 'DType' against 'HType'}} +// expected-note@-2 2 {{candidate template ignored: target attributes do not match}} + +// Check explicit instantiation. +template __device__ __host__ DType overload_h_d(int a); // There's no HD template... +// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}} +template __device__ __host__ HType overload_h_d(int a); // There's no HD template... +// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}} +template __device__ DType overload_h_d(int a); // OK. instantiates D +template __host__ HType overload_h_d(int a); // OK. instantiates H + +// Check explicit specialization. +template <> __device__ __host__ DType overload_h_d(long a); // There's no HD template... +// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}} +template <> __device__ __host__ HType overload_h_d(long a); // There's no HD template... +// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}} +template <> __device__ DType overload_h_d(long a); // OK. instantiates D +template <> __host__ HType overload_h_d(long a); // OK. instantiates H + + +// Can't overload HD template with H or D template, though functions are OK. +template __host__ __device__ HDType overload_hd(T a) { return HDType(); } +// expected-note@-1 {{previous declaration is here}} +// expected-note@-2 2 {{candidate template ignored: could not match 'HDType' against 'HType'}} +template __device__ HDType overload_hd(T a); +// expected-error@-1 {{__device__ function 'overload_hd' cannot overload __host__
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
tra added inline comments. Comment at: lib/Sema/SemaCUDA.cpp:87 + + if ((HasHostAttr && HasDeviceAttr) || ForceCUDAHostDeviceDepth > 0) +return CFT_HostDevice; jlebar wrote: > Checking ForceCUDAHostDeviceDepth here is...yeah. Especially because the > other overload of this function doesn't do it. > > I know you get rid of it in the next patch, but how much work would it be to > get rid of it here? It definitely makes this patch harder to check. OK. Moved the check to the place where I use it. Comment at: lib/Sema/SemaCUDA.cpp:791 + CUDAFunctionTarget NewTarget = IdentifyCUDATarget(NewFD); + for (auto OldND : Previous) { +FunctionDecl *OldFD = OldND->getAsFunction(); jlebar wrote: > If this is just a Decl* or NamedDecl*, can we write out the type? I'm not sure what exactly you'd like to see. Diags will print out the line and target info for both sides. Could you give me example of existing diagnostics that would be similar to what you want? Comment at: lib/Sema/SemaCUDA.cpp:793 +FunctionDecl *OldFD = OldND->getAsFunction(); +if (!OldFD || OldFD->isFunctionTemplateSpecialization()) + continue; jlebar wrote: > Please add a comment explaining why we ignore template specializations. That's another check that's no longer needed as the only template instantiations/specializations that end up in the overload set are those that were instantiated from templates with matching target. Comment at: lib/Sema/SemaTemplate.cpp:8117 +if (LangOpts.CUDA && +IdentifyCUDATarget(Specialization) != IdentifyCUDATarget(Attr)) { + FailedCandidates.addCandidate().set( jlebar wrote: > Can we just pass D here (and thus not write the new overload of > IdentifyCUDATarget)? Nope. D is a Declarator which is very different form FunctionDecl. It carries info about what we've parsed, but we didn't construct a FunctionDecl from it yet. https://reviews.llvm.org/D25809 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
tra updated this revision to Diff 75515. tra marked 5 inline comments as done. tra added a comment. addressed jlebar's comments. https://reviews.llvm.org/D25809 Files: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaCUDA.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp test/CodeGenCUDA/launch-bounds.cu test/SemaCUDA/function-overload.cu test/SemaCUDA/function-template-overload.cu test/SemaCUDA/target_attr_inheritance.cu Index: test/SemaCUDA/target_attr_inheritance.cu === --- test/SemaCUDA/target_attr_inheritance.cu +++ /dev/null @@ -1,29 +0,0 @@ -// Verifies correct inheritance of target attributes during template -// instantiation and specialization. - -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s - -#include "Inputs/cuda.h" - -// Function must inherit target attributes during instantiation, but not during -// specialization. -template __host__ __device__ T function_template(const T ); - -// Specialized functions have their own attributes. -// expected-note@+1 {{candidate function not viable: call to __host__ function from __device__ function}} -template <> __host__ float function_template(const float ); - -// expected-note@+1 {{candidate function not viable: call to __device__ function from __host__ function}} -template <> __device__ double function_template(const double ); - -__host__ void hf() { - function_template(1.0f); // OK. Specialization is __host__. - function_template(2.0); // expected-error {{no matching function for call to 'function_template'}} - function_template(1); // OK. Instantiated function template is HD. -} -__device__ void df() { - function_template(3.0f); // expected-error {{no matching function for call to 'function_template'}} - function_template(4.0); // OK. Specialization is __device__. - function_template(1); // OK. Instantiated function template is HD. -} Index: test/SemaCUDA/function-template-overload.cu === --- /dev/null +++ test/SemaCUDA/function-template-overload.cu @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s + +#include "Inputs/cuda.h" + +struct HType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'DType'}} +struct DType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'HType'}} +struct HDType {}; + +template __host__ HType overload_h_d(T a) { return HType(); } +// expected-note@-1 2 {{candidate template ignored: could not match 'HType' against 'DType'}} +// expected-note@-2 2 {{candidate template ignored: target attributes do not match}} +template __device__ DType overload_h_d(T a) { return DType(); } +// expected-note@-1 2 {{candidate template ignored: could not match 'DType' against 'HType'}} +// expected-note@-2 2 {{candidate template ignored: target attributes do not match}} + +// Check explicit instantiation. +template __device__ __host__ DType overload_h_d(int a); // There's no HD template... +// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}} +template __device__ __host__ HType overload_h_d(int a); // There's no HD template... +// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}} +template __device__ DType overload_h_d(int a); // OK. instantiates D +template __host__ HType overload_h_d(int a); // OK. instantiates H + +// Check explicit specialization. +template <> __device__ __host__ DType overload_h_d(long a); // There's no HD template... +// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}} +template <> __device__ __host__ HType overload_h_d(long a); // There's no HD template... +// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}} +template <> __device__ DType overload_h_d(long a); // OK. instantiates D +template <> __host__ HType overload_h_d(long a); // OK. instantiates H + + +// Can't overload HD template with H or D template, though functions are OK. +template __host__ __device__ HDType overload_hd(T a) { return HDType(); } +// expected-note@-1 {{previous declaration is here}} +// expected-note@-2 2 {{candidate template ignored: could not match 'HDType' against 'HType'}} +template __device__ HDType overload_hd(T a); +// expected-error@-1 {{__device__ function 'overload_hd' cannot overload
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
jlebar added inline comments. Comment at: test/SemaCUDA/function-template-overload.cu:44 +// explicitly specialize or instantiate function tempaltes. +template <> __host__ HType overload_hd(int a); +// expected-error@-1 {{no function template matches function template specialization 'overload_hd'}} jlebar wrote: > Please ignore the above comment; it is not correct, but I cannot delete it or > edit it in phab. :-/ (Wow, it also didn't submit the comment I was referring to. How broken.) https://reviews.llvm.org/D25809 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
jlebar added inline comments. Comment at: lib/Sema/SemaCUDA.cpp:87 + + if ((HasHostAttr && HasDeviceAttr) || ForceCUDAHostDeviceDepth > 0) +return CFT_HostDevice; Checking ForceCUDAHostDeviceDepth here is...yeah. Especially because the other overload of this function doesn't do it. I know you get rid of it in the next patch, but how much work would it be to get rid of it here? It definitely makes this patch harder to check. Comment at: lib/Sema/SemaCUDA.cpp:790 + LookupResult ) { + CUDAFunctionTarget NewTarget = IdentifyCUDATarget(NewFD); + for (auto OldND : Previous) { Nit, can we assert that we're in cuda mode? Comment at: lib/Sema/SemaCUDA.cpp:791 + CUDAFunctionTarget NewTarget = IdentifyCUDATarget(NewFD); + for (auto OldND : Previous) { +FunctionDecl *OldFD = OldND->getAsFunction(); If this is just a Decl* or NamedDecl*, can we write out the type? Comment at: lib/Sema/SemaCUDA.cpp:793 +FunctionDecl *OldFD = OldND->getAsFunction(); +if (!OldFD || OldFD->isFunctionTemplateSpecialization()) + continue; Please add a comment explaining why we ignore template specializations. Comment at: lib/Sema/SemaTemplate.cpp:7044 + // Filter out matches that have different target. + if (LangOpts.CUDA && Can we have a better comment here? (And, can we expand upon it in D25845?) Comment at: lib/Sema/SemaTemplate.cpp:8117 +if (LangOpts.CUDA && +IdentifyCUDATarget(Specialization) != IdentifyCUDATarget(Attr)) { + FailedCandidates.addCandidate().set( Can we just pass D here (and thus not write the new overload of IdentifyCUDATarget)? Comment at: test/SemaCUDA/function-template-overload.cu:34 + +// Can't overload HD template with H or D template, though functions are OK. +template __host__ __device__ HDType overload_hd(T a) { return HDType(); } "though non-template functions are OK"? Comment at: test/SemaCUDA/function-template-overload.cu:44 +// explicitly specialize or instantiate function tempaltes. +template <> __host__ HType overload_hd(int a); +// expected-error@-1 {{no function template matches function template specialization 'overload_hd'}} This is OK: template __host__ __device__ HDType overload_hd(T a); template <> __host__ HType overload_hd(int a); but this is not OK: template __host__ HType overload_h_d(T a) { return HType(); } template __device__ DType overload_h_d(T a) { return DType(); } template <> __device__ __host__ DType overload_h_d(long a); Is the rule that you *can* specialize an HD function template as H or D, but you can't go in reverse? If so, I am not getting that from the commit message or comments here. Like in D25705, please clarify this somewhere in the code (and commit message) if this isn't just me blatantly misreading things (which is possible). Comment at: test/SemaCUDA/function-template-overload.cu:44 +// explicitly specialize or instantiate function tempaltes. +template <> __host__ HType overload_hd(int a); +// expected-error@-1 {{no function template matches function template specialization 'overload_hd'}} Please ignore the above comment; it is not correct, but I cannot delete it or edit it in phab. :-/ https://reviews.llvm.org/D25809 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25809: [CUDA] Improved target attribute-based overloading.
tra created this revision. tra added reviewers: jlebar, rsmith. tra added a subscriber: cfe-commits. Current behavior: - __host__ __device__ (HD) functions are considered to be redeclarations of `__host__` (H) of `__device__` (D) functions with same signature. - Target attributes are not taken into account during selection of function template during explicit instantiation and specialization. Issues: a) It's possible for a H or D function to inherit HD attributes from a HD declaration which results in those functions being silently treated as HD in the rest of the code which leads to clang accepting the code instead of diagnosing it as an error. b) If we have definitions of HD and a H or D function, compiler complains about redefinition of the same function, which is misleading. c) It is impossible to disambiguate across target-overloaded function templates during explicit instantiation/specialization. Changes in this patch: a) treat HD functions as overloads and add Sema checks to explicitly diagnose attempts to overload HD functions with H or D ones. b) Require matching target attributes for explicit function template instantiation/specialization and narrow list of candidates to templates with the same target. Diagnose rejected candidates. The changes (a) and (b) can be split into separate patches, but both must be committed simultaneously as (a) alone further breaks function template instantiation/specialization when target attributes are involved and (b) is half-broken until (a) is in place and prevents HD attributes merging into functions with H or D attributes. Open issues: - It's not clear how to handle explicit specialization of constexpr function templates: - Implicit target attributes of constexpr functions and templates change depending on whether -fno-cuda-host-device-constexpr is in effect. - C++11 [dcl.constexpr]p1: An explicit specialization of a constexpr function can differ from the template declaration with respect to the constexpr specifier. One idea is to only match explicitly written target attributes when we choose candidate templates. This makes it easier to tell which template we instantiate based only on what's in the source we compile. https://reviews.llvm.org/D25809 Files: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaCUDA.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp test/CodeGenCUDA/launch-bounds.cu test/SemaCUDA/function-overload.cu test/SemaCUDA/function-template-overload.cu test/SemaCUDA/target_attr_inheritance.cu Index: test/SemaCUDA/target_attr_inheritance.cu === --- test/SemaCUDA/target_attr_inheritance.cu +++ /dev/null @@ -1,29 +0,0 @@ -// Verifies correct inheritance of target attributes during template -// instantiation and specialization. - -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s - -#include "Inputs/cuda.h" - -// Function must inherit target attributes during instantiation, but not during -// specialization. -template __host__ __device__ T function_template(const T ); - -// Specialized functions have their own attributes. -// expected-note@+1 {{candidate function not viable: call to __host__ function from __device__ function}} -template <> __host__ float function_template(const float ); - -// expected-note@+1 {{candidate function not viable: call to __device__ function from __host__ function}} -template <> __device__ double function_template(const double ); - -__host__ void hf() { - function_template(1.0f); // OK. Specialization is __host__. - function_template(2.0); // expected-error {{no matching function for call to 'function_template'}} - function_template(1); // OK. Instantiated function template is HD. -} -__device__ void df() { - function_template(3.0f); // expected-error {{no matching function for call to 'function_template'}} - function_template(4.0); // OK. Specialization is __device__. - function_template(1); // OK. Instantiated function template is HD. -} Index: test/SemaCUDA/function-template-overload.cu === --- /dev/null +++ test/SemaCUDA/function-template-overload.cu @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s + +#include "Inputs/cuda.h" + +struct HType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'DType'}} +struct DType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'HType'}} +struct HDType {}; + +template __host__ HType overload_h_d(T a) { return HType(); } +// expected-note@-1 2 {{candidate