Coverage Report

Created: 2020-09-22 08:39

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- ModelInjector.cpp ---------------------------------------*- C++ -*-===//
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
#include "ModelInjector.h"
10
#include "clang/AST/Decl.h"
11
#include "clang/Basic/IdentifierTable.h"
12
#include "clang/Basic/LangStandard.h"
13
#include "clang/Basic/Stack.h"
14
#include "clang/AST/DeclObjC.h"
15
#include "clang/Frontend/ASTUnit.h"
16
#include "clang/Frontend/CompilerInstance.h"
17
#include "clang/Frontend/FrontendAction.h"
18
#include "clang/Lex/Preprocessor.h"
19
#include "clang/Serialization/ASTReader.h"
20
#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
21
#include "llvm/ADT/STLExtras.h"
22
#include "llvm/Support/CrashRecoveryContext.h"
23
#include "llvm/Support/FileSystem.h"
24
#include <utility>
25
26
using namespace clang;
27
using namespace ento;
28
29
1.33k
ModelInjector::ModelInjector(CompilerInstance &CI) : CI(CI) {}
30
31
17.2k
Stmt *ModelInjector::getBody(const FunctionDecl *D) {
32
17.2k
  onBodySynthesis(D);
33
17.2k
  return Bodies[D->getName()];
34
17.2k
}
35
36
0
Stmt *ModelInjector::getBody(const ObjCMethodDecl *D) {
37
0
  onBodySynthesis(D);
38
0
  return Bodies[D->getName()];
39
0
}
40
41
17.2k
void ModelInjector::onBodySynthesis(const NamedDecl *D) {
42
43
  // FIXME: what about overloads? Declarations can be used as keys but what
44
  // about file name index? Mangled names may not be suitable for that either.
45
17.2k
  if (Bodies.count(D->getName()) != 0)
46
1.58k
    return;
47
48
15.6k
  SourceManager &SM = CI.getSourceManager();
49
15.6k
  FileID mainFileID = SM.getMainFileID();
50
51
15.6k
  AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts();
52
15.6k
  llvm::StringRef modelPath = analyzerOpts->ModelPath;
53
54
15.6k
  llvm::SmallString<128> fileName;
55
56
15.6k
  if (!modelPath.empty())
57
4
    fileName =
58
4
        llvm::StringRef(modelPath.str() + "/" + D->getName().str() + ".model");
59
15.6k
  else
60
15.6k
    fileName = llvm::StringRef(D->getName().str() + ".model");
61
62
15.6k
  if (!llvm::sys::fs::exists(fileName.str())) {
63
15.6k
    Bodies[D->getName()] = nullptr;
64
15.6k
    return;
65
15.6k
  }
66
67
2
  auto Invocation = std::make_shared<CompilerInvocation>(CI.getInvocation());
68
69
2
  FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
70
2
  InputKind IK = Language::CXX; // FIXME
71
2
  FrontendOpts.Inputs.clear();
72
2
  FrontendOpts.Inputs.emplace_back(fileName, IK);
73
2
  FrontendOpts.DisableFree = true;
74
75
2
  Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
76
77
  // Modules are parsed by a separate CompilerInstance, so this code mimics that
78
  // behavior for models
79
2
  CompilerInstance Instance(CI.getPCHContainerOperations());
80
2
  Instance.setInvocation(std::move(Invocation));
81
2
  Instance.createDiagnostics(
82
2
      new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
83
2
      /*ShouldOwnClient=*/true);
84
85
2
  Instance.getDiagnostics().setSourceManager(&SM);
86
87
  // The instance wants to take ownership, however DisableFree frontend option
88
  // is set to true to avoid double free issues
89
2
  Instance.setFileManager(&CI.getFileManager());
90
2
  Instance.setSourceManager(&SM);
91
2
  Instance.setPreprocessor(CI.getPreprocessorPtr());
92
2
  Instance.setASTContext(&CI.getASTContext());
93
94
2
  Instance.getPreprocessor().InitializeForModelFile();
95
96
2
  ParseModelFileAction parseModelFile(Bodies);
97
98
2
  llvm::CrashRecoveryContext CRC;
99
100
2
  CRC.RunSafelyOnThread([&]() { Instance.ExecuteAction(parseModelFile); },
101
2
                        DesiredStackSize);
102
103
2
  Instance.getPreprocessor().FinalizeForModelFile();
104
105
2
  Instance.resetAndLeakSourceManager();
106
2
  Instance.resetAndLeakFileManager();
107
2
  Instance.resetAndLeakPreprocessor();
108
109
  // The preprocessor enters to the main file id when parsing is started, so
110
  // the main file id is changed to the model file during parsing and it needs
111
  // to be reset to the former main file id after parsing of the model file
112
  // is done.
113
2
  SM.setMainFileID(mainFileID);
114
2
}