]> granicus.if.org Git - clang/commitdiff
Reject forbidden storage class specifiers in OpenCL. Patch by George Russell!
authorPeter Collingbourne <peter@pcc.me.uk>
Fri, 11 Feb 2011 19:59:54 +0000 (19:59 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Fri, 11 Feb 2011 19:59:54 +0000 (19:59 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125399 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticParseKinds.td
include/clang/Sema/DeclSpec.h
lib/Parse/ParseDecl.cpp
lib/Sema/DeclSpec.cpp
lib/Sema/SemaDecl.cpp
test/Parser/cl_storage_class.cl [new file with mode: 0644]
test/lit.cfg

index 0b14ed70241228c40e92629903a9a35d0fd0f513..1eedf639cecbbbb72b9075fbb9f2f1185091247b 100644 (file)
@@ -443,5 +443,9 @@ def warn_pragma_unused_expected_var : Warning<
 def warn_pragma_unused_expected_punc : Warning<
   "expected ')' or ',' in '#pragma unused'">;
 
+// OpenCL Section 6.8.g
+def err_not_opencl_storage_class_specifier : Error<
+  "OpenCL does not support the '%0' storage class specifier">;
+
 } // end of Parse Issue category.
 } // end of Parser diagnostics
index d95f3f78ca4bca3e58a6145b0973cc440086bab0..9c4bb646949b0d51e7f79dd22c09f8289405dc53 100644 (file)
@@ -403,7 +403,7 @@ 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);
+                           unsigned &DiagID, const LangOptions &Lang);
   bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec,
                                  unsigned &DiagID);
   bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec,
index dfac16a082f161bc3246bfd7d1635a9ae958b0b5..d97b4e30a0ae74211b53fb5abf449ea140cbb224 100644 (file)
@@ -1204,23 +1204,23 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
     // storage-class-specifier
     case tok::kw_typedef:
       isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec,
-                                         DiagID);
+                                         DiagID, getLang());
       break;
     case tok::kw_extern:
       if (DS.isThreadSpecified())
         Diag(Tok, diag::ext_thread_before) << "extern";
       isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec,
-                                         DiagID);
+                                         DiagID, getLang());
       break;
     case tok::kw___private_extern__:
       isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc,
-                                         PrevSpec, DiagID);
+                                         PrevSpec, DiagID, getLang());
       break;
     case tok::kw_static:
       if (DS.isThreadSpecified())
         Diag(Tok, diag::ext_thread_before) << "static";
       isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec,
-                                         DiagID);
+                                         DiagID, getLang());
       break;
     case tok::kw_auto:
       if (getLang().CPlusPlus0x)
@@ -1228,15 +1228,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
                                        DiagID);
       else
         isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
-                                           DiagID);
+                                           DiagID, getLang());
       break;
     case tok::kw_register:
       isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec,
-                                         DiagID);
+                                         DiagID, getLang());
       break;
     case tok::kw_mutable:
       isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec,
-                                         DiagID);
+                                         DiagID, getLang());
       break;
     case tok::kw___thread:
       isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID);
index 8a35ab70923f904b3af1ae15cbe2805a17469b37..bc289ec42c99e029170ae2e7009d1eb4e6e64f18 100644 (file)
@@ -226,7 +226,25 @@ const char *DeclSpec::getSpecifierName(TQ T) {
 
 bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
                                    const char *&PrevSpec,
-                                   unsigned &DiagID) {
+                                   unsigned &DiagID,
+                                   const LangOptions &Lang) {
+  // OpenCL prohibits extern, auto, register, and static
+  // It seems sensible to prohibit private_extern too
+  if (Lang.OpenCL) {
+    switch (S) {
+    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);
+      return true;
+    default:
+      break;
+    }
+  }
+
   if (StorageClassSpec != SCS_unspecified) {
     // Changing storage class is allowed only if the previous one
     // was the 'extern' that is part of a linkage specification and
index d756de5e2db5d44a9a4014370290231ffbcf6af7..2807e759b56d4bffb0b8245308a1247bfe34f121 100644 (file)
@@ -1922,7 +1922,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
 
       // Recover by adding 'static'.
       DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(),
-                             PrevSpec, DiagID);
+                             PrevSpec, DiagID, getLangOptions());
     }
     // C++ [class.union]p3:
     //   A storage class is not allowed in a declaration of an
@@ -1935,7 +1935,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
 
       // Recover by removing the storage specifier.
       DS.SetStorageClassSpec(DeclSpec::SCS_unspecified, SourceLocation(),
-                             PrevSpec, DiagID);
+                             PrevSpec, DiagID, getLangOptions());
     }
 
     // C++ [class.union]p2:
diff --git a/test/Parser/cl_storage_class.cl b/test/Parser/cl_storage_class.cl
new file mode 100644 (file)
index 0000000..5db8f4b
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 %s -x cl -verify -fsyntax-only
+
+void test_storage_class_specs()
+{
+  static int a;    // expected-error {{OpenCL does not support the 'static' storage class specifier}}
+  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}}
+}
index 13986a069b9f648a9fc6e9fff9c1641e0c027ce7..6567c6d229cbb16d0b2f890b948646cbcf4fb547 100644 (file)
@@ -28,7 +28,7 @@ execute_external = platform.system() != 'Windows'
 config.test_format = lit.formats.ShTest(execute_external)
 
 # suffixes: A list of file extensions to treat as test files.
-config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll']
+config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl']
 
 # test_source_root: The root path where tests are located.
 config.test_source_root = os.path.dirname(__file__)