[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 15:41:37 +03:00
|
|
|
//===- SemaSYCL.cpp - Semantic Analysis for SYCL constructs ---------------===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// This implements Semantic Analysis for SYCL constructs.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2021-04-23 08:22:35 -07:00
|
|
|
#include "clang/AST/Mangle.h"
|
[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 15:41:37 +03:00
|
|
|
#include "clang/Sema/Sema.h"
|
|
|
|
#include "clang/Sema/SemaDiagnostic.h"
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// SYCL device specific diagnostics implementation
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
2020-09-23 18:00:23 -04:00
|
|
|
Sema::SemaDiagnosticBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc,
|
|
|
|
unsigned DiagID) {
|
[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 15:41:37 +03:00
|
|
|
assert(getLangOpts().SYCLIsDevice &&
|
|
|
|
"Should only be called during SYCL compilation");
|
|
|
|
FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext());
|
2020-09-23 18:00:23 -04:00
|
|
|
SemaDiagnosticBuilder::Kind DiagKind = [this, FD] {
|
[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 15:41:37 +03:00
|
|
|
if (!FD)
|
2020-09-23 18:00:23 -04:00
|
|
|
return SemaDiagnosticBuilder::K_Nop;
|
[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 15:41:37 +03:00
|
|
|
if (getEmissionStatus(FD) == Sema::FunctionEmissionStatus::Emitted)
|
2020-09-23 18:00:23 -04:00
|
|
|
return SemaDiagnosticBuilder::K_ImmediateWithCallStack;
|
|
|
|
return SemaDiagnosticBuilder::K_Deferred;
|
[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 15:41:37 +03:00
|
|
|
}();
|
2020-09-23 18:00:23 -04:00
|
|
|
return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, FD, *this);
|
[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 15:41:37 +03:00
|
|
|
}
|
|
|
|
|
2021-12-29 13:46:15 +03:00
|
|
|
static bool isZeroSizedArray(Sema &SemaRef, QualType Ty) {
|
|
|
|
if (const auto *CAT = SemaRef.getASTContext().getAsConstantArrayType(Ty))
|
|
|
|
return CAT->getSize() == 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
|
|
|
|
llvm::DenseSet<QualType> Visited,
|
|
|
|
ValueDecl *DeclToCheck) {
|
|
|
|
assert(getLangOpts().SYCLIsDevice &&
|
|
|
|
"Should only be called during SYCL compilation");
|
|
|
|
// Emit notes only for the first discovered declaration of unsupported type
|
|
|
|
// to avoid mess of notes. This flag is to track that error already happened.
|
|
|
|
bool NeedToEmitNotes = true;
|
|
|
|
|
|
|
|
auto Check = [&](QualType TypeToCheck, const ValueDecl *D) {
|
|
|
|
bool ErrorFound = false;
|
|
|
|
if (isZeroSizedArray(*this, TypeToCheck)) {
|
|
|
|
SYCLDiagIfDeviceCode(UsedAt, diag::err_typecheck_zero_array_size) << 1;
|
|
|
|
ErrorFound = true;
|
|
|
|
}
|
|
|
|
// Checks for other types can also be done here.
|
|
|
|
if (ErrorFound) {
|
|
|
|
if (NeedToEmitNotes) {
|
|
|
|
if (auto *FD = dyn_cast<FieldDecl>(D))
|
|
|
|
SYCLDiagIfDeviceCode(FD->getLocation(),
|
|
|
|
diag::note_illegal_field_declared_here)
|
|
|
|
<< FD->getType()->isPointerType() << FD->getType();
|
|
|
|
else
|
|
|
|
SYCLDiagIfDeviceCode(D->getLocation(), diag::note_declared_at);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ErrorFound;
|
|
|
|
};
|
|
|
|
|
|
|
|
// In case we have a Record used do the DFS for a bad field.
|
|
|
|
SmallVector<const ValueDecl *, 4> StackForRecursion;
|
|
|
|
StackForRecursion.push_back(DeclToCheck);
|
|
|
|
|
|
|
|
// While doing DFS save how we get there to emit a nice set of notes.
|
|
|
|
SmallVector<const FieldDecl *, 4> History;
|
|
|
|
History.push_back(nullptr);
|
|
|
|
|
|
|
|
do {
|
|
|
|
const ValueDecl *Next = StackForRecursion.pop_back_val();
|
|
|
|
if (!Next) {
|
|
|
|
assert(!History.empty());
|
|
|
|
// Found a marker, we have gone up a level.
|
|
|
|
History.pop_back();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
QualType NextTy = Next->getType();
|
|
|
|
|
|
|
|
if (!Visited.insert(NextTy).second)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
auto EmitHistory = [&]() {
|
|
|
|
// The first element is always nullptr.
|
|
|
|
for (uint64_t Index = 1; Index < History.size(); ++Index) {
|
|
|
|
SYCLDiagIfDeviceCode(History[Index]->getLocation(),
|
|
|
|
diag::note_within_field_of_type)
|
|
|
|
<< History[Index]->getType();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (Check(NextTy, Next)) {
|
|
|
|
if (NeedToEmitNotes)
|
|
|
|
EmitHistory();
|
|
|
|
NeedToEmitNotes = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// In case pointer/array/reference type is met get pointee type, then
|
|
|
|
// proceed with that type.
|
|
|
|
while (NextTy->isAnyPointerType() || NextTy->isArrayType() ||
|
|
|
|
NextTy->isReferenceType()) {
|
|
|
|
if (NextTy->isArrayType())
|
|
|
|
NextTy = QualType{NextTy->getArrayElementTypeNoTypeQual(), 0};
|
|
|
|
else
|
|
|
|
NextTy = NextTy->getPointeeType();
|
|
|
|
if (Check(NextTy, Next)) {
|
|
|
|
if (NeedToEmitNotes)
|
|
|
|
EmitHistory();
|
|
|
|
NeedToEmitNotes = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const auto *RecDecl = NextTy->getAsRecordDecl()) {
|
|
|
|
if (auto *NextFD = dyn_cast<FieldDecl>(Next))
|
|
|
|
History.push_back(NextFD);
|
|
|
|
// When nullptr is discovered, this means we've gone back up a level, so
|
|
|
|
// the history should be cleaned.
|
|
|
|
StackForRecursion.push_back(nullptr);
|
|
|
|
llvm::copy(RecDecl->fields(), std::back_inserter(StackForRecursion));
|
|
|
|
}
|
|
|
|
} while (!StackForRecursion.empty());
|
|
|
|
}
|