Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't print the main file to stdout multiple times in different translation units. #675

Merged
merged 2 commits into from
Aug 9, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang/include/clang/3C/ProgramInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ class ProgramInfo : public ProgramVariableAdder {
void registerTranslationUnits(
const std::vector<std::unique_ptr<clang::ASTUnit>> &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;
mattmccutchen-cci marked this conversation as resolved.
Show resolved Hide resolved

private:
// List of constraint variables for declarations, indexed by their location in
// the source. This information persists across invocations of the constraint
Expand Down
20 changes: 13 additions & 7 deletions clang/lib/3C/RewriteUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -632,7 +638,7 @@ void RewriteConsumer::HandleTranslationUnit(ASTContext &Context) {
}

// Output files.
emit(R, Context);
emit(R, Context, Info.StdoutModeEmittedMainFile);

Info.getPerfStats().endRewritingTime();

Expand Down
12 changes: 12 additions & 0 deletions clang/test/3C/multiple_tu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>) byte_count(0));

void foo() {
//CHECK: {{^}}void foo() {
int *a;
my_free(a);
//CHECK: my_free<int>(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() {