Skip to content

Commit 2f5bf26

Browse files
Don't print the main file to stdout multiple times in different translation units. (#675)
1 parent 4f8511d commit 2f5bf26

File tree

3 files changed

+31
-7
lines changed

3 files changed

+31
-7
lines changed

clang/include/clang/3C/RewriteUtils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ class RewriteConsumer : public ASTConsumer {
159159
static std::set<PersistentSourceLoc> EmittedDiagnostics;
160160

161161
void emitRootCauseDiagnostics(ASTContext &Context);
162+
163+
// Hack to avoid printing the main file to stdout multiple times in the edge
164+
// case of a compilation database containing multiple translation units for
165+
// the main file
166+
// (https://github.com/correctcomputation/checkedc-clang/issues/374#issuecomment-893612654).
167+
bool StdoutModeEmittedMainFile = false;
162168
};
163169

164170
bool canRewrite(Rewriter &R, const SourceRange &SR);

clang/lib/3C/RewriteUtils.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,11 @@ void rewriteSourceRange(Rewriter &R, const CharSourceRange &Range,
120120
}
121121
}
122122

123-
static void emit(Rewriter &R, ASTContext &C) {
123+
static void emit(Rewriter &R, ASTContext &C, bool &StdoutModeEmittedMainFile) {
124124
if (Verbose)
125125
errs() << "Writing files out\n";
126126

127127
bool StdoutMode = (OutputPostfix == "-" && OutputDir.empty());
128-
bool StdoutModeSawMainFile = false;
129128
SourceManager &SM = C.getSourceManager();
130129
// Iterate over each modified rewrite buffer.
131130
for (auto Buffer = R.buffer_begin(); Buffer != R.buffer_end(); ++Buffer) {
@@ -226,9 +225,15 @@ static void emit(Rewriter &R, ASTContext &C) {
226225

227226
if (StdoutMode) {
228227
if (Buffer->first == SM.getMainFileID()) {
229-
// This is the new version of the main file. Print it to stdout.
230-
Buffer->second.write(outs());
231-
StdoutModeSawMainFile = true;
228+
// This is the new version of the main file. Print it to stdout,
229+
// except in the edge case where we have a compilation database with
230+
// multiple translation units with the same main file and we already
231+
// emitted a copy of the main file for a previous translation unit
232+
// (https://github.com/correctcomputation/checkedc-clang/issues/374#issuecomment-893612654).
233+
if (!StdoutModeEmittedMainFile) {
234+
Buffer->second.write(outs());
235+
StdoutModeEmittedMainFile = true;
236+
}
232237
} else {
233238
unsigned ID = DE.getCustomDiagID(
234239
UnwritableChangeDiagnosticLevel,
@@ -300,9 +305,10 @@ static void emit(Rewriter &R, ASTContext &C) {
300305
}
301306
}
302307

303-
if (StdoutMode && !StdoutModeSawMainFile) {
308+
if (StdoutMode && !StdoutModeEmittedMainFile) {
304309
// The main file is unchanged. Write out its original content.
305310
outs() << SM.getBufferOrFake(SM.getMainFileID()).getBuffer();
311+
StdoutModeEmittedMainFile = true;
306312
}
307313
}
308314

@@ -632,7 +638,7 @@ void RewriteConsumer::HandleTranslationUnit(ASTContext &Context) {
632638
}
633639

634640
// Output files.
635-
emit(R, Context);
641+
emit(R, Context, StdoutModeEmittedMainFile);
636642

637643
Info.getPerfStats().endRewritingTime();
638644

clang/test/3C/multiple_tu.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,22 @@
1313
// present in the root cause statistics json output. The json is used to
1414
// generate the output for 3c-wrap root_cause, so the error appeared there as well.
1515

16+
// Furthermore, in stdout mode, if the main file was processed twice, the
17+
// rewritten version was printed to stdout twice
18+
// (https://github.com/correctcomputation/checkedc-clang/issues/374#issuecomment-893612654).
19+
// Check that this doesn't happen any more.
20+
1621
_Itype_for_any(T) void my_free(void *pointer : itype(_Array_ptr<T>) byte_count(0));
1722

1823
void foo() {
24+
//CHECK: {{^}}void foo() {
1925
int *a;
2026
my_free(a);
2127
//CHECK: my_free<int>(a);
2228
}
29+
30+
// Make sure the file does not get printed to stdout a second time. Since
31+
// -match-full-lines does not apply to CHECK-NOT, the {{^}} is needed to anchor
32+
// the match to the beginning of the line and prevent the CHECK-NOT from
33+
// matching itself.
34+
//CHECK-NOT: {{^}}void foo() {

0 commit comments

Comments
 (0)