Commit 21ce559c9c

Andrew Kelley <superjoe30@gmail.com>
2018-02-05 04:06:03
add --forbid-library
to help track down accidentally linking against a library
1 parent 6171874
src/all_types.hpp
@@ -1631,6 +1631,8 @@ struct CodeGen {
     TypeTableEntry *ptr_to_stack_trace_type;
 
     ZigList<ZigLLVMDIType **> error_di_types;
+
+    ZigList<Buf *> forbidden_libs;
 };
 
 enum VarLinkage {
src/analyze.cpp
@@ -5609,17 +5609,6 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
     return link_lib;
 }
 
-void add_link_lib_symbol(CodeGen *g, Buf *lib_name, Buf *symbol_name) {
-    LinkLib *link_lib = add_link_lib(g, lib_name);
-    for (size_t i = 0; i < link_lib->symbols.length; i += 1) {
-        Buf *existing_symbol_name = link_lib->symbols.at(i);
-        if (buf_eql_buf(existing_symbol_name, symbol_name)) {
-            return;
-        }
-    }
-    link_lib->symbols.append(symbol_name);
-}
-
 uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry) {
     type_ensure_zero_bits_known(g, type_entry);
     if (type_entry->zero_bits) return 0;
src/analyze.hpp
@@ -175,7 +175,6 @@ bool type_is_copyable(CodeGen *g, TypeTableEntry *type_entry);
 LinkLib *create_link_lib(Buf *name);
 bool calling_convention_does_first_arg_return(CallingConvention cc);
 LinkLib *add_link_lib(CodeGen *codegen, Buf *lib);
-void add_link_lib_symbol(CodeGen *g, Buf *lib_name, Buf *symbol_name);
 
 uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry);
 TypeTableEntry *get_align_amt_type(CodeGen *g);
src/codegen.cpp
@@ -253,6 +253,10 @@ LinkLib *codegen_add_link_lib(CodeGen *g, Buf *name) {
     return add_link_lib(g, name);
 }
 
+void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib) {
+    codegen->forbidden_libs.append(lib);
+}
+
 void codegen_add_framework(CodeGen *g, const char *framework) {
     g->darwin_frameworks.append(buf_create_from_str(framework));
 }
@@ -6311,3 +6315,4 @@ PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir,
     }
     return pkg;
 }
+
src/codegen.hpp
@@ -36,6 +36,7 @@ void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir);
 void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
 void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole);
 void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
+void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);
 LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);
 void codegen_add_framework(CodeGen *codegen, const char *name);
 void codegen_add_rpath(CodeGen *codegen, const char *name);
src/ir.cpp
@@ -11762,6 +11762,25 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field
     }
 }
 
+static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node) {
+    LinkLib *link_lib = add_link_lib(ira->codegen, lib_name);
+    for (size_t i = 0; i < link_lib->symbols.length; i += 1) {
+        Buf *existing_symbol_name = link_lib->symbols.at(i);
+        if (buf_eql_buf(existing_symbol_name, symbol_name)) {
+            return;
+        }
+    }
+    for (size_t i = 0; i < ira->codegen->forbidden_libs.length; i += 1) {
+        Buf *forbidden_lib_name = ira->codegen->forbidden_libs.at(i);
+        if (buf_eql_buf(lib_name, forbidden_lib_name)) {
+            ir_add_error_node(ira, source_node,
+                buf_sprintf("linking against forbidden library '%s'", buf_ptr(symbol_name)));
+        }
+    }
+    link_lib->symbols.append(symbol_name);
+}
+
+
 static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) {
     bool pointer_only = false;
     resolve_top_level_decl(ira->codegen, tld, pointer_only, source_instruction->source_node);
@@ -11777,7 +11796,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
             TldVar *tld_var = (TldVar *)tld;
             VariableTableEntry *var = tld_var->var;
             if (tld_var->extern_lib_name != nullptr) {
-                add_link_lib_symbol(ira->codegen, tld_var->extern_lib_name, &var->name);
+                add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, source_instruction->source_node);
             }
 
             return ir_analyze_var_ptr(ira, source_instruction, var, false, false);
@@ -11799,7 +11818,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
             const_val->data.x_fn.fn_entry = fn_entry;
 
             if (tld_fn->extern_lib_name != nullptr) {
-                add_link_lib_symbol(ira->codegen, tld_fn->extern_lib_name, &fn_entry->symbol_name);
+                add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, source_instruction->source_node);
             }
 
             bool ptr_is_const = true;
@@ -15839,7 +15858,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
                 return ira->codegen->builtin_types.entry_invalid;
 
             if (tld_var->extern_lib_name != nullptr) {
-                add_link_lib_symbol(ira->codegen, tld_var->extern_lib_name, &var->name);
+                add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, instruction->base.source_node);
             }
 
             if (lval.is_ptr) {
@@ -15858,7 +15877,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
             assert(fn_entry->type_entry);
 
             if (tld_fn->extern_lib_name != nullptr) {
-                add_link_lib_symbol(ira->codegen, tld_fn->extern_lib_name, &fn_entry->symbol_name);
+                add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, instruction->base.source_node);
             }
 
             IrInstruction *ref_instruction = ir_create_const_fn(&ira->new_irb, instruction->base.scope,
src/main.cpp
@@ -66,6 +66,7 @@ static int usage(const char *arg0) {
         "  --msvc-lib-dir [path]        (windows) directory where vcruntime.lib resides\n"
         "  --kernel32-lib-dir [path]    (windows) directory where kernel32.lib resides\n"
         "  --library [lib]              link against lib\n"
+        "  --forbid-library [lib]       make it an error to link against lib\n"
         "  --library-path [dir]         add a directory to the library search path\n"
         "  --linker-script [path]       use a custom linker script\n"
         "  --object [obj]               add object file to build\n"
@@ -309,6 +310,7 @@ int main(int argc, char **argv) {
     ZigList<const char *> llvm_argv = {0};
     ZigList<const char *> lib_dirs = {0};
     ZigList<const char *> link_libs = {0};
+    ZigList<const char *> forbidden_link_libs = {0};
     ZigList<const char *> frameworks = {0};
     int err;
     const char *target_arch = nullptr;
@@ -592,6 +594,8 @@ int main(int argc, char **argv) {
                     lib_dirs.append(argv[i]);
                 } else if (strcmp(arg, "--library") == 0) {
                     link_libs.append(argv[i]);
+                } else if (strcmp(arg, "--forbid-library") == 0) {
+                    forbidden_link_libs.append(argv[i]);
                 } else if (strcmp(arg, "--object") == 0) {
                     objects.append(argv[i]);
                 } else if (strcmp(arg, "--assembly") == 0) {
@@ -804,6 +808,10 @@ int main(int argc, char **argv) {
                 LinkLib *link_lib = codegen_add_link_lib(g, buf_create_from_str(link_libs.at(i)));
                 link_lib->provided_explicitly = true;
             }
+            for (size_t i = 0; i < forbidden_link_libs.length; i += 1) {
+                Buf *forbidden_link_lib = buf_create_from_str(forbidden_link_libs.at(i));
+                codegen_add_forbidden_lib(g, forbidden_link_lib);
+            }
             for (size_t i = 0; i < frameworks.length; i += 1) {
                 codegen_add_framework(g, frameworks.at(i));
             }