Take 2 on AltiVec-style vector initializers. 

Fixes PR4704 problems

Addresses Eli's patch feedback re: ugly cast code

Updates all postfix operators to remove ParenListExprs.  While this is awful,
no better solution (say, in the parser) is obvious to me.  Better solutions
welcome.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78621 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index b237ac3..b35fe67 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -50,6 +50,7 @@
   class Stmt;
   class Expr;
   class InitListExpr;
+  class ParenListExpr;
   class DesignatedInitExpr;
   class CallExpr;
   class DeclRefExpr;
@@ -1484,7 +1485,10 @@
   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 @@
                                          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 MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg ME);
+  OwningExprResult ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
+                                            SourceLocation RParenLoc, ExprArg E,
+                                            QualType Ty);
 
   virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
                                                 TypeTy *Ty,
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index e1cba36..977aa0f 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -341,6 +341,9 @@
 Action::OwningExprResult
 Sema::ActOnCXXEnterMemberScope(Scope *S, CXXScopeSpec &SS, ExprArg Base,
                                tok::TokenKind OpKind) {
+  // Since this might be a postfix expression, get rid of ParenListExprs.
+  Base = MaybeConvertParenListExprToParenExpr(S, move(Base));
+
   Expr *BaseExpr = (Expr*)Base.get();
   assert(BaseExpr && "no record expansion");
 
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index f00ab54..e9b1dd4 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1620,6 +1620,8 @@
 Action::OwningExprResult
 Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
                           tok::TokenKind Kind, ExprArg Input) {
+  // Since this might be a postfix expression, get rid of ParenListExprs.
+  Input = MaybeConvertParenListExprToParenExpr(S, move(Input));
   Expr *Arg = (Expr *)Input.get();
 
   UnaryOperator::Opcode Opc;
@@ -1738,9 +1740,12 @@
 Action::OwningExprResult
 Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,
                               ExprArg Idx, SourceLocation RLoc) {
+  // Since this might be a postfix expression, get rid of ParenListExprs.
+  Base = MaybeConvertParenListExprToParenExpr(S, move(Base));
+
   Expr *LHSExp = static_cast<Expr*>(Base.get()),
        *RHSExp = static_cast<Expr*>(Idx.get());
-
+  
   if (getLangOptions().CPlusPlus &&
       (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) {
     Base.release();
@@ -1918,7 +1923,8 @@
        << 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());
 
@@ -2111,9 +2117,12 @@
   if (SS && SS->isInvalid())
     return ExprError();
 
+  // Since this might be a postfix expression, get rid of ParenListExprs.
+  Base = MaybeConvertParenListExprToParenExpr(S, move(Base));
+
   Expr *BaseExpr = Base.takeAs<Expr>();
   assert(BaseExpr && "no record expression");
-
+  
   // Perform default conversions.
   DefaultFunctionArrayConversion(BaseExpr);
 
@@ -2683,13 +2692,17 @@
                     MultiExprArg args,
                     SourceLocation *CommaLocs, SourceLocation RParenLoc) {
   unsigned NumArgs = args.size();
+
+  // Since this might be a postfix expression, get rid of ParenListExprs.
+  fn = MaybeConvertParenListExprToParenExpr(S, move(fn));
+  
   Expr *Fn = fn.takeAs<Expr>();
   Expr **Args = reinterpret_cast<Expr**>(args.release());
   assert(Fn && "no function call expression");
   FunctionDecl *FDecl = NULL;
   NamedDecl *NDecl = NULL;
   DeclarationName UnqualifiedName;
-
+  
   if (getLangOptions().CPlusPlus) {
     // Determine whether this is a dependent call inside a C++ template,
     // in which case we won't do any semantic analysis now.
@@ -3090,24 +3103,92 @@
 }
 
 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;
   
   assert((Ty != 0) && (Op.get() != 0) &&
          "ActOnCastExpr(): missing type or expr");
 
-  Expr *castExpr = Op.takeAs<Expr>();
+  Expr *castExpr = (Expr *)Op.get();
   QualType castType = QualType::getFromOpaquePtr(Ty);
+  
+  // If the Expr being casted is a ParenListExpr, handle it specially.
+  if (isa<ParenListExpr>(castExpr))
+    return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, move(Op),castType);
 
   if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), castType, castExpr, 
                      Kind))
     return ExprError();
+  
+  Op.release();
   return Owned(new (Context) CStyleCastExpr(castType.getNonReferenceType(),
                                             Kind, castExpr, castType, 
                                             LParenLoc, RParenLoc));
 }
 
+/// This is not an AltiVec-style cast, so turn the ParenListExpr into a sequence
+/// of comma binary operators.
+Action::OwningExprResult
+Sema::MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg EA) {
+  Expr *expr = EA.takeAs<Expr>();
+  ParenListExpr *E = dyn_cast<ParenListExpr>(expr);
+  if (!E)
+    return Owned(expr);
+  
+  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 ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), move(Result));
+}
+
+Action::OwningExprResult
+Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
+                               SourceLocation RParenLoc, ExprArg Op,
+                               QualType Ty) {
+  ParenListExpr *PE = (ParenListExpr *)Op.get();
+  
+  // If this is an altivec initializer, '(' type ')' '(' init, ..., init ')' 
+  // then handle it as such.
+  if (getLangOptions().AltiVec && Ty->isVectorType()) {
+    if (PE->getNumExprs() == 0) {
+      Diag(PE->getExprLoc(), diag::err_altivec_empty_initializer);
+      return ExprError();
+    }
+
+    llvm::SmallVector<Expr *, 8> initExprs;
+    for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i)
+      initExprs.push_back(PE->getExpr(i));
+
+    // FIXME: This means that pretty-printing the final AST will produce curly
+    // braces instead of the original commas.
+    Op.release();
+    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.
+    Op = MaybeConvertParenListExprToParenExpr(S, move(Op));
+    return ActOnCastExpr(S, LParenLoc, Ty.getAsOpaquePtr(), RParenLoc,move(Op));
+  }
+}
+
+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 +3213,8 @@
   }
 
   // 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 2911382..1e564ce 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -805,16 +805,47 @@
                                       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 186c98c..7a09210 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -639,6 +639,20 @@
 }
 
 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 @@
   if (SubExpr.isInvalid())
     return SemaRef.ExprError();
   
-  return SemaRef.ActOnCastExpr(E->getLParenLoc(), 
+  return SemaRef.ActOnCastExpr(/*Scope=*/0, E->getLParenLoc(), 
                                ExplicitTy.getAsOpaquePtr(),
                                E->getRParenLoc(),
                                move(SubExpr));