From: Peter Collingbourne Date: Thu, 6 Oct 2011 03:01:00 +0000 (+0000) Subject: OpenCL: add a non-standard extension, cl_clang_storage_class_specifiers, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b8b0e75aeec85a7a268fdba311de4f1cd527fae1;p=clang OpenCL: add a non-standard extension, cl_clang_storage_class_specifiers, which enables support for C99 storage-class specifiers. This extension is intended to be used by implementations to implement OpenCL C built-in functions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141271 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/OpenCLExtensions.def b/include/clang/Basic/OpenCLExtensions.def index 95cc1a9a51..103fa839b8 100644 --- a/include/clang/Basic/OpenCLExtensions.def +++ b/include/clang/Basic/OpenCLExtensions.def @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +// OpenCL 1.1. OPENCLEXT(cl_khr_fp64) OPENCLEXT(cl_khr_int64_base_atomics) OPENCLEXT(cl_khr_int64_extended_atomics) @@ -25,4 +26,7 @@ OPENCLEXT(cl_khr_local_int32_extended_atomics) OPENCLEXT(cl_khr_byte_addressable_store) OPENCLEXT(cl_khr_3d_image_writes) +// Clang Extensions. +OPENCLEXT(cl_clang_storage_class_specifiers) + #undef OPENCLEXT diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index d06c1ed70d..645ddcb468 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -42,6 +42,7 @@ namespace clang { class NestedNameSpecifierLoc; class ObjCDeclSpec; class Preprocessor; + class Sema; class Declarator; struct TemplateIdAnnotation; @@ -537,8 +538,8 @@ public: /// /// TODO: use a more general approach that still allows these /// diagnostics to be ignored when desired. - bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID, const LangOptions &Lang); + bool SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID); bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 0e4fee3086..5e1a42dc07 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1945,30 +1945,30 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // storage-class-specifier case tok::kw_typedef: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc, + PrevSpec, DiagID); break; case tok::kw_extern: if (DS.isThreadSpecified()) Diag(Tok, diag::ext_thread_before) << "extern"; - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc, + PrevSpec, DiagID); break; case tok::kw___private_extern__: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc, - PrevSpec, DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern, + Loc, PrevSpec, DiagID); break; case tok::kw_static: if (DS.isThreadSpecified()) Diag(Tok, diag::ext_thread_before) << "static"; - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc, + PrevSpec, DiagID); break; case tok::kw_auto: if (getLang().CPlusPlus0x) { if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, + PrevSpec, DiagID); if (!isInvalid) Diag(Tok, diag::ext_auto_storage_class) << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); @@ -1976,16 +1976,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID); } else - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, + PrevSpec, DiagID); break; case tok::kw_register: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc, + PrevSpec, DiagID); break; case tok::kw_mutable: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc, + PrevSpec, DiagID); break; case tok::kw___thread: isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID); diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index e4d76c8fd5..d7732c78dd 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -15,6 +15,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/LocInfoType.h" #include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Sema.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" @@ -403,21 +404,24 @@ const char *DeclSpec::getSpecifierName(TQ T) { llvm_unreachable("Unknown typespec!"); } -bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc, +bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID, - const LangOptions &Lang) { - // OpenCL prohibits extern, auto, register, and static + unsigned &DiagID) { + // OpenCL 1.1 6.8g: "The extern, static, auto and register storage-class + // specifiers are not supported." // It seems sensible to prohibit private_extern too - if (Lang.OpenCL) { - switch (S) { + // The cl_clang_storage_class_specifiers extension enables support for + // these storage-class specifiers. + if (S.getLangOptions().OpenCL && + !S.getOpenCLOptions().cl_clang_storage_class_specifiers) { + switch (SC) { case SCS_extern: case SCS_private_extern: case SCS_auto: case SCS_register: case SCS_static: DiagID = diag::err_not_opencl_storage_class_specifier; - PrevSpec = getSpecifierName(S); + PrevSpec = getSpecifierName(SC); return true; default: break; @@ -427,8 +431,8 @@ bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc, if (StorageClassSpec != SCS_unspecified) { // Maybe this is an attempt to use C++0x 'auto' outside of C++0x mode. bool isInvalid = true; - if (TypeSpecType == TST_unspecified && Lang.CPlusPlus) { - if (S == SCS_auto) + if (TypeSpecType == TST_unspecified && S.getLangOptions().CPlusPlus) { + if (SC == SCS_auto) return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID); if (StorageClassSpec == SCS_auto) { isInvalid = SetTypeSpecType(TST_auto, StorageClassSpecLoc, @@ -443,12 +447,12 @@ bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc, if (isInvalid && !(SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern && - S == SCS_typedef)) - return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID); + SC == SCS_typedef)) + return BadSpecifier(SC, (SCS)StorageClassSpec, PrevSpec, DiagID); } - StorageClassSpec = S; + StorageClassSpec = SC; StorageClassSpecLoc = Loc; - assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield"); + assert((unsigned)SC == StorageClassSpec && "SCS constants overflow bitfield"); return false; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d5567d5fdc..1974f30b8e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2592,8 +2592,8 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Invalid = true; // Recover by adding 'static'. - DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(), - PrevSpec, DiagID, getLangOptions()); + DS.SetStorageClassSpec(*this, DeclSpec::SCS_static, SourceLocation(), + PrevSpec, DiagID); } // C++ [class.union]p3: // A storage class is not allowed in a declaration of an @@ -2605,8 +2605,8 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Invalid = true; // Recover by removing the storage specifier. - DS.SetStorageClassSpec(DeclSpec::SCS_unspecified, SourceLocation(), - PrevSpec, DiagID, getLangOptions()); + DS.SetStorageClassSpec(*this, DeclSpec::SCS_unspecified, SourceLocation(), + PrevSpec, DiagID); } // Ignore const/volatile/restrict qualifiers. diff --git a/test/Parser/opencl-storage-class.cl b/test/Parser/opencl-storage-class.cl index d479358f00..874329b62d 100644 --- a/test/Parser/opencl-storage-class.cl +++ b/test/Parser/opencl-storage-class.cl @@ -6,4 +6,10 @@ void test_storage_class_specs() register int b; // expected-error {{OpenCL does not support the 'register' storage class specifier}} extern int c; // expected-error {{OpenCL does not support the 'extern' storage class specifier}} auto int d; // expected-error {{OpenCL does not support the 'auto' storage class specifier}} + +#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers : enable + static int e; + register int f; + extern int g; + auto int h; }