@@ -761,67 +761,196 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
761
761
D);
762
762
}
763
763
764
+ private:
765
+ bool TraversingASTNodeNotSpelledInSource = false ;
766
+ bool TraversingASTNodeNotAsIs = false ;
767
+ bool TraversingASTChildrenNotSpelledInSource = false ;
768
+
769
+ class CurMatchData {
770
+ // We don't have enough free low bits in 32bit builds to discriminate 8 pointer
771
+ // types in PointerUnion. so split the union in 2 using a free bit from the
772
+ // callback pointer.
773
+ #define CMD_TYPES_0 \
774
+ const QualType *, const TypeLoc *, const NestedNameSpecifier *, \
775
+ const NestedNameSpecifierLoc *
776
+ #define CMD_TYPES_1 \
777
+ const CXXCtorInitializer *, const TemplateArgumentLoc *, const Attr *, \
778
+ const DynTypedNode *
779
+
780
+ #define IMPL (Index ) \
781
+ template <typename NodeType> \
782
+ typename std::enable_if_t < \
783
+ llvm::is_one_of<const NodeType *, CMD_TYPES_##Index>::value> \
784
+ SetCallbackAndRawNode (const MatchCallback *CB, const NodeType &N) { \
785
+ assertEmpty (); \
786
+ Callback.setPointerAndInt (CB, Index); \
787
+ Node##Index = &N; \
788
+ } \
789
+ \
790
+ template <typename T> \
791
+ typename std::enable_if_t < \
792
+ llvm::is_one_of<const T *, CMD_TYPES_##Index>::value, const T *> \
793
+ getNode () const { \
794
+ assertHoldsState (); \
795
+ return Callback.getInt () == (Index) ? Node##Index.dyn_cast <const T *>() \
796
+ : nullptr ; \
797
+ }
798
+
799
+ public:
800
+ CurMatchData () : Node0(nullptr ) {}
801
+
802
+ IMPL (0 )
803
+ IMPL (1 )
804
+
805
+ const MatchCallback *getCallback () const { return Callback.getPointer (); }
806
+
807
+ void SetBoundNodes (const BoundNodes &BN) {
808
+ assertHoldsState ();
809
+ BNodes = &BN;
810
+ }
811
+
812
+ void clearBoundNodes () {
813
+ assertHoldsState ();
814
+ BNodes = nullptr ;
815
+ }
816
+
817
+ const BoundNodes *getBoundNodes () const {
818
+ assertHoldsState ();
819
+ return BNodes;
820
+ }
821
+
822
+ void reset () {
823
+ assertHoldsState ();
824
+ Callback.setPointerAndInt (nullptr , 0 );
825
+ Node0 = nullptr ;
826
+ }
827
+
828
+ private:
829
+ void assertHoldsState () const {
830
+ assert (Callback.getPointer () != nullptr && !Node0.isNull ());
831
+ }
832
+
833
+ void assertEmpty () const {
834
+ assert (Callback.getPointer () == nullptr && Node0.isNull () &&
835
+ BNodes == nullptr );
836
+ }
837
+
838
+ llvm::PointerIntPair<const MatchCallback *, 1 > Callback;
839
+ union {
840
+ llvm::PointerUnion<CMD_TYPES_0> Node0;
841
+ llvm::PointerUnion<CMD_TYPES_1> Node1;
842
+ };
843
+ const BoundNodes *BNodes = nullptr ;
844
+
845
+ #undef CMD_TYPES_0
846
+ #undef CMD_TYPES_1
847
+ #undef IMPL
848
+ } CurMatchState;
849
+
850
+ struct CurMatchRAII {
851
+ template <typename NodeType>
852
+ CurMatchRAII (MatchASTVisitor &MV, const MatchCallback *CB,
853
+ const NodeType &NT)
854
+ : MV(MV) {
855
+ MV.CurMatchState .SetCallbackAndRawNode (CB, NT);
856
+ }
857
+
858
+ ~CurMatchRAII () { MV.CurMatchState .reset (); }
859
+
860
+ private:
861
+ MatchASTVisitor &MV;
862
+ };
863
+
864
+ public:
764
865
class TraceReporter : llvm::PrettyStackTraceEntry {
866
+ static void dumpNode (const ASTContext &Ctx, const DynTypedNode &Node,
867
+ raw_ostream &OS) {
868
+ if (const auto *D = Node.get <Decl>()) {
869
+ OS << D->getDeclKindName () << " Decl " ;
870
+ if (const auto *ND = dyn_cast<NamedDecl>(D)) {
871
+ ND->printQualifiedName (OS);
872
+ OS << " : " ;
873
+ } else
874
+ OS << " : " ;
875
+ D->getSourceRange ().print (OS, Ctx.getSourceManager ());
876
+ } else if (const auto *S = Node.get <Stmt>()) {
877
+ OS << S->getStmtClassName () << " : " ;
878
+ S->getSourceRange ().print (OS, Ctx.getSourceManager ());
879
+ } else if (const auto *T = Node.get <Type>()) {
880
+ OS << T->getTypeClassName () << " Type : " ;
881
+ QualType (T, 0 ).print (OS, Ctx.getPrintingPolicy ());
882
+ } else if (const auto *QT = Node.get <QualType>()) {
883
+ OS << " QualType : " ;
884
+ QT->print (OS, Ctx.getPrintingPolicy ());
885
+ } else {
886
+ OS << Node.getNodeKind ().asStringRef () << " : " ;
887
+ Node.getSourceRange ().print (OS, Ctx.getSourceManager ());
888
+ }
889
+ }
890
+
891
+ static void dumpNodeFromState (const ASTContext &Ctx,
892
+ const CurMatchData &State, raw_ostream &OS) {
893
+ if (const DynTypedNode *MatchNode = State.getNode <DynTypedNode>()) {
894
+ dumpNode (Ctx, *MatchNode, OS);
895
+ } else if (const auto *QT = State.getNode <QualType>()) {
896
+ dumpNode (Ctx, DynTypedNode::create (*QT), OS);
897
+ } else if (const auto *TL = State.getNode <TypeLoc>()) {
898
+ dumpNode (Ctx, DynTypedNode::create (*TL), OS);
899
+ } else if (const auto *NNS = State.getNode <NestedNameSpecifier>()) {
900
+ dumpNode (Ctx, DynTypedNode::create (*NNS), OS);
901
+ } else if (const auto *NNSL = State.getNode <NestedNameSpecifierLoc>()) {
902
+ dumpNode (Ctx, DynTypedNode::create (*NNSL), OS);
903
+ } else if (const auto *CtorInit = State.getNode <CXXCtorInitializer>()) {
904
+ dumpNode (Ctx, DynTypedNode::create (*CtorInit), OS);
905
+ } else if (const auto *TAL = State.getNode <TemplateArgumentLoc>()) {
906
+ dumpNode (Ctx, DynTypedNode::create (*TAL), OS);
907
+ } else if (const auto *At = State.getNode <Attr>()) {
908
+ dumpNode (Ctx, DynTypedNode::create (*At), OS);
909
+ }
910
+ }
911
+
765
912
public:
766
913
TraceReporter (const MatchASTVisitor &MV) : MV(MV) {}
767
914
void print (raw_ostream &OS) const override {
768
- if (!MV.CurMatched ) {
915
+ const CurMatchData &State = MV.CurMatchState ;
916
+ const MatchCallback *CB = State.getCallback ();
917
+ if (!CB) {
769
918
OS << " ASTMatcher: Not currently matching\n " ;
770
919
return ;
771
920
}
921
+
772
922
assert (MV.ActiveASTContext &&
773
923
" ActiveASTContext should be set if there is a matched callback" );
774
924
775
- OS << " ASTMatcher: Processing '" << MV.CurMatched ->getID () << " '\n " ;
776
- const BoundNodes::IDToNodeMap &Map = MV.CurBoundNodes ->getMap ();
777
- if (Map.empty ()) {
778
- OS << " No bound nodes\n " ;
779
- return ;
780
- }
781
- OS << " --- Bound Nodes Begin ---\n " ;
782
- for (const auto &Item : Map) {
783
- OS << " " << Item.first << " - { " ;
784
- if (const auto *D = Item.second .get <Decl>()) {
785
- OS << D->getDeclKindName () << " Decl " ;
786
- if (const auto *ND = dyn_cast<NamedDecl>(D)) {
787
- ND->printQualifiedName (OS);
788
- OS << " : " ;
789
- } else
790
- OS << " : " ;
791
- D->getSourceRange ().print (OS,
792
- MV.ActiveASTContext ->getSourceManager ());
793
- } else if (const auto *S = Item.second .get <Stmt>()) {
794
- OS << S->getStmtClassName () << " : " ;
795
- S->getSourceRange ().print (OS,
796
- MV.ActiveASTContext ->getSourceManager ());
797
- } else if (const auto *T = Item.second .get <Type>()) {
798
- OS << T->getTypeClassName () << " Type : " ;
799
- QualType (T, 0 ).print (OS, MV.ActiveASTContext ->getPrintingPolicy ());
800
- } else if (const auto *QT = Item.second .get <QualType>()) {
801
- OS << " QualType : " ;
802
- QT->print (OS, MV.ActiveASTContext ->getPrintingPolicy ());
803
- } else {
804
- OS << Item.second .getNodeKind ().asStringRef () << " : " ;
805
- Item.second .getSourceRange ().print (
806
- OS, MV.ActiveASTContext ->getSourceManager ());
925
+ ASTContext &Ctx = MV.getASTContext ();
926
+
927
+ if (const BoundNodes *Nodes = State.getBoundNodes ()) {
928
+ OS << " ASTMatcher: Processing '" << CB->getID () << " ' against:\n\t " ;
929
+ dumpNodeFromState (Ctx, State, OS);
930
+ const BoundNodes::IDToNodeMap &Map = Nodes->getMap ();
931
+ if (Map.empty ()) {
932
+ OS << " \n No bound nodes\n " ;
933
+ return ;
807
934
}
808
- OS << " }\n " ;
935
+ OS << " \n --- Bound Nodes Begin ---\n " ;
936
+ for (const auto &Item : Map) {
937
+ OS << " " << Item.first << " - { " ;
938
+ dumpNode (Ctx, Item.second , OS);
939
+ OS << " }\n " ;
940
+ }
941
+ OS << " --- Bound Nodes End ---\n " ;
942
+ } else {
943
+ OS << " ASTMatcher: Matching '" << CB->getID () << " ' against:\n\t " ;
944
+ dumpNodeFromState (Ctx, State, OS);
945
+ OS << ' \n ' ;
809
946
}
810
- OS << " --- Bound Nodes End ---\n " ;
811
947
}
812
948
813
949
private:
814
950
const MatchASTVisitor &MV;
815
951
};
816
952
817
953
private:
818
- bool TraversingASTNodeNotSpelledInSource = false ;
819
- bool TraversingASTNodeNotAsIs = false ;
820
- bool TraversingASTChildrenNotSpelledInSource = false ;
821
-
822
- const MatchCallback *CurMatched = nullptr ;
823
- const BoundNodes *CurBoundNodes = nullptr ;
824
-
825
954
struct ASTNodeNotSpelledInSourceScope {
826
955
ASTNodeNotSpelledInSourceScope (MatchASTVisitor *V, bool B)
827
956
: MV(V), MB(V->TraversingASTNodeNotSpelledInSource) {
@@ -887,6 +1016,7 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
887
1016
if (EnableCheckProfiling)
888
1017
Timer.setBucket (&TimeByBucket[MP.second ->getID ()]);
889
1018
BoundNodesTreeBuilder Builder;
1019
+ CurMatchRAII RAII (*this , MP.second , Node);
890
1020
if (MP.first .matches (Node, this , &Builder)) {
891
1021
MatchVisitor Visitor (*this , ActiveASTContext, MP.second );
892
1022
Builder.visitMatches (&Visitor);
@@ -919,6 +1049,7 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
919
1049
continue ;
920
1050
}
921
1051
1052
+ CurMatchRAII RAII (*this , MP.second , DynNode);
922
1053
if (MP.first .matches (DynNode, this , &Builder)) {
923
1054
MatchVisitor Visitor (*this , ActiveASTContext, MP.second );
924
1055
Builder.visitMatches (&Visitor);
@@ -1107,35 +1238,30 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
1107
1238
// the aggregated bound nodes for each match.
1108
1239
class MatchVisitor : public BoundNodesTreeBuilder ::Visitor {
1109
1240
struct CurBoundScope {
1110
- CurBoundScope (MatchASTVisitor &MV , const BoundNodes &BN) : MV(MV) {
1111
- assert (MV. CurMatched && !MV. CurBoundNodes );
1112
- MV. CurBoundNodes = &BN ;
1241
+ CurBoundScope (MatchASTVisitor::CurMatchData &State , const BoundNodes &BN)
1242
+ : State(State) {
1243
+ State. SetBoundNodes (BN) ;
1113
1244
}
1114
1245
1115
- ~CurBoundScope () { MV. CurBoundNodes = nullptr ; }
1246
+ ~CurBoundScope () { State. clearBoundNodes () ; }
1116
1247
1117
1248
private:
1118
- MatchASTVisitor &MV ;
1249
+ MatchASTVisitor::CurMatchData &State ;
1119
1250
};
1120
1251
1121
1252
public:
1122
1253
MatchVisitor (MatchASTVisitor &MV, ASTContext *Context,
1123
1254
MatchFinder::MatchCallback *Callback)
1124
- : MV(MV), Context(Context), Callback(Callback) {
1125
- assert (!MV.CurMatched && !MV.CurBoundNodes );
1126
- MV.CurMatched = Callback;
1127
- }
1128
-
1129
- ~MatchVisitor () { MV.CurMatched = nullptr ; }
1255
+ : State(MV.CurMatchState), Context(Context), Callback(Callback) {}
1130
1256
1131
1257
void visitMatch (const BoundNodes& BoundNodesView) override {
1132
1258
TraversalKindScope RAII (*Context, Callback->getCheckTraversalKind ());
1133
- CurBoundScope RAII2 (MV , BoundNodesView);
1259
+ CurBoundScope RAII2 (State , BoundNodesView);
1134
1260
Callback->run (MatchFinder::MatchResult (BoundNodesView, Context));
1135
1261
}
1136
1262
1137
1263
private:
1138
- MatchASTVisitor &MV ;
1264
+ MatchASTVisitor::CurMatchData &State ;
1139
1265
ASTContext* Context;
1140
1266
MatchFinder::MatchCallback* Callback;
1141
1267
};
0 commit comments