mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-29 05:01:11 +00:00
add ConstEvaluatedExprVisitor
Differential Revision: http://reviews.llvm.org/D10210 llvm-svn: 239474
This commit is contained in:
parent
965bf6a3ce
commit
503fc39d1f
@ -26,29 +26,31 @@ class ASTContext;
|
||||
|
||||
/// \brief Given a potentially-evaluated expression, this visitor visits all
|
||||
/// of its potentially-evaluated subexpressions, recursively.
|
||||
template<typename ImplClass>
|
||||
class EvaluatedExprVisitor : public StmtVisitor<ImplClass> {
|
||||
ASTContext &Context;
|
||||
|
||||
template<template <typename> class Ptr, typename ImplClass>
|
||||
class EvaluatedExprVisitorBase : public StmtVisitorBase<Ptr, ImplClass, void> {
|
||||
const ASTContext &Context;
|
||||
|
||||
public:
|
||||
explicit EvaluatedExprVisitor(ASTContext &Context) : Context(Context) { }
|
||||
|
||||
#define PTR(CLASS) typename Ptr<CLASS>::type
|
||||
|
||||
explicit EvaluatedExprVisitorBase(const ASTContext &Context) : Context(Context) { }
|
||||
|
||||
// Expressions that have no potentially-evaluated subexpressions (but may have
|
||||
// other sub-expressions).
|
||||
void VisitDeclRefExpr(DeclRefExpr *E) { }
|
||||
void VisitOffsetOfExpr(OffsetOfExpr *E) { }
|
||||
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { }
|
||||
void VisitExpressionTraitExpr(ExpressionTraitExpr *E) { }
|
||||
void VisitBlockExpr(BlockExpr *E) { }
|
||||
void VisitCXXUuidofExpr(CXXUuidofExpr *E) { }
|
||||
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { }
|
||||
|
||||
void VisitMemberExpr(MemberExpr *E) {
|
||||
void VisitDeclRefExpr(PTR(DeclRefExpr) E) { }
|
||||
void VisitOffsetOfExpr(PTR(OffsetOfExpr) E) { }
|
||||
void VisitUnaryExprOrTypeTraitExpr(PTR(UnaryExprOrTypeTraitExpr) E) { }
|
||||
void VisitExpressionTraitExpr(PTR(ExpressionTraitExpr) E) { }
|
||||
void VisitBlockExpr(PTR(BlockExpr) E) { }
|
||||
void VisitCXXUuidofExpr(PTR(CXXUuidofExpr) E) { }
|
||||
void VisitCXXNoexceptExpr(PTR(CXXNoexceptExpr) E) { }
|
||||
|
||||
void VisitMemberExpr(PTR(MemberExpr) E) {
|
||||
// Only the base matters.
|
||||
return this->Visit(E->getBase());
|
||||
}
|
||||
|
||||
void VisitChooseExpr(ChooseExpr *E) {
|
||||
|
||||
void VisitChooseExpr(PTR(ChooseExpr) E) {
|
||||
// Don't visit either child expression if the condition is dependent.
|
||||
if (E->getCond()->isValueDependent())
|
||||
return;
|
||||
@ -56,7 +58,7 @@ public:
|
||||
return this->Visit(E->getChosenSubExpr());
|
||||
}
|
||||
|
||||
void VisitGenericSelectionExpr(GenericSelectionExpr *E) {
|
||||
void VisitGenericSelectionExpr(PTR(GenericSelectionExpr) E) {
|
||||
// The controlling expression of a generic selection is not evaluated.
|
||||
|
||||
// Don't visit either child expression if the condition is type-dependent.
|
||||
@ -67,23 +69,23 @@ public:
|
||||
return this->Visit(E->getResultExpr());
|
||||
}
|
||||
|
||||
void VisitDesignatedInitExpr(DesignatedInitExpr *E) {
|
||||
void VisitDesignatedInitExpr(PTR(DesignatedInitExpr) E) {
|
||||
// Only the actual initializer matters; the designators are all constant
|
||||
// expressions.
|
||||
return this->Visit(E->getInit());
|
||||
}
|
||||
|
||||
void VisitCXXTypeidExpr(CXXTypeidExpr *E) {
|
||||
void VisitCXXTypeidExpr(PTR(CXXTypeidExpr) E) {
|
||||
if (E->isPotentiallyEvaluated())
|
||||
return this->Visit(E->getExprOperand());
|
||||
}
|
||||
|
||||
void VisitCallExpr(CallExpr *CE) {
|
||||
void VisitCallExpr(PTR(CallExpr) CE) {
|
||||
if (!CE->isUnevaluatedBuiltinCall(Context))
|
||||
return static_cast<ImplClass*>(this)->VisitExpr(CE);
|
||||
}
|
||||
|
||||
void VisitLambdaExpr(LambdaExpr *LE) {
|
||||
void VisitLambdaExpr(PTR(LambdaExpr) LE) {
|
||||
// Only visit the capture initializers, and not the body.
|
||||
for (LambdaExpr::capture_init_iterator I = LE->capture_init_begin(),
|
||||
E = LE->capture_init_end();
|
||||
@ -94,11 +96,31 @@ public:
|
||||
|
||||
/// \brief The basis case walks all of the children of the statement or
|
||||
/// expression, assuming they are all potentially evaluated.
|
||||
void VisitStmt(Stmt *S) {
|
||||
for (Stmt::child_range C = S->children(); C; ++C)
|
||||
void VisitStmt(PTR(Stmt) S) {
|
||||
for (auto C = S->children(); C; ++C)
|
||||
if (*C)
|
||||
this->Visit(*C);
|
||||
}
|
||||
|
||||
#undef PTR
|
||||
};
|
||||
|
||||
/// EvaluatedExprVisitor - This class visits 'Expr *'s
|
||||
template<typename ImplClass>
|
||||
class EvaluatedExprVisitor
|
||||
: public EvaluatedExprVisitorBase<make_ptr, ImplClass> {
|
||||
public:
|
||||
explicit EvaluatedExprVisitor(const ASTContext &Context) :
|
||||
EvaluatedExprVisitorBase<make_ptr, ImplClass>(Context) { }
|
||||
};
|
||||
|
||||
/// ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
|
||||
template<typename ImplClass>
|
||||
class ConstEvaluatedExprVisitor
|
||||
: public EvaluatedExprVisitorBase<make_const_ptr, ImplClass> {
|
||||
public:
|
||||
explicit ConstEvaluatedExprVisitor(const ASTContext &Context) :
|
||||
EvaluatedExprVisitorBase<make_const_ptr, ImplClass>(Context) { }
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -598,7 +598,7 @@ public:
|
||||
|
||||
/// \brief Determine whether this expression involves a call to any function
|
||||
/// that is not trivial.
|
||||
bool hasNonTrivialCall(ASTContext &Ctx);
|
||||
bool hasNonTrivialCall(const ASTContext &Ctx) const;
|
||||
|
||||
/// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded
|
||||
/// integer. This must be called on an expression that constant folds to an
|
||||
@ -2273,7 +2273,7 @@ public:
|
||||
|
||||
/// \brief Returns \c true if this is a call to a builtin which does not
|
||||
/// evaluate side-effects within its arguments.
|
||||
bool isUnevaluatedBuiltinCall(ASTContext &Ctx) const;
|
||||
bool isUnevaluatedBuiltinCall(const ASTContext &Ctx) const;
|
||||
|
||||
/// getCallReturnType - Get the return type of the call expr. This is not
|
||||
/// always the type of the expr itself, if the return type is a reference
|
||||
|
@ -1238,7 +1238,7 @@ unsigned CallExpr::getBuiltinCallee() const {
|
||||
return FDecl->getBuiltinID();
|
||||
}
|
||||
|
||||
bool CallExpr::isUnevaluatedBuiltinCall(ASTContext &Ctx) const {
|
||||
bool CallExpr::isUnevaluatedBuiltinCall(const ASTContext &Ctx) const {
|
||||
if (unsigned BI = getBuiltinCallee())
|
||||
return Ctx.BuiltinInfo.isUnevaluated(BI);
|
||||
return false;
|
||||
@ -3136,21 +3136,21 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
|
||||
|
||||
namespace {
|
||||
/// \brief Look for a call to a non-trivial function within an expression.
|
||||
class NonTrivialCallFinder : public EvaluatedExprVisitor<NonTrivialCallFinder>
|
||||
class NonTrivialCallFinder : public ConstEvaluatedExprVisitor<NonTrivialCallFinder>
|
||||
{
|
||||
typedef EvaluatedExprVisitor<NonTrivialCallFinder> Inherited;
|
||||
|
||||
typedef ConstEvaluatedExprVisitor<NonTrivialCallFinder> Inherited;
|
||||
|
||||
bool NonTrivial;
|
||||
|
||||
public:
|
||||
explicit NonTrivialCallFinder(ASTContext &Context)
|
||||
explicit NonTrivialCallFinder(const ASTContext &Context)
|
||||
: Inherited(Context), NonTrivial(false) { }
|
||||
|
||||
bool hasNonTrivialCall() const { return NonTrivial; }
|
||||
|
||||
void VisitCallExpr(CallExpr *E) {
|
||||
if (CXXMethodDecl *Method
|
||||
= dyn_cast_or_null<CXXMethodDecl>(E->getCalleeDecl())) {
|
||||
|
||||
void VisitCallExpr(const CallExpr *E) {
|
||||
if (const CXXMethodDecl *Method
|
||||
= dyn_cast_or_null<const CXXMethodDecl>(E->getCalleeDecl())) {
|
||||
if (Method->isTrivial()) {
|
||||
// Recurse to children of the call.
|
||||
Inherited::VisitStmt(E);
|
||||
@ -3160,8 +3160,8 @@ namespace {
|
||||
|
||||
NonTrivial = true;
|
||||
}
|
||||
|
||||
void VisitCXXConstructExpr(CXXConstructExpr *E) {
|
||||
|
||||
void VisitCXXConstructExpr(const CXXConstructExpr *E) {
|
||||
if (E->getConstructor()->isTrivial()) {
|
||||
// Recurse to children of the call.
|
||||
Inherited::VisitStmt(E);
|
||||
@ -3170,8 +3170,8 @@ namespace {
|
||||
|
||||
NonTrivial = true;
|
||||
}
|
||||
|
||||
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
|
||||
|
||||
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E) {
|
||||
if (E->getTemporary()->getDestructor()->isTrivial()) {
|
||||
Inherited::VisitStmt(E);
|
||||
return;
|
||||
@ -3182,7 +3182,7 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
bool Expr::hasNonTrivialCall(ASTContext &Ctx) {
|
||||
bool Expr::hasNonTrivialCall(const ASTContext &Ctx) const {
|
||||
NonTrivialCallFinder Finder(Ctx);
|
||||
Finder.Visit(this);
|
||||
return Finder.hasNonTrivialCall();
|
||||
|
@ -370,25 +370,25 @@ namespace {
|
||||
|
||||
/// A visitor which checks whether an initializer uses 'this' in a
|
||||
/// way which requires the vtable to be properly set.
|
||||
struct DynamicThisUseChecker : EvaluatedExprVisitor<DynamicThisUseChecker> {
|
||||
typedef EvaluatedExprVisitor<DynamicThisUseChecker> super;
|
||||
struct DynamicThisUseChecker : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
|
||||
typedef ConstEvaluatedExprVisitor<DynamicThisUseChecker> super;
|
||||
|
||||
bool UsesThis;
|
||||
|
||||
DynamicThisUseChecker(ASTContext &C) : super(C), UsesThis(false) {}
|
||||
DynamicThisUseChecker(const ASTContext &C) : super(C), UsesThis(false) {}
|
||||
|
||||
// Black-list all explicit and implicit references to 'this'.
|
||||
//
|
||||
// Do we need to worry about external references to 'this' derived
|
||||
// from arbitrary code? If so, then anything which runs arbitrary
|
||||
// external code might potentially access the vtable.
|
||||
void VisitCXXThisExpr(CXXThisExpr *E) { UsesThis = true; }
|
||||
void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; }
|
||||
};
|
||||
}
|
||||
|
||||
static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) {
|
||||
DynamicThisUseChecker Checker(C);
|
||||
Checker.Visit(const_cast<Expr*>(Init));
|
||||
Checker.Visit(Init);
|
||||
return Checker.UsesThis;
|
||||
}
|
||||
|
||||
|
@ -574,28 +574,29 @@ namespace {
|
||||
/// ContainsReference - A visitor class to search for references to
|
||||
/// a particular declaration (the needle) within any evaluated component of an
|
||||
/// expression (recursively).
|
||||
class ContainsReference : public EvaluatedExprVisitor<ContainsReference> {
|
||||
class ContainsReference : public ConstEvaluatedExprVisitor<ContainsReference> {
|
||||
bool FoundReference;
|
||||
const DeclRefExpr *Needle;
|
||||
|
||||
public:
|
||||
ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)
|
||||
: EvaluatedExprVisitor<ContainsReference>(Context),
|
||||
FoundReference(false), Needle(Needle) {}
|
||||
typedef ConstEvaluatedExprVisitor<ContainsReference> Inherited;
|
||||
|
||||
void VisitExpr(Expr *E) {
|
||||
ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)
|
||||
: Inherited(Context), FoundReference(false), Needle(Needle) {}
|
||||
|
||||
void VisitExpr(const Expr *E) {
|
||||
// Stop evaluating if we already have a reference.
|
||||
if (FoundReference)
|
||||
return;
|
||||
|
||||
EvaluatedExprVisitor<ContainsReference>::VisitExpr(E);
|
||||
Inherited::VisitExpr(E);
|
||||
}
|
||||
|
||||
void VisitDeclRefExpr(DeclRefExpr *E) {
|
||||
void VisitDeclRefExpr(const DeclRefExpr *E) {
|
||||
if (E == Needle)
|
||||
FoundReference = true;
|
||||
else
|
||||
EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E);
|
||||
Inherited::VisitDeclRefExpr(E);
|
||||
}
|
||||
|
||||
bool doesContainReference() const { return FoundReference; }
|
||||
@ -854,7 +855,7 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
|
||||
return false;
|
||||
|
||||
ContainsReference CR(S.Context, DRE);
|
||||
CR.Visit(const_cast<Expr*>(Initializer));
|
||||
CR.Visit(Initializer);
|
||||
if (CR.doesContainReference()) {
|
||||
S.Diag(DRE->getLocStart(),
|
||||
diag::warn_uninit_self_reference_in_init)
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "clang/AST/CXXInheritance.h"
|
||||
#include "clang/AST/CharUnits.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/EvaluatedExprVisitor.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user