Consumed Analysis: Change callable_when so that it can take a list of states
that a function can be called in. This reduced the total number of annotations
needed and makes writing more complicated behaviour less burdensome.
Patch by chriswails@gmail.com.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191983 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index cc1cb0b..a206acd 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -1503,36 +1503,20 @@
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
- void warnUseOfTempWhileConsumed(StringRef MethodName, SourceLocation Loc) {
+ void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,
+ SourceLocation Loc) {
PartialDiagnosticAt Warning(Loc, S.PDiag(
- diag::warn_use_of_temp_while_consumed) << MethodName);
+ diag::warn_use_of_temp_in_invalid_state) << MethodName << State);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
- void warnUseOfTempInUnknownState(StringRef MethodName, SourceLocation Loc) {
+ void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
+ StringRef State, SourceLocation Loc) {
- PartialDiagnosticAt Warning(Loc, S.PDiag(
- diag::warn_use_of_temp_in_unknown_state) << MethodName);
-
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
- }
-
- void warnUseWhileConsumed(StringRef MethodName, StringRef VariableName,
- SourceLocation Loc) {
-
- PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_while_consumed) <<
- MethodName << VariableName);
-
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
- }
-
- void warnUseInUnknownState(StringRef MethodName, StringRef VariableName,
- SourceLocation Loc) {
-
- PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_unknown_state) <<
- MethodName << VariableName);
+ PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) <<
+ MethodName << VariableName << State);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
@@ -1570,7 +1554,7 @@
(D.getDiagnosticLevel(diag::warn_double_lock, SourceLocation()) !=
DiagnosticsEngine::Ignored);
DefaultPolicy.enableConsumedAnalysis = (unsigned)
- (D.getDiagnosticLevel(diag::warn_use_while_consumed, SourceLocation()) !=
+ (D.getDiagnosticLevel(diag::warn_use_in_invalid_state, SourceLocation()) !=
DiagnosticsEngine::Ignored);
}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index c6337a5..41cc3fd 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1041,8 +1041,11 @@
Attr.getAttributeSpellingListIndex()));
}
-static void handleCallableWhenUnconsumedAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleCallableWhenAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+
+ if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) return;
+
if (!isa<CXXMethodDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
Attr.getName() << ExpectedMethod;
@@ -1052,9 +1055,34 @@
if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
return;
+ SmallVector<CallableWhenAttr::ConsumedState, 3> States;
+ for (unsigned ArgIndex = 0; ArgIndex < Attr.getNumArgs(); ++ArgIndex) {
+ CallableWhenAttr::ConsumedState CallableState;
+
+ if (Attr.isArgExpr(ArgIndex) &&
+ isa<StringLiteral>(Attr.getArgAsExpr(ArgIndex))) {
+
+ Expr *Arg = Attr.getArgAsExpr(ArgIndex);
+ StringRef StateString = cast<StringLiteral>(Arg)->getString();
+
+ if (!CallableWhenAttr::ConvertStrToConsumedState(StateString,
+ CallableState)) {
+ S.Diag(Arg->getExprLoc(), diag::warn_attribute_type_not_supported)
+ << Attr.getName() << StateString;
+ return;
+ }
+
+ States.push_back(CallableState);
+ } else {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
+ << AANT_ArgumentString;
+ return;
+ }
+ }
+
D->addAttr(::new (S.Context)
- CallableWhenUnconsumedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ CallableWhenAttr(Attr.getRange(), S.Context, States.data(),
+ States.size(), Attr.getAttributeSpellingListIndex()));
}
static void handleTestsConsumedAttr(Sema &S, Decl *D,
@@ -4767,8 +4795,8 @@
case AttributeList::AT_Consumes:
handleConsumesAttr(S, D, Attr);
break;
- case AttributeList::AT_CallableWhenUnconsumed:
- handleCallableWhenUnconsumedAttr(S, D, Attr);
+ case AttributeList::AT_CallableWhen:
+ handleCallableWhenAttr(S, D, Attr);
break;
case AttributeList::AT_TestsConsumed:
handleTestsConsumedAttr(S, D, Attr);