Index: cfe/trunk/include/clang/AST/ASTContext.h =================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h +++ cfe/trunk/include/clang/AST/ASTContext.h @@ -2317,21 +2317,15 @@ return getTargetAddressSpace(Q.getAddressSpace()); } - unsigned getTargetAddressSpace(unsigned AS) const { - if (AS < LangAS::Offset || AS >= LangAS::Offset + LangAS::Count) - return AS; - else - return (*AddrSpaceMap)[AS - LangAS::Offset]; - } + unsigned getTargetAddressSpace(unsigned AS) const; /// Get target-dependent integer value for null pointer which is used for /// constant folding. uint64_t getTargetNullPointerValue(QualType QT) const; bool addressSpaceMapManglingFor(unsigned AS) const { - return AddrSpaceMapMangling || - AS < LangAS::Offset || - AS >= LangAS::Offset + LangAS::Count; + return AddrSpaceMapMangling || + AS >= LangAS::Count; } private: Index: cfe/trunk/include/clang/AST/Type.h =================================================================== --- cfe/trunk/include/clang/AST/Type.h +++ cfe/trunk/include/clang/AST/Type.h @@ -333,6 +333,20 @@ bool hasAddressSpace() const { return Mask & AddressSpaceMask; } unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } + /// Get the address space attribute value to be printed by diagnostics. + unsigned getAddressSpaceAttributePrintValue() const { + auto Addr = getAddressSpace(); + // This function is not supposed to be used with language specific + // address spaces. If that happens, the diagnostic message should consider + // printing the QualType instead of the address space value. + assert(Addr == 0 || Addr >= LangAS::Count); + if (Addr) + return Addr - LangAS::Count; + // TODO: The diagnostic messages where Addr may be 0 should be fixed + // since it cannot differentiate the situation where 0 denotes the default + // address space or user specified __attribute__((address_space(0))). + return 0; + } void setAddressSpace(unsigned space) { assert(space <= MaxAddressSpace); Mask = (Mask & ~AddressSpaceMask) Index: cfe/trunk/include/clang/Basic/AddressSpaces.h =================================================================== --- cfe/trunk/include/clang/Basic/AddressSpaces.h +++ cfe/trunk/include/clang/Basic/AddressSpaces.h @@ -20,24 +20,32 @@ namespace LangAS { -/// \brief Defines the set of possible language-specific address spaces. +/// \brief Defines the address space values used by the address space qualifier +/// of QualType. /// -/// This uses a high starting offset so as not to conflict with any address -/// space used by a target. enum ID { - Offset = 0x7FFF00, + // The default value 0 is the value used in QualType for the the situation + // where there is no address space qualifier. For most languages, this also + // corresponds to the situation where there is no address space qualifier in + // the source code, except for OpenCL, where the address space value 0 in + // QualType represents private address space in OpenCL source code. + Default = 0, - opencl_global = Offset, + // OpenCL specific address spaces. + opencl_global, opencl_local, opencl_constant, opencl_generic, + // CUDA specific address spaces. cuda_device, cuda_constant, cuda_shared, - Last, - Count = Last-Offset + // This denotes the count of language-specific address spaces and also + // the offset added to the target-specific address spaces, which are usually + // specified by address space attributes __attribute__(address_space(n))). + Count }; /// The type of a lookup table which maps from language-specific address spaces Index: cfe/trunk/lib/AST/ASTContext.cpp =================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp +++ cfe/trunk/lib/AST/ASTContext.cpp @@ -703,6 +703,7 @@ // The fake address space map must have a distinct entry for each // language-specific address space. static const unsigned FakeAddrSpaceMap[] = { + 0, // Default 1, // opencl_global 3, // opencl_local 2, // opencl_constant @@ -8727,7 +8728,8 @@ char *End; unsigned AddrSpace = strtoul(Str, &End, 10); if (End != Str && AddrSpace != 0) { - Type = Context.getAddrSpaceQualType(Type, AddrSpace); + Type = Context.getAddrSpaceQualType(Type, AddrSpace + + LangAS::Count); Str = End; } if (c == '*') @@ -9546,6 +9548,18 @@ return getTargetInfo().getNullPointerValue(AS); } +unsigned ASTContext::getTargetAddressSpace(unsigned AS) const { + // For OpenCL, only function local variables are not explicitly marked with + // an address space in the AST, and these need to be the address space of + // alloca. + if (!AS && LangOpts.OpenCL) + return getTargetInfo().getDataLayout().getAllocaAddrSpace(); + if (AS >= LangAS::Count) + return AS - LangAS::Count; + else + return (*AddrSpaceMap)[AS]; +} + // Explicitly instantiate this in case a Redeclarable is used from a TU that // doesn't include ASTContext.h template Index: cfe/trunk/lib/AST/ExprClassification.cpp =================================================================== --- cfe/trunk/lib/AST/ExprClassification.cpp +++ cfe/trunk/lib/AST/ExprClassification.cpp @@ -627,7 +627,8 @@ // Const stuff is obviously not modifiable. if (CT.isConstQualified()) return Cl::CM_ConstQualified; - if (CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant) + if (Ctx.getLangOpts().OpenCL && + CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant) return Cl::CM_ConstAddrSpace; // Arrays are not modifiable, only their elements are. Index: cfe/trunk/lib/AST/TypePrinter.cpp =================================================================== --- cfe/trunk/lib/AST/TypePrinter.cpp +++ cfe/trunk/lib/AST/TypePrinter.cpp @@ -1653,14 +1653,22 @@ OS << "__local"; break; case LangAS::opencl_constant: + case LangAS::cuda_constant: OS << "__constant"; break; case LangAS::opencl_generic: OS << "__generic"; break; + case LangAS::cuda_device: + OS << "__device"; + break; + case LangAS::cuda_shared: + OS << "__shared"; + break; default: + assert(addrspace >= LangAS::Count); OS << "__attribute__((address_space("; - OS << addrspace; + OS << addrspace - LangAS::Count; OS << ")))"; } } Index: cfe/trunk/lib/Basic/Targets.cpp =================================================================== --- cfe/trunk/lib/Basic/Targets.cpp +++ cfe/trunk/lib/Basic/Targets.cpp @@ -1777,6 +1777,7 @@ }; static const unsigned NVPTXAddrSpaceMap[] = { + 0, // Default 1, // opencl_global 3, // opencl_local 4, // opencl_constant @@ -2031,6 +2032,7 @@ } static const LangAS::Map AMDGPUPrivateIsZeroMap = { + 4, // Default 1, // opencl_global 3, // opencl_local 2, // opencl_constant @@ -2040,6 +2042,7 @@ 3 // cuda_shared }; static const LangAS::Map AMDGPUGenericIsZeroMap = { + 0, // Default 1, // opencl_global 3, // opencl_local 2, // opencl_constant @@ -2064,7 +2067,7 @@ static const char *const DataLayoutStringSIGenericIsZero = "e-p:64:64-p1:64:64-p2:64:64-p3:32:32-p4:32:32-p5:32:32" "-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128" - "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64"; + "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5"; class AMDGPUTargetInfo final : public TargetInfo { static const Builtin::Info BuiltinInfo[]; @@ -2139,6 +2142,7 @@ (IsGenericZero ? DataLayoutStringSIGenericIsZero : DataLayoutStringSIPrivateIsZero) : DataLayoutStringR600); + assert(DataLayout->getAllocaAddrSpace() == AS.Private); AddrSpaceMap = IsGenericZero ? &AMDGPUGenericIsZeroMap : &AMDGPUPrivateIsZeroMap; @@ -7408,6 +7412,7 @@ // publicly available in http://tce.cs.tut.fi static const unsigned TCEOpenCLAddrSpaceMap[] = { + 0, // Default 3, // opencl_global 4, // opencl_local 5, // opencl_constant @@ -8374,6 +8379,7 @@ }; static const unsigned SPIRAddrSpaceMap[] = { + 0, // Default 1, // opencl_global 3, // opencl_local 2, // opencl_constant Index: cfe/trunk/lib/Sema/SemaExprCXX.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp @@ -2048,9 +2048,10 @@ else if (AllocType->isVariablyModifiedType()) return Diag(Loc, diag::err_variably_modified_new_type) << AllocType; - else if (unsigned AddressSpace = AllocType.getAddressSpace()) + else if (AllocType.getAddressSpace()) return Diag(Loc, diag::err_address_space_qualified_new) - << AllocType.getUnqualifiedType() << AddressSpace; + << AllocType.getUnqualifiedType() + << AllocType.getQualifiers().getAddressSpaceAttributePrintValue(); else if (getLangOpts().ObjCAutoRefCount) { if (const ArrayType *AT = Context.getAsArrayType(AllocType)) { QualType BaseAllocType = Context.getBaseElementType(AT); @@ -3117,10 +3118,11 @@ QualType Pointee = Type->getAs()->getPointeeType(); QualType PointeeElem = Context.getBaseElementType(Pointee); - if (unsigned AddressSpace = Pointee.getAddressSpace()) + if (Pointee.getAddressSpace()) return Diag(Ex.get()->getLocStart(), diag::err_address_space_qualified_delete) - << Pointee.getUnqualifiedType() << AddressSpace; + << Pointee.getUnqualifiedType() + << Pointee.getQualifiers().getAddressSpaceAttributePrintValue(); CXXRecordDecl *PointeeRD = nullptr; if (Pointee->isVoidType() && !isSFINAEContext()) { Index: cfe/trunk/lib/Sema/SemaOverload.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp +++ cfe/trunk/lib/Sema/SemaOverload.cpp @@ -9528,7 +9528,8 @@ << (unsigned) FnKind << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy - << FromQs.getAddressSpace() << ToQs.getAddressSpace() + << FromQs.getAddressSpaceAttributePrintValue() + << ToQs.getAddressSpaceAttributePrintValue() << (unsigned) isObjectArgument << I+1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; Index: cfe/trunk/lib/Sema/SemaType.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaType.cpp +++ cfe/trunk/lib/Sema/SemaType.cpp @@ -5529,14 +5529,14 @@ addrSpace.setIsSigned(false); } llvm::APSInt max(addrSpace.getBitWidth()); - max = Qualifiers::MaxAddressSpace; + max = Qualifiers::MaxAddressSpace - LangAS::Count; if (addrSpace > max) { S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high) - << int(Qualifiers::MaxAddressSpace) << ASArgExpr->getSourceRange(); + << (unsigned)max.getZExtValue() << ASArgExpr->getSourceRange(); Attr.setInvalid(); return; } - ASIdx = static_cast(addrSpace.getZExtValue()); + ASIdx = static_cast(addrSpace.getZExtValue()) + LangAS::Count; } else { // The keyword-based type attributes imply which address space to use. switch (Attr.getKind()) { Index: cfe/trunk/test/CodeGen/address-space.c =================================================================== --- cfe/trunk/test/CodeGen/address-space.c +++ cfe/trunk/test/CodeGen/address-space.c @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck -check-prefixes=CHECK,GIZ %s +// RUN: %clang_cc1 -triple amdgcn -emit-llvm < %s | FileCheck -check-prefixes=CHECK,PIZ %s +// RUN: %clang_cc1 -triple amdgcn---amdgiz -emit-llvm < %s | FileCheck -check-prefixes=CHeCK,GIZ %s // CHECK: @foo = common addrspace(1) global int foo __attribute__((address_space(1))); @@ -6,6 +8,9 @@ // CHECK: @ban = common addrspace(1) global int ban[10] __attribute__((address_space(1))); +// CHECK: @a = common global +int a __attribute__((address_space(0))); + // CHECK-LABEL: define i32 @test1() // CHECK: load i32, i32 addrspace(1)* @foo int test1() { return foo; } @@ -19,9 +24,11 @@ __attribute__((address_space(2))) int *A, *B; // CHECK-LABEL: define void @test3() -// CHECK: load i32 addrspace(2)*, i32 addrspace(2)** @B +// GIZ: load i32 addrspace(2)*, i32 addrspace(2)** @B +// PIZ: load i32 addrspace(2)*, i32 addrspace(2)* addrspace(4)* @B // CHECK: load i32, i32 addrspace(2)* -// CHECK: load i32 addrspace(2)*, i32 addrspace(2)** @A +// GIZ: load i32 addrspace(2)*, i32 addrspace(2)** @A +// PIZ: load i32 addrspace(2)*, i32 addrspace(2)* addrspace(4)* @A // CHECK: store i32 {{.*}}, i32 addrspace(2)* void test3() { *A = *B; Index: cfe/trunk/test/CodeGen/default-address-space.c =================================================================== --- cfe/trunk/test/CodeGen/default-address-space.c +++ cfe/trunk/test/CodeGen/default-address-space.c @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -triple amdgcn -emit-llvm < %s | FileCheck -check-prefixes=PIZ,COM %s +// RUN: %clang_cc1 -triple amdgcn---amdgiz -emit-llvm < %s | FileCheck -check-prefixes=CHECK,COM %s + +// PIZ-DAG: @foo = common addrspace(4) global i32 0 +// CHECK-DAG: @foo = common global i32 0 +int foo; + +// PIZ-DAG: @ban = common addrspace(4) global [10 x i32] zeroinitializer +// CHECK-DAG: @ban = common global [10 x i32] zeroinitializer +int ban[10]; + +// PIZ-DAG: @A = common addrspace(4) global i32 addrspace(4)* null +// PIZ-DAG: @B = common addrspace(4) global i32 addrspace(4)* null +// CHECK-DAG: @A = common global i32* null +// CHECK-DAG: @B = common global i32* null +int *A; +int *B; + +// COM-LABEL: define i32 @test1() +// PIZ: load i32, i32 addrspace(4)* @foo +// CHECK: load i32, i32* @foo +int test1() { return foo; } + +// COM-LABEL: define i32 @test2(i32 %i) +// PIZ: load i32, i32 addrspace(4)* +// PIZ-NEXT: ret i32 +// CHECK: load i32, i32* +// CHECK-NEXT: ret i32 +int test2(int i) { return ban[i]; } + +// COM-LABEL: define void @test3() +// PIZ: load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* @B +// PIZ: load i32, i32 addrspace(4)* +// PIZ: load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* @A +// PIZ: store i32 {{.*}}, i32 addrspace(4)* +// CHECK: load i32*, i32** @B +// CHECK: load i32, i32* +// CHECK: load i32*, i32** @A +// CHECK: store i32 {{.*}}, i32* +void test3() { + *A = *B; +} + +// PIZ-LABEL: define void @test4(i32 addrspace(4)* %a) +// PIZ: %[[a_addr:.*]] = alloca i32 addrspace(4)* +// PIZ: store i32 addrspace(4)* %a, i32 addrspace(4)** %[[a_addr]] +// PIZ: %[[r0:.*]] = load i32 addrspace(4)*, i32 addrspace(4)** %[[a_addr]] +// PIZ: %[[arrayidx:.*]] = getelementptr inbounds i32, i32 addrspace(4)* %[[r0]] +// PIZ: store i32 0, i32 addrspace(4)* %[[arrayidx]] +// CHECK-LABEL: define void @test4(i32* %a) +// CHECK: %[[a_addr:.*]] = alloca i32*, align 4, addrspace(5) +// CHECK: store i32* %a, i32* addrspace(5)* %[[a_addr]] +// CHECK: %[[r0:.*]] = load i32*, i32* addrspace(5)* %[[a_addr]] +// CHECK: %[[arrayidx:.*]] = getelementptr inbounds i32, i32* %[[r0]] +// CHECK: store i32 0, i32* %[[arrayidx]] +void test4(int *a) { + a[0] = 0; +} Index: cfe/trunk/test/CodeGenOpenCL/address-spaces.cl =================================================================== --- cfe/trunk/test/CodeGenOpenCL/address-spaces.cl +++ cfe/trunk/test/CodeGenOpenCL/address-spaces.cl @@ -1,7 +1,12 @@ -// RUN: %clang_cc1 %s -O0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 %s -O0 -DCL20 -cl-std=CL2.0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefix=CL20 +// RUN: %clang_cc1 %s -O0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR +// RUN: %clang_cc1 %s -O0 -DCL20 -cl-std=CL2.0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CL20,CL20SPIR +// RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa-opencl -emit-llvm -o - | FileCheck --check-prefixes=CHECK,SPIR %s +// RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa-opencl -DCL20 -cl-std=CL2.0 -emit-llvm -o - | FileCheck %s --check-prefixes=CL20,CL20SPIR +// RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa-amdgizcl -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,GIZ +// RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa-amdgizcl -DCL20 -cl-std=CL2.0 -emit-llvm -o - | FileCheck %s --check-prefixes=CL20,CL20GIZ -// CHECK: i32* %arg +// SPIR: i32* %arg +// GIZ: i32 addrspace(5)* %arg void f__p(__private int *arg) {} // CHECK: i32 addrspace(1)* %arg @@ -13,7 +18,8 @@ // CHECK: i32 addrspace(2)* %arg void f__c(__constant int *arg) {} -// CHECK: i32* %arg +// SPIR: i32* %arg +// GIZ: i32 addrspace(5)* %arg void fp(private int *arg) {} // CHECK: i32 addrspace(1)* %arg @@ -29,16 +35,21 @@ int i; // CL20-DAG: @i = common addrspace(1) global i32 0 int *ptr; -// CL20-DAG: @ptr = common addrspace(1) global i32 addrspace(4)* null +// CL20SPIR-DAG: @ptr = common addrspace(1) global i32 addrspace(4)* null +// CL20GIZ-DAG: @ptr = common addrspace(1) global i32* null #endif -// CHECK: i32* %arg -// CL20-DAG: i32 addrspace(4)* %arg +// SPIR: i32* %arg +// GIZ: i32 addrspace(5)* %arg +// CL20SPIR-DAG: i32 addrspace(4)* %arg +// CL20GIZ-DAG: i32* %arg void f(int *arg) { int i; -// CHECK: %i = alloca i32, -// CL20-DAG: %i = alloca i32, +// SPIR: %i = alloca i32, +// GIZ: %i = alloca i32{{.*}}addrspace(5) +// CL20SPIR-DAG: %i = alloca i32, +// CL20GIZ-DAG: %i = alloca i32{{.*}}addrspace(5) #ifdef CL20 static int ii; Index: cfe/trunk/test/CodeGenOpenCL/amdgpu-env-amdgiz.cl =================================================================== --- cfe/trunk/test/CodeGenOpenCL/amdgpu-env-amdgiz.cl +++ cfe/trunk/test/CodeGenOpenCL/amdgpu-env-amdgiz.cl @@ -4,6 +4,6 @@ // RUN: %clang_cc1 %s -O0 -triple amdgcn---amdgizcl -emit-llvm -o - | FileCheck -check-prefix=GIZ %s // CHECK: target datalayout = "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64" -// GIZ: target datalayout = "e-p:64:64-p1:64:64-p2:64:64-p3:32:32-p4:32:32-p5:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64" +// GIZ: target datalayout = "e-p:64:64-p1:64:64-p2:64:64-p3:32:32-p4:32:32-p5:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-A5" void foo(void) {} Index: cfe/trunk/test/CodeGenOpenCL/vla.cl =================================================================== --- cfe/trunk/test/CodeGenOpenCL/vla.cl +++ cfe/trunk/test/CodeGenOpenCL/vla.cl @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -emit-llvm -triple "spir-unknown-unknown" -O0 -cl-std=CL2.0 -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple "spir-unknown-unknown" -O0 -cl-std=CL2.0 -o - %s | FileCheck -check-prefixes=CHECK,SPIR %s +// RUN: %clang_cc1 -emit-llvm -triple amdgcn-amd-amdhsa-opencl -O0 -cl-std=CL2.0 -o - %s | FileCheck -check-prefixes=CHECK,SPIR %s +// RUN: %clang_cc1 -emit-llvm -triple amdgcn-amd-amdhsa-amdgizcl -O0 -cl-std=CL2.0 -o - %s | FileCheck -check-prefixes=CHECK,GIZ %s constant int sz0 = 5; // CHECK: @sz0 = addrspace(2) constant i32 5 @@ -11,8 +13,12 @@ kernel void testvla() { int vla0[sz0]; -// CHECK: %vla0 = alloca [5 x i32] +// SPIR: %vla0 = alloca [5 x i32] +// SPIR-NOT: %vla0 = alloca [5 x i32]{{.*}}addrspace +// GIZ: %vla0 = alloca [5 x i32]{{.*}}addrspace(5) char vla1[sz1]; -// CHECK: %vla1 = alloca [16 x i8] +// SPIR: %vla1 = alloca [16 x i8] +// SPIR-NOT: %vla1 = alloca [16 x i8]{{.*}}addrspace +// GIZ: %vla1 = alloca [16 x i8]{{.*}}addrspace(5) local short vla2[sz2]; } Index: cfe/trunk/test/Sema/address_spaces.c =================================================================== --- cfe/trunk/test/Sema/address_spaces.c +++ cfe/trunk/test/Sema/address_spaces.c @@ -20,7 +20,7 @@ _AS1 int arrarr[5][5]; // expected-error {{automatic variable qualified with an address space}} __attribute__((address_space(-1))) int *_boundsA; // expected-error {{address space is negative}} - __attribute__((address_space(0x7FFFFF))) int *_boundsB; + __attribute__((address_space(0x7FFFFF))) int *_boundsB; // expected-error {{address space is larger than the maximum supported}} __attribute__((address_space(0x1000000))) int *_boundsC; // expected-error {{address space is larger than the maximum supported}} // chosen specifically to overflow 32 bits and come out reasonable __attribute__((address_space(4294967500))) int *_boundsD; // expected-error {{address space is larger than the maximum supported}} Index: cfe/trunk/test/Sema/invalid-assignment-constant-address-space.c =================================================================== --- cfe/trunk/test/Sema/invalid-assignment-constant-address-space.c +++ cfe/trunk/test/Sema/invalid-assignment-constant-address-space.c @@ -1,8 +0,0 @@ -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only - -#define OPENCL_CONSTANT 8388354 -int __attribute__((address_space(OPENCL_CONSTANT))) c[3] = {0}; - -void foo() { - c[0] = 1; //expected-error{{read-only variable is not assignable}} -} Index: cfe/trunk/test/SemaOpenCL/invalid-assignment-constant-address-space.cl =================================================================== --- cfe/trunk/test/SemaOpenCL/invalid-assignment-constant-address-space.cl +++ cfe/trunk/test/SemaOpenCL/invalid-assignment-constant-address-space.cl @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only + +int constant c[3] = {0}; + +void foo() { + c[0] = 1; //expected-error{{read-only variable is not assignable}} +}