summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp29
-rw-r--r--clang/lib/Basic/TargetInfo.cpp6
-rw-r--r--clang/lib/CodeGen/CGCall.cpp3
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp4
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp11
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp2
-rw-r--r--clang/lib/CodeGen/CGExprConstant.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp5
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.cpp9
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp3
-rw-r--r--clang/lib/Parse/ParseDecl.cpp130
-rw-r--r--clang/lib/Sema/AttributeList.cpp1
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp1
-rw-r--r--clang/lib/Sema/SemaType.cpp40
14 files changed, 227 insertions, 19 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index d20c25851e1..fd5fd0e54b2 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -190,6 +190,22 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
return 0;
}
+static const LangAS::Map &getAddressSpaceMap(const TargetInfo &T,
+ const LangOptions &LOpts) {
+ if (LOpts.FakeAddressSpaceMap) {
+ // The fake address space map must have a distinct entry for each
+ // language-specific address space.
+ static const unsigned FakeAddrSpaceMap[] = {
+ 1, // opencl_global
+ 2, // opencl_local
+ 3 // opencl_constant
+ };
+ return FakeAddrSpaceMap;
+ } else {
+ return T.getAddressSpaceMap();
+ }
+}
+
ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
const TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
@@ -204,7 +220,8 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0),
cudaConfigureCallDecl(0),
NullTypeSourceInfo(QualType()),
- SourceMgr(SM), LangOpts(LOpts), ABI(createCXXABI(t)), Target(t),
+ SourceMgr(SM), LangOpts(LOpts), ABI(createCXXABI(t)),
+ AddrSpaceMap(getAddressSpaceMap(t, LOpts)), Target(t),
Idents(idents), Selectors(sels),
BuiltinInfo(builtins),
DeclarationNames(*this),
@@ -806,7 +823,8 @@ ASTContext::getTypeInfo(const Type *T) const {
Align = Target.getPointerAlign(0);
break;
case Type::BlockPointer: {
- unsigned AS = cast<BlockPointerType>(T)->getPointeeType().getAddressSpace();
+ unsigned AS = getTargetAddressSpace(
+ cast<BlockPointerType>(T)->getPointeeType());
Width = Target.getPointerWidth(AS);
Align = Target.getPointerAlign(AS);
break;
@@ -815,13 +833,14 @@ ASTContext::getTypeInfo(const Type *T) const {
case Type::RValueReference: {
// alignof and sizeof should never enter this code path here, so we go
// the pointer route.
- unsigned AS = cast<ReferenceType>(T)->getPointeeType().getAddressSpace();
+ unsigned AS = getTargetAddressSpace(
+ cast<ReferenceType>(T)->getPointeeType());
Width = Target.getPointerWidth(AS);
Align = Target.getPointerAlign(AS);
break;
}
case Type::Pointer: {
- unsigned AS = cast<PointerType>(T)->getPointeeType().getAddressSpace();
+ unsigned AS = getTargetAddressSpace(cast<PointerType>(T)->getPointeeType());
Width = Target.getPointerWidth(AS);
Align = Target.getPointerAlign(AS);
break;
@@ -1468,7 +1487,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
// the target.
llvm::APInt ArySize(ArySizeIn);
ArySize =
- ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace()));
+ ArySize.zextOrTrunc(Target.getPointerWidth(getTargetAddressSpace(EltTy)));
llvm::FoldingSetNodeID ID;
ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, IndexTypeQuals);
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index a9eeb8b4cc4..1696cae840c 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/APFloat.h"
@@ -19,6 +20,8 @@
#include <cstdlib>
using namespace clang;
+static const LangAS::Map DefaultAddrSpaceMap = { 0 };
+
// TargetInfo Constructor.
TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
// Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or
@@ -64,6 +67,9 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
// Default to using the Itanium ABI.
CXXABI = CXXABI_Itanium;
+
+ // Default to an empty address space map.
+ AddrSpaceMap = &DefaultAddrSpaceMap;
}
// Out of line virtual dtor for TargetInfo.
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 15ab6b080be..7a1600f166c 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -627,7 +627,8 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
assert(!RetAI.getIndirectAlign() && "Align unused on indirect return.");
ResultType = llvm::Type::getVoidTy(getLLVMContext());
const llvm::Type *STy = ConvertType(RetTy, IsRecursive);
- ArgTys.push_back(llvm::PointerType::get(STy, RetTy.getAddressSpace()));
+ unsigned AS = Context.getTargetAddressSpace(RetTy);
+ ArgTys.push_back(llvm::PointerType::get(STy, AS));
break;
}
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index b23b3922222..bf5e7a5d1a9 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -462,8 +462,8 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
// Bit size, align and offset of the type.
// Size is always the size of a pointer. We can't use getTypeSize here
// because that does not return the correct value for references.
- uint64_t Size =
- CGM.getContext().Target.getPointerWidth(PointeeTy.getAddressSpace());
+ unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
+ uint64_t Size = CGM.getContext().Target.getPointerWidth(AS);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
return
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 2cd4c87d3fe..792865668bc 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -179,7 +179,8 @@ CodeGenFunction::CreateStaticVarDecl(const VarDecl &D,
new llvm::GlobalVariable(CGM.getModule(), LTy,
Ty.isConstant(getContext()), Linkage,
CGM.EmitNullConstant(D.getType()), Name, 0,
- D.isThreadSpecified(), Ty.getAddressSpace());
+ D.isThreadSpecified(),
+ CGM.getContext().getTargetAddressSpace(Ty));
GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
if (Linkage != llvm::GlobalValue::InternalLinkage)
GV->setVisibility(CurFn->getVisibility());
@@ -222,7 +223,7 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
OldGV->getLinkage(), Init, "",
/*InsertBefore*/ OldGV,
D.isThreadSpecified(),
- D.getType().getAddressSpace());
+ CGM.getContext().getTargetAddressSpace(D.getType()));
GV->setVisibility(OldGV->getVisibility());
// Steal the name of the old global
@@ -289,7 +290,8 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
// FIXME: It is really dangerous to store this in the map; if anyone
// RAUW's the GV uses of this constant will be invalid.
const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType());
- const llvm::Type *LPtrTy = LTy->getPointerTo(D.getType().getAddressSpace());
+ const llvm::Type *LPtrTy =
+ LTy->getPointerTo(CGM.getContext().getTargetAddressSpace(D.getType()));
DMEntry = llvm::ConstantExpr::getBitCast(GV, LPtrTy);
// Emit global variable debug descriptor for static vars.
@@ -724,7 +726,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// Get the element type.
const llvm::Type *LElemTy = ConvertTypeForMem(Ty);
- const llvm::Type *LElemPtrTy = LElemTy->getPointerTo(Ty.getAddressSpace());
+ const llvm::Type *LElemPtrTy =
+ LElemTy->getPointerTo(CGM.getContext().getTargetAddressSpace(Ty));
llvm::Value *VLASize = EmitVLASize(Ty);
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 99ea773fa03..34a231cea17 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -726,7 +726,7 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV,
// Cast to the access type.
const llvm::Type *PTy = llvm::Type::getIntNPtrTy(getLLVMContext(),
AI.AccessWidth,
- ExprType.getAddressSpace());
+ CGM.getContext().getTargetAddressSpace(ExprType));
Ptr = Builder.CreateBitCast(Ptr, PTy);
// Perform the load.
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index a735c3f409d..11b08c0b046 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -800,7 +800,7 @@ public:
E->getType().isConstant(CGM.getContext()),
llvm::GlobalValue::InternalLinkage,
C, ".compoundliteral", 0, false,
- E->getType().getAddressSpace());
+ CGM.getContext().getTargetAddressSpace(E->getType()));
return C;
}
case Expr::DeclRefExprClass: {
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 11e85870d14..ea74abff540 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1060,7 +1060,7 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
Ty = getTypes().ConvertTypeForMem(ASTTy);
const llvm::PointerType *PTy =
- llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
+ llvm::PointerType::get(Ty, getContext().getTargetAddressSpace(ASTTy));
llvm::StringRef MangledName = getMangledName(D);
return GetOrCreateLLVMGlobal(MangledName, PTy, D);
@@ -1239,7 +1239,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
// from the type of the global (this happens with unions).
if (GV == 0 ||
GV->getType()->getElementType() != InitType ||
- GV->getType()->getAddressSpace() != ASTTy.getAddressSpace()) {
+ GV->getType()->getAddressSpace() !=
+ getContext().getTargetAddressSpace(ASTTy)) {
// Move the old entry aside so that we'll create a new one.
Entry->setName(llvm::StringRef());
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 5254922f13a..b9acbc4e9b6 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -270,14 +270,16 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
QualType ETy = RTy.getPointeeType();
llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext());
PointersToResolve.push_back(std::make_pair(ETy, PointeeType));
- return llvm::PointerType::get(PointeeType, ETy.getAddressSpace());
+ unsigned AS = Context.getTargetAddressSpace(ETy);
+ return llvm::PointerType::get(PointeeType, AS);
}
case Type::Pointer: {
const PointerType &PTy = cast<PointerType>(Ty);
QualType ETy = PTy.getPointeeType();
llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext());
PointersToResolve.push_back(std::make_pair(ETy, PointeeType));
- return llvm::PointerType::get(PointeeType, ETy.getAddressSpace());
+ unsigned AS = Context.getTargetAddressSpace(ETy);
+ return llvm::PointerType::get(PointeeType, AS);
}
case Type::VariableArray: {
@@ -402,7 +404,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
const QualType FTy = cast<BlockPointerType>(Ty).getPointeeType();
llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext());
PointersToResolve.push_back(std::make_pair(FTy, PointeeType));
- return llvm::PointerType::get(PointeeType, FTy.getAddressSpace());
+ unsigned AS = Context.getTargetAddressSpace(FTy);
+ return llvm::PointerType::get(PointeeType, AS);
}
case Type::MemberPointer: {
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 9d9c99611cf..2b5c289cbf9 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -672,6 +672,8 @@ static void LangOptsToArgs(const LangOptions &Opts,
Res.push_back("-fconstant-string-class");
Res.push_back(Opts.ObjCConstantStringClass);
}
+ if (Opts.FakeAddressSpaceMap)
+ Res.push_back("-ffake-address-space-map");
}
static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts,
@@ -1483,6 +1485,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.FastRelaxedMath = Args.hasArg(OPT_cl_fast_relaxed_math);
Opts.OptimizeSize = 0;
Opts.MRTD = Args.hasArg(OPT_mrtd);
+ Opts.FakeAddressSpaceMap = Args.hasArg(OPT_ffake_address_space_map);
// FIXME: Eliminate this dependency.
unsigned Opt = getOptimizationLevel(Args, IK, Diags);
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 42083803b69..f27ff79f193 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -13,6 +13,7 @@
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Basic/OpenCL.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
@@ -311,6 +312,56 @@ void Parser::ParseOpenCLAttributes(ParsedAttributes &attrs) {
}
}
+void Parser::ParseOpenCLQualifiers(DeclSpec &DS) {
+ SourceLocation Loc = Tok.getLocation();
+ switch(Tok.getKind()) {
+ // OpenCL qualifiers:
+ case tok::kw___private:
+ case tok::kw_private:
+ DS.addAttributes(AttrFactory.CreateIntegerAttribute(
+ Actions.getASTContext(),
+ PP.getIdentifierInfo("address_space"), Loc, 0));
+ break;
+
+ case tok::kw___global:
+ DS.addAttributes(AttrFactory.CreateIntegerAttribute(
+ Actions.getASTContext(),
+ PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_global));
+ break;
+
+ case tok::kw___local:
+ DS.addAttributes(AttrFactory.CreateIntegerAttribute(
+ Actions.getASTContext(),
+ PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_local));
+ break;
+
+ case tok::kw___constant:
+ DS.addAttributes(AttrFactory.CreateIntegerAttribute(
+ Actions.getASTContext(),
+ PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_constant));
+ break;
+
+ case tok::kw___read_only:
+ DS.addAttributes(AttrFactory.CreateIntegerAttribute(
+ Actions.getASTContext(),
+ PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_read_only));
+ break;
+
+ case tok::kw___write_only:
+ DS.addAttributes(AttrFactory.CreateIntegerAttribute(
+ Actions.getASTContext(),
+ PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_write_only));
+ break;
+
+ case tok::kw___read_write:
+ DS.addAttributes(AttrFactory.CreateIntegerAttribute(
+ Actions.getASTContext(),
+ PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_read_write));
+ break;
+ default: break;
+ }
+}
+
void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed)
<< attrs.Range;
@@ -1446,6 +1497,20 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
ParseDecltypeSpecifier(DS);
continue;
+ // OpenCL qualifiers:
+ case tok::kw_private:
+ if (!getLang().OpenCL)
+ goto DoneWithDeclSpec;
+ case tok::kw___private:
+ case tok::kw___global:
+ case tok::kw___local:
+ case tok::kw___constant:
+ case tok::kw___read_only:
+ case tok::kw___write_only:
+ case tok::kw___read_write:
+ ParseOpenCLQualifiers(DS);
+ break;
+
case tok::less:
// GCC ObjC supports types like "<SomeProtocol>" as a synonym for
// "id<SomeProtocol>". This is hopelessly old fashioned and dangerous,
@@ -1697,6 +1762,20 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
ParseDecltypeSpecifier(DS);
return true;
+ // OpenCL qualifiers:
+ case tok::kw_private:
+ if (!getLang().OpenCL)
+ return false;
+ case tok::kw___private:
+ case tok::kw___global:
+ case tok::kw___local:
+ case tok::kw___constant:
+ case tok::kw___read_only:
+ case tok::kw___write_only:
+ case tok::kw___read_write:
+ ParseOpenCLQualifiers(DS);
+ break;
+
// C++0x auto support.
case tok::kw_auto:
if (!getLang().CPlusPlus0x)
@@ -2269,10 +2348,22 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
bool Parser::isTypeQualifier() const {
switch (Tok.getKind()) {
default: return false;
+
+ // type-qualifier only in OpenCL
+ case tok::kw_private:
+ return getLang().OpenCL;
+
// type-qualifier
case tok::kw_const:
case tok::kw_volatile:
case tok::kw_restrict:
+ case tok::kw___private:
+ case tok::kw___local:
+ case tok::kw___global:
+ case tok::kw___constant:
+ case tok::kw___read_only:
+ case tok::kw___read_write:
+ case tok::kw___write_only:
return true;
}
}
@@ -2400,7 +2491,19 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw___w64:
case tok::kw___ptr64:
case tok::kw___pascal:
+
+ case tok::kw___private:
+ case tok::kw___local:
+ case tok::kw___global:
+ case tok::kw___constant:
+ case tok::kw___read_only:
+ case tok::kw___read_write:
+ case tok::kw___write_only:
+
return true;
+
+ case tok::kw_private:
+ return getLang().OpenCL;
}
}
@@ -2413,6 +2516,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
switch (Tok.getKind()) {
default: return false;
+ case tok::kw_private:
+ return getLang().OpenCL;
+
case tok::identifier: // foo::bar
// Unfortunate hack to support "Class.factoryMethod" notation.
if (getLang().ObjC1 && NextToken().is(tok::period))
@@ -2522,6 +2628,15 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw___ptr64:
case tok::kw___forceinline:
case tok::kw___pascal:
+
+ case tok::kw___private:
+ case tok::kw___local:
+ case tok::kw___global:
+ case tok::kw___constant:
+ case tok::kw___read_only:
+ case tok::kw___read_write:
+ case tok::kw___write_only:
+
return true;
}
}
@@ -2627,6 +2742,21 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
getLang());
break;
+
+ // OpenCL qualifiers:
+ case tok::kw_private:
+ if (!getLang().OpenCL)
+ goto DoneWithTypeQuals;
+ case tok::kw___private:
+ case tok::kw___global:
+ case tok::kw___local:
+ case tok::kw___constant:
+ case tok::kw___read_only:
+ case tok::kw___write_only:
+ case tok::kw___read_write:
+ ParseOpenCLQualifiers(DS);
+ break;
+
case tok::kw___w64:
case tok::kw___ptr64:
case tok::kw___cdecl:
diff --git a/clang/lib/Sema/AttributeList.cpp b/clang/lib/Sema/AttributeList.cpp
index 1663fd58a99..a715989c685 100644
--- a/clang/lib/Sema/AttributeList.cpp
+++ b/clang/lib/Sema/AttributeList.cpp
@@ -94,6 +94,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("unavailable", AT_unavailable)
.Case("overloadable", AT_overloadable)
.Case("address_space", AT_address_space)
+ .Case("opencl_image_access", AT_opencl_image_access)
.Case("always_inline", AT_always_inline)
.Case("returns_twice", IgnoredAttribute)
.Case("vec_type_hint", IgnoredAttribute)
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 5f6de1409e2..3c1127784d4 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2724,6 +2724,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D,
case AttributeList::AT_IBOutletCollection:
HandleIBOutletCollection(D, Attr, S); break;
case AttributeList::AT_address_space:
+ case AttributeList::AT_opencl_image_access:
case AttributeList::AT_objc_gc:
case AttributeList::AT_vector_size:
case AttributeList::AT_neon_vector_type:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index b78c21bbb63..dc2d3ac518b 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -13,6 +13,7 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
+#include "clang/Basic/OpenCL.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
@@ -2965,6 +2966,41 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
return true;
}
+/// Handle OpenCL image access qualifiers: read_only, write_only, read_write
+static void HandleOpenCLImageAccessAttribute(QualType& CurType,
+ const AttributeList &Attr,
+ Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
+ return;
+ }
+ Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
+ llvm::APSInt arg(32);
+ if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
+ !sizeExpr->isIntegerConstantExpr(arg, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+ << "opencl_image_access" << sizeExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ unsigned iarg = static_cast<unsigned>(arg.getZExtValue());
+ switch (iarg) {
+ case CLIA_read_only:
+ case CLIA_write_only:
+ case CLIA_read_write:
+ // Implemented in a separate patch
+ break;
+ default:
+ // Implemented in a separate patch
+ S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
+ << sizeExpr->getSourceRange();
+ Attr.setInvalid();
+ break;
+ }
+}
+
/// HandleVectorSizeAttribute - this attribute is only applicable to integral
/// and float scalars, although arrays, pointers, and function return values are
/// allowed in conjunction with this construct. Aggregates with this attribute
@@ -3119,6 +3155,10 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
"neon_polyvector_type");
break;
+ case AttributeList::AT_opencl_image_access:
+ HandleOpenCLImageAccessAttribute(type, attr, state.getSema());
+ break;
+
FUNCTION_TYPE_ATTRS_CASELIST:
// Never process function type attributes as part of the
// declaration-specifiers.
OpenPOWER on IntegriCloud