Index: clang/include/clang/Basic/OpenCLImageTypes.def =================================================================== --- clang/include/clang/Basic/OpenCLImageTypes.def +++ clang/include/clang/Basic/OpenCLImageTypes.def @@ -65,7 +65,7 @@ IMAGE_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA, "cl_khr_gl_msaa_sharing") IMAGE_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth, "cl_khr_gl_msaa_sharing") IMAGE_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth, "cl_khr_gl_msaa_sharing") -IMAGE_WRITE_TYPE(image3d, OCLImage3d, "cl_khr_3d_image_writes") +IMAGE_WRITE_TYPE(image3d, OCLImage3d, "") IMAGE_READ_WRITE_TYPE(image1d, OCLImage1d, "") IMAGE_READ_WRITE_TYPE(image1d_array, OCLImage1dArray, "") Index: clang/lib/Parse/ParseDecl.cpp =================================================================== --- clang/lib/Parse/ParseDecl.cpp +++ clang/lib/Parse/ParseDecl.cpp @@ -3071,6 +3071,23 @@ SourceLocation Loc = Tok.getLocation(); + // Helper for image types in OpenCL. + auto handleOpenCLImageKW = [&](StringRef Ext, + TypeSpecifierType ImageTypeSpec) { + // Check if the image type is supported and otherwise turn the keyword + // into an identifier because image types from extensions are not reserved + // identifiers. + if (!StringRef(Ext).empty() && + !getActions().getOpenCLOptions().isSupported(Ext, getLangOpts())) { + Tok.getIdentifierInfo()->revertTokenIDToIdentifier(); + Tok.setKind(tok::identifier); + return false; + } + isInvalid = + DS.SetTypeSpecType(ImageTypeSpec, Loc, PrevSpec, DiagID, Policy); + return true; + }; + switch (Tok.getKind()) { default: DoneWithDeclSpec: @@ -3934,10 +3951,13 @@ } isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy); break; -#define GENERIC_IMAGE_TYPE(ImgType, Id) \ - case tok::kw_##ImgType##_t: \ - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_##ImgType##_t, Loc, PrevSpec, \ - DiagID, Policy); \ +// We only need to enumerate each image type once. +#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext) +#define IMAGE_WRITE_TYPE(Type, Id, Ext) +#define IMAGE_READ_TYPE(ImgType, Id, Ext) \ + case tok::kw_##ImgType##_t: \ + if (!handleOpenCLImageKW(Ext, DeclSpec::TST_##ImgType##_t)) \ + goto DoneWithDeclSpec; \ break; #include "clang/Basic/OpenCLImageTypes.def" case tok::kw___unknown_anytype: Index: clang/lib/Sema/Sema.cpp =================================================================== --- clang/lib/Sema/Sema.cpp +++ clang/lib/Sema/Sema.cpp @@ -363,10 +363,6 @@ } } - -#define GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) \ - setOpenCLExtensionForType(Context.Id, Ext); -#include "clang/Basic/OpenCLImageTypes.def" #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ if (getOpenCLOptions().isSupported(#Ext, getLangOpts())) { \ addImplicitTypedef(#ExtType, Context.Id##Ty); \ Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ clang/lib/Sema/SemaType.cpp @@ -1711,12 +1711,20 @@ break; } + // FIXME: we want resulting declarations to be marked invalid, but claiming // the type is invalid is too strong - e.g. it causes ActOnTypeName to return // a null type. if (Result->containsErrors()) declarator.setInvalidType(); + if (S.getLangOpts().OpenCL && Result->isOCLImage3dWOType() && + !S.getOpenCLOptions().isSupported("cl_khr_3d_image_writes", S.getLangOpts())) { + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_opencl_requires_extension) + << 0 << Result << "cl_khr_3d_image_writes"; + declarator.setInvalidType(); + } + if (S.getLangOpts().OpenCL && S.checkOpenCLDisabledTypeDeclSpec(DS, Result)) declarator.setInvalidType(true); Index: clang/test/SemaOpenCL/access-qualifier.cl =================================================================== --- clang/test/SemaOpenCL/access-qualifier.cl +++ clang/test/SemaOpenCL/access-qualifier.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -pedantic -fsyntax-only -cl-std=CL1.2 %s +// RUN: %clang_cc1 -verify -pedantic -fsyntax-only -cl-std=CL1.2 %s -cl-ext=-cl_khr_3d_image_writes // RUN: %clang_cc1 -verify -pedantic -fsyntax-only -cl-std=CL2.0 %s typedef image1d_t img1d_ro_default; // expected-note {{previously declared 'read_only' here}} Index: clang/test/SemaOpenCL/invalid-image.cl =================================================================== --- clang/test/SemaOpenCL/invalid-image.cl +++ clang/test/SemaOpenCL/invalid-image.cl @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -verify -cl-std=clc++ %s -// RUN: %clang_cc1 -verify %s +// RUN: %clang_cc1 -verify %s -cl-ext=+cl_khr_gl_msaa_sharing +// RUN: %clang_cc1 -verify %s -cl-ext=-cl_khr_gl_msaa_sharing // RUN: %clang_cc1 -verify -D=ATTR_TEST -fms-compatibility %s void test1(image1d_t *i) {} // expected-error-re{{pointer to type '{{__generic __read_only|__read_only}} image1d_t' is invalid in OpenCL}} @@ -19,3 +20,9 @@ // Test case for an infinite loop bug. kernel void foob(read_only __ptr32 image2d_t i) { } // expected-error{{'__ptr32' attribute only applies to pointer arguments}} #endif + +#ifndef cl_khr_gl_msaa_sharing +// Image types from 'cl_khr_gl_msaa_sharing' are not reserved identifiers. +typedef int image2d_msaa_t; +#endif +void foo(image2d_msaa_t i);