@@ -65,78 +65,9 @@ bool RemoveItypes;
6565bool ForceItypes;
6666#endif
6767
68- static ClangTool *GlobalCTool = nullptr ;
69-
7068static CompilationDatabase *CurrCompDB = nullptr ;
7169static tooling::CommandLineArguments SourceFiles;
7270
73- template <typename T, typename V>
74- class GenericAction : public ASTFrontendAction {
75- public:
76- GenericAction (V &I) : Info(I) {}
77-
78- virtual std::unique_ptr<ASTConsumer>
79- CreateASTConsumer (CompilerInstance &Compiler, StringRef InFile) {
80- return std::unique_ptr<ASTConsumer>(new T (Info, &Compiler.getASTContext ()));
81- }
82-
83- private:
84- V &Info;
85- };
86-
87- template <typename T, typename V>
88- class RewriteAction : public ASTFrontendAction {
89- public:
90- RewriteAction (V &I) : Info(I) {}
91-
92- virtual std::unique_ptr<ASTConsumer>
93- CreateASTConsumer (CompilerInstance &Compiler, StringRef InFile) {
94- return std::unique_ptr<ASTConsumer>(new T (Info));
95- }
96-
97- private:
98- V &Info;
99- };
100-
101- template <typename T>
102- std::unique_ptr<FrontendActionFactory>
103- newFrontendActionFactoryA (ProgramInfo &I, bool VerifyTheseDiagnostics = false ) {
104- class ArgFrontendActionFactory : public FrontendActionFactory {
105- public:
106- explicit ArgFrontendActionFactory (ProgramInfo &I,
107- bool VerifyTheseDiagnostics)
108- : Info(I), VerifyTheseDiagnostics(VerifyTheseDiagnostics) {}
109-
110- std::unique_ptr<FrontendAction> create () override {
111- return std::unique_ptr<FrontendAction>(new T (Info));
112- }
113-
114- bool runInvocation (std::shared_ptr<CompilerInvocation> Invocation,
115- FileManager *Files,
116- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
117- DiagnosticConsumer *DiagConsumer) override {
118- if (VerifyTheseDiagnostics) {
119- // Mirroring the logic of clang::ParseDiagnosticArgs in
120- // clang/lib/Frontend/CompilerInvocation.cpp. In particular, note that
121- // VerifyPrefixes is assumed to be sorted, in case we add more in the
122- // future.
123- DiagnosticOptions &DiagOpts = Invocation->getDiagnosticOpts ();
124- DiagOpts.VerifyDiagnostics = true ;
125- DiagOpts.VerifyPrefixes .push_back (" expected" );
126- }
127- return FrontendActionFactory::runInvocation (
128- Invocation, Files, PCHContainerOps, DiagConsumer);
129- }
130-
131- private:
132- ProgramInfo &Info;
133- bool VerifyTheseDiagnostics;
134- };
135-
136- return std::unique_ptr<FrontendActionFactory>(
137- new ArgFrontendActionFactory (I, VerifyTheseDiagnostics));
138- }
139-
14071ArgumentsAdjuster getIgnoreCheckedPointerAdjuster () {
14172 return [](const CommandLineArguments &Args, StringRef /* unused*/ ) {
14273 CommandLineArguments AdjustedArgs;
@@ -154,13 +85,16 @@ ArgumentsAdjuster getIgnoreCheckedPointerAdjuster() {
15485 return AdjustedArgs;
15586 };
15687}
157-
158- static ClangTool &getGlobalClangTool () {
159- if (GlobalCTool == nullptr ) {
160- GlobalCTool = new ClangTool (*CurrCompDB, SourceFiles);
161- GlobalCTool->appendArgumentsAdjuster (getIgnoreCheckedPointerAdjuster ());
162- }
163- return *GlobalCTool;
88+ ArgumentsAdjuster addVerifyAdjuster () {
89+ return [](const CommandLineArguments &Args, StringRef /* unused*/ ) {
90+ CommandLineArguments AdjustedArgs (Args);
91+ if (std::find (AdjustedArgs.begin (),AdjustedArgs.end ()," -verify" )
92+ == AdjustedArgs.end ()) {
93+ AdjustedArgs.push_back (" -Xclang" );
94+ AdjustedArgs.push_back (" -verify" );
95+ }
96+ return AdjustedArgs;
97+ };
16498}
16599
166100void dumpConstraintOutputJson (const std::string &PostfixStr,
@@ -347,42 +281,53 @@ _3CInterface::_3CInterface(const struct _3COptions &CCopt,
347281 GlobalProgramInfo.getPerfStats ().startTotalTime ();
348282}
349283
350- bool _3CInterface::addVariables () {
284+ bool _3CInterface::parseASTs () {
351285
352286 std::lock_guard<std::mutex> Lock (InterfaceMutex);
353287
354- ClangTool &Tool = getGlobalClangTool ();
288+ auto *Tool = new ClangTool (*CurrCompDB, SourceFiles);
289+ Tool->appendArgumentsAdjuster (getIgnoreCheckedPointerAdjuster ());
290+ // TODO: This currently only enables compiler diagnostic verification.
291+ // see https://github.com/correctcomputation/checkedc-clang/issues/425
292+ // for status.
293+ if (VerifyDiagnosticOutput)
294+ Tool->appendArgumentsAdjuster (addVerifyAdjuster ());
355295
356- // 1a. Add Variables.
357- std::unique_ptr<ToolAction> AdderTool = newFrontendActionFactoryA<
358- GenericAction<VariableAdderConsumer, ProgramInfo>>(GlobalProgramInfo);
296+ // load the ASTs
297+ return !Tool-> buildASTs (ASTs);
298+ }
359299
360- if (AdderTool) {
361- int ToolExitCode = Tool.run (AdderTool.get ());
362- if (ToolExitCode != 0 )
363- return false ;
364- } else
365- llvm_unreachable (" No action" );
300+ bool _3CInterface::addVariables () {
366301
367- return true ;
302+ std::lock_guard<std::mutex> Lock (InterfaceMutex);
303+
304+ // 1. Add Variables.
305+ VariableAdderConsumer VA = VariableAdderConsumer (GlobalProgramInfo, nullptr );
306+ unsigned int Errs = 0 ;
307+ for (auto &TU : ASTs) {
308+ TU->enableSourceFileDiagnostics ();
309+ VA.HandleTranslationUnit (TU->getASTContext ());
310+ TU->getDiagnostics ().getClient ()->EndSourceFile ();
311+ Errs += TU->getDiagnostics ().getClient ()->getNumErrors ();
312+ }
313+
314+ return Errs == 0 ;
368315}
369316
370317bool _3CInterface::buildInitialConstraints () {
371318
372319 std::lock_guard<std::mutex> Lock (InterfaceMutex);
373320
374- ClangTool &Tool = getGlobalClangTool ();
375-
376- // 1b. Gather constraints.
377- std::unique_ptr<ToolAction> ConstraintTool = newFrontendActionFactoryA<
378- GenericAction<ConstraintBuilderConsumer, ProgramInfo>>(GlobalProgramInfo);
379-
380- if (ConstraintTool) {
381- int ToolExitCode = Tool.run (ConstraintTool.get ());
382- if (ToolExitCode != 0 )
383- return false ;
384- } else
385- llvm_unreachable (" No action" );
321+ // 2. Gather constraints.
322+ ConstraintBuilderConsumer CB = ConstraintBuilderConsumer (GlobalProgramInfo, nullptr );
323+ unsigned int Errs = 0 ;
324+ for (auto &TU : ASTs) {
325+ TU->enableSourceFileDiagnostics ();
326+ CB.HandleTranslationUnit (TU->getASTContext ());
327+ TU->getDiagnostics ().getClient ()->EndSourceFile ();
328+ Errs += TU->getDiagnostics ().getClient ()->getNumErrors ();
329+ }
330+ if (Errs > 0 ) return false ;
386331
387332 if (!GlobalProgramInfo.link ()) {
388333 errs () << " Linking failed!\n " ;
@@ -398,7 +343,7 @@ bool _3CInterface::solveConstraints() {
398343 std::lock_guard<std::mutex> Lock (InterfaceMutex);
399344 assert (ConstraintsBuilt && " Constraints not yet built. We need to call "
400345 " build constraint before trying to solve them." );
401- // 2 . Solve constraints.
346+ // 3 . Solve constraints.
402347 if (Verbose)
403348 errs () << " Solving constraints\n " ;
404349
@@ -420,7 +365,6 @@ bool _3CInterface::solveConstraints() {
420365 if (DumpIntermediate)
421366 dumpConstraintOutputJson (FINAL_OUTPUT_SUFFIX, GlobalProgramInfo);
422367
423- ClangTool &Tool = getGlobalClangTool ();
424368 if (AllTypes) {
425369 if (DebugArrSolver)
426370 GlobalProgramInfo.getABoundsInfo ().dumpAVarGraph (
@@ -430,31 +374,32 @@ bool _3CInterface::solveConstraints() {
430374 // bounds declarations.
431375 GlobalProgramInfo.getABoundsInfo ().performFlowAnalysis (&GlobalProgramInfo);
432376
433- // 3 . Infer the bounds based on calls to malloc and calloc
434- std::unique_ptr<ToolAction> ABInfTool = newFrontendActionFactoryA<
435- GenericAction<AllocBasedBoundsInference, ProgramInfo>>(
436- GlobalProgramInfo);
437- if (ABInfTool) {
438- int ToolExitCode = Tool. run (ABInfTool. get ());
439- if (ToolExitCode != 0 )
440- return false ;
441- } else
442- llvm_unreachable ( " No Action " ) ;
377+ // 4 . Infer the bounds based on calls to malloc and calloc
378+ AllocBasedBoundsInference ABBI = AllocBasedBoundsInference (GlobalProgramInfo, nullptr );
379+ unsigned int Errs = 0 ;
380+ for ( auto &TU : ASTs) {
381+ TU-> enableSourceFileDiagnostics ();
382+ ABBI. HandleTranslationUnit (TU-> getASTContext ());
383+ TU-> getDiagnostics (). getClient ()-> EndSourceFile ();
384+ Errs += TU-> getDiagnostics (). getClient ()-> getNumErrors () ;
385+ }
386+ if (Errs > 0 ) return false ;
443387
444388 // Propagate the information from allocator bounds.
445389 GlobalProgramInfo.getABoundsInfo ().performFlowAnalysis (&GlobalProgramInfo);
446390 }
447391
448- // 4 . Run intermediate tool hook to run visitors that need to be executed
392+ // 5 . Run intermediate tool hook to run visitors that need to be executed
449393 // after constraint solving but before rewriting.
450- std::unique_ptr<ToolAction> IMTool = newFrontendActionFactoryA<
451- GenericAction<IntermediateToolHook, ProgramInfo>>(GlobalProgramInfo);
452- if (IMTool) {
453- int ToolExitCode = Tool.run (IMTool.get ());
454- if (ToolExitCode != 0 )
455- return false ;
456- } else
457- llvm_unreachable (" No Action" );
394+ IntermediateToolHook ITH = IntermediateToolHook (GlobalProgramInfo, nullptr );
395+ unsigned int Errs = 0 ;
396+ for (auto &TU : ASTs) {
397+ TU->enableSourceFileDiagnostics ();
398+ ITH.HandleTranslationUnit (TU->getASTContext ());
399+ TU->getDiagnostics ().getClient ()->EndSourceFile ();
400+ Errs += TU->getDiagnostics ().getClient ()->getNumErrors ();
401+ }
402+ if (Errs > 0 ) return false ;
458403
459404 if (AllTypes) {
460405 // Propagate data-flow information for Array pointers.
@@ -497,48 +442,19 @@ bool _3CInterface::solveConstraints() {
497442 return true ;
498443}
499444
500- bool _3CInterface::writeConvertedFileToDisk (const std::string &FilePath) {
501- std::lock_guard<std::mutex> Lock (InterfaceMutex);
502- bool RetVal = false ;
503- if (std::find (SourceFiles.begin (), SourceFiles.end (), FilePath) !=
504- SourceFiles.end ()) {
505- RetVal = true ;
506- std::vector<std::string> SourceFiles;
507- SourceFiles.clear ();
508- SourceFiles.push_back (FilePath);
509- // Don't use global tool. Create a new tool for give single file.
510- ClangTool Tool (*CurrCompDB, SourceFiles);
511- Tool.appendArgumentsAdjuster (getIgnoreCheckedPointerAdjuster ());
512- std::unique_ptr<ToolAction> RewriteTool =
513- newFrontendActionFactoryA<RewriteAction<RewriteConsumer, ProgramInfo>>(
514- GlobalProgramInfo, VerifyDiagnosticOutput);
515-
516- if (RewriteTool) {
517- int ToolExitCode = Tool.run (RewriteTool.get ());
518- if (ToolExitCode != 0 )
519- RetVal = false ;
520- }
521- }
522- GlobalProgramInfo.getPerfStats ().endTotalTime ();
523- GlobalProgramInfo.getPerfStats ().startTotalTime ();
524- return RetVal;
525- }
526-
527445bool _3CInterface::writeAllConvertedFilesToDisk () {
528446 std::lock_guard<std::mutex> Lock (InterfaceMutex);
529447
530- ClangTool &Tool = getGlobalClangTool ();
531-
532- // Rewrite the input files.
533- std::unique_ptr<ToolAction> RewriteTool =
534- newFrontendActionFactoryA<RewriteAction<RewriteConsumer, ProgramInfo>>(
535- GlobalProgramInfo, VerifyDiagnosticOutput);
536- if (RewriteTool) {
537- int ToolExitCode = Tool.run (RewriteTool.get ());
538- if (ToolExitCode != 0 )
539- return false ;
540- } else
541- llvm_unreachable (" No action" );
448+ // 6. Rewrite the input files.
449+ RewriteConsumer RC = RewriteConsumer (GlobalProgramInfo);
450+ unsigned int Errs = 0 ;
451+ for (auto &TU : ASTs) {
452+ TU->enableSourceFileDiagnostics ();
453+ RC.HandleTranslationUnit (TU->getASTContext ());
454+ TU->getDiagnostics ().getClient ()->EndSourceFile ();
455+ Errs += TU->getDiagnostics ().getClient ()->getNumErrors ();
456+ }
457+ if (Errs > 0 ) return false ;
542458
543459 GlobalProgramInfo.getPerfStats ().endTotalTime ();
544460 GlobalProgramInfo.getPerfStats ().startTotalTime ();
0 commit comments