13
13
#include " clang/Lex/Preprocessor.h"
14
14
#include " llvm/Support/Regex.h"
15
15
#include < algorithm>
16
- #include < deque>
17
16
#include < optional>
17
+ #include < vector>
18
18
19
19
using namespace clang ::ast_matchers;
20
20
@@ -23,8 +23,8 @@ namespace clang::tidy::misc {
23
23
namespace {
24
24
25
25
struct Include {
26
- FileID Id ;
27
- llvm:: StringRef Name;
26
+ const FileEntry *File ;
27
+ StringRef Name;
28
28
SourceLocation Loc;
29
29
};
30
30
@@ -50,31 +50,27 @@ class CyclicDependencyCallbacks : public PPCallbacks {
50
50
if (Reason != EnterFile && Reason != ExitFile)
51
51
return ;
52
52
53
- FileID Id = SM.getFileID (Loc);
53
+ const FileID Id = SM.getFileID (Loc);
54
54
if (Id.isInvalid ())
55
55
return ;
56
56
57
+ const FileEntry *NewFile = SM.getFileEntryForID (Id);
58
+ const FileEntry *PrevFile = SM.getFileEntryForID (PrevFID);
59
+
57
60
if (Reason == ExitFile) {
58
- if ((Files.size () > 1U ) && (Files.back ().Id == PrevFID ) &&
59
- (Files[Files.size () - 2U ].Id == Id ))
61
+ if ((Files.size () > 1U ) && (Files.back ().File == PrevFile ) &&
62
+ (Files[Files.size () - 2U ].File == NewFile ))
60
63
Files.pop_back ();
61
64
return ;
62
65
}
63
66
64
- if (!Files.empty () && Files.back ().Id == Id )
67
+ if (!Files.empty () && Files.back ().File == NewFile )
65
68
return ;
66
69
67
- std::optional<llvm::StringRef> FilePath = SM.getNonBuiltinFilenameForID (Id);
68
- llvm::StringRef FileName =
69
- FilePath ? llvm::sys::path::filename (*FilePath) : llvm::StringRef ();
70
-
71
- if (!NextToEnter)
72
- NextToEnter = Include{Id, FileName, SourceLocation ()};
73
-
74
- assert (NextToEnter->Name == FileName);
75
- NextToEnter->Id = Id;
76
- Files.emplace_back (*NextToEnter);
77
- NextToEnter.reset ();
70
+ const std::optional<StringRef> FilePath = SM.getNonBuiltinFilenameForID (Id);
71
+ const StringRef FileName =
72
+ FilePath ? llvm::sys::path::filename (*FilePath) : StringRef ();
73
+ Files.push_back ({NewFile, FileName, std::exchange (NextToEnter, {})});
78
74
}
79
75
80
76
void InclusionDirective (SourceLocation, const Token &, StringRef FilePath,
@@ -85,36 +81,26 @@ class CyclicDependencyCallbacks : public PPCallbacks {
85
81
if (FileType != clang::SrcMgr::C_User)
86
82
return ;
87
83
88
- llvm::StringRef FileName = llvm::sys::path::filename (FilePath);
89
- NextToEnter = {FileID (), FileName, Range.getBegin ()};
84
+ NextToEnter = Range.getBegin ();
90
85
91
86
if (!File)
92
87
return ;
93
88
94
- FileID Id = SM.translateFile (*File);
95
- if (Id.isInvalid ())
96
- return ;
97
-
98
- checkForDoubleInclude (Id, FileName, Range.getBegin ());
99
- }
100
-
101
- void EndOfMainFile () override {
102
- if (!Files.empty () && Files.back ().Id == SM.getMainFileID ())
103
- Files.pop_back ();
104
-
105
- assert (Files.empty ());
89
+ checkForDoubleInclude (&File->getFileEntry (),
90
+ llvm::sys::path::filename (FilePath),
91
+ Range.getBegin ());
106
92
}
107
93
108
- void checkForDoubleInclude (FileID Id, llvm:: StringRef FileName,
94
+ void checkForDoubleInclude (const FileEntry *File, StringRef FileName,
109
95
SourceLocation Loc) {
110
- auto It =
111
- std ::find_if (Files. rbegin (), Files. rend ( ),
112
- [&](const Include &Entry) { return Entry.Id == Id ; });
96
+ const auto It =
97
+ llvm ::find_if (llvm::reverse ( Files),
98
+ [&](const Include &Entry) { return Entry.File == File ; });
113
99
if (It == Files.rend ())
114
100
return ;
115
101
116
- const std::optional< StringRef> FilePath = SM. getNonBuiltinFilenameForID (Id );
117
- if (! FilePath || isFileIgnored (* FilePath))
102
+ const StringRef FilePath = File-> tryGetRealPathName ( );
103
+ if (FilePath. empty () || isFileIgnored (FilePath))
118
104
return ;
119
105
120
106
if (It == Files.rbegin ()) {
@@ -144,9 +130,19 @@ class CyclicDependencyCallbacks : public PPCallbacks {
144
130
});
145
131
}
146
132
133
+ #ifndef NDEBUG
134
+ void EndOfMainFile () override {
135
+ if (!Files.empty () &&
136
+ Files.back ().File == SM.getFileEntryForID (SM.getMainFileID ()))
137
+ Files.pop_back ();
138
+
139
+ assert (Files.empty ());
140
+ }
141
+ #endif
142
+
147
143
private:
148
- std::deque <Include> Files;
149
- std::optional<Include> NextToEnter;
144
+ std::vector <Include> Files;
145
+ SourceLocation NextToEnter;
150
146
HeaderIncludeCycleCheck &Check;
151
147
const SourceManager &SM;
152
148
std::vector<llvm::Regex> IgnoredFilesRegexes;
0 commit comments