pxli168 updated this revision to Diff 46991.

http://reviews.llvm.org/D16876

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaChecking.cpp
  test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl

Index: test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
===================================================================
--- test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
+++ test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
@@ -5,51 +5,51 @@
   reserve_id_t rid;
 
   // read/write_pipe
-  read_pipe(tmp, p);    // expected-error {{first argument to read_pipe must be a pipe type}}
-  read_pipe(p);   // expected-error {{invalid number of arguments to function: read_pipe}}
-  read_pipe(p, tmp, tmp, ptr);   // expected-error {{invalid argument type to function read_pipe (expecting 'reserve_id_t')}}
-  read_pipe(p, rid, rid, ptr);   // expected-error {{invalid argument type to function read_pipe (expecting 'unsigned int')}}
-  read_pipe(p, tmp);   // expected-error {{invalid argument type to function read_pipe (expecting 'int *')}}
+  read_pipe(tmp, p);    // expected-error {{first argument to 'read_pipe' must be a pipe type}}
+  read_pipe(p);   // expected-error {{invalid number of arguments to function: 'read_pipe'}}
+  read_pipe(p, tmp, tmp, ptr);   // expected-error {{invalid argument type to function 'read_pipe' (expecting 'reserve_id_t')}}
+  read_pipe(p, rid, rid, ptr);   // expected-error {{invalid argument type to function 'read_pipe' (expecting 'unsigned int')}}
+  read_pipe(p, tmp);   // expected-error {{invalid argument type to function 'read_pipe' (expecting 'int *')}}
   write_pipe(p, ptr);    // expected-error {{invalid pipe access modifier (expecting write_only)}}
   write_pipe(p, rid, tmp, ptr);    // expected-error {{invalid pipe access modifier (expecting write_only)}}
 
   // reserve_read/write_pipe
-  reserve_read_pipe(p, ptr);    // expected-error{{invalid argument type to function reserve_read_pipe (expecting 'unsigned int')}}
-  work_group_reserve_read_pipe(tmp, tmp);    // expected-error{{first argument to work_group_reserve_read_pipe must be a pipe type}}
+  reserve_read_pipe(p, ptr);    // expected-error{{invalid argument type to function 'reserve_read_pipe' (expecting 'unsigned int')}}
+  work_group_reserve_read_pipe(tmp, tmp);    // expected-error{{first argument to 'work_group_reserve_read_pipe' must be a pipe type}}
   sub_group_reserve_write_pipe(p, tmp);    // expected-error{{invalid pipe access modifier (expecting write_only)}}
 
   // commit_read/write_pipe
-  commit_read_pipe(tmp, rid);    // expected-error{{first argument to commit_read_pipe must be a pipe type}}
-  work_group_commit_read_pipe(p, tmp);    // expected-error{{invalid argument type to function work_group_commit_read_pipe (expecting 'reserve_id_t')}}
+  commit_read_pipe(tmp, rid);    // expected-error{{first argument to 'commit_read_pipe' must be a pipe type}}
+  work_group_commit_read_pipe(p, tmp);    // expected-error{{invalid argument type to function 'work_group_commit_read_pipe' (expecting 'reserve_id_t')}}
   sub_group_commit_write_pipe(p, tmp);    // expected-error{{nvalid pipe access modifier (expecting write_only)}}
 }
 
 void test2(write_only pipe int p, global int* ptr){
   int tmp;
   reserve_id_t rid;
 
   // read/write_pipe
-  write_pipe(tmp, p);    // expected-error {{first argument to write_pipe must be a pipe type}}
-  write_pipe(p);   // expected-error {{invalid number of arguments to function: write_pipe}}
-  write_pipe(p, tmp, tmp, ptr);   // expected-error {{invalid argument type to function write_pipe (expecting 'reserve_id_t')}}
-  write_pipe(p, rid, rid, ptr);   // expected-error {{invalid argument type to function write_pipe (expecting 'unsigned int')}}
-  write_pipe(p, tmp);   // expected-error {{invalid argument type to function write_pipe (expecting 'int *')}}
+  write_pipe(tmp, p);    // expected-error {{first argument to 'write_pipe' must be a pipe type}}
+  write_pipe(p);   // expected-error {{invalid number of arguments to function: 'write_pipe'}}
+  write_pipe(p, tmp, tmp, ptr);   // expected-error {{invalid argument type to function 'write_pipe' (expecting 'reserve_id_t')}}
+  write_pipe(p, rid, rid, ptr);   // expected-error {{invalid argument type to function 'write_pipe' (expecting 'unsigned int')}}
+  write_pipe(p, tmp);   // expected-error {{invalid argument type to function 'write_pipe' (expecting 'int *')}}
   read_pipe(p, ptr);    // expected-error {{invalid pipe access modifier (expecting read_only)}}
   read_pipe(p, rid, tmp, ptr);    // expected-error {{invalid pipe access modifier (expecting read_only)}}
 
   // reserve_read/write_pipe
-  reserve_write_pipe(p, ptr);    // expected-error{{invalid argument type to function reserve_write_pipe (expecting 'unsigned int')}}
-  work_group_reserve_write_pipe(tmp, tmp);    // expected-error{{first argument to work_group_reserve_write_pipe must be a pipe type}}
+  reserve_write_pipe(p, ptr);    // expected-error{{invalid argument type to function 'reserve_write_pipe' (expecting 'unsigned int')}}
+  work_group_reserve_write_pipe(tmp, tmp);    // expected-error{{first argument to 'work_group_reserve_write_pipe' must be a pipe type}}
   sub_group_reserve_read_pipe(p, tmp);    // expected-error{{invalid pipe access modifier (expecting read_only)}}
 
   // commit_read/write_pipe
-  commit_write_pipe(tmp, rid);    // expected-error{{first argument to commit_write_pipe must be a pipe type}}
-  work_group_commit_write_pipe(p, tmp);    // expected-error{{invalid argument type to function work_group_commit_write_pipe (expecting 'reserve_id_t')}}
+  commit_write_pipe(tmp, rid);    // expected-error{{first argument to 'commit_write_pipe' must be a pipe type}}
+  work_group_commit_write_pipe(p, tmp);    // expected-error{{invalid argument type to function 'work_group_commit_write_pipe' (expecting 'reserve_id_t')}}
   sub_group_commit_read_pipe(p, tmp);    // expected-error{{nvalid pipe access modifier (expecting read_only)}}
 }
 
 void test3(){
   int tmp;
-  get_pipe_num_packets(tmp);    // expected-error {{first argument to get_pipe_num_packets must be a pipe type}}
-  get_pipe_max_packets(tmp);    // expected-error {{first argument to get_pipe_max_packets must be a pipe type}}
+  get_pipe_num_packets(tmp);    // expected-error {{first argument to 'get_pipe_num_packets' must be a pipe type}}
+  get_pipe_max_packets(tmp);    // expected-error {{first argument to 'get_pipe_max_packets' must be a pipe type}}
 }
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -258,47 +258,59 @@
   return false;
 }
 
-/// Returns readable name for a call.
-static StringRef getFunctionName(CallExpr *Call) {
-  return cast<FunctionDecl>(Call->getCalleeDecl())->getName();
-}
-
 /// Returns OpenCL access qual.
 // TODO: Refine OpenCLImageAccessAttr to OpenCLAccessAttr since pipe can use
 // it too
 static OpenCLImageAccessAttr *getOpenCLArgAccess(const Decl *D) {
-  if (D->hasAttr<OpenCLImageAccessAttr>())
-    return D->getAttr<OpenCLImageAccessAttr>();
-  return nullptr;
+  return D->getAttr<OpenCLImageAccessAttr>();
 }
 
 /// Returns true if pipe element type is different from the pointer.
 static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) {
   const Expr *Arg0 = Call->getArg(0);
   // First argument type should always be pipe.
   if (!Arg0->getType()->isPipeType()) {
     S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg)
-        << getFunctionName(Call) << Arg0->getSourceRange();
+        << Call->getDirectCallee() << Arg0->getSourceRange();
     return true;
   }
   OpenCLImageAccessAttr *AccessQual =
       getOpenCLArgAccess(cast<DeclRefExpr>(Arg0)->getDecl());
   // Validates the access qualifier is compatible with the call.
   // OpenCL v2.0 s6.13.16 - The access qualifiers for pipe should only be
   // read_only and write_only, and assumed to be read_only if no qualifier is
   // specified.
-  bool isValid = true;
-  bool ReadOnly = getFunctionName(Call).find("read") != StringRef::npos;
-  if (ReadOnly)
-    isValid = AccessQual == nullptr || AccessQual->isReadOnly();
-  else
-    isValid = AccessQual != nullptr && AccessQual->isWriteOnly();
-  if (!isValid) {
-    const char *AM = ReadOnly ? "read_only" : "write_only";
-    S.Diag(Arg0->getLocStart(),
-           diag::err_opencl_builtin_pipe_invalid_access_modifier)
-        << AM << Arg0->getSourceRange();
-    return true;
+  switch (Call->getDirectCallee()->getBuiltinID()) {
+  case Builtin::BIread_pipe:
+  case Builtin::BIreserve_read_pipe:
+  case Builtin::BIcommit_read_pipe:
+  case Builtin::BIwork_group_reserve_read_pipe:
+  case Builtin::BIsub_group_reserve_read_pipe:
+  case Builtin::BIwork_group_commit_read_pipe:
+  case Builtin::BIsub_group_commit_read_pipe:
+    if (!(!AccessQual || AccessQual->isReadOnly())) {
+      S.Diag(Arg0->getLocStart(),
+             diag::err_opencl_builtin_pipe_invalid_access_modifier)
+          << "read_only" << Arg0->getSourceRange();
+      return true;
+    }
+    break;
+  case Builtin::BIwrite_pipe:
+  case Builtin::BIreserve_write_pipe:
+  case Builtin::BIcommit_write_pipe:
+  case Builtin::BIwork_group_reserve_write_pipe:
+  case Builtin::BIsub_group_reserve_write_pipe:
+  case Builtin::BIwork_group_commit_write_pipe:
+  case Builtin::BIsub_group_commit_write_pipe:
+    if (!(AccessQual && AccessQual->isWriteOnly())) {
+      S.Diag(Arg0->getLocStart(),
+             diag::err_opencl_builtin_pipe_invalid_access_modifier)
+          << "write_only" << Arg0->getSourceRange();
+      return true;
+    }
+    break;
+  default:
+    break;
   }
 
   return false;
@@ -309,15 +321,13 @@
   const Expr *Arg0 = Call->getArg(0);
   const Expr *ArgIdx = Call->getArg(Idx);
   const PipeType *PipeTy = cast<PipeType>(Arg0->getType());
-  const Type *EltTy = PipeTy->getElementType().getTypePtr();
-  const PointerType *ArgTy =
-      dyn_cast<PointerType>(ArgIdx->getType().getTypePtr());
+  const QualType EltTy = PipeTy->getElementType();
+  const PointerType *ArgTy = ArgIdx->getType()->getAs<PointerType>();
   // The Idx argument should be a pointer and the type of the pointer and
   // the type of pipe element should also be the same.
-  if (!ArgTy || EltTy != ArgTy->getPointeeType().getTypePtr()) {
+  if (!ArgTy || S.Context.hasSameType(EltTy, ArgTy->getPointeeType())) {
     S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)
-        << getFunctionName(Call)
-        << S.Context.getPointerType(PipeTy->getElementType())
+        << Call->getDirectCallee() << S.Context.getPointerType(EltTy)
         << ArgIdx->getSourceRange();
     return true;
   }
@@ -329,50 +339,49 @@
 // \param Call A pointer to the builtin call.
 // \return True if a semantic error has been found, false otherwise.
 static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) {
-  // Two kinds of read/write pipe
-  // From OpenCL C Specification 6.13.16.2 the built-in read/write
-  // functions have following forms.
+  // OpenCL v2.0 s6.13.16.2 - The built-in read/write
+  // functions have two forms.
   switch (Call->getNumArgs()) {
   case 2: {
     if (checkOpenCLPipeArg(S, Call))
       return true;
     // The call with 2 arguments should be
-    // read/write_pipe(pipe T, T*)
-    // check packet type T
+    // read/write_pipe(pipe T, T*).
+    // Check packet type T.
     if (checkOpenCLPipePacketType(S, Call, 1))
       return true;
   } break;
 
   case 4: {
     if (checkOpenCLPipeArg(S, Call))
       return true;
     // The call with 4 arguments should be
-    // read/write_pipe(pipe T, reserve_id_t, uint, T*)
-    // check reserve_id_t
+    // read/write_pipe(pipe T, reserve_id_t, uint, T*).
+    // Check reserve_id_t.
     if (!Call->getArg(1)->getType()->isReserveIDT()) {
       S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)
-          << getFunctionName(Call) << S.Context.OCLReserveIDTy
+          << Call->getDirectCallee() << S.Context.OCLReserveIDTy
           << Call->getArg(1)->getSourceRange();
       return true;
     }
 
-    // check the index
+    // Check the index.
     const Expr *Arg2 = Call->getArg(2);
     if (!Arg2->getType()->isIntegerType() &&
         !Arg2->getType()->isUnsignedIntegerType()) {
       S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)
-          << getFunctionName(Call) << S.Context.UnsignedIntTy
+          << Call->getDirectCallee() << S.Context.UnsignedIntTy
           << Arg2->getSourceRange();
       return true;
     }
 
-    // check packet type T
+    // Check packet type T.
     if (checkOpenCLPipePacketType(S, Call, 3))
       return true;
   } break;
   default:
     S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_arg_num)
-        << getFunctionName(Call) << Call->getSourceRange();
+        << Call->getDirectCallee() << Call->getSourceRange();
     return true;
   }
 
@@ -391,11 +400,11 @@
   if (checkOpenCLPipeArg(S, Call))
     return true;
 
-  // check the reserve size
+  // Check the reserve size.
   if (!Call->getArg(1)->getType()->isIntegerType() &&
       !Call->getArg(1)->getType()->isUnsignedIntegerType()) {
     S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)
-        << getFunctionName(Call) << S.Context.UnsignedIntTy
+        << Call->getDirectCallee() << S.Context.UnsignedIntTy
         << Call->getArg(1)->getSourceRange();
     return true;
   }
@@ -415,10 +424,10 @@
   if (checkOpenCLPipeArg(S, Call))
     return true;
 
-  // check reserve_id_t
+  // Check reserve_id_t.
   if (!Call->getArg(1)->getType()->isReserveIDT()) {
     S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)
-        << getFunctionName(Call) << S.Context.OCLReserveIDTy
+        << Call->getDirectCallee() << S.Context.OCLReserveIDTy
         << Call->getArg(1)->getSourceRange();
     return true;
   }
@@ -437,7 +446,7 @@
 
   if (!Call->getArg(0)->getType()->isPipeType()) {
     S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg)
-        << getFunctionName(Call) << Call->getArg(0)->getSourceRange();
+        << Call->getDirectCallee() << Call->getArg(0)->getSourceRange();
     return true;
   }
 
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -7697,7 +7697,7 @@
 def err_opencl_builtin_pipe_first_arg : Error<
   "first argument to %0 must be a pipe type">;
 def err_opencl_builtin_pipe_arg_num : Error<
-    "invalid number of arguments to function: %0">;
+  "invalid number of arguments to function: %0">;
 def err_opencl_builtin_pipe_invalid_arg : Error<
   "invalid argument type to function %0 (expecting %1)">;
 def err_opencl_builtin_pipe_invalid_access_modifier : Error<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to