From 25b4fdb9d63095448e6cbc97b8865b36b0c8cbb6 Mon Sep 17 00:00:00 2001 From: Nate Begeman Date: Sun, 9 Aug 2009 17:55:44 +0000 Subject: [PATCH] AltiVec-style vector initializer syntax, vec4 a = (vec4)(a, b, c, d); In addition to being defined by the AltiVec PIM, this is also the vector initializer syntax used by OpenCL, so that vector literals are compatible with macro arguments. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78535 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 47 ++++++++++++ include/clang/AST/StmtNodes.def | 1 + include/clang/Basic/DiagnosticSemaKinds.td | 3 + include/clang/Parse/Action.h | 13 +++- include/clang/Parse/Parser.h | 7 +- lib/AST/Expr.cpp | 28 ++++++++ lib/AST/StmtPrinter.cpp | 9 +++ lib/AST/StmtProfile.cpp | 4 ++ lib/CodeGen/CGExprScalar.cpp | 2 +- lib/Frontend/PrintParserCallbacks.cpp | 5 +- lib/Parse/ParseExpr.cpp | 31 +++++--- lib/Parse/ParseExprCXX.cpp | 5 +- lib/Sema/Sema.h | 16 ++++- lib/Sema/SemaExpr.cpp | 83 +++++++++++++++++++++- lib/Sema/SemaInit.cpp | 45 ++++++++++-- lib/Sema/SemaTemplateInstantiateExpr.cpp | 16 ++++- test/Sema/altivec-init.c | 16 +++++ tools/clang-cc/clang-cc.cpp | 7 ++ 18 files changed, 307 insertions(+), 31 deletions(-) create mode 100644 test/Sema/altivec-init.c diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 23fd420914..c2bb87d3c0 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -2382,6 +2382,53 @@ public: virtual child_iterator child_end(); }; + +class ParenListExpr : public Expr { + Stmt **Exprs; + unsigned NumExprs; + SourceLocation LParenLoc, RParenLoc; + +protected: + virtual void DoDestroy(ASTContext& C); + +public: + ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, + unsigned numexprs, SourceLocation rparenloc); + + ~ParenListExpr() {} + + /// \brief Build an empty paren list. + //explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } + + unsigned getNumExprs() const { return NumExprs; } + + const Expr* getExpr(unsigned Init) const { + assert(Init < getNumExprs() && "Initializer access out of range!"); + return cast_or_null(Exprs[Init]); + } + + Expr* getExpr(unsigned Init) { + assert(Init < getNumExprs() && "Initializer access out of range!"); + return cast_or_null(Exprs[Init]); + } + + SourceLocation getLParenLoc() const { return LParenLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + + virtual SourceRange getSourceRange() const { + return SourceRange(LParenLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == ParenListExprClass; + } + static bool classof(const ParenListExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + //===----------------------------------------------------------------------===// // Clang Extensions //===----------------------------------------------------------------------===// diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index 914ea2798b..924ad3970f 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -91,6 +91,7 @@ EXPR(ExtVectorElementExpr , Expr) EXPR(InitListExpr , Expr) EXPR(DesignatedInitExpr , Expr) EXPR(ImplicitValueInitExpr , Expr) +EXPR(ParenListExpr , Expr) EXPR(VAArgExpr , Expr) // GNU Extensions. diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index fb36a717f4..39bbe4e481 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2015,6 +2015,9 @@ def err_shufflevector_argument_too_large : Error< "index for __builtin_shufflevector must be less than the total number " "of vector elements">; +def err_vector_incorrect_num_initializers : Error< + "%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">; +def err_altivec_empty_initializer : Error<"expected initializer">; def err_stack_const_level : Error< "level argument for a stack address builtin must be constant">; diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index b2be36eb05..777f75e5a6 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -825,6 +825,12 @@ public: return move(Val); // Default impl returns operand. } + virtual OwningExprResult ActOnParenListExpr(SourceLocation L, + SourceLocation R, + MultiExprArg Val) { + return ExprEmpty(); + } + // Postfix Expressions. virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Kind, @@ -901,11 +907,12 @@ public: return ExprEmpty(); } - virtual OwningExprResult ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty, - SourceLocation RParenLoc, ExprArg Op) { + virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, + TypeTy *Ty, SourceLocation RParenLoc, + ExprArg Op) { return ExprEmpty(); } - + virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, ExprArg LHS, ExprArg RHS) { diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index f2faa1c758..9e785a65ff 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -705,9 +705,11 @@ private: unsigned MinPrec); OwningExprResult ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, - bool &NotCastExpr); + bool &NotCastExpr, + bool parseParenAsExprList); OwningExprResult ParseCastExpression(bool isUnaryExpression, - bool isAddressOfOperand = false); + bool isAddressOfOperand = false, + bool parseParenAsExprList = false); OwningExprResult ParsePostfixExpressionSuffix(OwningExprResult LHS); OwningExprResult ParseSizeofAlignofExpression(); OwningExprResult ParseBuiltinPrimaryExpression(); @@ -733,6 +735,7 @@ private: }; OwningExprResult ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, + bool parseAsExprList, TypeTy *&CastTy, SourceLocation &RParenLoc); diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 2c07de6c79..ce8bb516c0 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1784,6 +1784,26 @@ void DesignatedInitExpr::DoDestroy(ASTContext &C) { Expr::DoDestroy(C); } +ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc, + Expr **exprs, unsigned nexprs, + SourceLocation rparenloc) +: Expr(ParenListExprClass, QualType(), + hasAnyTypeDependentArguments(exprs, nexprs), + hasAnyValueDependentArguments(exprs, nexprs)), + NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) { + + Exprs = new (C) Stmt*[nexprs]; + for (unsigned i = 0; i != nexprs; ++i) + Exprs[i] = exprs[i]; +} + +void ParenListExpr::DoDestroy(ASTContext& C) { + DestroyChildren(C); + if (Exprs) C.Deallocate(Exprs); + this->~ParenListExpr(); + C.Deallocate(this); +} + //===----------------------------------------------------------------------===// // ExprIterator. //===----------------------------------------------------------------------===// @@ -1988,6 +2008,14 @@ Stmt::child_iterator ImplicitValueInitExpr::child_end() { return child_iterator(); } +// ParenListExpr +Stmt::child_iterator ParenListExpr::child_begin() { + return &Exprs[0]; +} +Stmt::child_iterator ParenListExpr::child_end() { + return &Exprs[0]+NumExprs; +} + // ObjCStringLiteral Stmt::child_iterator ObjCStringLiteral::child_begin() { return &String; diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index a5b0df8e45..a2c04978b0 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -850,6 +850,15 @@ void StmtPrinter::VisitInitListExpr(InitListExpr* Node) { OS << " }"; } +void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) { + OS << "( "; + for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) { + if (i) OS << ", "; + PrintExpr(Node->getExpr(i)); + } + OS << " )"; +} + void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) { for (DesignatedInitExpr::designators_iterator D = Node->designators_begin(), DEnd = Node->designators_end(); diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index d0f02ae95b..5d9b8bc7bb 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -245,6 +245,10 @@ void StmtProfiler::VisitParenExpr(ParenExpr *S) { VisitExpr(S); } +void StmtProfiler::VisitParenListExpr(ParenListExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitUnaryOperator(UnaryOperator *S) { VisitExpr(S); ID.AddInteger(S->getOpcode()); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 3a9ec7ef6f..44f4c27927 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -467,7 +467,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, } // A scalar can be splatted to an extended vector of the same element type - if (DstType->isExtVectorType() && !isa(SrcType)) { + if (DstType->isExtVectorType() && !SrcType->isVectorType()) { // Cast the scalar to element type QualType EltTy = DstType->getAsExtVectorType()->getElementType(); llvm::Value *Elt = EmitScalarConversion(Src, SrcType, EltTy); diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp index c933a2f320..2101a85f41 100644 --- a/lib/Frontend/PrintParserCallbacks.cpp +++ b/lib/Frontend/PrintParserCallbacks.cpp @@ -574,8 +574,9 @@ namespace { Out << __FUNCTION__ << "\n"; return ExprEmpty(); } - virtual OwningExprResult ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty, - SourceLocation RParenLoc,ExprArg Op){ + virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, + TypeTy *Ty, SourceLocation RParenLoc, + ExprArg Op) { Out << __FUNCTION__ << "\n"; return ExprEmpty(); } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 62bd9ae73c..6e7deef95d 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -407,11 +407,13 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) { /// due to member pointers. /// Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, - bool isAddressOfOperand) { + bool isAddressOfOperand, + bool parseParenAsExprList){ bool NotCastExpr; OwningExprResult Res = ParseCastExpression(isUnaryExpression, isAddressOfOperand, - NotCastExpr); + NotCastExpr, + parseParenAsExprList); if (NotCastExpr) Diag(Tok, diag::err_expected_expression); return move(Res); @@ -530,7 +532,8 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, - bool &NotCastExpr) { + bool &NotCastExpr, + bool parseParenAsExprList){ OwningExprResult Res(Actions); tok::TokenKind SavedKind = Tok.getKind(); NotCastExpr = false; @@ -555,7 +558,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, SourceLocation LParenLoc = Tok.getLocation(); SourceLocation RParenLoc; Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/, - CastTy, RParenLoc); + parseParenAsExprList, CastTy, RParenLoc); if (Res.isInvalid()) return move(Res); switch (ParenExprType) { @@ -1021,7 +1024,7 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, // operands. EnterExpressionEvaluationContext Unevaluated(Actions, Action::Unevaluated); - Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/, + Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/, false, CastTy, RParenLoc); CastRange = SourceRange(LParenLoc, RParenLoc); @@ -1278,7 +1281,8 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() { /// Parser::OwningExprResult Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, - TypeTy *&CastTy, SourceLocation &RParenLoc) { + bool parseAsExprList, TypeTy *&CastTy, + SourceLocation &RParenLoc) { assert(Tok.is(tok::l_paren) && "Not a paren expr!"); GreaterThanIsOperatorScope G(GreaterThanIsOperator, true); SourceLocation OpenLoc = ConsumeParen(); @@ -1338,14 +1342,25 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // Parse the cast-expression that follows it next. // TODO: For cast expression with CastTy. - Result = ParseCastExpression(false); + Result = ParseCastExpression(false, false, true); if (!Result.isInvalid()) - Result = Actions.ActOnCastExpr(OpenLoc, CastTy, RParenLoc,move(Result)); + Result = Actions.ActOnCastExpr(CurScope, OpenLoc, CastTy, RParenLoc, + move(Result)); return move(Result); } Diag(Tok, diag::err_expected_lbrace_in_compound_literal); return ExprError(); + } else if (parseAsExprList) { + // Parse the expression-list. + ExprVector ArgExprs(Actions); + CommaLocsTy CommaLocs; + + if (!ParseExpressionList(ArgExprs, CommaLocs)) { + ExprType = SimpleExpr; + Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(), + move_arg(ArgExprs)); + } } else { Result = ParseExpression(); ExprType = SimpleExpr; diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 91b4d4d5a9..46526e47dd 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1154,7 +1154,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, // will be consumed. Result = ParseCastExpression(false/*isUnaryExpression*/, false/*isAddressofOperand*/, - NotCastExpr); + NotCastExpr, false); } // If we parsed a cast-expression, it's really a type-id, otherwise it's @@ -1196,7 +1196,8 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, // Result is what ParseCastExpression returned earlier. if (!Result.isInvalid()) - Result = Actions.ActOnCastExpr(LParenLoc, CastTy, RParenLoc,move(Result)); + Result = Actions.ActOnCastExpr(CurScope, LParenLoc, CastTy, RParenLoc, + move(Result)); return move(Result); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 4f7ae7ec0d..e183e3a496 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -50,6 +50,7 @@ namespace clang { class Stmt; class Expr; class InitListExpr; + class ParenListExpr; class DesignatedInitExpr; class CallExpr; class DeclRefExpr; @@ -1484,7 +1485,10 @@ public: virtual OwningExprResult ActOnCharacterConstant(const Token &); virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, ExprArg Val); - + virtual OwningExprResult ActOnParenListExpr(SourceLocation L, + SourceLocation R, + MultiExprArg Val); + /// ActOnStringLiteral - The specified tokens were lexed as pasted string /// fragments (e.g. "foo" "bar" L"baz"). virtual OwningExprResult ActOnStringLiteral(const Token *Toks, @@ -1545,8 +1549,14 @@ public: SourceLocation *CommaLocs, SourceLocation RParenLoc); - virtual OwningExprResult ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty, - SourceLocation RParenLoc, ExprArg Op); + virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, + TypeTy *Ty, SourceLocation RParenLoc, + ExprArg Op); + + OwningExprResult ConvertParenListExpr(Scope *S, ParenListExpr *E); + OwningExprResult ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, + SourceLocation RParenLoc, + ParenListExpr *E, QualType Ty); virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index f00ab5412d..23e58de68c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1918,7 +1918,8 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, << LHSExp->getSourceRange() << RHSExp->getSourceRange()); } // C99 6.5.2.1p1 - if (!IndexExpr->getType()->isIntegerType() && !IndexExpr->isTypeDependent()) + if (!(IndexExpr->getType()->isIntegerType() && + IndexExpr->getType()->isScalarType()) && !IndexExpr->isTypeDependent()) return ExprError(Diag(LLoc, diag::err_typecheck_subscript_not_integer) << IndexExpr->getSourceRange()); @@ -2114,6 +2115,11 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, Expr *BaseExpr = Base.takeAs(); assert(BaseExpr && "no record expression"); + // If BaseExpr is a ParenListExpr then convert it into a standard + // paren expr since this is not an altivec initializer. + if (ParenListExpr *PE = dyn_cast(BaseExpr)) + BaseExpr = ConvertParenListExpr(S, PE).takeAs(); + // Perform default conversions. DefaultFunctionArrayConversion(BaseExpr); @@ -2689,6 +2695,11 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, FunctionDecl *FDecl = NULL; NamedDecl *NDecl = NULL; DeclarationName UnqualifiedName; + + // If the function is a ParenListExpr, then convert it into a standard + // paren expr since this is not an altivec initializer. + if (ParenListExpr *PE = dyn_cast(Fn)) + Fn = ConvertParenListExpr(S, PE).takeAs(); if (getLangOptions().CPlusPlus) { // Determine whether this is a dependent call inside a C++ template, @@ -3090,7 +3101,7 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) { } Action::OwningExprResult -Sema::ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty, +Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, TypeTy *Ty, SourceLocation RParenLoc, ExprArg Op) { CastExpr::CastKind Kind = CastExpr::CK_Unknown; @@ -3099,6 +3110,10 @@ Sema::ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty, Expr *castExpr = Op.takeAs(); QualType castType = QualType::getFromOpaquePtr(Ty); + + // If the Expr being casted is a ParenListExpr, handle it specially. + if (ParenListExpr *PE = dyn_cast(castExpr)) + return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, PE, castType); if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), castType, castExpr, Kind)) @@ -3108,6 +3123,68 @@ Sema::ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty, LParenLoc, RParenLoc)); } +/// This is not an AltiVec-style cast, so turn the ParenListExpr into a sequence +/// of comma binary operators. +Action::OwningExprResult +Sema::ConvertParenListExpr(Scope *S, ParenListExpr *E) { + OwningExprResult Result(*this, E->getExpr(0)); + + for (unsigned i = 1, e = E->getNumExprs(); i != e && !Result.isInvalid(); ++i) + Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, move(Result), + Owned(E->getExpr(i))); + return move(Result); +} + +Action::OwningExprResult +Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, + SourceLocation RParenLoc, + ParenListExpr *E, QualType Ty) { + // If this is an altivec initializer, '(' type ')' '(' init, ..., init ')' + // then handle it as such. + if (getLangOptions().AltiVec && Ty->isVectorType()) { + if (E->getNumExprs() == 0) { + Diag(E->getExprLoc(), diag::err_altivec_empty_initializer); + return ExprError(); + } + + llvm::SmallVector initExprs; + for (unsigned i = 0, e = E->getNumExprs(); i != e; ++i) + initExprs.push_back(E->getExpr(i)); + + // FIXME: This means that pretty-printing the final AST will produce curly + // braces instead of the original commas. + InitListExpr *E = new (Context) InitListExpr(LParenLoc, &initExprs[0], + initExprs.size(), RParenLoc); + E->setType(Ty); + return ActOnCompoundLiteral(LParenLoc, Ty.getAsOpaquePtr(), RParenLoc, + Owned(E)); + } else { + // This is not an AltiVec-style cast, so turn the ParenListExpr into a + // sequence of BinOp comma operators. + OwningExprResult Result = ConvertParenListExpr(S, E); + Expr *castExpr = (Expr *)Result.get(); + CastExpr::CastKind Kind = CastExpr::CK_Unknown; + + if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty, castExpr, Kind)) + return ExprError(); + + return Owned(new (Context) CStyleCastExpr(Ty.getNonReferenceType(), + CastExpr::CK_Unknown, + Result.takeAs(), Ty, + LParenLoc, RParenLoc)); + } +} + +Action::OwningExprResult Sema::ActOnParenListExpr(SourceLocation L, + SourceLocation R, + MultiExprArg Val) { + unsigned nexprs = Val.size(); + Expr **exprs = reinterpret_cast(Val.release()); + assert((exprs != 0) && "ActOnParenListExpr() missing expr list"); + Expr *expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R); + return Owned(expr); +} + /// Note that lhs is not null here, even if this is the gnu "x ?: y" extension. /// In that case, lhs = cond. /// C99 6.5.15 @@ -3132,6 +3209,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, } // Now check the two expressions. + if (LHSTy->isVectorType() || RHSTy->isVectorType()) + return CheckVectorOperands(QuestionLoc, LHS, RHS); // If both operands have arithmetic type, do the usual arithmetic conversions // to find a common type: C99 6.5.15p3,5. diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 29113822f7..1e564ce45f 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -805,16 +805,47 @@ void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType, unsigned &StructuredIndex) { if (Index < IList->getNumInits()) { const VectorType *VT = DeclType->getAsVectorType(); - int maxElements = VT->getNumElements(); + unsigned maxElements = VT->getNumElements(); + unsigned numEltsInit = 0; QualType elementType = VT->getElementType(); - for (int i = 0; i < maxElements; ++i) { - // Don't attempt to go past the end of the init list - if (Index >= IList->getNumInits()) - break; - CheckSubElementType(IList, elementType, Index, - StructuredList, StructuredIndex); + if (!SemaRef.getLangOptions().OpenCL) { + for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) { + // Don't attempt to go past the end of the init list + if (Index >= IList->getNumInits()) + break; + CheckSubElementType(IList, elementType, Index, + StructuredList, StructuredIndex); + } + } else { + // OpenCL initializers allows vectors to be constructed from vectors. + for (unsigned i = 0; i < maxElements; ++i) { + // Don't attempt to go past the end of the init list + if (Index >= IList->getNumInits()) + break; + QualType IType = IList->getInit(Index)->getType(); + if (!IType->isVectorType()) { + CheckSubElementType(IList, elementType, Index, + StructuredList, StructuredIndex); + ++numEltsInit; + } else { + const VectorType *IVT = IType->getAsVectorType(); + unsigned numIElts = IVT->getNumElements(); + QualType VecType = SemaRef.Context.getExtVectorType(elementType, + numIElts); + CheckSubElementType(IList, VecType, Index, + StructuredList, StructuredIndex); + numEltsInit += numIElts; + } + } } + + // OpenCL & AltiVec require all elements to be initialized. + if (numEltsInit != maxElements) + if (SemaRef.getLangOptions().OpenCL || SemaRef.getLangOptions().AltiVec) + SemaRef.Diag(IList->getSourceRange().getBegin(), + diag::err_vector_incorrect_num_initializers) + << (numEltsInit < maxElements) << maxElements << numEltsInit; } } diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp index 186c98cf53..7a09210fe0 100644 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp @@ -638,6 +638,20 @@ TemplateExprInstantiator::VisitInitListExpr(InitListExpr *E) { E->getRBraceLoc()); } +Sema::OwningExprResult +TemplateExprInstantiator::VisitParenListExpr(ParenListExpr *E) { + ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef); + for (unsigned I = 0, N = E->getNumExprs(); I != N; ++I) { + OwningExprResult Init = Visit(E->getExpr(I)); + if (Init.isInvalid()) + return SemaRef.ExprError(); + Inits.push_back(Init.takeAs()); + } + + return SemaRef.ActOnParenListExpr(E->getLParenLoc(), E->getRParenLoc(), + move_arg(Inits)); +} + Sema::OwningExprResult TemplateExprInstantiator::VisitDesignatedInitExpr(DesignatedInitExpr *E) { Designation Desig; @@ -886,7 +900,7 @@ TemplateExprInstantiator::VisitCStyleCastExpr(CStyleCastExpr *E) { if (SubExpr.isInvalid()) return SemaRef.ExprError(); - return SemaRef.ActOnCastExpr(E->getLParenLoc(), + return SemaRef.ActOnCastExpr(/*Scope=*/0, E->getLParenLoc(), ExplicitTy.getAsOpaquePtr(), E->getRParenLoc(), move(SubExpr)); diff --git a/test/Sema/altivec-init.c b/test/Sema/altivec-init.c new file mode 100644 index 0000000000..6185186903 --- /dev/null +++ b/test/Sema/altivec-init.c @@ -0,0 +1,16 @@ +// RUN: clang-cc %s -faltivec -verify -pedantic -fsyntax-only -fblocks=0 + +typedef int v4 __attribute((vector_size(16))); +typedef short v8 __attribute((vector_size(16))); + +v8 foo(void) { + v8 a; + v4 b; + a = (v8){4, 2}; // expected-error {{too few elements in vector initialization (expected 8 elements, have 2)}} + b = (v4)(5, 6, 7, 8, 9); // expected-warning {{excess elements in vector initializer}} + b = (v4)(5, 6, 8, 8.0f); + return (v8){0, 1, 2, 3, 1, 2, 3, 4}; + + // FIXME: test that (type)(fn)(args) still works with -faltivec + // FIXME: test that c++ overloaded commas still work -faltivec +} diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp index e935baa27f..a7cff1d1a2 100644 --- a/tools/clang-cc/clang-cc.cpp +++ b/tools/clang-cc/clang-cc.cpp @@ -385,6 +385,10 @@ OverflowChecking("ftrapv", llvm::cl::desc("Trap on integer overflow"), llvm::cl::init(false)); +static llvm::cl::opt +AltiVec("faltivec", llvm::cl::desc("Enable AltiVec vector initializer syntax"), + llvm::cl::init(false)); + static llvm::cl::opt ObjCSenderDispatch("fobjc-sender-dependent-dispatch", llvm::cl::desc("Enable sender-dependent dispatch for" @@ -501,6 +505,9 @@ static void InitializeLangOptions(LangOptions &Options, LangKind LK){ if (ObjCEnableGCBitmapPrint) Options.ObjCGCBitmapPrint = 1; + if (AltiVec) + Options.AltiVec = 1; + Options.setVisibilityMode(SymbolVisibility); Options.OverflowChecking = OverflowChecking; } -- 2.40.0