Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -135,8 +135,7 @@ mutable llvm::FoldingSet AutoTypes; mutable llvm::FoldingSet AtomicTypes; llvm::FoldingSet AttributedTypes; - mutable llvm::FoldingSet ReadPipeTypes; - mutable llvm::FoldingSet WritePipeTypes; + mutable llvm::FoldingSet PipeTypes; mutable llvm::FoldingSet QualifiedTemplateNames; mutable llvm::FoldingSet DependentTemplateNames; @@ -1012,6 +1011,8 @@ QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const; + QualType getPipeType(QualType T, bool ReadOnly) const; + public: /// \brief Return the uniqued reference to the type for an address space /// qualified type with the specified type and address space. Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -5285,7 +5285,6 @@ /// PipeType - OpenCL20. class PipeType : public Type, public llvm::FoldingSetNode { -protected: QualType ElementType; bool isRead; @@ -5295,6 +5294,7 @@ elemType->isVariablyModifiedType(), elemType->containsUnexpandedParameterPack()), ElementType(elemType), isRead(isRead) {} + friend class ASTContext; // ASTContext creates these. public: QualType getElementType() const { return ElementType; } @@ -5304,11 +5304,12 @@ QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getElementType()); + Profile(ID, getElementType(), isReadOnly()); } - static void Profile(llvm::FoldingSetNodeID &ID, QualType T) { + static void Profile(llvm::FoldingSetNodeID &ID, QualType T, bool isRead) { ID.AddPointer(T.getAsOpaquePtr()); + ID.AddBoolean(isRead); } static bool classof(const Type *T) { @@ -5318,18 +5319,6 @@ 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. class QualifierCollector : public Qualifiers { public: Index: include/clang/Serialization/ASTBitCodes.h =================================================================== --- include/clang/Serialization/ASTBitCodes.h +++ include/clang/Serialization/ASTBitCodes.h @@ -905,12 +905,10 @@ TYPE_DECAYED = 41, /// \brief An AdjustedType record. TYPE_ADJUSTED = 42, - /// \brief A ReadPipeType record. - TYPE_READ_PIPE = 43, + /// \brief A PipeType record. + TYPE_PIPE = 43, /// \brief An ObjCTypeParamType record. - TYPE_OBJC_TYPE_PARAM = 44, - /// \brief A WritePipeType record. - TYPE_WRITE_PIPE = 45, + TYPE_OBJC_TYPE_PARAM = 44 }; /// \brief The type IDs for special types constructed by semantic Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -3338,54 +3338,37 @@ return QualType(FTP, 0); } -QualType ASTContext::getReadPipeType(QualType T) const { +QualType ASTContext::getPipeType(QualType T, bool ReadOnly) const { llvm::FoldingSetNodeID ID; - ReadPipeType::Profile(ID, T); + PipeType::Profile(ID, T, ReadOnly); void *InsertPos = 0; - if (ReadPipeType *PT = ReadPipeTypes.FindNodeOrInsertPos(ID, InsertPos)) + if (PipeType *PT = PipeTypes.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 = getReadPipeType(getCanonicalType(T)); + Canonical = getPipeType(getCanonicalType(T), ReadOnly); // Get the new insert position for the node we care about. - ReadPipeType *NewIP = ReadPipeTypes.FindNodeOrInsertPos(ID, InsertPos); + PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - ReadPipeType *New = new (*this, TypeAlignment) ReadPipeType(T, Canonical); + PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical, ReadOnly); Types.push_back(New); - ReadPipeTypes.InsertNode(New, InsertPos); + PipeTypes.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)); +QualType ASTContext::getReadPipeType(QualType T) const { + return getPipeType(T, true); +} - // 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); +QualType ASTContext::getWritePipeType(QualType T) const { + return getPipeType(T, false); } #ifndef NDEBUG @@ -8272,8 +8255,9 @@ return LHS; if (getCanonicalType(RHSValue) == getCanonicalType(ResultType)) return RHS; - return isa(LHS) ? getReadPipeType(ResultType) - : getWritePipeType(ResultType); + const PipeType *PT = LHS->getAs(); + return PT->isReadOnly() ? getReadPipeType(ResultType) + : getWritePipeType(ResultType); } } Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -5793,27 +5793,21 @@ return Context.getAtomicType(ValueType); } - case TYPE_READ_PIPE: { - if (Record.size() != 1) { + case TYPE_PIPE: { + if (Record.size() != 2) { Error("Incorrect encoding of pipe type"); return QualType(); } // Reading the pipe element type. QualType ElementType = readType(*Loc.F, Record, Idx); - return Context.getReadPipeType(ElementType); + unsigned ReadOnly = Record[1]; + if (ReadOnly) + return Context.getReadPipeType(ElementType); + else + return Context.getWritePipeType(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!"); } Index: lib/Serialization/ASTWriter.cpp =================================================================== --- lib/Serialization/ASTWriter.cpp +++ lib/Serialization/ASTWriter.cpp @@ -516,10 +516,8 @@ void ASTTypeWriter::VisitPipeType(const PipeType *T) { Record.AddTypeRef(T->getElementType()); - if (T->isReadOnly()) - Code = TYPE_READ_PIPE; - else - Code = TYPE_WRITE_PIPE; + Record.push_back(T->isReadOnly()); + Code = TYPE_PIPE; } namespace {