[PATCH] D30949: [CodeGen] Add an option to enable LLVM IR linting

Vedant Kumar via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 14 11:34:54 PDT 2017


vsk created this revision.

LLVM has a nifty linter which checks for some common kinds of unusual or
undefined behavior by doing some basic IR-level static analysis.

Add a CC1 option to clang which enables this analysis.

Having the linter available through clang could be a useful debugging
tool. It can also be a useful reporting tool: hacking your build system
to add in "-Xclang -enable-llvm-linter" is usually easier than hacking
it to add "$CC ... | opt -S -o /dev/null -lint".

Eventually, I'd like to teach the linter about the sanitizers, so that
it can statically report the kinds of bugs the sanitizers know how to
flag. This would work by checking for diagnostic calls which post-dom
function entry blocks (unconditionally buggy code). The research paper
on the STACK static UB checker suggests that this could be useful.


https://reviews.llvm.org/D30949

Files:
  include/clang/Driver/CC1Options.td
  include/clang/Frontend/CodeGenOptions.def
  lib/CodeGen/BackendUtil.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/enable-llvm-linter.c


Index: test/CodeGen/enable-llvm-linter.c
===================================================================
--- /dev/null
+++ test/CodeGen/enable-llvm-linter.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -enable-llvm-linter -O0 -emit-llvm -o /dev/null %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -enable-llvm-linter -O3 -emit-llvm -o /dev/null %s 2>&1 | FileCheck %s
+
+// CHECK: Unusual: Address one pointer dereference
+// CHECK-NEXT: load i32, i32*
+int foo() {
+  int *p = (int *)1;
+  return *p;
+}
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -650,6 +650,7 @@
 
   Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
   Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier);
+  Opts.LintModule = Args.hasArg(OPT_enable_llvm_linter);
 
   Opts.DisableGCov = Args.hasArg(OPT_test_coverage);
   Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data);
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/Analysis/Lint.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Bitcode/BitcodeReader.h"
@@ -257,6 +258,11 @@
   PM.add(createEfficiencySanitizerPass(Opts));
 }
 
+static void addLinterPass(const PassManagerBuilder &Builder,
+                          legacy::PassManagerBase &PM) {
+  PM.add(createLintPass());
+}
+
 static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
                                          const CodeGenOptions &CodeGenOpts) {
   TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple);
@@ -415,6 +421,12 @@
                            addEfficiencySanitizerPass);
   }
 
+  if (CodeGenOpts.LintModule) {
+    PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, addLinterPass);
+    PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
+                           addLinterPass);
+  }
+
   // Set up the per-function pass manager.
   FPM.add(new TargetLibraryInfoWrapperPass(*TLII));
   if (CodeGenOpts.VerifyModule)
Index: include/clang/Frontend/CodeGenOptions.def
===================================================================
--- include/clang/Frontend/CodeGenOptions.def
+++ include/clang/Frontend/CodeGenOptions.def
@@ -184,6 +184,9 @@
 CODEGENOPT(VerifyModule      , 1, 1) ///< Control whether the module should be run
                                      ///< through the LLVM Verifier.
 
+CODEGENOPT(LintModule        , 1, 0) ///< Control whether the module should be run
+                                     ///< through the LLVM Linter.
+
 CODEGENOPT(StackRealignment  , 1, 0) ///< Control whether to force stack
                                      ///< realignment.
 CODEGENOPT(UseInitArray      , 1, 0) ///< Control whether to use .init_array or
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td
+++ include/clang/Driver/CC1Options.td
@@ -164,6 +164,8 @@
 
 def disable_llvm_verifier : Flag<["-"], "disable-llvm-verifier">,
   HelpText<"Don't run the LLVM IR verifier pass">;
+def enable_llvm_linter : Flag<["-"], "enable-llvm-linter">,
+  HelpText<"Run the LLVM IR linter pass">;
 def disable_llvm_passes : Flag<["-"], "disable-llvm-passes">,
   HelpText<"Use together with -emit-llvm to get pristine LLVM IR from the "
            "frontend by not running any LLVM passes at all">;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D30949.91755.patch
Type: text/x-patch
Size: 3758 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170314/69e217fc/attachment-0001.bin>


More information about the cfe-commits mailing list