Hi Joey, In order for ReadPipeType and WritePipeType to work with LLVM type system (isa, dyn_cast), you need to modify the existing TypeClass::Pipe kind into TypeClass::ReadPipe and TypeClass::WritePipe, have Pipe::classof recognize both kinds and have ReadPipe::classof and WritePipe::classof recognize their respective kinds.
See rule 4 in http://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html Good example is how ConstantArrayType, IncompleteArrayType, VariableArrayType, DependentSizedArrayType inherit from ArrayType. Yaron 2016-11-18 16:10 GMT+02:00 Joey Gouly via cfe-commits < cfe-commits@lists.llvm.org>: > 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 >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits