Created
March 27, 2020 20:42
-
-
Save darkbuck/836dbb3112ca2e5fab769cf3cdaecd09 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| From 2e138f850b233ab2d19f0269000a7abb29f4a828 Mon Sep 17 00:00:00 2001 | |
| From: Michael Liao <michael.hliao@gmail.com> | |
| Date: Fri, 27 Mar 2020 15:21:50 -0400 | |
| Subject: [PATCH 1/1] Support template partial specialization. | |
| --- | |
| .../clang/Basic/DiagnosticSemaKinds.td | 7 - | |
| clang/lib/CodeGen/CodeGenModule.cpp | 2 +- | |
| clang/lib/Sema/SemaDeclCXX.cpp | 193 ++++++------------ | |
| clang/test/CodeGenCUDA/surface.cu | 7 +- | |
| 4 files changed, 70 insertions(+), 139 deletions(-) | |
| diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td | |
| index 044d35f19e2..3ea132b193a 100644 | |
| --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td | |
| +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td | |
| @@ -7982,13 +7982,6 @@ def err_cuda_device_builtin_surftex_ref_decl : Error< | |
| def note_cuda_device_builtin_surftex_should_be_template_class : Note< | |
| "%0 needs to be instantiated from a class template with proper " | |
| "template arguments">; | |
| -def note_cuda_device_builtin_surftex_should_have_n_args : Note< | |
| - "%0 needs to be instantiated from a class template with exactly " | |
| - "%1 template arguments">; | |
| -def note_cuda_device_builtin_surftex_should_have_match_arg : Note< | |
| - "%0 needs to be instantiated from a class template with the " | |
| - "%select{1st|2nd|3rd}1 template argument as " | |
| - "%select{a type|an integral value}2">; | |
| def warn_non_pod_vararg_with_format_string : Warning< | |
| "cannot pass %select{non-POD|non-trivial}0 object of type %1 to variadic " | |
| diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp | |
| index fbde1bf5cab..963638cacb1 100644 | |
| --- a/clang/lib/CodeGen/CodeGenModule.cpp | |
| +++ b/clang/lib/CodeGen/CodeGenModule.cpp | |
| @@ -4063,7 +4063,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, | |
| const ClassTemplateSpecializationDecl *TD = | |
| cast<ClassTemplateSpecializationDecl>( | |
| D->getType()->getAs<RecordType>()->getDecl()); | |
| - const TemplateArgumentList &Args = TD->getTemplateInstantiationArgs(); | |
| + const TemplateArgumentList &Args = TD->getTemplateArgs(); | |
| if (TD->hasAttr<CUDADeviceBuiltinSurfaceTypeAttr>()) { | |
| assert(Args.size() == 2 && | |
| "Unexpected number of template arguments of CUDA device " | |
| diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp | |
| index 27488557e1b..46c46176499 100644 | |
| --- a/clang/lib/Sema/SemaDeclCXX.cpp | |
| +++ b/clang/lib/Sema/SemaDeclCXX.cpp | |
| @@ -5881,38 +5881,52 @@ static void checkCUDADeviceBuiltinSurfaceClassTemplate(Sema &S, | |
| CXXRecordDecl *Class) { | |
| bool ErrorReported = false; | |
| auto reportIllegalClassTemplate = [&ErrorReported](Sema &S, | |
| - CXXRecordDecl *RD) { | |
| + ClassTemplateDecl *TD) { | |
| if (ErrorReported) | |
| return; | |
| - S.Diag(RD->getLocation(), | |
| + S.Diag(TD->getLocation(), | |
| diag::err_cuda_device_builtin_surftex_cls_template) | |
| - << /*surface*/ 0 << RD; | |
| + << /*surface*/ 0 << TD; | |
| ErrorReported = true; | |
| }; | |
| - TemplateParameterList *Params = | |
| - Class->getDescribedClassTemplate()->getTemplateParameters(); | |
| + ClassTemplateDecl *TD = Class->getDescribedClassTemplate(); | |
| + if (!TD) { | |
| + auto *SD = dyn_cast<ClassTemplateSpecializationDecl>(Class); | |
| + if (!SD) { | |
| + S.Diag(Class->getLocation(), | |
| + diag::err_cuda_device_builtin_surftex_ref_decl) | |
| + << /*surface*/ 0 << Class; | |
| + S.Diag(Class->getLocation(), | |
| + diag::note_cuda_device_builtin_surftex_should_be_template_class) | |
| + << Class; | |
| + return; | |
| + } | |
| + TD = SD->getSpecializedTemplate(); | |
| + } | |
| + | |
| + TemplateParameterList *Params = TD->getTemplateParameters(); | |
| unsigned N = Params->size(); | |
| if (N != 2) { | |
| - reportIllegalClassTemplate(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| + reportIllegalClassTemplate(S, TD); | |
| + S.Diag(TD->getLocation(), | |
| diag::note_cuda_device_builtin_surftex_cls_should_have_n_args) | |
| - << Class << 2; | |
| + << TD << 2; | |
| } | |
| if (N > 0 && !isa<TemplateTypeParmDecl>(Params->getParam(0))) { | |
| - reportIllegalClassTemplate(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| + reportIllegalClassTemplate(S, TD); | |
| + S.Diag(TD->getLocation(), | |
| diag::note_cuda_device_builtin_surftex_cls_should_have_match_arg) | |
| - << Class << /*1st*/ 0 << /*type*/ 0; | |
| + << TD << /*1st*/ 0 << /*type*/ 0; | |
| } | |
| if (N > 1) { | |
| auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(1)); | |
| if (!NTTP || !NTTP->getType()->isIntegralOrEnumerationType()) { | |
| - reportIllegalClassTemplate(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| + reportIllegalClassTemplate(S, TD); | |
| + S.Diag(TD->getLocation(), | |
| diag::note_cuda_device_builtin_surftex_cls_should_have_match_arg) | |
| - << Class << /*2nd*/ 1 << /*integer*/ 1; | |
| + << TD << /*2nd*/ 1 << /*integer*/ 1; | |
| } | |
| } | |
| } | |
| @@ -5921,139 +5935,65 @@ static void checkCUDADeviceBuiltinTextureClassTemplate(Sema &S, | |
| CXXRecordDecl *Class) { | |
| bool ErrorReported = false; | |
| auto reportIllegalClassTemplate = [&ErrorReported](Sema &S, | |
| - CXXRecordDecl *RD) { | |
| + ClassTemplateDecl *TD) { | |
| if (ErrorReported) | |
| return; | |
| - S.Diag(RD->getLocation(), | |
| + S.Diag(TD->getLocation(), | |
| diag::err_cuda_device_builtin_surftex_cls_template) | |
| - << /*texture*/ 1 << RD; | |
| + << /*texture*/ 1 << TD; | |
| ErrorReported = true; | |
| }; | |
| - TemplateParameterList *Params = | |
| - Class->getDescribedClassTemplate()->getTemplateParameters(); | |
| + ClassTemplateDecl *TD = Class->getDescribedClassTemplate(); | |
| + if (!TD) { | |
| + auto *SD = dyn_cast<ClassTemplateSpecializationDecl>(Class); | |
| + if (!SD) { | |
| + S.Diag(Class->getLocation(), | |
| + diag::err_cuda_device_builtin_surftex_ref_decl) | |
| + << /*texture*/ 1 << Class; | |
| + S.Diag(Class->getLocation(), | |
| + diag::note_cuda_device_builtin_surftex_should_be_template_class) | |
| + << Class; | |
| + return; | |
| + } | |
| + TD = SD->getSpecializedTemplate(); | |
| + } | |
| + | |
| + TemplateParameterList *Params = TD->getTemplateParameters(); | |
| unsigned N = Params->size(); | |
| if (N != 3) { | |
| - reportIllegalClassTemplate(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| + reportIllegalClassTemplate(S, TD); | |
| + S.Diag(TD->getLocation(), | |
| diag::note_cuda_device_builtin_surftex_cls_should_have_n_args) | |
| - << Class << 3; | |
| + << TD << 3; | |
| } | |
| if (N > 0 && !isa<TemplateTypeParmDecl>(Params->getParam(0))) { | |
| - reportIllegalClassTemplate(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| + reportIllegalClassTemplate(S, TD); | |
| + S.Diag(TD->getLocation(), | |
| diag::note_cuda_device_builtin_surftex_cls_should_have_match_arg) | |
| - << Class << /*1st*/ 0 << /*type*/ 0; | |
| + << TD << /*1st*/ 0 << /*type*/ 0; | |
| } | |
| if (N > 1) { | |
| auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(1)); | |
| if (!NTTP || !NTTP->getType()->isIntegralOrEnumerationType()) { | |
| - reportIllegalClassTemplate(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| + reportIllegalClassTemplate(S, TD); | |
| + S.Diag(TD->getLocation(), | |
| diag::note_cuda_device_builtin_surftex_cls_should_have_match_arg) | |
| - << Class << /*2nd*/ 1 << /*integer*/ 1; | |
| + << TD << /*2nd*/ 1 << /*integer*/ 1; | |
| } | |
| } | |
| if (N > 2) { | |
| auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(2)); | |
| if (!NTTP || !NTTP->getType()->isIntegralOrEnumerationType()) { | |
| - reportIllegalClassTemplate(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| + reportIllegalClassTemplate(S, TD); | |
| + S.Diag(TD->getLocation(), | |
| diag::note_cuda_device_builtin_surftex_cls_should_have_match_arg) | |
| - << Class << /*3rd*/ 2 << /*integer*/ 1; | |
| + << TD << /*3rd*/ 2 << /*integer*/ 1; | |
| } | |
| } | |
| } | |
| -static void checkCUDADeviceBuiltinSurfaceType(Sema &S, CXXRecordDecl *Class) { | |
| - bool ErrorReported = false; | |
| - auto reportIllegalReferenceType = [&ErrorReported](Sema &S, | |
| - CXXRecordDecl *RD) { | |
| - if (ErrorReported) | |
| - return; | |
| - S.Diag(RD->getLocation(), diag::err_cuda_device_builtin_surftex_ref_decl) | |
| - << /*surface*/ 0 << RD; | |
| - ErrorReported = true; | |
| - }; | |
| - | |
| - const auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(Class); | |
| - if (!TD) { | |
| - reportIllegalReferenceType(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| - diag::note_cuda_device_builtin_surftex_should_be_template_class) | |
| - << Class; | |
| - return; | |
| - } | |
| - const auto &Args = TD->getTemplateInstantiationArgs(); | |
| - unsigned N = Args.size(); | |
| - if (N != 2) { | |
| - reportIllegalReferenceType(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| - diag::note_cuda_device_builtin_surftex_should_have_n_args) | |
| - << Class << /*nargs*/ 2; | |
| - } | |
| - if (N > 0 && Args[0].getKind() != TemplateArgument::Type) { | |
| - reportIllegalReferenceType(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| - diag::note_cuda_device_builtin_surftex_should_have_match_arg) | |
| - << Class << /*1st*/ 0 << /*type*/ 0; | |
| - } | |
| - if (N > 1 && Args[1].getKind() != TemplateArgument::Integral) { | |
| - reportIllegalReferenceType(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| - diag::note_cuda_device_builtin_surftex_should_have_match_arg) | |
| - << Class << /*2nd*/ 1 << /*integral*/ 1; | |
| - } | |
| -} | |
| - | |
| -static void checkCUDADeviceBuiltinTextureType(Sema &S, CXXRecordDecl *Class) { | |
| - bool ErrorReported = false; | |
| - auto reportIllegalReferenceType = [&ErrorReported](Sema &S, | |
| - CXXRecordDecl *RD) { | |
| - if (ErrorReported) | |
| - return; | |
| - S.Diag(RD->getLocation(), diag::err_cuda_device_builtin_surftex_ref_decl) | |
| - << /*texture*/ 1 << RD; | |
| - ErrorReported = true; | |
| - }; | |
| - | |
| - const auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(Class); | |
| - if (!TD) { | |
| - reportIllegalReferenceType(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| - diag::note_cuda_device_builtin_surftex_should_be_template_class) | |
| - << Class; | |
| - return; | |
| - } | |
| - const auto &Args = TD->getTemplateInstantiationArgs(); | |
| - unsigned N = Args.size(); | |
| - if (N != 3) { | |
| - reportIllegalReferenceType(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| - diag::note_cuda_device_builtin_surftex_should_have_n_args) | |
| - << Class << /*nargs*/ 3; | |
| - } | |
| - if (N > 0 && Args[0].getKind() != TemplateArgument::Type) { | |
| - reportIllegalReferenceType(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| - diag::note_cuda_device_builtin_surftex_should_have_match_arg) | |
| - << Class << /*1st*/ 0 << /*type*/ 0; | |
| - } | |
| - if (N > 1 && Args[1].getKind() != TemplateArgument::Integral) { | |
| - reportIllegalReferenceType(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| - diag::note_cuda_device_builtin_surftex_should_have_match_arg) | |
| - << Class << /*2nd*/ 1 << /*integral*/ 1; | |
| - } | |
| - if (N > 2 && Args[2].getKind() != TemplateArgument::Integral) { | |
| - reportIllegalReferenceType(S, Class); | |
| - S.Diag(Class->getLocation(), | |
| - diag::note_cuda_device_builtin_surftex_should_have_match_arg) | |
| - << Class << /*3rd*/ 2 << /*integral*/ 1; | |
| - } | |
| -} | |
| - | |
| void Sema::checkClassLevelCodeSegAttribute(CXXRecordDecl *Class) { | |
| // Mark any compiler-generated routines with the implicit code_seg attribute. | |
| for (auto *Method : Class->methods()) { | |
| @@ -6836,17 +6776,10 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { | |
| } | |
| if (getLangOpts().CUDA) { | |
| - if (Record->getDescribedClassTemplate()) { | |
| - if (Record->hasAttr<CUDADeviceBuiltinSurfaceTypeAttr>()) | |
| - checkCUDADeviceBuiltinSurfaceClassTemplate(*this, Record); | |
| - else if (Record->hasAttr<CUDADeviceBuiltinTextureTypeAttr>()) | |
| - checkCUDADeviceBuiltinTextureClassTemplate(*this, Record); | |
| - } else { | |
| - if (Record->hasAttr<CUDADeviceBuiltinSurfaceTypeAttr>()) | |
| - checkCUDADeviceBuiltinSurfaceType(*this, Record); | |
| - else if (Record->hasAttr<CUDADeviceBuiltinTextureTypeAttr>()) | |
| - checkCUDADeviceBuiltinTextureType(*this, Record); | |
| - } | |
| + if (Record->hasAttr<CUDADeviceBuiltinSurfaceTypeAttr>()) | |
| + checkCUDADeviceBuiltinSurfaceClassTemplate(*this, Record); | |
| + else if (Record->hasAttr<CUDADeviceBuiltinTextureTypeAttr>()) | |
| + checkCUDADeviceBuiltinTextureClassTemplate(*this, Record); | |
| } | |
| } | |
| diff --git a/clang/test/CodeGenCUDA/surface.cu b/clang/test/CodeGenCUDA/surface.cu | |
| index c4c0a59f495..a28e052fc2b 100644 | |
| --- a/clang/test/CodeGenCUDA/surface.cu | |
| +++ b/clang/test/CodeGenCUDA/surface.cu | |
| @@ -9,10 +9,15 @@ struct surfaceReference { | |
| int desc; | |
| }; | |
| -template <typename T, int type = 1> | |
| +template <typename T, int dim = 1> | |
| struct __attribute__((device_builtin_surface_type)) surface : public surfaceReference { | |
| }; | |
| +// Partial specialization over `void`. | |
| +template<int dim> | |
| +struct __attribute__((device_builtin_surface_type)) surface<void, dim> : public surfaceReference { | |
| +}; | |
| + | |
| // On the device side, surface references are represented as `i64` handles. | |
| // DEVICE: @surf = addrspace(1) global i64 undef, align 4 | |
| // On the host side, they remain in the original type. | |
| -- | |
| 2.26.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment