[cfe-commits] r39418 - in /cfe/cfe/trunk: AST/ASTContext.cpp AST/SemaExpr.cpp Driver/clang.cpp Sema/SemaExpr.cpp include/clang/AST/ASTContext.h include/clang/AST/Expr.h include/clang/Basic/DiagnosticKinds.def
Steve Naroff
snaroff at apple.com
Wed Jul 11 09:44:09 PDT 2007
Author: snaroff
Date: Wed Jul 11 11:44:08 2007
New Revision: 39418
URL: http://llvm.org/viewvc/llvm-project?rev=39418&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
More typechecking, refactoring...
- Implemented the following routines...CheckAdditiveOperands,
CheckCommaOperands, CheckLogicalOperands.
- Added maxComplexType, maxFloatingType, & maxIntegerType to ASTContext.
Ranking helper functions moved to ASTContext as well (they are private:-)
- Simplified UsualArithmeticConversions using the new ASTContext hooks.
- Fixed isAssignmentOp()...is was preventing comma exprs from ever being created:-(
- Changed a GCC compat extension to truly be an extension (and turned extensions
on by default). This now produces a warning by default.
Modified:
cfe/cfe/trunk/AST/ASTContext.cpp
cfe/cfe/trunk/AST/SemaExpr.cpp
cfe/cfe/trunk/Driver/clang.cpp
cfe/cfe/trunk/Sema/SemaExpr.cpp
cfe/cfe/trunk/include/clang/AST/ASTContext.h
cfe/cfe/trunk/include/clang/AST/Expr.h
cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
Modified: cfe/cfe/trunk/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/ASTContext.cpp?rev=39418&r1=39417&r2=39418&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/ASTContext.cpp (original)
+++ cfe/cfe/trunk/AST/ASTContext.cpp Wed Jul 11 11:44:08 2007
@@ -293,3 +293,116 @@
return UnsignedLongTy;
}
+/// getIntegerRank - Helper function for UsualArithmeticConversions().
+int ASTContext::getIntegerRank(QualType t) {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
+ switch (BT->getKind()) {
+ case BuiltinType::SChar:
+ case BuiltinType::UChar:
+ return 1;
+ case BuiltinType::Short:
+ case BuiltinType::UShort:
+ return 2;
+ case BuiltinType::Int:
+ case BuiltinType::UInt:
+ return 3;
+ case BuiltinType::Long:
+ case BuiltinType::ULong:
+ return 4;
+ case BuiltinType::LongLong:
+ case BuiltinType::ULongLong:
+ return 5;
+ default:
+ assert(0 && "GetIntegerRank(): not an integer type");
+ }
+ }
+ return 0;
+}
+
+/// getFloatingRank - Helper function for UsualArithmeticConversions().
+int ASTContext::getFloatingRank(QualType t) {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
+ switch (BT->getKind()) {
+ case BuiltinType::Float:
+ case BuiltinType::FloatComplex:
+ return 1;
+ case BuiltinType::Double:
+ case BuiltinType::DoubleComplex:
+ return 2;
+ case BuiltinType::LongDouble:
+ case BuiltinType::LongDoubleComplex:
+ return 3;
+ default:
+ assert(0 && "getFloatingPointRank(): not a floating type");
+ }
+ }
+ return 0;
+}
+
+QualType ASTContext::convertSignedWithGreaterRankThanUnsigned(
+ QualType signedType, QualType unsignedType) {
+ // FIXME: Need to check if the signed type can represent all values of the
+ // unsigned type. If it can, then the result is the signed type. If it can't,
+ // then the result is the unsigned version of the signed type.
+ return signedType;
+}
+
+
+/// ConvertFloatingRankToComplexType - Another helper for converting floats.
+QualType ASTContext::convertFloatingRankToComplexType(int rank) {
+ switch (rank) {
+ case 1:
+ return FloatComplexTy;
+ case 2:
+ return DoubleComplexTy;
+ case 3:
+ return LongDoubleComplexTy;
+ default:
+ assert(0 && "convertRankToComplex(): illegal value for rank");
+ }
+}
+
+// maxComplexType - the following code handles 3 different combinations:
+// complex/complex, complex/float, float/complex.
+// When both operands are complex, the shorter operand is converted to the
+// type of the longer, and that is the type of the result. This corresponds
+// to what is done when combining two real floating-point operands.
+// The fun begins when size promotion occur across type domains. g
+// getFloatingRank & convertFloatingRankToComplexType handle this without
+// enumerating all permutations.
+// It also allows us to add new types without breakage.
+// From H&S 6.3.4: When one operand is complex and the other is a real
+// floating-point type, the less precise type is converted, within it's
+// real or complex domain, to the precision of the other type. For example,
+// when combining a "long double" with a "double _Complex", the
+// "double _Complex" is promoted to "long double _Complex".
+
+QualType ASTContext::maxComplexType(QualType lt, QualType rt) {
+ int lhsRank = getFloatingRank(lt);
+ int rhsRank = getFloatingRank(rt);
+
+ return convertFloatingRankToComplexType(std::max(lhsRank, rhsRank));
+}
+
+// maxFloatingType - handles the simple case, both operands are floats.
+QualType ASTContext::maxFloatingType(QualType lt, QualType rt) {
+ return getFloatingRank(lt) > getFloatingRank(rt) ? lt : rt;
+}
+
+QualType ASTContext::maxIntegerType(QualType lhs, QualType rhs) {
+ // Lastly, handle two integers (C99 6.3.1.8p1)
+ bool t1Unsigned = lhs->isUnsignedIntegerType();
+ bool t2Unsigned = rhs->isUnsignedIntegerType();
+
+ if ((t1Unsigned && t2Unsigned) || (!t1Unsigned && !t2Unsigned))
+ return getIntegerRank(lhs) >= getIntegerRank(rhs) ? lhs : rhs;
+
+ // We have two integer types with differing signs
+ QualType unsignedType = t1Unsigned ? lhs : rhs;
+ QualType signedType = t1Unsigned ? rhs : lhs;
+
+ if (getIntegerRank(unsignedType) >= getIntegerRank(signedType))
+ return unsignedType;
+ else
+ return convertSignedWithGreaterRankThanUnsigned(signedType, unsignedType);
+}
Modified: cfe/cfe/trunk/AST/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaExpr.cpp?rev=39418&r1=39417&r2=39418&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:44:08 2007
@@ -25,6 +25,12 @@
using namespace llvm;
using namespace clang;
+// Sema.h avoids including Expr.h. As a result, all the Check* functions take
+// an unsigned which is really an enum. These typedefs provide a short hand
+// notiation for casting (to keep the lines within 80 columns:-)
+typedef BinaryOperator::Opcode BOP;
+typedef UnaryOperator::Opcode UOP;
+
/// ParseStringLiteral - The specified tokens were lexed as pasted string
/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string
/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
@@ -88,8 +94,7 @@
switch (Kind) {
default:
assert(0 && "Unknown simple primary expr!");
- case tok::char_constant: // constant: character-constant
- // TODO: MOVE this to be some other callback.
+ // TODO: MOVE this to be some other callback.
case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
@@ -411,7 +416,7 @@
return CheckAssignmentOperands(lhs, rhs, TokLoc, Opc);
else if (Opc == BinaryOperator::Comma)
return CheckCommaOperands(lhs, rhs, TokLoc);
-
+
assert(0 && "ParseBinOp(): illegal binary op");
}
@@ -427,7 +432,7 @@
assert(!lhs.isNull() && "ParseConditionalOp(): no lhs type");
assert(!rhs.isNull() && "ParseConditionalOp(): no rhs type");
- QualType canonType = rhs.getCanonicalType(); // TEMPORARY
+ QualType canonType = rhs.getCanonicalType(); // FIXME
return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, canonType);
}
@@ -448,75 +453,6 @@
return t;
}
-/// GetIntegerRank - Helper function for UsualArithmeticConversions().
-static inline int GetIntegerRank(QualType t) {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
- switch (BT->getKind()) {
- case BuiltinType::SChar:
- case BuiltinType::UChar:
- return 1;
- case BuiltinType::Short:
- case BuiltinType::UShort:
- return 2;
- case BuiltinType::Int:
- case BuiltinType::UInt:
- return 3;
- case BuiltinType::Long:
- case BuiltinType::ULong:
- return 4;
- case BuiltinType::LongLong:
- case BuiltinType::ULongLong:
- return 5;
- default:
- assert(0 && "getFloatingPointRank(): not a floating type");
- }
- }
- return 0;
-}
-
-static inline QualType ConvertSignedWithGreaterRankThanUnsigned(
- QualType signedType, QualType unsignedType) {
- // FIXME: Need to check if the signed type can represent all values of the
- // unsigned type. If it can, then the result is the signed type. If it can't,
- // then the result is the unsigned version of the signed type.
- return signedType;
-}
-
-/// GetFloatingRank - Helper function for UsualArithmeticConversions().
-static inline int GetFloatingRank(QualType t) {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
- switch (BT->getKind()) {
- case BuiltinType::Float:
- case BuiltinType::FloatComplex:
- return 1;
- case BuiltinType::Double:
- case BuiltinType::DoubleComplex:
- return 2;
- case BuiltinType::LongDouble:
- case BuiltinType::LongDoubleComplex:
- return 3;
- default:
- assert(0 && "getFloatingPointRank(): not a floating type");
- }
- }
- return 0;
-}
-
-/// ConvertFloatingRankToComplexType - Another helper for converting floats.
-static inline QualType ConvertFloatingRankToComplexType(int rank,
- ASTContext &C) {
- switch (rank) {
- case 1:
- return C.FloatComplexTy;
- case 2:
- return C.DoubleComplexTy;
- case 3:
- return C.LongDoubleComplexTy;
- default:
- assert(0 && "convertRankToComplex(): illegal value for rank");
- }
-}
-
/// UsualArithmeticConversions - Performs various conversions that are common to
/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
/// routine returns the first non-arithmetic type found. The client is
@@ -545,23 +481,7 @@
if (lhs->isIntegerType())
return rhs;
- // the following code handles three different combinations:
- // complex/complex, complex/float, float/complex. When both operands
- // are complex, the shorter operand is converted to the type of the longer,
- // and that is the type of the result. This corresponds to what is done
- // when combining two real floating-point operands. The fun begins when
- // size promotion occur across type domains. GetFloatingRank &
- // ConvertFloatingRankToComplexType handle this without enumerating all
- // permutations. It also allows us to add new types without breakage.
- int lhsRank = GetFloatingRank(lhs);
- int rhsRank = GetFloatingRank(rhs);
-
- // From H&S 6.3.4: When one operand is complex and the other is a real
- // floating-point type, the less precise type is converted, within it's
- // real or complex domain, to the precision of the other type. For example,
- // when combining a "long double" with a "double _Complex", the
- // "double _Complex" is promoted to "long double _Complex".
- return ConvertFloatingRankToComplexType(std::max(lhsRank,rhsRank), Context);
+ return Context.maxComplexType(lhs, rhs);
}
// Now handle "real" floating types (i.e. float, double, long double).
if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
@@ -572,23 +492,9 @@
return rhs;
// we have two real floating types, float/complex combos were handled above.
- return GetFloatingRank(lhs) >= GetFloatingRank(rhs) ? lhs : rhs;
+ return Context.maxFloatingType(lhs, rhs);
}
- // Lastly, handle two integers (C99 6.3.1.8p1)
- bool t1Unsigned = lhs->isUnsignedIntegerType();
- bool t2Unsigned = rhs->isUnsignedIntegerType();
-
- if ((t1Unsigned && t2Unsigned) || (!t1Unsigned && !t2Unsigned))
- return GetIntegerRank(lhs) >= GetIntegerRank(rhs) ? lhs : rhs;
-
- // We have two integer types with differing signs
- QualType unsignedType = t1Unsigned ? lhs : rhs;
- QualType signedType = t1Unsigned ? rhs : lhs;
-
- if (GetIntegerRank(unsignedType) >= GetIntegerRank(signedType))
- return unsignedType;
- else
- return ConvertSignedWithGreaterRankThanUnsigned(signedType, unsignedType);
+ return Context.maxIntegerType(lhs, rhs);
}
Action::ExprResult Sema::CheckMultiplicativeOperands(
@@ -596,21 +502,37 @@
{
QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType());
- if ((BinaryOperator::Opcode)code == BinaryOperator::Rem) {
+ if ((BOP)code == BinaryOperator::Rem) {
if (!resType->isIntegerType())
return Diag(loc, diag::err_typecheck_invalid_operands);
} else { // *, /
if (!resType->isArithmeticType())
return Diag(loc, diag::err_typecheck_invalid_operands);
}
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
+ return new BinaryOperator(lex, rex, (BOP)code, resType);
}
Action::ExprResult Sema::CheckAdditiveOperands( // C99 6.5.6
Expr *lex, Expr *rex, SourceLocation loc, unsigned code)
{
- // FIXME: add type checking and fix result type
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
+ QualType lhsType = lex->getType(), rhsType = rex->getType();
+ QualType resType = UsualArithmeticConversions(lhsType, rhsType);
+
+ // handle the common case first (both operands are arithmetic).
+ if (resType->isArithmeticType())
+ return new BinaryOperator(lex, rex, (BOP)code, resType);
+ else {
+ if ((BOP)code == BinaryOperator::Add) {
+ if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
+ (lhsType->isIntegerType() && rhsType->isPointerType()))
+ return new BinaryOperator(lex, rex, (BOP)code, resType);
+ } else { // -
+ if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
+ (lhsType->isPointerType() && rhsType->isPointerType()))
+ return new BinaryOperator(lex, rex, (BOP)code, resType);
+ }
+ }
+ return Diag(loc, diag::err_typecheck_invalid_operands);
}
Action::ExprResult Sema::CheckShiftOperands( // C99 6.5.7
@@ -621,7 +543,7 @@
if (!resType->isIntegerType())
return Diag(loc, diag::err_typecheck_invalid_operands);
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
+ return new BinaryOperator(lex, rex, (BOP)code, resType);
}
Action::ExprResult Sema::CheckRelationalOperands( // C99 6.5.8
@@ -630,17 +552,14 @@
QualType lType = lex->getType(), rType = rex->getType();
if (lType->isRealType() && rType->isRealType())
- ;
- else if (lType->isPointerType() && rType->isPointerType())
- ;
- else {
- // The following test is for GCC compatibility.
- if (lType->isIntegerType() || rType->isIntegerType())
- return Diag(loc, diag::err_typecheck_comparison_of_pointer_integer);
- return Diag(loc, diag::err_typecheck_invalid_operands);
- }
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code,
- Context.IntTy);
+ return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+
+ if (lType->isPointerType() && rType->isPointerType())
+ return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+
+ if (lType->isIntegerType() || rType->isIntegerType()) // GCC extension.
+ return Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
+ return Diag(loc, diag::err_typecheck_invalid_operands);
}
Action::ExprResult Sema::CheckEqualityOperands( // C99 6.5.9
@@ -649,17 +568,14 @@
QualType lType = lex->getType(), rType = rex->getType();
if (lType->isArithmeticType() && rType->isArithmeticType())
- ;
- else if (lType->isPointerType() && rType->isPointerType())
- ;
- else {
- // The following test is for GCC compatibility.
- if (lType->isIntegerType() || rType->isIntegerType())
- return Diag(loc, diag::err_typecheck_comparison_of_pointer_integer);
- return Diag(loc, diag::err_typecheck_invalid_operands);
- }
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code,
- Context.IntTy);
+ return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+
+ if (lType->isPointerType() && rType->isPointerType())
+ return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+
+ if (lType->isIntegerType() || rType->isIntegerType()) // GCC extension.
+ return Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
+ return Diag(loc, diag::err_typecheck_invalid_operands);
}
Action::ExprResult Sema::CheckBitwiseOperands(
@@ -670,28 +586,33 @@
if (!resType->isIntegerType())
return Diag(loc, diag::err_typecheck_invalid_operands);
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
+ return new BinaryOperator(lex, rex, (BOP)code, resType);
}
Action::ExprResult Sema::CheckLogicalOperands( // C99 6.5.[13,14]
Expr *lex, Expr *rex, SourceLocation loc, unsigned code)
{
- // FIXME: add type checking and fix result type
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
+ QualType lhsType = UsualUnaryConversion(lex->getType());
+ QualType rhsType = UsualUnaryConversion(rex->getType());
+
+ if (!lhsType->isScalarType() || !rhsType->isScalarType())
+ return Diag(loc, diag::err_typecheck_invalid_operands);
+
+ return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
}
Action::ExprResult Sema::CheckAssignmentOperands( // C99 6.5.16
Expr *lex, Expr *rex, SourceLocation loc, unsigned code)
{
// FIXME: add type checking and fix result type
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
+ return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
}
Action::ExprResult Sema::CheckCommaOperands( // C99 6.5.17
Expr *lex, Expr *rex, SourceLocation loc)
{
- // FIXME: add type checking and fix result type
- return new BinaryOperator(lex, rex, BinaryOperator::Comma, Context.IntTy);
+ QualType rhsType = UsualUnaryConversion(rex->getType());
+ return new BinaryOperator(lex, rex, BinaryOperator::Comma, rhsType);
}
Action::ExprResult
@@ -717,7 +638,7 @@
if (!canonType.isModifiableLvalue())
return Diag(OpLoc, diag::err_typecheck_not_modifiable, qType);
- return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, qType);
+ return new UnaryOperator(op, (UOP)OpCode, qType);
}
/// getPrimaryDeclaration - Helper function for CheckAddressOfOperand().
@@ -806,5 +727,5 @@
return Diag(OpLoc, diag::err_typecheck_unary_expr, resultType);
break;
}
- return new UnaryOperator(op, (UnaryOperator::Opcode)Opc, resultType);
+ return new UnaryOperator(op, (UOP)Opc, resultType);
}
Modified: cfe/cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Driver/clang.cpp?rev=39418&r1=39417&r2=39418&view=diff
==============================================================================
--- cfe/cfe/trunk/Driver/clang.cpp (original)
+++ cfe/cfe/trunk/Driver/clang.cpp Wed Jul 11 11:44:08 2007
@@ -299,7 +299,7 @@
WarningsAsErrors("Werror", cl::desc("Treat all warnings as errors"));
static cl::opt<bool>
-WarnOnExtensions("pedantic",
+WarnOnExtensions("pedantic", cl::init(true),
cl::desc("Issue a warning on uses of GCC extensions"));
static cl::opt<bool>
Modified: cfe/cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaExpr.cpp?rev=39418&r1=39417&r2=39418&view=diff
==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:44:08 2007
@@ -25,6 +25,12 @@
using namespace llvm;
using namespace clang;
+// Sema.h avoids including Expr.h. As a result, all the Check* functions take
+// an unsigned which is really an enum. These typedefs provide a short hand
+// notiation for casting (to keep the lines within 80 columns:-)
+typedef BinaryOperator::Opcode BOP;
+typedef UnaryOperator::Opcode UOP;
+
/// ParseStringLiteral - The specified tokens were lexed as pasted string
/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string
/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
@@ -88,8 +94,7 @@
switch (Kind) {
default:
assert(0 && "Unknown simple primary expr!");
- case tok::char_constant: // constant: character-constant
- // TODO: MOVE this to be some other callback.
+ // TODO: MOVE this to be some other callback.
case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
@@ -411,7 +416,7 @@
return CheckAssignmentOperands(lhs, rhs, TokLoc, Opc);
else if (Opc == BinaryOperator::Comma)
return CheckCommaOperands(lhs, rhs, TokLoc);
-
+
assert(0 && "ParseBinOp(): illegal binary op");
}
@@ -427,7 +432,7 @@
assert(!lhs.isNull() && "ParseConditionalOp(): no lhs type");
assert(!rhs.isNull() && "ParseConditionalOp(): no rhs type");
- QualType canonType = rhs.getCanonicalType(); // TEMPORARY
+ QualType canonType = rhs.getCanonicalType(); // FIXME
return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, canonType);
}
@@ -448,75 +453,6 @@
return t;
}
-/// GetIntegerRank - Helper function for UsualArithmeticConversions().
-static inline int GetIntegerRank(QualType t) {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
- switch (BT->getKind()) {
- case BuiltinType::SChar:
- case BuiltinType::UChar:
- return 1;
- case BuiltinType::Short:
- case BuiltinType::UShort:
- return 2;
- case BuiltinType::Int:
- case BuiltinType::UInt:
- return 3;
- case BuiltinType::Long:
- case BuiltinType::ULong:
- return 4;
- case BuiltinType::LongLong:
- case BuiltinType::ULongLong:
- return 5;
- default:
- assert(0 && "getFloatingPointRank(): not a floating type");
- }
- }
- return 0;
-}
-
-static inline QualType ConvertSignedWithGreaterRankThanUnsigned(
- QualType signedType, QualType unsignedType) {
- // FIXME: Need to check if the signed type can represent all values of the
- // unsigned type. If it can, then the result is the signed type. If it can't,
- // then the result is the unsigned version of the signed type.
- return signedType;
-}
-
-/// GetFloatingRank - Helper function for UsualArithmeticConversions().
-static inline int GetFloatingRank(QualType t) {
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
- switch (BT->getKind()) {
- case BuiltinType::Float:
- case BuiltinType::FloatComplex:
- return 1;
- case BuiltinType::Double:
- case BuiltinType::DoubleComplex:
- return 2;
- case BuiltinType::LongDouble:
- case BuiltinType::LongDoubleComplex:
- return 3;
- default:
- assert(0 && "getFloatingPointRank(): not a floating type");
- }
- }
- return 0;
-}
-
-/// ConvertFloatingRankToComplexType - Another helper for converting floats.
-static inline QualType ConvertFloatingRankToComplexType(int rank,
- ASTContext &C) {
- switch (rank) {
- case 1:
- return C.FloatComplexTy;
- case 2:
- return C.DoubleComplexTy;
- case 3:
- return C.LongDoubleComplexTy;
- default:
- assert(0 && "convertRankToComplex(): illegal value for rank");
- }
-}
-
/// UsualArithmeticConversions - Performs various conversions that are common to
/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
/// routine returns the first non-arithmetic type found. The client is
@@ -545,23 +481,7 @@
if (lhs->isIntegerType())
return rhs;
- // the following code handles three different combinations:
- // complex/complex, complex/float, float/complex. When both operands
- // are complex, the shorter operand is converted to the type of the longer,
- // and that is the type of the result. This corresponds to what is done
- // when combining two real floating-point operands. The fun begins when
- // size promotion occur across type domains. GetFloatingRank &
- // ConvertFloatingRankToComplexType handle this without enumerating all
- // permutations. It also allows us to add new types without breakage.
- int lhsRank = GetFloatingRank(lhs);
- int rhsRank = GetFloatingRank(rhs);
-
- // From H&S 6.3.4: When one operand is complex and the other is a real
- // floating-point type, the less precise type is converted, within it's
- // real or complex domain, to the precision of the other type. For example,
- // when combining a "long double" with a "double _Complex", the
- // "double _Complex" is promoted to "long double _Complex".
- return ConvertFloatingRankToComplexType(std::max(lhsRank,rhsRank), Context);
+ return Context.maxComplexType(lhs, rhs);
}
// Now handle "real" floating types (i.e. float, double, long double).
if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
@@ -572,23 +492,9 @@
return rhs;
// we have two real floating types, float/complex combos were handled above.
- return GetFloatingRank(lhs) >= GetFloatingRank(rhs) ? lhs : rhs;
+ return Context.maxFloatingType(lhs, rhs);
}
- // Lastly, handle two integers (C99 6.3.1.8p1)
- bool t1Unsigned = lhs->isUnsignedIntegerType();
- bool t2Unsigned = rhs->isUnsignedIntegerType();
-
- if ((t1Unsigned && t2Unsigned) || (!t1Unsigned && !t2Unsigned))
- return GetIntegerRank(lhs) >= GetIntegerRank(rhs) ? lhs : rhs;
-
- // We have two integer types with differing signs
- QualType unsignedType = t1Unsigned ? lhs : rhs;
- QualType signedType = t1Unsigned ? rhs : lhs;
-
- if (GetIntegerRank(unsignedType) >= GetIntegerRank(signedType))
- return unsignedType;
- else
- return ConvertSignedWithGreaterRankThanUnsigned(signedType, unsignedType);
+ return Context.maxIntegerType(lhs, rhs);
}
Action::ExprResult Sema::CheckMultiplicativeOperands(
@@ -596,21 +502,37 @@
{
QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType());
- if ((BinaryOperator::Opcode)code == BinaryOperator::Rem) {
+ if ((BOP)code == BinaryOperator::Rem) {
if (!resType->isIntegerType())
return Diag(loc, diag::err_typecheck_invalid_operands);
} else { // *, /
if (!resType->isArithmeticType())
return Diag(loc, diag::err_typecheck_invalid_operands);
}
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
+ return new BinaryOperator(lex, rex, (BOP)code, resType);
}
Action::ExprResult Sema::CheckAdditiveOperands( // C99 6.5.6
Expr *lex, Expr *rex, SourceLocation loc, unsigned code)
{
- // FIXME: add type checking and fix result type
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
+ QualType lhsType = lex->getType(), rhsType = rex->getType();
+ QualType resType = UsualArithmeticConversions(lhsType, rhsType);
+
+ // handle the common case first (both operands are arithmetic).
+ if (resType->isArithmeticType())
+ return new BinaryOperator(lex, rex, (BOP)code, resType);
+ else {
+ if ((BOP)code == BinaryOperator::Add) {
+ if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
+ (lhsType->isIntegerType() && rhsType->isPointerType()))
+ return new BinaryOperator(lex, rex, (BOP)code, resType);
+ } else { // -
+ if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
+ (lhsType->isPointerType() && rhsType->isPointerType()))
+ return new BinaryOperator(lex, rex, (BOP)code, resType);
+ }
+ }
+ return Diag(loc, diag::err_typecheck_invalid_operands);
}
Action::ExprResult Sema::CheckShiftOperands( // C99 6.5.7
@@ -621,7 +543,7 @@
if (!resType->isIntegerType())
return Diag(loc, diag::err_typecheck_invalid_operands);
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
+ return new BinaryOperator(lex, rex, (BOP)code, resType);
}
Action::ExprResult Sema::CheckRelationalOperands( // C99 6.5.8
@@ -630,17 +552,14 @@
QualType lType = lex->getType(), rType = rex->getType();
if (lType->isRealType() && rType->isRealType())
- ;
- else if (lType->isPointerType() && rType->isPointerType())
- ;
- else {
- // The following test is for GCC compatibility.
- if (lType->isIntegerType() || rType->isIntegerType())
- return Diag(loc, diag::err_typecheck_comparison_of_pointer_integer);
- return Diag(loc, diag::err_typecheck_invalid_operands);
- }
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code,
- Context.IntTy);
+ return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+
+ if (lType->isPointerType() && rType->isPointerType())
+ return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+
+ if (lType->isIntegerType() || rType->isIntegerType()) // GCC extension.
+ return Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
+ return Diag(loc, diag::err_typecheck_invalid_operands);
}
Action::ExprResult Sema::CheckEqualityOperands( // C99 6.5.9
@@ -649,17 +568,14 @@
QualType lType = lex->getType(), rType = rex->getType();
if (lType->isArithmeticType() && rType->isArithmeticType())
- ;
- else if (lType->isPointerType() && rType->isPointerType())
- ;
- else {
- // The following test is for GCC compatibility.
- if (lType->isIntegerType() || rType->isIntegerType())
- return Diag(loc, diag::err_typecheck_comparison_of_pointer_integer);
- return Diag(loc, diag::err_typecheck_invalid_operands);
- }
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code,
- Context.IntTy);
+ return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+
+ if (lType->isPointerType() && rType->isPointerType())
+ return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
+
+ if (lType->isIntegerType() || rType->isIntegerType()) // GCC extension.
+ return Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
+ return Diag(loc, diag::err_typecheck_invalid_operands);
}
Action::ExprResult Sema::CheckBitwiseOperands(
@@ -670,28 +586,33 @@
if (!resType->isIntegerType())
return Diag(loc, diag::err_typecheck_invalid_operands);
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, resType);
+ return new BinaryOperator(lex, rex, (BOP)code, resType);
}
Action::ExprResult Sema::CheckLogicalOperands( // C99 6.5.[13,14]
Expr *lex, Expr *rex, SourceLocation loc, unsigned code)
{
- // FIXME: add type checking and fix result type
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
+ QualType lhsType = UsualUnaryConversion(lex->getType());
+ QualType rhsType = UsualUnaryConversion(rex->getType());
+
+ if (!lhsType->isScalarType() || !rhsType->isScalarType())
+ return Diag(loc, diag::err_typecheck_invalid_operands);
+
+ return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
}
Action::ExprResult Sema::CheckAssignmentOperands( // C99 6.5.16
Expr *lex, Expr *rex, SourceLocation loc, unsigned code)
{
// FIXME: add type checking and fix result type
- return new BinaryOperator(lex, rex, (BinaryOperator::Opcode)code, Context.IntTy);
+ return new BinaryOperator(lex, rex, (BOP)code, Context.IntTy);
}
Action::ExprResult Sema::CheckCommaOperands( // C99 6.5.17
Expr *lex, Expr *rex, SourceLocation loc)
{
- // FIXME: add type checking and fix result type
- return new BinaryOperator(lex, rex, BinaryOperator::Comma, Context.IntTy);
+ QualType rhsType = UsualUnaryConversion(rex->getType());
+ return new BinaryOperator(lex, rex, BinaryOperator::Comma, rhsType);
}
Action::ExprResult
@@ -717,7 +638,7 @@
if (!canonType.isModifiableLvalue())
return Diag(OpLoc, diag::err_typecheck_not_modifiable, qType);
- return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, qType);
+ return new UnaryOperator(op, (UOP)OpCode, qType);
}
/// getPrimaryDeclaration - Helper function for CheckAddressOfOperand().
@@ -806,5 +727,5 @@
return Diag(OpLoc, diag::err_typecheck_unary_expr, resultType);
break;
}
- return new UnaryOperator(op, (UnaryOperator::Opcode)Opc, resultType);
+ return new UnaryOperator(op, (UOP)Opc, resultType);
}
Modified: cfe/cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/ASTContext.h?rev=39418&r1=39417&r2=39418&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/cfe/trunk/include/clang/AST/ASTContext.h Wed Jul 11 11:44:08 2007
@@ -82,12 +82,39 @@
/// getSizeType - Return the unique type for "size_t" (C99 7.17), defined
/// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4).
QualType getSizeType() const;
+
+ // maxIntegerType - Returns the highest ranked integer type. Handles 3
+ // different type combos: unsigned/unsigned, signed/signed, signed/unsigned.
+ QualType maxIntegerType(QualType lhs, QualType rhs);
+
+ // maxFloatingType - Returns the highest ranked float type. Both input
+ // types are required to be floats.
+ QualType maxFloatingType(QualType lt, QualType rt);
+
+ // maxComplexType - Returns the highest ranked complex type. Handles 3
+ // different type combos: complex/complex, complex/float, float/complex.
+ QualType maxComplexType(QualType lt, QualType rt);
+
private:
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
void operator=(const ASTContext&); // DO NOT IMPLEMENT
void InitBuiltinTypes();
void InitBuiltinType(QualType &R, BuiltinType::Kind K);
+
+ /// getIntegerRank - Return an integer conversion rank (C99 6.3.1.1p1).
+ /// This routine will assert if passed a built-in type that isn't an integer.
+ int getIntegerRank(QualType t);
+
+ /// getFloatingRank - Return a relative rank for floating point types.
+ /// This routine will assert if passed a built-in type that isn't a float.
+ int getFloatingRank(QualType t);
+
+ /// FIXME: comment
+ QualType convertSignedWithGreaterRankThanUnsigned(QualType signedT,
+ QualType unsignedT);
+ /// FIXME: comment
+ QualType convertFloatingRankToComplexType(int rank);
};
} // end namespace clang
Modified: cfe/cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Expr.h?rev=39418&r1=39417&r2=39418&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Expr.h Wed Jul 11 11:44:08 2007
@@ -368,7 +368,7 @@
static bool isEqualityOp(Opcode Op) { return Op == EQ || Op == NE; }
static bool isBitwiseOp(Opcode Op) { return Op >= And && Op <= Or; }
static bool isLogicalOp(Opcode Op) { return Op == LAnd || Op == LOr; }
- static bool isAssignmentOp(Opcode Op) { return Op >= Assign || Op<=OrAssign; }
+ static bool isAssignmentOp(Opcode Op) { return Op >= Assign && Op<=OrAssign; }
Opcode getOpcode() const { return Opc; }
Expr *getLHS() { return LHS; }
Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=39418&r1=39417&r2=39418&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:44:08 2007
@@ -537,7 +537,7 @@
"invalid argument type to unary expression '%s'")
DIAG(err_typecheck_invalid_operands, ERROR,
"invalid operands to binary expression")
-DIAG(err_typecheck_comparison_of_pointer_integer, WARNING,
+DIAG(ext_typecheck_comparison_of_pointer_integer, EXTENSION,
"comparison between pointer and integer")
// Statements.
More information about the cfe-commits
mailing list