SemaSYCL.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. //===- SemaSYCL.cpp - Semantic Analysis for SYCL constructs ---------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. // This implements Semantic Analysis for SYCL constructs.
  9. //===----------------------------------------------------------------------===//
  10. #include "clang/AST/Mangle.h"
  11. #include "clang/Sema/Sema.h"
  12. #include "clang/Sema/SemaDiagnostic.h"
  13. using namespace clang;
  14. // -----------------------------------------------------------------------------
  15. // SYCL device specific diagnostics implementation
  16. // -----------------------------------------------------------------------------
  17. Sema::SemaDiagnosticBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc,
  18. unsigned DiagID) {
  19. assert(getLangOpts().SYCLIsDevice &&
  20. "Should only be called during SYCL compilation");
  21. FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext());
  22. SemaDiagnosticBuilder::Kind DiagKind = [this, FD] {
  23. if (!FD)
  24. return SemaDiagnosticBuilder::K_Nop;
  25. if (getEmissionStatus(FD) == Sema::FunctionEmissionStatus::Emitted)
  26. return SemaDiagnosticBuilder::K_ImmediateWithCallStack;
  27. return SemaDiagnosticBuilder::K_Deferred;
  28. }();
  29. return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, FD, *this);
  30. }
  31. bool Sema::checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee) {
  32. assert(getLangOpts().SYCLIsDevice &&
  33. "Should only be called during SYCL compilation");
  34. assert(Callee && "Callee may not be null.");
  35. // Errors in an unevaluated context don't need to be generated,
  36. // so we can safely skip them.
  37. if (isUnevaluatedContext() || isConstantEvaluated())
  38. return true;
  39. SemaDiagnosticBuilder::Kind DiagKind = SemaDiagnosticBuilder::K_Nop;
  40. return DiagKind != SemaDiagnosticBuilder::K_Immediate &&
  41. DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack;
  42. }
  43. static bool isZeroSizedArray(Sema &SemaRef, QualType Ty) {
  44. if (const auto *CAT = SemaRef.getASTContext().getAsConstantArrayType(Ty))
  45. return CAT->getSize() == 0;
  46. return false;
  47. }
  48. void Sema::deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
  49. llvm::DenseSet<QualType> Visited,
  50. ValueDecl *DeclToCheck) {
  51. assert(getLangOpts().SYCLIsDevice &&
  52. "Should only be called during SYCL compilation");
  53. // Emit notes only for the first discovered declaration of unsupported type
  54. // to avoid mess of notes. This flag is to track that error already happened.
  55. bool NeedToEmitNotes = true;
  56. auto Check = [&](QualType TypeToCheck, const ValueDecl *D) {
  57. bool ErrorFound = false;
  58. if (isZeroSizedArray(*this, TypeToCheck)) {
  59. SYCLDiagIfDeviceCode(UsedAt, diag::err_typecheck_zero_array_size) << 1;
  60. ErrorFound = true;
  61. }
  62. // Checks for other types can also be done here.
  63. if (ErrorFound) {
  64. if (NeedToEmitNotes) {
  65. if (auto *FD = dyn_cast<FieldDecl>(D))
  66. SYCLDiagIfDeviceCode(FD->getLocation(),
  67. diag::note_illegal_field_declared_here)
  68. << FD->getType()->isPointerType() << FD->getType();
  69. else
  70. SYCLDiagIfDeviceCode(D->getLocation(), diag::note_declared_at);
  71. }
  72. }
  73. return ErrorFound;
  74. };
  75. // In case we have a Record used do the DFS for a bad field.
  76. SmallVector<const ValueDecl *, 4> StackForRecursion;
  77. StackForRecursion.push_back(DeclToCheck);
  78. // While doing DFS save how we get there to emit a nice set of notes.
  79. SmallVector<const FieldDecl *, 4> History;
  80. History.push_back(nullptr);
  81. do {
  82. const ValueDecl *Next = StackForRecursion.pop_back_val();
  83. if (!Next) {
  84. assert(!History.empty());
  85. // Found a marker, we have gone up a level.
  86. History.pop_back();
  87. continue;
  88. }
  89. QualType NextTy = Next->getType();
  90. if (!Visited.insert(NextTy).second)
  91. continue;
  92. auto EmitHistory = [&]() {
  93. // The first element is always nullptr.
  94. for (uint64_t Index = 1; Index < History.size(); ++Index) {
  95. SYCLDiagIfDeviceCode(History[Index]->getLocation(),
  96. diag::note_within_field_of_type)
  97. << History[Index]->getType();
  98. }
  99. };
  100. if (Check(NextTy, Next)) {
  101. if (NeedToEmitNotes)
  102. EmitHistory();
  103. NeedToEmitNotes = false;
  104. }
  105. // In case pointer/array/reference type is met get pointee type, then
  106. // proceed with that type.
  107. while (NextTy->isAnyPointerType() || NextTy->isArrayType() ||
  108. NextTy->isReferenceType()) {
  109. if (NextTy->isArrayType())
  110. NextTy = QualType{NextTy->getArrayElementTypeNoTypeQual(), 0};
  111. else
  112. NextTy = NextTy->getPointeeType();
  113. if (Check(NextTy, Next)) {
  114. if (NeedToEmitNotes)
  115. EmitHistory();
  116. NeedToEmitNotes = false;
  117. }
  118. }
  119. if (const auto *RecDecl = NextTy->getAsRecordDecl()) {
  120. if (auto *NextFD = dyn_cast<FieldDecl>(Next))
  121. History.push_back(NextFD);
  122. // When nullptr is discovered, this means we've gone back up a level, so
  123. // the history should be cleaned.
  124. StackForRecursion.push_back(nullptr);
  125. llvm::copy(RecDecl->fields(), std::back_inserter(StackForRecursion));
  126. }
  127. } while (!StackForRecursion.empty());
  128. }