RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const { // Do we have a decl at all? const Decl *D = getDecl(); if (!D) return RuntimeDefinition(); // If the method is non-virtual, we know we can inline it. const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); if (!MD->isVirtual()) return AnyFunctionCall::getRuntimeDefinition(); // Do we know the implicit 'this' object being called? const MemRegion *R = getCXXThisVal().getAsRegion(); if (!R) return RuntimeDefinition(); // Do we know anything about the type of 'this'? DynamicTypeInfo DynType = getState()->getDynamicTypeInfo(R); if (!DynType.isValid()) return RuntimeDefinition(); // Is the type a C++ class? (This is mostly a defensive check.) QualType RegionType = DynType.getType()->getPointeeType(); assert(!RegionType.isNull() && "DynamicTypeInfo should always be a pointer."); const CXXRecordDecl *RD = RegionType->getAsCXXRecordDecl(); if (!RD || !RD->hasDefinition()) return RuntimeDefinition(); // Find the decl for this method in that class. const CXXMethodDecl *Result = MD->getCorrespondingMethodInClass(RD, true); if (!Result) { // We might not even get the original statically-resolved method due to // some particularly nasty casting (e.g. casts to sister classes). // However, we should at least be able to search up and down our own class // hierarchy, and some real bugs have been caught by checking this. assert(!RD->isDerivedFrom(MD->getParent()) && "Couldn't find known method"); // FIXME: This is checking that our DynamicTypeInfo is at least as good as // the static type. However, because we currently don't update // DynamicTypeInfo when an object is cast, we can't actually be sure the // DynamicTypeInfo is up to date. This assert should be re-enabled once // this is fixed. <rdar://problem/12287087> //assert(!MD->getParent()->isDerivedFrom(RD) && "Bad DynamicTypeInfo"); return RuntimeDefinition(); } // Does the decl that we found have an implementation? const FunctionDecl *Definition; if (!Result->hasBody(Definition)) return RuntimeDefinition(); // 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()) return RuntimeDefinition(Definition, R->StripCasts()); return RuntimeDefinition(Definition, /*DispatchRegion=*/0); }
RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const { // Do we have a decl at all? const Decl *D = getDecl(); if (!D) return RuntimeDefinition(); // If the method is non-virtual, we know we can inline it. const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); if (!MD->isVirtual()) return AnyFunctionCall::getRuntimeDefinition(); // Do we know the implicit 'this' object being called? const MemRegion *R = getCXXThisVal().getAsRegion(); if (!R) return RuntimeDefinition(); // Do we know anything about the type of 'this'? DynamicTypeInfo DynType = getState()->getDynamicTypeInfo(R); if (!DynType.isValid()) return RuntimeDefinition(); // Is the type a C++ class? (This is mostly a defensive check.) QualType RegionType = DynType.getType()->getPointeeType(); const CXXRecordDecl *RD = RegionType->getAsCXXRecordDecl(); if (!RD || !RD->hasDefinition()) return RuntimeDefinition(); // Find the decl for this method in that class. const CXXMethodDecl *Result = MD->getCorrespondingMethodInClass(RD, true); assert(Result && "At the very least the static decl should show up."); // Does the decl that we found have an implementation? const FunctionDecl *Definition; if (!Result->hasBody(Definition)) return RuntimeDefinition(); // 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()) return RuntimeDefinition(Definition, R->StripCasts()); return RuntimeDefinition(Definition, /*DispatchRegion=*/0); }