Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ClangExtDefMapGen.cpp -----------------------------------------------===//
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
// Clang tool which creates a list of defined functions and the files in which
10
// they are defined.
11
//
12
//===--------------------------------------------------------------------===//
13
14
#include "clang/AST/ASTConsumer.h"
15
#include "clang/AST/ASTContext.h"
16
#include "clang/Basic/SourceManager.h"
17
#include "clang/CrossTU/CrossTranslationUnit.h"
18
#include "clang/Frontend/CompilerInstance.h"
19
#include "clang/Frontend/FrontendActions.h"
20
#include "clang/Tooling/CommonOptionsParser.h"
21
#include "clang/Tooling/Tooling.h"
22
#include "llvm/Support/CommandLine.h"
23
#include "llvm/Support/Signals.h"
24
#include <sstream>
25
#include <string>
26
27
using namespace llvm;
28
using namespace clang;
29
using namespace clang::cross_tu;
30
using namespace clang::tooling;
31
32
static cl::OptionCategory ClangExtDefMapGenCategory("clang-extdefmapgen options");
33
34
class MapExtDefNamesConsumer : public ASTConsumer {
35
public:
36
  MapExtDefNamesConsumer(ASTContext &Context)
37
1
      : Ctx(Context), SM(Context.getSourceManager()) {}
38
39
1
  ~MapExtDefNamesConsumer() {
40
1
    // Flush results to standard output.
41
1
    llvm::outs() << createCrossTUIndexString(Index);
42
1
  }
43
44
1
  void HandleTranslationUnit(ASTContext &Context) override {
45
1
    handleDecl(Context.getTranslationUnitDecl());
46
1
  }
47
48
private:
49
  void handleDecl(const Decl *D);
50
  void addIfInMain(const DeclaratorDecl *DD, SourceLocation defStart);
51
52
  ASTContext &Ctx;
53
  SourceManager &SM;
54
  llvm::StringMap<std::string> Index;
55
  std::string CurrentFileName;
56
};
57
58
37
void MapExtDefNamesConsumer::handleDecl(const Decl *D) {
59
37
  if (!D)
60
0
    return;
61
37
62
37
  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
63
4
    if (FD->isThisDeclarationADefinition())
64
4
      if (const Stmt *Body = FD->getBody())
65
2
        addIfInMain(FD, Body->getBeginLoc());
66
33
  } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
67
10
    if (cross_tu::containsConst(VD, Ctx) && 
VD->hasInit()9
)
68
8
      if (const Expr *Init = VD->getInit())
69
8
        addIfInMain(VD, Init->getBeginLoc());
70
10
  }
71
37
72
37
  if (const auto *DC = dyn_cast<DeclContext>(D))
73
14
    for (const Decl *D : DC->decls())
74
36
      handleDecl(D);
75
37
}
76
77
void MapExtDefNamesConsumer::addIfInMain(const DeclaratorDecl *DD,
78
10
                                         SourceLocation defStart) {
79
10
  llvm::Optional<std::string> LookupName =
80
10
      CrossTranslationUnitContext::getLookupName(DD);
81
10
  if (!LookupName)
82
1
    return;
83
9
  assert(!LookupName->empty() && "Lookup name should be non-empty.");
84
9
85
9
  if (CurrentFileName.empty()) {
86
1
    CurrentFileName = std::string(
87
1
        SM.getFileEntryForID(SM.getMainFileID())->tryGetRealPathName());
88
1
    if (CurrentFileName.empty())
89
0
      CurrentFileName = "invalid_file";
90
1
  }
91
9
92
9
  switch (DD->getLinkageInternal()) {
93
7
  case ExternalLinkage:
94
7
  case VisibleNoLinkage:
95
7
  case UniqueExternalLinkage:
96
7
    if (SM.isInMainFile(defStart))
97
7
      Index[*LookupName] = CurrentFileName;
98
7
    break;
99
7
  default:
100
2
    break;
101
9
  }
102
9
}
103
104
class MapExtDefNamesAction : public ASTFrontendAction {
105
protected:
106
  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
107
1
                                                 llvm::StringRef) {
108
1
    return std::make_unique<MapExtDefNamesConsumer>(CI.getASTContext());
109
1
  }
110
};
111
112
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
113
114
10.8k
int main(int argc, const char **argv) {
115
10.8k
  // Print a stack trace if we signal out.
116
10.8k
  sys::PrintStackTraceOnErrorSignal(argv[0], false);
117
10.8k
  PrettyStackTraceProgram X(argc, argv);
118
10.8k
119
10.8k
  const char *Overview = "\nThis tool collects the USR name and location "
120
10.8k
                         "of external definitions in the source files "
121
10.8k
                         "(excluding headers).\n";
122
10.8k
  CommonOptionsParser OptionsParser(argc, argv, ClangExtDefMapGenCategory,
123
10.8k
                                    cl::ZeroOrMore, Overview);
124
10.8k
125
10.8k
  ClangTool Tool(OptionsParser.getCompilations(),
126
10.8k
                 OptionsParser.getSourcePathList());
127
10.8k
128
10.8k
  return Tool.run(newFrontendActionFactory<MapExtDefNamesAction>().get());
129
10.8k
}