Coverage Report

Created: 2019-07-24 05:18

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