SVal StoreManager::getLValueFieldOrIvar(const Decl* D, SVal Base) { if (Base.isUnknownOrUndef()) return Base; Loc BaseL = cast<Loc>(Base); const MemRegion* BaseR = 0; switch (BaseL.getSubKind()) { case loc::MemRegionKind: BaseR = cast<loc::MemRegionVal>(BaseL).getRegion(); break; case loc::GotoLabelKind: // These are anormal cases. Flag an undefined value. return UndefinedVal(); case loc::ConcreteIntKind: // While these seem funny, this can happen through casts. // FIXME: What we should return is the field offset. For example, // add the field offset to the integer value. That way funny things // like this work properly: &(((struct foo *) 0xa)->f) return Base; default: assert(0 && "Unhandled Base."); return Base; } // NOTE: We must have this check first because ObjCIvarDecl is a subclass // of FieldDecl. if (const ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(D)) return loc::MemRegionVal(MRMgr.getObjCIvarRegion(ID, BaseR)); return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR)); }
void HackMazeBitmap(Loc x, Loc y, BitCell *newBits) { arrowImage->data = (char *)newBits; XPutImage(dpy, mwWindow, copyGC, arrowImage, 0, 0, x.value()*16 + MAZE_X_ORIGIN, y.value()*16 + MAZE_Y_ORIGIN, 16, 16); }
SVal GRSimpleVals::EvalEquality(GRExprEngine& Eng, Loc L, Loc R, bool isEqual) { BasicValueFactory& BasicVals = Eng.getBasicVals(); switch (L.getSubKind()) { default: assert(false && "EQ/NE not implemented for this Loc."); return UnknownVal(); case loc::ConcreteIntKind: if (isa<loc::ConcreteInt>(R)) { bool b = cast<loc::ConcreteInt>(L).getValue() == cast<loc::ConcreteInt>(R).getValue(); // Are we computing '!='? Flip the result. if (!isEqual) b = !b; return NonLoc::MakeIntTruthVal(BasicVals, b); } else if (SymbolRef Sym = R.getAsSymbol()) { const SymIntExpr * SE = Eng.getSymbolManager().getSymIntExpr(Sym, isEqual ? BinaryOperator::EQ : BinaryOperator::NE, cast<loc::ConcreteInt>(L).getValue(), Eng.getContext().IntTy); return nonloc::SymExprVal(SE); } break; case loc::MemRegionKind: { if (SymbolRef LSym = L.getAsLocSymbol()) { if (isa<loc::ConcreteInt>(R)) { const SymIntExpr *SE = Eng.getSymbolManager().getSymIntExpr(LSym, isEqual ? BinaryOperator::EQ : BinaryOperator::NE, cast<loc::ConcreteInt>(R).getValue(), Eng.getContext().IntTy); return nonloc::SymExprVal(SE); } } } // Fall-through. case loc::GotoLabelKind: return NonLoc::MakeIntTruthVal(BasicVals, isEqual ? L == R : L != R); } return NonLoc::MakeIntTruthVal(BasicVals, isEqual ? false : true); }
vector<Loc> getMoves(Depth d) { vector<Loc> allMoves; do { Loc l = cc.getNextMove(d); if (!l.isValid()) break; allMoves.push_back(l); } while (true); return allMoves; }
SVal GRSimpleVals::EvalCast(GRExprEngine& Eng, Loc X, QualType T) { // Casts from pointers -> pointers, just return the lval. // // Casts from pointers -> references, just return the lval. These // can be introduced by the frontend for corner cases, e.g // casting from va_list* to __builtin_va_list&. // assert (!X.isUnknownOrUndef()); if (Loc::IsLocType(T) || T->isReferenceType()) return X; // FIXME: Handle transparent unions where a value can be "transparently" // lifted into a union type. if (T->isUnionType()) return UnknownVal(); assert (T->isIntegerType()); BasicValueFactory& BasicVals = Eng.getBasicVals(); unsigned BitWidth = Eng.getContext().getTypeSize(T); if (!isa<loc::ConcreteInt>(X)) return nonloc::LocAsInteger::Make(BasicVals, X, BitWidth); llvm::APSInt V = cast<loc::ConcreteInt>(X).getValue(); V.setIsUnsigned(T->isUnsignedIntegerType() || Loc::IsLocType(T)); V.extOrTrunc(BitWidth); return nonloc::ConcreteInt(BasicVals.getValue(V)); }
void Dsymbol::error(Loc loc, const char *format, ...) { if (!global.gag) { char *p = loc.toChars(); if (!*p) p = locToChars(); if (*p) fprintf(stdmsg, "%s: ", p); mem.free(p); fprintf(stdmsg, "%s %s ", kind(), toPrettyChars()); va_list ap; va_start(ap, format); vfprintf(stdmsg, format, ap); va_end(ap); fprintf(stdmsg, "\n"); fflush(stdmsg); } global.errors++; //fatal(); }
void verror(Loc loc, const char *format, va_list ap) { if (!global.gag) { char *p = loc.toChars(); if (*p) fprintf(stdmsg, "%s: ", p); mem.free(p); fprintf(stdmsg, "Error: "); // MS doesn't recognize %zu format OutBuffer tmp; tmp.vprintf(format, ap); #if _MSC_VER fprintf(stdmsg, "%s", tmp.toChars()); #else vfprintf(stdmsg, format, ap); #endif fprintf(stdmsg, "\n"); fflush(stdmsg); //halt(); } global.errors++; }
void vwarning(Loc loc, const char *format, va_list ap) { if (global.params.warnings && !global.gag) { char *p = loc.toChars(); if (*p) fprintf(stdmsg, "%s: ", p); mem.free(p); fprintf(stdmsg, "Warning: "); #if _MSC_VER // MS doesn't recognize %zu format OutBuffer tmp; tmp.vprintf(format, ap); fprintf(stdmsg, "%s", tmp.toChars()); #else vfprintf(stdmsg, format, ap); #endif fprintf(stdmsg, "\n"); fflush(stdmsg); //halt(); if (global.params.warnings == 1) global.warnings++; // warnings don't count if gagged } }
void Dsymbol::verror(Loc loc, const char *format, va_list ap) { if (!global.gag) { char *p = loc.toChars(); if (!*p) p = locToChars(); if (*p) fprintf(stdmsg, "%s: ", p); mem.free(p); fprintf(stdmsg, "Error: "); fprintf(stdmsg, "%s %s ", kind(), toPrettyChars()); vfprintf(stdmsg, format, ap); fprintf(stdmsg, "\n"); fflush(stdmsg); //halt(); } else { global.gaggedErrors++; } global.errors++; //fatal(); }
SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) { // Casts from pointers -> pointers, just return the lval. // // Casts from pointers -> references, just return the lval. These // can be introduced by the frontend for corner cases, e.g // casting from va_list* to __builtin_va_list&. // if (Loc::isLocType(castTy) || castTy->isReferenceType()) return val; // FIXME: Handle transparent unions where a value can be "transparently" // lifted into a union type. if (castTy->isUnionType()) return UnknownVal(); // Casting a Loc to a bool will almost always be true, // unless this is a weak function or a symbolic region. if (castTy->isBooleanType()) { switch (val.getSubKind()) { case loc::MemRegionValKind: { const MemRegion *R = val.castAs<loc::MemRegionVal>().getRegion(); if (const FunctionCodeRegion *FTR = dyn_cast<FunctionCodeRegion>(R)) if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FTR->getDecl())) if (FD->isWeak()) // FIXME: Currently we are using an extent symbol here, // because there are no generic region address metadata // symbols to use, only content metadata. return nonloc::SymbolVal(SymMgr.getExtentSymbol(FTR)); if (const SymbolicRegion *SymR = R->getSymbolicBase()) return nonloc::SymbolVal(SymR->getSymbol()); // FALL-THROUGH LLVM_FALLTHROUGH; } case loc::GotoLabelKind: // Labels and non-symbolic memory regions are always true. return makeTruthVal(true, castTy); } } if (castTy->isIntegralOrEnumerationType()) { unsigned BitWidth = Context.getTypeSize(castTy); if (!val.getAs<loc::ConcreteInt>()) return makeLocAsInteger(val, BitWidth); llvm::APSInt i = val.castAs<loc::ConcreteInt>().getValue(); BasicVals.getAPSIntType(castTy).apply(i); return makeIntVal(i); } // All other cases: return 'UnknownVal'. This includes casting pointers // to floats, which is probably badness it itself, but this is a good // intermediate solution until we do something better. return UnknownVal(); }
void ModuleEmitter::setUnverifiable(Loc& loc) { if (verifiable_) { //WARNING(loc, "unverifiable code"); warning("%s: unverifiable code", loc.toChars()); } verifiable_ = false; g_haveUnverifiableCode = true; }
ProgramStateRef ProgramState::bindLoc(Loc LV, SVal V, bool notifyChanges) const { ProgramStateManager &Mgr = getStateManager(); ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(), LV, V)); const MemRegion *MR = LV.getAsRegion(); if (MR && Mgr.getOwningEngine() && notifyChanges) return Mgr.getOwningEngine()->processRegionChange(newState, MR); return newState; }
void FuncDeclaration::printGCUsage(Loc loc, const char* warn) { if (!global.params.vgc) return; Module *m = getModule(); if (m && m->isRoot() && !inUnittest()) { fprintf(global.stdmsg, "%s: vgc: %s\n", loc.toChars(), warn); } }
bool onlyOneMain(Loc loc) { static Loc lastLoc; static bool hasMain = false; if (hasMain) { const char *msg = ""; if (global.params.addMain) msg = ", -main switch added another main()"; const char *otherMainNames = ""; if (config.exe == EX_WIN32 || config.exe == EX_WIN64) otherMainNames = "/WinMain/DllMain"; error(loc, "only one main%s allowed%s. Previously found main at %s", otherMainNames, msg, lastLoc.toChars()); return false; } lastLoc = loc; hasMain = true; return true; }
void ShowView(Loc x, Loc y, Direction dir) { register XYpair *tp = viewTable; register int tx = x.value(); register int ty = y.value(); RatIndexType ratIndex(0); RatLook ratLook; bool oldVisible; ClearView(); prevEdge3 = prevEdge7 = FALSE; while (!M->maze_[tx][ty]) { tp = hidden(tx, ty, dir, tp); /* draw a cell */ switch (dir.value()) { case NORTH: tx++; break; case SOUTH: tx--; break; case EAST: ty++; break; case WEST: ty--; break; } } if (prevEdge3) (void) plotLine(edge3Lines, TRUE); if (prevEdge7) (void) plotLine(edge7Lines, TRUE); /* show the tokens */ for (ratIndex = 0; ratIndex < MAX_RATS; ratIndex = RatIndexType(ratIndex.value() + 1)) { if (ratIndex == MY_RAT_INDEX) continue; ratLook = &Rats2Display[ratIndex.value()]; oldVisible = ratLook->visible; TokenVisible(ratIndex); if (ratLook->visible == TRUE) XORToken(ratIndex); if (ratLook->visible != oldVisible) UpdateScoreCard(ratIndex); } }
SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) { if (Base.isUnknownOrUndef()) return Base; Loc BaseL = Base.castAs<Loc>(); const SubRegion* BaseR = nullptr; switch (BaseL.getSubKind()) { case loc::MemRegionValKind: BaseR = cast<SubRegion>(BaseL.castAs<loc::MemRegionVal>().getRegion()); break; case loc::GotoLabelKind: // These are anormal cases. Flag an undefined value. return UndefinedVal(); case loc::ConcreteIntKind: // While these seem funny, this can happen through casts. // FIXME: What we should return is the field offset, not base. For example, // add the field offset to the integer value. That way things // like this work properly: &(((struct foo *) 0xa)->f) // However, that's not easy to fix without reducing our abilities // to catch null pointer dereference. Eg., ((struct foo *)0x0)->f = 7 // is a null dereference even though we're dereferencing offset of f // rather than null. Coming up with an approach that computes offsets // over null pointers properly while still being able to catch null // dereferences might be worth it. return Base; default: llvm_unreachable("Unhandled Base."); } // NOTE: We must have this check first because ObjCIvarDecl is a subclass // of FieldDecl. if (const auto *ID = dyn_cast<ObjCIvarDecl>(D)) return loc::MemRegionVal(MRMgr.getObjCIvarRegion(ID, BaseR)); return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR)); }
Store BasicStoreManager::Remove(Store store, Loc loc) { switch (loc.getSubKind()) { case loc::MemRegionKind: { const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion(); if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R))) return store; return VBFactory.Remove(GetBindings(store), R).getRoot(); } default: assert ("Remove for given Loc type not yet implemented."); return store; } }
void BackEnd::fatalError(Loc& loc, const char* msg) { string prefix; if (const char* p = loc.toChars()) { prefix = p; prefix += ": "; } if (msg) { prefix += msg; prefix += " -- "; } throw std::runtime_error(prefix + "code generation cannot continue"); }
// Need to handle DeclStmts to pick up initializing of iterators and to mark // uninitialized ones as Undefined. void IteratorsChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { const Decl *D = *DS->decl_begin(); const VarDecl *VD = dyn_cast<VarDecl>(D); // Only care about iterators. if (getTemplateKind(VD->getType()) != VectorIteratorKind) return; // Get the MemRegion associated with the iterator and mark it as Undefined. const ProgramState *state = C.getState(); Loc VarLoc = state->getLValue(VD, C.getLocationContext()); const MemRegion *MR = VarLoc.getAsRegion(); if (!MR) return; state = state->set<IteratorState>(MR, RefState::getUndefined()); // if there is an initializer, handle marking Valid if a proper initializer const Expr *InitEx = VD->getInit(); if (InitEx) { // FIXME: This is too syntactic. Since 'InitEx' will be analyzed first // it should resolve to an SVal that we can check for validity // *semantically* instead of walking through the AST. if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(InitEx)) { if (CE->getNumArgs() == 1) { const Expr *E = CE->getArg(0); if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E)) E = M->GetTemporaryExpr(); if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) InitEx = ICE->getSubExpr(); state = handleAssign(state, MR, InitEx, C.getLocationContext()); } } } C.addTransition(state); }
void verror(Loc loc, const char *format, va_list ap) { if (!global.gag) { char *p = loc.toChars(); if (*p) fprintf(stdmsg, "%s: ", p); mem.free(p); fprintf(stdmsg, "Error: "); vfprintf(stdmsg, format, ap); fprintf(stdmsg, "\n"); fflush(stdmsg); } global.errors++; }
ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state, Loc Cond, bool Assumption) { switch (Cond.getSubKind()) { default: assert (false && "'Assume' not implemented for this Loc."); return state; case loc::MemRegionKind: { // FIXME: Should this go into the storemanager? const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion(); const SubRegion *SubR = dyn_cast<SubRegion>(R); while (SubR) { // FIXME: now we only find the first symbolic region. if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) { const llvm::APSInt &zero = getBasicVals().getZeroWithPtrWidth(); if (Assumption) return assumeSymNE(state, SymR->getSymbol(), zero, zero); else return assumeSymEQ(state, SymR->getSymbol(), zero, zero); } SubR = dyn_cast<SubRegion>(SubR->getSuperRegion()); } // FALL-THROUGH. } case loc::GotoLabelKind: return Assumption ? state : NULL; case loc::ConcreteIntKind: { bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0; bool isFeasible = b ? Assumption : !Assumption; return isFeasible ? state : NULL; } } // end switch }
SVal BasicStoreManager::Retrieve(Store store, Loc loc, QualType T) { if (isa<UnknownVal>(loc)) return UnknownVal(); assert(!isa<UndefinedVal>(loc)); switch (loc.getSubKind()) { case loc::MemRegionKind: { const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion(); if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R))) return UnknownVal(); BindingsTy B = GetBindings(store); BindingsTy::data_type *Val = B.lookup(R); const TypedRegion *TR = cast<TypedRegion>(R); if (Val) return CastRetrievedVal(*Val, TR, T); SVal V = LazyRetrieve(store, TR); return V.isUnknownOrUndef() ? V : CastRetrievedVal(V, TR, T); } case loc::ConcreteIntKind: // Some clients may call GetSVal with such an option simply because // they are doing a quick scan through their Locs (potentially to // invalidate their bindings). Just return Undefined. return UndefinedVal(); default: assert (false && "Invalid Loc."); break; } return UnknownVal(); }
// FIXME: all this logic will change if/when we have MemRegion::getLocation(). SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, Loc rhs, QualType resultTy) { // Only comparisons and subtractions are valid operations on two pointers. // See [C99 6.5.5 through 6.5.14] or [C++0x 5.6 through 5.15]. // However, if a pointer is casted to an integer, evalBinOpNN may end up // calling this function with another operation (PR7527). We don't attempt to // model this for now, but it could be useful, particularly when the // "location" is actually an integer value that's been passed through a void*. if (!(BinaryOperator::isComparisonOp(op) || op == BO_Sub)) return UnknownVal(); // Special cases for when both sides are identical. if (lhs == rhs) { switch (op) { default: llvm_unreachable("Unimplemented operation for two identical values"); case BO_Sub: return makeZeroVal(resultTy); case BO_EQ: case BO_LE: case BO_GE: return makeTruthVal(true, resultTy); case BO_NE: case BO_LT: case BO_GT: return makeTruthVal(false, resultTy); } } switch (lhs.getSubKind()) { default: llvm_unreachable("Ordering not implemented for this Loc."); case loc::GotoLabelKind: // The only thing we know about labels is that they're non-null. if (rhs.isZeroConstant()) { switch (op) { default: break; case BO_Sub: return evalCastFromLoc(lhs, resultTy); case BO_EQ: case BO_LE: case BO_LT: return makeTruthVal(false, resultTy); case BO_NE: case BO_GT: case BO_GE: return makeTruthVal(true, resultTy); } } // There may be two labels for the same location, and a function region may // have the same address as a label at the start of the function (depending // on the ABI). // FIXME: we can probably do a comparison against other MemRegions, though. // FIXME: is there a way to tell if two labels refer to the same location? return UnknownVal(); case loc::ConcreteIntKind: { // If one of the operands is a symbol and the other is a constant, // build an expression for use by the constraint manager. if (SymbolRef rSym = rhs.getAsLocSymbol()) { // We can only build expressions with symbols on the left, // so we need a reversible operator. if (!BinaryOperator::isComparisonOp(op)) return UnknownVal(); const llvm::APSInt &lVal = cast<loc::ConcreteInt>(lhs).getValue(); return makeNonLoc(rSym, ReverseComparison(op), lVal, resultTy); } // If both operands are constants, just perform the operation. if (loc::ConcreteInt *rInt = dyn_cast<loc::ConcreteInt>(&rhs)) { SVal ResultVal = cast<loc::ConcreteInt>(lhs).evalBinOp(BasicVals, op, *rInt); if (Loc *Result = dyn_cast<Loc>(&ResultVal)) return evalCastFromLoc(*Result, resultTy); else return UnknownVal(); } // Special case comparisons against NULL. // This must come after the test if the RHS is a symbol, which is used to // build constraints. The address of any non-symbolic region is guaranteed // to be non-NULL, as is any label. assert(isa<loc::MemRegionVal>(rhs) || isa<loc::GotoLabel>(rhs)); if (lhs.isZeroConstant()) { switch (op) { default: break; case BO_EQ: case BO_GT: case BO_GE: return makeTruthVal(false, resultTy); case BO_NE: case BO_LT: case BO_LE: return makeTruthVal(true, resultTy); } } // Comparing an arbitrary integer to a region or label address is // completely unknowable. return UnknownVal(); } case loc::MemRegionKind: { if (loc::ConcreteInt *rInt = dyn_cast<loc::ConcreteInt>(&rhs)) { // If one of the operands is a symbol and the other is a constant, // build an expression for use by the constraint manager. if (SymbolRef lSym = lhs.getAsLocSymbol()) return MakeSymIntVal(lSym, op, rInt->getValue(), resultTy); // Special case comparisons to NULL. // This must come after the test if the LHS is a symbol, which is used to // build constraints. The address of any non-symbolic region is guaranteed // to be non-NULL. if (rInt->isZeroConstant()) { switch (op) { default: break; case BO_Sub: return evalCastFromLoc(lhs, resultTy); case BO_EQ: case BO_LT: case BO_LE: return makeTruthVal(false, resultTy); case BO_NE: case BO_GT: case BO_GE: return makeTruthVal(true, resultTy); } } // Comparing a region to an arbitrary integer is completely unknowable. return UnknownVal(); } // Get both values as regions, if possible. const MemRegion *LeftMR = lhs.getAsRegion(); assert(LeftMR && "MemRegionKind SVal doesn't have a region!"); const MemRegion *RightMR = rhs.getAsRegion(); if (!RightMR) // The RHS is probably a label, which in theory could address a region. // FIXME: we can probably make a more useful statement about non-code // regions, though. return UnknownVal(); const MemSpaceRegion *LeftMS = LeftMR->getMemorySpace(); const MemSpaceRegion *RightMS = RightMR->getMemorySpace(); const MemSpaceRegion *UnknownMS = MemMgr.getUnknownRegion(); const MemRegion *LeftBase = LeftMR->getBaseRegion(); const MemRegion *RightBase = RightMR->getBaseRegion(); // If the two regions are from different known memory spaces they cannot be // equal. Also, assume that no symbolic region (whose memory space is // unknown) is on the stack. if (LeftMS != RightMS && ((LeftMS != UnknownMS && RightMS != UnknownMS) || (isa<StackSpaceRegion>(LeftMS) || isa<StackSpaceRegion>(RightMS)))) { switch (op) { default: return UnknownVal(); case BO_EQ: return makeTruthVal(false, resultTy); case BO_NE: return makeTruthVal(true, resultTy); } } // If both values wrap regions, see if they're from different base regions. // Note, heap base symbolic regions are assumed to not alias with // each other; for example, we assume that malloc returns different address // on each invocation. if (LeftBase != RightBase && ((!isa<SymbolicRegion>(LeftBase) && !isa<SymbolicRegion>(RightBase)) || (isa<HeapSpaceRegion>(LeftMS) || isa<HeapSpaceRegion>(RightMS))) ){ switch (op) { default: return UnknownVal(); case BO_EQ: return makeTruthVal(false, resultTy); case BO_NE: return makeTruthVal(true, resultTy); } } // FIXME: If/when there is a getAsRawOffset() for FieldRegions, this // ElementRegion path and the FieldRegion path below should be unified. if (const ElementRegion *LeftER = dyn_cast<ElementRegion>(LeftMR)) { // First see if the right region is also an ElementRegion. const ElementRegion *RightER = dyn_cast<ElementRegion>(RightMR); if (!RightER) return UnknownVal(); // Next, see if the two ERs have the same super-region and matching types. // FIXME: This should do something useful even if the types don't match, // though if both indexes are constant the RegionRawOffset path will // give the correct answer. if (LeftER->getSuperRegion() == RightER->getSuperRegion() && LeftER->getElementType() == RightER->getElementType()) { // Get the left index and cast it to the correct type. // If the index is unknown or undefined, bail out here. SVal LeftIndexVal = LeftER->getIndex(); NonLoc *LeftIndex = dyn_cast<NonLoc>(&LeftIndexVal); if (!LeftIndex) return UnknownVal(); LeftIndexVal = evalCastFromNonLoc(*LeftIndex, resultTy); LeftIndex = dyn_cast<NonLoc>(&LeftIndexVal); if (!LeftIndex) return UnknownVal(); // Do the same for the right index. SVal RightIndexVal = RightER->getIndex(); NonLoc *RightIndex = dyn_cast<NonLoc>(&RightIndexVal); if (!RightIndex) return UnknownVal(); RightIndexVal = evalCastFromNonLoc(*RightIndex, resultTy); RightIndex = dyn_cast<NonLoc>(&RightIndexVal); if (!RightIndex) return UnknownVal(); // Actually perform the operation. // evalBinOpNN expects the two indexes to already be the right type. return evalBinOpNN(state, op, *LeftIndex, *RightIndex, resultTy); } // If the element indexes aren't comparable, see if the raw offsets are. RegionRawOffset LeftOffset = LeftER->getAsArrayOffset(); RegionRawOffset RightOffset = RightER->getAsArrayOffset(); if (LeftOffset.getRegion() != NULL && LeftOffset.getRegion() == RightOffset.getRegion()) { CharUnits left = LeftOffset.getOffset(); CharUnits right = RightOffset.getOffset(); switch (op) { default: return UnknownVal(); case BO_LT: return makeTruthVal(left < right, resultTy); case BO_GT: return makeTruthVal(left > right, resultTy); case BO_LE: return makeTruthVal(left <= right, resultTy); case BO_GE: return makeTruthVal(left >= right, resultTy); case BO_EQ: return makeTruthVal(left == right, resultTy); case BO_NE: return makeTruthVal(left != right, resultTy); } } // If we get here, we have no way of comparing the ElementRegions. return UnknownVal(); } // See if both regions are fields of the same structure. // FIXME: This doesn't handle nesting, inheritance, or Objective-C ivars. if (const FieldRegion *LeftFR = dyn_cast<FieldRegion>(LeftMR)) { // Only comparisons are meaningful here! if (!BinaryOperator::isComparisonOp(op)) return UnknownVal(); // First see if the right region is also a FieldRegion. const FieldRegion *RightFR = dyn_cast<FieldRegion>(RightMR); if (!RightFR) return UnknownVal(); // Next, see if the two FRs have the same super-region. // FIXME: This doesn't handle casts yet, and simply stripping the casts // doesn't help. if (LeftFR->getSuperRegion() != RightFR->getSuperRegion()) return UnknownVal(); const FieldDecl *LeftFD = LeftFR->getDecl(); const FieldDecl *RightFD = RightFR->getDecl(); const RecordDecl *RD = LeftFD->getParent(); // Make sure the two FRs are from the same kind of record. Just in case! // FIXME: This is probably where inheritance would be a problem. if (RD != RightFD->getParent()) return UnknownVal(); // We know for sure that the two fields are not the same, since that // would have given us the same SVal. if (op == BO_EQ) return makeTruthVal(false, resultTy); if (op == BO_NE) return makeTruthVal(true, resultTy); // Iterate through the fields and see which one comes first. // [C99 6.7.2.1.13] "Within a structure object, the non-bit-field // members and the units in which bit-fields reside have addresses that // increase in the order in which they are declared." bool leftFirst = (op == BO_LT || op == BO_LE); for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); I!=E; ++I) { if (*I == LeftFD) return makeTruthVal(leftFirst, resultTy); if (*I == RightFD) return makeTruthVal(!leftFirst, resultTy); } llvm_unreachable("Fields not found in parent record's definition"); } // If we get here, we have no way of comparing the regions. return UnknownVal(); } } }
SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, NonLoc rhs, QualType resultTy) { assert(!BinaryOperator::isComparisonOp(op) && "arguments to comparison ops must be of the same type"); // Special case: rhs is a zero constant. if (rhs.isZeroConstant()) return lhs; // We are dealing with pointer arithmetic. // Handle pointer arithmetic on constant values. if (Optional<nonloc::ConcreteInt> rhsInt = rhs.getAs<nonloc::ConcreteInt>()) { if (Optional<loc::ConcreteInt> lhsInt = lhs.getAs<loc::ConcreteInt>()) { const llvm::APSInt &leftI = lhsInt->getValue(); assert(leftI.isUnsigned()); llvm::APSInt rightI(rhsInt->getValue(), /* isUnsigned */ true); // Convert the bitwidth of rightI. This should deal with overflow // since we are dealing with concrete values. rightI = rightI.extOrTrunc(leftI.getBitWidth()); // Offset the increment by the pointer size. llvm::APSInt Multiplicand(rightI.getBitWidth(), /* isUnsigned */ true); rightI *= Multiplicand; // Compute the adjusted pointer. switch (op) { case BO_Add: rightI = leftI + rightI; break; case BO_Sub: rightI = leftI - rightI; break; default: llvm_unreachable("Invalid pointer arithmetic operation"); } return loc::ConcreteInt(getBasicValueFactory().getValue(rightI)); } } // Handle cases where 'lhs' is a region. if (const MemRegion *region = lhs.getAsRegion()) { rhs = convertToArrayIndex(rhs).castAs<NonLoc>(); SVal index = UnknownVal(); const MemRegion *superR = 0; QualType elementType; if (const ElementRegion *elemReg = dyn_cast<ElementRegion>(region)) { assert(op == BO_Add || op == BO_Sub); index = evalBinOpNN(state, op, elemReg->getIndex(), rhs, getArrayIndexType()); superR = elemReg->getSuperRegion(); elementType = elemReg->getElementType(); } else if (isa<SubRegion>(region)) { superR = region; index = rhs; if (resultTy->isAnyPointerType()) elementType = resultTy->getPointeeType(); } if (Optional<NonLoc> indexV = index.getAs<NonLoc>()) { return loc::MemRegionVal(MemMgr.getElementRegion(elementType, *indexV, superR, getContext())); } } return UnknownVal(); }
SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, NonLoc rhs, QualType resultTy) { if (op >= BO_PtrMemD && op <= BO_PtrMemI) { if (auto PTMSV = rhs.getAs<nonloc::PointerToMember>()) { if (PTMSV->isNullMemberPointer()) return UndefinedVal(); if (const FieldDecl *FD = PTMSV->getDeclAs<FieldDecl>()) { SVal Result = lhs; for (const auto &I : *PTMSV) Result = StateMgr.getStoreManager().evalDerivedToBase( Result, I->getType(),I->isVirtual()); return state->getLValue(FD, Result); } } return rhs; } assert(!BinaryOperator::isComparisonOp(op) && "arguments to comparison ops must be of the same type"); // Special case: rhs is a zero constant. if (rhs.isZeroConstant()) return lhs; // We are dealing with pointer arithmetic. // Handle pointer arithmetic on constant values. if (Optional<nonloc::ConcreteInt> rhsInt = rhs.getAs<nonloc::ConcreteInt>()) { if (Optional<loc::ConcreteInt> lhsInt = lhs.getAs<loc::ConcreteInt>()) { const llvm::APSInt &leftI = lhsInt->getValue(); assert(leftI.isUnsigned()); llvm::APSInt rightI(rhsInt->getValue(), /* isUnsigned */ true); // Convert the bitwidth of rightI. This should deal with overflow // since we are dealing with concrete values. rightI = rightI.extOrTrunc(leftI.getBitWidth()); // Offset the increment by the pointer size. llvm::APSInt Multiplicand(rightI.getBitWidth(), /* isUnsigned */ true); rightI *= Multiplicand; // Compute the adjusted pointer. switch (op) { case BO_Add: rightI = leftI + rightI; break; case BO_Sub: rightI = leftI - rightI; break; default: llvm_unreachable("Invalid pointer arithmetic operation"); } return loc::ConcreteInt(getBasicValueFactory().getValue(rightI)); } } // Handle cases where 'lhs' is a region. if (const MemRegion *region = lhs.getAsRegion()) { rhs = convertToArrayIndex(rhs).castAs<NonLoc>(); SVal index = UnknownVal(); const MemRegion *superR = nullptr; // We need to know the type of the pointer in order to add an integer to it. // Depending on the type, different amount of bytes is added. QualType elementType; if (const ElementRegion *elemReg = dyn_cast<ElementRegion>(region)) { assert(op == BO_Add || op == BO_Sub); index = evalBinOpNN(state, op, elemReg->getIndex(), rhs, getArrayIndexType()); superR = elemReg->getSuperRegion(); elementType = elemReg->getElementType(); } else if (isa<SubRegion>(region)) { assert(op == BO_Add || op == BO_Sub); index = (op == BO_Add) ? rhs : evalMinus(rhs); superR = region; // TODO: Is this actually reliable? Maybe improving our MemRegion // hierarchy to provide typed regions for all non-void pointers would be // better. For instance, we cannot extend this towards LocAsInteger // operations, where result type of the expression is integer. if (resultTy->isAnyPointerType()) elementType = resultTy->getPointeeType(); } if (Optional<NonLoc> indexV = index.getAs<NonLoc>()) { return loc::MemRegionVal(MemMgr.getElementRegion(elementType, *indexV, superR, getContext())); } } return UnknownVal(); }
// FIXME: all this logic will change if/when we have MemRegion::getLocation(). SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, Loc rhs, QualType resultTy) { // Only comparisons and subtractions are valid operations on two pointers. // See [C99 6.5.5 through 6.5.14] or [C++0x 5.6 through 5.15]. // However, if a pointer is casted to an integer, evalBinOpNN may end up // calling this function with another operation (PR7527). We don't attempt to // model this for now, but it could be useful, particularly when the // "location" is actually an integer value that's been passed through a void*. if (!(BinaryOperator::isComparisonOp(op) || op == BO_Sub)) return UnknownVal(); // Special cases for when both sides are identical. if (lhs == rhs) { switch (op) { default: llvm_unreachable("Unimplemented operation for two identical values"); case BO_Sub: return makeZeroVal(resultTy); case BO_EQ: case BO_LE: case BO_GE: return makeTruthVal(true, resultTy); case BO_NE: case BO_LT: case BO_GT: return makeTruthVal(false, resultTy); } } switch (lhs.getSubKind()) { default: llvm_unreachable("Ordering not implemented for this Loc."); case loc::GotoLabelKind: // The only thing we know about labels is that they're non-null. if (rhs.isZeroConstant()) { switch (op) { default: break; case BO_Sub: return evalCastFromLoc(lhs, resultTy); case BO_EQ: case BO_LE: case BO_LT: return makeTruthVal(false, resultTy); case BO_NE: case BO_GT: case BO_GE: return makeTruthVal(true, resultTy); } } // There may be two labels for the same location, and a function region may // have the same address as a label at the start of the function (depending // on the ABI). // FIXME: we can probably do a comparison against other MemRegions, though. // FIXME: is there a way to tell if two labels refer to the same location? return UnknownVal(); case loc::ConcreteIntKind: { // If one of the operands is a symbol and the other is a constant, // build an expression for use by the constraint manager. if (SymbolRef rSym = rhs.getAsLocSymbol()) { // We can only build expressions with symbols on the left, // so we need a reversible operator. if (!BinaryOperator::isComparisonOp(op)) return UnknownVal(); const llvm::APSInt &lVal = lhs.castAs<loc::ConcreteInt>().getValue(); op = BinaryOperator::reverseComparisonOp(op); return makeNonLoc(rSym, op, lVal, resultTy); } // If both operands are constants, just perform the operation. if (Optional<loc::ConcreteInt> rInt = rhs.getAs<loc::ConcreteInt>()) { SVal ResultVal = lhs.castAs<loc::ConcreteInt>().evalBinOp(BasicVals, op, *rInt); if (Optional<NonLoc> Result = ResultVal.getAs<NonLoc>()) return evalCastFromNonLoc(*Result, resultTy); assert(!ResultVal.getAs<Loc>() && "Loc-Loc ops should not produce Locs"); return UnknownVal(); } // Special case comparisons against NULL. // This must come after the test if the RHS is a symbol, which is used to // build constraints. The address of any non-symbolic region is guaranteed // to be non-NULL, as is any label. assert(rhs.getAs<loc::MemRegionVal>() || rhs.getAs<loc::GotoLabel>()); if (lhs.isZeroConstant()) { switch (op) { default: break; case BO_EQ: case BO_GT: case BO_GE: return makeTruthVal(false, resultTy); case BO_NE: case BO_LT: case BO_LE: return makeTruthVal(true, resultTy); } } // Comparing an arbitrary integer to a region or label address is // completely unknowable. return UnknownVal(); } case loc::MemRegionValKind: { if (Optional<loc::ConcreteInt> rInt = rhs.getAs<loc::ConcreteInt>()) { // If one of the operands is a symbol and the other is a constant, // build an expression for use by the constraint manager. if (SymbolRef lSym = lhs.getAsLocSymbol(true)) return MakeSymIntVal(lSym, op, rInt->getValue(), resultTy); // Special case comparisons to NULL. // This must come after the test if the LHS is a symbol, which is used to // build constraints. The address of any non-symbolic region is guaranteed // to be non-NULL. if (rInt->isZeroConstant()) { if (op == BO_Sub) return evalCastFromLoc(lhs, resultTy); if (BinaryOperator::isComparisonOp(op)) { QualType boolType = getContext().BoolTy; NonLoc l = evalCastFromLoc(lhs, boolType).castAs<NonLoc>(); NonLoc r = makeTruthVal(false, boolType).castAs<NonLoc>(); return evalBinOpNN(state, op, l, r, resultTy); } } // Comparing a region to an arbitrary integer is completely unknowable. return UnknownVal(); } // Get both values as regions, if possible. const MemRegion *LeftMR = lhs.getAsRegion(); assert(LeftMR && "MemRegionValKind SVal doesn't have a region!"); const MemRegion *RightMR = rhs.getAsRegion(); if (!RightMR) // The RHS is probably a label, which in theory could address a region. // FIXME: we can probably make a more useful statement about non-code // regions, though. return UnknownVal(); const MemRegion *LeftBase = LeftMR->getBaseRegion(); const MemRegion *RightBase = RightMR->getBaseRegion(); const MemSpaceRegion *LeftMS = LeftBase->getMemorySpace(); const MemSpaceRegion *RightMS = RightBase->getMemorySpace(); const MemSpaceRegion *UnknownMS = MemMgr.getUnknownRegion(); // If the two regions are from different known memory spaces they cannot be // equal. Also, assume that no symbolic region (whose memory space is // unknown) is on the stack. if (LeftMS != RightMS && ((LeftMS != UnknownMS && RightMS != UnknownMS) || (isa<StackSpaceRegion>(LeftMS) || isa<StackSpaceRegion>(RightMS)))) { switch (op) { default: return UnknownVal(); case BO_EQ: return makeTruthVal(false, resultTy); case BO_NE: return makeTruthVal(true, resultTy); } } // If both values wrap regions, see if they're from different base regions. // Note, heap base symbolic regions are assumed to not alias with // each other; for example, we assume that malloc returns different address // on each invocation. // FIXME: ObjC object pointers always reside on the heap, but currently // we treat their memory space as unknown, because symbolic pointers // to ObjC objects may alias. There should be a way to construct // possibly-aliasing heap-based regions. For instance, MacOSXApiChecker // guesses memory space for ObjC object pointers manually instead of // relying on us. if (LeftBase != RightBase && ((!isa<SymbolicRegion>(LeftBase) && !isa<SymbolicRegion>(RightBase)) || (isa<HeapSpaceRegion>(LeftMS) || isa<HeapSpaceRegion>(RightMS))) ){ switch (op) { default: return UnknownVal(); case BO_EQ: return makeTruthVal(false, resultTy); case BO_NE: return makeTruthVal(true, resultTy); } } // Handle special cases for when both regions are element regions. const ElementRegion *RightER = dyn_cast<ElementRegion>(RightMR); const ElementRegion *LeftER = dyn_cast<ElementRegion>(LeftMR); if (RightER && LeftER) { // Next, see if the two ERs have the same super-region and matching types. // FIXME: This should do something useful even if the types don't match, // though if both indexes are constant the RegionRawOffset path will // give the correct answer. if (LeftER->getSuperRegion() == RightER->getSuperRegion() && LeftER->getElementType() == RightER->getElementType()) { // Get the left index and cast it to the correct type. // If the index is unknown or undefined, bail out here. SVal LeftIndexVal = LeftER->getIndex(); Optional<NonLoc> LeftIndex = LeftIndexVal.getAs<NonLoc>(); if (!LeftIndex) return UnknownVal(); LeftIndexVal = evalCastFromNonLoc(*LeftIndex, ArrayIndexTy); LeftIndex = LeftIndexVal.getAs<NonLoc>(); if (!LeftIndex) return UnknownVal(); // Do the same for the right index. SVal RightIndexVal = RightER->getIndex(); Optional<NonLoc> RightIndex = RightIndexVal.getAs<NonLoc>(); if (!RightIndex) return UnknownVal(); RightIndexVal = evalCastFromNonLoc(*RightIndex, ArrayIndexTy); RightIndex = RightIndexVal.getAs<NonLoc>(); if (!RightIndex) return UnknownVal(); // Actually perform the operation. // evalBinOpNN expects the two indexes to already be the right type. return evalBinOpNN(state, op, *LeftIndex, *RightIndex, resultTy); } } // Special handling of the FieldRegions, even with symbolic offsets. const FieldRegion *RightFR = dyn_cast<FieldRegion>(RightMR); const FieldRegion *LeftFR = dyn_cast<FieldRegion>(LeftMR); if (RightFR && LeftFR) { SVal R = evalBinOpFieldRegionFieldRegion(LeftFR, RightFR, op, resultTy, *this); if (!R.isUnknown()) return R; } // Compare the regions using the raw offsets. RegionOffset LeftOffset = LeftMR->getAsOffset(); RegionOffset RightOffset = RightMR->getAsOffset(); if (LeftOffset.getRegion() != nullptr && LeftOffset.getRegion() == RightOffset.getRegion() && !LeftOffset.hasSymbolicOffset() && !RightOffset.hasSymbolicOffset()) { int64_t left = LeftOffset.getOffset(); int64_t right = RightOffset.getOffset(); switch (op) { default: return UnknownVal(); case BO_LT: return makeTruthVal(left < right, resultTy); case BO_GT: return makeTruthVal(left > right, resultTy); case BO_LE: return makeTruthVal(left <= right, resultTy); case BO_GE: return makeTruthVal(left >= right, resultTy); case BO_EQ: return makeTruthVal(left == right, resultTy); case BO_NE: return makeTruthVal(left != right, resultTy); } } // At this point we're not going to get a good answer, but we can try // conjuring an expression instead. SymbolRef LHSSym = lhs.getAsLocSymbol(); SymbolRef RHSSym = rhs.getAsLocSymbol(); if (LHSSym && RHSSym) return makeNonLoc(LHSSym, op, RHSSym, resultTy); // If we get here, we have no way of comparing the regions. return UnknownVal(); } } }
SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, NonLoc rhs, QualType resultTy) { // Special case: rhs is a zero constant. if (rhs.isZeroConstant()) return lhs; // Special case: 'rhs' is an integer that has the same width as a pointer and // we are using the integer location in a comparison. Normally this cannot be // triggered, but transfer functions like those for OSCommpareAndSwapBarrier32 // can generate comparisons that trigger this code. // FIXME: Are all locations guaranteed to have pointer width? if (BinaryOperator::isComparisonOp(op)) { if (nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs)) { const llvm::APSInt *x = &rhsInt->getValue(); ASTContext &ctx = Context; if (ctx.getTypeSize(ctx.VoidPtrTy) == x->getBitWidth()) { // Convert the signedness of the integer (if necessary). if (x->isSigned()) x = &getBasicValueFactory().getValue(*x, true); return evalBinOpLL(state, op, lhs, loc::ConcreteInt(*x), resultTy); } } return UnknownVal(); } // We are dealing with pointer arithmetic. // Handle pointer arithmetic on constant values. if (nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs)) { if (loc::ConcreteInt *lhsInt = dyn_cast<loc::ConcreteInt>(&lhs)) { const llvm::APSInt &leftI = lhsInt->getValue(); assert(leftI.isUnsigned()); llvm::APSInt rightI(rhsInt->getValue(), /* isUnsigned */ true); // Convert the bitwidth of rightI. This should deal with overflow // since we are dealing with concrete values. rightI = rightI.extOrTrunc(leftI.getBitWidth()); // Offset the increment by the pointer size. llvm::APSInt Multiplicand(rightI.getBitWidth(), /* isUnsigned */ true); rightI *= Multiplicand; // Compute the adjusted pointer. switch (op) { case BO_Add: rightI = leftI + rightI; break; case BO_Sub: rightI = leftI - rightI; break; default: llvm_unreachable("Invalid pointer arithmetic operation"); } return loc::ConcreteInt(getBasicValueFactory().getValue(rightI)); } } // Handle cases where 'lhs' is a region. if (const MemRegion *region = lhs.getAsRegion()) { rhs = cast<NonLoc>(convertToArrayIndex(rhs)); SVal index = UnknownVal(); const MemRegion *superR = 0; QualType elementType; if (const ElementRegion *elemReg = dyn_cast<ElementRegion>(region)) { assert(op == BO_Add || op == BO_Sub); index = evalBinOpNN(state, op, elemReg->getIndex(), rhs, getArrayIndexType()); superR = elemReg->getSuperRegion(); elementType = elemReg->getElementType(); } else if (isa<SubRegion>(region)) { superR = region; index = rhs; if (resultTy->isAnyPointerType()) elementType = resultTy->getPointeeType(); } if (NonLoc *indexV = dyn_cast<NonLoc>(&index)) { return loc::MemRegionVal(MemMgr.getElementRegion(elementType, *indexV, superR, getContext())); } } return UnknownVal(); }
// intialize bool PointsOOC::init() { cerr << "PointsOOC::PointsOOC" << endl; // enable osg debugging //osg::setNotifyLevel( osg::INFO ); _mainMenu = new SubMenu("PointsOOC", "PointsOOC"); _mainMenu->setCallback(this); _loadMenu = new SubMenu("Load","Load"); _loadMenu->setCallback(this); _mainMenu->addItem(_loadMenu); _removeButton = new MenuButton("Remove All"); _removeButton->setCallback(this); _mainMenu->addItem(_removeButton); MenuSystem::instance()->addMenuItem(_mainMenu); vector<string> list; string configBase = "Plugin.PointsOOC.Files"; ConfigManager::getChildren(configBase, list); for(int i = 0; i < list.size(); i++) { MenuButton * button = new MenuButton(list[i]); button->setCallback(this); _loadMenu->addItem(button); _menuFileList.push_back(button); std::string path = ConfigManager::getEntry("value", configBase + "." + list[i], ""); _filePaths.push_back(path); //std::cout << path << std::endl; } // load saved initial scales and locations _configPath = ConfigManager::getEntry("Plugin.PointsOOC.ConfigDir"); ifstream cfile; cfile.open((_configPath + "/PointsOOCInit.cfg").c_str(), ios::in); if(!cfile.fail()) { string line; while(!cfile.eof()) { Loc l; l.pointFunc[0] = 1.0; l.pointFunc[1] = 0.0; char name[150]; cfile >> name; if(cfile.eof()) { break; } cfile >> l.pointSize; cfile >> l.shaderSize; cfile >> l.pointFunc[2]; cfile >> l.pointAlpha; cfile >> l.shaderEnabled; for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { cfile >> l.pos(i, j); } } _locInit[string(name)] = l; } }