diff --git a/infer/src/clang/cFrontend_utils.ml b/infer/src/clang/cFrontend_utils.ml index 7e78db259..4af4022c2 100644 --- a/infer/src/clang/cFrontend_utils.ml +++ b/infer/src/clang/cFrontend_utils.ml @@ -546,7 +546,7 @@ struct Procname.mangled_c_method class_name method_name type_name_crc let mk_sil_var name decl_info_type_ptr_opt procname outer_procname = - let name_string = name.Clang_ast_t.ni_name in + let name_string = Ast_utils.get_qualified_name name in let simple_name = Mangled.from_string name_string in match decl_info_type_ptr_opt with | Some (decl_info, type_ptr, var_decl_info, should_be_mangled) -> @@ -563,7 +563,7 @@ struct let line_opt = start_location.Clang_ast_t.sl_line in let line_str = match line_opt with | Some line -> string_of_int line | None -> "" in let mangled = CRC.crc16 (type_name ^ line_str) in - let mangled_name = Mangled.mangled name.Clang_ast_t.ni_name mangled in + let mangled_name = Mangled.mangled name_string mangled in Sil.mk_pvar mangled_name procname | None -> Sil.mk_pvar simple_name procname diff --git a/infer/tests/codetoanalyze/cpp/frontend/namespace/global_variable.cpp b/infer/tests/codetoanalyze/cpp/frontend/namespace/global_variable.cpp new file mode 100644 index 000000000..12d6e2cc8 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/namespace/global_variable.cpp @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2015 - present Facebook, Inc. +* All rights reserved. +* +* This source code is licensed under the BSD style license found in the +* LICENSE file in the root directory of this source tree. An additional grant +* of patent rights can be found in the PATENTS file in the same directory. +*/ + +namespace f1 { +int val; + +struct A { + static int v; +}; + +} + +namespace f2 { +int val; +} + +struct B { + static int v; +}; + +struct C : public B { }; + +int div0_namepace_res() { + f1::val = 1; + f2::val = -2; + return 1 / (f1::val + f2::val + 1); +} + +int div0_static_field() { + B::v= 1; + f1::A::v = -2; + return 1 / (f1::A::v + B::v + 1); +} + +int div0_static_field_member_access(f1::A *a, C *b) { + a->v = 1; + b->v = -2; + return 1 / (f1::A::v + B::v + 1); +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/namespace/global_variable.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/namespace/global_variable.cpp.dot new file mode 100644 index 000000000..4710f4ef1 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/namespace/global_variable.cpp.dot @@ -0,0 +1,59 @@ +digraph iCFG { +15 [label="15: BinaryOperatorStmt: Assign \n *&#GB$f1::A::v:int =1 [line 42]\n " shape="box"] + + + 15 -> 14 ; +14 [label="14: BinaryOperatorStmt: Assign \n *&#GB$B::v:int =-2 [line 43]\n " shape="box"] + + + 14 -> 13 ; +13 [label="13: Return Stmt \n n$0=*&#GB$f1::A::v:int [line 44]\n n$1=*&#GB$B::v:int [line 44]\n *&return:int =(1 / ((n$0 + n$1) + 1)) [line 44]\n REMOVE_TEMPS(n$0,n$1); [line 44]\n APPLY_ABSTRACTION; [line 44]\n " shape="box"] + + + 13 -> 12 ; +12 [label="12: Exit div0_static_field_member_access \n " color=yellow style=filled] + + +11 [label="11: Start div0_static_field_member_access\nFormals: a:class f1::A * b:class C *\nLocals: \n DECLARE_LOCALS(&return); [line 41]\n NULLIFY(&a,false); [line 41]\n NULLIFY(&b,false); [line 41]\n " color=yellow style=filled] + + + 11 -> 15 ; +10 [label="10: BinaryOperatorStmt: Assign \n *&#GB$B::v:int =1 [line 36]\n " shape="box"] + + + 10 -> 9 ; +9 [label="9: BinaryOperatorStmt: Assign \n *&#GB$f1::A::v:int =-2 [line 37]\n " shape="box"] + + + 9 -> 8 ; +8 [label="8: Return Stmt \n n$0=*&#GB$f1::A::v:int [line 38]\n n$1=*&#GB$B::v:int [line 38]\n *&return:int =(1 / ((n$0 + n$1) + 1)) [line 38]\n REMOVE_TEMPS(n$0,n$1); [line 38]\n APPLY_ABSTRACTION; [line 38]\n " shape="box"] + + + 8 -> 7 ; +7 [label="7: Exit div0_static_field \n " color=yellow style=filled] + + +6 [label="6: Start div0_static_field\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 35]\n " color=yellow style=filled] + + + 6 -> 10 ; +5 [label="5: BinaryOperatorStmt: Assign \n *&#GB$f1::val:int =1 [line 30]\n " shape="box"] + + + 5 -> 4 ; +4 [label="4: BinaryOperatorStmt: Assign \n *&#GB$f2::val:int =-2 [line 31]\n " shape="box"] + + + 4 -> 3 ; +3 [label="3: Return Stmt \n n$0=*&#GB$f1::val:int [line 32]\n n$1=*&#GB$f2::val:int [line 32]\n *&return:int =(1 / ((n$0 + n$1) + 1)) [line 32]\n REMOVE_TEMPS(n$0,n$1); [line 32]\n APPLY_ABSTRACTION; [line 32]\n " shape="box"] + + + 3 -> 2 ; +2 [label="2: Exit div0_namepace_res \n " color=yellow style=filled] + + +1 [label="1: Start div0_namepace_res\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 29]\n " color=yellow style=filled] + + + 1 -> 5 ; +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/namespace/namespace.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/namespace/namespace.cpp.dot index 176751d4f..585ea4664 100644 --- a/infer/tests/codetoanalyze/cpp/frontend/namespace/namespace.cpp.dot +++ b/infer/tests/codetoanalyze/cpp/frontend/namespace/namespace.cpp.dot @@ -31,7 +31,7 @@ digraph iCFG { 17 -> 16 ; -16 [label="16: BinaryOperatorStmt: Assign \n n$0=*&#GB$pi:double [line 57]\n *&j:double =n$0 [line 57]\n REMOVE_TEMPS(n$0); [line 57]\n NULLIFY(&j,false); [line 57]\n " shape="box"] +16 [label="16: BinaryOperatorStmt: Assign \n n$0=*&#GB$bar::pi:double [line 57]\n *&j:double =n$0 [line 57]\n REMOVE_TEMPS(n$0); [line 57]\n NULLIFY(&j,false); [line 57]\n " shape="box"] 16 -> 15 ; @@ -53,7 +53,7 @@ digraph iCFG { 11 -> 12 ; -10 [label="10: Return Stmt \n n$0=*&#GB$pi:double [line 29]\n *&return:double =(2 * n$0) [line 29]\n REMOVE_TEMPS(n$0); [line 29]\n APPLY_ABSTRACTION; [line 29]\n " shape="box"] +10 [label="10: Return Stmt \n n$0=*&#GB$bar::pi:double [line 29]\n *&return:double =(2 * n$0) [line 29]\n REMOVE_TEMPS(n$0); [line 29]\n APPLY_ABSTRACTION; [line 29]\n " shape="box"] 10 -> 9 ; diff --git a/infer/tests/endtoend/cpp/NamespaceGlobalVariableTest.java b/infer/tests/endtoend/cpp/NamespaceGlobalVariableTest.java new file mode 100644 index 000000000..18e1df5eb --- /dev/null +++ b/infer/tests/endtoend/cpp/NamespaceGlobalVariableTest.java @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2015 - present Facebook, Inc. +* All rights reserved. +* +* This source code is licensed under the BSD style license found in the +* LICENSE file in the root directory of this source tree. An additional grant +* of patent rights can be found in the PATENTS file in the same directory. +*/ + +package endtoend.cpp; + +import static org.hamcrest.MatcherAssert.assertThat; +import static utils.matchers.ResultContainsExactly.containsExactly; + +import com.google.common.collect.ImmutableList; + +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; + +import java.io.IOException; + +import utils.DebuggableTemporaryFolder; +import utils.InferException; +import utils.InferResults; +import utils.InferRunner; + +public class NamespaceGlobalVariableTest { + + public static final String FILE = + "infer/tests/codetoanalyze/cpp/frontend/namespace/global_variable.cpp"; + + private static ImmutableList inferCmd; + + public static final String DIVIDE_BY_ZERO = "DIVIDE_BY_ZERO"; + + @ClassRule + public static DebuggableTemporaryFolder folder = + new DebuggableTemporaryFolder(); + + @BeforeClass + public static void runInfer() throws InterruptedException, IOException { + inferCmd = InferRunner.createCPPInferCommand(folder, FILE); + } + + @Test + public void whenInferRunsOnDiv0MethodsErrorIsFound() + throws InterruptedException, IOException, InferException { + InferResults inferResults = InferRunner.runInferCPP(inferCmd); + String[] procedures = { + "div0_namepace_res", + "div0_static_field", + "div0_static_field_member_access", + }; + assertThat( + "Results should contain the expected divide by zero", + inferResults, + containsExactly( + DIVIDE_BY_ZERO, + FILE, + procedures + ) + ); + } +} diff --git a/infer/tests/frontend/cpp/NamespaceTest.java b/infer/tests/frontend/cpp/NamespaceTest.java index 751b167a6..7c3789ee7 100644 --- a/infer/tests/frontend/cpp/NamespaceTest.java +++ b/infer/tests/frontend/cpp/NamespaceTest.java @@ -39,4 +39,10 @@ public class NamespaceTest { throws InterruptedException, IOException, InferException { frontendTest("function.cpp"); } + + @Test + public void testGlobalVariableDotFilesMatch() + throws InterruptedException, IOException, InferException { + frontendTest("global_variable.cpp"); + } }