llvm-project/clang/lib/Sema/SemaOpenCL.cpp
Vlad Serebrennikov 6b755b0cf4
[clang] Split up SemaDeclAttr.cpp (#93966)
This patch moves language- and target-specific functions out of
`SemaDeclAttr.cpp`. As a consequence, `SemaAVR`, `SemaM68k`,
`SemaMSP430`, `SemaOpenCL`, `SemaSwift` were created (but they are not
the only languages and targets affected).

Notable things are that `Sema.h` actually grew a bit, because of
templated helpers that rely on `Sema` that I had to make available from
outside of `SemaDeclAttr.cpp`. I also had to left CUDA-related in
`SemaDeclAttr.cpp`, because it looks like HIP is building up on top of
CUDA attributes.

This is a follow-up to #93179 and continuation of efforts to split
`Sema` up. Additional context can be found in #84184 and #92682.
2024-06-05 09:46:37 +04:00

100 lines
3.8 KiB
C++

//===--- SemaOpenCL.cpp --- Semantic Analysis for OpenCL 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file implements semantic analysis for OpenCL.
///
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaOpenCL.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclBase.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Sema.h"
namespace clang {
SemaOpenCL::SemaOpenCL(Sema &S) : SemaBase(S) {}
void SemaOpenCL::handleNoSVMAttr(Decl *D, const ParsedAttr &AL) {
if (getLangOpts().getOpenCLCompatibleVersion() < 200)
Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version)
<< AL << "2.0" << 1;
else
Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored)
<< AL << getLangOpts().getOpenCLVersionString();
}
void SemaOpenCL::handleAccessAttr(Decl *D, const ParsedAttr &AL) {
if (D->isInvalidDecl())
return;
// Check if there is only one access qualifier.
if (D->hasAttr<OpenCLAccessAttr>()) {
if (D->getAttr<OpenCLAccessAttr>()->getSemanticSpelling() ==
AL.getSemanticSpelling()) {
Diag(AL.getLoc(), diag::warn_duplicate_declspec)
<< AL.getAttrName()->getName() << AL.getRange();
} else {
Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers)
<< D->getSourceRange();
D->setInvalidDecl(true);
return;
}
}
// OpenCL v2.0 s6.6 - read_write can be used for image types to specify that
// an image object can be read and written. OpenCL v2.0 s6.13.6 - A kernel
// cannot read from and write to the same pipe object. Using the read_write
// (or __read_write) qualifier with the pipe qualifier is a compilation error.
// OpenCL v3.0 s6.8 - For OpenCL C 2.0, or with the
// __opencl_c_read_write_images feature, image objects specified as arguments
// to a kernel can additionally be declared to be read-write.
// C++ for OpenCL 1.0 inherits rule from OpenCL C v2.0.
// C++ for OpenCL 2021 inherits rule from OpenCL C v3.0.
if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) {
const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();
if (AL.getAttrName()->getName().contains("read_write")) {
bool ReadWriteImagesUnsupported =
(getLangOpts().getOpenCLCompatibleVersion() < 200) ||
(getLangOpts().getOpenCLCompatibleVersion() == 300 &&
!SemaRef.getOpenCLOptions().isSupported(
"__opencl_c_read_write_images", getLangOpts()));
if (ReadWriteImagesUnsupported || DeclTy->isPipeType()) {
Diag(AL.getLoc(), diag::err_opencl_invalid_read_write)
<< AL << PDecl->getType() << DeclTy->isImageType();
D->setInvalidDecl(true);
return;
}
}
}
D->addAttr(::new (getASTContext()) OpenCLAccessAttr(getASTContext(), AL));
}
void SemaOpenCL::handleSubGroupSize(Decl *D, const ParsedAttr &AL) {
uint32_t SGSize;
const Expr *E = AL.getArgAsExpr(0);
if (!SemaRef.checkUInt32Argument(AL, E, SGSize))
return;
if (SGSize == 0) {
Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
<< AL << E->getSourceRange();
return;
}
OpenCLIntelReqdSubGroupSizeAttr *Existing =
D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>();
if (Existing && Existing->getSubGroupSize() != SGSize)
Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
D->addAttr(::new (getASTContext())
OpenCLIntelReqdSubGroupSizeAttr(getASTContext(), AL, SGSize));
}
} // namespace clang