xref: /freebsd/contrib/llvm-project/clang/lib/AST/ASTDumper.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the AST dump methods, which dump out the
100b57cec5SDimitry Andric // AST in a form that exposes type details and other fields.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/AST/ASTDumper.h"
150b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
160b57cec5SDimitry Andric #include "clang/AST/DeclLookups.h"
170b57cec5SDimitry Andric #include "clang/AST/JSONNodeDumper.h"
180b57cec5SDimitry Andric #include "clang/Basic/Builtins.h"
190b57cec5SDimitry Andric #include "clang/Basic/Module.h"
200b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
22*bdd1243dSDimitry Andric 
230b57cec5SDimitry Andric using namespace clang;
240b57cec5SDimitry Andric using namespace clang::comments;
250b57cec5SDimitry Andric 
26*bdd1243dSDimitry Andric void ASTDumper::dumpInvalidDeclContext(const DeclContext *DC) {
27*bdd1243dSDimitry Andric   NodeDumper.AddChild([=] {
28*bdd1243dSDimitry Andric     if (!DC) {
29*bdd1243dSDimitry Andric       ColorScope Color(OS, ShowColors, NullColor);
30*bdd1243dSDimitry Andric       OS << "<<<NULL>>>";
31*bdd1243dSDimitry Andric       return;
32*bdd1243dSDimitry Andric     }
33*bdd1243dSDimitry Andric     // An invalid DeclContext is one for which a dyn_cast() from a DeclContext
34*bdd1243dSDimitry Andric     // pointer to a Decl pointer would fail an assertion or otherwise fall prey
35*bdd1243dSDimitry Andric     // to undefined behavior as a result of an invalid associated DeclKind.
36*bdd1243dSDimitry Andric     // Such invalidity is not supposed to happen of course, but, when it does,
37*bdd1243dSDimitry Andric     // the information provided below is intended to provide some hints about
38*bdd1243dSDimitry Andric     // what might have gone awry.
39*bdd1243dSDimitry Andric     {
40*bdd1243dSDimitry Andric       ColorScope Color(OS, ShowColors, DeclKindNameColor);
41*bdd1243dSDimitry Andric       OS << "DeclContext";
42*bdd1243dSDimitry Andric     }
43*bdd1243dSDimitry Andric     NodeDumper.dumpPointer(DC);
44*bdd1243dSDimitry Andric     OS << " <";
45*bdd1243dSDimitry Andric     {
46*bdd1243dSDimitry Andric       ColorScope Color(OS, ShowColors, DeclNameColor);
47*bdd1243dSDimitry Andric       OS << "unrecognized Decl kind " << (unsigned)DC->getDeclKind();
48*bdd1243dSDimitry Andric     }
49*bdd1243dSDimitry Andric     OS << ">";
50*bdd1243dSDimitry Andric   });
51*bdd1243dSDimitry Andric }
52*bdd1243dSDimitry Andric 
530b57cec5SDimitry Andric void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
540b57cec5SDimitry Andric   NodeDumper.AddChild([=] {
550b57cec5SDimitry Andric     OS << "StoredDeclsMap ";
560b57cec5SDimitry Andric     NodeDumper.dumpBareDeclRef(cast<Decl>(DC));
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric     const DeclContext *Primary = DC->getPrimaryContext();
590b57cec5SDimitry Andric     if (Primary != DC) {
600b57cec5SDimitry Andric       OS << " primary";
610b57cec5SDimitry Andric       NodeDumper.dumpPointer(cast<Decl>(Primary));
620b57cec5SDimitry Andric     }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric     bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric     auto Range = getDeserialize()
670b57cec5SDimitry Andric                      ? Primary->lookups()
680b57cec5SDimitry Andric                      : Primary->noload_lookups(/*PreserveInternalState=*/true);
690b57cec5SDimitry Andric     for (auto I = Range.begin(), E = Range.end(); I != E; ++I) {
700b57cec5SDimitry Andric       DeclarationName Name = I.getLookupName();
710b57cec5SDimitry Andric       DeclContextLookupResult R = *I;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric       NodeDumper.AddChild([=] {
740b57cec5SDimitry Andric         OS << "DeclarationName ";
750b57cec5SDimitry Andric         {
760b57cec5SDimitry Andric           ColorScope Color(OS, ShowColors, DeclNameColor);
770b57cec5SDimitry Andric           OS << '\'' << Name << '\'';
780b57cec5SDimitry Andric         }
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric         for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
810b57cec5SDimitry Andric              RI != RE; ++RI) {
820b57cec5SDimitry Andric           NodeDumper.AddChild([=] {
830b57cec5SDimitry Andric             NodeDumper.dumpBareDeclRef(*RI);
840b57cec5SDimitry Andric 
855ffd83dbSDimitry Andric             if (!(*RI)->isUnconditionallyVisible())
860b57cec5SDimitry Andric               OS << " hidden";
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric             // If requested, dump the redecl chain for this lookup.
890b57cec5SDimitry Andric             if (DumpDecls) {
900b57cec5SDimitry Andric               // Dump earliest decl first.
910b57cec5SDimitry Andric               std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {
920b57cec5SDimitry Andric                 if (Decl *Prev = D->getPreviousDecl())
930b57cec5SDimitry Andric                   DumpWithPrev(Prev);
940b57cec5SDimitry Andric                 Visit(D);
950b57cec5SDimitry Andric               };
960b57cec5SDimitry Andric               DumpWithPrev(*RI);
970b57cec5SDimitry Andric             }
980b57cec5SDimitry Andric           });
990b57cec5SDimitry Andric         }
1000b57cec5SDimitry Andric       });
1010b57cec5SDimitry Andric     }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric     if (HasUndeserializedLookups) {
1040b57cec5SDimitry Andric       NodeDumper.AddChild([=] {
1050b57cec5SDimitry Andric         ColorScope Color(OS, ShowColors, UndeserializedColor);
1060b57cec5SDimitry Andric         OS << "<undeserialized lookups>";
1070b57cec5SDimitry Andric       });
1080b57cec5SDimitry Andric     }
1090b57cec5SDimitry Andric   });
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric template <typename SpecializationDecl>
1130b57cec5SDimitry Andric void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,
1140b57cec5SDimitry Andric                                                bool DumpExplicitInst,
1150b57cec5SDimitry Andric                                                bool DumpRefOnly) {
1160b57cec5SDimitry Andric   bool DumpedAny = false;
1170b57cec5SDimitry Andric   for (const auto *RedeclWithBadType : D->redecls()) {
1180b57cec5SDimitry Andric     // FIXME: The redecls() range sometimes has elements of a less-specific
1190b57cec5SDimitry Andric     // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
1200b57cec5SDimitry Andric     // us TagDecls, and should give CXXRecordDecls).
121349cc55cSDimitry Andric     auto *Redecl = cast<SpecializationDecl>(RedeclWithBadType);
1220b57cec5SDimitry Andric     switch (Redecl->getTemplateSpecializationKind()) {
1230b57cec5SDimitry Andric     case TSK_ExplicitInstantiationDeclaration:
1240b57cec5SDimitry Andric     case TSK_ExplicitInstantiationDefinition:
1250b57cec5SDimitry Andric       if (!DumpExplicitInst)
1260b57cec5SDimitry Andric         break;
127*bdd1243dSDimitry Andric       [[fallthrough]];
1280b57cec5SDimitry Andric     case TSK_Undeclared:
1290b57cec5SDimitry Andric     case TSK_ImplicitInstantiation:
1300b57cec5SDimitry Andric       if (DumpRefOnly)
1310b57cec5SDimitry Andric         NodeDumper.dumpDeclRef(Redecl);
1320b57cec5SDimitry Andric       else
1330b57cec5SDimitry Andric         Visit(Redecl);
1340b57cec5SDimitry Andric       DumpedAny = true;
1350b57cec5SDimitry Andric       break;
1360b57cec5SDimitry Andric     case TSK_ExplicitSpecialization:
1370b57cec5SDimitry Andric       break;
1380b57cec5SDimitry Andric     }
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   // Ensure we dump at least one decl for each specialization.
1420b57cec5SDimitry Andric   if (!DumpedAny)
1430b57cec5SDimitry Andric     NodeDumper.dumpDeclRef(D);
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric template <typename TemplateDecl>
1470b57cec5SDimitry Andric void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
1480b57cec5SDimitry Andric   dumpTemplateParameters(D->getTemplateParameters());
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   Visit(D->getTemplatedDecl());
1510b57cec5SDimitry Andric 
152e8d8bef9SDimitry Andric   if (GetTraversalKind() == TK_AsIs) {
1530b57cec5SDimitry Andric     for (const auto *Child : D->specializations())
1540b57cec5SDimitry Andric       dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
1550b57cec5SDimitry Andric                                      !D->isCanonicalDecl());
1560b57cec5SDimitry Andric   }
157e8d8bef9SDimitry Andric }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
1600b57cec5SDimitry Andric   // FIXME: We don't add a declaration of a function template specialization
1610b57cec5SDimitry Andric   // to its context when it's explicitly instantiated, so dump explicit
1620b57cec5SDimitry Andric   // instantiations when we dump the template itself.
1630b57cec5SDimitry Andric   dumpTemplateDecl(D, true);
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
1670b57cec5SDimitry Andric   dumpTemplateDecl(D, false);
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
1710b57cec5SDimitry Andric   dumpTemplateDecl(D, false);
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1750b57cec5SDimitry Andric // Type method implementations
1760b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric void QualType::dump(const char *msg) const {
1790b57cec5SDimitry Andric   if (msg)
1800b57cec5SDimitry Andric     llvm::errs() << msg << ": ";
1810b57cec5SDimitry Andric   dump();
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
1845ffd83dbSDimitry Andric LLVM_DUMP_METHOD void QualType::dump() const {
1855ffd83dbSDimitry Andric   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
1860b57cec5SDimitry Andric   Dumper.Visit(*this);
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
1895ffd83dbSDimitry Andric LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS,
1905ffd83dbSDimitry Andric                                      const ASTContext &Context) const {
1915ffd83dbSDimitry Andric   ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
1925ffd83dbSDimitry Andric   Dumper.Visit(*this);
1935ffd83dbSDimitry Andric }
1940b57cec5SDimitry Andric 
1955ffd83dbSDimitry Andric LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
1965ffd83dbSDimitry Andric 
1975ffd83dbSDimitry Andric LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS,
1985ffd83dbSDimitry Andric                                  const ASTContext &Context) const {
1995ffd83dbSDimitry Andric   QualType(this, 0).dump(OS, Context);
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2030b57cec5SDimitry Andric // Decl method implementations
2040b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,
2090b57cec5SDimitry Andric                                  ASTDumpOutputFormat Format) const {
2100b57cec5SDimitry Andric   ASTContext &Ctx = getASTContext();
2110b57cec5SDimitry Andric   const SourceManager &SM = Ctx.getSourceManager();
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   if (ADOF_JSON == Format) {
2140b57cec5SDimitry Andric     JSONDumper P(OS, SM, Ctx, Ctx.getPrintingPolicy(),
2150b57cec5SDimitry Andric                  &Ctx.getCommentCommandTraits());
2160b57cec5SDimitry Andric     (void)Deserialize; // FIXME?
2170b57cec5SDimitry Andric     P.Visit(this);
2180b57cec5SDimitry Andric   } else {
2195ffd83dbSDimitry Andric     ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
2200b57cec5SDimitry Andric     P.setDeserialize(Deserialize);
2210b57cec5SDimitry Andric     P.Visit(this);
2220b57cec5SDimitry Andric   }
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric LLVM_DUMP_METHOD void Decl::dumpColor() const {
2260b57cec5SDimitry Andric   const ASTContext &Ctx = getASTContext();
2275ffd83dbSDimitry Andric   ASTDumper P(llvm::errs(), Ctx, /*ShowColors=*/true);
2280b57cec5SDimitry Andric   P.Visit(this);
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric 
231*bdd1243dSDimitry Andric LLVM_DUMP_METHOD void DeclContext::dumpAsDecl() const {
232*bdd1243dSDimitry Andric   dumpAsDecl(nullptr);
233*bdd1243dSDimitry Andric }
234*bdd1243dSDimitry Andric 
235*bdd1243dSDimitry Andric LLVM_DUMP_METHOD void DeclContext::dumpAsDecl(const ASTContext *Ctx) const {
236*bdd1243dSDimitry Andric   // By design, DeclContext is required to be a base class of some class that
237*bdd1243dSDimitry Andric   // derives from Decl. Thus, it should always be possible to dyn_cast() from
238*bdd1243dSDimitry Andric   // a DeclContext pointer to a Decl pointer and Decl::castFromDeclContext()
239*bdd1243dSDimitry Andric   // asserts that to be the case. Since this function is intended for use in a
240*bdd1243dSDimitry Andric   // debugger, it performs an additional check in order to prevent a failed
241*bdd1243dSDimitry Andric   // cast and assertion. If that check fails, then the (invalid) DeclContext
242*bdd1243dSDimitry Andric   // is dumped with an indication of its invalidity.
243*bdd1243dSDimitry Andric   if (hasValidDeclKind()) {
244*bdd1243dSDimitry Andric     const auto *D = cast<Decl>(this);
245*bdd1243dSDimitry Andric     D->dump();
246*bdd1243dSDimitry Andric   } else {
247*bdd1243dSDimitry Andric     // If an ASTContext is not available, a less capable ASTDumper is
248*bdd1243dSDimitry Andric     // constructed for which color diagnostics are, regrettably, disabled.
249*bdd1243dSDimitry Andric     ASTDumper P = Ctx ? ASTDumper(llvm::errs(), *Ctx,
250*bdd1243dSDimitry Andric                                   Ctx->getDiagnostics().getShowColors())
251*bdd1243dSDimitry Andric                       : ASTDumper(llvm::errs(), /*ShowColors*/ false);
252*bdd1243dSDimitry Andric     P.dumpInvalidDeclContext(this);
253*bdd1243dSDimitry Andric   }
254*bdd1243dSDimitry Andric }
255*bdd1243dSDimitry Andric 
2560b57cec5SDimitry Andric LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
2570b57cec5SDimitry Andric   dumpLookups(llvm::errs());
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
2610b57cec5SDimitry Andric                                                bool DumpDecls,
2620b57cec5SDimitry Andric                                                bool Deserialize) const {
2630b57cec5SDimitry Andric   const DeclContext *DC = this;
2640b57cec5SDimitry Andric   while (!DC->isTranslationUnit())
2650b57cec5SDimitry Andric     DC = DC->getParent();
2665ffd83dbSDimitry Andric   const ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
2675ffd83dbSDimitry Andric   ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
2680b57cec5SDimitry Andric   P.setDeserialize(Deserialize);
2690b57cec5SDimitry Andric   P.dumpLookups(this, DumpDecls);
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2730b57cec5SDimitry Andric // Stmt method implementations
2740b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric LLVM_DUMP_METHOD void Stmt::dump() const {
2775ffd83dbSDimitry Andric   ASTDumper P(llvm::errs(), /*ShowColors=*/false);
2785ffd83dbSDimitry Andric   P.Visit(this);
2795ffd83dbSDimitry Andric }
2805ffd83dbSDimitry Andric 
2815ffd83dbSDimitry Andric LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS,
2825ffd83dbSDimitry Andric                                  const ASTContext &Context) const {
2835ffd83dbSDimitry Andric   ASTDumper P(OS, Context, Context.getDiagnostics().getShowColors());
2840b57cec5SDimitry Andric   P.Visit(this);
2850b57cec5SDimitry Andric }
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric LLVM_DUMP_METHOD void Stmt::dumpColor() const {
2885ffd83dbSDimitry Andric   ASTDumper P(llvm::errs(), /*ShowColors=*/true);
2890b57cec5SDimitry Andric   P.Visit(this);
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2930b57cec5SDimitry Andric // Comment method implementations
2940b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric LLVM_DUMP_METHOD void Comment::dump() const {
2975ffd83dbSDimitry Andric   const auto *FC = dyn_cast<FullComment>(this);
2980b57cec5SDimitry Andric   if (!FC)
2990b57cec5SDimitry Andric     return;
3005ffd83dbSDimitry Andric   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
3015ffd83dbSDimitry Andric   Dumper.Visit(FC, FC);
3025ffd83dbSDimitry Andric }
3035ffd83dbSDimitry Andric 
3045ffd83dbSDimitry Andric LLVM_DUMP_METHOD void Comment::dump(raw_ostream &OS,
3055ffd83dbSDimitry Andric                                     const ASTContext &Context) const {
3065ffd83dbSDimitry Andric   const auto *FC = dyn_cast<FullComment>(this);
3075ffd83dbSDimitry Andric   if (!FC)
3085ffd83dbSDimitry Andric     return;
3095ffd83dbSDimitry Andric   ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
3105ffd83dbSDimitry Andric   Dumper.Visit(FC, FC);
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric LLVM_DUMP_METHOD void Comment::dumpColor() const {
3145ffd83dbSDimitry Andric   const auto *FC = dyn_cast<FullComment>(this);
3150b57cec5SDimitry Andric   if (!FC)
3160b57cec5SDimitry Andric     return;
3175ffd83dbSDimitry Andric   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/true);
3185ffd83dbSDimitry Andric   Dumper.Visit(FC, FC);
3195ffd83dbSDimitry Andric }
3205ffd83dbSDimitry Andric 
3215ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
3225ffd83dbSDimitry Andric // APValue method implementations
3235ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
3245ffd83dbSDimitry Andric 
3255ffd83dbSDimitry Andric LLVM_DUMP_METHOD void APValue::dump() const {
3265ffd83dbSDimitry Andric   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
3275ffd83dbSDimitry Andric   Dumper.Visit(*this, /*Ty=*/QualType());
3285ffd83dbSDimitry Andric }
3295ffd83dbSDimitry Andric 
3305ffd83dbSDimitry Andric LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,
3315ffd83dbSDimitry Andric                                     const ASTContext &Context) const {
3325ffd83dbSDimitry Andric   ASTDumper Dumper(llvm::errs(), Context,
3335ffd83dbSDimitry Andric                    Context.getDiagnostics().getShowColors());
3345ffd83dbSDimitry Andric   Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));
3350b57cec5SDimitry Andric }
336