summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis/Consumed.cpp
diff options
context:
space:
mode:
authorDeLesley Hutchins <delesley@google.com>2013-10-17 23:23:53 +0000
committerDeLesley Hutchins <delesley@google.com>2013-10-17 23:23:53 +0000
commit6939177ceab8b9df367bbaeccb16a74d85447644 (patch)
treebb51351642d736f4bb09e8b6a5b5e9dc05f8e4fa /clang/lib/Analysis/Consumed.cpp
parent403425bba8939ecbf217f3f9e6b1ceb6ad45f16b (diff)
downloadbcm5719-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.cpp69
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);
}
OpenPOWER on IntegriCloud