summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2009-03-28 01:22:36 +0000
committerEli Friedman <eli.friedman@gmail.com>2009-03-28 01:22:36 +0000
commit8b7b1b1aee8685c34130f7e4a8457a52558af034 (patch)
tree997b1bd6718354cc991f5ff9ef94c6a397e51c69 /clang/lib/Sema/SemaExpr.cpp
parent0cb4cc106c263e9d5ae3253a4c08a552f6766b80 (diff)
downloadbcm5719-llvm-8b7b1b1aee8685c34130f7e4a8457a52558af034.tar.gz
bcm5719-llvm-8b7b1b1aee8685c34130f7e4a8457a52558af034.zip
Change compound assignment operators to keep track of both the promoted
LHS type and the computation result type; this encodes information into the AST which is otherwise non-obvious. Fix Sema to always come up with the right answer for both of these types. Fix IRGen and the analyzer to account for these changes. This fixes PR2601. The approach is inspired by PR2601 comment 2. Note that this changes real *= complex in CodeGen from a silent miscompilation to an explicit error. I'm not really sure that the analyzer changes are correct, or how to test them... someone more familiar with the analyzer should check those changes. llvm-svn: 67889
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp113
1 files changed, 72 insertions, 41 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 8b646e9943f..0a77c21875f 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -174,10 +174,10 @@ void Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) {
/// GCC.
QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
bool isCompAssign) {
- if (!isCompAssign) {
+ if (!isCompAssign)
UsualUnaryConversions(lhsExpr);
- UsualUnaryConversions(rhsExpr);
- }
+
+ UsualUnaryConversions(rhsExpr);
// For conversion purposes, we ignore any qualifiers.
// For example, "const float" and "float" are equivalent.
@@ -196,10 +196,9 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
return lhs;
QualType destType = UsualArithmeticConversionsType(lhs, rhs);
- if (!isCompAssign) {
+ if (!isCompAssign)
ImpCastExprToType(lhsExpr, destType);
- ImpCastExprToType(rhsExpr, destType);
- }
+ ImpCastExprToType(rhsExpr, destType);
return destType;
}
@@ -3147,16 +3146,22 @@ inline QualType Sema::CheckRemainderOperands(
}
inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
- Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign)
+ Expr *&lex, Expr *&rex, SourceLocation Loc, QualType* CompLHSTy)
{
- if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
- return CheckVectorOperands(Loc, lex, rex);
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+ QualType compType = CheckVectorOperands(Loc, lex, rex);
+ if (CompLHSTy) *CompLHSTy = compType;
+ return compType;
+ }
- QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+ QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy);
// handle the common case first (both operands are arithmetic).
- if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
+ if (lex->getType()->isArithmeticType() &&
+ rex->getType()->isArithmeticType()) {
+ if (CompLHSTy) *CompLHSTy = compType;
return compType;
+ }
// Put any potential pointer into PExp
Expr* PExp = lex, *IExp = rex;
@@ -3193,6 +3198,12 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
lex->getType()))
return QualType();
+ if (CompLHSTy) {
+ QualType LHSTy = lex->getType();
+ if (LHSTy->isPromotableIntegerType())
+ LHSTy = Context.IntTy;
+ *CompLHSTy = LHSTy;
+ }
return PExp->getType();
}
}
@@ -3202,17 +3213,22 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
// C99 6.5.6
QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
- SourceLocation Loc, bool isCompAssign) {
- if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
- return CheckVectorOperands(Loc, lex, rex);
+ SourceLocation Loc, QualType* CompLHSTy) {
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+ QualType compType = CheckVectorOperands(Loc, lex, rex);
+ if (CompLHSTy) *CompLHSTy = compType;
+ return compType;
+ }
- QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+ QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy);
// Enforce type constraints: C99 6.5.6p3.
// Handle the common case first (both operands are arithmetic).
- if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
+ if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType()) {
+ if (CompLHSTy) *CompLHSTy = compType;
return compType;
+ }
// Either ptr - int or ptr - ptr.
if (const PointerType *LHSPTy = lex->getType()->getAsPointerType()) {
@@ -3258,6 +3274,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
<< ComplainAboutFunc->getType()
<< ComplainAboutFunc->getSourceRange();
+ if (CompLHSTy) *CompLHSTy = lex->getType();
return lex->getType();
}
@@ -3310,7 +3327,8 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
Diag(Loc, diag::ext_gnu_ptr_func_arith)
<< ComplainAboutFunc->getType()
<< ComplainAboutFunc->getSourceRange();
-
+
+ if (CompLHSTy) *CompLHSTy = lex->getType();
return Context.getPointerDiffType();
}
}
@@ -3327,12 +3345,18 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
// Shifts don't perform usual arithmetic conversions, they just do integer
// promotions on each operand. C99 6.5.7p3
+ QualType LHSTy;
+ if (lex->getType()->isPromotableIntegerType())
+ LHSTy = Context.IntTy;
+ else
+ LHSTy = lex->getType();
if (!isCompAssign)
- UsualUnaryConversions(lex);
+ ImpCastExprToType(lex, LHSTy);
+
UsualUnaryConversions(rex);
// "The type of the result is that of the promoted left operand."
- return lex->getType();
+ return LHSTy;
}
// C99 6.5.8
@@ -4049,9 +4073,11 @@ static inline UnaryOperator::Opcode ConvertTokenKindToUnaryOpcode(
Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
unsigned Op,
Expr *lhs, Expr *rhs) {
- QualType ResultTy; // Result type of the binary operator.
- QualType CompTy; // Computation type for compound assignments (e.g. '+=')
+ QualType ResultTy; // Result type of the binary operator.
BinaryOperator::Opcode Opc = (BinaryOperator::Opcode)Op;
+ // The following two variables are used for compound assignment operators
+ QualType CompLHSTy; // Type of LHS after promotions for computation
+ QualType CompResultTy; // Type of computation result
switch (Opc) {
case BinaryOperator::Assign:
@@ -4100,37 +4126,41 @@ Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BinaryOperator::MulAssign:
case BinaryOperator::DivAssign:
- CompTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true);
- if (!CompTy.isNull())
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompTy);
+ CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true);
+ CompLHSTy = CompResultTy;
+ if (!CompResultTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
case BinaryOperator::RemAssign:
- CompTy = CheckRemainderOperands(lhs, rhs, OpLoc, true);
- if (!CompTy.isNull())
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompTy);
+ CompResultTy = CheckRemainderOperands(lhs, rhs, OpLoc, true);
+ CompLHSTy = CompResultTy;
+ if (!CompResultTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
case BinaryOperator::AddAssign:
- CompTy = CheckAdditionOperands(lhs, rhs, OpLoc, true);
- if (!CompTy.isNull())
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompTy);
+ CompResultTy = CheckAdditionOperands(lhs, rhs, OpLoc, &CompLHSTy);
+ if (!CompResultTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
case BinaryOperator::SubAssign:
- CompTy = CheckSubtractionOperands(lhs, rhs, OpLoc, true);
- if (!CompTy.isNull())
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompTy);
+ CompResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc, &CompLHSTy);
+ if (!CompResultTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
case BinaryOperator::ShlAssign:
case BinaryOperator::ShrAssign:
- CompTy = CheckShiftOperands(lhs, rhs, OpLoc, true);
- if (!CompTy.isNull())
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompTy);
+ CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, true);
+ CompLHSTy = CompResultTy;
+ if (!CompResultTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
case BinaryOperator::AndAssign:
case BinaryOperator::XorAssign:
case BinaryOperator::OrAssign:
- CompTy = CheckBitwiseOperands(lhs, rhs, OpLoc, true);
- if (!CompTy.isNull())
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompTy);
+ CompResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc, true);
+ CompLHSTy = CompResultTy;
+ if (!CompResultTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
case BinaryOperator::Comma:
ResultTy = CheckCommaOperands(lhs, rhs, OpLoc);
@@ -4138,11 +4168,12 @@ Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
}
if (ResultTy.isNull())
return ExprError();
- if (CompTy.isNull())
+ if (CompResultTy.isNull())
return Owned(new (Context) BinaryOperator(lhs, rhs, Opc, ResultTy, OpLoc));
else
return Owned(new (Context) CompoundAssignOperator(lhs, rhs, Opc, ResultTy,
- CompTy, OpLoc));
+ CompLHSTy, CompResultTy,
+ OpLoc));
}
// Binary Operators. 'Tok' is the token for the operator.
OpenPOWER on IntegriCloud