xref: /minix3/external/bsd/llvm/dist/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc //===-- ModelInjector.cpp ---------------------------------------*- C++ -*-===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*0a6a1f1dSLionel Sambuc // License. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc 
10*0a6a1f1dSLionel Sambuc #include "ModelInjector.h"
11*0a6a1f1dSLionel Sambuc #include "clang/AST/Decl.h"
12*0a6a1f1dSLionel Sambuc #include "clang/Basic/IdentifierTable.h"
13*0a6a1f1dSLionel Sambuc #include "clang/Frontend/ASTUnit.h"
14*0a6a1f1dSLionel Sambuc #include "clang/Frontend/CompilerInstance.h"
15*0a6a1f1dSLionel Sambuc #include "clang/Frontend/FrontendAction.h"
16*0a6a1f1dSLionel Sambuc #include "clang/Lex/Preprocessor.h"
17*0a6a1f1dSLionel Sambuc #include "clang/Serialization/ASTReader.h"
18*0a6a1f1dSLionel Sambuc #include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
19*0a6a1f1dSLionel Sambuc #include "llvm/ADT/STLExtras.h"
20*0a6a1f1dSLionel Sambuc #include "llvm/Support/CrashRecoveryContext.h"
21*0a6a1f1dSLionel Sambuc #include "llvm/Support/FileSystem.h"
22*0a6a1f1dSLionel Sambuc #include <string>
23*0a6a1f1dSLionel Sambuc #include <utility>
24*0a6a1f1dSLionel Sambuc 
25*0a6a1f1dSLionel Sambuc using namespace clang;
26*0a6a1f1dSLionel Sambuc using namespace ento;
27*0a6a1f1dSLionel Sambuc 
ModelInjector(CompilerInstance & CI)28*0a6a1f1dSLionel Sambuc ModelInjector::ModelInjector(CompilerInstance &CI) : CI(CI) {}
29*0a6a1f1dSLionel Sambuc 
getBody(const FunctionDecl * D)30*0a6a1f1dSLionel Sambuc Stmt *ModelInjector::getBody(const FunctionDecl *D) {
31*0a6a1f1dSLionel Sambuc   onBodySynthesis(D);
32*0a6a1f1dSLionel Sambuc   return Bodies[D->getName()];
33*0a6a1f1dSLionel Sambuc }
34*0a6a1f1dSLionel Sambuc 
getBody(const ObjCMethodDecl * D)35*0a6a1f1dSLionel Sambuc Stmt *ModelInjector::getBody(const ObjCMethodDecl *D) {
36*0a6a1f1dSLionel Sambuc   onBodySynthesis(D);
37*0a6a1f1dSLionel Sambuc   return Bodies[D->getName()];
38*0a6a1f1dSLionel Sambuc }
39*0a6a1f1dSLionel Sambuc 
onBodySynthesis(const NamedDecl * D)40*0a6a1f1dSLionel Sambuc void ModelInjector::onBodySynthesis(const NamedDecl *D) {
41*0a6a1f1dSLionel Sambuc 
42*0a6a1f1dSLionel Sambuc   // FIXME: what about overloads? Declarations can be used as keys but what
43*0a6a1f1dSLionel Sambuc   // about file name index? Mangled names may not be suitable for that either.
44*0a6a1f1dSLionel Sambuc   if (Bodies.count(D->getName()) != 0)
45*0a6a1f1dSLionel Sambuc     return;
46*0a6a1f1dSLionel Sambuc 
47*0a6a1f1dSLionel Sambuc   SourceManager &SM = CI.getSourceManager();
48*0a6a1f1dSLionel Sambuc   FileID mainFileID = SM.getMainFileID();
49*0a6a1f1dSLionel Sambuc 
50*0a6a1f1dSLionel Sambuc   AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts();
51*0a6a1f1dSLionel Sambuc   llvm::StringRef modelPath = analyzerOpts->Config["model-path"];
52*0a6a1f1dSLionel Sambuc 
53*0a6a1f1dSLionel Sambuc   llvm::SmallString<128> fileName;
54*0a6a1f1dSLionel Sambuc 
55*0a6a1f1dSLionel Sambuc   if (!modelPath.empty())
56*0a6a1f1dSLionel Sambuc     fileName =
57*0a6a1f1dSLionel Sambuc         llvm::StringRef(modelPath.str() + "/" + D->getName().str() + ".model");
58*0a6a1f1dSLionel Sambuc   else
59*0a6a1f1dSLionel Sambuc     fileName = llvm::StringRef(D->getName().str() + ".model");
60*0a6a1f1dSLionel Sambuc 
61*0a6a1f1dSLionel Sambuc   if (!llvm::sys::fs::exists(fileName.str())) {
62*0a6a1f1dSLionel Sambuc     Bodies[D->getName()] = nullptr;
63*0a6a1f1dSLionel Sambuc     return;
64*0a6a1f1dSLionel Sambuc   }
65*0a6a1f1dSLionel Sambuc 
66*0a6a1f1dSLionel Sambuc   IntrusiveRefCntPtr<CompilerInvocation> Invocation(
67*0a6a1f1dSLionel Sambuc       new CompilerInvocation(CI.getInvocation()));
68*0a6a1f1dSLionel Sambuc 
69*0a6a1f1dSLionel Sambuc   FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
70*0a6a1f1dSLionel Sambuc   InputKind IK = IK_CXX; // FIXME
71*0a6a1f1dSLionel Sambuc   FrontendOpts.Inputs.clear();
72*0a6a1f1dSLionel Sambuc   FrontendOpts.Inputs.push_back(FrontendInputFile(fileName, IK));
73*0a6a1f1dSLionel Sambuc   FrontendOpts.DisableFree = true;
74*0a6a1f1dSLionel Sambuc 
75*0a6a1f1dSLionel Sambuc   Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
76*0a6a1f1dSLionel Sambuc 
77*0a6a1f1dSLionel Sambuc   // Modules are parsed by a separate CompilerInstance, so this code mimics that
78*0a6a1f1dSLionel Sambuc   // behavior for models
79*0a6a1f1dSLionel Sambuc   CompilerInstance Instance;
80*0a6a1f1dSLionel Sambuc   Instance.setInvocation(&*Invocation);
81*0a6a1f1dSLionel Sambuc   Instance.createDiagnostics(
82*0a6a1f1dSLionel Sambuc       new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
83*0a6a1f1dSLionel Sambuc       /*ShouldOwnClient=*/true);
84*0a6a1f1dSLionel Sambuc 
85*0a6a1f1dSLionel Sambuc   Instance.getDiagnostics().setSourceManager(&SM);
86*0a6a1f1dSLionel Sambuc 
87*0a6a1f1dSLionel Sambuc   Instance.setVirtualFileSystem(&CI.getVirtualFileSystem());
88*0a6a1f1dSLionel Sambuc 
89*0a6a1f1dSLionel Sambuc   // The instance wants to take ownership, however DisableFree frontend option
90*0a6a1f1dSLionel Sambuc   // is set to true to avoid double free issues
91*0a6a1f1dSLionel Sambuc   Instance.setFileManager(&CI.getFileManager());
92*0a6a1f1dSLionel Sambuc   Instance.setSourceManager(&SM);
93*0a6a1f1dSLionel Sambuc   Instance.setPreprocessor(&CI.getPreprocessor());
94*0a6a1f1dSLionel Sambuc   Instance.setASTContext(&CI.getASTContext());
95*0a6a1f1dSLionel Sambuc 
96*0a6a1f1dSLionel Sambuc   Instance.getPreprocessor().InitializeForModelFile();
97*0a6a1f1dSLionel Sambuc 
98*0a6a1f1dSLionel Sambuc   ParseModelFileAction parseModelFile(Bodies);
99*0a6a1f1dSLionel Sambuc 
100*0a6a1f1dSLionel Sambuc   const unsigned ThreadStackSize = 8 << 20;
101*0a6a1f1dSLionel Sambuc   llvm::CrashRecoveryContext CRC;
102*0a6a1f1dSLionel Sambuc 
103*0a6a1f1dSLionel Sambuc   CRC.RunSafelyOnThread([&]() { Instance.ExecuteAction(parseModelFile); },
104*0a6a1f1dSLionel Sambuc                         ThreadStackSize);
105*0a6a1f1dSLionel Sambuc 
106*0a6a1f1dSLionel Sambuc   Instance.getPreprocessor().FinalizeForModelFile();
107*0a6a1f1dSLionel Sambuc 
108*0a6a1f1dSLionel Sambuc   Instance.resetAndLeakSourceManager();
109*0a6a1f1dSLionel Sambuc   Instance.resetAndLeakFileManager();
110*0a6a1f1dSLionel Sambuc   Instance.resetAndLeakPreprocessor();
111*0a6a1f1dSLionel Sambuc 
112*0a6a1f1dSLionel Sambuc   // The preprocessor enters to the main file id when parsing is started, so
113*0a6a1f1dSLionel Sambuc   // the main file id is changed to the model file during parsing and it needs
114*0a6a1f1dSLionel Sambuc   // to be reseted to the former main file id after parsing of the model file
115*0a6a1f1dSLionel Sambuc   // is done.
116*0a6a1f1dSLionel Sambuc   SM.setMainFileID(mainFileID);
117*0a6a1f1dSLionel Sambuc }
118