forked from OSchip/llvm-project
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. llvm-svn: 78621
This commit is contained in:
parent
3b90d973b0
commit
5ec4b318e3
|
@ -2391,6 +2391,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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -91,6 +91,7 @@ EXPR(ExtVectorElementExpr , Expr)
|
|||
EXPR(InitListExpr , Expr)
|
||||
EXPR(DesignatedInitExpr , Expr)
|
||||
EXPR(ImplicitValueInitExpr , Expr)
|
||||
EXPR(ParenListExpr , Expr)
|
||||
EXPR(VAArgExpr , Expr)
|
||||
|
||||
// GNU Extensions.
|
||||
|
|
|
@ -2019,6 +2019,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">;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -475,7 +475,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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg ME);
|
||||
OwningExprResult ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
|
||||
SourceLocation RParenLoc, ExprArg E,
|
||||
QualType Ty);
|
||||
|
||||
virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
|
||||
TypeTy *Ty,
|
||||
|
|
|
@ -341,6 +341,9 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
|||
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");
|
||||
|
||||
|
|
|
@ -1620,6 +1620,8 @@ QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) {
|
|||
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 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
|
|||
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 @@ 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());
|
||||
|
||||
|
@ -2111,9 +2117,12 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
|||
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 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
|
|||
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 @@ 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;
|
||||
|
||||
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 @@ 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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -386,6 +386,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"
|
||||
|
@ -502,6 +506,9 @@ static void InitializeLangOptions(LangOptions &Options, LangKind LK){
|
|||
if (ObjCEnableGCBitmapPrint)
|
||||
Options.ObjCGCBitmapPrint = 1;
|
||||
|
||||
if (AltiVec)
|
||||
Options.AltiVec = 1;
|
||||
|
||||
Options.setVisibilityMode(SymbolVisibility);
|
||||
Options.OverflowChecking = OverflowChecking;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue