source: src/SymTab/Demangle.cc@ 158b026

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 158b026 was 4071778, checked in by Peter A. Buhr <pabuhr@…>, 6 years ago

remove lvalue from mangling/demangling as it is no longer used

  • Property mode set to 100644
File size: 19.9 KB
RevLine 
[d1e0979]1//
2// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Demangler.cc --
8//
9// Author : Rob Schluntz
10// Created On : Thu Jul 19 12:52:41 2018
[4071778]11// Last Modified By : Peter A. Buhr
12// Last Modified On : Tue Jul 30 13:46:33 2019
13// Update Count : 3
[d1e0979]14//
15
16#include <algorithm>
17#include <sstream>
18
19#include "CodeGen/GenType.h"
20#include "Common/PassVisitor.h"
21#include "Mangler.h"
22#include "SynTree/Type.h"
23#include "SynTree/Declaration.h"
24
[04c77791]25#define DEBUG
[d1e0979]26#ifdef DEBUG
27#define PRINT(x) x
28#else
29#define PRINT(x) {}
30#endif
31
32namespace {
33 struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting {
34 std::string typeString;
35 GenType( const std::string &typeString );
36
37 void previsit( BaseSyntaxNode * );
38 void postvisit( BaseSyntaxNode * );
39
40 void postvisit( FunctionType * funcType );
41 void postvisit( VoidType * voidType );
42 void postvisit( BasicType * basicType );
43 void postvisit( PointerType * pointerType );
44 void postvisit( ArrayType * arrayType );
45 void postvisit( ReferenceType * refType );
46 void postvisit( StructInstType * structInst );
47 void postvisit( UnionInstType * unionInst );
48 void postvisit( EnumInstType * enumInst );
49 void postvisit( TypeInstType * typeInst );
50 void postvisit( TupleType * tupleType );
51 void postvisit( VarArgsType * varArgsType );
52 void postvisit( ZeroType * zeroType );
53 void postvisit( OneType * oneType );
54 void postvisit( GlobalScopeType * globalType );
55 void postvisit( QualifiedType * qualType );
56
57 private:
58 void handleQualifiers( Type *type );
59 std::string handleGeneric( ReferenceToType * refType );
60 void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic );
61 };
62
63 std::string genDemangleType( Type * type, const std::string & baseString ) {
64 PassVisitor<GenType> gt( baseString );
65 assert( type );
66 type->accept( gt );
67 return gt.pass.typeString;
68 }
69
70 GenType::GenType( const std::string &typeString ) : typeString( typeString ) {}
71
72 // *** BaseSyntaxNode
73 void GenType::previsit( BaseSyntaxNode * ) {
74 // turn off automatic recursion for all nodes, to allow each visitor to
75 // precisely control the order in which its children are visited.
76 visit_children = false;
77 }
78
79 void GenType::postvisit( BaseSyntaxNode * node ) {
80 std::stringstream ss;
81 node->print( ss );
82 assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() );
83 }
84
85 void GenType::postvisit( VoidType * voidType ) {
86 typeString = "void " + typeString;
87 handleQualifiers( voidType );
88 }
89
90 void GenType::postvisit( BasicType * basicType ) {
91 BasicType::Kind kind = basicType->kind;
92 assert( 0 <= kind && kind < BasicType::NUMBER_OF_BASIC_TYPES );
93 typeString = std::string( BasicType::typeNames[kind] ) + " " + typeString;
94 handleQualifiers( basicType );
95 }
96
97 void GenType::genArray( const Type::Qualifiers & qualifiers, Type * base, Expression *dimension, bool isVarLen, bool ) {
98 std::ostringstream os;
99 if ( typeString != "" ) {
100 if ( typeString[ 0 ] == '*' ) {
101 os << "(" << typeString << ")";
102 } else {
103 os << typeString;
104 } // if
105 } // if
106 os << "[";
107
108 if ( qualifiers.is_const ) {
109 os << "const ";
110 } // if
111 if ( qualifiers.is_volatile ) {
112 os << "volatile ";
113 } // if
114 if ( qualifiers.is_restrict ) {
115 os << "__restrict ";
116 } // if
117 if ( qualifiers.is_atomic ) {
118 os << "_Atomic ";
119 } // if
120 if ( dimension != 0 ) {
121 // TODO: ???
122 // PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
123 // dimension->accept( cg );
124 } else if ( isVarLen ) {
125 // no dimension expression on a VLA means it came in with the * token
126 os << "*";
127 } // if
128 os << "]";
129
130 typeString = os.str();
131
132 base->accept( *visitor );
133 }
134
135 void GenType::postvisit( PointerType * pointerType ) {
136 assert( pointerType->base != 0);
137 if ( pointerType->get_isStatic() || pointerType->get_isVarLen() || pointerType->dimension ) {
138 assert(false);
139 genArray( pointerType->get_qualifiers(), pointerType->base, pointerType->dimension, pointerType->get_isVarLen(), pointerType->get_isStatic() );
140 } else {
141 handleQualifiers( pointerType );
142 if ( typeString[ 0 ] == '?' ) {
143 typeString = "* " + typeString;
144 } else {
145 typeString = "*" + typeString;
146 } // if
147 pointerType->base->accept( *visitor );
148 } // if
149 }
150
151 void GenType::postvisit( ArrayType * arrayType ) {
152 genArray( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->get_isVarLen(), arrayType->get_isStatic() );
153 }
154
155 void GenType::postvisit( ReferenceType * refType ) {
156 assert( false );
157 assert( refType->base != 0);
158 handleQualifiers( refType );
159 typeString = "&" + typeString;
160 refType->base->accept( *visitor );
161 }
162
163 void GenType::postvisit( FunctionType * funcType ) {
164 std::ostringstream os;
165
166 if ( typeString != "" ) {
167 if ( typeString[0] == '*' ) {
168 os << "(" << typeString << ")";
169 } else {
170 os << typeString;
171 } // if
172 } // if
173
174 /************* parameters ***************/
175 const std::list<DeclarationWithType *> &pars = funcType->parameters;
176
177 if ( pars.empty() ) {
178 if ( funcType->get_isVarArgs() ) {
179 os << "()";
180 } else {
181 os << "(void)";
182 } // if
183 } else {
184 os << "(" ;
185
186 unsigned int i = 0;
187 for (DeclarationWithType * p : pars) {
188 os << genDemangleType( p->get_type(), "" );
189 if (++i != pars.size()) os << ", ";
190 }
191
192 if ( funcType->get_isVarArgs() ) {
193 os << ", ...";
194 } // if
195 os << ")";
196 } // if
197
198 typeString = os.str();
199
200 if ( funcType->returnVals.size() == 0 ) {
201 typeString += ": void";
202 } else {
203 typeString += ": " + genDemangleType(funcType->returnVals.front()->get_type(), "");
204 } // if
205
206 // add forall
207 if( ! funcType->forall.empty() ) {
208 std::ostringstream os;
209 os << "forall(";
210 unsigned int i = 0;
211 for ( auto td : funcType->forall ) {
212 os << td->typeString() << " " << td->name;
213 if (! td->assertions.empty()) {
214 os << " | { ";
215 unsigned int j = 0;
216 for (DeclarationWithType * assert : td->assertions) {
217 os << genDemangleType(assert->get_type(), assert->name);
218 if (++j != td->assertions.size()) os << ", ";
219 }
220 os << "}";
221 }
222 if (++i != funcType->forall.size()) os << ", ";
223 }
224 os << ")";
225 typeString = typeString + " -> " + os.str();
226 }
227 }
228
229 std::string GenType::handleGeneric( ReferenceToType * refType ) {
230 if ( ! refType->parameters.empty() ) {
231 std::ostringstream os;
232 // TODO: ???
233 // PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
234 os << "(";
235 // cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() );
236 os << ") ";
237 return os.str();
238 }
239 return "";
240 }
241
242 void GenType::postvisit( StructInstType * structInst ) {
243 typeString = "struct " + structInst->name + handleGeneric( structInst ) + " " + typeString;
244 handleQualifiers( structInst );
245 }
246
247 void GenType::postvisit( UnionInstType * unionInst ) {
248 typeString = "union " + unionInst->name + handleGeneric( unionInst ) + " " + typeString;
249 handleQualifiers( unionInst );
250 }
251
252 void GenType::postvisit( EnumInstType * enumInst ) {
253 typeString = "enum " + enumInst->name + " " + typeString;
254 handleQualifiers( enumInst );
255 }
256
257 void GenType::postvisit( TypeInstType * typeInst ) {
258 typeString = typeInst->name + " " + typeString;
259 handleQualifiers( typeInst );
260 }
261
262 void GenType::postvisit( TupleType * tupleType ) {
263 unsigned int i = 0;
264 std::ostringstream os;
265 os << "[";
266 for ( Type * t : *tupleType ) {
267 i++;
268 os << genDemangleType( t, "" ) << (i == tupleType->size() ? "" : ", ");
269 }
270 os << "] ";
271 typeString = os.str() + typeString;
272 }
273
274 void GenType::postvisit( VarArgsType * varArgsType ) {
275 typeString = "__builtin_va_list " + typeString;
276 handleQualifiers( varArgsType );
277 }
278
279 void GenType::postvisit( ZeroType * zeroType ) {
280 // ideally these wouldn't hit codegen at all, but should be safe to make them ints
281 typeString = "zero_t " + typeString;
282 handleQualifiers( zeroType );
283 }
284
285 void GenType::postvisit( OneType * oneType ) {
286 // ideally these wouldn't hit codegen at all, but should be safe to make them ints
287 typeString = "one_t " + typeString;
288 handleQualifiers( oneType );
289 }
290
291 void GenType::postvisit( GlobalScopeType * globalType ) {
292 handleQualifiers( globalType );
293 }
294
295 void GenType::postvisit( QualifiedType * qualType ) {
296 std::ostringstream os;
297 os << genDemangleType( qualType->parent, "" ) << "." << genDemangleType( qualType->child, "" ) << typeString;
298 typeString = os.str();
299 handleQualifiers( qualType );
300 }
301
302 void GenType::handleQualifiers( Type * type ) {
303 if ( type->get_const() ) {
304 typeString = "const " + typeString;
305 } // if
306 if ( type->get_volatile() ) {
307 typeString = "volatile " + typeString;
308 } // if
309 if ( type->get_restrict() ) {
310 typeString = "__restrict " + typeString;
311 } // if
312 if ( type->get_atomic() ) {
313 typeString = "_Atomic " + typeString;
314 } // if
315 }
316}
317
318
319namespace SymTab {
320 namespace Mangler {
321 namespace {
[c20fafd]322 struct StringView {
323 private:
324 std::string str;
325 size_t idx = 0;
326 // typedef Type * (StringView::*parser)(Type::Qualifiers);
327 typedef std::function<Type * (Type::Qualifiers)> parser;
328 std::vector<std::pair<std::string, parser>> parsers;
329 public:
330 StringView(const std::string & str);
331
332 bool done() const { return idx >= str.size(); }
333 char cur() const { assert(! done()); return str[idx]; }
334
335 bool expect(char ch) { return str[idx++] == ch; }
336 void next(size_t inc = 1) { idx += inc; }
337
338 /// determines if `pref` is a prefix of `str`
339 bool isPrefix(const std::string & pref);
340 bool extractNumber(size_t & out);
341 bool extractName(std::string & out);
342 bool stripMangleName(std::string & name);
343
344 Type * parseFunction(Type::Qualifiers tq);
345 Type * parseTuple(Type::Qualifiers tq);
346 Type * parseVoid(Type::Qualifiers tq);
347 Type * parsePointer(Type::Qualifiers tq);
[2f9768f]348 Type * parseArray(Type::Qualifiers tq);
[c20fafd]349 Type * parseStruct(Type::Qualifiers tq);
[38587bc]350 Type * parseUnion(Type::Qualifiers tq);
351 Type * parseEnum(Type::Qualifiers tq);
[efa8b6a]352 Type * parseType(Type::Qualifiers tq);
[c20fafd]353
354 Type * parseType();
355 bool parse(std::string & name, Type *& type);
356 };
357
358 StringView::StringView(const std::string & str) : str(str) {
359 // basic types
360 for (size_t k = 0; k < BasicType::NUMBER_OF_BASIC_TYPES; ++k) {
[8316a49]361 parsers.emplace_back(Encoding::basicTypes[k], [k](Type::Qualifiers tq) {
[c20fafd]362 PRINT( std::cerr << "basic type: " << k << std::endl; )
363 return new BasicType(tq, (BasicType::Kind)k);
364 });
365 }
[04c77791]366 // type variable types
367 for (size_t k = 0; k < TypeDecl::NUMBER_OF_KINDS; ++k) {
[550e819]368 static const std::string typeVariableNames[] = { "DT", "FT", "TT", };
369 static_assert(
370 sizeof(typeVariableNames)/sizeof(typeVariableNames[0]) == TypeDecl::NUMBER_OF_KINDS,
371 "Each type variable kind should have a demangle name prefix"
372 );
[04c77791]373 parsers.emplace_back(Encoding::typeVariables[k], [k, this](Type::Qualifiers tq) -> TypeInstType * {
374 PRINT( std::cerr << "type variable type: " << k << std::endl; )
[550e819]375 size_t N;
376 if (! extractNumber(N)) return nullptr;
377 return new TypeInstType(tq, toString(typeVariableNames[k], N), (TypeDecl::Kind)k != TypeDecl::Ftype);
[04c77791]378 });
379 }
[c20fafd]380 // everything else
381 parsers.emplace_back(Encoding::void_t, [this](Type::Qualifiers tq) { return parseVoid(tq); });
382 parsers.emplace_back(Encoding::function, [this](Type::Qualifiers tq) { return parseFunction(tq); });
383 parsers.emplace_back(Encoding::pointer, [this](Type::Qualifiers tq) { return parsePointer(tq); });
[2f9768f]384 parsers.emplace_back(Encoding::array, [this](Type::Qualifiers tq) { return parseArray(tq); });
[c20fafd]385 parsers.emplace_back(Encoding::tuple, [this](Type::Qualifiers tq) { return parseTuple(tq); });
386 parsers.emplace_back(Encoding::struct_t, [this](Type::Qualifiers tq) { return parseStruct(tq); });
[38587bc]387 parsers.emplace_back(Encoding::union_t, [this](Type::Qualifiers tq) { return parseUnion(tq); });
388 parsers.emplace_back(Encoding::enum_t, [this](Type::Qualifiers tq) { return parseEnum(tq); });
[efa8b6a]389 parsers.emplace_back(Encoding::type, [this](Type::Qualifiers tq) { return parseType(tq); });
[56b53b2]390 parsers.emplace_back(Encoding::zero, [](Type::Qualifiers tq) { return new ZeroType(tq); });
391 parsers.emplace_back(Encoding::one, [](Type::Qualifiers tq) { return new OneType(tq); });
[c20fafd]392 }
393
394 bool StringView::extractNumber(size_t & out) {
395 std::stringstream numss;
[efa8b6a]396 if (idx >= str.size()) return false;
[c20fafd]397 while (isdigit(str[idx])) {
398 numss << str[idx];
399 ++idx;
[efa8b6a]400 if (idx == str.size()) break;
[c20fafd]401 }
402 if (! (numss >> out)) return false;
[efa8b6a]403 PRINT( std::cerr << "extractNumber success: " << out << std::endl; )
[c20fafd]404 return true;
405 }
406
407 bool StringView::extractName(std::string & out) {
408 size_t len;
409 if (! extractNumber(len)) return false;
[efa8b6a]410 if (idx+len > str.size()) return false;
[c20fafd]411 out = str.substr(idx, len);
412 idx += len;
[efa8b6a]413 PRINT( std::cerr << "extractName success: " << out << std::endl; )
[c20fafd]414 return true;
415 }
416
417 bool StringView::isPrefix(const std::string & pref) {
418 if ( pref.size() > str.size()-idx ) return false;
419 auto its = std::mismatch( pref.begin(), pref.end(), std::next(str.begin(), idx) );
420 if (its.first == pref.end()) {
421 idx += pref.size();
422 return true;
423 }
424 return false;
425 }
426
[d1e0979]427 // strips __NAME__cfa__TYPE_N, where N is [0-9]+: returns str is a match is found, returns empty string otherwise
[c20fafd]428 bool StringView::stripMangleName(std::string & name) {
429 PRINT( std::cerr << "====== " << str.size() << " " << str << std::endl; )
430 if (str.size() < 2+Encoding::manglePrefix.size()) return false; // +2 for at least _1 suffix
431 if (! isPrefix(Encoding::manglePrefix) || ! isdigit(str.back())) return false;
[d1e0979]432
[c20fafd]433 // get name
434 if (! extractName(name)) return false;
[d1e0979]435
436 // find bounds for type
[c20fafd]437 PRINT( std::cerr << idx << " " << str.size() << std::endl; )
[d1e0979]438 PRINT( std::cerr << "[");
[c20fafd]439 while (isdigit(str.back())) {
[d1e0979]440 PRINT(std::cerr << ".");
[c20fafd]441 str.pop_back();
442 if (str.size() <= idx) return false;
[d1e0979]443 }
444 PRINT( std::cerr << "]" << std::endl );
[c20fafd]445 if (str.back() != '_') return false;
446 str.pop_back();
447 PRINT( std::cerr << str.size() << " " << name << " " << str.substr(idx) << std::endl; )
448 return str.size() > idx;
449 }
[d1e0979]450
[c20fafd]451 Type * StringView::parseFunction(Type::Qualifiers tq) {
452 PRINT( std::cerr << "function..." << std::endl; )
453 if (done()) return nullptr;
454 FunctionType * ftype = new FunctionType( tq, false );
[d7d63e5]455 std::unique_ptr<Type> manager(ftype);
[c20fafd]456 Type * retVal = parseType();
457 if (! retVal) return nullptr;
458 PRINT( std::cerr << "with return type: " << retVal << std::endl; )
459 ftype->returnVals.push_back(ObjectDecl::newObject("", retVal, nullptr));
460 if (done() || ! expect('_')) return nullptr;
461 while (! done()) {
462 PRINT( std::cerr << "got ch: " << cur() << std::endl; )
[d7d63e5]463 if (cur() == '_') return manager.release();
[c20fafd]464 Type * param = parseType();
465 if (! param) return nullptr;
466 PRINT( std::cerr << "with parameter : " << param << std::endl; )
467 ftype->parameters.push_back(ObjectDecl::newObject("", param, nullptr));
468 }
469 return nullptr;
[d1e0979]470 }
471
[c20fafd]472 Type * StringView::parseTuple(Type::Qualifiers tq) {
473 PRINT( std::cerr << "tuple..." << std::endl; )
474 std::list< Type * > types;
475 size_t ncomponents;
476 if (! extractNumber(ncomponents)) return nullptr;
477 for (size_t i = 0; i < ncomponents; ++i) {
[d7d63e5]478 // TODO: delete all on return
[c20fafd]479 if (done()) return nullptr;
480 PRINT( std::cerr << "got ch: " << cur() << std::endl; )
481 Type * t = parseType();
482 if (! t) return nullptr;
483 PRINT( std::cerr << "with type : " << t << std::endl; )
484 types.push_back(t);
485 }
486 return new TupleType( tq, types );
[d1e0979]487 }
488
[c20fafd]489 Type * StringView::parseVoid(Type::Qualifiers tq) {
490 return new VoidType( tq );
491 }
492
493 Type * StringView::parsePointer(Type::Qualifiers tq) {
494 PRINT( std::cerr << "pointer..." << std::endl; )
495 Type * t = parseType();
496 if (! t) return nullptr;
497 return new PointerType( tq, t );
498 }
499
[2f9768f]500 Type * StringView::parseArray(Type::Qualifiers tq) {
501 PRINT( std::cerr << "array..." << std::endl; )
502 size_t length;
503 if (! extractNumber(length)) return nullptr;
504 Type * t = parseType();
505 if (! t) return nullptr;
506 return new ArrayType( tq, t, new ConstantExpr( Constant::from_ulong(length) ), false, false );
507 }
508
[c20fafd]509 Type * StringView::parseStruct(Type::Qualifiers tq) {
510 PRINT( std::cerr << "struct..." << std::endl; )
511 std::string name;
512 if (! extractName(name)) return nullptr;
513 return new StructInstType(tq, name);
514 }
515
[38587bc]516 Type * StringView::parseUnion(Type::Qualifiers tq) {
517 PRINT( std::cerr << "union..." << std::endl; )
518 std::string name;
519 if (! extractName(name)) return nullptr;
520 return new UnionInstType(tq, name);
521 }
522
523 Type * StringView::parseEnum(Type::Qualifiers tq) {
524 PRINT( std::cerr << "enum..." << std::endl; )
525 std::string name;
526 if (! extractName(name)) return nullptr;
527 return new EnumInstType(tq, name);
528 }
529
[efa8b6a]530 Type * StringView::parseType(Type::Qualifiers tq) {
531 PRINT( std::cerr << "type..." << std::endl; )
532 std::string name;
533 if (! extractName(name)) return nullptr;
534 PRINT( std::cerr << "typename..." << name << std::endl; )
535 return new TypeInstType(tq, name, false);
536 }
537
[c20fafd]538 Type * StringView::parseType() {
539 if (done()) return nullptr;
[d1e0979]540
[04c77791]541 std::list<TypeDecl *> forall;
542 if (isPrefix(Encoding::forall)) {
543 PRINT( std::cerr << "polymorphic with..." << std::endl; )
544 size_t dcount, fcount, vcount, acount;
545 if (! extractNumber(dcount)) return nullptr;
546 PRINT( std::cerr << dcount << " dtypes" << std::endl; )
547 if (! expect('_')) return nullptr;
548 if (! extractNumber(fcount)) return nullptr;
549 PRINT( std::cerr << fcount << " ftypes" << std::endl; )
550 if (! expect('_')) return nullptr;
551 if (! extractNumber(vcount)) return nullptr;
552 PRINT( std::cerr << vcount << " ttypes" << std::endl; )
553 if (! expect('_')) return nullptr;
554 if (! extractNumber(acount)) return nullptr;
555 PRINT( std::cerr << acount << " assertions" << std::endl; )
556 if (! expect('_')) return nullptr;
[550e819]557 for (size_t i = 0; i < acount; ++i) {
558 // TODO: need to recursively parse assertions, but for now just return nullptr so that
559 // demangler does not crash if there are assertions
560 return nullptr;
561 }
[04c77791]562 if (! expect('_')) return nullptr;
563 }
564
[d1e0979]565 // qualifiers
566 Type::Qualifiers tq;
567 while (true) {
[c20fafd]568 auto qual = std::find_if(Encoding::qualifiers.begin(), Encoding::qualifiers.end(), [this](decltype(Encoding::qualifiers)::value_type val) {
569 return isPrefix(val.second);
[d1e0979]570 });
[c20fafd]571 if (qual == Encoding::qualifiers.end()) break;
[d1e0979]572 tq |= qual->first;
573 }
574
[c20fafd]575 // find the correct type parser and use it
576 auto iter = std::find_if(parsers.begin(), parsers.end(), [this](std::pair<std::string, parser> & p) {
577 return isPrefix(p.first);
[d1e0979]578 });
[c20fafd]579 assertf(iter != parsers.end(), "Unhandled type letter: %c at index: %zd", cur(), idx);
[04c77791]580 Type * ret = iter->second(tq);
581 if (! ret) return nullptr;
582 ret->forall = std::move(forall);
583 return ret;
[d1e0979]584 }
585
[c20fafd]586 bool StringView::parse(std::string & name, Type *& type) {
587 if (! stripMangleName(name)) return false;
588 PRINT( std::cerr << "stripped name: " << name << std::endl; )
589 Type * t = parseType();
590 if (! t) return false;
591 type = t;
592 return true;
[d1e0979]593 }
[f47d0ad]594
595 std::string demangle(const std::string & mangleName) {
596 SymTab::Mangler::StringView view(mangleName);
597 std::string name;
598 Type * type = nullptr;
599 if (! view.parse(name, type)) return mangleName;
[d7d63e5]600 std::unique_ptr<Type> manager(type);
[f47d0ad]601 return genDemangleType(type, name);
602 }
[d1e0979]603 } // namespace
604 } // namespace Mangler
605} // namespace SymTab
606
607extern "C" {
[90cac45]608 char * cforall_demangle(const char * mangleName, int option __attribute__((unused))) {
[f47d0ad]609 const std::string & demangleName = SymTab::Mangler::demangle(mangleName);
610 return strdup(demangleName.c_str());
611 }
[d1e0979]612}
613
614// Local Variables: //
615// tab-width: 4 //
616// mode: c++ //
617// compile-command: "make install" //
618// End: //
Note: See TracBrowser for help on using the repository browser.