forked from OSchip/llvm-project
parent
65c8a9ee9a
commit
9efdabc565
|
@ -487,6 +487,15 @@ void StmtPrinter::VisitTypesCompatibleExpr(TypesCompatibleExpr *Node) {
|
|||
OS << Node->getArgType2().getAsString() << ")";
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitChooseExpr(ChooseExpr *Node) {
|
||||
OS << "__builtin_choose_expr(";
|
||||
PrintExpr(Node->getCond());
|
||||
OS << ",";
|
||||
PrintExpr(Node->getLHS());
|
||||
OS << ",";
|
||||
PrintExpr(Node->getRHS());
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
// C++
|
||||
|
||||
|
|
|
@ -805,19 +805,35 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case tok::kw___builtin_choose_expr:
|
||||
Res = ParseAssignmentExpression();
|
||||
|
||||
case tok::kw___builtin_choose_expr: {
|
||||
ExprResult Cond = ParseAssignmentExpression();
|
||||
if (Cond.isInvalid) {
|
||||
SkipUntil(tok::r_paren);
|
||||
return Cond;
|
||||
}
|
||||
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
||||
return ExprResult(true);
|
||||
|
||||
Res = ParseAssignmentExpression();
|
||||
|
||||
ExprResult Expr1 = ParseAssignmentExpression();
|
||||
if (Expr1.isInvalid) {
|
||||
SkipUntil(tok::r_paren);
|
||||
return Expr1;
|
||||
}
|
||||
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
||||
return ExprResult(true);
|
||||
|
||||
Res = ParseAssignmentExpression();
|
||||
break;
|
||||
ExprResult Expr2 = ParseAssignmentExpression();
|
||||
if (Expr2.isInvalid) {
|
||||
SkipUntil(tok::r_paren);
|
||||
return Expr2;
|
||||
}
|
||||
if (Tok.getKind() != tok::r_paren) {
|
||||
Diag(Tok, diag::err_expected_rparen);
|
||||
return ExprResult(true);
|
||||
}
|
||||
return Actions.ParseChooseExpr(StartLoc, Cond.Val, Expr1.Val, Expr2.Val,
|
||||
ConsumeParen());
|
||||
}
|
||||
case tok::kw___builtin_types_compatible_p:
|
||||
TypeTy *Ty1 = ParseTypeName();
|
||||
|
||||
|
|
|
@ -285,6 +285,11 @@ public:
|
|||
virtual ExprResult ParseTypesCompatibleExpr(SourceLocation BuiltinLoc,
|
||||
TypeTy *arg1, TypeTy *arg2,
|
||||
SourceLocation RPLoc);
|
||||
|
||||
// __builtin_choose_expr(constExpr, expr1, expr2)
|
||||
virtual ExprResult ParseChooseExpr(SourceLocation BuiltinLoc,
|
||||
ExprTy *cond, ExprTy *expr1, ExprTy *expr2,
|
||||
SourceLocation RPLoc);
|
||||
|
||||
/// ParseCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
|
||||
virtual ExprResult ParseCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind,
|
||||
|
|
|
@ -1584,3 +1584,25 @@ Sema::ExprResult Sema::ParseTypesCompatibleExpr(SourceLocation BuiltinLoc,
|
|||
return new TypesCompatibleExpr(Context.IntTy, BuiltinLoc, argT1, argT2, RPLoc);
|
||||
}
|
||||
|
||||
Sema::ExprResult Sema::ParseChooseExpr(SourceLocation BuiltinLoc, ExprTy *cond,
|
||||
ExprTy *expr1, ExprTy *expr2,
|
||||
SourceLocation RPLoc) {
|
||||
Expr *CondExpr = static_cast<Expr*>(cond);
|
||||
Expr *LHSExpr = static_cast<Expr*>(expr1);
|
||||
Expr *RHSExpr = static_cast<Expr*>(expr2);
|
||||
|
||||
assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)");
|
||||
|
||||
// The conditional expression is required to be a constant expression.
|
||||
llvm::APSInt condEval(32);
|
||||
SourceLocation ExpLoc;
|
||||
if (!CondExpr->isIntegerConstantExpr(condEval, Context, &ExpLoc))
|
||||
return Diag(ExpLoc, diag::err_typecheck_choose_expr_requires_constant,
|
||||
CondExpr->getSourceRange());
|
||||
|
||||
// If the condition is > zero, then the AST type is the same as the LSHExpr.
|
||||
QualType resType = condEval.getZExtValue() ? LHSExpr->getType() :
|
||||
RHSExpr->getType();
|
||||
return new ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, resType, RPLoc);
|
||||
}
|
||||
|
||||
|
|
|
@ -776,6 +776,35 @@ public:
|
|||
static bool classof(const TypesCompatibleExpr *) { return true; }
|
||||
};
|
||||
|
||||
/// ChooseExpr - GNU builtin-in function __builtin_choose_expr.
|
||||
/// This AST node is similar to the conditional operator (?:) in C, with
|
||||
/// the following exceptions:
|
||||
/// - the test expression much be a constant expression.
|
||||
/// - the expression returned has it's type unaltered by promotion rules.
|
||||
/// - does not evaluate the expression that was not chosen.
|
||||
class ChooseExpr : public Expr {
|
||||
Expr *Cond, *LHS, *RHS; // First, second, and third arguments.
|
||||
SourceLocation BuiltinLoc, RParenLoc;
|
||||
public:
|
||||
ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, QualType t,
|
||||
SourceLocation RP)
|
||||
: Expr(ChooseExprClass, t),
|
||||
Cond(cond), LHS(lhs), RHS(rhs), BuiltinLoc(BLoc), RParenLoc(RP) {}
|
||||
|
||||
Expr *getCond() const { return Cond; }
|
||||
Expr *getLHS() const { return LHS; }
|
||||
Expr *getRHS() const { return RHS; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(BuiltinLoc, RParenLoc);
|
||||
}
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == ChooseExprClass;
|
||||
}
|
||||
static bool classof(const ChooseExpr *) { return true; }
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
@ -68,11 +68,12 @@ STMT(49, OCUVectorElementExpr , Expr)
|
|||
STMT(50, AddrLabelExpr , Expr)
|
||||
STMT(51, StmtExpr , Expr)
|
||||
STMT(52, TypesCompatibleExpr , Expr)
|
||||
STMT(53, ChooseExpr , Expr)
|
||||
|
||||
// C++ Expressions.
|
||||
STMT(53, CXXCastExpr , Expr)
|
||||
STMT(54, CXXBoolLiteralExpr , Expr)
|
||||
LAST_EXPR(54)
|
||||
STMT(54, CXXCastExpr , Expr)
|
||||
STMT(55, CXXBoolLiteralExpr , Expr)
|
||||
LAST_EXPR(55)
|
||||
|
||||
#undef STMT
|
||||
#undef FIRST_STMT
|
||||
|
|
|
@ -652,7 +652,8 @@ DIAG(err_typecheck_cond_incompatible_operands, ERROR,
|
|||
"incompatible operand types ('%0' and '%1')")
|
||||
DIAG(ext_typecheck_cond_incompatible_pointers, WARNING,
|
||||
"pointer type mismatch ('%0' and '%1')")
|
||||
|
||||
DIAG(err_typecheck_choose_expr_requires_constant, ERROR,
|
||||
"'__builtin_choose_expr' requires a constant expression")
|
||||
DIAG(warn_unused_expr, WARNING,
|
||||
"expression result unused")
|
||||
|
||||
|
|
|
@ -381,6 +381,12 @@ public:
|
|||
SourceLocation RPLoc) {
|
||||
return 0;
|
||||
}
|
||||
// __builtin_choose_expr(constExpr, expr1, expr2)
|
||||
virtual ExprResult ParseChooseExpr(SourceLocation BuiltinLoc,
|
||||
ExprTy *cond, ExprTy *expr1, ExprTy *expr2,
|
||||
SourceLocation RPLoc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===------------------------- C++ Expressions --------------------------===//
|
||||
|
||||
|
|
|
@ -31,5 +31,14 @@ static void test()
|
|||
func_choose(a);
|
||||
func_choose(b);
|
||||
func_choose(d);
|
||||
|
||||
int c;
|
||||
struct xx { int a; } x, y;
|
||||
|
||||
c = __builtin_choose_expr(a+3-7, b, x); // expected-error{{'__builtin_choose_expr' requires a constant expression}}
|
||||
c = __builtin_choose_expr(0, b, x); // expected-error{{incompatible types assigning 'struct xx' to 'int'}}
|
||||
c = __builtin_choose_expr(5+3-7, b, x);
|
||||
y = __builtin_choose_expr(4+3-7, b, x);
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue