forked from OSchip/llvm-project
[CFG] [analyzer] Disable argument construction contexts for variadic functions.
The analyzer doesn't make use of them anyway and they seem to have pretty weird AST from time to time, so let's just skip them for now. Fixes a crash reported as pr37769. Differential Revision: https://reviews.llvm.org/D50855 llvm-svn: 340977
This commit is contained in:
parent
8c95b48ba2
commit
ed19831f63
|
@ -734,10 +734,14 @@ private:
|
|||
///
|
||||
/// If \p Result is provided, the new region will be bound to this expression
|
||||
/// instead of \p InitWithAdjustments.
|
||||
ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State,
|
||||
const LocationContext *LC,
|
||||
const Expr *InitWithAdjustments,
|
||||
const Expr *Result = nullptr);
|
||||
///
|
||||
/// Returns the temporary region with adjustments into the optional
|
||||
/// OutRegionWithAdjustments out-parameter if a new region was indeed needed,
|
||||
/// otherwise sets it to nullptr.
|
||||
ProgramStateRef createTemporaryRegionIfNeeded(
|
||||
ProgramStateRef State, const LocationContext *LC,
|
||||
const Expr *InitWithAdjustments, const Expr *Result = nullptr,
|
||||
const SubRegion **OutRegionWithAdjustments = nullptr);
|
||||
|
||||
/// Returns a region representing the first element of a (possibly
|
||||
/// multi-dimensional) array, for the purposes of element construction or
|
||||
|
|
|
@ -283,11 +283,10 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
|
|||
return state;
|
||||
}
|
||||
|
||||
ProgramStateRef
|
||||
ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
|
||||
const LocationContext *LC,
|
||||
const Expr *InitWithAdjustments,
|
||||
const Expr *Result) {
|
||||
ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
|
||||
ProgramStateRef State, const LocationContext *LC,
|
||||
const Expr *InitWithAdjustments, const Expr *Result,
|
||||
const SubRegion **OutRegionWithAdjustments) {
|
||||
// FIXME: This function is a hack that works around the quirky AST
|
||||
// we're often having with respect to C++ temporaries. If only we modelled
|
||||
// the actual execution order of statements properly in the CFG,
|
||||
|
@ -297,8 +296,11 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
|
|||
if (!Result) {
|
||||
// If we don't have an explicit result expression, we're in "if needed"
|
||||
// mode. Only create a region if the current value is a NonLoc.
|
||||
if (!InitValWithAdjustments.getAs<NonLoc>())
|
||||
if (!InitValWithAdjustments.getAs<NonLoc>()) {
|
||||
if (OutRegionWithAdjustments)
|
||||
*OutRegionWithAdjustments = nullptr;
|
||||
return State;
|
||||
}
|
||||
Result = InitWithAdjustments;
|
||||
} else {
|
||||
// We need to create a region no matter what. For sanity, make sure we don't
|
||||
|
@ -418,11 +420,17 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
|
|||
// The result expression would now point to the correct sub-region of the
|
||||
// newly created temporary region. Do this last in order to getSVal of Init
|
||||
// correctly in case (Result == Init).
|
||||
State = State->BindExpr(Result, LC, Reg);
|
||||
if (Result->isGLValue()) {
|
||||
State = State->BindExpr(Result, LC, Reg);
|
||||
} else {
|
||||
State = State->BindExpr(Result, LC, InitValWithAdjustments);
|
||||
}
|
||||
|
||||
// Notify checkers once for two bindLoc()s.
|
||||
State = processRegionChange(State, TR, LC);
|
||||
|
||||
if (OutRegionWithAdjustments)
|
||||
*OutRegionWithAdjustments = cast<SubRegion>(Reg.getAsRegion());
|
||||
return State;
|
||||
}
|
||||
|
||||
|
@ -2532,8 +2540,12 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
|
|||
}
|
||||
|
||||
// Handle regular struct fields / member variables.
|
||||
state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
|
||||
SVal baseExprVal = state->getSVal(BaseExpr, LCtx);
|
||||
const SubRegion *MR = nullptr;
|
||||
state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr,
|
||||
/*Result=*/nullptr,
|
||||
/*OutRegionWithAdjustments=*/&MR);
|
||||
SVal baseExprVal =
|
||||
MR ? loc::MemRegionVal(MR) : state->getSVal(BaseExpr, LCtx);
|
||||
|
||||
const auto *field = cast<FieldDecl>(Member);
|
||||
SVal L = state->getLValue(field, baseExprVal);
|
||||
|
|
|
@ -1152,3 +1152,23 @@ void run() {
|
|||
// and the non-definition decl should be found by direct lookup.
|
||||
void T::foo(C) {}
|
||||
} // namespace argument_virtual_decl_lookup
|
||||
|
||||
namespace union_indirect_field_crash {
|
||||
union U {
|
||||
struct {
|
||||
int x;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T> class C {
|
||||
public:
|
||||
void foo() const {
|
||||
(void)(true ? U().x : 0);
|
||||
}
|
||||
};
|
||||
|
||||
void test() {
|
||||
C<int> c;
|
||||
c.foo();
|
||||
}
|
||||
} // namespace union_indirect_field_crash
|
||||
|
|
Loading…
Reference in New Issue