1176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//===-- ModelInjector.cpp ---------------------------------------*- C++ -*-===// 2176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// 3176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// The LLVM Compiler Infrastructure 4176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// 5176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// This file is distributed under the University of Illinois Open Source 6176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// License. See LICENSE.TXT for details. 7176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// 8176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//===----------------------------------------------------------------------===// 9176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 10176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "ModelInjector.h" 110e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include "clang/AST/Decl.h" 120e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include "clang/Basic/IdentifierTable.h" 13176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "clang/Frontend/ASTUnit.h" 14176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "clang/Frontend/CompilerInstance.h" 15176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "clang/Frontend/FrontendAction.h" 16176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "clang/Lex/Preprocessor.h" 170e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include "clang/Serialization/ASTReader.h" 180e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" 190e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include "llvm/ADT/STLExtras.h" 20176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "llvm/Support/CrashRecoveryContext.h" 21176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "llvm/Support/FileSystem.h" 220e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include <string> 230e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include <utility> 24176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 25176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesusing namespace clang; 26176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesusing namespace ento; 27176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 28176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesModelInjector::ModelInjector(CompilerInstance &CI) : CI(CI) {} 29176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 30176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesStmt *ModelInjector::getBody(const FunctionDecl *D) { 31176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines onBodySynthesis(D); 32176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return Bodies[D->getName()]; 33176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 34176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 35176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesStmt *ModelInjector::getBody(const ObjCMethodDecl *D) { 36176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines onBodySynthesis(D); 37176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return Bodies[D->getName()]; 38176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 39176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 40176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesvoid ModelInjector::onBodySynthesis(const NamedDecl *D) { 41176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 42176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // FIXME: what about overloads? Declarations can be used as keys but what 43176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // about file name index? Mangled names may not be suitable for that either. 44176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Bodies.count(D->getName()) != 0) 45176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return; 46176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 47176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceManager &SM = CI.getSourceManager(); 48176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines FileID mainFileID = SM.getMainFileID(); 49176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 50176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts(); 51176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines llvm::StringRef modelPath = analyzerOpts->Config["model-path"]; 52176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 53176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines llvm::SmallString<128> fileName; 54176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 55176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!modelPath.empty()) 56176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines fileName = 57176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines llvm::StringRef(modelPath.str() + "/" + D->getName().str() + ".model"); 58176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else 59176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines fileName = llvm::StringRef(D->getName().str() + ".model"); 60176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 61176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!llvm::sys::fs::exists(fileName.str())) { 62176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Bodies[D->getName()] = nullptr; 63176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return; 64176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 65176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 66176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines IntrusiveRefCntPtr<CompilerInvocation> Invocation( 67176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines new CompilerInvocation(CI.getInvocation())); 68176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 69176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines FrontendOptions &FrontendOpts = Invocation->getFrontendOpts(); 70176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines InputKind IK = IK_CXX; // FIXME 71176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines FrontendOpts.Inputs.clear(); 72176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines FrontendOpts.Inputs.push_back(FrontendInputFile(fileName, IK)); 73176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines FrontendOpts.DisableFree = true; 74176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 75176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Invocation->getDiagnosticOpts().VerifyDiagnostics = 0; 76176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 77176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // Modules are parsed by a separate CompilerInstance, so this code mimics that 78176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // behavior for models 79176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CompilerInstance Instance; 80176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.setInvocation(&*Invocation); 81176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.createDiagnostics( 82176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()), 83176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /*ShouldOwnClient=*/true); 84176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 85176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.getDiagnostics().setSourceManager(&SM); 86176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 87176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.setVirtualFileSystem(&CI.getVirtualFileSystem()); 88176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 89176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // The instance wants to take ownership, however DisableFree frontend option 90176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // is set to true to avoid double free issues 91176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.setFileManager(&CI.getFileManager()); 92176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.setSourceManager(&SM); 93176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.setPreprocessor(&CI.getPreprocessor()); 94176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.setASTContext(&CI.getASTContext()); 95176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 96176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.getPreprocessor().InitializeForModelFile(); 97176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 98176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ParseModelFileAction parseModelFile(Bodies); 99176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 100176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const unsigned ThreadStackSize = 8 << 20; 101176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines llvm::CrashRecoveryContext CRC; 102176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 103176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CRC.RunSafelyOnThread([&]() { Instance.ExecuteAction(parseModelFile); }, 104176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ThreadStackSize); 105176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 106176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.getPreprocessor().FinalizeForModelFile(); 107176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 108176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.resetAndLeakSourceManager(); 109176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.resetAndLeakFileManager(); 110176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Instance.resetAndLeakPreprocessor(); 111176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 112176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // The preprocessor enters to the main file id when parsing is started, so 113176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // the main file id is changed to the model file during parsing and it needs 114176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // to be reseted to the former main file id after parsing of the model file 115176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // is done. 116176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SM.setMainFileID(mainFileID); 117176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 118