svenvh created this revision.
svenvh added reviewers: Anastasia, rjmccall.
Herald added subscribers: cfe-commits, yaxunl.

In OpenCL C++ mode, the "program scope variable must reside ..."
diagnostic is firing early in some cases, potentially confusing the
user.  It is the first diagnostic reported for

  int g(global int *p) {}

but the actual problem is the undeclared identifier `global`.

The main reason to improve error reporting for the example above is
that OpenCL C address space qualifiers such as `global` are not part
of OpenCL C++.  This means the PSV diagnostic will fire when porting
OpenCL C code to OpenCL C++ if an address space qualifier is left in
by accident.

The PSV diagnostic is emitted for the example above because the parser
believes `g` is a variable declaration instead of a function
declaration.  This seems to be inherent to C++ parsing, so postpone
the PSV diagnostic until we have parsed the entire declarator group.
We still get the PSV diagnostic for the example, but it is no longer
the first so it should be easier for the user to see what the actual
problem is.


Repository:
  rC Clang

https://reviews.llvm.org/D53705

Files:
  lib/Sema/SemaDecl.cpp
  test/SemaOpenCL/storageclass-cl20.cl
  test/SemaOpenCL/storageclass.cl
  test/SemaOpenCLCXX/invalid-qualifier.cl

Index: test/SemaOpenCLCXX/invalid-qualifier.cl
===================================================================
--- /dev/null
+++ test/SemaOpenCLCXX/invalid-qualifier.cl
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -fsyntax-only -verify
+// RUN: not %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -fsyntax-only 2>&1 | FileCheck %s
+
+// Use FileCheck to check that "program scope variable must reside ..." is not
+// the first diagnostic reported.
+
+int f1(global int *p) {}
+// expected-error@-1{{use of undeclared identifier 'global'}}
+// expected-error@-2{{expected ';' after top level declarator}}
+// expected-error@-3{{program scope variable must reside in constant address space}}
+// CHECK: use of undeclared identifier 'global'
+// CHECK: program scope variable must reside in constant address space
+
+; // For parser recovery.
+
+int f2(local int *p) {}
+// expected-error@-1{{use of undeclared identifier 'local'}}
+// expected-error@-2{{expected ';' after top level declarator}}
+// expected-error@-3{{program scope variable must reside in constant address space}}
+// CHECK: use of undeclared identifier 'local'
+// CHECK: program scope variable must reside in constant address space
+
+; // For parser recovery.
+
+int g(abcdef int q) {}
+// expected-error@-1{{use of undeclared identifier 'abcdef'}}
+// expected-error@-2{{expected ';' after top level declarator}}
+// expected-error@-3{{program scope variable must reside in constant address space}}
+// CHECK: use of undeclared identifier 'abcdef'
+// CHECK: program scope variable must reside in constant address space
+
+; // For parser recovery.
Index: test/SemaOpenCL/storageclass.cl
===================================================================
--- test/SemaOpenCL/storageclass.cl
+++ test/SemaOpenCL/storageclass.cl
@@ -4,11 +4,12 @@
 constant int G2 = 0;
 int G3 = 0;        // expected-error{{program scope variable must reside in constant address space}}
 global int G4 = 0; // expected-error{{program scope variable must reside in constant address space}}
+int G5, G6;        // expected-error 2 {{program scope variable must reside in constant address space}}
 
 static float g_implicit_static_var = 0; // expected-error {{program scope variable must reside in constant address space}}
 static constant float g_constant_static_var = 0;
 static global float g_global_static_var = 0;   // expected-error {{program scope variable must reside in constant address space}}
-static local float g_local_static_var = 0;     // expected-error {{program scope variable must reside in constant address space}}
+static local float g_local_static_var = 0;     // expected-error {{'__local' variable cannot have an initializer}}
 static private float g_private_static_var = 0; // expected-error {{program scope variable must reside in constant address space}}
 static generic float g_generic_static_var = 0; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{program scope variable must reside in constant address space}}
 
Index: test/SemaOpenCL/storageclass-cl20.cl
===================================================================
--- test/SemaOpenCL/storageclass-cl20.cl
+++ test/SemaOpenCL/storageclass-cl20.cl
@@ -2,12 +2,12 @@
 
 int G2 = 0;
 global int G3 = 0;
-local int G4 = 0;              // expected-error{{program scope variable must reside in global or constant address space}}
+local int G4 = 0;              // expected-error{{'__local' variable cannot have an initializer}}
 
 static float g_implicit_static_var = 0;
 static constant float g_constant_static_var = 0;
 static global float g_global_static_var = 0;
-static local float g_local_static_var = 0;     // expected-error {{program scope variable must reside in global or constant address space}}
+static local float g_local_static_var = 0;     // expected-error {{'__local' variable cannot have an initializer}}
 static private float g_private_static_var = 0; // expected-error {{program scope variable must reside in global or constant address space}}
 static generic float g_generic_static_var = 0; // expected-error {{program scope variable must reside in global or constant address space}}
 
@@ -28,7 +28,7 @@
   static float l_implicit_static_var = 0;
   static constant float l_constant_static_var = 0;
   static global float l_global_static_var = 0;
-  static local float l_local_static_var = 0;     // expected-error {{static local variable must reside in global or constant address space}}
+  static local float l_local_static_var = 0;     // expected-error {{'__local' variable cannot have an initializer}}
   static private float l_private_static_var = 0; // expected-error {{static local variable must reside in global or constant address space}}
   static generic float l_generic_static_var = 0; // expected-error {{static local variable must reside in global or constant address space}}
 
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -7352,28 +7352,8 @@
         return;
       }
     }
-    // OpenCL v1.2 s6.5 - All program scope variables must be declared in the
-    // __constant address space.
-    // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static
-    // variables inside a function can also be declared in the global
-    // address space.
-    if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() ||
-        NewVD->hasExternalStorage()) {
-      if (!T->isSamplerT() &&
-          !(T.getAddressSpace() == LangAS::opencl_constant ||
-            (T.getAddressSpace() == LangAS::opencl_global &&
-             getLangOpts().OpenCLVersion == 200))) {
-        int Scope = NewVD->isStaticLocal() | NewVD->hasExternalStorage() << 1;
-        if (getLangOpts().OpenCLVersion == 200)
-          Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
-              << Scope << "global or constant";
-        else
-          Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
-              << Scope << "constant";
-        NewVD->setInvalidDecl();
-        return;
-      }
-    } else {
+    if (!NewVD->isFileVarDecl() && !NewVD->isStaticLocal() &&
+        !NewVD->hasExternalStorage()) {
       if (T.getAddressSpace() == LangAS::opencl_global) {
         Diag(NewVD->getLocation(), diag::err_opencl_function_variable)
             << 1 /*is any function*/ << "global";
@@ -12161,8 +12141,39 @@
             DiagnosedNonDeducedAuto = true;
           }
         }
-      }
 
+        // OpenCL v1.2 s6.5 - All program scope variables must be declared in
+        // the __constant address space.
+        // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static
+        // variables inside a function can also be declared in the global
+        // address space.
+        if (getLangOpts().OpenCL) {
+          if (VarDecl *NewVD = dyn_cast<VarDecl>(D)) {
+            if (!D->isInvalidDecl()) {
+              QualType T = NewVD->getType();
+              if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() ||
+                  NewVD->hasExternalStorage()) {
+                if (!T->isSamplerT() &&
+                    !(T.getAddressSpace() == LangAS::opencl_constant ||
+                      (T.getAddressSpace() == LangAS::opencl_global &&
+                       getLangOpts().OpenCLVersion == 200))) {
+                  int Scope =
+                      NewVD->isStaticLocal() | NewVD->hasExternalStorage() << 1;
+                  if (getLangOpts().OpenCLVersion == 200)
+                    Diag(NewVD->getLocation(),
+                         diag::err_opencl_global_invalid_addr_space)
+                        << Scope << "global or constant";
+                  else
+                    Diag(NewVD->getLocation(),
+                         diag::err_opencl_global_invalid_addr_space)
+                        << Scope << "constant";
+                  NewVD->setInvalidDecl();
+                }
+              }
+            }
+          }
+        }
+      }
       Decls.push_back(D);
     }
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to