aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2009-08-09 17:55:44 +0000
committerNate Begeman <natebegeman@mac.com>2009-08-09 17:55:44 +0000
commit25b4fdb9d63095448e6cbc97b8865b36b0c8cbb6 (patch)
treea9a6eb7d4057c432773c1eaa5dd98b099aafc0a9
parent10c40eee98c600d24437474463b056f323d0cfd2 (diff)
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
-rw-r--r--include/clang/AST/Expr.h47
-rw-r--r--include/clang/AST/StmtNodes.def1
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--include/clang/Parse/Action.h13
-rw-r--r--include/clang/Parse/Parser.h7
-rw-r--r--lib/AST/Expr.cpp28
-rw-r--r--lib/AST/StmtPrinter.cpp9
-rw-r--r--lib/AST/StmtProfile.cpp4
-rw-r--r--lib/CodeGen/CGExprScalar.cpp2
-rw-r--r--lib/Frontend/PrintParserCallbacks.cpp5
-rw-r--r--lib/Parse/ParseExpr.cpp31
-rw-r--r--lib/Parse/ParseExprCXX.cpp5
-rw-r--r--lib/Sema/Sema.h16
-rw-r--r--lib/Sema/SemaExpr.cpp83
-rw-r--r--lib/Sema/SemaInit.cpp45
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp16
-rw-r--r--test/Sema/altivec-init.c16
-rw-r--r--tools/clang-cc/clang-cc.cpp7
18 files changed, 307 insertions, 31 deletions
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<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
//===----------------------------------------------------------------------===//
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<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);
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<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.
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
@@ -639,6 +639,20 @@ TemplateExprInstantiator::VisitInitListExpr(InitListExpr *E) {
}
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
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
@@ -386,6 +386,10 @@ OverflowChecking("ftrapv",
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"
"Objective-C messages"), llvm::cl::init(false));
@@ -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;
}