Skip to content

Commit 47baa9f

Browse files
authored
Merge pull request #74767 from eeckstein/demangle-type-error-handling
Demangler: handle errors in `demangleType`
2 parents df7df7e + b9cb593 commit 47baa9f

File tree

6 files changed

+67
-24
lines changed

6 files changed

+67
-24
lines changed

include/swift/RemoteInspection/TypeRefBuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,8 @@ class TypeRefBuilder {
638638
auto substitutedDemangleTree = Builder.demangleTypeRef(
639639
substitutedTypeRef,
640640
/* useOpaqueTypeSymbolicReferences */ true);
641+
if (!substitutedDemangleTree)
642+
continue;
641643

642644
// If the substituted type is an opaque type, also gather info
643645
// about which protocols it is required to conform to and the

lib/Demangling/Demangler.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ llvm::StringRef swift::Demangle::dropSwiftManglingPrefix(StringRef mangledName){
224224
}
225225

226226
static bool isAliasNode(Demangle::NodePointer Node) {
227+
if (!Node)
228+
return false;
227229
switch (Node->getKind()) {
228230
case Demangle::Node::Kind::Type:
229231
return isAliasNode(Node->getChild(0));
@@ -241,6 +243,8 @@ bool swift::Demangle::isAlias(llvm::StringRef mangledName) {
241243
}
242244

243245
static bool isClassNode(Demangle::NodePointer Node) {
246+
if (!Node)
247+
return false;
244248
switch (Node->getKind()) {
245249
case Demangle::Node::Kind::Type:
246250
return isClassNode(Node->getChild(0));
@@ -259,6 +263,8 @@ bool swift::Demangle::isClass(llvm::StringRef mangledName) {
259263
}
260264

261265
static bool isEnumNode(Demangle::NodePointer Node) {
266+
if (!Node)
267+
return false;
262268
switch (Node->getKind()) {
263269
case Demangle::Node::Kind::Type:
264270
return isEnumNode(Node->getChild(0));
@@ -277,6 +283,8 @@ bool swift::Demangle::isEnum(llvm::StringRef mangledName) {
277283
}
278284

279285
static bool isProtocolNode(Demangle::NodePointer Node) {
286+
if (!Node)
287+
return false;
280288
switch (Node->getKind()) {
281289
case Demangle::Node::Kind::Type:
282290
return isProtocolNode(Node->getChild(0));
@@ -296,6 +304,8 @@ bool swift::Demangle::isProtocol(llvm::StringRef mangledName) {
296304
}
297305

298306
static bool isStructNode(Demangle::NodePointer Node) {
307+
if (!Node)
308+
return false;
299309
switch (Node->getKind()) {
300310
case Demangle::Node::Kind::Type:
301311
return isStructNode(Node->getChild(0));
@@ -774,12 +784,16 @@ NodePointer Demangler::demangleType(StringRef MangledName,
774784
std::function<SymbolicReferenceResolver_t> Resolver) {
775785
DemangleInitRAII state(*this, MangledName, std::move(Resolver));
776786

777-
parseAndPushNodes();
787+
if (!parseAndPushNodes())
788+
return nullptr;
789+
790+
NodePointer Result = popNode();
778791

779-
if (NodePointer Result = popNode())
780-
return Result;
792+
// The result is only valid if it was the only node on the stack.
793+
if (popNode())
794+
return nullptr;
781795

782-
return createNode(Node::Kind::Suffix, Text);
796+
return Result;
783797
}
784798

785799
bool Demangler::parseAndPushNodes() {

test/Demangle/demangle-types.test

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
RUN: %swift-demangle -type Si | %FileCheck %s --check-prefix=SWIFT-INT
2+
SWIFT-INT: Swift.Int
3+
4+
RUN: %swift-demangle -type SS_ | %FileCheck %s --check-prefix=MULTI-NODE-ERROR
5+
MULTI-NODE-ERROR: <<invalid type>>
6+
7+
RUN: %swift-demangle -type SSIeAghrx_ | %FileCheck %s --check-prefix=PARSE-ERROR
8+
PARSE-ERROR: <<invalid type>>
9+

test/Runtime/demangleToMetadata.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,28 +79,28 @@ DemangleToMetadataTests.test("function types") {
7979
expectEqual(type(of: f0_throws), _typeByName("yyKc")!)
8080

8181
// More parameters.
82-
expectEqual(type(of: f1), _typeByName("yyyt_tc")!)
83-
expectEqual(type(of: f2), _typeByName("yyyt_yttc")!)
82+
expectEqual(type(of: f1), _typeByName("yyt_tc")!)
83+
expectEqual(type(of: f2), _typeByName("yyt_yttc")!)
8484

8585
// Variadic parameters.
86-
expectEqual(type(of: f1_variadic), _typeByName("yyytd_tc")!)
86+
expectEqual(type(of: f1_variadic), _typeByName("yytd_tc")!)
8787

8888
// Inout parameters.
89-
expectEqual(type(of: f1_inout), _typeByName("yyytzc")!)
89+
expectEqual(type(of: f1_inout), _typeByName("yytzc")!)
9090

9191
// Ownership parameters.
92-
expectEqual(type(of: f1_shared), _typeByName("yyyXlhc")!)
93-
expectEqual(type(of: f1_owned), _typeByName("yyyXlnc")!)
92+
expectEqual(type(of: f1_shared), _typeByName("yyXlhc")!)
93+
expectEqual(type(of: f1_owned), _typeByName("yyXlnc")!)
9494

9595
// Concurrent function types.
96-
expectEqual(type(of: f1_takes_concurrent), _typeByName("yyyyYbXEc")!)
96+
expectEqual(type(of: f1_takes_concurrent), _typeByName("yyyYbXEc")!)
9797

9898
// Mix-and-match.
99-
expectEqual(type(of: f2_variadic_inout), _typeByName("yyytd_ytztc")!)
99+
expectEqual(type(of: f2_variadic_inout), _typeByName("yytd_ytztc")!)
100100

101101
// A function type that hasn't been built before.
102102
expectEqual("(Int, Float, Double, String, Character, UInt, Bool) -> ()",
103-
String(describing: _typeByName("yySi_SfSdSSs9CharacterVSuSbtc")!))
103+
String(describing: _typeByName("ySi_SfSdSSs9CharacterVSuSbtc")!))
104104

105105
// Escaping
106106
expectEqual(type(of: f1_escaping), _typeByName("ySfSicc")!)
@@ -145,16 +145,16 @@ func f1_composition_superclass(_: C & P1 & P2) { }
145145

146146
DemangleToMetadataTests.test("existential types") {
147147
// Any, AnyObject
148-
expectEqual(type(of: f2_any_anyobject), _typeByName("yyyp_yXltc")!)
148+
expectEqual(type(of: f2_any_anyobject), _typeByName("yyp_yXltc")!)
149149

150150
// References to protocols.
151-
expectEqual(type(of: f1_composition), _typeByName("yy4main2P1_4main2P2pc")!)
151+
expectEqual(type(of: f1_composition), _typeByName("y4main2P1_4main2P2pc")!)
152152

153153
// Reference to protocol with AnyObject.
154-
expectEqual(type(of: f1_composition_anyobject), _typeByName("yy4main2P1_Xlc")!)
154+
expectEqual(type(of: f1_composition_anyobject), _typeByName("y4main2P1_Xlc")!)
155155

156156
// References to superclass.
157-
expectEqual(type(of: f1_composition_superclass), _typeByName("yy4main2P1_4main2P2AA1CCXcc")!)
157+
expectEqual(type(of: f1_composition_superclass), _typeByName("y4main2P1_4main2P2AA1CCXcc")!)
158158

159159
// Demangle an existential type that hasn't been seen before.
160160
expectEqual("P1 & P2 & P3", String(describing: _typeByName("4main2P1_4main2P24main2P3p")!))

test/Runtime/demangleToMetadataObjC.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ func f1_composition_objc_protocol_P4(_: mainP4) { }
4040

4141
DemangleToMetadataTests.test("@objc protocols") {
4242
expectEqual(type(of: f1_composition_objc_protocol),
43-
_typeByName("yy4main2P1_pc")!)
43+
_typeByName("y4main2P1_pc")!)
4444
expectEqual(type(of: f1_composition_objc_protocol_P4),
45-
_typeByName("yy4main0A2P4_pc")!)
45+
_typeByName("y4main0A2P4_pc")!)
4646
}
4747

4848
DemangleToMetadataTests.test("Objective-C classes") {
@@ -53,13 +53,13 @@ func f1_composition_NSCoding(_: NSCoding) { }
5353
func f1_composition_P5(_: P5) { }
5454

5555
DemangleToMetadataTests.test("Objective-C protocols") {
56-
expectEqual(type(of: f1_composition_NSCoding), _typeByName("yySo8NSCoding_pc")!)
56+
expectEqual(type(of: f1_composition_NSCoding), _typeByName("ySo8NSCoding_pc")!)
5757

5858
// @objc Swift protocols can be found by their Objective-C names...
59-
expectEqual(type(of: f1_composition_P5), _typeByName("yySo15P5RenamedInObjC_pc")!)
59+
expectEqual(type(of: f1_composition_P5), _typeByName("ySo15P5RenamedInObjC_pc")!)
6060

6161
// ... but not their Swift names.
62-
expectNil(_typeByName("yy4main2P5_pc"))
62+
expectNil(_typeByName("y4main2P5_pc"))
6363
}
6464

6565
DemangleToMetadataTests.test("Classes that don't exist") {

tools/swift-demangle/swift-demangle.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ static llvm::cl::opt<bool>
4545
TreeOnly("tree-only",
4646
llvm::cl::desc("Tree-only mode (do not show the demangled string)"));
4747

48+
static llvm::cl::opt<bool>
49+
DemangleType("type",
50+
llvm::cl::desc("Demangle a runtime type string"));
51+
4852
static llvm::cl::opt<bool>
4953
StripSpecialization("strip-specialization",
5054
llvm::cl::desc("Remangle the origin of a specialized function"));
@@ -141,7 +145,17 @@ static void demangle(llvm::raw_ostream &os, llvm::StringRef name,
141145
hadLeadingUnderscore = true;
142146
name = name.substr(1);
143147
}
144-
swift::Demangle::NodePointer pointer = DCtx.demangleSymbolAsNode(name);
148+
swift::Demangle::NodePointer pointer;
149+
if (DemangleType) {
150+
pointer = DCtx.demangleTypeAsNode(name);
151+
if (!pointer) {
152+
os << "<<invalid type>>";
153+
return;
154+
}
155+
} else {
156+
pointer = DCtx.demangleSymbolAsNode(name);
157+
}
158+
145159
if (ExpandMode || TreeOnly) {
146160
os << "Demangling for " << name << '\n';
147161
os << getNodeTreeAsString(pointer);
@@ -399,6 +413,10 @@ int main(int argc, char **argv) {
399413

400414
if (InputNames.empty()) {
401415
CompactMode = true;
416+
if (DemangleType) {
417+
llvm::errs() << "The option -type cannot be used to demangle stdin.\n";
418+
return EXIT_FAILURE;
419+
}
402420
return demangleSTDIN(options);
403421
} else {
404422
swift::Demangle::Context DCtx;
@@ -415,7 +433,7 @@ int main(int argc, char **argv) {
415433
"is quoted or escaped.\n";
416434
continue;
417435
}
418-
if (name.starts_with("S") || name.starts_with("s") ) {
436+
if (!DemangleType && (name.starts_with("S") || name.starts_with("s"))) {
419437
std::string correctedName = std::string("$") + name.str();
420438
demangle(llvm::outs(), correctedName, DCtx, options);
421439
} else {

0 commit comments

Comments
 (0)