Coverage Report

Created: 2023-09-12 09:32

/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.79k
ModelInjector::ModelInjector(CompilerInstance &CI) : CI(CI) {}
30
31
20.8k
Stmt *ModelInjector::getBody(const FunctionDecl *D) {
32
20.8k
  onBodySynthesis(D);
33
20.8k
  return Bodies[D->getName()];
34
20.8k
}
35
36
0
Stmt *ModelInjector::getBody(const ObjCMethodDecl *D) {
37
0
  onBodySynthesis(D);
38
0
  return Bodies[D->getName()];
39
0
}
40
41
20.8k
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
20.8k
  if (Bodies.count(D->getName()) != 0)
46
1.70k
    return;
47
48
19.1k
  SourceManager &SM = CI.getSourceManager();
49
19.1k
  FileID mainFileID = SM.getMainFileID();
50
51
19.1k
  llvm::StringRef modelPath = CI.getAnalyzerOpts().ModelPath;
52
53
19.1k
  llvm::SmallString<128> fileName;
54
55
19.1k
  if (!modelPath.empty())
56
4
    fileName =
57
4
        llvm::StringRef(modelPath.str() + "/" + D->getName().str() + ".model");
58
19.1k
  else
59
19.1k
    fileName = llvm::StringRef(D->getName().str() + ".model");
60
61
19.1k
  if (!llvm::sys::fs::exists(fileName.str())) {
62
19.1k
    Bodies[D->getName()] = nullptr;
63
19.1k
    return;
64
19.1k
  }
65
66
2
  auto Invocation = std::make_shared<CompilerInvocation>(CI.getInvocation());
67
68
2
  FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
69
2
  InputKind IK = Language::CXX; // FIXME
70
2
  FrontendOpts.Inputs.clear();
71
2
  FrontendOpts.Inputs.emplace_back(fileName, IK);
72
2
  FrontendOpts.DisableFree = true;
73
74
2
  Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
75
76
  // Modules are parsed by a separate CompilerInstance, so this code mimics that
77
  // behavior for models
78
2
  CompilerInstance Instance(CI.getPCHContainerOperations());
79
2
  Instance.setInvocation(std::move(Invocation));
80
2
  Instance.createDiagnostics(
81
2
      new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
82
2
      /*ShouldOwnClient=*/true);
83
84
2
  Instance.getDiagnostics().setSourceManager(&SM);
85
86
  // The instance wants to take ownership, however DisableFree frontend option
87
  // is set to true to avoid double free issues
88
2
  Instance.setFileManager(&CI.getFileManager());
89
2
  Instance.setSourceManager(&SM);
90
2
  Instance.setPreprocessor(CI.getPreprocessorPtr());
91
2
  Instance.setASTContext(&CI.getASTContext());
92
93
2
  Instance.getPreprocessor().InitializeForModelFile();
94
95
2
  ParseModelFileAction parseModelFile(Bodies);
96
97
2
  llvm::CrashRecoveryContext CRC;
98
99
2
  CRC.RunSafelyOnThread([&]() { Instance.ExecuteAction(parseModelFile); },
100
2
                        DesiredStackSize);
101
102
2
  Instance.getPreprocessor().FinalizeForModelFile();
103
104
2
  Instance.resetAndLeakSourceManager();
105
2
  Instance.resetAndLeakFileManager();
106
2
  Instance.resetAndLeakPreprocessor();
107
108
  // The preprocessor enters to the main file id when parsing is started, so
109
  // the main file id is changed to the model file during parsing and it needs
110
  // to be reset to the former main file id after parsing of the model file
111
  // is done.
112
2
  SM.setMainFileID(mainFileID);
113
2
}