16
16
#include " clang/Rewrite/Rewriter.h"
17
17
#include " clang/Lex/Preprocessor.h"
18
18
#include " clang/Basic/SourceManager.h"
19
- #include " llvm/Support/MemoryBuffer.h"
20
19
#include " llvm/Support/Streams.h"
21
20
#include " llvm/System/Path.h"
22
21
#include < fstream>
23
22
using namespace clang ;
24
23
24
+ // / isSameToken - Return true if the two specified tokens start have the same
25
+ // / content.
26
+ static bool isSameToken (Token &RawTok, Token &PPTok) {
27
+ if (PPTok.getKind () == RawTok.getKind ())
28
+ return true ;
29
+
30
+ if (PPTok.getIdentifierInfo () &&
31
+ PPTok.getIdentifierInfo () == RawTok.getIdentifierInfo ())
32
+ return true ;
33
+
34
+ return false ;
35
+ }
36
+
37
+ static void GetNextRawTok (Lexer &RawLex, Token &RawTok, Preprocessor &PP) {
38
+ RawLex.LexRawToken (RawTok);
39
+
40
+ // If we have an identifier with no identifier info for our raw token, look
41
+ // up the indentifier info.
42
+ if (RawTok.is (tok::identifier) && !RawTok.getIdentifierInfo ())
43
+ RawTok.setIdentifierInfo (PP.LookUpIdentifierInfo (RawTok));
44
+ }
45
+
25
46
// / RewriteMacrosInInput - Implement -rewrite-macros mode.
26
47
void clang::RewriteMacrosInInput (Preprocessor &PP,const std::string &InFileName,
27
48
const std::string &OutFileName) {
28
49
SourceManager &SM = PP.getSourceManager ();
29
50
30
51
Rewriter Rewrite;
31
52
Rewrite.setSourceMgr (SM);
53
+ RewriteBuffer &RB = Rewrite.getEditBuffer (SM.getMainFileID ());
32
54
33
- // Get the ID and start/end of the main file.
34
- unsigned MainFileID = SM.getMainFileID ();
35
- // const llvm::MemoryBuffer *MainBuf = SM.getBuffer(MainFileID);
36
- // const char *MainFileStart = MainBuf->getBufferStart();
37
- // const char *MainFileEnd = MainBuf->getBufferEnd();
38
-
55
+ const SourceManager &SourceMgr = PP.getSourceManager ();
56
+ std::pair<const char *, const char *> File =
57
+ SourceMgr.getBufferData (SM.getMainFileID ());
39
58
40
- // Create the output file.
59
+ // Create a lexer to lex all the tokens of the main file in raw mode. Even
60
+ // though it is in raw mode, it will not return comments.
61
+ Lexer RawLex (SourceLocation::getFileLoc (SM.getMainFileID (), 0 ),
62
+ PP.getLangOptions (), File.first , File.second );
63
+ Token RawTok;
64
+ GetNextRawTok (RawLex, RawTok, PP);
65
+
66
+ // Get the first preprocessing token.
67
+ PP.EnterMainSourceFile ();
68
+ Token PPTok;
69
+ PP.Lex (PPTok);
41
70
71
+ // Preprocess the input file in parallel with raw lexing the main file. Ignore
72
+ // all tokens that are preprocessed from a file other than the main file (e.g.
73
+ // a header). If we see tokens that are in the preprocessed file bug not the
74
+ // lexed file, we have a macro expansion. If we see tokens in the lexed file
75
+ // that aren't in the preprocessed view, we have macros that expand to no
76
+ // tokens, or macro arguments etc.
77
+ while (RawTok.isNot (tok::eof) || PPTok.isNot (tok::eof)) {
78
+ SourceLocation PPLoc = SM.getLogicalLoc (PPTok.getLocation ());
79
+
80
+ // If PPTok is from a different source file, ignore it.
81
+ if (!SM.isFromMainFile (PPLoc)) {
82
+ PP.Lex (PPTok);
83
+ continue ;
84
+ }
85
+
86
+ // If the raw file hits a preprocessor directive, they will be extra tokens
87
+ // in the input file, but we don't want to treat them as such... just ignore
88
+ // them.
89
+ if (RawTok.is (tok::hash) && RawTok.isAtStartOfLine ()) {
90
+ GetNextRawTok (RawLex, RawTok, PP);
91
+ while (!RawTok.isAtStartOfLine () && RawTok.isNot (tok::eof))
92
+ GetNextRawTok (RawLex, RawTok, PP);
93
+ continue ;
94
+ }
95
+
96
+ // Okay, both tokens are from the same file. Get their offsets from the
97
+ // start of the file.
98
+ unsigned PPOffs = SM.getFullFilePos (PPLoc);
99
+ unsigned RawOffs = SM.getFullFilePos (RawTok.getLocation ());
100
+
101
+ // If the offsets are the same and the token kind is the same, ignore them.
102
+ if (PPOffs == RawOffs && isSameToken (RawTok, PPTok)) {
103
+ GetNextRawTok (RawLex, RawTok, PP);
104
+ PP.Lex (PPTok);
105
+ continue ;
106
+ }
107
+
108
+ // If the PP token is farther along than the raw token, something was
109
+ // deleted. Comment out the raw token.
110
+ if (RawOffs <= PPOffs) {
111
+ // Comment out a whole run of tokens instead of bracketing each one with
112
+ // comments.
113
+ RB.InsertTextAfter (RawOffs, " /*" , 2 );
114
+ unsigned EndPos;
115
+
116
+ // Switch on comment lexing. If we get a comment, we don't want to
117
+ // include it as part of our run of tokens, because we don't want to
118
+ // nest /* */ comments.
119
+ RawLex.SetCommentRetentionState (true );
120
+
121
+ do {
122
+ EndPos = RawOffs+RawTok.getLength ();
123
+
124
+ GetNextRawTok (RawLex, RawTok, PP);
125
+ RawOffs = SM.getFullFilePos (RawTok.getLocation ());
126
+
127
+ if (RawTok.is (tok::comment)) {
128
+ RawLex.SetCommentRetentionState (false );
129
+ // Skip past the comment.
130
+ GetNextRawTok (RawLex, RawTok, PP);
131
+ break ;
132
+ }
133
+
134
+ } while (RawOffs <= PPOffs && !RawTok.isAtStartOfLine () &&
135
+ (PPOffs != RawOffs || !isSameToken (RawTok, PPTok)));
136
+
137
+ RawLex.SetCommentRetentionState (false );
138
+
139
+ RB.InsertTextBefore (EndPos, " */" , 2 );
140
+ continue ;
141
+ }
142
+
143
+ // Otherwise, there was a replacement an expansion. Insert the new token
144
+ // in the output buffer. Insert the whole run of new tokens at once to get
145
+ // them in the right order.
146
+ unsigned InsertPos = PPOffs;
147
+ std::string Expansion;
148
+ while (PPOffs < RawOffs) {
149
+ Expansion += ' ' + PP.getSpelling (PPTok);
150
+ PP.Lex (PPTok);
151
+ PPLoc = SM.getLogicalLoc (PPTok.getLocation ());
152
+ PPOffs = SM.getFullFilePos (PPLoc);
153
+ }
154
+ Expansion += ' ' ;
155
+ RB.InsertTextBefore (InsertPos, &Expansion[0 ], Expansion.size ());
156
+ }
157
+
158
+ // Create the output file.
42
159
std::ostream *OutFile;
43
160
if (OutFileName == " -" ) {
44
161
OutFile = llvm::cout.stream ();
@@ -58,7 +175,7 @@ void clang::RewriteMacrosInInput(Preprocessor &PP,const std::string &InFileName,
58
175
// Get the buffer corresponding to MainFileID. If we haven't changed it, then
59
176
// we are done.
60
177
if (const RewriteBuffer *RewriteBuf =
61
- Rewrite.getRewriteBufferFor (MainFileID )) {
178
+ Rewrite.getRewriteBufferFor (SM. getMainFileID () )) {
62
179
// printf("Changed:\n");
63
180
*OutFile << std::string (RewriteBuf->begin (), RewriteBuf->end ());
64
181
} else {
0 commit comments