summaryrefslogtreecommitdiffstats
path: root/lib/StaticAnalyzer/Core/CallEvent.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-11-24 09:15:30 +0000
committerdim <dim@FreeBSD.org>2014-11-24 09:15:30 +0000
commit173a4f43a911175643bda81ee675e8d9269056ea (patch)
tree47df2c12b57214af6c31e47404b005675b8b7ffc /lib/StaticAnalyzer/Core/CallEvent.cpp
parent88f7a7d5251a2d813460274c92decc143a11569b (diff)
downloadFreeBSD-src-173a4f43a911175643bda81ee675e8d9269056ea.zip
FreeBSD-src-173a4f43a911175643bda81ee675e8d9269056ea.tar.gz
Vendor import of clang RELEASE_350/final tag r216957 (effectively, 3.5.0 release):
https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_350/final@216957
Diffstat (limited to 'lib/StaticAnalyzer/Core/CallEvent.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/CallEvent.cpp122
1 files changed, 57 insertions, 65 deletions
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp
index a3b34f4..7e0670a 100644
--- a/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -68,8 +68,7 @@ static bool isCallbackArg(SVal V, QualType T) {
if (const RecordType *RT = T->getAsStructureType()) {
const RecordDecl *RD = RT->getDecl();
- for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I) {
+ for (const auto *I : RD->fields()) {
QualType FieldT = I->getType();
if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType())
return true;
@@ -140,6 +139,11 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
ProgramStateRef Orig) const {
ProgramStateRef Result = (Orig ? Orig : getState());
+ // Don't invalidate anything if the callee is marked pure/const.
+ if (const Decl *callee = getDecl())
+ if (callee->hasAttr<PureAttr>() || callee->hasAttr<ConstAttr>())
+ return Result;
+
SmallVector<SVal, 8> ValuesToInvalidate;
RegionAndSymbolInvalidationTraits ETraits;
@@ -168,7 +172,7 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
return Result->invalidateRegions(ValuesToInvalidate, getOriginExpr(),
BlockCount, getLocationContext(),
/*CausedByPointerEscape*/ true,
- /*Symbols=*/0, this, &ETraits);
+ /*Symbols=*/nullptr, this, &ETraits);
}
ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
@@ -209,14 +213,12 @@ SVal CallEvent::getReturnValue() const {
return getSVal(E);
}
-void CallEvent::dump() const {
- dump(llvm::errs());
-}
+LLVM_DUMP_METHOD void CallEvent::dump() const { dump(llvm::errs()); }
void CallEvent::dump(raw_ostream &Out) const {
ASTContext &Ctx = getState()->getStateManager().getContext();
if (const Expr *E = getOriginExpr()) {
- E->printPretty(Out, 0, Ctx.getPrintingPolicy());
+ E->printPretty(Out, nullptr, Ctx.getPrintingPolicy());
Out << "\n";
return;
}
@@ -241,9 +243,9 @@ bool CallEvent::isCallStmt(const Stmt *S) {
QualType CallEvent::getDeclaredResultType(const Decl *D) {
assert(D);
if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D))
- return FD->getResultType();
+ return FD->getReturnType();
if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D))
- return MD->getResultType();
+ return MD->getReturnType();
if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
// Blocks are difficult because the return type may not be stored in the
// BlockDecl itself. The AST should probably be enhanced, but for now we
@@ -256,7 +258,7 @@ QualType CallEvent::getDeclaredResultType(const Decl *D) {
if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) {
QualType Ty = TSI->getType();
if (const FunctionType *FT = Ty->getAs<FunctionType>())
- Ty = FT->getResultType();
+ Ty = FT->getReturnType();
if (!Ty->isDependentType())
return Ty;
}
@@ -284,14 +286,14 @@ static void addParameterValuesToBindings(const StackFrameContext *CalleeCtx,
CallEvent::BindingsTy &Bindings,
SValBuilder &SVB,
const CallEvent &Call,
- CallEvent::param_iterator I,
- CallEvent::param_iterator E) {
+ ArrayRef<ParmVarDecl*> parameters) {
MemRegionManager &MRMgr = SVB.getRegionManager();
// If the function has fewer parameters than the call has arguments, we simply
// do not bind any values to them.
unsigned NumArgs = Call.getNumArgs();
unsigned Idx = 0;
+ ArrayRef<ParmVarDecl*>::iterator I = parameters.begin(), E = parameters.end();
for (; I != E && Idx < NumArgs; ++I, ++Idx) {
const ParmVarDecl *ParamDecl = *I;
assert(ParamDecl && "Formal parameter has no decl?");
@@ -306,21 +308,11 @@ static void addParameterValuesToBindings(const StackFrameContext *CalleeCtx,
// FIXME: Variadic arguments are not handled at all right now.
}
-
-CallEvent::param_iterator AnyFunctionCall::param_begin() const {
- const FunctionDecl *D = getDecl();
- if (!D)
- return 0;
-
- return D->param_begin();
-}
-
-CallEvent::param_iterator AnyFunctionCall::param_end() const {
+ArrayRef<ParmVarDecl*> AnyFunctionCall::parameters() const {
const FunctionDecl *D = getDecl();
if (!D)
- return 0;
-
- return D->param_end();
+ return None;
+ return D->parameters();
}
void AnyFunctionCall::getInitialStackFrameContents(
@@ -329,7 +321,7 @@ void AnyFunctionCall::getInitialStackFrameContents(
const FunctionDecl *D = cast<FunctionDecl>(CalleeCtx->getDecl());
SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this,
- D->param_begin(), D->param_end());
+ D->parameters());
}
bool AnyFunctionCall::argumentsMayEscape() const {
@@ -389,7 +381,7 @@ bool AnyFunctionCall::argumentsMayEscape() const {
}
-const FunctionDecl *SimpleCall::getDecl() const {
+const FunctionDecl *SimpleFunctionCall::getDecl() const {
const FunctionDecl *D = getOriginExpr()->getDirectCallee();
if (D)
return D;
@@ -484,7 +476,7 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
// that ExprEngine can decide what to do with it.
if (DynType.canBeASubClass())
return RuntimeDefinition(Definition, R->StripCasts());
- return RuntimeDefinition(Definition, /*DispatchRegion=*/0);
+ return RuntimeDefinition(Definition, /*DispatchRegion=*/nullptr);
}
void CXXInstanceCall::getInitialStackFrameContents(
@@ -550,18 +542,11 @@ const BlockDataRegion *BlockCall::getBlockRegion() const {
return dyn_cast_or_null<BlockDataRegion>(DataReg);
}
-CallEvent::param_iterator BlockCall::param_begin() const {
- const BlockDecl *D = getBlockDecl();
+ArrayRef<ParmVarDecl*> BlockCall::parameters() const {
+ const BlockDecl *D = getDecl();
if (!D)
- return 0;
- return D->param_begin();
-}
-
-CallEvent::param_iterator BlockCall::param_end() const {
- const BlockDecl *D = getBlockDecl();
- if (!D)
- return 0;
- return D->param_end();
+ return nullptr;
+ return D->parameters();
}
void BlockCall::getExtraInvalidatedValues(ValueList &Values) const {
@@ -575,7 +560,7 @@ void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
const BlockDecl *D = cast<BlockDecl>(CalleeCtx->getDecl());
SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this,
- D->param_begin(), D->param_end());
+ D->parameters());
}
@@ -604,8 +589,6 @@ void CXXConstructorCall::getInitialStackFrameContents(
}
}
-
-
SVal CXXDestructorCall::getCXXThisVal() const {
if (Data)
return loc::MemRegionVal(DtorDataTy::getFromOpaqueValue(Data).getPointer());
@@ -621,21 +604,11 @@ RuntimeDefinition CXXDestructorCall::getRuntimeDefinition() const {
return CXXInstanceCall::getRuntimeDefinition();
}
-
-CallEvent::param_iterator ObjCMethodCall::param_begin() const {
+ArrayRef<ParmVarDecl*> ObjCMethodCall::parameters() const {
const ObjCMethodDecl *D = getDecl();
if (!D)
- return 0;
-
- return D->param_begin();
-}
-
-CallEvent::param_iterator ObjCMethodCall::param_end() const {
- const ObjCMethodDecl *D = getDecl();
- if (!D)
- return 0;
-
- return D->param_end();
+ return ArrayRef<ParmVarDecl*>();
+ return D->parameters();
}
void
@@ -694,13 +667,13 @@ SourceRange ObjCMethodCall::getSourceRange() const {
typedef llvm::PointerIntPair<const PseudoObjectExpr *, 2> ObjCMessageDataTy;
const PseudoObjectExpr *ObjCMethodCall::getContainingPseudoObjectExpr() const {
- assert(Data != 0 && "Lazy lookup not yet performed.");
+ assert(Data && "Lazy lookup not yet performed.");
assert(getMessageKind() != OCM_Message && "Explicit message send.");
return ObjCMessageDataTy::getFromOpaqueValue(Data).getPointer();
}
ObjCMessageKind ObjCMethodCall::getMessageKind() const {
- if (Data == 0) {
+ if (!Data) {
// Find the parent, ignoring implicit casts.
ParentMap &PM = getLocationContext()->getParentMap();
@@ -738,7 +711,7 @@ ObjCMessageKind ObjCMethodCall::getMessageKind() const {
}
const_cast<ObjCMethodCall *>(this)->Data
- = ObjCMessageDataTy(0, 1).getOpaqueValue();
+ = ObjCMessageDataTy(nullptr, 1).getOpaqueValue();
assert(getMessageKind() == OCM_Message);
return OCM_Message;
}
@@ -774,7 +747,7 @@ bool ObjCMethodCall::canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
// Find the first declaration in the class hierarchy that declares
// the selector.
- ObjCMethodDecl *D = 0;
+ ObjCMethodDecl *D = nullptr;
while (true) {
D = IDecl->lookupMethod(Sel, true);
@@ -813,10 +786,10 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
if (E->isInstanceMessage()) {
// Find the the receiver type.
- const ObjCObjectPointerType *ReceiverT = 0;
+ const ObjCObjectPointerType *ReceiverT = nullptr;
bool CanBeSubClassed = false;
QualType SupersType = E->getSuperType();
- const MemRegion *Receiver = 0;
+ const MemRegion *Receiver = nullptr;
if (!SupersType.isNull()) {
// Super always means the type of immediate predecessor to the method
@@ -865,14 +838,22 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
Optional<const ObjCMethodDecl *> &Val = PMC[std::make_pair(IDecl, Sel)];
// Query lookupPrivateMethod() if the cache does not hit.
- if (!Val.hasValue())
+ if (!Val.hasValue()) {
Val = IDecl->lookupPrivateMethod(Sel);
+ // If the method is a property accessor, we should try to "inline" it
+ // even if we don't actually have an implementation.
+ if (!*Val)
+ if (const ObjCMethodDecl *CompileTimeMD = E->getMethodDecl())
+ if (CompileTimeMD->isPropertyAccessor())
+ Val = IDecl->lookupInstanceMethod(Sel);
+ }
+
const ObjCMethodDecl *MD = Val.getValue();
if (CanBeSubClassed)
return RuntimeDefinition(MD, Receiver);
else
- return RuntimeDefinition(MD, 0);
+ return RuntimeDefinition(MD, nullptr);
}
} else {
@@ -888,13 +869,24 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
return RuntimeDefinition();
}
+bool ObjCMethodCall::argumentsMayEscape() const {
+ if (isInSystemHeader() && !isInstanceMessage()) {
+ Selector Sel = getSelector();
+ if (Sel.getNumArgs() == 1 &&
+ Sel.getIdentifierInfoForSlot(0)->isStr("valueWithPointer"))
+ return true;
+ }
+
+ return CallEvent::argumentsMayEscape();
+}
+
void ObjCMethodCall::getInitialStackFrameContents(
const StackFrameContext *CalleeCtx,
BindingsTy &Bindings) const {
const ObjCMethodDecl *D = cast<ObjCMethodDecl>(CalleeCtx->getDecl());
SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this,
- D->param_begin(), D->param_end());
+ D->parameters());
SVal SelfVal = getReceiverSVal();
if (!SelfVal.isUnknown()) {
@@ -923,7 +915,7 @@ CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State,
// Otherwise, it's a normal function call, static member function call, or
// something we can't reason about.
- return create<FunctionCall>(CE, State, LCtx);
+ return create<SimpleFunctionCall>(CE, State, LCtx);
}
OpenPOWER on IntegriCloud