Skip to content

Commit 3ca000a

Browse files
committed
[SYCL] Improve SYCL API class matching.
Signed-off-by: Vladimir Lazarev <vladimir.lazarev@intel.com>
1 parent 4095f94 commit 3ca000a

File tree

1 file changed

+73
-13
lines changed

1 file changed

+73
-13
lines changed

clang/lib/Sema/SemaSYCL.cpp

+73-13
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "llvm/Support/Path.h"
2222
#include "llvm/Support/raw_ostream.h"
2323

24+
#include <array>
25+
2426
using namespace clang;
2527

2628
typedef llvm::DenseMap<DeclaratorDecl *, DeclaratorDecl *> DeclMap;
@@ -40,19 +42,22 @@ enum target {
4042
/// Various utilities.
4143
class Util {
4244
public:
43-
// TODO SYCL use AST infrastructure instead of string matching
44-
45-
/// Checks whether given clang type is a sycl accessor class.
46-
static bool isSyclAccessorType(QualType Ty) {
47-
std::string Name = Ty.getCanonicalType().getAsString();
48-
return Name.find("class cl::sycl::accessor") != std::string::npos;
49-
}
50-
51-
/// Checks whether given clang type is a sycl stream class.
52-
static bool isSyclStreamType(QualType Ty) {
53-
std::string Name = Ty.getCanonicalType().getAsString();
54-
return Name == "stream";
55-
}
45+
using DeclContextDesc = std::pair<clang::Decl::Kind, StringRef>;
46+
47+
/// Checks whether given clang type is a full specialization of the sycl
48+
/// accessor class.
49+
static bool isSyclAccessorType(const QualType &Ty);
50+
51+
/// Checks whether given clang type is the sycl stream class.
52+
static bool isSyclStreamType(const QualType &Ty);
53+
54+
/// Checks whether given clang type is declared in the given hierarchy of
55+
/// declaration contexts.
56+
/// \param Ty the clang type being checked
57+
/// \param Scopes the declaration scopes leading from the type to the
58+
/// translation unit (excluding the latter)
59+
static bool matchQualifiedTypeName(const QualType &Ty,
60+
ArrayRef<Util::DeclContextDesc> Scopes);
5661
};
5762

5863
static CXXRecordDecl *getKernelObjectType(FunctionDecl *Caller) {
@@ -1017,3 +1022,58 @@ void SYCLIntegrationHeader::endKernel() {
10171022
SYCLIntegrationHeader::SYCLIntegrationHeader(DiagnosticsEngine &_Diag)
10181023
: Diag(_Diag) {}
10191024

1025+
bool Util::isSyclAccessorType(const QualType &Ty) {
1026+
static std::array<DeclContextDesc, 3> Scopes = {
1027+
Util::DeclContextDesc { clang::Decl::Kind::Namespace, "cl" },
1028+
Util::DeclContextDesc { clang::Decl::Kind::Namespace, "sycl" },
1029+
Util::DeclContextDesc { clang::Decl::Kind::ClassTemplateSpecialization,
1030+
"accessor" }
1031+
};
1032+
return matchQualifiedTypeName(Ty, Scopes);
1033+
}
1034+
1035+
bool Util::isSyclStreamType(const QualType &Ty) {
1036+
static std::array<DeclContextDesc, 3> Scopes = {
1037+
Util::DeclContextDesc { clang::Decl::Kind::Namespace, "cl" },
1038+
Util::DeclContextDesc { clang::Decl::Kind::Namespace, "sycl" },
1039+
Util::DeclContextDesc { clang::Decl::Kind::CXXRecord, "stream" }
1040+
};
1041+
return matchQualifiedTypeName(Ty, Scopes);
1042+
}
1043+
1044+
bool Util::matchQualifiedTypeName(const QualType &Ty,
1045+
ArrayRef<Util::DeclContextDesc> Scopes) {
1046+
// The idea: check the declaration context chain starting from the type
1047+
// itself. At each step check the context is of expected kind
1048+
// (namespace) and name.
1049+
const CXXRecordDecl *RecTy = Ty->getAsCXXRecordDecl();
1050+
1051+
if (!RecTy)
1052+
return false; // only classes/structs supported
1053+
const auto *Ctx = dyn_cast<DeclContext>(RecTy);
1054+
StringRef Name = "";
1055+
1056+
for (const auto &Scope : llvm::reverse(Scopes)) {
1057+
clang::Decl::Kind DK = Ctx->getDeclKind();
1058+
1059+
if (DK != Scope.first)
1060+
return false;
1061+
1062+
switch (DK) {
1063+
case clang::Decl::Kind::ClassTemplateSpecialization:
1064+
// ClassTemplateSpecializationDecl inherits from CXXRecordDecl
1065+
case clang::Decl::Kind::CXXRecord:
1066+
Name = cast<CXXRecordDecl>(Ctx)->getName();
1067+
break;
1068+
case clang::Decl::Kind::Namespace:
1069+
Name = cast<NamespaceDecl>(Ctx)->getName();
1070+
break;
1071+
default:
1072+
llvm_unreachable("matchQualifiedTypeName: decl kind not supported");
1073+
}
1074+
if (Name != Scope.second)
1075+
return false;
1076+
Ctx = Ctx->getParent();
1077+
}
1078+
return Ctx->isTranslationUnit();
1079+
}

0 commit comments

Comments
 (0)