diff options
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 17 |
1 files changed, 15 insertions, 2 deletions
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); |