diff options
author | DeLesley Hutchins <delesley@google.com> | 2013-10-17 23:23:53 +0000 |
---|---|---|
committer | DeLesley Hutchins <delesley@google.com> | 2013-10-17 23:23:53 +0000 |
commit | 6939177ceab8b9df367bbaeccb16a74d85447644 (patch) | |
tree | bb51351642d736f4bb09e8b6a5b5e9dc05f8e4fa /clang/lib/Analysis/Consumed.cpp | |
parent | 403425bba8939ecbf217f3f9e6b1ceb6ad45f16b (diff) | |
download | bcm5719-llvm-6939177ceab8b9df367bbaeccb16a74d85447644.tar.gz bcm5719-llvm-6939177ceab8b9df367bbaeccb16a74d85447644.zip |
Consumed analysis: Add param_typestate attribute, which specifies that
function parameters must be in a particular state. Patch by
chris.wailes@gmail.com. Reviewed by delesley@google.com.
llvm-svn: 192934
Diffstat (limited to 'clang/lib/Analysis/Consumed.cpp')
-rw-r--r-- | clang/lib/Analysis/Consumed.cpp | 69 |
1 files changed, 55 insertions, 14 deletions
diff --git a/clang/lib/Analysis/Consumed.cpp b/clang/lib/Analysis/Consumed.cpp index 021c26dff2f..a7d747f705b 100644 --- a/clang/lib/Analysis/Consumed.cpp +++ b/clang/lib/Analysis/Consumed.cpp @@ -180,13 +180,14 @@ static ConsumedState mapConsumableAttrState(const QualType QT) { llvm_unreachable("invalid enum"); } -static ConsumedState mapSetTypestateAttrState(const SetTypestateAttr *STAttr) { - switch (STAttr->getNewState()) { - case SetTypestateAttr::Unknown: +static ConsumedState +mapParamTypestateAttrState(const ParamTypestateAttr *PTAttr) { + switch (PTAttr->getParamState()) { + case ParamTypestateAttr::Unknown: return CS_Unknown; - case SetTypestateAttr::Unconsumed: + case ParamTypestateAttr::Unconsumed: return CS_Unconsumed; - case SetTypestateAttr::Consumed: + case ParamTypestateAttr::Consumed: return CS_Consumed; } llvm_unreachable("invalid_enum"); @@ -205,6 +206,18 @@ mapReturnTypestateAttrState(const ReturnTypestateAttr *RTSAttr) { llvm_unreachable("invalid enum"); } +static ConsumedState mapSetTypestateAttrState(const SetTypestateAttr *STAttr) { + switch (STAttr->getNewState()) { + case SetTypestateAttr::Unknown: + return CS_Unknown; + case SetTypestateAttr::Unconsumed: + return CS_Unconsumed; + case SetTypestateAttr::Consumed: + return CS_Consumed; + } + llvm_unreachable("invalid_enum"); +} + static StringRef stateToString(ConsumedState State) { switch (State) { case consumed::CS_None: @@ -577,12 +590,33 @@ void ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) { InfoEntry Entry = PropagationMap.find(Call->getArg(Index)); - if (Entry == PropagationMap.end() || !Entry->second.isVar()) { + if (Entry == PropagationMap.end() || + !(Entry->second.isState() || Entry->second.isVar())) continue; - } PropagationInfo PInfo = Entry->second; + // Check that the parameter is in the correct state. + + if (Param->hasAttr<ParamTypestateAttr>()) { + ConsumedState ParamState = + PInfo.isState() ? PInfo.getState() : + StateMap->getState(PInfo.getVar()); + + ConsumedState ExpectedState = + mapParamTypestateAttrState(Param->getAttr<ParamTypestateAttr>()); + + if (ParamState != ExpectedState) + Analyzer.WarningsHandler.warnParamTypestateMismatch( + Call->getArg(Index - Offset)->getExprLoc(), + stateToString(ExpectedState), stateToString(ParamState)); + } + + if (!Entry->second.isVar()) + continue; + + // Adjust state on the caller side. + if (ParamType->isRValueReferenceType() || (ParamType->isLValueReferenceType() && !cast<LValueReferenceType>(*ParamType).isSpelledAsLValue())) { @@ -812,15 +846,22 @@ void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) { void ConsumedStmtVisitor::VisitParmVarDecl(const ParmVarDecl *Param) { QualType ParamType = Param->getType(); ConsumedState ParamState = consumed::CS_None; - - if (!(ParamType->isPointerType() || ParamType->isReferenceType()) && - isConsumableType(ParamType)) + + if (Param->hasAttr<ParamTypestateAttr>()) { + ParamState = + mapParamTypestateAttrState(Param->getAttr<ParamTypestateAttr>()); + + } else if (!(ParamType->isPointerType() || ParamType->isReferenceType()) && + isConsumableType(ParamType)) { + ParamState = mapConsumableAttrState(ParamType); - else if (ParamType->isReferenceType() && - isConsumableType(ParamType->getPointeeType())) + + } else if (ParamType->isReferenceType() && + isConsumableType(ParamType->getPointeeType())) { ParamState = consumed::CS_Unknown; - - if (ParamState) + } + + if (ParamState != CS_None) StateMap->setState(Param, ParamState); } |