зеркало из https://github.com/microsoft/clang-1.git
Fix a couple false positive "uninitialized value" warnings with RegionStore
involving reasoning about unions (which we don't handle yet). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78342 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
470c2a9ab6
Коммит
d4e5a606c9
|
@ -0,0 +1,55 @@
|
|||
//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides Optional, a template class modeled in the spirit of
|
||||
// OCaml's 'opt' variant. The idea is to strongly type whether or not
|
||||
// a value can be optional.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_ANALYSIS_OPTIONAL
|
||||
#define LLVM_CLANG_ANALYSIS_OPTIONAL
|
||||
|
||||
namespace clang {
|
||||
|
||||
template<typename T>
|
||||
class Optional {
|
||||
const T x;
|
||||
unsigned hasVal : 1;
|
||||
public:
|
||||
explicit Optional() : hasVal(false) {}
|
||||
Optional(const T &y) : x(y), hasVal(true) {}
|
||||
|
||||
static inline Optional create(const T* y) {
|
||||
return y ? Optional(*y) : Optional();
|
||||
}
|
||||
|
||||
const T* getPointer() const { assert(hasVal); return &x; }
|
||||
|
||||
operator bool() const { return hasVal; }
|
||||
const T* operator->() const { return getPointer(); }
|
||||
const T& operator*() const { assert(hasVal); return x; }
|
||||
};
|
||||
} //end clang namespace
|
||||
|
||||
namespace llvm {
|
||||
template <typename T>
|
||||
struct simplify_type<const ::clang::Optional<T> > {
|
||||
typedef const T* SimpleType;
|
||||
static SimpleType getSimplifiedValue(const ::clang::Optional<T> &Val) {
|
||||
return Val.getPointer();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct simplify_type< ::clang::Optional<T> >
|
||||
: public simplify_type<const ::clang::Optional<T> > {};
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
|
@ -18,6 +18,7 @@
|
|||
#include "clang/Analysis/PathSensitive/GRState.h"
|
||||
#include "clang/Analysis/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/Analysis/Analyses/LiveVariables.h"
|
||||
#include "clang/Analysis/Support/Optional.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
|
@ -187,6 +188,11 @@ public:
|
|||
|
||||
RegionStoreSubRegionMap *getRegionStoreSubRegionMap(const GRState *state);
|
||||
|
||||
|
||||
/// getDefaultBinding - Returns an SVal* representing an optional default
|
||||
/// binding associated with a region and its subregions.
|
||||
Optional<SVal> getDefaultBinding(const GRState *state, const MemRegion *R);
|
||||
|
||||
/// getLValueString - Returns an SVal representing the lvalue of a
|
||||
/// StringLiteral. Within RegionStore a StringLiteral has an
|
||||
/// associated StringRegion, and the lvalue of a StringLiteral is
|
||||
|
@ -829,6 +835,17 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
|
|||
// Loading values from regions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Optional<SVal> RegionStoreManager::getDefaultBinding(const GRState *state,
|
||||
const MemRegion *R) {
|
||||
|
||||
if (R->isBoundable())
|
||||
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R))
|
||||
if (TR->getValueType(getContext())->isUnionType())
|
||||
return UnknownVal();
|
||||
|
||||
return Optional<SVal>::create(state->get<RegionDefaultValue>(R));
|
||||
}
|
||||
|
||||
static bool IsReinterpreted(QualType RTy, QualType UsedTy, ASTContext &Ctx) {
|
||||
RTy = Ctx.getCanonicalType(RTy);
|
||||
UsedTy = Ctx.getCanonicalType(UsedTy);
|
||||
|
@ -911,6 +928,10 @@ RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
|
|||
|
||||
if (RTy->isStructureType())
|
||||
return SValuator::CastResult(state, RetrieveStruct(state, R));
|
||||
|
||||
// FIXME: Handle unions.
|
||||
if (RTy->isUnionType())
|
||||
return SValuator::CastResult(state, UnknownVal());
|
||||
|
||||
if (RTy->isArrayType())
|
||||
return SValuator::CastResult(state, RetrieveArray(state, R));
|
||||
|
@ -1109,7 +1130,7 @@ SVal RegionStoreManager::RetrieveField(const GRState* state,
|
|||
|
||||
const MemRegion* superR = R->getSuperRegion();
|
||||
while (superR) {
|
||||
if (const SVal* D = state->get<RegionDefaultValue>(superR)) {
|
||||
if (const Optional<SVal> &D = getDefaultBinding(state, superR)) {
|
||||
if (SymbolRef parentSym = D->getAsSymbol())
|
||||
return ValMgr.getDerivedRegionValueSymbolVal(parentSym, R);
|
||||
|
||||
|
|
|
@ -32,10 +32,12 @@ extern NSString * const NSConnectionReplyMode;
|
|||
|
||||
// PR 2948 (testcase; crash on VisitLValue for union types)
|
||||
// http://llvm.org/bugs/show_bug.cgi?id=2948
|
||||
|
||||
void checkaccess_union() {
|
||||
int ret = 0, status;
|
||||
if (((((__extension__ (((union { // expected-warning {{ Branch condition evaluates to an uninitialized value.}}
|
||||
// Since RegionStore doesn't handle unions yet,
|
||||
// this branch condition won't be triggered
|
||||
// as involving an uninitialized value.
|
||||
if (((((__extension__ (((union { // no-warning
|
||||
__typeof (status) __in; int __i;}
|
||||
)
|
||||
{
|
||||
|
@ -44,7 +46,6 @@ void checkaccess_union() {
|
|||
ret = 1;
|
||||
}
|
||||
|
||||
|
||||
// Check our handling of fields being invalidated by function calls.
|
||||
struct test2_struct { int x; int y; char* s; };
|
||||
void test2_helper(struct test2_struct* p);
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range %s -verify
|
||||
|
||||
//===-- unions-region.m ---------------------------------------------------===//
|
||||
//
|
||||
// This file tests the analyzer's reasoning about unions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// When using RegionStore, this test case previously had a false positive
|
||||
// of a 'pass-by-value argument is uninitialized' warning at the call to
|
||||
// 'testA_aux'.
|
||||
|
||||
union u_testA {
|
||||
unsigned i;
|
||||
float f;
|
||||
};
|
||||
|
||||
float testA(float f) {
|
||||
int testA_aux(unsigned x);
|
||||
int testA_aux_2(union u_testA z);
|
||||
|
||||
union u_testA swap;
|
||||
swap.f = f;
|
||||
|
||||
if (testA_aux(swap.i)) // no-warning
|
||||
swap.i = ((swap.i & 0xffff0000) >> 16) | ((swap.i & 0x0000fffff) << 16);
|
||||
|
||||
testA_aux_2(swap); // no-warning
|
||||
|
||||
return swap.f;
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче