[cfe-dev] OpenCL vec_step feature implementation - Updated patch

Peter Collingbourne peter at pcc.me.uk
Wed Feb 23 12:44:36 PST 2011


On Tue, Feb 22, 2011 at 11:05:37PM +0200, Benyei, Guy wrote:
> Hello,
> Here is another update for our vec_step patch. The changes I did in this patch:
> 
> Changed the new expression name that includes sizeof, alignof and vec_step to UnaryExprOrTypeTraitExpr.
> Fail compilation on vec_step of derived types.
> Added negative test cases.
> Fixed some comments.
> 
> Please review.

Comments are inlined below.

> Index: include/clang/AST/Expr.h
> ===================================================================
> --- include/clang/AST/Expr.h	(revision 126222)
> +++ include/clang/AST/Expr.h	(working copy)
> @@ -1556,10 +1556,15 @@
>    }
>  };
>  
> -/// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of
> -/// types and expressions.
> -class SizeOfAlignOfExpr : public Expr {
> -  bool isSizeof : 1;  // true if sizeof, false if alignof.
> +/// UnaryExprOrTypeTraitExpr - either:
> +/// [C99 6.5.3.4] - This is for sizeof/alignof, both of types and expressions.
> +/// [OpenCL 1.1 6.11.12] - The vec_step builtin function, which works on both
> +/// types and expressions
> +class UnaryExprOrTypeTraitExpr : public Expr {
> +public:
> +  enum Kind_t { SizeOf, AlignOf, VecStep };

This enum should live in include/clang/Basic/TypeTraits.h with the
other type trait kind enums.

> +private:
> +  Kind_t Kind;

This should be a bit-field so that we share storage space with isType.

>    bool isType : 1;    // true if operand is a type, false if an expression
>    union {
>      TypeSourceInfo *Ty;
> @@ -1568,36 +1573,36 @@
>    SourceLocation OpLoc, RParenLoc;
>  
>  public:
> -  SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo,
> +  UnaryExprOrTypeTraitExpr(Kind_t exprKind, TypeSourceInfo *TInfo,
>                      QualType resultType, SourceLocation op,
>                      SourceLocation rp) :
> -      Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary,
> +      Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
>             false, // Never type-dependent (C++ [temp.dep.expr]p3).
>             // Value-dependent if the argument is type-dependent.
>             TInfo->getType()->isDependentType(),
>             TInfo->getType()->containsUnexpandedParameterPack()),
> -      isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) {
> +      Kind(exprKind), isType(true), OpLoc(op), RParenLoc(rp) {
>      Argument.Ty = TInfo;
>    }
>  
> -  SizeOfAlignOfExpr(bool issizeof, Expr *E,
> +  UnaryExprOrTypeTraitExpr(Kind_t exprKind, Expr *E,
>                      QualType resultType, SourceLocation op,
>                      SourceLocation rp) :
> -      Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary,
> +      Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
>             false, // Never type-dependent (C++ [temp.dep.expr]p3).
>             // Value-dependent if the argument is type-dependent.
>             E->isTypeDependent(),
>             E->containsUnexpandedParameterPack()),
> -      isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) {
> +      Kind(exprKind), isType(false), OpLoc(op), RParenLoc(rp) {
>      Argument.Ex = E;
>    }
>  
>    /// \brief Construct an empty sizeof/alignof expression.
> -  explicit SizeOfAlignOfExpr(EmptyShell Empty)
> -    : Expr(SizeOfAlignOfExprClass, Empty) { }
> +  explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty)
> +    : Expr(UnaryExprOrTypeTraitExprClass, Empty) { }
>  
> -  bool isSizeOf() const { return isSizeof; }
> -  void setSizeof(bool S) { isSizeof = S; }
> +  Kind_t getKind() const { return Kind; }
> +  void setKind(Kind_t K) { Kind = K; }
>  
>    bool isArgumentType() const { return isType; }
>    QualType getArgumentType() const {
> @@ -1612,7 +1617,7 @@
>      return static_cast<Expr*>(Argument.Ex);
>    }
>    const Expr *getArgumentExpr() const {
> -    return const_cast<SizeOfAlignOfExpr*>(this)->getArgumentExpr();
> +    return const_cast<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr();
>    }
>  
>    void setArgument(Expr *E) { Argument.Ex = E; isType = false; }
> @@ -1638,9 +1643,9 @@
>    }
>  
>    static bool classof(const Stmt *T) {
> -    return T->getStmtClass() == SizeOfAlignOfExprClass;
> +    return T->getStmtClass() == UnaryExprOrTypeTraitExprClass;
>    }
> -  static bool classof(const SizeOfAlignOfExpr *) { return true; }
> +  static bool classof(const UnaryExprOrTypeTraitExpr *) { return true; }
>  
>    // Iterators
>    child_range children();
> Index: include/clang/Basic/TokenKinds.def
> ===================================================================
> --- include/clang/Basic/TokenKinds.def	(revision 126222)
> +++ include/clang/Basic/TokenKinds.def	(working copy)
> @@ -345,10 +345,12 @@
>  KEYWORD(__thiscall                  , KEYALL)
>  KEYWORD(__forceinline               , KEYALL)
>  
> -// OpenCL-specific keywords (see OpenCL 1.1 [6.1.9])
> +// OpenCL-specific keywords (see OpenCL 1.1)
>  KEYWORD(__kernel                    , KEYOPENCL)
>  ALIAS("kernel", __kernel            , KEYOPENCL)
> +KEYWORD(vec_step                    , KEYOPENCL)
>  
> +

You can remove this newline.

>  // Borland Extensions.
>  KEYWORD(__pascal                    , KEYALL)
>  
> Index: lib/AST/ExprConstant.cpp
> ===================================================================
> --- lib/AST/ExprConstant.cpp	(revision 126222)
> +++ lib/AST/ExprConstant.cpp	(working copy)
> @@ -290,7 +290,8 @@
>    bool VisitFloatingLiteral(FloatingLiteral *E) { return false; }
>    bool VisitStringLiteral(StringLiteral *E) { return false; }
>    bool VisitCharacterLiteral(CharacterLiteral *E) { return false; }
> -  bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { return false; }
> +  bool VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E)
> +    { return false; }
>    bool VisitArraySubscriptExpr(ArraySubscriptExpr *E)
>      { return Visit(E->getLHS()) || Visit(E->getRHS()); }
>    bool VisitChooseExpr(ChooseExpr *E)
> @@ -1015,7 +1016,7 @@
>    bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E);
>  
>    bool VisitCastExpr(CastExpr* E);
> -  bool VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
> +  bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
>  
>    bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {
>      return Success(E->getValue(), E);
> @@ -1598,15 +1599,36 @@
>  
>  /// VisitSizeAlignOfExpr - Evaluate a sizeof or alignof with a result as the
>  /// expression's type.
> -bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
> +bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
> +                                    const UnaryExprOrTypeTraitExpr *E) {
>    // Handle alignof separately.
> -  if (!E->isSizeOf()) {
> +  if (E->getKind() == UnaryExprOrTypeTraitExpr::AlignOf) {
>      if (E->isArgumentType())
>        return Success(GetAlignOfType(E->getArgumentType()).getQuantity(), E);
>      else
>        return Success(GetAlignOfExpr(E->getArgumentExpr()).getQuantity(), E);
>    }
>  
> +  if (E->getKind() == UnaryExprOrTypeTraitExpr::VecStep) {
> +    clang::QualType Ty;
> +    if (E->isArgumentType())
> +      Ty = E->getArgumentType();
> +    else
> +      Ty = E->getArgumentExpr()->getType();
> +
> +    if (Ty->isVectorType()) {
> +      unsigned n = Ty->getAs<clang::VectorType>()->getNumElements();
> +
> +      // The vec_step built-in functions that take a 3-component
> +      // vector return 4. (OpenCL 1.1 spec 6.11.12)
> +      if (n == 3)
> +        n = 4;
> +
> +      return Success(n, E);
> +    } else
> +      return Success(1, E);
> +  }
> +
>    QualType SrcTy = E->getTypeOfArgument();
>    // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
>    //   the result is the size of the referenced type."

This should use a case statement without a default so that we get a
compiler warning if we add another trait without changing this code.

> @@ -2879,9 +2901,10 @@
>        // are ICEs, the value of the offsetof must be an integer constant.
>        return CheckEvalInICE(E, Ctx);
>    }
> -  case Expr::SizeOfAlignOfExprClass: {
> -    const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(E);
> -    if (Exp->isSizeOf() && Exp->getTypeOfArgument()->isVariableArrayType())
> +  case Expr::UnaryExprOrTypeTraitExprClass: {
> +    const UnaryExprOrTypeTraitExpr *Exp = cast<UnaryExprOrTypeTraitExpr>(E);
> +    if ((Exp->getKind() ==  UnaryExprOrTypeTraitExpr::SizeOf) &&
> +        Exp->getTypeOfArgument()->isVariableArrayType())
>        return ICEDiag(2, E->getLocStart());
>      return NoDiag();
>    }
> Index: lib/AST/ItaniumMangle.cpp
> ===================================================================
> --- lib/AST/ItaniumMangle.cpp	(revision 126222)
> +++ lib/AST/ItaniumMangle.cpp	(working copy)
> @@ -1874,10 +1874,11 @@
>      break;
>    }
>  
> -  case Expr::SizeOfAlignOfExprClass: {
> -    const SizeOfAlignOfExpr *SAE = cast<SizeOfAlignOfExpr>(E);
> -    if (SAE->isSizeOf()) Out << 's';
> -    else Out << 'a';
> +  case Expr::UnaryExprOrTypeTraitExprClass: {
> +    const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E);
> +    if (SAE->getKind() == UnaryExprOrTypeTraitExpr::SizeOf) Out << 's';
> +    else if (SAE->getKind() == UnaryExprOrTypeTraitExpr::AlignOf) Out << 'a';
> +    else Out << 'v';

Case statement here also.

This encoding does not conform with the Itanium ABI (it clashes with
the encoding for 'vendor extended operators').  We should error out
here for vec_step until we have a proper encoding.

>      if (SAE->isArgumentType()) {
>        Out << 't';
>        mangleType(SAE->getArgumentType());
> Index: lib/AST/StmtDumper.cpp
> ===================================================================
> --- lib/AST/StmtDumper.cpp	(revision 126222)
> +++ lib/AST/StmtDumper.cpp	(working copy)
> @@ -141,7 +141,7 @@
>      void VisitFloatingLiteral(FloatingLiteral *Node);
>      void VisitStringLiteral(StringLiteral *Str);
>      void VisitUnaryOperator(UnaryOperator *Node);
> -    void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
> +    void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node);
>      void VisitMemberExpr(MemberExpr *Node);
>      void VisitExtVectorElementExpr(ExtVectorElementExpr *Node);
>      void VisitBinaryOperator(BinaryOperator *Node);
> @@ -441,9 +441,21 @@
>    OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
>       << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
>  }
> -void StmtDumper::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
> +void StmtDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) {
>    DumpExpr(Node);
> -  OS << " " << (Node->isSizeOf() ? "sizeof" : "alignof") << " ";
> +  switch(Node->getKind()) {
> +  default:
> +    assert(false && "Unknown kind for UnaryExprOrTypeTraitExpr");
> +  case UnaryExprOrTypeTraitExpr::SizeOf:
> +    OS << "sizeof";
> +    break;
> +  case UnaryExprOrTypeTraitExpr::AlignOf:
> +    OS << "__alignof";
> +    break;
> +  case UnaryExprOrTypeTraitExpr::VecStep:
> +    OS << "vec_step";
> +    break;
> +  }

No default here.

>    if (Node->isArgumentType())
>      DumpType(Node->getArgumentType());
>  }
> Index: lib/AST/StmtPrinter.cpp
> ===================================================================
> --- lib/AST/StmtPrinter.cpp	(revision 126222)
> +++ lib/AST/StmtPrinter.cpp	(working copy)
> @@ -706,8 +706,21 @@
>    OS << ")";
>  }
>  
> -void StmtPrinter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
> -  OS << (Node->isSizeOf() ? "sizeof" : "__alignof");
> +void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(
> +                                      UnaryExprOrTypeTraitExpr *Node) {
> +  switch(Node->getKind()) {
> +  default:
> +    assert(false && "Unknown kind for UnaryExprOrTypeTraitExpr");
> +  case UnaryExprOrTypeTraitExpr::SizeOf:
> +    OS << "sizeof";
> +    break;
> +  case UnaryExprOrTypeTraitExpr::AlignOf:
> +    OS << "__alignof";
> +    break;
> +  case UnaryExprOrTypeTraitExpr::VecStep:
> +    OS << "vec_step";
> +    break;
> +  }

No default.

>    if (Node->isArgumentType())
>      OS << "(" << Node->getArgumentType().getAsString(Policy) << ")";
>    else {
> Index: lib/Frontend/StmtXML.cpp
> ===================================================================
> --- lib/Frontend/StmtXML.cpp	(revision 126222)
> +++ lib/Frontend/StmtXML.cpp	(working copy)
> @@ -36,7 +36,7 @@
>                                               Str->getString().size()));
>    }
>  
> -  void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S) {
> +  void addSpecialAttribute(const char* pName, UnaryExprOrTypeTraitExpr* S) {
>      if (S->isArgumentType())
>        Doc.addAttribute(pName, S->getArgumentType());
>    }
> @@ -126,7 +126,7 @@
>      void VisitStringLiteral(StringLiteral *Str);
>      void VisitUnaryOperator(UnaryOperator *Node);
>      void VisitOffsetOfExpr(OffsetOfExpr *Node);
> -    void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
> +    void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node);
>      void VisitMemberExpr(MemberExpr *Node);
>      void VisitExtVectorElementExpr(ExtVectorElementExpr *Node);
>      void VisitBinaryOperator(BinaryOperator *Node);
> @@ -310,7 +310,7 @@
>    DumpExpr(Node);
>  }
>  
> -void StmtXML::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
> +void StmtXML::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) {
>    DumpExpr(Node);
>    Doc.addAttribute("is_sizeof", Node->isSizeOf() ? "sizeof" : "alignof");

This should be changed to use getKind.

> Index: lib/Sema/SemaExpr.cpp
> ===================================================================
> --- lib/Sema/SemaExpr.cpp	(revision 126222)
> +++ lib/Sema/SemaExpr.cpp	(working copy)
> @@ -2716,10 +2716,10 @@
>  
>  /// The UsualUnaryConversions() function is *not* called by this routine.
>  /// See C99 6.3.2.1p[2-4] for more details.
> -bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
> -                                     SourceLocation OpLoc,
> -                                     SourceRange ExprRange,
> -                                     bool isSizeof) {
> +bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType exprType,
> +                                   SourceLocation OpLoc,
> +                                   SourceRange ExprRange,
> +                                   UnaryExprOrTypeTraitExpr::Kind_t exprKind) {
>    if (exprType->isDependentType())
>      return false;
>  
> @@ -2733,28 +2733,36 @@
>    // C99 6.5.3.4p1:
>    if (exprType->isFunctionType()) {
>      // alignof(function) is allowed as an extension.
> -    if (isSizeof)
> -      Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange;
> -    return false;
> +    if (exprKind != UnaryExprOrTypeTraitExpr::AlignOf)
> +      Diag(OpLoc, diag::ext_sizeof_vecstep_function_type) 
> +        << exprKind << ExprRange;
> +     return false;
>    }
>  
>    // Allow sizeof(void)/alignof(void) as an extension.
>    if (exprType->isVoidType()) {
>      Diag(OpLoc, diag::ext_sizeof_void_type)
> -      << (isSizeof ? "sizeof" : "__alignof") << ExprRange;
> +      << exprKind << ExprRange;
>      return false;
>    }
>  
>    if (RequireCompleteType(OpLoc, exprType,
>                            PDiag(diag::err_sizeof_alignof_incomplete_type)
> -                          << int(!isSizeof) << ExprRange))
> +                          << exprKind << ExprRange))
>      return true;
>  
> +  if(exprType->isDerivedType() && exprKind == UnaryExprOrTypeTraitExpr::VecStep)
> +  {
> +    Diag(OpLoc, diag::err_vecstep_derived_type) << exprType << ExprRange;
> +    return true;
> +  }
> +
>    // Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode.
>    if (LangOpts.ObjCNonFragileABI && exprType->isObjCObjectType()) {
>      Diag(OpLoc, diag::err_sizeof_nonfragile_interface)
> -      << exprType << isSizeof << ExprRange;
> -    return true;
> +      << exprType << (exprKind == UnaryExprOrTypeTraitExpr::SizeOf)
> +      << ExprRange;
> +	  return true;

"return true;" shouldn't change indentation here.

>    }
>  
>    return false;
> @@ -2783,25 +2791,45 @@
>      if (isa<FieldDecl>(ME->getMemberDecl()))
>        return false;
>  
> -  return S.CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false);
> +  return S.CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, ExprRange,
> +                                            UnaryExprOrTypeTraitExpr::AlignOf);
>  }
>  
> +bool Sema::CheckVecStepExpr(Expr *E, SourceLocation OpLoc,
> +                            SourceRange ExprRange) {
> +  if (!getLangOptions().OpenCL) {
> +    // vec_step is supported in OpenCL only
> +    Diag(OpLoc, diag::err_vecstep_not_in_opencl);
> +    return true;
> +  }

We shouldn't reach here unless we're in OpenCL mode because the
keyword is OpenCL-only.

> Index: lib/StaticAnalyzer/Checkers/ExprEngine.cpp
> ===================================================================
> --- lib/StaticAnalyzer/Checkers/ExprEngine.cpp	(revision 126222)
> +++ lib/StaticAnalyzer/Checkers/ExprEngine.cpp	(working copy)
> @@ -1085,8 +1085,9 @@
>        VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Pred, Dst);
>        break;
>  
> -    case Stmt::SizeOfAlignOfExprClass:
> -      VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), Pred, Dst);
> +    case Stmt::UnaryExprOrTypeTraitExprClass:
> +      VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
> +                                    Pred, Dst);
>        break;
>  
>      case Stmt::StmtExprClass: {
> @@ -2816,14 +2817,15 @@
>    assert(0 && "unprocessed InitListExpr type");
>  }
>  
> -/// VisitSizeOfAlignOfExpr - Transfer function for sizeof(type).
> -void ExprEngine::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex,
> +/// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof(type).
> +void ExprEngine::VisitUnaryExprOrTypeTraitExpr(
> +                                          const UnaryExprOrTypeTraitExpr* Ex,
>                                            ExplodedNode* Pred,
>                                            ExplodedNodeSet& Dst) {
>    QualType T = Ex->getTypeOfArgument();
>    CharUnits amt;
>  
> -  if (Ex->isSizeOf()) {
> +  if (Ex->getKind() == UnaryExprOrTypeTraitExpr::SizeOf) {
>      if (T == getContext().VoidTy) {
>        // sizeof(void) == 1 byte.
>        amt = CharUnits::One();
> @@ -2874,9 +2876,26 @@
>        amt = getContext().getTypeSizeInChars(T);
>      }
>    }
> -  else  // Get alignment of the type.
> -    amt = getContext().getTypeAlignInChars(T);
> +  else if (Ex->getKind() == UnaryExprOrTypeTraitExpr::AlignOf) {
> +    // Get alignment of the type.
> +     amt = getContext().getTypeAlignInChars(T);
> +  }
> +  else {
> +    if (T->isVectorType()) {
> +      int n = T->getAs<clang::VectorType>()->getNumElements();
>  
> +      // The vec_step built-in functions that take a 3-component
> +      // vector return 4. (OpenCL 1.1 spec 6.11.12)
> +      if (n == 3)
> +        n = 4;
> +
> +      amt = CharUnits::fromQuantity(n);
> +    }
> +    else {
> +      amt = CharUnits::fromQuantity(1);
> +    }
> +  }
> +

We should be able to replace all non-special cases here with a call
to the constant expression evaluator.

> Index: test/CodeGenOpenCL/vec_step.cl
> ===================================================================
> --- test/CodeGenOpenCL/vec_step.cl	(revision 0)
> +++ test/CodeGenOpenCL/vec_step.cl	(revision 0)
> @@ -0,0 +1,45 @@
> +// RUN: %clang_cc1 %s -emit-llvm -D NO_NEGATIVE_CASES -O0 -o - | FileCheck %s
> +// RUN: %clang_cc1 -fsyntax-only -verify %s
> +
> +typedef int int2 __attribute__((ext_vector_type(2)));
> +typedef int int3 __attribute__((ext_vector_type(3)));
> +typedef int int4 __attribute__((ext_vector_type(4)));
> +typedef int int8 __attribute__((ext_vector_type(8)));
> +typedef int int16 __attribute__((ext_vector_type(16)));
> +
> +void foo(int3 arg1, int8 arg2) {
> +  int4 auto1;
> +  int16 *auto2;
> +  int auto3;
> +  int2 auto4;
> +  struct S *incomplete1; // expected-note{{forward declaration of 'struct S'}}
> +  
> +  
> +  int res1 = vec_step(arg1);
> +// CHECK: store i32 4, i32* %res1
> +  int res2 = vec_step(arg2);
> +// CHECK: store i32 8, i32* %res2
> +  int res3 = vec_step(auto1);
> +// CHECK: store i32 4, i32* %res3
> +  int res4 = vec_step(*auto2);
> +// CHECK: store i32 16, i32* %res4
> +  int res5 = vec_step(auto3);
> +// CHECK: store i32 1, i32* %res5
> +  int res6 = vec_step(auto4);
> +// CHECK: store i32 2, i32* %res6
> +  int res7 = vec_step(int2);
> +// CHECK: store i32 2, i32* %res7
> +  int res8 = vec_step(int3);
> +// CHECK: store i32 4, i32* %res8
> +  int res9 = vec_step(int4);
> +// CHECK: store i32 4, i32* %res9
> +  int res10 = vec_step(int8);
> +// CHECK: store i32 8, i32* %res10
> +  int res11 = vec_step(int16);
> +// CHECK: store i32 16, i32* %res11
> +
> +#ifndef NO_NEGATIVE_CASES
> +  int res12 = vec_step(*incomplete1); // expected-error{{invalid application of 'vec_step' to an incomplete type 'struct S'}}
> +  int res13 = vec_step(int16*); // expected-error{{invalid application of vec_step to derived type 'int16 *'}}
> +#endif
> +}

Normally we test integral constant expressions in the Clang test
suite using the

int array[foo ? 1 : -1]; 

idiom.  See for example the test/Sema/expr-comma.c test case.
You should be able to move this test case to SemaOpenCL and you
shouldn't need to use the NO_NEGATIVE_CASES macro if using this idiom.

Thanks,
-- 
Peter



More information about the cfe-dev mailing list