]> granicus.if.org Git - clang/commitdiff
AltiVec-style vector initializer syntax, vec4 a = (vec4)(a, b, c, d);
authorNate Begeman <natebegeman@mac.com>
Sun, 9 Aug 2009 17:55:44 +0000 (17:55 +0000)
committerNate Begeman <natebegeman@mac.com>
Sun, 9 Aug 2009 17:55:44 +0000 (17:55 +0000)
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

18 files changed:
include/clang/AST/Expr.h
include/clang/AST/StmtNodes.def
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Parse/Action.h
include/clang/Parse/Parser.h
lib/AST/Expr.cpp
lib/AST/StmtPrinter.cpp
lib/AST/StmtProfile.cpp
lib/CodeGen/CGExprScalar.cpp
lib/Frontend/PrintParserCallbacks.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
lib/Sema/SemaInit.cpp
lib/Sema/SemaTemplateInstantiateExpr.cpp
test/Sema/altivec-init.c [new file with mode: 0644]
tools/clang-cc/clang-cc.cpp

index 23fd420914f461b85b6210373faf3af0f8ec4334..c2bb87d3c05758cbe7072efe7365d0986ff314e4 100644 (file)
@@ -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<Expr>(Exprs[Init]);
+  }
+  
+  Expr* getExpr(unsigned Init) { 
+    assert(Init < getNumExprs() && "Initializer access out of range!");
+    return cast_or_null<Expr>(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
 //===----------------------------------------------------------------------===//
index 914ea2798b49fdfd5930c347b8e25fb432ff2b8f..924ad3970f0df6d940bb8f9a29c0c753b14b33fc 100644 (file)
@@ -91,6 +91,7 @@ EXPR(ExtVectorElementExpr  , Expr)
 EXPR(InitListExpr          , Expr)
 EXPR(DesignatedInitExpr    , Expr)
 EXPR(ImplicitValueInitExpr , Expr)
+EXPR(ParenListExpr         , Expr)
 EXPR(VAArgExpr             , Expr)
 
 // GNU Extensions.
index fb36a717f429a786eb13b30f9d5ec1acd49cd72e..39bbe4e481621e6d90911d7756b3b2bd55d66d27 100644 (file)
@@ -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">;
index b2be36eb0501f47cbd13d84395e79be12c9406a6..777f75e5a602c89c62706777a766d100b6beffe5 100644 (file)
@@ -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) {
index f2faa1c758d8947f30794c7aaf52a5184fd80490..9e785a65ff8a43dd7a159808f03affa869004e99 100644 (file)
@@ -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);
   
index 2c07de6c79accb2d953eec03605be2bc8d22e389..ce8bb516c09074130256f7fd9aede267c69b0e8f 100644 (file)
@@ -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;
index a5b0df8e45caac7fe798fb530b39a425704b13bb..a2c04978b030ba619cd829afd5ed785b281b8ccb 100644 (file)
@@ -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();
index d0f02ae95bc12084e7623a7d4fabfabeb39d7c22..5d9b8bc7bbc134892e533e2decaa4f7fa5df4d49 100644 (file)
@@ -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());
index 3a9ec7ef6f95ba0558feef5eb6e7930d9746a830..44f4c27927b802c0ea0e2bb62e123cb2f2237d1e 100644 (file)
@@ -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<VectorType>(SrcType)) {
+  if (DstType->isExtVectorType() && !SrcType->isVectorType()) {
     // Cast the scalar to element type
     QualType EltTy = DstType->getAsExtVectorType()->getElementType();
     llvm::Value *Elt = EmitScalarConversion(Src, SrcType, EltTy);
index c933a2f320dc7682b4fe7e6c65720ac6ebccdef1..2101a85f4113c3e65e016cb657ab133bed781fef 100644 (file)
@@ -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();
     }
index 62bd9ae73ce02bdfd85733172574af4c2b74cc91..6e7deef95dc321866d4e4e7972bed93383e5837a 100644 (file)
@@ -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;
index 91b4d4d5a962ffeb43e8016a72482105cb191d2b..46526e47dd82f5e9fc4ed73db16d9dfc3005277b 100644 (file)
@@ -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);
   }
   
index 4f7ae7ec0d1e427e0d27b7c38f23b6bb6aab7c90..e183e3a49688dab980f0dfa4745149be961d1bda 100644 (file)
@@ -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,
index f00ab5412d32fba115ef733db2543ca1cb022f89..23e58de68c979bca75c50ddde386861d34f3e42c 100644 (file)
@@ -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<Expr>();
   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<ParenListExpr>(BaseExpr))
+    BaseExpr = ConvertParenListExpr(S, PE).takeAs<Expr>();
+  
   // 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<ParenListExpr>(Fn))
+    Fn = ConvertParenListExpr(S, PE).takeAs<Expr>();
 
   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<Expr>();
   QualType castType = QualType::getFromOpaquePtr(Ty);
+  
+  // If the Expr being casted is a ParenListExpr, handle it specially.
+  if (ParenListExpr *PE = dyn_cast<ParenListExpr>(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<Expr *, 8> 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<Expr>(), Ty,
+                                              LParenLoc, RParenLoc));
+  }
+}
+
+Action::OwningExprResult Sema::ActOnParenListExpr(SourceLocation L,
+                                                  SourceLocation R,
+                                                  MultiExprArg Val) {
+  unsigned nexprs = Val.size();
+  Expr **exprs = reinterpret_cast<Expr**>(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.
index 29113822f7303cc2db9ad99205db9ebf4f0b0092..1e564ce45fbbab04fffc0d576f23a384740a792d 100644 (file)
@@ -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;
   }
 }
 
index 186c98cf53eca53268599a9094ddd0d28f65af1b..7a09210fe048a5c5ff313e1b71eecdd74fb79d81 100644 (file)
@@ -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<Expr>());
+  }
+
+  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 (file)
index 0000000..6185186
--- /dev/null
@@ -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
+}
index e935baa27f3a87b7709982313f3209e51b848be1..a7cff1d1a27ae360ef9993983f84a1dff3199bc0 100644 (file)
@@ -385,6 +385,10 @@ OverflowChecking("ftrapv",
                  llvm::cl::desc("Trap on integer overflow"),
                  llvm::cl::init(false));
 
+static llvm::cl::opt<bool>
+AltiVec("faltivec", llvm::cl::desc("Enable AltiVec vector initializer syntax"),
+                    llvm::cl::init(false));
+
 static llvm::cl::opt<bool>
 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;
 }