forked from OSchip/llvm-project
Bug #:
Submitted by: Reviewed by: - Added Type::isPromotableIntegerType(). - The unary operators are now largely complete (Sema::ParseUnaryOp and friends). - Implemented ImplicitConversion hook (was a stub). llvm-svn: 39409
This commit is contained in:
parent
4750051ebb
commit
4b7ce03f55
|
@ -180,9 +180,42 @@ Action::ExprResult Sema::ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
|
|||
return CheckAddressOfOperand((Expr *)Input, OpLoc, Opc);
|
||||
else if (Opc == UnaryOperator::Deref)
|
||||
return CheckIndirectionOperand((Expr *)Input, OpLoc, Opc);
|
||||
|
||||
// when all the check functions are written, this will go away...
|
||||
return new UnaryOperator((Expr*)Input, Opc, QualType());
|
||||
else {
|
||||
// handle the arithmetic unary operators (C99 6.5.3.3)
|
||||
QualType opType = ImplicitConversion((Expr *)Input)->getType();
|
||||
assert(!opType.isNull() && "no type for arithmetic unary expression");
|
||||
QualType resultType = opType;
|
||||
|
||||
switch (Opc) {
|
||||
case UnaryOperator::Plus:
|
||||
case UnaryOperator::Minus:
|
||||
if (!opType->isArithmeticType()) // C99 6.5.3.3p1
|
||||
return Diag(OpLoc, diag::err_typecheck_unary_expr, opType);
|
||||
|
||||
if (opType->isPromotableIntegerType()) // C99 6.5.3.3p2
|
||||
resultType = Context.IntTy;
|
||||
break;
|
||||
case UnaryOperator::Not: // bitwise complement
|
||||
if (!opType->isIntegralType()) // C99 6.5.3.3p1
|
||||
return Diag(OpLoc, diag::err_typecheck_unary_expr, opType);
|
||||
|
||||
if (opType->isPromotableIntegerType()) // C99 6.5.3.3p2
|
||||
resultType = Context.IntTy;
|
||||
break;
|
||||
case UnaryOperator::LNot: // logical negation
|
||||
if (!opType->isScalarType()) // C99 6.5.3.3p1
|
||||
return Diag(OpLoc, diag::err_typecheck_unary_expr, opType);
|
||||
|
||||
if (opType->isPromotableIntegerType()) // C99 6.5.3.3p2
|
||||
resultType = Context.IntTy;
|
||||
break;
|
||||
case UnaryOperator::SizeOf: // C99 6.5.3.4 TODO
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return new UnaryOperator((Expr*)Input, Opc, resultType);
|
||||
}
|
||||
}
|
||||
|
||||
Action::ExprResult Sema::
|
||||
|
@ -392,12 +425,21 @@ Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc,
|
|||
return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS);
|
||||
}
|
||||
|
||||
/// ImplicitConversion - Performs various conversions that are common to most
|
||||
/// operators. At present, this routine only handles conversions that require
|
||||
/// synthesizing an expression/type. Arithmetic type promotions are done locally,
|
||||
/// since they don't require a new expression.
|
||||
Expr *Sema::ImplicitConversion(Expr *E) {
|
||||
#if 0
|
||||
QualType t = E->getType();
|
||||
if (t != 0) t.dump();
|
||||
else printf("no type for expr %s\n", E->getStmtClassName());
|
||||
#endif
|
||||
assert(!t.isNull() && "no type for implicit conversion");
|
||||
|
||||
if (t->isFunctionType()) // C99 6.3.2.1p4
|
||||
return new UnaryOperator(E, UnaryOperator::AddrOf, Context.getPointerType(t));
|
||||
else if (t->isArrayType()) { // C99 6.3.2.1p3
|
||||
QualType elt = cast<ArrayType>(t)->getElementType();
|
||||
QualType convertedType = Context.getPointerType(elt);
|
||||
return new UnaryOperator(E, UnaryOperator::AddrOf, convertedType);
|
||||
}
|
||||
return E;
|
||||
}
|
||||
|
||||
|
|
|
@ -199,6 +199,24 @@ bool Type::isLvalue() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Type::isPromotableIntegerType() const {
|
||||
if (CanonicalType->getTypeClass() == Builtin) {
|
||||
const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType.getTypePtr());
|
||||
switch (BT->getKind()) {
|
||||
case BuiltinType::Bool:
|
||||
case BuiltinType::Char:
|
||||
case BuiltinType::SChar:
|
||||
case BuiltinType::UChar:
|
||||
case BuiltinType::Short:
|
||||
case BuiltinType::UShort:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type,
|
||||
/// does not have an incomplete type, does not have a const-qualified type, and
|
||||
/// if it is a structure or union, does not have any member (including,
|
||||
|
|
|
@ -180,9 +180,42 @@ Action::ExprResult Sema::ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
|
|||
return CheckAddressOfOperand((Expr *)Input, OpLoc, Opc);
|
||||
else if (Opc == UnaryOperator::Deref)
|
||||
return CheckIndirectionOperand((Expr *)Input, OpLoc, Opc);
|
||||
|
||||
// when all the check functions are written, this will go away...
|
||||
return new UnaryOperator((Expr*)Input, Opc, QualType());
|
||||
else {
|
||||
// handle the arithmetic unary operators (C99 6.5.3.3)
|
||||
QualType opType = ImplicitConversion((Expr *)Input)->getType();
|
||||
assert(!opType.isNull() && "no type for arithmetic unary expression");
|
||||
QualType resultType = opType;
|
||||
|
||||
switch (Opc) {
|
||||
case UnaryOperator::Plus:
|
||||
case UnaryOperator::Minus:
|
||||
if (!opType->isArithmeticType()) // C99 6.5.3.3p1
|
||||
return Diag(OpLoc, diag::err_typecheck_unary_expr, opType);
|
||||
|
||||
if (opType->isPromotableIntegerType()) // C99 6.5.3.3p2
|
||||
resultType = Context.IntTy;
|
||||
break;
|
||||
case UnaryOperator::Not: // bitwise complement
|
||||
if (!opType->isIntegralType()) // C99 6.5.3.3p1
|
||||
return Diag(OpLoc, diag::err_typecheck_unary_expr, opType);
|
||||
|
||||
if (opType->isPromotableIntegerType()) // C99 6.5.3.3p2
|
||||
resultType = Context.IntTy;
|
||||
break;
|
||||
case UnaryOperator::LNot: // logical negation
|
||||
if (!opType->isScalarType()) // C99 6.5.3.3p1
|
||||
return Diag(OpLoc, diag::err_typecheck_unary_expr, opType);
|
||||
|
||||
if (opType->isPromotableIntegerType()) // C99 6.5.3.3p2
|
||||
resultType = Context.IntTy;
|
||||
break;
|
||||
case UnaryOperator::SizeOf: // C99 6.5.3.4 TODO
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return new UnaryOperator((Expr*)Input, Opc, resultType);
|
||||
}
|
||||
}
|
||||
|
||||
Action::ExprResult Sema::
|
||||
|
@ -392,12 +425,21 @@ Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc,
|
|||
return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS);
|
||||
}
|
||||
|
||||
/// ImplicitConversion - Performs various conversions that are common to most
|
||||
/// operators. At present, this routine only handles conversions that require
|
||||
/// synthesizing an expression/type. Arithmetic type promotions are done locally,
|
||||
/// since they don't require a new expression.
|
||||
Expr *Sema::ImplicitConversion(Expr *E) {
|
||||
#if 0
|
||||
QualType t = E->getType();
|
||||
if (t != 0) t.dump();
|
||||
else printf("no type for expr %s\n", E->getStmtClassName());
|
||||
#endif
|
||||
assert(!t.isNull() && "no type for implicit conversion");
|
||||
|
||||
if (t->isFunctionType()) // C99 6.3.2.1p4
|
||||
return new UnaryOperator(E, UnaryOperator::AddrOf, Context.getPointerType(t));
|
||||
else if (t->isArrayType()) { // C99 6.3.2.1p3
|
||||
QualType elt = cast<ArrayType>(t)->getElementType();
|
||||
QualType convertedType = Context.getPointerType(elt);
|
||||
return new UnaryOperator(E, UnaryOperator::AddrOf, convertedType);
|
||||
}
|
||||
return E;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,8 +51,6 @@ namespace clang {
|
|||
CXXBoolLiteralExpr(bool val) :
|
||||
Expr(CXXBoolLiteralExprClass, QualType()), Value(val) {}
|
||||
|
||||
virtual Expr *getPrimaryExpr() { return this; }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
};
|
||||
|
||||
|
|
|
@ -226,6 +226,9 @@ public:
|
|||
bool isAggregateType() const; // C99 6.2.5p21 (arrays, structures)
|
||||
|
||||
bool isLvalue() const; // C99 6.3.2.1
|
||||
|
||||
/// Type Conversions/Promotions
|
||||
bool isPromotableIntegerType() const; // C99 6.3.1.1p2
|
||||
private:
|
||||
// this forces clients to use isModifiableLvalue on QualType, the class that
|
||||
// knows if the type is const. This predicate is a helper to QualType.
|
||||
|
|
|
@ -533,6 +533,8 @@ DIAG(err_typecheck_address_of_register, ERROR,
|
|||
"address of register variable requested")
|
||||
DIAG(err_typecheck_invalid_lvalue_addrof, ERROR,
|
||||
"invalid lvalue in address expression")
|
||||
DIAG(err_typecheck_unary_expr, ERROR,
|
||||
"invalid argument type to unary expression '%s'")
|
||||
|
||||
// Statements.
|
||||
DIAG(err_continue_not_in_loop, ERROR,
|
||||
|
|
Loading…
Reference in New Issue