Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h @@ -30,17 +30,18 @@ namespace ento { /// Get dynamic type information for the region \p MR. -DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR); - -/// Get raw dynamic type information for the region \p MR. -const DynamicTypeInfo *getRawDynamicTypeInfo(ProgramStateRef State, +Optional getDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR); +/// Get the stored dynamic type information for the region \p MR. +Optional getStoredDynamicTypeInfo(ProgramStateRef State, + const MemRegion *MR); + /// Get dynamic cast information from \p CastFromTy to \p CastToTy of \p MR. -const DynamicCastInfo *getDynamicCastInfo(ProgramStateRef State, - const MemRegion *MR, - QualType CastFromTy, - QualType CastToTy); +Optional getDynamicCastInfo(ProgramStateRef State, + const MemRegion *MR, + QualType CastFromTy, + QualType CastToTy); /// Set dynamic type information of the region; return the new state. ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR, Index: clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp @@ -92,7 +92,7 @@ }; } // namespace -static bool isInfeasibleCast(const DynamicCastInfo *CastInfo, +static bool isInfeasibleCast(Optional CastInfo, bool CastSucceeds) { if (!CastInfo) return false; @@ -101,7 +101,7 @@ } static const NoteTag *getNoteTag(CheckerContext &C, - const DynamicCastInfo *CastInfo, + Optional CastInfo, QualType CastToTy, const Expr *Object, bool CastSucceeds, bool IsKnownCast) { std::string CastToName = @@ -182,7 +182,7 @@ } const MemRegion *MR = DV.getAsRegion(); - const DynamicCastInfo *CastInfo = + Optional CastInfo = getDynamicCastInfo(State, MR, CastFromTy, CastToTy); // We assume that every checked cast succeeds. @@ -228,7 +228,7 @@ return; const MemRegion *MR = DV.getAsRegion(); - const DynamicCastInfo *CastInfo = + Optional CastInfo = getDynamicCastInfo(State, MR, CastFromTy, CastToTy); bool CastSucceeds; Index: clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp @@ -93,13 +93,13 @@ ProgramStateRef State = N->getState(); ProgramStateRef StatePrev = N->getFirstPred()->getState(); - DynamicTypeInfo TrackedType = getDynamicTypeInfo(State, Reg); - DynamicTypeInfo TrackedTypePrev = getDynamicTypeInfo(StatePrev, Reg); - if (!TrackedType.isValid()) + Optional TrackedType = getDynamicTypeInfo(State, Reg); + Optional TrackedTypePrev = + getDynamicTypeInfo(StatePrev, Reg); + if (!TrackedType) return nullptr; - if (TrackedTypePrev.isValid() && - TrackedTypePrev.getType() == TrackedType.getType()) + if (TrackedTypePrev && TrackedTypePrev->getType() == TrackedType->getType()) return nullptr; // Retrieve the associated statement. @@ -112,7 +112,7 @@ SmallString<256> Buf; llvm::raw_svector_ostream OS(Buf); OS << "Type '"; - QualType::print(TrackedType.getType().getTypePtr(), Qualifiers(), OS, + QualType::print(TrackedType->getType().getTypePtr(), Qualifiers(), OS, LangOpts, llvm::Twine()); OS << "' is inferred from "; @@ -162,12 +162,12 @@ return; ProgramStateRef State = C.getState(); - DynamicTypeInfo DynTypeInfo = getDynamicTypeInfo(State, Region); + Optional DynTypeInfo = getDynamicTypeInfo(State, Region); - if (!DynTypeInfo.isValid()) + if (!DynTypeInfo) return; - QualType DynType = DynTypeInfo.getType(); + QualType DynType = DynTypeInfo->getType(); QualType StaticType = CE->getType(); const auto *DynObjCType = DynType->getAs(); @@ -192,7 +192,7 @@ if (ASTCtxt.canAssignObjCInterfaces(StaticObjCType, DynObjCType)) return; - if (DynTypeInfo.canBeASubClass() && + if (DynTypeInfo->canBeASubClass() && ASTCtxt.canAssignObjCInterfaces(DynObjCType, StaticObjCType)) return; Index: clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -224,8 +224,9 @@ const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion(); if (!RecReg) return; - DynamicTypeInfo RecDynType = getDynamicTypeInfo(State, RecReg); - C.addTransition(setDynamicTypeInfo(State, RetReg, RecDynType)); + if (Optional RecDynType = + getDynamicTypeInfo(State, RecReg)) + C.addTransition(setDynamicTypeInfo(State, RetReg, *RecDynType)); break; } } @@ -351,12 +352,12 @@ CastE->getType()->getAs(); if (!NewTy) return nullptr; - QualType OldDTy = getDynamicTypeInfo(C.getState(), ToR).getType(); - if (OldDTy.isNull()) { + Optional OldDTy = getDynamicTypeInfo(C.getState(), ToR); + if (!OldDTy) { return NewTy; } const ObjCObjectPointerType *OldTy = - OldDTy->getAs(); + OldDTy->getType()->getAs(); if (!OldTy) return nullptr; @@ -874,7 +875,7 @@ // When there is an entry available for the return symbol in DynamicTypeMap, // the call was inlined, and the information in the DynamicTypeMap is should // be precise. - if (RetRegion && !getRawDynamicTypeInfo(State, RetRegion)) { + if (RetRegion && !getStoredDynamicTypeInfo(State, RetRegion)) { // TODO: we have duplicated information in DynamicTypeMap and // MostSpecializedTypeArgsMap. We should only store anything in the later if // the stored data differs from the one stored in the former. Index: clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp @@ -1912,10 +1912,10 @@ const CXXRecordDecl *getCXXRecordDecl(ProgramStateRef State, const MemRegion *Reg) { auto TI = getDynamicTypeInfo(State, Reg); - if (!TI.isValid()) + if (!TI) return nullptr; - auto Type = TI.getType(); + auto Type = TI->getType(); if (const auto *RefT = Type->getAs()) { Type = RefT->getPointeeType(); } Index: clang/lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -737,12 +737,12 @@ return {}; // Do we know anything about the type of 'this'? - DynamicTypeInfo DynType = getDynamicTypeInfo(getState(), R); - if (!DynType.isValid()) + Optional DynType = getDynamicTypeInfo(getState(), R); + if (!DynType) return {}; // Is the type a C++ class? (This is mostly a defensive check.) - QualType RegionType = DynType.getType()->getPointeeType(); + QualType RegionType = DynType->getType()->getPointeeType(); assert(!RegionType.isNull() && "DynamicTypeInfo should always be a pointer."); const CXXRecordDecl *RD = RegionType->getAsCXXRecordDecl(); @@ -771,7 +771,7 @@ // Does the decl that we found have an implementation? const FunctionDecl *Definition; if (!Result->hasBody(Definition)) { - if (!DynType.canBeASubClass()) + if (!DynType->canBeASubClass()) return AnyFunctionCall::getRuntimeDefinition(); return {}; } @@ -779,7 +779,7 @@ // We found a definition. If we're not sure that this devirtualization is // actually what will happen at runtime, make sure to provide the region so // that ExprEngine can decide what to do with it. - if (DynType.canBeASubClass()) + if (DynType->canBeASubClass()) return RuntimeDefinition(Definition, R->StripCasts()); return RuntimeDefinition(Definition, /*DispatchRegion=*/nullptr); } @@ -1208,15 +1208,15 @@ if (!Receiver) return {}; - DynamicTypeInfo DTI = getDynamicTypeInfo(getState(), Receiver); - if (!DTI.isValid()) { + Optional DTI = getDynamicTypeInfo(getState(), Receiver); + if (!DTI) { assert(isa(Receiver) && "Unhandled untyped region class!"); return {}; } - QualType DynType = DTI.getType(); - CanBeSubClassed = DTI.canBeASubClass(); + QualType DynType = DTI->getType(); + CanBeSubClassed = DTI->canBeASubClass(); ReceiverT = dyn_cast(DynType.getCanonicalType()); if (ReceiverT && CanBeSubClassed) Index: clang/lib/StaticAnalyzer/Core/DynamicType.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/DynamicType.cpp +++ clang/lib/StaticAnalyzer/Core/DynamicType.cpp @@ -37,7 +37,8 @@ namespace clang { namespace ento { -DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR) { +Optional getDynamicTypeInfo(ProgramStateRef State, + const MemRegion *MR) { MR = MR->StripCasts(); // Look up the dynamic type in the GDM. @@ -53,27 +54,30 @@ return DynamicTypeInfo(Sym->getType()); } - return {}; + return None; } -const DynamicTypeInfo *getRawDynamicTypeInfo(ProgramStateRef State, - const MemRegion *MR) { - return State->get(MR); +Optional getStoredDynamicTypeInfo(ProgramStateRef State, + const MemRegion *MR) { + if (const DynamicTypeInfo *DTI = State->get(MR)) + return *DTI; + + return None; } -const DynamicCastInfo *getDynamicCastInfo(ProgramStateRef State, - const MemRegion *MR, - QualType CastFromTy, - QualType CastToTy) { +Optional getDynamicCastInfo(ProgramStateRef State, + const MemRegion *MR, + QualType CastFromTy, + QualType CastToTy) { const auto *Lookup = State->get().lookup(MR); if (!Lookup) - return nullptr; + return None; for (const DynamicCastInfo &Cast : *Lookup) if (Cast.equals(CastFromTy, CastToTy)) - return &Cast; + return Cast; - return nullptr; + return None; } ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR,