diff options
author | DeLesley Hutchins <delesley@google.com> | 2013-10-04 21:28:06 +0000 |
---|---|---|
committer | DeLesley Hutchins <delesley@google.com> | 2013-10-04 21:28:06 +0000 |
commit | 210791a021a18e3eb60d4a67df6cd452006aa338 (patch) | |
tree | 9ad11e882dc8256f24f8bd6f8f5388de78c8279a /clang/lib/Sema/SemaDeclAttr.cpp | |
parent | 721726adfc043224c9e5e0925b581d0448c6723d (diff) | |
download | bcm5719-llvm-210791a021a18e3eb60d4a67df6cd452006aa338.tar.gz bcm5719-llvm-210791a021a18e3eb60d4a67df6cd452006aa338.zip |
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.
llvm-svn: 191983
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c6337a5015e..41cc3fd285a 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1041,8 +1041,11 @@ static void handleConsumesAttr(Sema &S, Decl *D, const AttributeList &Attr) { 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 @@ static void handleCallableWhenUnconsumedAttr(Sema &S, Decl *D, 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 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, 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); |