Remove OwnershipAttr::Kind, since it's essentially redundant with attr::Kind the way it's being used. Also fix isa<OwnershipAttr> support, break more-than-80-char lines, and other miscellaneous ownership attr cleanup.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110908 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jordy Rose 2010-08-12 08:54:03 +00:00
Родитель 6d311229f0
Коммит 2a479929f7
4 изменённых файлов: 66 добавлений и 81 удалений

Просмотреть файл

@ -379,23 +379,14 @@ class OwnershipAttr: public AttrWithString {
unsigned* ArgNums; unsigned* ArgNums;
unsigned Size; unsigned Size;
public: public:
enum OwnershipKind { Holds, Takes, Returns, None };
OwnershipKind OKind;
attr::Kind AKind; attr::Kind AKind;
public: public:
OwnershipAttr(attr::Kind AK, ASTContext &C, unsigned* arg_nums, unsigned size, OwnershipAttr(attr::Kind AK, ASTContext &C, unsigned* arg_nums, unsigned size,
llvm::StringRef module, OwnershipKind kind); llvm::StringRef module);
virtual void Destroy(ASTContext &C); virtual void Destroy(ASTContext &C);
OwnershipKind getKind() const {
return OKind;
}
bool isKind(const OwnershipKind k) const {
return OKind == k;
}
/// Ownership attributes have a 'module', which is the name of a kind of /// Ownership attributes have a 'module', which is the name of a kind of
/// resource that can be checked. /// resource that can be checked.
/// The Malloc checker uses the module 'malloc'. /// The Malloc checker uses the module 'malloc'.
@ -423,7 +414,14 @@ public:
virtual Attr *clone(ASTContext &C) const; virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A) { static bool classof(const Attr *A) {
return true; switch (A->getKind()) {
case attr::OwnershipTakes:
case attr::OwnershipHolds:
case attr::OwnershipReturns:
return true;
default:
return false;
}
} }
static bool classof(const OwnershipAttr *A) { static bool classof(const OwnershipAttr *A) {
return true; return true;
@ -443,9 +441,6 @@ public:
static bool classof(const OwnershipTakesAttr *A) { static bool classof(const OwnershipTakesAttr *A) {
return true; return true;
} }
static bool classof(const OwnershipAttr *A) {
return A->OKind == Takes;
}
}; };
class OwnershipHoldsAttr: public OwnershipAttr { class OwnershipHoldsAttr: public OwnershipAttr {
@ -461,9 +456,6 @@ public:
static bool classof(const OwnershipHoldsAttr *A) { static bool classof(const OwnershipHoldsAttr *A) {
return true; return true;
} }
static bool classof(const OwnershipAttr *A) {
return A->OKind == Holds;
}
}; };
class OwnershipReturnsAttr: public OwnershipAttr { class OwnershipReturnsAttr: public OwnershipAttr {
@ -479,9 +471,6 @@ public:
static bool classof(const OwnershipReturnsAttr *A) { static bool classof(const OwnershipReturnsAttr *A) {
return true; return true;
} }
static bool classof(const OwnershipAttr *A) {
return A->OKind == Returns;
}
}; };
class FormatAttr : public AttrWithString { class FormatAttr : public AttrWithString {

Просмотреть файл

@ -49,17 +49,13 @@ NonNullAttr::NonNullAttr(ASTContext &C, unsigned* arg_nums, unsigned size)
} }
OwnershipAttr::OwnershipAttr(attr::Kind AK, ASTContext &C, unsigned* arg_nums, OwnershipAttr::OwnershipAttr(attr::Kind AK, ASTContext &C, unsigned* arg_nums,
unsigned size, unsigned size, llvm::StringRef module)
llvm::StringRef module, : AttrWithString(AK, C, module), ArgNums(0), Size(0) {
OwnershipKind kind) :
AttrWithString(AK, C, module), ArgNums(0), Size(0), OKind(kind) {
if (size == 0) if (size == 0)
return; return;
assert(arg_nums); assert(arg_nums);
ArgNums = new (C) unsigned[size]; ArgNums = new (C) unsigned[size];
Size = size; Size = size;
AKind = AK;
OKind = kind;
memcpy(ArgNums, arg_nums, sizeof(*ArgNums) * size); memcpy(ArgNums, arg_nums, sizeof(*ArgNums) * size);
} }
@ -70,19 +66,19 @@ void OwnershipAttr::Destroy(ASTContext &C) {
} }
OwnershipTakesAttr::OwnershipTakesAttr(ASTContext &C, unsigned* arg_nums, OwnershipTakesAttr::OwnershipTakesAttr(ASTContext &C, unsigned* arg_nums,
unsigned size, llvm::StringRef module) : unsigned size, llvm::StringRef module)
OwnershipAttr(attr::OwnershipTakes, C, arg_nums, size, module, Takes) { : OwnershipAttr(attr::OwnershipTakes, C, arg_nums, size, module) {
} }
OwnershipHoldsAttr::OwnershipHoldsAttr(ASTContext &C, unsigned* arg_nums, OwnershipHoldsAttr::OwnershipHoldsAttr(ASTContext &C, unsigned* arg_nums,
unsigned size, llvm::StringRef module) : unsigned size, llvm::StringRef module)
OwnershipAttr(attr::OwnershipHolds, C, arg_nums, size, module, Holds) { : OwnershipAttr(attr::OwnershipHolds, C, arg_nums, size, module) {
} }
OwnershipReturnsAttr::OwnershipReturnsAttr(ASTContext &C, unsigned* arg_nums, OwnershipReturnsAttr::OwnershipReturnsAttr(ASTContext &C, unsigned* arg_nums,
unsigned size, unsigned size,
llvm::StringRef module) : llvm::StringRef module)
OwnershipAttr(attr::OwnershipReturns, C, arg_nums, size, module, Returns) { : OwnershipAttr(attr::OwnershipReturns, C, arg_nums, size, module) {
} }
#define DEF_SIMPLE_ATTR_CLONE(ATTR) \ #define DEF_SIMPLE_ATTR_CLONE(ATTR) \
@ -187,7 +183,7 @@ Attr *NonNullAttr::clone(ASTContext &C) const {
} }
Attr *OwnershipAttr::clone(ASTContext &C) const { Attr *OwnershipAttr::clone(ASTContext &C) const {
return ::new (C) OwnershipAttr(AKind, C, ArgNums, Size, getModule(), OKind); return ::new (C) OwnershipAttr(AKind, C, ArgNums, Size, getModule());
} }
Attr *OwnershipReturnsAttr::clone(ASTContext &C) const { Attr *OwnershipReturnsAttr::clone(ASTContext &C) const {

Просмотреть файл

@ -100,7 +100,8 @@ private:
const GRState *state); const GRState *state);
void FreeMem(CheckerContext &C, const CallExpr *CE); void FreeMem(CheckerContext &C, const CallExpr *CE);
void FreeMemAttr(CheckerContext &C, const CallExpr *CE, const OwnershipAttr* Att); void FreeMemAttr(CheckerContext &C, const CallExpr *CE,
const OwnershipAttr* Att);
const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE, const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
const GRState *state, unsigned Num, bool Hold); const GRState *state, unsigned Num, bool Hold);
@ -176,22 +177,19 @@ bool MallocChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
bool rv = false; bool rv = false;
if (FD->hasAttrs()) { if (FD->hasAttrs()) {
for (const Attr *attr = FD->getAttrs(); attr; attr = attr->getNext()) { for (const Attr *attr = FD->getAttrs(); attr; attr = attr->getNext()) {
if(const OwnershipAttr* Att = dyn_cast<OwnershipAttr>(attr)) { switch (attr->getKind()) {
switch (Att->getKind()) { case attr::OwnershipReturns:
case OwnershipAttr::Returns: { MallocMemReturnsAttr(C, CE, cast<OwnershipAttr>(attr));
MallocMemReturnsAttr(C, CE, Att); rv = true;
rv = true; break;
break; case attr::OwnershipTakes:
} case attr::OwnershipHolds:
case OwnershipAttr::Takes: FreeMemAttr(C, CE, cast<OwnershipAttr>(attr));
case OwnershipAttr::Holds: { rv = true;
FreeMemAttr(C, CE, Att); break;
rv = true; default:
break; // Ignore non-ownership attributes.
} break;
default:
break;
}
} }
} }
} }
@ -259,13 +257,13 @@ void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
} }
void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE, void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE,
const OwnershipAttr* Att) { const OwnershipAttr* Att) {
if (!Att->isModule("malloc")) if (!Att->isModule("malloc"))
return; return;
for (const unsigned *I = Att->begin(), *E = Att->end(); I != E; ++I) { for (const unsigned *I = Att->begin(), *E = Att->end(); I != E; ++I) {
const GRState *state = const GRState *state =
FreeMemAux(C, CE, C.getState(), *I, Att->isKind(OwnershipAttr::Holds)); FreeMemAux(C, CE, C.getState(), *I, isa<OwnershipHoldsAttr>(Att));
if (state) if (state)
C.addTransition(state); C.addTransition(state);
} }

Просмотреть файл

@ -357,8 +357,8 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
// The following arguments must be argument indexes, the arguments must be // The following arguments must be argument indexes, the arguments must be
// of integer type for Returns, otherwise of pointer type. // of integer type for Returns, otherwise of pointer type.
// The difference between Holds and Takes is that a pointer may still be used // The difference between Holds and Takes is that a pointer may still be used
// after being held. free() should be __attribute((ownership_takes)), whereas a list // after being held. free() should be __attribute((ownership_takes)), whereas
// append function may well be __attribute((ownership_holds)). // a list append function may well be __attribute((ownership_holds)).
if (!AL.getParameterName()) { if (!AL.getParameterName()) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string) S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string)
@ -366,30 +366,33 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
return; return;
} }
// Figure out our Kind, and check arguments while we're at it. // Figure out our Kind, and check arguments while we're at it.
OwnershipAttr::OwnershipKind K = OwnershipAttr::None; attr::Kind K;
if (AL.getName()->getName().equals("ownership_takes")) { switch (AL.getKind()) {
K = OwnershipAttr::Takes; case AttributeList::AT_ownership_takes:
K = attr::OwnershipTakes;
if (AL.getNumArgs() < 1) { if (AL.getNumArgs() < 1) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
return; return;
} }
} else if (AL.getName()->getName().equals("ownership_holds")) { break;
K = OwnershipAttr::Holds; case AttributeList::AT_ownership_holds:
K = attr::OwnershipHolds;
if (AL.getNumArgs() < 1) { if (AL.getNumArgs() < 1) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
return; return;
} }
} else if (AL.getName()->getName().equals("ownership_returns")) { break;
K = OwnershipAttr::Returns; case AttributeList::AT_ownership_returns:
K = attr::OwnershipReturns;
if (AL.getNumArgs() > 1) { if (AL.getNumArgs() > 1) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
<< AL.getNumArgs() + 1; << AL.getNumArgs() + 1;
return; return;
} }
} break;
// This should never happen given how we are called. default:
if (K == OwnershipAttr::None) { // This should never happen given how we are called.
return; llvm_unreachable("Unknown ownership attribute");
} }
if (!isFunction(d) || !hasFunctionProto(d)) { if (!isFunction(d) || !hasFunctionProto(d)) {
@ -408,7 +411,8 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
llvm::SmallVector<unsigned, 10> OwnershipArgs; llvm::SmallVector<unsigned, 10> OwnershipArgs;
for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E; ++I) { for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E;
++I) {
Expr *IdxExpr = static_cast<Expr *>(*I); Expr *IdxExpr = static_cast<Expr *>(*I);
llvm::APSInt ArgNum(32); llvm::APSInt ArgNum(32);
@ -428,21 +432,21 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
} }
--x; --x;
switch (K) { switch (K) {
case OwnershipAttr::Takes: case attr::OwnershipTakes:
case OwnershipAttr::Holds: { case attr::OwnershipHolds: {
// Is the function argument a pointer type? // Is the function argument a pointer type?
QualType T = getFunctionOrMethodArgType(d, x); QualType T = getFunctionOrMethodArgType(d, x);
if (!T->isAnyPointerType() && !T->isBlockPointerType()) { if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
// FIXME: Should also highlight argument in decl. // FIXME: Should also highlight argument in decl.
S.Diag(AL.getLoc(), diag::err_ownership_type) S.Diag(AL.getLoc(), diag::err_ownership_type)
<< ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds") << ((K==attr::OwnershipTakes)?"ownership_takes":"ownership_holds")
<< "pointer" << "pointer"
<< IdxExpr->getSourceRange(); << IdxExpr->getSourceRange();
continue; continue;
} }
break; break;
} }
case OwnershipAttr::Returns: { case attr::OwnershipReturns: {
if (AL.getNumArgs() > 1) { if (AL.getNumArgs() > 1) {
// Is the function argument an integer type? // Is the function argument an integer type?
Expr *IdxExpr = static_cast<Expr *>(AL.getArg(0)); Expr *IdxExpr = static_cast<Expr *>(AL.getArg(0));
@ -457,20 +461,18 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
} }
break; break;
} }
// Should never happen, here to silence a warning. default:
default: { llvm_unreachable("Unknown ownership attribute");
return;
}
} // switch } // switch
// Check we don't have a conflict with another ownership attribute. // Check we don't have a conflict with another ownership attribute.
if (d->hasAttrs()) { if (K != attr::OwnershipReturns && d->hasAttrs()) {
for (const Attr *attr = d->getAttrs(); attr; attr = attr->getNext()) { for (const Attr *attr = d->getAttrs(); attr; attr = attr->getNext()) {
if (const OwnershipAttr* Att = dyn_cast<OwnershipAttr>(attr)) { if (const OwnershipAttr* Att = dyn_cast<OwnershipAttr>(attr)) {
// Two ownership attributes of the same kind can't conflict, // Two ownership attributes of the same kind can't conflict,
// except returns attributes. // except returns attributes.
if (K == OwnershipAttr::Returns || Att->getKind() != K) { if (Att->getKind() != K) {
for (const unsigned *I = Att->begin(), *E = Att->end(); I != E; ++I) { for (const unsigned *I = Att->begin(), *E = Att->end(); I!=E; ++I) {
if (x == *I) { if (x == *I) {
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
<< AL.getName()->getName() << "ownership_*"; << AL.getName()->getName() << "ownership_*";
@ -487,7 +489,7 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
unsigned size = OwnershipArgs.size(); unsigned size = OwnershipArgs.size();
llvm::array_pod_sort(start, start + size); llvm::array_pod_sort(start, start + size);
switch (K) { switch (K) {
case OwnershipAttr::Takes: { case attr::OwnershipTakes: {
if (OwnershipArgs.empty()) { if (OwnershipArgs.empty()) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
return; return;
@ -496,7 +498,7 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
Module)); Module));
break; break;
} }
case OwnershipAttr::Holds: { case attr::OwnershipHolds: {
if (OwnershipArgs.empty()) { if (OwnershipArgs.empty()) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
return; return;
@ -505,13 +507,13 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
Module)); Module));
break; break;
} }
case OwnershipAttr::Returns: { case attr::OwnershipReturns: {
d->addAttr(::new (S.Context) OwnershipReturnsAttr(S.Context, start, size, d->addAttr(::new (S.Context) OwnershipReturnsAttr(S.Context, start, size,
Module)); Module));
break; break;
} }
default: default:
break; llvm_unreachable("Unknown ownership attribute");
} }
} }