Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/ASTDumper.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file implements the AST dump methods, which dump out the
10
// AST in a form that exposes type details and other fields.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/AST/ASTDumper.h"
15
#include "clang/AST/ASTContext.h"
16
#include "clang/AST/DeclLookups.h"
17
#include "clang/AST/JSONNodeDumper.h"
18
#include "clang/Basic/Builtins.h"
19
#include "clang/Basic/Module.h"
20
#include "clang/Basic/SourceManager.h"
21
#include "llvm/Support/raw_ostream.h"
22
using namespace clang;
23
using namespace clang::comments;
24
25
7
void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
26
7
  NodeDumper.AddChild([=] {
27
7
    OS << "StoredDeclsMap ";
28
7
    NodeDumper.dumpBareDeclRef(cast<Decl>(DC));
29
7
30
7
    const DeclContext *Primary = DC->getPrimaryContext();
31
7
    if (Primary != DC) {
32
0
      OS << " primary";
33
0
      NodeDumper.dumpPointer(cast<Decl>(Primary));
34
0
    }
35
7
36
7
    bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
37
7
38
7
    auto Range = getDeserialize()
39
7
                     ? 
Primary->lookups()0
40
7
                     : Primary->noload_lookups(/*PreserveInternalState=*/true);
41
138
    for (auto I = Range.begin(), E = Range.end(); I != E; 
++I131
) {
42
131
      DeclarationName Name = I.getLookupName();
43
131
      DeclContextLookupResult R = *I;
44
131
45
131
      NodeDumper.AddChild([=] {
46
131
        OS << "DeclarationName ";
47
131
        {
48
131
          ColorScope Color(OS, ShowColors, DeclNameColor);
49
131
          OS << '\'' << Name << '\'';
50
131
        }
51
131
52
131
        for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
53
299
             RI != RE; 
++RI168
) {
54
168
          NodeDumper.AddChild([=] {
55
168
            NodeDumper.dumpBareDeclRef(*RI);
56
168
57
168
            if ((*RI)->isHidden())
58
7
              OS << " hidden";
59
168
60
168
            // If requested, dump the redecl chain for this lookup.
61
168
            if (DumpDecls) {
62
2
              // Dump earliest decl first.
63
3
              std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {
64
3
                if (Decl *Prev = D->getPreviousDecl())
65
1
                  DumpWithPrev(Prev);
66
3
                Visit(D);
67
3
              };
68
2
              DumpWithPrev(*RI);
69
2
            }
70
168
          });
71
168
        }
72
131
      });
73
131
    }
74
7
75
7
    if (HasUndeserializedLookups) {
76
5
      NodeDumper.AddChild([=] {
77
5
        ColorScope Color(OS, ShowColors, UndeserializedColor);
78
5
        OS << "<undeserialized lookups>";
79
5
      });
80
5
    }
81
7
  });
82
7
}
83
84
template <typename SpecializationDecl>
85
void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,
86
                                               bool DumpExplicitInst,
87
148
                                               bool DumpRefOnly) {
88
148
  bool DumpedAny = false;
89
240
  for (const auto *RedeclWithBadType : D->redecls()) {
90
240
    // FIXME: The redecls() range sometimes has elements of a less-specific
91
240
    // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
92
240
    // us TagDecls, and should give CXXRecordDecls).
93
240
    auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
94
240
    if (!Redecl) {
95
85
      // Found the injected-class-name for a class template. This will be dumped
96
85
      // as part of its surrounding class so we don't need to dump it here.
97
85
      assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
98
85
             "expected an injected-class-name");
99
85
      continue;
100
85
    }
101
155
102
155
    switch (Redecl->getTemplateSpecializationKind()) {
103
15
    case TSK_ExplicitInstantiationDeclaration:
104
15
    case TSK_ExplicitInstantiationDefinition:
105
15
      if (!DumpExplicitInst)
106
10
        break;
107
5
      LLVM_FALLTHROUGH;
108
130
    case TSK_Undeclared:
109
130
    case TSK_ImplicitInstantiation:
110
130
      if (DumpRefOnly)
111
8
        NodeDumper.dumpDeclRef(Redecl);
112
122
      else
113
122
        Visit(Redecl);
114
130
      DumpedAny = true;
115
130
      break;
116
130
    case TSK_ExplicitSpecialization:
117
15
      break;
118
155
    }
119
155
  }
120
148
121
148
  // Ensure we dump at least one decl for each specialization.
122
148
  if (!DumpedAny)
123
22
    NodeDumper.dumpDeclRef(D);
124
148
}
void clang::ASTDumper::dumpTemplateDeclSpecialization<clang::FunctionDecl>(clang::FunctionDecl const*, bool, bool)
Line
Count
Source
87
43
                                               bool DumpRefOnly) {
88
43
  bool DumpedAny = false;
89
46
  for (const auto *RedeclWithBadType : D->redecls()) {
90
46
    // FIXME: The redecls() range sometimes has elements of a less-specific
91
46
    // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
92
46
    // us TagDecls, and should give CXXRecordDecls).
93
46
    auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
94
46
    if (!Redecl) {
95
0
      // Found the injected-class-name for a class template. This will be dumped
96
0
      // as part of its surrounding class so we don't need to dump it here.
97
0
      assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
98
0
             "expected an injected-class-name");
99
0
      continue;
100
0
    }
101
46
102
46
    switch (Redecl->getTemplateSpecializationKind()) {
103
5
    case TSK_ExplicitInstantiationDeclaration:
104
5
    case TSK_ExplicitInstantiationDefinition:
105
5
      if (!DumpExplicitInst)
106
0
        break;
107
5
      LLVM_FALLTHROUGH;
108
40
    case TSK_Undeclared:
109
40
    case TSK_ImplicitInstantiation:
110
40
      if (DumpRefOnly)
111
1
        NodeDumper.dumpDeclRef(Redecl);
112
39
      else
113
39
        Visit(Redecl);
114
40
      DumpedAny = true;
115
40
      break;
116
40
    case TSK_ExplicitSpecialization:
117
6
      break;
118
46
    }
119
46
  }
120
43
121
43
  // Ensure we dump at least one decl for each specialization.
122
43
  if (!DumpedAny)
123
3
    NodeDumper.dumpDeclRef(D);
124
43
}
void clang::ASTDumper::dumpTemplateDeclSpecialization<clang::ClassTemplateSpecializationDecl>(clang::ClassTemplateSpecializationDecl const*, bool, bool)
Line
Count
Source
87
103
                                               bool DumpRefOnly) {
88
103
  bool DumpedAny = false;
89
190
  for (const auto *RedeclWithBadType : D->redecls()) {
90
190
    // FIXME: The redecls() range sometimes has elements of a less-specific
91
190
    // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
92
190
    // us TagDecls, and should give CXXRecordDecls).
93
190
    auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
94
190
    if (!Redecl) {
95
85
      // Found the injected-class-name for a class template. This will be dumped
96
85
      // as part of its surrounding class so we don't need to dump it here.
97
85
      assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
98
85
             "expected an injected-class-name");
99
85
      continue;
100
85
    }
101
105
102
105
    switch (Redecl->getTemplateSpecializationKind()) {
103
10
    case TSK_ExplicitInstantiationDeclaration:
104
10
    case TSK_ExplicitInstantiationDefinition:
105
10
      if (!DumpExplicitInst)
106
10
        break;
107
0
      LLVM_FALLTHROUGH;
108
86
    case TSK_Undeclared:
109
86
    case TSK_ImplicitInstantiation:
110
86
      if (DumpRefOnly)
111
5
        NodeDumper.dumpDeclRef(Redecl);
112
81
      else
113
81
        Visit(Redecl);
114
86
      DumpedAny = true;
115
86
      break;
116
86
    case TSK_ExplicitSpecialization:
117
9
      break;
118
105
    }
119
105
  }
120
103
121
103
  // Ensure we dump at least one decl for each specialization.
122
103
  if (!DumpedAny)
123
19
    NodeDumper.dumpDeclRef(D);
124
103
}
void clang::ASTDumper::dumpTemplateDeclSpecialization<clang::VarTemplateSpecializationDecl>(clang::VarTemplateSpecializationDecl const*, bool, bool)
Line
Count
Source
87
2
                                               bool DumpRefOnly) {
88
2
  bool DumpedAny = false;
89
4
  for (const auto *RedeclWithBadType : D->redecls()) {
90
4
    // FIXME: The redecls() range sometimes has elements of a less-specific
91
4
    // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
92
4
    // us TagDecls, and should give CXXRecordDecls).
93
4
    auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
94
4
    if (!Redecl) {
95
0
      // Found the injected-class-name for a class template. This will be dumped
96
0
      // as part of its surrounding class so we don't need to dump it here.
97
0
      assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
98
0
             "expected an injected-class-name");
99
0
      continue;
100
0
    }
101
4
102
4
    switch (Redecl->getTemplateSpecializationKind()) {
103
0
    case TSK_ExplicitInstantiationDeclaration:
104
0
    case TSK_ExplicitInstantiationDefinition:
105
0
      if (!DumpExplicitInst)
106
0
        break;
107
0
      LLVM_FALLTHROUGH;
108
4
    case TSK_Undeclared:
109
4
    case TSK_ImplicitInstantiation:
110
4
      if (DumpRefOnly)
111
2
        NodeDumper.dumpDeclRef(Redecl);
112
2
      else
113
2
        Visit(Redecl);
114
4
      DumpedAny = true;
115
4
      break;
116
4
    case TSK_ExplicitSpecialization:
117
0
      break;
118
4
    }
119
4
  }
120
2
121
2
  // Ensure we dump at least one decl for each specialization.
122
2
  if (!DumpedAny)
123
0
    NodeDumper.dumpDeclRef(D);
124
2
}
125
126
template <typename TemplateDecl>
127
255
void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
128
255
  dumpTemplateParameters(D->getTemplateParameters());
129
255
130
255
  Visit(D->getTemplatedDecl());
131
255
132
255
  for (const auto *Child : D->specializations())
133
148
    dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
134
148
                                   !D->isCanonicalDecl());
135
255
}
void clang::ASTDumper::dumpTemplateDecl<clang::FunctionTemplateDecl>(clang::FunctionTemplateDecl const*, bool)
Line
Count
Source
127
114
void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
128
114
  dumpTemplateParameters(D->getTemplateParameters());
129
114
130
114
  Visit(D->getTemplatedDecl());
131
114
132
114
  for (const auto *Child : D->specializations())
133
43
    dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
134
43
                                   !D->isCanonicalDecl());
135
114
}
void clang::ASTDumper::dumpTemplateDecl<clang::ClassTemplateDecl>(clang::ClassTemplateDecl const*, bool)
Line
Count
Source
127
137
void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
128
137
  dumpTemplateParameters(D->getTemplateParameters());
129
137
130
137
  Visit(D->getTemplatedDecl());
131
137
132
137
  for (const auto *Child : D->specializations())
133
103
    dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
134
103
                                   !D->isCanonicalDecl());
135
137
}
void clang::ASTDumper::dumpTemplateDecl<clang::VarTemplateDecl>(clang::VarTemplateDecl const*, bool)
Line
Count
Source
127
4
void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
128
4
  dumpTemplateParameters(D->getTemplateParameters());
129
4
130
4
  Visit(D->getTemplatedDecl());
131
4
132
4
  for (const auto *Child : D->specializations())
133
2
    dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
134
2
                                   !D->isCanonicalDecl());
135
4
}
136
137
114
void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
138
114
  // FIXME: We don't add a declaration of a function template specialization
139
114
  // to its context when it's explicitly instantiated, so dump explicit
140
114
  // instantiations when we dump the template itself.
141
114
  dumpTemplateDecl(D, true);
142
114
}
143
144
137
void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
145
137
  dumpTemplateDecl(D, false);
146
137
}
147
148
4
void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
149
4
  dumpTemplateDecl(D, false);
150
4
}
151
152
//===----------------------------------------------------------------------===//
153
// Type method implementations
154
//===----------------------------------------------------------------------===//
155
156
0
void QualType::dump(const char *msg) const {
157
0
  if (msg)
158
0
    llvm::errs() << msg << ": ";
159
0
  dump();
160
0
}
161
162
0
LLVM_DUMP_METHOD void QualType::dump() const { dump(llvm::errs()); }
163
164
4
LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS) const {
165
4
  ASTDumper Dumper(OS, nullptr, nullptr);
166
4
  Dumper.Visit(*this);
167
4
}
168
169
0
LLVM_DUMP_METHOD void Type::dump() const { dump(llvm::errs()); }
170
171
0
LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS) const {
172
0
  QualType(this, 0).dump(OS);
173
0
}
174
175
//===----------------------------------------------------------------------===//
176
// Decl method implementations
177
//===----------------------------------------------------------------------===//
178
179
18
LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }
180
181
LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,
182
1.13k
                                 ASTDumpOutputFormat Format) const {
183
1.13k
  ASTContext &Ctx = getASTContext();
184
1.13k
  const SourceManager &SM = Ctx.getSourceManager();
185
1.13k
186
1.13k
  if (ADOF_JSON == Format) {
187
122
    JSONDumper P(OS, SM, Ctx, Ctx.getPrintingPolicy(),
188
122
                 &Ctx.getCommentCommandTraits());
189
122
    (void)Deserialize; // FIXME?
190
122
    P.Visit(this);
191
1.01k
  } else {
192
1.01k
    ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &SM,
193
1.01k
                SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy());
194
1.01k
    P.setDeserialize(Deserialize);
195
1.01k
    P.Visit(this);
196
1.01k
  }
197
1.13k
}
198
199
0
LLVM_DUMP_METHOD void Decl::dumpColor() const {
200
0
  const ASTContext &Ctx = getASTContext();
201
0
  ASTDumper P(llvm::errs(), &Ctx.getCommentCommandTraits(),
202
0
              &Ctx.getSourceManager(), /*ShowColors*/ true,
203
0
              Ctx.getPrintingPolicy());
204
0
  P.Visit(this);
205
0
}
206
207
0
LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
208
0
  dumpLookups(llvm::errs());
209
0
}
210
211
LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
212
                                               bool DumpDecls,
213
7
                                               bool Deserialize) const {
214
7
  const DeclContext *DC = this;
215
13
  while (!DC->isTranslationUnit())
216
6
    DC = DC->getParent();
217
7
  ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
218
7
  const SourceManager &SM = Ctx.getSourceManager();
219
7
  ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager(),
220
7
              SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy());
221
7
  P.setDeserialize(Deserialize);
222
7
  P.dumpLookups(this, DumpDecls);
223
7
}
224
225
//===----------------------------------------------------------------------===//
226
// Stmt method implementations
227
//===----------------------------------------------------------------------===//
228
229
0
LLVM_DUMP_METHOD void Stmt::dump(SourceManager &SM) const {
230
0
  dump(llvm::errs(), SM);
231
0
}
232
233
1
LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
234
1
  ASTDumper P(OS, nullptr, &SM);
235
1
  P.Visit(this);
236
1
}
237
238
0
LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS) const {
239
0
  ASTDumper P(OS, nullptr, nullptr);
240
0
  P.Visit(this);
241
0
}
242
243
11
LLVM_DUMP_METHOD void Stmt::dump() const {
244
11
  ASTDumper P(llvm::errs(), nullptr, nullptr);
245
11
  P.Visit(this);
246
11
}
247
248
0
LLVM_DUMP_METHOD void Stmt::dumpColor() const {
249
0
  ASTDumper P(llvm::errs(), nullptr, nullptr, /*ShowColors*/true);
250
0
  P.Visit(this);
251
0
}
252
253
//===----------------------------------------------------------------------===//
254
// Comment method implementations
255
//===----------------------------------------------------------------------===//
256
257
0
LLVM_DUMP_METHOD void Comment::dump() const {
258
0
  dump(llvm::errs(), nullptr, nullptr);
259
0
}
260
261
0
LLVM_DUMP_METHOD void Comment::dump(const ASTContext &Context) const {
262
0
  dump(llvm::errs(), &Context.getCommentCommandTraits(),
263
0
       &Context.getSourceManager());
264
0
}
265
266
void Comment::dump(raw_ostream &OS, const CommandTraits *Traits,
267
79
                   const SourceManager *SM) const {
268
79
  const FullComment *FC = dyn_cast<FullComment>(this);
269
79
  if (!FC)
270
0
    return;
271
79
  ASTDumper D(OS, Traits, SM);
272
79
  D.Visit(FC, FC);
273
79
}
274
275
0
LLVM_DUMP_METHOD void Comment::dumpColor() const {
276
0
  const FullComment *FC = dyn_cast<FullComment>(this);
277
0
  if (!FC)
278
0
    return;
279
0
  ASTDumper D(llvm::errs(), nullptr, nullptr, /*ShowColors*/true);
280
0
  D.Visit(FC, FC);
281
0
}