Index: include/clang/Basic/Builtins.h =================================================================== --- include/clang/Basic/Builtins.h +++ include/clang/Basic/Builtins.h @@ -31,12 +31,12 @@ class LangOptions; enum LanguageID { - GNU_LANG = 0x1, // builtin requires GNU mode. - C_LANG = 0x2, // builtin for c only. - CXX_LANG = 0x4, // builtin for cplusplus only. - OBJC_LANG = 0x8, // builtin for objective-c and objective-c++ - MS_LANG = 0x10, // builtin requires MS mode. - OCLC_LANG = 0x20,// builtin for OpenCL C only. + GNU_LANG = 0x1, // builtin requires GNU mode. + C_LANG = 0x2, // builtin for c only. + CXX_LANG = 0x4, // builtin for cplusplus only. + OBJC_LANG = 0x8, // builtin for objective-c and objective-c++ + MS_LANG = 0x10, // builtin requires MS mode. + OCLC_LANG = 0x20, // builtin for OpenCL C only. ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages. ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode. ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode. Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -7746,7 +7746,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 @@ -259,16 +259,9 @@ return false; } -/// Returns readable name for a call. -static StringRef getFunctionName(CallExpr *Call) { - return cast(Call->getCalleeDecl())->getName(); -} - /// Returns OpenCL access qual. static OpenCLAccessAttr *getOpenCLArgAccess(const Decl *D) { - if (D->hasAttr()) return D->getAttr(); - return nullptr; } /// Returns true if pipe element type is different from the pointer. @@ -277,7 +270,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; } OpenCLAccessAttr *AccessQual = @@ -286,20 +279,38 @@ // 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; } @@ -308,15 +319,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; } @@ -328,16 +337,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; @@ -346,32 +354,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; } @@ -390,11 +398,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; } @@ -414,10 +422,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; } @@ -436,7 +444,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{{invalid 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{{invalid 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}} }