From 31ebf58ad4591fda8ec90de3a3eb31ba8cc60f03 Mon Sep 17 00:00:00 2001 From: "Matt McCutchen (Correct Computation)" Date: Thu, 5 Aug 2021 17:07:25 -0400 Subject: [PATCH 1/2] Don't print the main file to stdout multiple times in different translation units. --- clang/include/clang/3C/ProgramInfo.h | 6 ++++++ clang/lib/3C/RewriteUtils.cpp | 20 +++++++++++++------- clang/test/3C/multiple_tu.c | 12 ++++++++++++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/3C/ProgramInfo.h b/clang/include/clang/3C/ProgramInfo.h index 7b240ff2cbe8..b508f8f149d1 100644 --- a/clang/include/clang/3C/ProgramInfo.h +++ b/clang/include/clang/3C/ProgramInfo.h @@ -146,6 +146,12 @@ class ProgramInfo : public ProgramVariableAdder { void registerTranslationUnits( const std::vector> &ASTs); + // Hack to allow `emit` in RewriteUtils.cpp to avoid printing the main file to + // stdout multiple times in the edge case of a compilation database containing + // multiple translation units for the main file + // (https://github.com/correctcomputation/checkedc-clang/issues/374#issuecomment-893612654). + bool StdoutModeEmittedMainFile = false; + private: // List of constraint variables for declarations, indexed by their location in // the source. This information persists across invocations of the constraint diff --git a/clang/lib/3C/RewriteUtils.cpp b/clang/lib/3C/RewriteUtils.cpp index b9eb8169b8e2..ecc478ccf21d 100644 --- a/clang/lib/3C/RewriteUtils.cpp +++ b/clang/lib/3C/RewriteUtils.cpp @@ -120,12 +120,11 @@ void rewriteSourceRange(Rewriter &R, const CharSourceRange &Range, } } -static void emit(Rewriter &R, ASTContext &C) { +static void emit(Rewriter &R, ASTContext &C, bool &StdoutModeEmittedMainFile) { if (Verbose) errs() << "Writing files out\n"; bool StdoutMode = (OutputPostfix == "-" && OutputDir.empty()); - bool StdoutModeSawMainFile = false; SourceManager &SM = C.getSourceManager(); // Iterate over each modified rewrite buffer. for (auto Buffer = R.buffer_begin(); Buffer != R.buffer_end(); ++Buffer) { @@ -226,9 +225,15 @@ static void emit(Rewriter &R, ASTContext &C) { if (StdoutMode) { if (Buffer->first == SM.getMainFileID()) { - // This is the new version of the main file. Print it to stdout. - Buffer->second.write(outs()); - StdoutModeSawMainFile = true; + // This is the new version of the main file. Print it to stdout, + // except in the edge case where we have a compilation database with + // multiple translation units with the same main file and we already + // emitted a copy of the main file for a previous translation unit + // (https://github.com/correctcomputation/checkedc-clang/issues/374#issuecomment-893612654). + if (!StdoutModeEmittedMainFile) { + Buffer->second.write(outs()); + StdoutModeEmittedMainFile = true; + } } else { unsigned ID = DE.getCustomDiagID( UnwritableChangeDiagnosticLevel, @@ -300,9 +305,10 @@ static void emit(Rewriter &R, ASTContext &C) { } } - if (StdoutMode && !StdoutModeSawMainFile) { + if (StdoutMode && !StdoutModeEmittedMainFile) { // The main file is unchanged. Write out its original content. outs() << SM.getBufferOrFake(SM.getMainFileID()).getBuffer(); + StdoutModeEmittedMainFile = true; } } @@ -632,7 +638,7 @@ void RewriteConsumer::HandleTranslationUnit(ASTContext &Context) { } // Output files. - emit(R, Context); + emit(R, Context, Info.StdoutModeEmittedMainFile); Info.getPerfStats().endRewritingTime(); diff --git a/clang/test/3C/multiple_tu.c b/clang/test/3C/multiple_tu.c index d7fc64f5145c..f56cb54e6945 100644 --- a/clang/test/3C/multiple_tu.c +++ b/clang/test/3C/multiple_tu.c @@ -13,10 +13,22 @@ // present in the root cause statistics json output. The json is used to // generate the output for 3c-wrap root_cause, so the error appeared there as well. +// Furthermore, in stdout mode, if the main file was processed twice, the +// rewritten version was printed to stdout twice +// (https://github.com/correctcomputation/checkedc-clang/issues/374#issuecomment-893612654). +// Check that this doesn't happen any more. + _Itype_for_any(T) void my_free(void *pointer : itype(_Array_ptr) byte_count(0)); void foo() { + //CHECK: {{^}}void foo() { int *a; my_free(a); //CHECK: my_free(a); } + +// Make sure the file does not get printed to stdout a second time. Since +// -match-full-lines does not apply to CHECK-NOT, the {{^}} is needed to anchor +// the match to the beginning of the line and prevent the CHECK-NOT from +// matching itself. +//CHECK-NOT: {{^}}void foo() { From 42201149f8661bc9d1028b712a5e1844d671e18f Mon Sep 17 00:00:00 2001 From: "Matt McCutchen (Correct Computation)" Date: Mon, 9 Aug 2021 16:00:21 -0400 Subject: [PATCH 2/2] Move StdoutModeEmittedMainFile flag from ProgramInfo to RewriteConsumer as suggested by John. --- clang/include/clang/3C/ProgramInfo.h | 6 ------ clang/include/clang/3C/RewriteUtils.h | 6 ++++++ clang/lib/3C/RewriteUtils.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/3C/ProgramInfo.h b/clang/include/clang/3C/ProgramInfo.h index b508f8f149d1..7b240ff2cbe8 100644 --- a/clang/include/clang/3C/ProgramInfo.h +++ b/clang/include/clang/3C/ProgramInfo.h @@ -146,12 +146,6 @@ class ProgramInfo : public ProgramVariableAdder { void registerTranslationUnits( const std::vector> &ASTs); - // Hack to allow `emit` in RewriteUtils.cpp to avoid printing the main file to - // stdout multiple times in the edge case of a compilation database containing - // multiple translation units for the main file - // (https://github.com/correctcomputation/checkedc-clang/issues/374#issuecomment-893612654). - bool StdoutModeEmittedMainFile = false; - private: // List of constraint variables for declarations, indexed by their location in // the source. This information persists across invocations of the constraint diff --git a/clang/include/clang/3C/RewriteUtils.h b/clang/include/clang/3C/RewriteUtils.h index 5fd4dc8de7c6..0f312418bf5e 100644 --- a/clang/include/clang/3C/RewriteUtils.h +++ b/clang/include/clang/3C/RewriteUtils.h @@ -159,6 +159,12 @@ class RewriteConsumer : public ASTConsumer { static std::set EmittedDiagnostics; void emitRootCauseDiagnostics(ASTContext &Context); + + // Hack to avoid printing the main file to stdout multiple times in the edge + // case of a compilation database containing multiple translation units for + // the main file + // (https://github.com/correctcomputation/checkedc-clang/issues/374#issuecomment-893612654). + bool StdoutModeEmittedMainFile = false; }; bool canRewrite(Rewriter &R, const SourceRange &SR); diff --git a/clang/lib/3C/RewriteUtils.cpp b/clang/lib/3C/RewriteUtils.cpp index ecc478ccf21d..31656e9c80da 100644 --- a/clang/lib/3C/RewriteUtils.cpp +++ b/clang/lib/3C/RewriteUtils.cpp @@ -638,7 +638,7 @@ void RewriteConsumer::HandleTranslationUnit(ASTContext &Context) { } // Output files. - emit(R, Context, Info.StdoutModeEmittedMainFile); + emit(R, Context, StdoutModeEmittedMainFile); Info.getPerfStats().endRewritingTime();