зеркало из https://github.com/microsoft/clang-1.git
__builtin_object_size refinements. Ensure we handle expressions with
side-effects up front, as when we switch to the llvm intrinsic call for __builtin_object_size later, it will have two evaluations. We also finish off the intrinsic version of the code so we can just turn it on once llvm has the intrinsic. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85324 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
25950e8c13
Коммит
c4c9045dab
|
@ -151,6 +151,66 @@ static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType,
|
|||
return Result;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class VISIBILITY_HIDDEN HasSideEffect
|
||||
: public StmtVisitor<HasSideEffect, bool> {
|
||||
EvalInfo &Info;
|
||||
public:
|
||||
|
||||
HasSideEffect(EvalInfo &info) : Info(info) {}
|
||||
|
||||
// Unhandled nodes conservatively default to having side effects.
|
||||
bool VisitStmt(Stmt *S) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
|
||||
bool VisitDeclRefExpr(DeclRefExpr *E) {
|
||||
if (E->getType().isVolatileQualified())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
// We don't want to evaluate BlockExprs multiple times, as they generate
|
||||
// a ton of code.
|
||||
bool VisitBlockExpr(BlockExpr *E) { return true; }
|
||||
bool VisitPredefinedExpr(PredefinedExpr *E) { return false; }
|
||||
bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E)
|
||||
{ return Visit(E->getInitializer()); }
|
||||
bool VisitMemberExpr(MemberExpr *E) { return Visit(E->getBase()); }
|
||||
bool VisitIntegerLiteral(IntegerLiteral *E) { return false; }
|
||||
bool VisitFloatingLiteral(FloatingLiteral *E) { return false; }
|
||||
bool VisitStringLiteral(StringLiteral *E) { return false; }
|
||||
bool VisitCharacterLiteral(CharacterLiteral *E) { return false; }
|
||||
bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { return false; }
|
||||
bool VisitArraySubscriptExpr(ArraySubscriptExpr *E)
|
||||
{ return Visit(E->getLHS()) && Visit(E->getRHS()); }
|
||||
bool VisitChooseExpr(ChooseExpr *E)
|
||||
{ return Visit(E->getChosenSubExpr(Info.Ctx)); }
|
||||
bool VisitCastExpr(CastExpr *E) { return Visit(E->getSubExpr()); }
|
||||
bool VisitBinAssign(BinaryOperator *E) { return true; }
|
||||
bool VisitCompoundAssign(BinaryOperator *E) { return true; }
|
||||
bool VisitBinaryOperator(BinaryOperator *E) { return false; }
|
||||
bool VisitUnaryPreInc(UnaryOperator *E) { return true; }
|
||||
bool VisitUnaryPostInc(UnaryOperator *E) { return true; }
|
||||
bool VisitUnaryPreDec(UnaryOperator *E) { return true; }
|
||||
bool VisitUnaryPostDec(UnaryOperator *E) { return true; }
|
||||
bool VisitUnaryDeref(UnaryOperator *E) {
|
||||
if (E->getType().isVolatileQualified())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool VisitUnaryOperator(UnaryOperator *E) { return Visit(E->getSubExpr()); }
|
||||
};
|
||||
|
||||
bool HasSideEffects(const Expr* E, ASTContext &Ctx) {
|
||||
Expr::EvalResult Result;
|
||||
EvalInfo Info(Ctx, Result);
|
||||
|
||||
return HasSideEffect(Info).Visit(const_cast<Expr*>(E));
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// LValue Evaluation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -893,12 +953,12 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
|
|||
}
|
||||
}
|
||||
|
||||
if (Base.HasSideEffects) {
|
||||
if (HasSideEffects(E->getArg(0), Info.Ctx)) {
|
||||
if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() < 2)
|
||||
return Success(-1, E);
|
||||
return Success(0, E);
|
||||
}
|
||||
|
||||
|
||||
return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
|
||||
}
|
||||
|
||||
|
|
|
@ -203,11 +203,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
|
|||
#if 0
|
||||
// We pass this builtin onto the optimizer so that it can
|
||||
// figure out the object size in more complex cases.
|
||||
Value *F = CGM.getIntrinsic(Intrinsic::objectsize, 0, 0);
|
||||
Builder.CreateCall2(F,
|
||||
EmitScalarExpr(E->getArg(0)));
|
||||
EmitScalarExpr(E->getArg(1)));
|
||||
return RValue::get(Address);
|
||||
const llvm::Type *ResType[] = {
|
||||
ConvertType(E->getType())
|
||||
};
|
||||
Value *F = CGM.getIntrinsic(Intrinsic::objectsize, ResType, 1);
|
||||
return RValue::get(Builder.CreateCall2(F,
|
||||
EmitScalarExpr(E->getArg(0)),
|
||||
EmitScalarExpr(E->getArg(1))));
|
||||
#else
|
||||
// FIXME: Implement. For now we just always fail and pretend we
|
||||
// don't know the object size.
|
||||
|
|
Загрузка…
Ссылка в новой задаче