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