Skip to content

Commit 0b7e8c2

Browse files
authoredOct 24, 2024··
[C++20][Modules] Quote header unit name in preprocessor output (-E) (#112883)
Summary: Before this change clang produced output with header unit names that may conaint path separators, dots and other non-identifier characters. This diff prints header unit name in quotes and -E output can be compiled again. Also remove unnecessary space between header unit name and semi. Test Plan: check-clang
1 parent 6094417 commit 0b7e8c2

File tree

4 files changed

+32
-6
lines changed

4 files changed

+32
-6
lines changed
 

‎clang/lib/Frontend/PrintPreprocessedOutput.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -952,13 +952,15 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
952952
continue;
953953
} else if (Tok.is(tok::annot_header_unit)) {
954954
// This is a header-name that has been (effectively) converted into a
955-
// module-name.
955+
// module-name, print them inside quote.
956956
// FIXME: The module name could contain non-identifier module name
957-
// components. We don't have a good way to round-trip those.
957+
// components and OS specific file paths components. We don't have a good
958+
// way to round-trip those.
958959
Module *M = reinterpret_cast<Module *>(Tok.getAnnotationValue());
959960
std::string Name = M->getFullModuleName();
960-
Callbacks->OS->write(Name.data(), Name.size());
961-
Callbacks->HandleNewlinesInToken(Name.data(), Name.size());
961+
*Callbacks->OS << '"';
962+
Callbacks->OS->write_escaped(Name);
963+
*Callbacks->OS << '"';
962964
} else if (Tok.is(tok::annot_embed)) {
963965
// Manually explode the binary data out to a stream of comma-delimited
964966
// integer values. If the user passed -dE, that is handled by the

‎clang/lib/Lex/TokenConcatenation.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ static char GetFirstChar(const Preprocessor &PP, const Token &Tok) {
160160
bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok,
161161
const Token &PrevTok,
162162
const Token &Tok) const {
163+
// No space is required between header unit name in quote and semi.
164+
if (PrevTok.is(tok::annot_header_unit) && Tok.is(tok::semi))
165+
return false;
166+
163167
// Conservatively assume that every annotation token that has a printable
164168
// form requires whitespace.
165169
if (PrevTok.isAnnotation())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: rm -fR %t
2+
// RUN: split-file %s %t
3+
// RUN: cd %t
4+
// RUN: %clang_cc1 -verify -std=c++20 -emit-header-unit -xc++-user-header bz0.h
5+
// RUN: %clang_cc1 -verify -std=c++20 -fmodule-file=bz0.pcm -xc++-user-header bz1.h -E -o bz1.output.h
6+
// RUN: FileCheck %s < bz1.output.h
7+
// RUN: %clang_cc1 -std=c++20 -fmodule-file=bz0.pcm -emit-header-unit -xc++-user-header bz1.output.h
8+
9+
//--- bz0.h
10+
// expected-no-diagnostics
11+
#pragma once
12+
13+
void foo();
14+
15+
//--- bz1.h
16+
// expected-no-diagnostics
17+
import "bz0.h";
18+
19+
// CHECK: # 1 ".{{/|\\\\?}}bz1.h"
20+
// CHECK: import ".{{/|\\\\?}}bz0.h";

‎clang/test/Modules/cxx20-include-translation.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,6 @@ export void charlie() {
105105
}
106106

107107
// CHECK: #pragma clang module import ".{{/|\\\\?}}h1.h"
108-
// CHECK: import .{{/|\\\\?}}h2.h
109-
// CHECK: import .{{/|\\\\?}}h3.h
108+
// CHECK: import ".{{/|\\\\?}}h2.h"
109+
// CHECK: import ".{{/|\\\\?}}h3.h"
110110
// CHECK-NOT: #pragma clang module import ".{{/|\\\\?}}h4.h"

0 commit comments

Comments
 (0)
Please sign in to comment.