Another chunk of the new RecursiveASTVisitor implementation: switch the return

value semantics such that we recurse while the visitors return true, and halt
as soon as one returns false. Patch by csilvers.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105787 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chandler Carruth 2010-06-10 10:31:57 +00:00
Родитель 022a8a59f6
Коммит e3e210c3aa
3 изменённых файлов: 57 добавлений и 59 удалений

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

@ -37,7 +37,7 @@ namespace clang {
// object (s.t. a user of RecursiveASTVisitor can override the method
// in CALL_EXPR).
#define TRY_TO(CALL_EXPR) \
do { if (getDerived().CALL_EXPR) return true; } while (0)
do { if (!getDerived().CALL_EXPR) return false; } while (0)
/// \brief A class that does preorder depth-first traversal on the
/// entire Clang AST and visits each node.
@ -67,7 +67,7 @@ namespace clang {
///
/// These three method groups are tiered (Traverse* > WalkUpFrom* >
/// Visit*). A method (e.g. Traverse*) may call methods from the same
/// tier (e.g. other Traverse*) or one-tier lower (e.g. WalkUpFrom*).
/// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*).
/// It may not call methods from a higher tier.
///
/// This scheme guarantees that all Visit*() calls for the same AST
@ -81,10 +81,8 @@ namespace clang {
/// expressions, or other AST nodes where the visitor should customize
/// behavior. Most users only need to override Visit*. Advanced
/// users may override Traverse* and WalkUpFrom* to implement custom
/// traversal strategies. Returning true from one of these overridden
/// traversal strategies. Returning false from one of these overridden
/// functions will abort the entire traversal.
///
/// FIXME: reverse the meaning of the bool return value.
template<typename Derived>
class RecursiveASTVisitor {
public:
@ -95,7 +93,7 @@ public:
/// dispatching to Visit*() based on the argument's dynamic type.
/// This is NOT meant to be overridden by a subclass.
///
/// \returns true if the visitation was terminated early, false
/// \returns false if the visitation was terminated early, true
/// otherwise (including when the argument is NULL).
bool TraverseStmt(Stmt *S);
@ -103,7 +101,7 @@ public:
/// Visit*Type() based on the argument's getTypeClass() property.
/// This is NOT meant to be overridden by a subclass.
///
/// \returns true if the visitation was terminated early, false
/// \returns false if the visitation was terminated early, true
/// otherwise (including when the argument is a Null type).
bool TraverseType(QualType T);
@ -111,25 +109,25 @@ public:
/// Visit*Decl() based on the argument's dynamic type. This is
/// NOT meant to be overridden by a subclass.
///
/// \returns true if the visitation was terminated early, false
/// \returns false if the visitation was terminated early, true
/// otherwise (including when the argument is NULL).
bool TraverseDecl(Decl *D);
/// \brief Recursively visit a C++ nested-name-specifier.
///
/// \returns true if the visitation was terminated early, false otherwise.
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
/// \brief Recursively visit a template name and dispatch to the
/// appropriate method.
///
/// \returns true if the visitation was terminated early, false otherwise.
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseTemplateName(TemplateName Template);
/// \brief Recursively visit a template argument and dispatch to the
/// appropriate method for the argument type.
///
/// \returns true if the visitation was terminated early, false otherwise.
/// \returns false if the visitation was terminated early, true otherwise.
// FIXME: take a TemplateArgumentLoc instead.
bool TraverseTemplateArgument(const TemplateArgument &Arg);
@ -137,7 +135,7 @@ public:
/// This can be overridden by a subclass, but it's not expected that
/// will be needed -- this visitor always dispatches to another.
///
/// \returns true if the visitation was terminated early, false otherwise.
/// \returns false if the visitation was terminated early, true otherwise.
// FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
bool TraverseTemplateArguments(const TemplateArgument *Args,
unsigned NumArgs);
@ -153,14 +151,14 @@ public:
// Define WalkUpFrom*() and empty Visit*() for all Stmt classes.
bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); }
bool VisitStmt(Stmt *S) { return false; }
bool VisitStmt(Stmt *S) { return true; }
#define STMT(CLASS, PARENT) \
bool WalkUpFrom##CLASS(CLASS *S) { \
TRY_TO(WalkUpFrom##PARENT(S)); \
TRY_TO(Visit##CLASS(S)); \
return false; \
return true; \
} \
bool Visit##CLASS(CLASS *S) { return false; }
bool Visit##CLASS(CLASS *S) { return true; }
#include "clang/AST/StmtNodes.inc"
// Define Traverse*(), WalkUpFrom*(), and Visit*() for unary
@ -170,14 +168,14 @@ public:
bool TraverseUnary##NAME(UnaryOperator *S) { \
TRY_TO(WalkUpFromUnary##NAME(S)); \
TRY_TO(TraverseStmt(S->getSubExpr())); \
return false; \
return true; \
} \
bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
TRY_TO(WalkUpFromUnaryOperator(S)); \
TRY_TO(VisitUnary##NAME(S)); \
return false; \
return true; \
} \
bool VisitUnary##NAME(UnaryOperator *S) { return false; }
bool VisitUnary##NAME(UnaryOperator *S) { return true; }
UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec)
UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec)
@ -197,14 +195,14 @@ public:
TRY_TO(WalkUpFromBin##NAME(S)); \
TRY_TO(TraverseStmt(S->getLHS())); \
TRY_TO(TraverseStmt(S->getRHS())); \
return false; \
return true; \
} \
bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \
TRY_TO(VisitBin##NAME(S)); \
return false; \
return true; \
} \
bool VisitBin##NAME(BINOP_TYPE *S) { return false; }
bool VisitBin##NAME(BINOP_TYPE *S) { return true; }
#define BINOP_FALLBACK(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator)
@ -249,14 +247,14 @@ public:
// Define WalkUpFrom*() and empty Visit*() for all Type classes.
bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); }
bool VisitType(Type *T) { return false; }
bool VisitType(Type *T) { return true; }
#define TYPE(CLASS, BASE) \
bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \
TRY_TO(WalkUpFrom##BASE(T)); \
TRY_TO(Visit##CLASS##Type(T)); \
return false; \
return true; \
} \
bool Visit##CLASS##Type(CLASS##Type *T) { return false; }
bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
#include "clang/AST/TypeNodes.def"
// ---- Methods on Decls ----
@ -270,14 +268,14 @@ public:
// Define WalkUpFrom*() and empty Visit*() for all Decl classes.
bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); }
bool VisitDecl(Decl *D) { return false; }
bool VisitDecl(Decl *D) { return true; }
#define DECL(CLASS, BASE) \
bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \
TRY_TO(WalkUpFrom##BASE(D)); \
TRY_TO(Visit##CLASS##Decl(D)); \
return false; \
return true; \
} \
bool Visit##CLASS##Decl(CLASS##Decl *D) { return false; }
bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
#include "clang/AST/DeclNodes.inc"
private:
@ -298,7 +296,7 @@ private:
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
if (!S)
return false;
return true;
// If we have a binary expr, dispatch to the subcode of the binop. A smart
// optimizer (e.g. LLVM) will fold this comparison into the switch stmt
@ -378,13 +376,13 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
#include "clang/AST/StmtNodes.inc"
}
return false;
return true;
}
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
if (T.isNull())
return false;
return true;
switch (T->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, BASE)
@ -393,13 +391,13 @@ bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
#include "clang/AST/TypeNodes.def"
}
return false;
return true;
}
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
if (!D)
return false;
return true;
switch (D->getKind()) {
#define ABSTRACT_DECL(DECL)
@ -408,7 +406,7 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
#include "clang/AST/DeclNodes.inc"
}
return false;
return true;
}
#undef DISPATCH
@ -417,36 +415,36 @@ template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
NestedNameSpecifier *NNS) {
if (!NNS)
return false;
return true;
if (NNS->getPrefix() &&
getDerived().TraverseNestedNameSpecifier(NNS->getPrefix()))
return true;
!getDerived().TraverseNestedNameSpecifier(NNS->getPrefix()))
return false;
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::Global:
return false;
return true;
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
return getDerived().TraverseType(QualType(NNS->getAsType(), 0));
}
return false;
return true;
}
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) {
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
return DTN->getQualifier() &&
getDerived().TraverseNestedNameSpecifier(DTN->getQualifier());
return (!DTN->getQualifier() ||
getDerived().TraverseNestedNameSpecifier(DTN->getQualifier()));
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
return getDerived().TraverseNestedNameSpecifier(QTN->getQualifier());
return false;
return true;
}
template<typename Derived>
@ -456,7 +454,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
case TemplateArgument::Null:
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
return false;
return true;
case TemplateArgument::Type:
return getDerived().TraverseType(Arg.getAsType());
@ -472,7 +470,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
Arg.pack_size());
}
return false;
return true;
}
template<typename Derived>
@ -483,7 +481,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
TRY_TO(TraverseTemplateArgument(Args[I]));
}
return false;
return true;
}
// ----------------- Type traversal -----------------
@ -494,7 +492,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
bool RecursiveASTVisitor<Derived>::Traverse##TYPE (TYPE *T) { \
TRY_TO(WalkUpFrom##TYPE (T)); \
{ CODE; } \
return false; \
return true; \
}
DEF_TRAVERSE_TYPE(BuiltinType, { })
@ -654,7 +652,7 @@ bool RecursiveASTVisitor<Derived>::Traverse##DECL (DECL *D) { \
Child != ChildEnd; ++Child) \
TRY_TO(TraverseDecl(*Child)); \
} \
return false; \
return true; \
}
DEF_TRAVERSE_DECL(AccessSpecDecl, { })
@ -718,7 +716,7 @@ DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
// This return statement makes sure the traversal of nodes in
// decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
// is skipped - don't remove it.
return false;
return true;
})
DEF_TRAVERSE_DECL(NamespaceDecl, {
@ -783,7 +781,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
TRY_TO(TraverseDecl(*I));
}
}
return false;
return true;
}
DEF_TRAVERSE_DECL(ClassTemplateDecl, {
@ -859,14 +857,14 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(
// traverse D->getAnonymousStructOrUnionObject(), as it's not
// something that is explicitly written in the source.
TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
return false;
return true;
}
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(
CXXRecordDecl *D) {
if (TraverseRecordHelper(D))
return true;
if (!TraverseRecordHelper(D))
return false;
if (D->hasDefinition()) {
for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
E = D->bases_end();
@ -876,7 +874,7 @@ bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(
// We don't traverse the friends or the conversions, as they are
// already in decls_begin()/decls_end().
}
return false;
return true;
}
DEF_TRAVERSE_DECL(RecordDecl, {
@ -905,7 +903,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
// FIXME: pass along the loc information to this callback as well?
TRY_TO(TraverseTemplateArgument(TAL[I].getArgument()));
}
return false;
return true;
}
DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
@ -942,7 +940,7 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
if (D->getTypeSourceInfo())
TRY_TO(TraverseType(D->getTypeSourceInfo()->getType()));
return false;
return true;
}
DEF_TRAVERSE_DECL(FieldDecl, {
@ -974,7 +972,7 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
if (D->isThisDeclarationADefinition()) {
TRY_TO(TraverseStmt(D->getBody()));
}
return false;
return true;
}
DEF_TRAVERSE_DECL(FunctionDecl, {
@ -1012,7 +1010,7 @@ bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
// vars, though not for global vars -- because the initializer is
// also captured when the var-decl is in a DeclStmt.
TRY_TO(TraverseStmt(D->getInit()));
return false;
return true;
}
DEF_TRAVERSE_DECL(VarDecl, {
@ -1071,7 +1069,7 @@ bool RecursiveASTVisitor<Derived>::Traverse##STMT (STMT *S) { \
C != CEnd; ++C) { \
TRY_TO(TraverseStmt(*C)); \
} \
return false; \
return true; \
}
DEF_TRAVERSE_STMT(AsmStmt, {

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

@ -23,7 +23,7 @@ namespace {
bool VisitCXXRecordDecl(CXXRecordDecl *D) {
std::cout << D->getNameAsString() << std::endl;
return false;
return true;
}
};
}

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

@ -7681,7 +7681,7 @@ bool MarkReferencedDecls::TraverseRecordType(RecordType *T) {
Args.flat_size());
}
return false;
return true;
}
void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {