Skip to content

Commit 8dcca58

Browse files
authored
Merge pull request #65263 from rintaro/nullterminatedstringref-rdar108215490
[Basic] Ensure empty NullTerminatedStringRef have valid pointer
2 parents f1b8d9d + a0eb32e commit 8dcca58

File tree

3 files changed

+103
-83
lines changed

3 files changed

+103
-83
lines changed

include/swift/Basic/Lazy.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,41 @@
1414
#define SWIFT_BASIC_LAZY_H
1515

1616
#include <memory>
17+
#include <functional>
1718

1819
#include "swift/Basic/Malloc.h"
1920
#include "swift/Basic/type_traits.h"
2021
#include "swift/Threading/Once.h"
2122

2223
namespace swift {
2324

25+
/// A template for lazy-initialized values.
26+
/// Usage:
27+
///
28+
/// LazyValue<std::string> value([]() { return createString(); })
29+
/// if (condition) {
30+
/// // 'createString()' is evaluated only when 'value` is dereferenced.
31+
/// doSomething(*value);
32+
/// }
33+
template <typename T, typename Initializer = std::function<T()>>
34+
class LazyValue {
35+
Initializer Init;
36+
llvm::Optional<T> Value;
37+
38+
public:
39+
LazyValue(Initializer Init) : Init(Init){};
40+
41+
T &get() {
42+
if (!Value.hasValue()) {
43+
Value = Init();
44+
}
45+
return Value.value();
46+
}
47+
48+
T *operator->() { return &get(); }
49+
T &operator*() { return get(); }
50+
};
51+
2452
/// A template for lazily-constructed, zero-initialized, leaked-on-exit
2553
/// global objects.
2654
template <class T> class Lazy {

include/swift/Basic/StringExtras.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ class NullTerminatedStringRef {
490490

491491
/// Create a null-terminated string, copying \p Str into \p A .
492492
template <typename Allocator>
493-
NullTerminatedStringRef(StringRef Str, Allocator &A) : Ref() {
493+
NullTerminatedStringRef(StringRef Str, Allocator &A) : Ref("") {
494494
if (Str.empty())
495495
return;
496496

lib/Sema/TypeCheckMacros.cpp

Lines changed: 74 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/AST/SourceFile.h"
3131
#include "swift/AST/TypeCheckRequests.h"
3232
#include "swift/Basic/Defer.h"
33+
#include "swift/Basic/Lazy.h"
3334
#include "swift/Basic/SourceManager.h"
3435
#include "swift/Basic/StringExtras.h"
3536
#include "swift/Demangling/Demangler.h"
@@ -441,6 +442,9 @@ ExternalMacroDefinitionRequest::evaluate(Evaluator &evaluator, ASTContext *ctx,
441442
/// Adjust the given mangled name for a macro expansion to produce a valid
442443
/// buffer name.
443444
static std::string adjustMacroExpansionBufferName(StringRef name) {
445+
if (name.empty()) {
446+
return "<macro-expansion>";
447+
}
444448
std::string result;
445449
if (name.startswith(MANGLING_PREFIX_STR)) {
446450
result += MACRO_EXPANSION_BUFFER_MANGLING_PREFIX;
@@ -676,31 +680,26 @@ Expr *swift::expandMacroExpr(
676680
if (!sourceFile)
677681
return nullptr;
678682

679-
// Evaluate the macro.
680-
NullTerminatedStringRef evaluatedSource;
681-
682683
MacroDecl *macro = cast<MacroDecl>(macroRef.getDecl());
683684

684685
if (isFromExpansionOfMacro(sourceFile, macro, MacroRole::Expression)) {
685686
ctx.Diags.diagnose(expr->getLoc(), diag::macro_recursive, macro->getName());
686687
return nullptr;
687688
}
688689

689-
/// The discriminator used for the macro.
690-
std::string cachedDiscriminator;
691-
auto getDiscriminator = [&]() -> StringRef {
692-
if (!cachedDiscriminator.empty())
693-
return cachedDiscriminator;
690+
// Evaluate the macro.
691+
std::unique_ptr<llvm::MemoryBuffer> evaluatedSource;
694692

693+
/// The discriminator used for the macro.
694+
LazyValue<std::string> discriminator([&]() -> std::string {
695695
#if SWIFT_SWIFT_PARSER
696696
if (auto expansionExpr = dyn_cast<MacroExpansionExpr>(expr)) {
697697
Mangle::ASTMangler mangler;
698-
cachedDiscriminator = mangler.mangleMacroExpansion(expansionExpr);
698+
return mangler.mangleMacroExpansion(expansionExpr);
699699
}
700700
#endif
701-
702-
return cachedDiscriminator;
703-
};
701+
return "";
702+
});
704703

705704
auto macroDef = macro->getDefinition();
706705
switch (macroDef.kind) {
@@ -722,8 +721,8 @@ Expr *swift::expandMacroExpr(
722721
// Expand the definition with the given arguments.
723722
auto result = expandMacroDefinition(
724723
macroDef.getExpanded(), macro, expr->getArgs());
725-
llvm::MallocAllocator allocator;
726-
evaluatedSource = NullTerminatedStringRef(result, allocator);
724+
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
725+
result, adjustMacroExpansionBufferName(*discriminator));
727726
break;
728727
}
729728

@@ -757,14 +756,16 @@ Expr *swift::expandMacroExpr(
757756
ptrdiff_t evaluatedSourceLength;
758757
swift_ASTGen_expandFreestandingMacro(
759758
&ctx.Diags, externalDef->opaqueHandle,
760-
static_cast<uint32_t>(externalDef->kind), getDiscriminator().data(),
761-
getDiscriminator().size(), astGenSourceFile,
759+
static_cast<uint32_t>(externalDef->kind), discriminator->data(),
760+
discriminator->size(), astGenSourceFile,
762761
expr->getStartLoc().getOpaquePointerValue(), &evaluatedSourceAddress,
763762
&evaluatedSourceLength);
764763
if (!evaluatedSourceAddress)
765764
return nullptr;
766-
evaluatedSource = NullTerminatedStringRef(evaluatedSourceAddress,
767-
(size_t)evaluatedSourceLength);
765+
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
766+
{evaluatedSourceAddress, (size_t)evaluatedSourceLength},
767+
adjustMacroExpansionBufferName(*discriminator));
768+
free((void *)evaluatedSourceAddress);
768769
break;
769770
#else
770771
ctx.Diags.diagnose(expr->getLoc(), diag::macro_unsupported);
@@ -773,26 +774,18 @@ Expr *swift::expandMacroExpr(
773774
}
774775
}
775776

776-
// Figure out a reasonable name for the macro expansion buffer.
777-
std::string bufferName;
778-
if (getDiscriminator().empty())
779-
bufferName = "macro-expansion";
780-
else {
781-
bufferName = adjustMacroExpansionBufferName(getDiscriminator());
782-
}
783-
784777
// Dump macro expansions to standard output, if requested.
785778
if (ctx.LangOpts.DumpMacroExpansions) {
786-
llvm::errs() << bufferName << " as " << expandedType.getString()
779+
llvm::errs() << evaluatedSource->getBufferIdentifier() << " as "
780+
<< expandedType.getString()
787781
<< "\n------------------------------\n"
788-
<< evaluatedSource
782+
<< evaluatedSource->getBuffer()
789783
<< "\n------------------------------\n";
790784
}
791785

792786
// Create a new source buffer with the contents of the expanded macro.
793-
auto macroBuffer =
794-
llvm::MemoryBuffer::getMemBufferCopy(evaluatedSource, bufferName);
795-
unsigned macroBufferID = sourceMgr.addNewSourceBuffer(std::move(macroBuffer));
787+
unsigned macroBufferID =
788+
sourceMgr.addNewSourceBuffer(std::move(evaluatedSource));
796789
auto macroBufferRange = sourceMgr.getRangeForBuffer(macroBufferID);
797790
GeneratedSourceInfo sourceInfo{
798791
GeneratedSourceInfo::ExpressionMacroExpansion,
@@ -803,7 +796,6 @@ Expr *swift::expandMacroExpr(
803796
dc
804797
};
805798
sourceMgr.setGeneratedSourceInfo(macroBufferID, sourceInfo);
806-
free((void*)evaluatedSource.data());
807799

808800
// Create a source file to hold the macro buffer. This is automatically
809801
// registered with the enclosing module.
@@ -865,9 +857,6 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
865857
if (!sourceFile)
866858
return None;
867859

868-
// Evaluate the macro.
869-
NullTerminatedStringRef evaluatedSource;
870-
871860
MacroDecl *macro = cast<MacroDecl>(med->getMacroRef().getDecl());
872861
auto macroRoles = macro->getMacroRoles();
873862
assert(macroRoles.contains(MacroRole::Declaration) ||
@@ -880,6 +869,19 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
880869
return None;
881870
}
882871

872+
// Evaluate the macro.
873+
std::unique_ptr<llvm::MemoryBuffer> evaluatedSource;
874+
875+
/// The discriminator used for the macro.
876+
LazyValue<std::string> discriminator([&]() -> std::string {
877+
#if SWIFT_SWIFT_PARSER
878+
Mangle::ASTMangler mangler;
879+
return mangler.mangleMacroExpansion(med);
880+
#else
881+
return "";
882+
#endif
883+
});
884+
883885
auto macroDef = macro->getDefinition();
884886
switch (macroDef.kind) {
885887
case MacroDefinition::Kind::Undefined:
@@ -899,8 +901,8 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
899901
// Expand the definition with the given arguments.
900902
auto result = expandMacroDefinition(
901903
macroDef.getExpanded(), macro, med->getArgs());
902-
llvm::MallocAllocator allocator;
903-
evaluatedSource = NullTerminatedStringRef(result, allocator);
904+
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
905+
result, adjustMacroExpansionBufferName(*discriminator));
904906
break;
905907
}
906908

@@ -945,21 +947,20 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
945947
if (!astGenSourceFile)
946948
return None;
947949

948-
Mangle::ASTMangler mangler;
949-
auto discriminator = mangler.mangleMacroExpansion(med);
950-
951950
const char *evaluatedSourceAddress;
952951
ptrdiff_t evaluatedSourceLength;
953952
swift_ASTGen_expandFreestandingMacro(
954953
&ctx.Diags, externalDef->opaqueHandle,
955-
static_cast<uint32_t>(externalDef->kind), discriminator.data(),
956-
discriminator.size(), astGenSourceFile,
954+
static_cast<uint32_t>(externalDef->kind), discriminator->data(),
955+
discriminator->size(), astGenSourceFile,
957956
med->getStartLoc().getOpaquePointerValue(), &evaluatedSourceAddress,
958957
&evaluatedSourceLength);
959958
if (!evaluatedSourceAddress)
960959
return None;
961-
evaluatedSource = NullTerminatedStringRef(evaluatedSourceAddress,
962-
(size_t)evaluatedSourceLength);
960+
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
961+
{evaluatedSourceAddress, (size_t)evaluatedSourceLength},
962+
adjustMacroExpansionBufferName(*discriminator));
963+
free((void *)evaluatedSourceAddress);
963964
break;
964965
#else
965966
med->diagnose(diag::macro_unsupported);
@@ -968,26 +969,17 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
968969
}
969970
}
970971

971-
// Figure out a reasonable name for the macro expansion buffer.
972-
std::string bufferName;
973-
{
974-
Mangle::ASTMangler mangler;
975-
bufferName = adjustMacroExpansionBufferName(
976-
mangler.mangleMacroExpansion(med));
977-
}
978-
979972
// Dump macro expansions to standard output, if requested.
980973
if (ctx.LangOpts.DumpMacroExpansions) {
981-
llvm::errs() << bufferName
974+
llvm::errs() << evaluatedSource->getBufferIdentifier()
982975
<< "\n------------------------------\n"
983-
<< evaluatedSource
976+
<< evaluatedSource->getBuffer()
984977
<< "\n------------------------------\n";
985978
}
986979

987980
// Create a new source buffer with the contents of the expanded macro.
988-
auto macroBuffer =
989-
llvm::MemoryBuffer::getMemBufferCopy(evaluatedSource, bufferName);
990-
unsigned macroBufferID = sourceMgr.addNewSourceBuffer(std::move(macroBuffer));
981+
unsigned macroBufferID =
982+
sourceMgr.addNewSourceBuffer(std::move(evaluatedSource));
991983
auto macroBufferRange = sourceMgr.getRangeForBuffer(macroBufferID);
992984
GeneratedSourceInfo sourceInfo{
993985
GeneratedSourceInfo::FreestandingDeclMacroExpansion,
@@ -998,7 +990,6 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
998990
dc
999991
};
1000992
sourceMgr.setGeneratedSourceInfo(macroBufferID, sourceInfo);
1001-
free((void*)evaluatedSource.data());
1002993

1003994
// Create a source file to hold the macro buffer. This is automatically
1004995
// registered with the enclosing module.
@@ -1092,9 +1083,18 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
10921083
}
10931084

10941085
// Evaluate the macro.
1095-
NullTerminatedStringRef evaluatedSource;
1086+
std::unique_ptr<llvm::MemoryBuffer> evaluatedSource;
1087+
1088+
/// The discriminator used for the macro.
1089+
LazyValue<std::string> discriminator([&]() -> std::string {
1090+
#if SWIFT_SWIFT_PARSER
1091+
Mangle::ASTMangler mangler;
1092+
return mangler.mangleAttachedMacroExpansion(attachedTo, attr, role);
1093+
#else
1094+
return "";
1095+
#endif
1096+
});
10961097

1097-
std::string discriminator;
10981098
auto macroDef = macro->getDefinition();
10991099
switch (macroDef.kind) {
11001100
case MacroDefinition::Kind::Undefined:
@@ -1115,7 +1115,8 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
11151115
auto result = expandMacroDefinition(
11161116
macroDef.getExpanded(), macro, attr->getArgs());
11171117
llvm::MallocAllocator allocator;
1118-
evaluatedSource = NullTerminatedStringRef(result, allocator);
1118+
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
1119+
result, adjustMacroExpansionBufferName(*discriminator));
11191120
break;
11201121
}
11211122

@@ -1161,26 +1162,22 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
11611162
if (auto var = dyn_cast<VarDecl>(attachedTo))
11621163
searchDecl = var->getParentPatternBinding();
11631164

1164-
{
1165-
Mangle::ASTMangler mangler;
1166-
discriminator =
1167-
mangler.mangleAttachedMacroExpansion(attachedTo, attr, role);
1168-
}
1169-
11701165
const char *evaluatedSourceAddress;
11711166
ptrdiff_t evaluatedSourceLength;
11721167
swift_ASTGen_expandAttachedMacro(
11731168
&ctx.Diags, externalDef->opaqueHandle,
1174-
static_cast<uint32_t>(externalDef->kind), discriminator.data(),
1175-
discriminator.size(), static_cast<uint32_t>(role), astGenAttrSourceFile,
1176-
attr->AtLoc.getOpaquePointerValue(), astGenDeclSourceFile,
1177-
searchDecl->getStartLoc().getOpaquePointerValue(),
1169+
static_cast<uint32_t>(externalDef->kind), discriminator->data(),
1170+
discriminator->size(), static_cast<uint32_t>(role),
1171+
astGenAttrSourceFile, attr->AtLoc.getOpaquePointerValue(),
1172+
astGenDeclSourceFile, searchDecl->getStartLoc().getOpaquePointerValue(),
11781173
astGenParentDeclSourceFile, parentDeclLoc, &evaluatedSourceAddress,
11791174
&evaluatedSourceLength);
11801175
if (!evaluatedSourceAddress)
11811176
return nullptr;
1182-
evaluatedSource = NullTerminatedStringRef(evaluatedSourceAddress,
1183-
(size_t)evaluatedSourceLength);
1177+
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
1178+
{evaluatedSourceAddress, (size_t)evaluatedSourceLength},
1179+
adjustMacroExpansionBufferName(*discriminator));
1180+
free((void *)evaluatedSourceAddress);
11841181
break;
11851182
#else
11861183
attachedTo->diagnose(diag::macro_unsupported);
@@ -1189,14 +1186,11 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
11891186
}
11901187
}
11911188

1192-
// Figure out a reasonable name for the macro expansion buffer.
1193-
std::string bufferName = adjustMacroExpansionBufferName(discriminator);
1194-
11951189
// Dump macro expansions to standard output, if requested.
11961190
if (ctx.LangOpts.DumpMacroExpansions) {
1197-
llvm::errs() << bufferName
1191+
llvm::errs() << evaluatedSource->getBufferIdentifier()
11981192
<< "\n------------------------------\n"
1199-
<< evaluatedSource
1193+
<< evaluatedSource->getBuffer()
12001194
<< "\n------------------------------\n";
12011195
}
12021196

@@ -1284,9 +1278,8 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
12841278
}
12851279

12861280
// Create a new source buffer with the contents of the expanded macro.
1287-
auto macroBuffer =
1288-
llvm::MemoryBuffer::getMemBufferCopy(evaluatedSource, bufferName);
1289-
unsigned macroBufferID = sourceMgr.addNewSourceBuffer(std::move(macroBuffer));
1281+
unsigned macroBufferID =
1282+
sourceMgr.addNewSourceBuffer(std::move(evaluatedSource));
12901283
auto macroBufferRange = sourceMgr.getRangeForBuffer(macroBufferID);
12911284
GeneratedSourceInfo sourceInfo{
12921285
generatedSourceKind,
@@ -1297,7 +1290,6 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
12971290
attr
12981291
};
12991292
sourceMgr.setGeneratedSourceInfo(macroBufferID, sourceInfo);
1300-
free((void*)evaluatedSource.data());
13011293

13021294
// Create a source file to hold the macro buffer. This is automatically
13031295
// registered with the enclosing module.

0 commit comments

Comments
 (0)