summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp17
-rw-r--r--clang/test/Sema/attr-ownership.c5
3 files changed, 24 insertions, 2 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 87032b8a5c8..24145317c9b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1949,6 +1949,10 @@ def err_attribute_invalid_implicit_this_argument : Error<
"%0 attribute is invalid for the implicit this argument">;
def err_ownership_type : Error<
"%0 attribute only applies to %select{pointer|integer}1 arguments">;
+def err_ownership_returns_index_mismatch : Error<
+ "'ownership_returns' attribute index does not match; here it is %0">;
+def note_ownership_returns_index_mismatch : Note<
+ "declared with index %0 here">;
def err_format_strftime_third_parameter : Error<
"strftime format attribute requires 3rd parameter to be 0">;
def err_format_attribute_requires_variadic : Error<
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index b7ca9924ef1..ff4192e91d3 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -1292,13 +1292,26 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
// Check we don't have a conflict with another ownership attribute.
for (const auto *I : D->specific_attrs<OwnershipAttr>()) {
- // FIXME: A returns attribute should conflict with any returns attribute
- // with a different index too.
+ // Cannot have two ownership attributes of different kinds for the same
+ // index.
if (I->getOwnKind() != K && I->args_end() !=
std::find(I->args_begin(), I->args_end(), Idx)) {
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
<< AL.getName() << I;
return;
+ } else if (K == OwnershipAttr::Returns &&
+ I->getOwnKind() == OwnershipAttr::Returns) {
+ // A returns attribute conflicts with any other returns attribute using
+ // a different index. Note, diagnostic reporting is 1-based, but stored
+ // argument indexes are 0-based.
+ if (std::find(I->args_begin(), I->args_end(), Idx) == I->args_end()) {
+ S.Diag(I->getLocation(), diag::err_ownership_returns_index_mismatch)
+ << *(I->args_begin()) + 1;
+ if (I->args_size())
+ S.Diag(AL.getLoc(), diag::note_ownership_returns_index_mismatch)
+ << (unsigned)Idx + 1 << Ex->getSourceRange();
+ return;
+ }
}
}
OwnershipArgs.push_back(Idx);
diff --git a/clang/test/Sema/attr-ownership.c b/clang/test/Sema/attr-ownership.c
index 2aa9f9f27cc..d2e48c65a23 100644
--- a/clang/test/Sema/attr-ownership.c
+++ b/clang/test/Sema/attr-ownership.c
@@ -17,3 +17,8 @@ void *f12(float i, int k, int f, int *j) __attribute__((ownership_returns(foo, 4
void f13(int *i, int *j) __attribute__((ownership_holds(foo, 1))) __attribute__((ownership_takes(foo, 2)));
void f14(int i, int j, int *k) __attribute__((ownership_holds(foo, 3))) __attribute__((ownership_takes(foo, 3))); // expected-error {{'ownership_holds' and 'ownership_takes' attributes are not compatible}}
+
+void f15(int, int)
+ __attribute__((ownership_returns(foo, 1))) // expected-note {{declared with index 1 here}}
+ __attribute__((ownership_returns(foo, 2))); // expected-error {{'ownership_returns' attribute index does not match; here it is 2}}
+void f16(int *i, int *j) __attribute__((ownership_holds(foo, 1))) __attribute__((ownership_holds(foo, 1))); // OK, same index
OpenPOWER on IntegriCloud