@@ -53,6 +53,18 @@ static bool consumeFront(std::string_view &S, std::string_view C) {
53
53
return true ;
54
54
}
55
55
56
+ static bool consumeFront (std::string_view &S, std::string_view PrefixA,
57
+ std::string_view PrefixB, bool A) {
58
+ const std::string_view &Prefix = A ? PrefixA : PrefixB;
59
+ return consumeFront (S, Prefix);
60
+ }
61
+
62
+ static bool startsWith (std::string_view S, std::string_view PrefixA,
63
+ std::string_view PrefixB, bool A) {
64
+ const std::string_view &Prefix = A ? PrefixA : PrefixB;
65
+ return llvm::itanium_demangle::starts_with (S, Prefix);
66
+ }
67
+
56
68
static bool isMemberPointer (std::string_view MangledName, bool &Error) {
57
69
Error = false ;
58
70
const char F = MangledName.front ();
@@ -2256,6 +2268,18 @@ Demangler::demangleTemplateParameterList(std::string_view &MangledName) {
2256
2268
2257
2269
NodeList &TP = **Current;
2258
2270
2271
+ // <auto-nttp> ::= $ M <type> <nttp>
2272
+ const bool IsAutoNTTP = consumeFront (MangledName, " $M" );
2273
+ if (IsAutoNTTP) {
2274
+ // The deduced type of the auto NTTP parameter isn't printed so
2275
+ // we want to ignore the AST created from demangling the type.
2276
+ //
2277
+ // TODO: Avoid the extra allocations to the bump allocator in this case.
2278
+ (void )demangleType (MangledName, QualifierMangleMode::Drop);
2279
+ if (Error)
2280
+ return nullptr ;
2281
+ }
2282
+
2259
2283
TemplateParameterReferenceNode *TPRN = nullptr ;
2260
2284
if (consumeFront (MangledName, " $$Y" )) {
2261
2285
// Template alias
@@ -2266,15 +2290,17 @@ Demangler::demangleTemplateParameterList(std::string_view &MangledName) {
2266
2290
} else if (consumeFront (MangledName, " $$C" )) {
2267
2291
// Type has qualifiers.
2268
2292
TP.N = demangleType (MangledName, QualifierMangleMode::Mangle);
2269
- } else if (llvm::itanium_demangle::starts_with (MangledName, " $1" ) ||
2270
- llvm::itanium_demangle::starts_with (MangledName, " $H" ) ||
2271
- llvm::itanium_demangle::starts_with (MangledName, " $I" ) ||
2272
- llvm::itanium_demangle::starts_with (MangledName, " $J" )) {
2293
+ } else if (startsWith (MangledName, " $1" , " 1 " , !IsAutoNTTP ) ||
2294
+ startsWith (MangledName, " $H" , " H " , !IsAutoNTTP ) ||
2295
+ startsWith (MangledName, " $I" , " I " , !IsAutoNTTP ) ||
2296
+ startsWith (MangledName, " $J" , " J " , !IsAutoNTTP )) {
2273
2297
// Pointer to member
2274
2298
TP.N = TPRN = Arena.alloc <TemplateParameterReferenceNode>();
2275
2299
TPRN->IsMemberPointer = true ;
2276
2300
2277
- MangledName.remove_prefix (1 );
2301
+ if (!IsAutoNTTP)
2302
+ MangledName.remove_prefix (1 ); // Remove leading '$'
2303
+
2278
2304
// 1 - single inheritance <name>
2279
2305
// H - multiple inheritance <name> <number>
2280
2306
// I - virtual inheritance <name> <number> <number>
@@ -2342,7 +2368,7 @@ Demangler::demangleTemplateParameterList(std::string_view &MangledName) {
2342
2368
}
2343
2369
TPRN->IsMemberPointer = true ;
2344
2370
2345
- } else if (consumeFront (MangledName, " $0" )) {
2371
+ } else if (consumeFront (MangledName, " $0" , " 0 " , !IsAutoNTTP )) {
2346
2372
// Integral non-type template parameter
2347
2373
bool IsNegative = false ;
2348
2374
uint64_t Value = 0 ;
0 commit comments