Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darkbuck/836dbb3112ca2e5fab769cf3cdaecd09 to your computer and use it in GitHub Desktop.
Save darkbuck/836dbb3112ca2e5fab769cf3cdaecd09 to your computer and use it in GitHub Desktop.
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