forked from OSchip/llvm-project
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. llvm-svn: 141271
This commit is contained in:
parent
6a0e48c746
commit
485b80fecc
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue