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< Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -258,18 +258,11 @@ return false; } -/// Returns readable name for a call. -static StringRef getFunctionName(CallExpr *Call) { - return cast(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()) - return D->getAttr(); - return nullptr; + return D->getAttr(); } /// Returns true if pipe element type is different from the pointer. @@ -278,7 +271,7 @@ // 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 = @@ -287,18 +280,37 @@ // 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(Arg0->getType()); - const Type *EltTy = PipeTy->getElementType().getTypePtr(); - const PointerType *ArgTy = - dyn_cast(ArgIdx->getType().getTypePtr()); + const QualType EltTy = PipeTy->getElementType(); + const PointerType *ArgTy = ArgIdx->getType()->getAs(); // 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,16 +339,15 @@ // \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; @@ -347,32 +356,32 @@ 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: 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,22 +5,22 @@ 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)}} } @@ -29,27 +29,27 @@ 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}} }