--- /dev/null
+//===-- 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
#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"
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
// 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);
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));
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);
// 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;}
)
{
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);
--- /dev/null
+// 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;
+}
+