summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/ASTContext.h4
-rw-r--r--clang/include/clang/AST/RecursiveASTVisitor.h4
-rw-r--r--clang/include/clang/AST/Type.h42
-rw-r--r--clang/include/clang/AST/TypeLoc.h19
-rw-r--r--clang/include/clang/AST/TypeNodes.def1
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--clang/include/clang/Basic/Specifiers.h5
-rw-r--r--clang/include/clang/Basic/TokenKinds.def2
-rw-r--r--clang/include/clang/Sema/DeclSpec.h32
-rw-r--r--clang/include/clang/Sema/Sema.h2
-rw-r--r--clang/include/clang/Serialization/ASTBitCodes.h4
-rw-r--r--clang/lib/AST/ASTContext.cpp53
-rw-r--r--clang/lib/AST/ASTImporter.cpp8
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp8
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp9
-rw-r--r--clang/lib/AST/Type.cpp5
-rw-r--r--clang/lib/AST/TypePrinter.cpp10
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp8
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.h1
-rw-r--r--clang/lib/CodeGen/CGOpenCLRuntime.cpp11
-rw-r--r--clang/lib/CodeGen/CGOpenCLRuntime.h5
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp29
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.cpp4
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp6
-rw-r--r--clang/lib/Parse/ParseDecl.cpp36
-rw-r--r--clang/lib/Sema/DeclSpec.cpp17
-rw-r--r--clang/lib/Sema/SemaDecl.cpp17
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp1
-rw-r--r--clang/lib/Sema/SemaExpr.cpp1
-rw-r--r--clang/lib/Sema/SemaLookup.cpp3
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp4
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplateVariadic.cpp1
-rw-r--r--clang/lib/Sema/SemaType.cpp58
-rw-r--r--clang/lib/Sema/TreeTransform.h29
-rw-r--r--clang/lib/Serialization/ASTReader.cpp14
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp9
-rw-r--r--clang/test/CodeGenOpenCL/pipe_types.cl27
-rw-r--r--clang/test/PCH/ocl_types.cl18
-rw-r--r--clang/test/PCH/ocl_types.h11
-rw-r--r--clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl8
-rw-r--r--clang/test/SemaOpenCL/pipes-1.2-negative.cl3
-rw-r--r--clang/tools/libclang/CIndex.cpp4
43 files changed, 525 insertions, 14 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index b66009e909a..9140eabe83b 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -131,6 +131,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<AutoType> AutoTypes;
mutable llvm::FoldingSet<AtomicType> AtomicTypes;
llvm::FoldingSet<AttributedType> AttributedTypes;
+ mutable llvm::FoldingSet<PipeType> PipeTypes;
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
@@ -1079,6 +1080,9 @@ public:
/// blocks.
QualType getBlockDescriptorType() const;
+ /// \brief Return pipe type for the specified type.
+ QualType getPipeType(QualType T) const;
+
/// Gets the struct used to keep track of the extended descriptor for
/// pointer to blocks.
QualType getBlockDescriptorExtendedType() const;
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index e6f758364a8..0c25a45c1ce 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -978,6 +978,8 @@ DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); })
+DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); })
+
#undef DEF_TRAVERSE_TYPE
// ----------------- TypeLoc traversal -----------------
@@ -1206,6 +1208,8 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
+DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
+
#undef DEF_TRAVERSE_TYPELOC
// ----------------- Decl traversal -----------------
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 0c08130da62..d63b2c43d55 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1721,6 +1721,7 @@ public:
bool isNDRangeT() const; // OpenCL ndrange_t
bool isReserveIDT() const; // OpenCL reserve_id_t
+ bool isPipeType() const; // OpenCL pipe type
bool isOpenCLSpecificType() const; // Any OpenCL specific type
/// Determines if this type, which must satisfy
@@ -5015,6 +5016,41 @@ class AtomicType : public Type, public llvm::FoldingSetNode {
}
};
+/// PipeType - OpenCL20.
+class PipeType : public Type, public llvm::FoldingSetNode {
+ QualType ElementType;
+
+ PipeType(QualType elemType, QualType CanonicalPtr) :
+ Type(Pipe, CanonicalPtr, elemType->isDependentType(),
+ elemType->isInstantiationDependentType(),
+ elemType->isVariablyModifiedType(),
+ elemType->containsUnexpandedParameterPack()),
+ ElementType(elemType) {}
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+
+ QualType getElementType() const { return ElementType; }
+
+ bool isSugared() const { return false; }
+
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getElementType());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
+ ID.AddPointer(T.getAsOpaquePtr());
+ }
+
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Pipe;
+ }
+
+};
+
/// A qualifier set is used to build a set of qualifiers.
class QualifierCollector : public Qualifiers {
public:
@@ -5461,9 +5497,13 @@ inline bool Type::isImageType() const {
isImage1dBufferT();
}
+inline bool Type::isPipeType() const {
+ return isa<PipeType>(CanonicalType);
+}
+
inline bool Type::isOpenCLSpecificType() const {
return isSamplerT() || isEventT() || isImageType() || isClkEventT() ||
- isQueueT() || isNDRangeT() || isReserveIDT();
+ isQueueT() || isNDRangeT() || isReserveIDT() || isPipeType();
}
inline bool Type::isTemplateTypeParmType() const {
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 26feda5d766..29035a41776 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -2033,7 +2033,26 @@ public:
}
};
+struct PipeTypeLocInfo {
+ SourceLocation KWLoc;
+};
+
+class PipeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, PipeTypeLoc, PipeType,
+ PipeTypeLocInfo> {
+public:
+ TypeLoc getValueLoc() const { return this->getInnerTypeLoc(); }
+
+ SourceRange getLocalSourceRange() const { return SourceRange(getKWLoc()); }
+
+ SourceLocation getKWLoc() const { return this->getLocalData()->KWLoc; }
+ void setKWLoc(SourceLocation Loc) { this->getLocalData()->KWLoc = Loc; }
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setKWLoc(Loc);
+ }
+
+ QualType getInnerType() const { return this->getTypePtr()->getElementType(); }
+};
}
#endif
diff --git a/clang/include/clang/AST/TypeNodes.def b/clang/include/clang/AST/TypeNodes.def
index 2549f0bf50c..8caf1024142 100644
--- a/clang/include/clang/AST/TypeNodes.def
+++ b/clang/include/clang/AST/TypeNodes.def
@@ -104,6 +104,7 @@ NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type)
TYPE(ObjCObject, Type)
TYPE(ObjCInterface, ObjCObjectType)
TYPE(ObjCObjectPointer, Type)
+TYPE(Pipe, Type)
TYPE(Atomic, Type)
#ifdef LAST_TYPE
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index db8169531e2..6ba482c78e4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7642,6 +7642,10 @@ def err_wrong_sampler_addressspace: Error<
"sampler type cannot be used with the __local and __global address space qualifiers">;
def err_opencl_global_invalid_addr_space : Error<
"program scope variable must reside in %0 address space">;
+def err_missing_actual_pipe_type : Error<
+ "missing actual type specifier for pipe">;
+def err_reference_pipe_type : Error <
+ "pipes packet types cannot be of reference type">;
def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">;
def err_opencl_kernel_attr :
Error<"attribute %0 can only be applied to a kernel function">;
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 1d59d64d6bc..e284171f777 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -36,6 +36,11 @@ namespace clang {
TSS_unsigned
};
+ enum TypeSpecifiersPipe {
+ TSP_unspecified,
+ TSP_pipe
+ };
+
/// \brief Specifies the kind of type.
enum TypeSpecifierType {
TST_unspecified,
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 9252d9947a9..65a77accf92 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -519,6 +519,8 @@ KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC|KEYZVECTOR)
// OpenMP Type Traits
KEYWORD(__builtin_omp_required_simd_align, KEYALL)
+KEYWORD(pipe , KEYOPENCL)
+
// Borland Extensions.
KEYWORD(__pascal , KEYALL)
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index e9fdb707f27..064d37b2a02 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -337,6 +337,7 @@ private:
unsigned TypeAltiVecPixel : 1;
unsigned TypeAltiVecBool : 1;
unsigned TypeSpecOwned : 1;
+ unsigned TypeSpecPipe : 1;
// type-qualifiers
unsigned TypeQualifiers : 4; // Bitwise OR of TQ.
@@ -385,6 +386,7 @@ private:
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
SourceLocation FS_forceinlineLoc;
SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConceptLoc;
+ SourceLocation TQ_pipeLoc;
WrittenBuiltinSpecs writtenBS;
void SaveWrittenBuiltinSpecs();
@@ -420,6 +422,7 @@ public:
TypeAltiVecPixel(false),
TypeAltiVecBool(false),
TypeSpecOwned(false),
+ TypeSpecPipe(false),
TypeQualifiers(TQ_unspecified),
FS_inline_specified(false),
FS_forceinline_specified(false),
@@ -473,6 +476,7 @@ public:
bool isTypeAltiVecBool() const { return TypeAltiVecBool; }
bool isTypeSpecOwned() const { return TypeSpecOwned; }
bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }
+ bool isTypeSpecPipe() const { return TypeSpecPipe; }
ParsedType getRepAsType() const {
assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
@@ -532,6 +536,7 @@ public:
SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; }
+ SourceLocation getPipeLoc() const { return TQ_pipeLoc; }
/// \brief Clear out all of the type qualifiers.
void ClearTypeQualifiers() {
@@ -540,6 +545,7 @@ public:
TQ_restrictLoc = SourceLocation();
TQ_volatileLoc = SourceLocation();
TQ_atomicLoc = SourceLocation();
+ TQ_pipeLoc = SourceLocation();
}
// function-specifier
@@ -643,6 +649,9 @@ public:
bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID,
const PrintingPolicy &Policy);
+ bool SetTypePipe(bool isPipe, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
bool SetTypeSpecError();
void UpdateDeclRep(Decl *Rep) {
assert(isDeclRep((TST) TypeSpecType));
@@ -1081,7 +1090,7 @@ typedef SmallVector<Token, 4> CachedTokens;
/// This is intended to be a small value object.
struct DeclaratorChunk {
enum {
- Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren
+ Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren, Pipe
} Kind;
/// Loc - The place where this type was defined.
@@ -1409,6 +1418,13 @@ struct DeclaratorChunk {
}
};
+ struct PipeTypeInfo : TypeInfoCommon {
+ /// The access writes.
+ unsigned AccessWrites : 3;
+
+ void destroy() {}
+ };
+
union {
TypeInfoCommon Common;
PointerTypeInfo Ptr;
@@ -1417,6 +1433,7 @@ struct DeclaratorChunk {
FunctionTypeInfo Fun;
BlockPointerTypeInfo Cls;
MemberPointerTypeInfo Mem;
+ PipeTypeInfo PipeInfo;
};
void destroy() {
@@ -1428,6 +1445,7 @@ struct DeclaratorChunk {
case DeclaratorChunk::Array: return Arr.destroy();
case DeclaratorChunk::MemberPointer: return Mem.destroy();
case DeclaratorChunk::Paren: return;
+ case DeclaratorChunk::Pipe: return PipeInfo.destroy();
}
}
@@ -1526,6 +1544,17 @@ struct DeclaratorChunk {
return I;
}
+ /// \brief Return a DeclaratorChunk for a block.
+ static DeclaratorChunk getPipe(unsigned TypeQuals,
+ SourceLocation Loc) {
+ DeclaratorChunk I;
+ I.Kind = Pipe;
+ I.Loc = Loc;
+ I.Cls.TypeQuals = TypeQuals;
+ I.Cls.AttrList = 0;
+ return I;
+ }
+
static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
unsigned TypeQuals,
SourceLocation Loc) {
@@ -2026,6 +2055,7 @@ public:
case DeclaratorChunk::Array:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
return false;
}
llvm_unreachable("Invalid type chunk");
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 279afbe740e..c82684ee458 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1269,6 +1269,8 @@ public:
SourceLocation Loc, DeclarationName Entity);
QualType BuildParenType(QualType T);
QualType BuildAtomicType(QualType T, SourceLocation Loc);
+ QualType BuildPipeType(QualType T,
+ SourceLocation Loc);
TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 16bda6ea03c..0dfb8cf3714 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -907,7 +907,9 @@ namespace clang {
/// \brief A DecayedType record.
TYPE_DECAYED = 41,
/// \brief An AdjustedType record.
- TYPE_ADJUSTED = 42
+ TYPE_ADJUSTED = 42,
+ /// \brief A PipeType record.
+ TYPE_PIPE = 43
};
/// \brief The type IDs for special types constructed by semantic
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index d4abbe47caf..64386967b22 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1836,6 +1836,13 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Align = static_cast<unsigned>(Width);
}
}
+ break;
+
+ case Type::Pipe: {
+ TypeInfo Info = getTypeInfo(cast<PipeType>(T)->getElementType());
+ Width = Info.Width;
+ Align = Info.Align;
+ }
}
@@ -2663,6 +2670,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
case Type::FunctionProto:
case Type::BlockPointer:
case Type::MemberPointer:
+ case Type::Pipe:
return type;
// These types can be variably-modified. All these modifications
@@ -3117,6 +3125,32 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
return QualType(FTP, 0);
}
+/// Return pipe type for the specified type.
+QualType ASTContext::getPipeType(QualType T) const {
+ llvm::FoldingSetNodeID ID;
+ PipeType::Profile(ID, T);
+
+ void *InsertPos = 0;
+ 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 = getPipeType(getCanonicalType(T));
+
+ // Get the new insert position for the node we care about.
+ PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!NewIP && "Shouldn't be in the map!");
+ (void)NewIP;
+ }
+ PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical);
+ Types.push_back(New);
+ PipeTypes.InsertNode(New, InsertPos);
+ return QualType(New, 0);
+}
+
#ifndef NDEBUG
static bool NeedsInjectedClassNameType(const RecordDecl *D) {
if (!isa<CXXRecordDecl>(D)) return false;
@@ -5857,6 +5891,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
case Type::Auto:
return;
+ case Type::Pipe:
#define ABSTRACT_TYPE(KIND, BASE)
#define TYPE(KIND, BASE)
#define DEPENDENT_TYPE(KIND, BASE) \
@@ -7792,6 +7827,24 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return QualType();
}
+ case Type::Pipe:
+ {
+ // Merge two pointer types, while trying to preserve typedef info
+ QualType LHSValue = LHS->getAs<PipeType>()->getElementType();
+ QualType RHSValue = RHS->getAs<PipeType>()->getElementType();
+ if (Unqualified) {
+ LHSValue = LHSValue.getUnqualifiedType();
+ RHSValue = RHSValue.getUnqualifiedType();
+ }
+ QualType ResultType = mergeTypes(LHSValue, RHSValue, false,
+ Unqualified);
+ if (ResultType.isNull()) return QualType();
+ if (getCanonicalType(LHSValue) == getCanonicalType(ResultType))
+ return LHS;
+ if (getCanonicalType(RHSValue) == getCanonicalType(ResultType))
+ return RHS;
+ return getPipeType(ResultType);
+ }
}
llvm_unreachable("Invalid Type::Class!");
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 359db1ba81b..916f1081798 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -878,6 +878,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
}
+ case Type::Pipe: {
+ if (!IsStructurallyEquivalent(Context,
+ cast<PipeType>(T1)->getElementType(),
+ cast<PipeType>(T2)->getElementType()))
+ return false;
+ break;
+ }
+
} // end switch
return true;
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 8018188a6b2..3f6b682f238 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -1509,6 +1509,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
case Type::Atomic:
+ case Type::Pipe:
llvm_unreachable("type is illegal as a nested name specifier");
case Type::SubstTemplateTypeParmPack:
@@ -2682,6 +2683,13 @@ void CXXNameMangler::mangleType(const AtomicType *T) {
mangleType(T->getValueType());
}
+void CXXNameMangler::mangleType(const PipeType *T) {
+ // Pipe type mangling rules are described in SPIR 2.0 specification
+ // A.1 Data types and A.3 Summary of changes
+ // <type> ::= 8ocl_pipe
+ Out << "8ocl_pipe";
+}
+
void CXXNameMangler::mangleIntegerLiteral(QualType T,
const llvm::APSInt &Value) {
// <expr-primary> ::= L <type> <value number> E # integer literal
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index d45232b6deb..4a45f9e4051 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -2428,6 +2428,15 @@ void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"});
}
+void MicrosoftCXXNameMangler::mangleType(const PipeType *T, Qualifiers,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this OpenCL pipe type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D,
raw_ostream &Out) {
assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index a15569ad02b..b467dac66b5 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -3361,6 +3361,8 @@ static CachedProperties computeCachedProperties(const Type *T) {
return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType());
case Type::Atomic:
return Cache::get(cast<AtomicType>(T)->getValueType());
+ case Type::Pipe:
+ return Cache::get(cast<PipeType>(T)->getElementType());
}
llvm_unreachable("unhandled type class");
@@ -3443,6 +3445,8 @@ static LinkageInfo computeLinkageInfo(const Type *T) {
return computeLinkageInfo(cast<ObjCObjectPointerType>(T)->getPointeeType());
case Type::Atomic:
return computeLinkageInfo(cast<AtomicType>(T)->getValueType());
+ case Type::Pipe:
+ return computeLinkageInfo(cast<PipeType>(T)->getElementType());
}
llvm_unreachable("unhandled type class");
@@ -3601,6 +3605,7 @@ bool Type::canHaveNullability() const {
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::Atomic:
+ case Type::Pipe:
return false;
}
llvm_unreachable("bad type kind!");
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 4617e1d3803..b202523bdaf 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -193,6 +193,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::Atomic:
+ case Type::Pipe:
CanPrefixQualifiers = true;
break;
@@ -859,6 +860,15 @@ void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
}
void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { }
+void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
+ IncludeStrongLifetimeRAII Strong(Policy);
+
+ OS << "pipe";
+ spaceBeforePlaceHolder(OS);
+}
+
+void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {
+}
/// Appends the given scope to the end of a string.
void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
if (DC->isTranslationUnit()) return;
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 78e3978e0ff..5df85194878 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2025,6 +2025,11 @@ llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) {
return getOrCreateType(Ty->getValueType(), U);
}
+llvm::DIType* CGDebugInfo::CreateType(const PipeType *Ty,
+ llvm::DIFile *U) {
+ return getOrCreateType(Ty->getElementType(), U);
+}
+
llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
const EnumDecl *ED = Ty->getDecl();
@@ -2284,6 +2289,9 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::Atomic:
return CreateType(cast<AtomicType>(Ty), Unit);
+ case Type::Pipe:
+ return CreateType(cast<PipeType>(Ty), Unit);
+
case Type::TemplateSpecialization:
return CreateType(cast<TemplateSpecializationType>(Ty), Unit);
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 57d5c808f29..a68dd33fa5f 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -168,6 +168,7 @@ class CGDebugInfo {
llvm::DIType *CreateType(const RValueReferenceType *Ty, llvm::DIFile *Unit);
llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F);
+ llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F);
/// Get enumeration type.
llvm::DIType *CreateEnumType(const EnumType *Ty);
llvm::DIType *CreateTypeDefinition(const EnumType *Ty);
diff --git a/clang/lib/CodeGen/CGOpenCLRuntime.cpp b/clang/lib/CodeGen/CGOpenCLRuntime.cpp
index 8af39ceecdf..686678962d3 100644
--- a/clang/lib/CodeGen/CGOpenCLRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenCLRuntime.cpp
@@ -99,3 +99,14 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
llvm::StructType::create(Ctx, "opencl.reserve_id_t"), 0);
}
}
+
+llvm::Type *CGOpenCLRuntime::getPipeType() {
+ if (!PipeTy){
+ uint32_t PipeAddrSpc =
+ CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
+ PipeTy = llvm::PointerType::get(llvm::StructType::create(
+ CGM.getLLVMContext(), "opencl.pipe_t"), PipeAddrSpc);
+ }
+
+ return PipeTy;
+}
diff --git a/clang/lib/CodeGen/CGOpenCLRuntime.h b/clang/lib/CodeGen/CGOpenCLRuntime.h
index 0c50b92914b..f1a7a310644 100644
--- a/clang/lib/CodeGen/CGOpenCLRuntime.h
+++ b/clang/lib/CodeGen/CGOpenCLRuntime.h
@@ -32,9 +32,10 @@ class CodeGenModule;
class CGOpenCLRuntime {
protected:
CodeGenModule &CGM;
+ llvm::Type *PipeTy;
public:
- CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
+ CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr) {}
virtual ~CGOpenCLRuntime();
/// Emit the IR required for a work-group-local variable declaration, and add
@@ -44,6 +45,8 @@ public:
const VarDecl &D);
virtual llvm::Type *convertOpenCLSpecificType(const Type *T);
+
+ virtual llvm::Type *getPipeType();
};
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 048a04328fc..1047120faee 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -195,6 +195,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) {
case Type::FunctionNoProto:
case Type::Enum:
case Type::ObjCObjectPointer:
+ case Type::Pipe:
return TEK_Scalar;
// Complexes.
@@ -511,7 +512,8 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
typeQuals += typeQuals.empty() ? "volatile" : " volatile";
} else {
uint32_t AddrSpc = 0;
- if (ty->isImageType())
+ bool isPipe = ty->isPipeType();
+ if (ty->isImageType() || isPipe)
AddrSpc =
CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
@@ -519,7 +521,11 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
llvm::ConstantAsMetadata::get(Builder.getInt32(AddrSpc)));
// Get argument type name.
- std::string typeName = ty.getUnqualifiedType().getAsString(Policy);
+ std::string typeName;
+ if (isPipe)
+ typeName = cast<PipeType>(ty)->getElementType().getAsString(Policy);
+ else
+ typeName = ty.getUnqualifiedType().getAsString(Policy);
// Turn "unsigned type" to "utype"
std::string::size_type pos = typeName.find("unsigned");
@@ -528,7 +534,12 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
argTypeNames.push_back(llvm::MDString::get(Context, typeName));
- std::string baseTypeName =
+ std::string baseTypeName;
+ if (isPipe)
+ baseTypeName =
+ cast<PipeType>(ty)->getElementType().getCanonicalType().getAsString(Policy);
+ else
+ baseTypeName =
ty.getUnqualifiedType().getCanonicalType().getAsString(Policy);
// Turn "unsigned type" to "utype"
@@ -543,12 +554,16 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
typeQuals = "const";
if (ty.isVolatileQualified())
typeQuals += typeQuals.empty() ? "volatile" : " volatile";
+ if (isPipe)
+ typeQuals = "pipe";
}
argTypeQuals.push_back(llvm::MDString::get(Context, typeQuals));
- // Get image access qualifier:
- if (ty->isImageType()) {
+ // Get image and pipe access qualifier:
+ // FIXME: now image and pipe share the same access qualifier maybe we can
+ // refine it to OpenCL access qualifier and also handle write_read
+ if (ty->isImageType()|| ty->isPipeType()) {
const OpenCLImageAccessAttr *A = parm->getAttr<OpenCLImageAccessAttr>();
if (A && A->isWriteOnly())
accessQuals.push_back(llvm::MDString::get(Context, "write_only"));
@@ -1727,6 +1742,10 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
case Type::Atomic:
type = cast<AtomicType>(ty)->getValueType();
break;
+
+ case Type::Pipe:
+ type = cast<PipeType>(ty)->getElementType();
+ break;
}
} while (type->isVariablyModifiedType());
}
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index fcda0532055..09d9bf17b3b 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -628,6 +628,10 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
}
break;
}
+ case Type::Pipe: {
+ ResultType = CGM.getOpenCLRuntime().getPipeType();
+ break;
+ }
}
assert(ResultType && "Didn't convert a type?");
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 0c4008f8ee7..e02c8dc3a86 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2715,6 +2715,9 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
case Type::Auto:
llvm_unreachable("Undeduced auto type shouldn't get here");
+ case Type::Pipe:
+ llvm_unreachable("Pipe types shouldn't get here");
+
case Type::Builtin:
// GCC treats vector and complex types as fundamental types.
case Type::Vector:
@@ -2939,6 +2942,9 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
case Type::Auto:
llvm_unreachable("Undeduced auto type shouldn't get here");
+ case Type::Pipe:
+ llvm_unreachable("Pipe type shouldn't get here");
+
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index e69bb2745c4..c64b97d01b9 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3326,6 +3326,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::kw___bool:
isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);
break;
+ case tok::kw_pipe:
+ if (!getLangOpts().OpenCL || (getLangOpts().OpenCLVersion < 200)) {
+ // OpenCL 2.0 defined this keyword. OpenCL 1.2 and earlier should
+ // support the "pipe" word as identifier.
+ Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
+ goto DoneWithDeclSpec;
+ }
+ isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy);
+ break;
case tok::kw___unknown_anytype:
isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc,
PrevSpec, DiagID, Policy);
@@ -4401,6 +4410,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
switch (Tok.getKind()) {
default: return false;
+ case tok::kw_pipe:
+ return getLangOpts().OpenCL && (getLangOpts().OpenCLVersion >= 200);
+
case tok::identifier: // foo::bar
// Unfortunate hack to support "Class.factoryMethod" notation.
if (getLangOpts().ObjC1 && NextToken().is(tok::period))
@@ -4847,6 +4859,9 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
if (Kind == tok::star || Kind == tok::caret)
return true;
+ if ((Kind == tok::kw_pipe) && Lang.OpenCL && (Lang.OpenCLVersion >= 200))
+ return true;
+
if (!Lang.CPlusPlus)
return false;
@@ -4865,6 +4880,17 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
return false;
}
+// Indicates whether the given declarator is a pipe declarator.
+static bool isPipeDeclerator(const Declarator &D) {
+ const unsigned NumTypes = D.getNumTypeObjects();
+
+ for (unsigned Idx = 0; Idx != NumTypes; ++Idx)
+ if (DeclaratorChunk::Pipe == D.getTypeObject(Idx).Kind)
+ return true;
+
+ return false;
+}
+
/// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator
/// is parsed by the function passed to it. Pass null, and the direct-declarator
/// isn't parsed at all, making this function effectively parse the C++
@@ -4941,6 +4967,15 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
}
tok::TokenKind Kind = Tok.getKind();
+
+ if (D.getDeclSpec().isTypeSpecPipe() && !isPipeDeclerator(D)) {
+ DeclSpec &DS = D.getMutableDeclSpec();
+
+ D.AddTypeInfo(
+ DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()),
+ DS.getAttributes(), SourceLocation());
+ }
+
// Not a pointer, C++ reference, or block.
if (!isPtrOperatorToken(Kind, getLangOpts(), D.getContext())) {
if (DirectDeclParser)
@@ -6092,6 +6127,7 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {
case DeclaratorChunk::Reference:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
NeedParens = true;
break;
case DeclaratorChunk::Array:
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index d664d870400..6f6c4ca5848 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -270,6 +270,7 @@ bool Declarator::isDeclarationOfFunction() const {
case DeclaratorChunk::Array:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
return false;
}
llvm_unreachable("Invalid type chunk");
@@ -713,6 +714,22 @@ bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
return false;
}
+bool DeclSpec::SetTypePipe(bool isPipe, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy) {
+
+ if (TypeSpecType != TST_unspecified) {
+ PrevSpec = DeclSpec::getSpecifierName((TST)TypeSpecType, Policy);
+ DiagID = diag::err_invalid_decl_spec_combination;
+ return true;
+ }
+
+ if (isPipe) {
+ TypeSpecPipe = TSP_pipe;
+ }
+ return false;
+}
+
bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID,
const PrintingPolicy &Policy) {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0864984c063..66c0e059d4b 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8256,6 +8256,23 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
for (auto Param : NewFD->params())
checkIsValidOpenCLKernelParameter(*this, D, Param, ValidTypes);
}
+ for (FunctionDecl::param_iterator PI = NewFD->param_begin(),
+ PE = NewFD->param_end(); PI != PE; ++PI) {
+ ParmVarDecl *Param = *PI;
+ QualType PT = Param->getType();
+
+ // OpenCL 2.0 pipe restrictions forbids pipe packet types to be non-value
+ // types.
+ if (getLangOpts().OpenCLVersion >= 200) {
+ if(const PipeType *PipeTy = PT->getAs<PipeType>()) {
+ QualType ElemTy = PipeTy->getElementType();
+ if (ElemTy->isReferenceType() || ElemTy->isPointerType()) {
+ Diag(Param->getTypeSpecStartLoc(), diag::err_reference_pipe_type );
+ D.setInvalidType();
+ }
+ }
+ }
+ }
MarkUnusedFileScopedDecl(NewFD);
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 02091a7bd53..4b03baf32ac 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7000,6 +7000,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
extendLeft(Before, Chunk.getSourceRange());
break;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 76d0ca56c0c..361b0a1b72d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13140,6 +13140,7 @@ bool Sema::tryCaptureVariable(
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
+ case Type::Pipe:
llvm_unreachable("type class is never variably-modified!");
case Type::Adjusted:
QTy = cast<AdjustedType>(Ty)->getOriginalType();
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 481ae6cd55b..1d7b15c35d1 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2616,6 +2616,9 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
case Type::Atomic:
T = cast<AtomicType>(T)->getValueType().getTypePtr();
continue;
+ case Type::Pipe:
+ T = cast<PipeType>(T)->getElementType().getTypePtr();
+ continue;
}
if (Queue.empty())
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 9775e4d940a..57156078c80 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4184,6 +4184,10 @@ bool UnnamedLocalNoLinkageFinder::VisitAtomicType(const AtomicType* T) {
return Visit(T->getValueType());
}
+bool UnnamedLocalNoLinkageFinder::VisitPipeType(const PipeType* T) {
+ return false;
+}
+
bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
if (Tag->getDeclContext()->isFunctionOrMethod()) {
S.Diag(SR.getBegin(),
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index cd54920b08c..71faafc6bc1 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -1652,6 +1652,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
case Type::Auto:
case Type::DependentTemplateSpecialization:
case Type::PackExpansion:
+ case Type::Pipe:
// No template argument deduction for these types
return Sema::TDK_Success;
}
@@ -4964,6 +4965,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
case Type::ObjCObject:
case Type::ObjCObjectPointer:
case Type::UnresolvedUsing:
+ case Type::Pipe:
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 61052f06c83..cb67d71f9e5 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -750,6 +750,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case DeclaratorChunk::Pointer:
case DeclaratorChunk::Reference:
case DeclaratorChunk::Paren:
+ case DeclaratorChunk::Pipe:
case DeclaratorChunk::BlockPointer:
// These declarator chunks cannot contain any parameter packs.
break;
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index c70568c23b5..f6ad132cde8 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -335,6 +335,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
case DeclaratorChunk::Array:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
return result;
// If we do find a function declarator, scan inwards from that,
@@ -347,6 +348,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
case DeclaratorChunk::Array:
case DeclaratorChunk::Function:
case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Pipe:
continue;
case DeclaratorChunk::MemberPointer:
@@ -427,6 +429,7 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
// Don't walk through these.
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
goto error;
}
}
@@ -459,6 +462,7 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Paren:
case DeclaratorChunk::Array:
+ case DeclaratorChunk::Pipe:
continue;
case DeclaratorChunk::Function:
@@ -520,6 +524,7 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state,
case DeclaratorChunk::Array:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
continue;
}
}
@@ -1272,6 +1277,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// value being declared, poison it as invalid so we don't get chains of
// errors.
declarator.setInvalidType(true);
+ } else if (S.getLangOpts().OpenCLVersion >= 200 && DS.isTypeSpecPipe()){
+ S.Diag(DeclLoc, diag::err_missing_actual_pipe_type)
+ << DS.getSourceRange();
+ declarator.setInvalidType(true);
} else {
S.Diag(DeclLoc, diag::ext_missing_type_specifier)
<< DS.getSourceRange();
@@ -1564,7 +1573,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// Apply any type attributes from the decl spec. This may cause the
// list of type attributes to be temporarily saved while the type
// attributes are pushed around.
- processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList());
+ // pipe attributes will be handled later ( at GetFullTypeForDeclarator )
+ if (!DS.isTypeSpecPipe())
+ processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList());
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@@ -1924,6 +1935,21 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
return Context.getRValueReferenceType(T);
}
+/// \brief Build a 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::BuildPipeType(QualType T, SourceLocation Loc) {
+ assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
+
+ // Build the pipe type.
+ return Context.getPipeType(T);
+}
+
/// Check whether the specified array size makes the array type a VLA. If so,
/// return true, if not, return the size of the array in SizeVal.
static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
@@ -2393,6 +2419,7 @@ static void inferARCWriteback(TypeProcessingState &state,
case DeclaratorChunk::Array: // suppress if written (id[])?
case DeclaratorChunk::Function:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
return;
}
}
@@ -2532,6 +2559,7 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
case DeclaratorChunk::Reference:
case DeclaratorChunk::Array:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
// FIXME: We can't currently provide an accurate source location and a
// fix-it hint for these.
unsigned AtomicQual = RetTy->isAtomicType() ? DeclSpec::TQ_atomic : 0;
@@ -3057,6 +3085,7 @@ static PointerDeclaratorKind classifyPointerDeclarator(Sema &S,
switch (chunk.Kind) {
case DeclaratorChunk::Array:
case DeclaratorChunk::Function:
+ case DeclaratorChunk::Pipe:
break;
case DeclaratorChunk::BlockPointer:
@@ -3305,6 +3334,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorChunk::Array:
DiagKind = 2;
break;
+ case DeclaratorChunk::Pipe:
+ break;
}
S.Diag(DeclChunk.Loc, DiagId) << DiagKind;
@@ -3370,6 +3401,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
switch (chunk.Kind) {
case DeclaratorChunk::Array:
case DeclaratorChunk::Function:
+ case DeclaratorChunk::Pipe:
break;
case DeclaratorChunk::BlockPointer:
@@ -3689,6 +3721,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
case DeclaratorChunk::Function:
case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::Pipe:
// These are invalid anyway, so just ignore.
break;
}
@@ -4038,7 +4071,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
}
- case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::MemberPointer: {
// The scope spec must refer to a class, or be dependent.
CXXScopeSpec &SS = DeclType.Mem.Scope();
QualType ClsType;
@@ -4098,6 +4131,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
}
+ case DeclaratorChunk::Pipe: {
+ T = S.BuildPipeType(T, DeclType.Loc );
+ break;
+ }
+ }
+
if (T.isNull()) {
D.setInvalidType(true);
T = Context.IntTy;
@@ -4392,6 +4431,7 @@ static void transferARCOwnership(TypeProcessingState &state,
case DeclaratorChunk::Function:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
return;
}
}
@@ -4682,6 +4722,14 @@ namespace {
}
}
+ void VisitPipeTypeLoc(PipeTypeLoc TL) {
+ TL.setKWLoc(DS.getTypeSpecTypeLoc());
+
+ TypeSourceInfo *TInfo = 0;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
+ }
+
void VisitTypeLoc(TypeLoc TL) {
// FIXME: add other typespec types and change this to an assert.
TL.initialize(Context, DS.getTypeSpecTypeLoc());
@@ -4802,6 +4850,10 @@ namespace {
TL.setLParenLoc(Chunk.Loc);
TL.setRParenLoc(Chunk.EndLoc);
}
+ void VisitPipeTypeLoc(PipeTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Pipe);
+ TL.setKWLoc(Chunk.Loc);
+ }
void VisitTypeLoc(TypeLoc TL) {
llvm_unreachable("unsupported TypeLoc kind in declarator!");
@@ -4815,6 +4867,7 @@ static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) {
case DeclaratorChunk::Function:
case DeclaratorChunk::Array:
case DeclaratorChunk::Paren:
+ case DeclaratorChunk::Pipe:
llvm_unreachable("cannot be _Atomic qualified");
case DeclaratorChunk::Pointer:
@@ -5738,6 +5791,7 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
// Don't walk through these.
case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Pipe:
return false;
}
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index e97a2626387..b8f977c16bb 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1046,6 +1046,9 @@ public:
/// Subclasses may override this routine to provide different behavior.
QualType RebuildAtomicType(QualType ValueType, SourceLocation KWLoc);
+ /// \brief Build a new pipe type given its value type.
+ QualType RebuildPipeType(QualType ValueType, SourceLocation KWLoc);
+
/// \brief Build a new template name given a nested name specifier, a flag
/// indicating whether the "template" keyword was provided, and the template
/// that the template name refers to.
@@ -5324,6 +5327,26 @@ QualType TreeTransform<Derived>::TransformAtomicType(TypeLocBuilder &TLB,
return Result;
}
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformPipeType(TypeLocBuilder &TLB,
+ PipeTypeLoc TL) {
+ QualType ValueType = getDerived().TransformType(TLB, TL.getValueLoc());
+ if (ValueType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() || ValueType != TL.getValueLoc().getType()) {
+ Result = getDerived().RebuildPipeType(ValueType, TL.getKWLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ PipeTypeLoc NewTL = TLB.push<PipeTypeLoc>(Result);
+ NewTL.setKWLoc(TL.getKWLoc());
+
+ return Result;
+}
+
/// \brief Simple iterator that traverses the template arguments in a
/// container that provides a \c getArgLoc() member function.
///
@@ -11350,6 +11373,12 @@ QualType TreeTransform<Derived>::RebuildAtomicType(QualType ValueType,
}
template<typename Derived>
+QualType TreeTransform<Derived>::RebuildPipeType(QualType ValueType,
+ SourceLocation KWLoc) {
+ return SemaRef.BuildPipeType(ValueType, KWLoc);
+}
+
+template<typename Derived>
TemplateName
TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
bool TemplateKW,
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index a279475eeaf..833ff57e4d0 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -5640,6 +5640,17 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
QualType ValueType = readType(*Loc.F, Record, Idx);
return Context.getAtomicType(ValueType);
}
+
+ case TYPE_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.getPipeType(ElementType);
+ }
}
llvm_unreachable("Invalid TypeCode!");
}
@@ -5911,6 +5922,9 @@ void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
TL.setLParenLoc(ReadSourceLocation(Record, Idx));
TL.setRParenLoc(ReadSourceLocation(Record, Idx));
}
+void TypeLocReader::VisitPipeTypeLoc(PipeTypeLoc TL) {
+ TL.setKWLoc(ReadSourceLocation(Record, Idx));
+}
TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F,
const RecordData &Record,
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index e36e9185170..ec04cd6c1fa 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -446,6 +446,12 @@ ASTTypeWriter::VisitAtomicType(const AtomicType *T) {
Code = TYPE_ATOMIC;
}
+void
+ASTTypeWriter::VisitPipeType(const PipeType *T) {
+ Writer.AddTypeRef(T->getElementType(), Record);
+ Code = TYPE_PIPE;
+}
+
namespace {
class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
@@ -672,6 +678,9 @@ void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
Writer.AddSourceLocation(TL.getLParenLoc(), Record);
Writer.AddSourceLocation(TL.getRParenLoc(), Record);
}
+void TypeLocWriter::VisitPipeTypeLoc(PipeTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getKWLoc(), Record);
+}
void ASTWriter::WriteTypeAbbrevs() {
using namespace llvm;
diff --git a/clang/test/CodeGenOpenCL/pipe_types.cl b/clang/test/CodeGenOpenCL/pipe_types.cl
new file mode 100644
index 00000000000..547071cf85a
--- /dev/null
+++ b/clang/test/CodeGenOpenCL/pipe_types.cl
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -emit-llvm -O0 -cl-std=CL2.0 -o - %s | FileCheck %s
+
+// CHECK: %opencl.pipe_t = type opaque
+typedef unsigned char __attribute__((ext_vector_type(3))) uchar3;
+typedef int __attribute__((ext_vector_type(4))) int4;
+
+void test1(read_only pipe int p) {
+// CHECK: define void @test1(%opencl.pipe_t* %p)
+ reserve_id_t rid;
+// CHECK: %rid = alloca %opencl.reserve_id_t
+}
+
+void test2(write_only pipe float p) {
+// CHECK: define void @test2(%opencl.pipe_t* %p)
+}
+
+void test3(read_only pipe const int p) {
+// CHECK: define void @test3(%opencl.pipe_t* %p)
+}
+
+void test4(read_only pipe uchar3 p) {
+// CHECK: define void @test4(%opencl.pipe_t* %p)
+}
+
+void test5(read_only pipe int4 p) {
+// CHECK: define void @test5(%opencl.pipe_t* %p)
+}
diff --git a/clang/test/PCH/ocl_types.cl b/clang/test/PCH/ocl_types.cl
index d788a326214..21097c48118 100644
--- a/clang/test/PCH/ocl_types.cl
+++ b/clang/test/PCH/ocl_types.cl
@@ -1,9 +1,9 @@
// Test this without pch.
-// RUN: %clang_cc1 -include %S/ocl_types.h -fsyntax-only %s
+// RUN: %clang_cc1 -include %S/ocl_types.h -fsyntax-only %s -cl-std=CL2.0 -D__OPENCL_VERSION__=200
// Test with pch.
-// RUN: %clang_cc1 -x cl -emit-pch -o %t %S/ocl_types.h
-// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -ast-print
+// RUN: %clang_cc1 -x cl -emit-pch -o %t %S/ocl_types.h -cl-std=CL2.0 -D__OPENCL_VERSION__=200
+// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -ast-print -cl-std=CL2.0 -D__OPENCL_VERSION__=200
void foo1(img1d_t img);
@@ -24,3 +24,15 @@ void foo7(smp_t smp) {
void foo8(evt_t evt) {
evt_t loc_evt;
}
+
+#if __OPENCL_VERSION__ >= 200
+
+void foo9(pipe int P) {
+ int_pipe_function(P);
+}
+
+void foo10(pipe Person P) {
+ person_pipe_function(P);
+}
+
+#endif
diff --git a/clang/test/PCH/ocl_types.h b/clang/test/PCH/ocl_types.h
index 93cf4f66442..bdc4bb11c1b 100644
--- a/clang/test/PCH/ocl_types.h
+++ b/clang/test/PCH/ocl_types.h
@@ -44,6 +44,7 @@ typedef image2d_depth_t img2ddep_t;
// image2d_array_depth_t
typedef image2d_array_depth_t img2darr_dep_t;
+#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable
// image2d_msaa_t
typedef image2d_msaa_t img2dmsaa_t;
@@ -56,4 +57,14 @@ typedef image2d_msaa_depth_t img2dmsaadep_t;
// image2d_array_msaa_depth_t
typedef image2d_array_msaa_depth_t img2darrmsaadep_t;
+// pipe specifier
+
+typedef struct _person {
+ int id;
+ const char *name;
+} Person;
+
+void int_pipe_function(pipe int);
+
+void person_pipe_function(pipe Person);
#endif
diff --git a/clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl b/clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl
new file mode 100644
index 00000000000..ee36892b93d
--- /dev/null
+++ b/clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
+
+void test1(pipe int *p){// expected-error {{pipes packet types cannot be of reference type}}
+}
+void test2(pipe p){// expected-error {{missing actual type specifier for pipe}}
+}
+void test3(int pipe p){// expected-error {{cannot combine with previous 'int' declaration specifier}}
+}
diff --git a/clang/test/SemaOpenCL/pipes-1.2-negative.cl b/clang/test/SemaOpenCL/pipes-1.2-negative.cl
new file mode 100644
index 00000000000..441a24cf852
--- /dev/null
+++ b/clang/test/SemaOpenCL/pipes-1.2-negative.cl
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.2
+
+void foo(read_only pipe int p); // expected-error {{expected parameter declarator}} expected-error {{expected ')'}} expected-note {{to match this '('}}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index dbda13c2353..9086c60e18b 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -1686,6 +1686,10 @@ bool CursorVisitor::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
return Visit(TL.getValueLoc());
}
+bool CursorVisitor::VisitPipeTypeLoc(PipeTypeLoc TL) {
+ return Visit(TL.getValueLoc());
+}
+
#define DEFAULT_TYPELOC_IMPL(CLASS, PARENT) \
bool CursorVisitor::Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { \
return Visit##PARENT##Loc(TL); \
OpenPOWER on IntegriCloud