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:
Steve Naroff 2007-04-20 22:26:17 +00:00
parent 4750051ebb
commit 4b7ce03f55
6 changed files with 121 additions and 16 deletions

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -51,8 +51,6 @@ namespace clang {
CXXBoolLiteralExpr(bool val) :
Expr(CXXBoolLiteralExprClass, QualType()), Value(val) {}
virtual Expr *getPrimaryExpr() { return this; }
virtual void visit(StmtVisitor &Visitor);
};

View File

@ -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.

View File

@ -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,