
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.
100 lines
3.8 KiB
C++
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
|