Provide a new kind of iterator, the specific_decl_iterator, that

filters the decls seen by decl_iterator with two criteria: the dynamic
type of the declaration and a run-time predicate described by a member
function. This simplifies EnumDecl, RecordDecl, and ObjCContainerDecl
considerably. It has no measurable performance impact.

llvm-svn: 61994
This commit is contained in:
Douglas Gregor 2009-01-09 17:18:27 +00:00
parent 93215eca9b
commit ffca3a21f1
15 changed files with 130 additions and 281 deletions

View File

@ -208,7 +208,7 @@ void DeclPrinter::PrintLinkageSpec(LinkageSpecDecl *LS) {
}
void DeclPrinter::PrintObjCMethodDecl(ObjCMethodDecl *OMD) {
if (OMD->isInstance())
if (OMD->isInstanceMethod())
Out << "\n- ";
else
Out << "\n+ ";

View File

@ -879,7 +879,7 @@ void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD,
// Unique method name
std::string NameStr;
if (OMD->isInstance())
if (OMD->isInstanceMethod())
NameStr += "_I_";
else
NameStr += "_C_";
@ -909,7 +909,7 @@ void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD,
ResultStr += "(";
// invisible arguments
if (OMD->isInstance()) {
if (OMD->isInstanceMethod()) {
QualType selfTy = Context->getObjCInterfaceType(OMD->getClassInterface());
selfTy = Context->getPointerType(selfTy);
if (!LangOpts.Microsoft) {
@ -2148,7 +2148,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
ObjCInterfaceDecl *RewriteObjC::isSuperReceiver(Expr *recExpr) {
// check if we are sending a message to 'super'
if (!CurMethodDef || !CurMethodDef->isInstance()) return 0;
if (!CurMethodDef || !CurMethodDef->isInstanceMethod()) return 0;
if (ObjCSuperExpr *Super = dyn_cast<ObjCSuperExpr>(recExpr)) {
const PointerType *PT = Super->getType()->getAsPointerType();

View File

@ -997,31 +997,14 @@ public:
// enumerator_iterator - Iterates through the enumerators of this
// enumeration.
struct enumerator_iterator : public DeclContext::decl_iterator {
typedef EnumConstantDecl* value_type;
typedef EnumConstantDecl* reference;
typedef EnumConstantDecl* pointer;
enumerator_iterator() : DeclContext::decl_iterator() { }
explicit enumerator_iterator(DeclContext::decl_iterator Pos)
: DeclContext::decl_iterator(Pos) { }
reference operator*() const {
return cast<EnumConstantDecl>(DeclContext::decl_iterator::operator*());
}
pointer operator->() const {
return cast<EnumConstantDecl>(DeclContext::decl_iterator::operator*());
}
};
typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator;
enumerator_iterator enumerator_begin() const {
return enumerator_iterator(this->decls_begin());
return enumerator_iterator(this->decls_begin(), this->decls_end());
}
enumerator_iterator enumerator_end() const {
return enumerator_iterator(this->decls_end());
return enumerator_iterator(this->decls_end(), this->decls_end());
}
/// getIntegerType - Return the integer type this enum decl corresponds to.
@ -1108,107 +1091,15 @@ public:
// Iterator access to field members. The field iterator only visits
// the non-static data members of this class, ignoring any static
// data members, functions, constructors, destructors, etc.
class field_const_iterator {
protected:
/// Current - Current position within the sequence of declarations
/// in this record.
DeclContext::decl_iterator Current;
typedef specific_decl_iterator<FieldDecl> field_iterator;
/// End - Last position in the sequence of declarations in this
/// record.
DeclContext::decl_iterator End;
/// SkipToNextField - Advances the current position up to the next
/// FieldDecl.
void SkipToNextField() {
while (Current != End && !isa<FieldDecl>(*Current))
++Current;
}
public:
typedef FieldDecl const * value_type;
typedef FieldDecl const * reference;
typedef FieldDecl const * pointer;
typedef std::ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category;
field_const_iterator() : Current(), End() { }
field_const_iterator(DeclContext::decl_iterator C,
DeclContext::decl_iterator E)
: Current(C), End(E) {
SkipToNextField();
}
reference operator*() const { return cast<FieldDecl>(*Current); }
pointer operator->() const { return cast<FieldDecl>(*Current); }
field_const_iterator& operator++() {
++Current;
SkipToNextField();
return *this;
}
field_const_iterator operator++(int) {
field_const_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool
operator==(const field_const_iterator& x, const field_const_iterator& y) {
return x.Current == y.Current;
}
friend bool
operator!=(const field_const_iterator& x, const field_const_iterator& y) {
return x.Current != y.Current;
}
};
class field_iterator : public field_const_iterator {
public:
typedef FieldDecl* value_type;
typedef FieldDecl* reference;
typedef FieldDecl* pointer;
field_iterator() : field_const_iterator() { }
field_iterator(DeclContext::decl_iterator C, DeclContext::decl_iterator E)
: field_const_iterator(C, E) { }
reference operator*() const { return cast<FieldDecl>(*Current); }
pointer operator->() const { return cast<FieldDecl>(*Current); }
field_iterator& operator++() {
++Current;
SkipToNextField();
return *this;
}
field_iterator operator++(int) {
field_iterator tmp(*this);
++(*this);
return tmp;
}
};
field_iterator field_begin() {
field_iterator field_begin() const {
return field_iterator(decls_begin(), decls_end());
}
field_iterator field_end() {
field_iterator field_end() const {
return field_iterator(decls_end(), decls_end());
}
field_const_iterator field_begin() const {
return field_const_iterator(decls_begin(), decls_end());
}
field_const_iterator field_end() const {
return field_const_iterator(decls_end(), decls_end());
}
// field_empty - Whether there are any fields (non-static data
// members) in this record.
bool field_empty() const { return field_begin() == field_end(); }

View File

@ -490,6 +490,90 @@ public:
decl_iterator decls_begin() const { return Decls.begin(); }
decl_iterator decls_end() const { return Decls.end(); }
/// specific_decl_iterator - Iterates over a subrange of
/// declarations stored in a DeclContext, providing only those that
/// are of type SpecificDecl (or a class derived from it) and,
/// optionally, that meet some additional run-time criteria. This
/// iterator is used, for example, to provide iteration over just
/// the fields within a RecordDecl (with SpecificDecl = FieldDecl)
/// or the instance methods within an Objective-C interface (with
/// SpecificDecl = ObjCMethodDecl and using
/// ObjCMethodDecl::isInstanceMethod as the run-time criteria).
template<typename SpecificDecl>
class specific_decl_iterator {
/// Current - The current, underlying declaration iterator, which
/// will either be the same as End or will point to a declaration of
/// type SpecificDecl.
DeclContext::decl_iterator Current;
/// End - One past the last declaration within the DeclContext.
DeclContext::decl_iterator End;
/// Acceptable - If non-NULL, points to a member function that
/// will determine if a particular declaration of type
/// SpecificDecl should be visited by the iteration.
bool (SpecificDecl::*Acceptable)() const;
/// SkipToNextDecl - Advances the current position up to the next
/// declaration of type SpecificDecl that also meets the criteria
/// required by Acceptable.
void SkipToNextDecl() {
while (Current != End &&
(!isa<SpecificDecl>(*Current) ||
(Acceptable && !(cast<SpecificDecl>(*Current)->*Acceptable)())))
++Current;
}
public:
typedef SpecificDecl* value_type;
typedef SpecificDecl* reference;
typedef SpecificDecl* pointer;
typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
difference_type;
typedef std::forward_iterator_tag iterator_category;
specific_decl_iterator() : Current(), End(), Acceptable(0) { }
/// specific_decl_iterator - Construct a new iterator over a
/// subset of the declarations in [C, E). If A is non-NULL, it is
/// a pointer to a member function of SpecificDecl that should
/// return true for all of the SpecificDecl instances that will be
/// in the subset of iterators. For example, if you want
/// Objective-C instance methods, SpecificDecl will be
/// ObjCMethodDecl and A will be &ObjCMethodDecl::isInstanceMethod.
specific_decl_iterator(DeclContext::decl_iterator C,
DeclContext::decl_iterator E,
bool (SpecificDecl::*A)() const = 0)
: Current(C), End(E), Acceptable(A) {
SkipToNextDecl();
}
reference operator*() { return cast<SpecificDecl>(*Current); }
pointer operator->() { return cast<SpecificDecl>(*Current); }
specific_decl_iterator& operator++() {
++Current;
SkipToNextDecl();
return *this;
}
specific_decl_iterator operator++(int) {
specific_decl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool
operator==(const specific_decl_iterator& x, const specific_decl_iterator& y) {
return x.Current == y.Current;
}
friend bool
operator!=(const specific_decl_iterator& x, const specific_decl_iterator& y) {
return x.Current != y.Current;
}
};
/// addDecl - Add the declaration D to this scope. Note that
/// declarations are added at the beginning of the declaration
/// chain, so reverseDeclChain() should be called after all
@ -590,7 +674,6 @@ inline bool Decl::isTemplateParameter() const {
return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm;
}
} // end clang.
namespace llvm {

View File

@ -216,9 +216,11 @@ public:
ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
bool isInstance() const { return IsInstance; }
bool isInstanceMethod() const { return IsInstance; }
bool isVariadic() const { return IsVariadic; }
bool isClassMethod() const { return !IsInstance; }
bool isSynthesized() const { return IsSynthesized; }
void setIsSynthesized() { IsSynthesized = true; }
@ -248,10 +250,6 @@ public:
/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl, and
/// ObjCProtocolDecl.
/// FIXME: Use for ObjC implementation decls.
/// FIXME: It would be nice to reduce amount of "boilerplate" iterator code
/// below. For now, the iterators are modeled after RecordDecl::field_iterator().
/// If DeclContext ends up providing some support for creating more strongly
/// typed iterators, the code below should be reduced considerably.
/// FIXME: Convert property implementation to DeclContext::addDecl(). Holding
/// off until we have an iterator adaptor that plays with DeclContext.
///
@ -289,155 +287,32 @@ public:
ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
// Iterator access to instance/class methods.
class method_iterator {
public:
enum IterKind { IterInstanceMeths, IterClassMeths, IterAllMeths };
protected:
/// Current - Current position within the sequence of declarations
/// in this record.
DeclContext::decl_iterator Current;
/// End - Last position in the sequence of declarations in this
/// record.
DeclContext::decl_iterator End;
/// IK - Specifies the kind of methods this iterator iterates over.
IterKind IK;
/// SkipToNextMethod - Advances the current position up to the next
/// ObjCMethodDecl.
void SkipToNextMethod() {
while (Current != End) {
ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(*Current);
if (M && (IK == IterAllMeths ||
(IK == IterInstanceMeths && M->isInstance()) ||
((IK == IterClassMeths && !M->isInstance()))))
return;
++Current;
}
}
public:
typedef ObjCMethodDecl const * value_type;
typedef ObjCMethodDecl const * reference;
typedef ObjCMethodDecl const * pointer;
typedef std::ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category;
method_iterator() : Current(), End(), IK(IterAllMeths) { }
method_iterator(DeclContext::decl_iterator C,
DeclContext::decl_iterator E, IterKind ik)
: Current(C), End(E), IK(ik) {
SkipToNextMethod();
}
reference operator*() const { return cast<ObjCMethodDecl>(*Current); }
pointer operator->() const { return cast<ObjCMethodDecl>(*Current); }
method_iterator& operator++() {
++Current;
SkipToNextMethod();
return *this;
}
method_iterator operator++(int) {
method_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool
operator==(const method_iterator& x, const method_iterator& y) {
return x.Current == y.Current;
}
friend bool
operator!=(const method_iterator& x, const method_iterator& y) {
return x.Current != y.Current;
}
};
method_iterator meth_begin() const {
return method_iterator(decls_begin(), decls_end(),
method_iterator::IterAllMeths);
typedef specific_decl_iterator<ObjCMethodDecl> method_iterator;
method_iterator meth_begin() const {
return method_iterator(decls_begin(), decls_end());
}
method_iterator meth_end() const {
return method_iterator(decls_end(), decls_end(),
method_iterator::IterAllMeths);
method_iterator meth_end() const {
return method_iterator(decls_end(), decls_end());
}
class instmeth_iterator : public method_iterator {
public:
typedef ObjCMethodDecl* value_type;
typedef ObjCMethodDecl* reference;
typedef ObjCMethodDecl* pointer;
instmeth_iterator() : method_iterator() { }
instmeth_iterator(DeclContext::decl_iterator C,
DeclContext::decl_iterator E)
: method_iterator(C, E, IterInstanceMeths) { }
reference operator*() const { return cast<ObjCMethodDecl>(*Current); }
pointer operator->() const { return cast<ObjCMethodDecl>(*Current); }
instmeth_iterator& operator++() {
++Current;
SkipToNextMethod();
return *this;
}
instmeth_iterator operator++(int) {
instmeth_iterator tmp(*this);
++(*this);
return tmp;
}
};
typedef method_iterator instmeth_iterator;
instmeth_iterator instmeth_begin() const {
return instmeth_iterator(decls_begin(), decls_end());
return instmeth_iterator(decls_begin(), decls_end(),
&ObjCMethodDecl::isInstanceMethod);
}
instmeth_iterator instmeth_end() const {
return instmeth_iterator(decls_end(), decls_end());
return instmeth_iterator(decls_end(), decls_end(),
&ObjCMethodDecl::isInstanceMethod);
}
class classmeth_iterator : public method_iterator {
public:
typedef ObjCMethodDecl* value_type;
typedef ObjCMethodDecl* reference;
typedef ObjCMethodDecl* pointer;
classmeth_iterator() : method_iterator() { }
classmeth_iterator(DeclContext::decl_iterator C,
DeclContext::decl_iterator E)
: method_iterator(C, E, IterClassMeths) { }
reference operator*() const { return cast<ObjCMethodDecl>(*Current); }
pointer operator->() const { return cast<ObjCMethodDecl>(*Current); }
classmeth_iterator& operator++() {
++Current;
SkipToNextMethod();
return *this;
}
classmeth_iterator operator++(int) {
classmeth_iterator tmp(*this);
++(*this);
return tmp;
}
};
typedef method_iterator classmeth_iterator;
classmeth_iterator classmeth_begin() const {
return classmeth_iterator(decls_begin(), decls_end());
return classmeth_iterator(decls_begin(), decls_end(),
&ObjCMethodDecl::isClassMethod);
}
classmeth_iterator classmeth_end() const {
return classmeth_iterator(decls_end(), decls_end());
return classmeth_iterator(decls_end(), decls_end(),
&ObjCMethodDecl::isClassMethod);
}
// Get the local instance/class method declared in this interface.

View File

@ -631,8 +631,8 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
// Layout each field, for now, just sequentially, respecting alignment. In
// the future, this will need to be tweakable by targets.
unsigned FieldIdx = 0;
for (RecordDecl::field_const_iterator Field = D->field_begin(),
FieldEnd = D->field_end();
for (RecordDecl::field_iterator Field = D->field_begin(),
FieldEnd = D->field_end();
Field != FieldEnd; (void)++Field, ++FieldIdx)
NewEntry->LayoutField(*Field, FieldIdx, IsUnion, StructPacking, *this);

View File

@ -217,7 +217,7 @@ ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
const ObjCInterfaceDecl *OID) {
QualType selfTy;
if (isInstance()) {
if (isInstanceMethod()) {
// There may be no interface context due to error in declaration
// of the interface (which has been reported). Recover gracefully.
if (OID) {

View File

@ -43,7 +43,7 @@ static void mangleDeclContextInternal(const DeclContext *D, std::string &S)
// FIXME: This should really use GetNameForMethod from CGObjCMac.
std::string Name;
Name += MD->isInstance() ? '-' : '+';
Name += MD->isInstanceMethod() ? '-' : '+';
Name += '[';
Name += MD->getClassInterface()->getNameAsString();
Name += ' ';

View File

@ -205,7 +205,7 @@ static bool isEmptyStruct(QualType T) {
const RecordDecl *RD = RT->getDecl();
if (RD->hasFlexibleArrayMember())
return false;
for (RecordDecl::field_const_iterator i = RD->field_begin(),
for (RecordDecl::field_iterator i = RD->field_begin(),
e = RD->field_end(); i != e; ++i) {
const FieldDecl *FD = *i;
if (!isEmptyStruct(FD->getType()))
@ -232,7 +232,7 @@ static const FieldDecl *isSingleElementStruct(QualType T) {
return 0;
const FieldDecl *Found = 0;
for (RecordDecl::field_const_iterator i = RD->field_begin(),
for (RecordDecl::field_iterator i = RD->field_begin(),
e = RD->field_end(); i != e; ++i) {
const FieldDecl *FD = *i;
QualType FT = FD->getType();
@ -263,7 +263,7 @@ static bool is32Or64BitBasicType(QualType Ty, ASTContext &Context) {
static bool areAllFields32Or64BitBasicType(const RecordDecl *RD,
ASTContext &Context) {
for (RecordDecl::field_const_iterator i = RD->field_begin(),
for (RecordDecl::field_iterator i = RD->field_begin(),
e = RD->field_end(); i != e; ++i) {
const FieldDecl *FD = *i;
@ -441,7 +441,7 @@ void CodeGenTypes::GetExpandedTypes(QualType Ty,
assert(!RD->hasFlexibleArrayMember() &&
"Cannot expand structure with flexible array.");
for (RecordDecl::field_const_iterator i = RD->field_begin(),
for (RecordDecl::field_iterator i = RD->field_begin(),
e = RD->field_end(); i != e; ++i) {
const FieldDecl *FD = *i;
assert(!FD->isBitField() &&

View File

@ -938,7 +938,7 @@ llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD) {
std::string CategoryName = OCD ? OCD->getNameAsString() : "";
std::string ClassName = OMD->getClassInterface()->getNameAsString();
std::string MethodName = OMD->getSelector().getAsString();
bool isClassMethod = !OMD->isInstance();
bool isClassMethod = !OMD->isInstanceMethod();
const llvm::FunctionType *MethodTy =
CGM.getTypes().GetFunctionType(CGFunctionInfo(OMD, CGM.getContext()));

View File

@ -2143,7 +2143,7 @@ llvm::Constant *CGObjCMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
void CGObjCMac::GetNameForMethod(const ObjCMethodDecl *D,
std::string &NameOut) {
// FIXME: Find the mangling GCC uses.
NameOut = (D->isInstance() ? "-" : "+");
NameOut = (D->isInstanceMethod() ? "-" : "+");
NameOut += '[';
NameOut += D->getClassInterface()->getNameAsString();
NameOut += ' ';

View File

@ -455,8 +455,8 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
std::vector<const llvm::Type*> LLVMFields;
unsigned curField = 0;
for (RecordDecl::field_const_iterator Field = RD.field_begin(),
FieldEnd = RD.field_end();
for (RecordDecl::field_iterator Field = RD.field_begin(),
FieldEnd = RD.field_end();
Field != FieldEnd; ++Field) {
uint64_t offset = RL.getFieldOffset(curField);
const llvm::Type *Ty = CGT.ConvertTypeRecursive(Field->getType());
@ -506,8 +506,8 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
/// all fields are added.
void RecordOrganizer::layoutUnionFields(const ASTRecordLayout &RL) {
unsigned curField = 0;
for (RecordDecl::field_const_iterator Field = RD.field_begin(),
FieldEnd = RD.field_end();
for (RecordDecl::field_iterator Field = RD.field_begin(),
FieldEnd = RD.field_end();
Field != FieldEnd; ++Field) {
// The offset should usually be zero, but bitfields could be strange
uint64_t offset = RL.getFieldOffset(curField);

View File

@ -30,7 +30,7 @@ void Sema::ObjCActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) {
return;
// Allow the rest of sema to find private method decl implementations.
if (MDecl->isInstance())
if (MDecl->isInstanceMethod())
AddInstanceMethodToGlobalPool(MDecl);
else
AddFactoryMethodToGlobalPool(MDecl);
@ -1172,7 +1172,7 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl,
cast_or_null<ObjCMethodDecl>(static_cast<Decl*>(allMethods[i]));
if (!Method) continue; // Already issued a diagnostic.
if (Method->isInstance()) {
if (Method->isInstanceMethod()) {
/// Check for instance method of the same name with incompatible types
const ObjCMethodDecl *&PrevMethod = InsMap[Method->getSelector()];
bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)

View File

@ -197,7 +197,7 @@ Sema::ExprResult Sema::ActOnClassMessage(
ClassDecl = OID->getSuperClass();
if (!ClassDecl)
return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName();
if (getCurMethodDecl()->isInstance()) {
if (getCurMethodDecl()->isInstanceMethod()) {
QualType superTy = Context.getObjCInterfaceType(ClassDecl);
superTy = Context.getPointerType(superTy);
ExprResult ReceiverExpr = new ObjCSuperExpr(SourceLocation(), superTy);

View File

@ -568,7 +568,7 @@ QualType Sema::ObjCGetTypeForMethodDefinition(DeclTy *D) {
llvm::SmallVector<QualType, 16> ArgTys;
// Add the first two invisible argument types for self and _cmd.
if (MDecl->isInstance()) {
if (MDecl->isInstanceMethod()) {
QualType selfTy = Context.getObjCInterfaceType(MDecl->getClassInterface());
selfTy = Context.getPointerType(selfTy);
ArgTys.push_back(selfTy);