]> granicus.if.org Git - clang/commitdiff
OpenCL: add a non-standard extension, cl_clang_storage_class_specifiers,
authorPeter Collingbourne <peter@pcc.me.uk>
Thu, 6 Oct 2011 03:01:00 +0000 (03:01 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Thu, 6 Oct 2011 03:01:00 +0000 (03:01 +0000)
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

include/clang/Basic/OpenCLExtensions.def
include/clang/Sema/DeclSpec.h
lib/Parse/ParseDecl.cpp
lib/Sema/DeclSpec.cpp
lib/Sema/SemaDecl.cpp
test/Parser/opencl-storage-class.cl

index 95cc1a9a513f671e518c52ec95ca55ea64d0a2ab..103fa839b8dfb80d3ff7cb9717984c44d79c1950 100644 (file)
@@ -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
index d06c1ed70d0bf2af35fcf02e28414c82a0534cb1..645ddcb468dfd9a03234ced92181291988099a4c 100644 (file)
@@ -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,
index 0e4fee3086db93af9595361a19560d2a932b8710..5e1a42dc0733106faf44fecffccca6440482e389 100644 (file)
@@ -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);
index e4d76c8fd56c2250a117fd43820c6fc459aced1c..d7732c78ddbf087df1156d8f05a52a3149ff8607 100644 (file)
@@ -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;
 }
 
index d5567d5fdc56b578f11e3ab4e4bc3b3d98065247..1974f30b8e554b8935a76eb5dcad0f0b6a86440e 100644 (file)
@@ -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.
index d479358f00240a18a76ba29859659d33e6343e22..874329b62d5a954c9733985cd1f01e163dee3b1a 100644 (file)
@@ -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;
 }