diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index a0ef7460c5..529b4d49c5 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -71,7 +71,7 @@ static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) { return false; Result = !FloatResult.isZero(); return true; - } else if (E->getType()->isPointerType()) { + } else if (E->getType()->hasPointerRepresentation()) { APValue PointerResult; if (!EvaluatePointer(E, PointerResult, Info)) return false; @@ -79,8 +79,19 @@ static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) { // the check look like? Result = PointerResult.getLValueBase() || PointerResult.getLValueOffset(); return true; + } else if (E->getType()->isAnyComplexType()) { + APValue ComplexResult; + if (!EvaluateComplex(E, ComplexResult, Info)) + return false; + if (ComplexResult.isComplexFloat()) { + Result = !ComplexResult.getComplexFloatReal().isZero() || + !ComplexResult.getComplexFloatImag().isZero(); + } else { + Result = ComplexResult.getComplexIntReal().getBoolValue() || + ComplexResult.getComplexIntImag().getBoolValue(); + } + return true; } - // FIXME: Handle pointer-like types, complex types return false; } @@ -890,21 +901,22 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { APValue LHSValue; if (!EvaluatePointer(E->getLHS(), LHSValue, Info)) return false; - + APValue RHSValue; if (!EvaluatePointer(E->getRHS(), RHSValue, Info)) return false; - - // FIXME: Is this correct? What if only one of the operands has a base? + + // Reject any bases; this is conservative, but good enough for + // common uses if (LHSValue.getLValueBase() || RHSValue.getLValueBase()) return false; - + const QualType Type = E->getLHS()->getType(); const QualType ElementType = Type->getAsPointerType()->getPointeeType(); uint64_t D = LHSValue.getLValueOffset() - RHSValue.getLValueOffset(); D /= Info.Ctx.getTypeSize(ElementType) / 8; - + return Success(D, E); } } @@ -980,20 +992,20 @@ unsigned IntExprEvaluator::GetAlignOfType(QualType T) { // __alignof__(void) = 1 as a gcc extension. if (Ty->isVoidType()) return 1; - + // GCC extension: alignof(function) = 4. // FIXME: AlignOf shouldn't be unconditionally 4! It should listen to the // attribute(align) directive. if (Ty->isFunctionType()) return 4; - + if (const ExtQualType *EXTQT = dyn_cast(Ty)) return GetAlignOfType(QualType(EXTQT->getBaseType(), 0)); // alignof VLA/incomplete array. if (const ArrayType *VAT = dyn_cast(Ty)) return GetAlignOfType(VAT->getElementType()); - + // sizeof (objc class)? if (isa(Ty)) return 1; // FIXME: This probably isn't right. @@ -1010,7 +1022,7 @@ unsigned IntExprEvaluator::GetAlignOfExpr(const Expr *E) { // to 1 in those cases. if (const DeclRefExpr *DRE = dyn_cast(E)) return Info.Ctx.getDeclAlignInBytes(DRE->getDecl()); - + if (const MemberExpr *ME = dyn_cast(E)) return Info.Ctx.getDeclAlignInBytes(ME->getMemberDecl()); @@ -1030,14 +1042,14 @@ bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { else return Success(GetAlignOfExpr(E->getArgumentExpr()), E); } - + QualType SrcTy = E->getTypeOfArgument(); // sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc // extension. if (SrcTy->isVoidType() || SrcTy->isFunctionType()) return Success(1, E); - + // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. if (!SrcTy->isConstantSizeType()) return false; diff --git a/test/Sema/const-eval.c b/test/Sema/const-eval.c index 7714f48817..03aeb2a0b3 100644 --- a/test/Sema/const-eval.c +++ b/test/Sema/const-eval.c @@ -50,3 +50,8 @@ EVAL_EXPR(22, (__real__ (2i+3)) == 3 ? 1 : -1); int g23[(int)(1.0 / 1.0)] = { 1 }; int g24[(int)(1.0 / 1.0)] = { 1 , 2 }; // expected-warning {{excess elements in array initializer}} int g25[(int)(1.0 + 1.0)], g26 = sizeof(g25); + +EVAL_EXPR(26, (_Complex double)0 ? -1 : 1) +EVAL_EXPR(27, (_Complex int)0 ? -1 : 1) +EVAL_EXPR(28, (_Complex double)1 ? 1 : -1) +EVAL_EXPR(29, (_Complex int)1 ? 1 : -1)