Skip to content

Commit 0be2e49

Browse files
committed
Support non-identifier module names when preprocessing modules.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@305758 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent de5743d commit 0be2e49

File tree

8 files changed

+119
-60
lines changed

8 files changed

+119
-60
lines changed

include/clang/Basic/Module.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,9 @@ class Module {
393393

394394
/// \brief Retrieve the full name of this module, including the path from
395395
/// its top-level module.
396-
std::string getFullModuleName() const;
396+
/// \param AllowStringLiterals If \c true, components that might not be
397+
/// lexically valid as identifiers will be emitted as string literals.
398+
std::string getFullModuleName(bool AllowStringLiterals = false) const;
397399

398400
/// \brief Whether the full name of this module is equal to joining
399401
/// \p nameParts with "."s.

lib/Basic/Module.cpp

+41-22
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
#include "clang/Basic/Module.h"
16+
#include "clang/Basic/CharInfo.h"
1617
#include "clang/Basic/FileManager.h"
1718
#include "clang/Basic/LangOptions.h"
1819
#include "clang/Basic/TargetInfo.h"
@@ -125,23 +126,48 @@ const Module *Module::getTopLevelModule() const {
125126
return Result;
126127
}
127128

128-
std::string Module::getFullModuleName() const {
129+
static StringRef getModuleNameFromComponent(
130+
const std::pair<std::string, SourceLocation> &IdComponent) {
131+
return IdComponent.first;
132+
}
133+
static StringRef getModuleNameFromComponent(StringRef R) { return R; }
134+
135+
template<typename InputIter>
136+
static void printModuleId(raw_ostream &OS, InputIter Begin, InputIter End,
137+
bool AllowStringLiterals = true) {
138+
for (InputIter It = Begin; It != End; ++It) {
139+
if (It != Begin)
140+
OS << ".";
141+
142+
StringRef Name = getModuleNameFromComponent(*It);
143+
if (!AllowStringLiterals || isValidIdentifier(Name))
144+
OS << Name;
145+
else {
146+
OS << '"';
147+
OS.write_escaped(Name);
148+
OS << '"';
149+
}
150+
}
151+
}
152+
153+
template<typename Container>
154+
static void printModuleId(raw_ostream &OS, const Container &C) {
155+
return printModuleId(OS, C.begin(), C.end());
156+
}
157+
158+
std::string Module::getFullModuleName(bool AllowStringLiterals) const {
129159
SmallVector<StringRef, 2> Names;
130160

131161
// Build up the set of module names (from innermost to outermost).
132162
for (const Module *M = this; M; M = M->Parent)
133163
Names.push_back(M->Name);
134164

135165
std::string Result;
136-
for (SmallVectorImpl<StringRef>::reverse_iterator I = Names.rbegin(),
137-
IEnd = Names.rend();
138-
I != IEnd; ++I) {
139-
if (!Result.empty())
140-
Result += '.';
141-
142-
Result += *I;
143-
}
144-
166+
167+
llvm::raw_string_ostream Out(Result);
168+
printModuleId(Out, Names.rbegin(), Names.rend(), AllowStringLiterals);
169+
Out.flush();
170+
145171
return Result;
146172
}
147173

@@ -240,14 +266,6 @@ Module *Module::findSubmodule(StringRef Name) const {
240266
return SubModules[Pos->getValue()];
241267
}
242268

243-
static void printModuleId(raw_ostream &OS, const ModuleId &Id) {
244-
for (unsigned I = 0, N = Id.size(); I != N; ++I) {
245-
if (I)
246-
OS << ".";
247-
OS << Id[I].first;
248-
}
249-
}
250-
251269
void Module::getExportedModules(SmallVectorImpl<Module *> &Exported) const {
252270
// All non-explicit submodules are exported.
253271
for (std::vector<Module *>::const_iterator I = SubModules.begin(),
@@ -334,7 +352,8 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
334352
OS << "framework ";
335353
if (IsExplicit)
336354
OS << "explicit ";
337-
OS << "module " << Name;
355+
OS << "module ";
356+
printModuleId(OS, &Name, &Name + 1);
338357

339358
if (IsSystem || IsExternC) {
340359
OS.indent(Indent + 2);
@@ -434,7 +453,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
434453
OS.indent(Indent + 2);
435454
OS << "export ";
436455
if (Module *Restriction = Exports[I].getPointer()) {
437-
OS << Restriction->getFullModuleName();
456+
OS << Restriction->getFullModuleName(true);
438457
if (Exports[I].getInt())
439458
OS << ".*";
440459
} else {
@@ -455,7 +474,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
455474
for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) {
456475
OS.indent(Indent + 2);
457476
OS << "use ";
458-
OS << DirectUses[I]->getFullModuleName();
477+
OS << DirectUses[I]->getFullModuleName(true);
459478
OS << "\n";
460479
}
461480

@@ -488,7 +507,7 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
488507
for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) {
489508
OS.indent(Indent + 2);
490509
OS << "conflict ";
491-
OS << Conflicts[I].Other->getFullModuleName();
510+
OS << Conflicts[I].Other->getFullModuleName(true);
492511
OS << ", \"";
493512
OS.write_escaped(Conflicts[I].Message);
494513
OS << "\"\n";

lib/Frontend/CompilerInstance.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "clang/AST/ASTConsumer.h"
1212
#include "clang/AST/ASTContext.h"
1313
#include "clang/AST/Decl.h"
14+
#include "clang/Basic/CharInfo.h"
1415
#include "clang/Basic/Diagnostic.h"
1516
#include "clang/Basic/FileManager.h"
1617
#include "clang/Basic/MemoryBufferCache.h"
@@ -1902,17 +1903,23 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
19021903
void CompilerInstance::loadModuleFromSource(SourceLocation ImportLoc,
19031904
StringRef ModuleName,
19041905
StringRef Source) {
1906+
// Avoid creating filenames with special characters.
1907+
SmallString<128> CleanModuleName(ModuleName);
1908+
for (auto &C : CleanModuleName)
1909+
if (!isAlphanumeric(C))
1910+
C = '_';
1911+
19051912
// FIXME: Using a randomized filename here means that our intermediate .pcm
19061913
// output is nondeterministic (as .pcm files refer to each other by name).
19071914
// Can this affect the output in any way?
19081915
SmallString<128> ModuleFileName;
19091916
if (std::error_code EC = llvm::sys::fs::createTemporaryFile(
1910-
ModuleName, "pcm", ModuleFileName)) {
1917+
CleanModuleName, "pcm", ModuleFileName)) {
19111918
getDiagnostics().Report(ImportLoc, diag::err_fe_unable_to_open_output)
19121919
<< ModuleFileName << EC.message();
19131920
return;
19141921
}
1915-
std::string ModuleMapFileName = (ModuleName + ".map").str();
1922+
std::string ModuleMapFileName = (CleanModuleName + ".map").str();
19161923

19171924
FrontendInputFile Input(
19181925
ModuleMapFileName,

lib/Frontend/PrintPreprocessedOutput.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
349349
case tok::pp_include_next:
350350
startNewLineIfNeeded();
351351
MoveToLine(HashLoc);
352-
OS << "#pragma clang module import " << Imported->getFullModuleName()
352+
OS << "#pragma clang module import " << Imported->getFullModuleName(true)
353353
<< " /* clang -E: implicit import for "
354354
<< "#" << PP.getSpelling(IncludeTok) << " "
355355
<< (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"')
@@ -378,14 +378,14 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
378378
/// Handle entering the scope of a module during a module compilation.
379379
void PrintPPOutputPPCallbacks::BeginModule(const Module *M) {
380380
startNewLineIfNeeded();
381-
OS << "#pragma clang module begin " << M->getFullModuleName();
381+
OS << "#pragma clang module begin " << M->getFullModuleName(true);
382382
setEmittedDirectiveOnThisLine();
383383
}
384384

385385
/// Handle leaving the scope of a module during a module compilation.
386386
void PrintPPOutputPPCallbacks::EndModule(const Module *M) {
387387
startNewLineIfNeeded();
388-
OS << "#pragma clang module end /*" << M->getFullModuleName() << "*/";
388+
OS << "#pragma clang module end /*" << M->getFullModuleName(true) << "*/";
389389
setEmittedDirectiveOnThisLine();
390390
}
391391

lib/Frontend/Rewrite/FrontendActions.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "clang/Rewrite/Frontend/FrontendActions.h"
1111
#include "clang/AST/ASTConsumer.h"
12+
#include "clang/Basic/CharInfo.h"
1213
#include "clang/Frontend/CompilerInstance.h"
1314
#include "clang/Frontend/FrontendActions.h"
1415
#include "clang/Frontend/FrontendDiagnostic.h"
@@ -224,7 +225,15 @@ class RewriteIncludesAction::RewriteImportsListener : public ASTReaderListener {
224225
auto OS = Out.lock();
225226
assert(OS && "loaded module file after finishing rewrite action?");
226227

227-
(*OS) << "#pragma clang module build " << MF->ModuleName << "\n";
228+
(*OS) << "#pragma clang module build ";
229+
if (isValidIdentifier(MF->ModuleName))
230+
(*OS) << MF->ModuleName;
231+
else {
232+
(*OS) << '"';
233+
OS->write_escaped(MF->ModuleName);
234+
(*OS) << '"';
235+
}
236+
(*OS) << '\n';
228237

229238
// Rewrite the contents of the module in a separate compiler instance.
230239
CompilerInstance Instance(CI.getPCHContainerOperations(),

lib/Frontend/Rewrite/InclusionRewriter.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ void InclusionRewriter::WriteLineInfo(StringRef Filename, int Line,
140140
}
141141

142142
void InclusionRewriter::WriteImplicitModuleImport(const Module *Mod) {
143-
OS << "#pragma clang module import " << Mod->getFullModuleName()
143+
OS << "#pragma clang module import " << Mod->getFullModuleName(true)
144144
<< " /* clang -frewrite-includes: implicit import */" << MainEOL;
145145
}
146146

@@ -471,15 +471,15 @@ void InclusionRewriter::Process(FileID FileId,
471471
else if (const IncludedFile *Inc = FindIncludeAtLocation(Loc)) {
472472
const Module *Mod = FindEnteredModule(Loc);
473473
if (Mod)
474-
OS << "#pragma clang module begin " << Mod->getFullModuleName()
475-
<< "\n";
474+
OS << "#pragma clang module begin "
475+
<< Mod->getFullModuleName(true) << "\n";
476476

477477
// Include and recursively process the file.
478478
Process(Inc->Id, Inc->FileType);
479479

480480
if (Mod)
481-
OS << "#pragma clang module end /*" << Mod->getFullModuleName()
482-
<< "*/\n";
481+
OS << "#pragma clang module end /*"
482+
<< Mod->getFullModuleName(true) << "*/\n";
483483

484484
// Add line marker to indicate we're returning from an included
485485
// file.

lib/Lex/Pragma.cpp

+44-26
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "clang/Basic/TokenKinds.h"
2121
#include "clang/Lex/HeaderSearch.h"
2222
#include "clang/Lex/LexDiagnostic.h"
23+
#include "clang/Lex/LiteralSupport.h"
2324
#include "clang/Lex/MacroInfo.h"
2425
#include "clang/Lex/PPCallbacks.h"
2526
#include "clang/Lex/Preprocessor.h"
@@ -754,15 +755,52 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
754755
getHeaderSearchInfo().AddIncludeAlias(OriginalSource, ReplaceFileName);
755756
}
756757

758+
// Lex a component of a module name: either an identifier or a string literal;
759+
// for components that can be expressed both ways, the two forms are equivalent.
760+
static bool LexModuleNameComponent(
761+
Preprocessor &PP, Token &Tok,
762+
std::pair<IdentifierInfo *, SourceLocation> &ModuleNameComponent,
763+
bool First) {
764+
PP.LexUnexpandedToken(Tok);
765+
if (Tok.is(tok::string_literal) && !Tok.hasUDSuffix()) {
766+
StringLiteralParser Literal(Tok, PP);
767+
if (Literal.hadError)
768+
return true;
769+
ModuleNameComponent = std::make_pair(
770+
PP.getIdentifierInfo(Literal.GetString()), Tok.getLocation());
771+
} else if (!Tok.isAnnotation() && Tok.getIdentifierInfo()) {
772+
ModuleNameComponent =
773+
std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation());
774+
} else {
775+
PP.Diag(Tok.getLocation(), diag::err_pp_expected_module_name) << First;
776+
return true;
777+
}
778+
return false;
779+
}
780+
781+
static bool LexModuleName(
782+
Preprocessor &PP, Token &Tok,
783+
llvm::SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>>
784+
&ModuleName) {
785+
while (true) {
786+
std::pair<IdentifierInfo*, SourceLocation> NameComponent;
787+
if (LexModuleNameComponent(PP, Tok, NameComponent, ModuleName.empty()))
788+
return true;
789+
ModuleName.push_back(NameComponent);
790+
791+
PP.LexUnexpandedToken(Tok);
792+
if (Tok.isNot(tok::period))
793+
return false;
794+
}
795+
}
796+
757797
void Preprocessor::HandlePragmaModuleBuild(Token &Tok) {
758798
SourceLocation Loc = Tok.getLocation();
759799

760-
LexUnexpandedToken(Tok);
761-
if (Tok.isAnnotation() || !Tok.getIdentifierInfo()) {
762-
Diag(Tok.getLocation(), diag::err_pp_expected_module_name) << true;
800+
std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc;
801+
if (LexModuleNameComponent(*this, Tok, ModuleNameLoc, true))
763802
return;
764-
}
765-
IdentifierInfo *ModuleName = Tok.getIdentifierInfo();
803+
IdentifierInfo *ModuleName = ModuleNameLoc.first;
766804

767805
LexUnexpandedToken(Tok);
768806
if (Tok.isNot(tok::eod)) {
@@ -1383,26 +1421,6 @@ struct PragmaMessageHandler : public PragmaHandler {
13831421
}
13841422
};
13851423

1386-
static bool LexModuleName(
1387-
Preprocessor &PP, Token &Tok,
1388-
llvm::SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>>
1389-
&ModuleName) {
1390-
while (true) {
1391-
PP.LexUnexpandedToken(Tok);
1392-
if (Tok.isAnnotation() || !Tok.getIdentifierInfo()) {
1393-
PP.Diag(Tok.getLocation(), diag::err_pp_expected_module_name)
1394-
<< ModuleName.empty();
1395-
return true;
1396-
}
1397-
1398-
ModuleName.emplace_back(Tok.getIdentifierInfo(), Tok.getLocation());
1399-
1400-
PP.LexUnexpandedToken(Tok);
1401-
if (Tok.isNot(tok::period))
1402-
return false;
1403-
}
1404-
}
1405-
14061424
/// Handle the clang \#pragma module import extension. The syntax is:
14071425
/// \code
14081426
/// #pragma clang module import some.module.name
@@ -1473,7 +1491,7 @@ struct PragmaModuleBeginHandler : public PragmaHandler {
14731491
// be loaded or implicitly loadable.
14741492
// FIXME: We could create the submodule here. We'd need to know whether
14751493
// it's supposed to be explicit, but not much else.
1476-
Module *M = PP.getHeaderSearchInfo().getModuleMap().findModule(Current);
1494+
Module *M = PP.getHeaderSearchInfo().lookupModule(Current);
14771495
if (!M) {
14781496
PP.Diag(ModuleName.front().second,
14791497
diag::err_pp_module_begin_no_module_map) << Current;

test/Modules/string_names.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
// RUN: rm -rf %t
22
// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -fmodules-decluse -I %S/Inputs/string_names %s -fmodule-name="my/module-a" -verify
33

4+
// Check that we can preprocess with string module names.
5+
// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/string_names %s -fmodule-name="my/module-a" -E -frewrite-imports -o %t/test.ii
6+
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-decluse -I %S/Inputs/string_names %t/test.ii -fmodule-name="my/module-a"
7+
48
#include "a.h"
59
#include "b.h" // expected-error {{does not depend on a module exporting}}
610
#include "c.h"

0 commit comments

Comments
 (0)