Author: joey Date: Fri Nov 18 08:10:54 2016 New Revision: 287343 URL: http://llvm.org/viewvc/llvm-project?rev=287343&view=rev Log: [OpenCL] Introduce ReadPipeType and WritePipeType. This allows Sema to diagnose passing a read_only pipe to a write_only pipe argument.
Modified: cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/include/clang/AST/Type.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/include/clang/Serialization/ASTBitCodes.h cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/lib/AST/TypePrinter.cpp cfe/trunk/lib/Sema/SemaType.cpp cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/lib/Serialization/ASTReader.cpp cfe/trunk/lib/Serialization/ASTWriter.cpp cfe/trunk/test/Misc/ast-dump-pipe.cl cfe/trunk/test/SemaOpenCL/access-qualifier.cl cfe/trunk/test/SemaOpenCL/invalid-pipes-cl2.0.cl Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Fri Nov 18 08:10:54 2016 @@ -135,7 +135,8 @@ class ASTContext : public RefCountedBase mutable llvm::FoldingSet<AutoType> AutoTypes; mutable llvm::FoldingSet<AtomicType> AtomicTypes; llvm::FoldingSet<AttributedType> AttributedTypes; - mutable llvm::FoldingSet<PipeType> PipeTypes; + mutable llvm::FoldingSet<ReadPipeType> ReadPipeTypes; + mutable llvm::FoldingSet<WritePipeType> WritePipeTypes; mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; @@ -1120,8 +1121,10 @@ public: /// blocks. QualType getBlockDescriptorType() const; - /// \brief Return pipe type for the specified type. - QualType getPipeType(QualType T) const; + /// \brief Return a read_only pipe type for the specified type. + QualType getReadPipeType(QualType T) const; + /// \brief Return a write_only pipe type for the specified type. + QualType getWritePipeType(QualType T) const; /// Gets the struct used to keep track of the extended descriptor for /// pointer to blocks. Modified: cfe/trunk/include/clang/AST/Type.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Type.h (original) +++ cfe/trunk/include/clang/AST/Type.h Fri Nov 18 08:10:54 2016 @@ -5285,18 +5285,18 @@ class AtomicType : public Type, public l /// PipeType - OpenCL20. class PipeType : public Type, public llvm::FoldingSetNode { +protected: QualType ElementType; + bool isRead; - PipeType(QualType elemType, QualType CanonicalPtr) : + PipeType(QualType elemType, QualType CanonicalPtr, bool isRead) : Type(Pipe, CanonicalPtr, elemType->isDependentType(), elemType->isInstantiationDependentType(), elemType->isVariablyModifiedType(), elemType->containsUnexpandedParameterPack()), - ElementType(elemType) {} - friend class ASTContext; // ASTContext creates these. + ElementType(elemType), isRead(isRead) {} public: - QualType getElementType() const { return ElementType; } bool isSugared() const { return false; } @@ -5311,11 +5311,23 @@ public: ID.AddPointer(T.getAsOpaquePtr()); } - static bool classof(const Type *T) { return T->getTypeClass() == Pipe; } + bool isReadOnly() const { return isRead; } +}; + +class ReadPipeType : public PipeType { + ReadPipeType(QualType elemType, QualType CanonicalPtr) : + PipeType(elemType, CanonicalPtr, true) {} + friend class ASTContext; // ASTContext creates these. +}; + +class WritePipeType : public PipeType { + WritePipeType(QualType elemType, QualType CanonicalPtr) : + PipeType(elemType, CanonicalPtr, false) {} + friend class ASTContext; // ASTContext creates these. }; /// A qualifier set is used to build a set of qualifiers. Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Fri Nov 18 08:10:54 2016 @@ -1303,7 +1303,9 @@ public: SourceLocation Loc, DeclarationName Entity); QualType BuildParenType(QualType T); QualType BuildAtomicType(QualType T, SourceLocation Loc); - QualType BuildPipeType(QualType T, + QualType BuildReadPipeType(QualType T, + SourceLocation Loc); + QualType BuildWritePipeType(QualType T, SourceLocation Loc); TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S); Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original) +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Fri Nov 18 08:10:54 2016 @@ -905,10 +905,12 @@ namespace clang { TYPE_DECAYED = 41, /// \brief An AdjustedType record. TYPE_ADJUSTED = 42, - /// \brief A PipeType record. - TYPE_PIPE = 43, + /// \brief A ReadPipeType record. + TYPE_READ_PIPE = 43, /// \brief An ObjCTypeParamType record. - TYPE_OBJC_TYPE_PARAM = 44 + TYPE_OBJC_TYPE_PARAM = 44, + /// \brief A WritePipeType record. + TYPE_WRITE_PIPE = 45, }; /// \brief The type IDs for special types constructed by semantic Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Fri Nov 18 08:10:54 2016 @@ -3338,29 +3338,53 @@ QualType ASTContext::getFunctionTypeInte return QualType(FTP, 0); } -/// Return pipe type for the specified type. -QualType ASTContext::getPipeType(QualType T) const { +QualType ASTContext::getReadPipeType(QualType T) const { llvm::FoldingSetNodeID ID; - PipeType::Profile(ID, T); + ReadPipeType::Profile(ID, T); void *InsertPos = 0; - if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos)) + if (ReadPipeType *PT = ReadPipeTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(PT, 0); // If the pipe element type isn't canonical, this won't be a canonical type // either, so fill in the canonical type field. QualType Canonical; if (!T.isCanonical()) { - Canonical = getPipeType(getCanonicalType(T)); + Canonical = getReadPipeType(getCanonicalType(T)); // Get the new insert position for the node we care about. - PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos); + ReadPipeType *NewIP = ReadPipeTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical); + ReadPipeType *New = new (*this, TypeAlignment) ReadPipeType(T, Canonical); Types.push_back(New); - PipeTypes.InsertNode(New, InsertPos); + ReadPipeTypes.InsertNode(New, InsertPos); + return QualType(New, 0); +} + +QualType ASTContext::getWritePipeType(QualType T) const { + llvm::FoldingSetNodeID ID; + WritePipeType::Profile(ID, T); + + void *InsertPos = 0; + if (WritePipeType *PT = WritePipeTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(PT, 0); + + // If the pipe element type isn't canonical, this won't be a canonical type + // either, so fill in the canonical type field. + QualType Canonical; + if (!T.isCanonical()) { + Canonical = getWritePipeType(getCanonicalType(T)); + + // Get the new insert position for the node we care about. + WritePipeType *NewIP = WritePipeTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!NewIP && "Shouldn't be in the map!"); + (void)NewIP; + } + WritePipeType *New = new (*this, TypeAlignment) WritePipeType(T, Canonical); + Types.push_back(New); + WritePipeTypes.InsertNode(New, InsertPos); return QualType(New, 0); } @@ -7720,7 +7744,7 @@ bool ASTContext::typesAreCompatible(Qual bool CompareUnqualified) { if (getLangOpts().CPlusPlus) return hasSameType(LHS, RHS); - + return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull(); } @@ -8248,7 +8272,8 @@ QualType ASTContext::mergeTypes(QualType return LHS; if (getCanonicalType(RHSValue) == getCanonicalType(ResultType)) return RHS; - return getPipeType(ResultType); + return isa<ReadPipeType>(LHS) ? getReadPipeType(ResultType) + : getWritePipeType(ResultType); } } Modified: cfe/trunk/lib/AST/TypePrinter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/lib/AST/TypePrinter.cpp (original) +++ cfe/trunk/lib/AST/TypePrinter.cpp Fri Nov 18 08:10:54 2016 @@ -901,6 +901,10 @@ void TypePrinter::printAtomicAfter(const void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); + if (T->isReadOnly()) + OS << "read_only "; + else + OS << "write_only "; OS << "pipe "; print(T->getElementType(), OS, StringRef()); spaceBeforePlaceHolder(OS); Modified: cfe/trunk/lib/Sema/SemaType.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaType.cpp (original) +++ cfe/trunk/lib/Sema/SemaType.cpp Fri Nov 18 08:10:54 2016 @@ -2040,7 +2040,7 @@ QualType Sema::BuildReferenceType(QualTy return Context.getRValueReferenceType(T); } -/// \brief Build a Pipe type. +/// \brief Build a Read-only Pipe type. /// /// \param T The type to which we'll be building a Pipe. /// @@ -2048,11 +2048,20 @@ QualType Sema::BuildReferenceType(QualTy /// /// \returns A suitable pipe type, if there are no errors. Otherwise, returns a /// NULL type. -QualType Sema::BuildPipeType(QualType T, SourceLocation Loc) { - assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType"); +QualType Sema::BuildReadPipeType(QualType T, SourceLocation Loc) { + return Context.getReadPipeType(T); +} - // Build the pipe type. - return Context.getPipeType(T); +/// \brief Build a Write-only Pipe type. +/// +/// \param T The type to which we'll be building a Pipe. +/// +/// \param Loc We do not use it for now. +/// +/// \returns A suitable pipe type, if there are no errors. Otherwise, returns a +/// NULL type. +QualType Sema::BuildWritePipeType(QualType T, SourceLocation Loc) { + return Context.getWritePipeType(T); } /// Check whether the specified array size makes the array type a VLA. If so, @@ -4531,7 +4540,9 @@ static TypeSourceInfo *GetFullTypeForDec } case DeclaratorChunk::Pipe: { - T = S.BuildPipeType(T, DeclType.Loc ); + T = S.BuildReadPipeType(T, DeclType.Loc); + processTypeAttrs(state, T, TAL_DeclSpec, + D.getDeclSpec().getAttributes().getList()); break; } } @@ -6681,6 +6692,11 @@ static void HandleOpenCLAccessAttr(QualT S.Diag(TypedefTy->getDecl()->getLocStart(), diag::note_opencl_typedef_access_qualifier) << PrevAccessQual; + } else if (CurType->isPipeType()) { + if (Attr.getSemanticSpelling() == OpenCLAccessAttr::Keyword_write_only) { + QualType ElemType = CurType->getAs<PipeType>()->getElementType(); + CurType = S.Context.getWritePipeType(ElemType); + } } } Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Fri Nov 18 08:10:54 2016 @@ -1059,7 +1059,8 @@ public: QualType RebuildAtomicType(QualType ValueType, SourceLocation KWLoc); /// \brief Build a new pipe type given its value type. - QualType RebuildPipeType(QualType ValueType, SourceLocation KWLoc); + QualType RebuildPipeType(QualType ValueType, SourceLocation KWLoc, + bool isReadPipe); /// \brief Build a new template name given a nested name specifier, a flag /// indicating whether the "template" keyword was provided, and the template @@ -5483,7 +5484,9 @@ QualType TreeTransform<Derived>::Transfo QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || ValueType != TL.getValueLoc().getType()) { - Result = getDerived().RebuildPipeType(ValueType, TL.getKWLoc()); + const PipeType *PT = Result->getAs<PipeType>(); + bool isReadPipe = PT->isReadOnly(); + Result = getDerived().RebuildPipeType(ValueType, TL.getKWLoc(), isReadPipe); if (Result.isNull()) return QualType(); } @@ -11839,8 +11842,10 @@ QualType TreeTransform<Derived>::Rebuild template<typename Derived> QualType TreeTransform<Derived>::RebuildPipeType(QualType ValueType, - SourceLocation KWLoc) { - return SemaRef.BuildPipeType(ValueType, KWLoc); + SourceLocation KWLoc, + bool isReadPipe) { + return isReadPipe ? SemaRef.BuildReadPipeType(ValueType, KWLoc) + : SemaRef.BuildWritePipeType(ValueType, KWLoc); } template<typename Derived> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReader.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Nov 18 08:10:54 2016 @@ -5793,7 +5793,7 @@ QualType ASTReader::readTypeRecord(unsig return Context.getAtomicType(ValueType); } - case TYPE_PIPE: { + case TYPE_READ_PIPE: { if (Record.size() != 1) { Error("Incorrect encoding of pipe type"); return QualType(); @@ -5801,7 +5801,18 @@ QualType ASTReader::readTypeRecord(unsig // Reading the pipe element type. QualType ElementType = readType(*Loc.F, Record, Idx); - return Context.getPipeType(ElementType); + return Context.getReadPipeType(ElementType); + } + + case TYPE_WRITE_PIPE: { + if (Record.size() != 1) { + Error("Incorrect encoding of pipe type"); + return QualType(); + } + + // Reading the pipe element type. + QualType ElementType = readType(*Loc.F, Record, Idx); + return Context.getWritePipeType(ElementType); } } llvm_unreachable("Invalid TypeCode!"); Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Nov 18 08:10:54 2016 @@ -516,7 +516,10 @@ ASTTypeWriter::VisitAtomicType(const Ato void ASTTypeWriter::VisitPipeType(const PipeType *T) { Record.AddTypeRef(T->getElementType()); - Code = TYPE_PIPE; + if (T->isReadOnly()) + Code = TYPE_READ_PIPE; + else + Code = TYPE_WRITE_PIPE; } namespace { Modified: cfe/trunk/test/Misc/ast-dump-pipe.cl URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-pipe.cl?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/test/Misc/ast-dump-pipe.cl (original) +++ cfe/trunk/test/Misc/ast-dump-pipe.cl Fri Nov 18 08:10:54 2016 @@ -1,4 +1,12 @@ // RUN: %clang_cc1 -triple spir64 -cl-std=CL2.0 -ast-dump -ast-dump-filter pipetype %s | FileCheck -strict-whitespace %s typedef pipe int pipetype; -// CHECK: PipeType {{.*}} 'pipe int' +// CHECK: PipeType {{.*}} 'read_only pipe int' +// CHECK-NEXT: BuiltinType {{.*}} 'int' + +typedef read_only pipe int pipetype2; +// CHECK: PipeType {{.*}} 'read_only pipe int' +// CHECK-NEXT: BuiltinType {{.*}} 'int' + +typedef write_only pipe int pipetype3; +// CHECK: PipeType {{.*}} 'write_only pipe int' // CHECK-NEXT: BuiltinType {{.*}} 'int' Modified: cfe/trunk/test/SemaOpenCL/access-qualifier.cl URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/access-qualifier.cl?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/test/SemaOpenCL/access-qualifier.cl (original) +++ cfe/trunk/test/SemaOpenCL/access-qualifier.cl Fri Nov 18 08:10:54 2016 @@ -63,7 +63,14 @@ kernel void k11(read_only write_only ima kernel void k12(read_only read_only image1d_t i){} // expected-error{{multiple access qualifiers}} #if __OPENCL_C_VERSION__ >= 200 -kernel void k13(read_write pipe int i){} // expected-error{{access qualifier 'read_write' can not be used for 'pipe int'}} +kernel void k13(read_write pipe int i){} // expected-error{{access qualifier 'read_write' can not be used for 'read_only pipe int'}} #else kernel void k13(__read_write image1d_t i){} // expected-error{{access qualifier '__read_write' can not be used for '__read_write image1d_t' prior to OpenCL version 2.0}} #endif + +#if __OPENCL_C_VERSION__ >= 200 +void myPipeWrite(write_only pipe int); // expected-note {{passing argument to parameter here}} +kernel void k14(read_only pipe int p) { + myPipeWrite(p); // expected-error {{passing 'read_only pipe int' to parameter of incompatible type 'write_only pipe int'}} +} +#endif Modified: cfe/trunk/test/SemaOpenCL/invalid-pipes-cl2.0.cl URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/invalid-pipes-cl2.0.cl?rev=287343&r1=287342&r2=287343&view=diff ============================================================================== --- cfe/trunk/test/SemaOpenCL/invalid-pipes-cl2.0.cl (original) +++ cfe/trunk/test/SemaOpenCL/invalid-pipes-cl2.0.cl Fri Nov 18 08:10:54 2016 @@ -7,16 +7,16 @@ void test2(pipe p) {// expected-error {{ void test3(int pipe p) {// expected-error {{cannot combine with previous 'int' declaration specifier}} } void test4() { - pipe int p; // expected-error {{type 'pipe int' can only be used as a function parameter}} + pipe int p; // expected-error {{type 'read_only pipe int' can only be used as a function parameter}} //TODO: fix parsing of this pipe int (*p); } void test5(pipe int p) { - p+p; // expected-error{{invalid operands to binary expression ('pipe int' and 'pipe int')}} - p=p; // expected-error{{invalid operands to binary expression ('pipe int' and 'pipe int')}} - &p; // expected-error{{invalid argument type 'pipe int' to unary expression}} - *p; // expected-error{{invalid argument type 'pipe int' to unary expression}} + p+p; // expected-error{{invalid operands to binary expression ('read_only pipe int' and 'read_only pipe int')}} + p=p; // expected-error{{invalid operands to binary expression ('read_only pipe int' and 'read_only pipe int')}} + &p; // expected-error{{invalid argument type 'read_only pipe int' to unary expression}} + *p; // expected-error{{invalid argument type 'read_only pipe int' to unary expression}} } typedef pipe int pipe_int_t; -pipe_int_t test6() {} // expected-error{{declaring function return value of type 'pipe_int_t' (aka 'pipe int') is not allowed}} +pipe_int_t test6() {} // expected-error{{declaring function return value of type 'pipe_int_t' (aka 'read_only pipe int') is not allowed}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits