llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Arseniy Zaostrovnykh (necto) <details> <summary>Changes</summary> Add tests for all kinds of CTU import failures expressed in the `cross_tu::index_error_code` enumeration. Many of the test cases have no diagnostics, because the respective errors are silently ignored in `CrossTranslationUnitContext::emitCrossTUDiagnostics`. I expect to improve this part, and these tests should demonstrate how the improvements manifest to the user. -- CPP-7804 --- Full diff: https://github.com/llvm/llvm-project/pull/188773.diff 16 Files Affected: - (added) clang/test/Analysis/ctu/Inputs/invalid-ast-other.cpp (+1) - (added) clang/test/Analysis/ctu/diag/Inputs/bar.cpp (+1) - (added) clang/test/Analysis/ctu/diag/Inputs/simple-extern-c.cpp (+1) - (added) clang/test/Analysis/ctu/diag/Inputs/simple.cpp (+1) - (added) clang/test/Analysis/ctu/diag/invalid-index.cpp (+18) - (added) clang/test/Analysis/ctu/diag/invlist-ambiguous.cpp (+19) - (added) clang/test/Analysis/ctu/diag/invlist-empty.cpp (+23) - (added) clang/test/Analysis/ctu/diag/invlist-lookup-miss.cpp (+21) - (added) clang/test/Analysis/ctu/diag/invlist-missing.cpp (+20) - (added) clang/test/Analysis/ctu/diag/invlist-wrong-format.cpp (+21) - (added) clang/test/Analysis/ctu/diag/lang-dialect-mismatch.cpp (+21) - (added) clang/test/Analysis/ctu/diag/lang-mismatch.c (+23) - (added) clang/test/Analysis/ctu/diag/load-threshold.cpp (+33) - (added) clang/test/Analysis/ctu/diag/missing-index.cpp (+18) - (added) clang/test/Analysis/ctu/invalid-ast.cpp (+26) - (added) clang/test/Analysis/ctu/missing-ast.cpp (+24) ``````````diff diff --git a/clang/test/Analysis/ctu/Inputs/invalid-ast-other.cpp b/clang/test/Analysis/ctu/Inputs/invalid-ast-other.cpp new file mode 100644 index 0000000000000..06440e3a86f7d --- /dev/null +++ b/clang/test/Analysis/ctu/Inputs/invalid-ast-other.cpp @@ -0,0 +1 @@ +void external() {} diff --git a/clang/test/Analysis/ctu/diag/Inputs/bar.cpp b/clang/test/Analysis/ctu/diag/Inputs/bar.cpp new file mode 100644 index 0000000000000..51fc652a8c1a7 --- /dev/null +++ b/clang/test/Analysis/ctu/diag/Inputs/bar.cpp @@ -0,0 +1 @@ +int bar(int x) { return x + 2; } diff --git a/clang/test/Analysis/ctu/diag/Inputs/simple-extern-c.cpp b/clang/test/Analysis/ctu/diag/Inputs/simple-extern-c.cpp new file mode 100644 index 0000000000000..dc6193b4a3d51 --- /dev/null +++ b/clang/test/Analysis/ctu/diag/Inputs/simple-extern-c.cpp @@ -0,0 +1 @@ +extern "C" int foo(int x) { return x + 1; } diff --git a/clang/test/Analysis/ctu/diag/Inputs/simple.cpp b/clang/test/Analysis/ctu/diag/Inputs/simple.cpp new file mode 100644 index 0000000000000..83a87cb20ca99 --- /dev/null +++ b/clang/test/Analysis/ctu/diag/Inputs/simple.cpp @@ -0,0 +1 @@ +int foo(int x) { return x + 1; } diff --git a/clang/test/Analysis/ctu/diag/invalid-index.cpp b/clang/test/Analysis/ctu/diag/invalid-index.cpp new file mode 100644 index 0000000000000..640e6ceee654c --- /dev/null +++ b/clang/test/Analysis/ctu/diag/invalid-index.cpp @@ -0,0 +1,18 @@ +// Test that a malformed externalDefMap.txt produces err_extdefmap_parsing error. +// +// RUN: rm -rf %t && mkdir %t +// RUN: echo 'this is invalid' > %t/externalDefMap.txt +// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t \ +// RUN: -verify %s + +// We expect an error in this file, but without a location. +// expected-error-re@./invalid-index.cpp:*{{error parsing index file: '{{.+}}externalDefMap.txt' line: 1 '<USR-Length>:<USR> <File-Path>' format expected}} + +int foo(int); + +void test() { + foo(1); +} diff --git a/clang/test/Analysis/ctu/diag/invlist-ambiguous.cpp b/clang/test/Analysis/ctu/diag/invlist-ambiguous.cpp new file mode 100644 index 0000000000000..570c6c7fe2585 --- /dev/null +++ b/clang/test/Analysis/ctu/diag/invlist-ambiguous.cpp @@ -0,0 +1,19 @@ +// Test that duplicate keys in the invocation list silently fails CTU import. +// +// RUN: rm -rf %t && mkdir %t +// RUN: echo '11:c:@F@foo#I# simple.cpp' > %t/externalDefMap.txt +// RUN: echo '"/some/path.cpp": ["clang", "/some/path.cpp"]' > %t/invocations.yaml +// RUN: echo '"/some/path.cpp": ["clang", "/some/path.cpp"]' >> %t/invocations.yaml +// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t \ +// RUN: -analyzer-config ctu-invocation-list=%t/invocations.yaml \ +// RUN: -verify %s + +int foo(int); + +void test() { + // expected-no-diagnostics + foo(1); // no-warning. Ignoring "Invocation list file contains multiple references to the same source file." +} diff --git a/clang/test/Analysis/ctu/diag/invlist-empty.cpp b/clang/test/Analysis/ctu/diag/invlist-empty.cpp new file mode 100644 index 0000000000000..b0504960b98b2 --- /dev/null +++ b/clang/test/Analysis/ctu/diag/invlist-empty.cpp @@ -0,0 +1,23 @@ +// Test that an empty invocation list file silently fails CTU import. +// +// Note: invocation_list_empty (index_error_code::invocation_list_empty) is +// dead code: llvm::yaml::Stream::begin() always creates at least one Document, +// so FirstInvocationFile == InvocationFile.end() is never true. An empty file +// reaches the !DocumentRoot branch instead, producing invocation_list_wrong_format. +// +// RUN: rm -rf %t && mkdir %t +// RUN: echo '11:c:@F@foo#I# simple.cpp' > %t/externalDefMap.txt +// RUN: touch %t/invocations.yaml +// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t \ +// RUN: -analyzer-config ctu-invocation-list=%t/invocations.yaml \ +// RUN: -verify %s + +int foo(int); + +void test() { + // expected-no-diagnostics + foo(1); // no-warning. Ignoring "Invocation list file is in wrong format." +} diff --git a/clang/test/Analysis/ctu/diag/invlist-lookup-miss.cpp b/clang/test/Analysis/ctu/diag/invlist-lookup-miss.cpp new file mode 100644 index 0000000000000..3adc035dff681 --- /dev/null +++ b/clang/test/Analysis/ctu/diag/invlist-lookup-miss.cpp @@ -0,0 +1,21 @@ +// Test that a valid invocation list without the requested source file silently fails CTU import. +// +// The invocation list has a valid entry for a different path, but not for the +// source file referenced in externalDefMap.txt. +// +// RUN: rm -rf %t && mkdir %t +// RUN: echo '11:c:@F@foo#I# diag-simple.cpp' > %t/externalDefMap.txt +// RUN: echo '"/nonexistent.cpp": ["clang", "/nonexistent.cpp"]' > %t/invocations.yaml +// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t \ +// RUN: -analyzer-config ctu-invocation-list=%t/invocations.yaml \ +// RUN: -verify %s + +int foo(int); + +void test() { + // expected-no-diagnostics + foo(1); // no-warning. Ignoring "Invocation list file does not contain the requested source file." +} diff --git a/clang/test/Analysis/ctu/diag/invlist-missing.cpp b/clang/test/Analysis/ctu/diag/invlist-missing.cpp new file mode 100644 index 0000000000000..bac264ab10b4e --- /dev/null +++ b/clang/test/Analysis/ctu/diag/invlist-missing.cpp @@ -0,0 +1,20 @@ +// Test that a missing invocation list silently fails CTU import. +// +// The externalDefMap.txt maps foo to a non-.ast source path, triggering +// loadFromSource(). The invocation list path points to a nonexistent file. +// +// RUN: rm -rf %t && mkdir %t +// RUN: echo '11:c:@F@foo#I# simple.cpp' > %t/externalDefMap.txt +// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t \ +// RUN: -analyzer-config ctu-invocation-list=%t/nonexistent.yaml \ +// RUN: -verify %s + +int foo(int); + +void test() { + // expected-no-diagnostics + foo(1); // no-warning. Ignoring "Invocation list file is not found." +} diff --git a/clang/test/Analysis/ctu/diag/invlist-wrong-format.cpp b/clang/test/Analysis/ctu/diag/invlist-wrong-format.cpp new file mode 100644 index 0000000000000..cfa3cc65e8d06 --- /dev/null +++ b/clang/test/Analysis/ctu/diag/invlist-wrong-format.cpp @@ -0,0 +1,21 @@ +// Test that a malformed invocation list produces silently fails CTU import. +// +// A YAML sequence (- item) at the root is not a mapping, so dyn_cast to +// MappingNode fails, triggering invocation_list_wrong_format. +// +// RUN: rm -rf %t && mkdir %t +// RUN: echo '11:c:@F@foo#I# simple.cpp' > %t/externalDefMap.txt +// RUN: echo '- just_a_list_item' > %t/invocations.yaml +// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t \ +// RUN: -analyzer-config ctu-invocation-list=%t/invocations.yaml \ +// RUN: -verify %s + +int foo(int); + +void test() { + // expected-no-diagnostics + foo(1); // no-warning. Ignoring "Invocation list file is in wrong format." +} diff --git a/clang/test/Analysis/ctu/diag/lang-dialect-mismatch.cpp b/clang/test/Analysis/ctu/diag/lang-dialect-mismatch.cpp new file mode 100644 index 0000000000000..c41072d46df02 --- /dev/null +++ b/clang/test/Analysis/ctu/diag/lang-dialect-mismatch.cpp @@ -0,0 +1,21 @@ +// Test that loading a C++17 AST from a C++14 translation unit produces +// lang_dialect_mismatch. Both are C++ (no lang_mismatch), but CPlusPlus17 +// differs, triggering the dialect check, and silently failing CTU import. +// +// RUN: rm -rf %t && mkdir %t +// RUN: %clang_cc1 -std=c++17 -triple x86_64-pc-linux-gnu \ +// RUN: -emit-pch -o %t/simple.cpp.ast \ +// RUN: %S/Inputs/simple.cpp +// RUN: echo '11:c:@F@foo#I# simple.cpp.ast' > %t/externalDefMap.txt +// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t \ +// RUN: -verify %s + +int foo(int); + +void test() { + // expected-no-diagnostics + foo(1); // no-warning. Ignoring "Invocation list file contains multiple references to the same source file." +} diff --git a/clang/test/Analysis/ctu/diag/lang-mismatch.c b/clang/test/Analysis/ctu/diag/lang-mismatch.c new file mode 100644 index 0000000000000..deee7077ec495 --- /dev/null +++ b/clang/test/Analysis/ctu/diag/lang-mismatch.c @@ -0,0 +1,23 @@ +// Test that loading a C++ AST from a C translation unit produces lang_mismatch. +// +// The external definition is compiled as C++ with extern "C" linkage, so the +// USR matches the C function declaration (both use the no-parameter-type USR +// format: c:@F@foo, 8 chars). The lang mismatch leads to a silent CTU import failure. +// +// RUN: rm -rf %t && mkdir %t +// RUN: %clang_cc1 -x c++ -std=c++14 -triple x86_64-pc-linux-gnu \ +// RUN: -emit-pch -o %t/simple-extern-c.cpp.ast \ +// RUN: %S/Inputs/simple-extern-c.cpp +// RUN: echo '8:c:@F@foo simple-extern-c.cpp.ast' > %t/externalDefMap.txt +// RUN: %clang_analyze_cc1 -x c -triple x86_64-pc-linux-gnu \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t \ +// RUN: -verify %s + +int foo(int); + +void test(void) { + // expected-no-diagnostics + foo(1); // no-warning. Ignoring "Language mismatch." +} diff --git a/clang/test/Analysis/ctu/diag/load-threshold.cpp b/clang/test/Analysis/ctu/diag/load-threshold.cpp new file mode 100644 index 0000000000000..9e40b8a42958f --- /dev/null +++ b/clang/test/Analysis/ctu/diag/load-threshold.cpp @@ -0,0 +1,33 @@ +// Test that exceeding ctu-import-cpp-threshold produces load_threshold_reached, +// which is silently fails AST import. +// +// With threshold=1, the first external AST (foo) is loaded successfully. +// The second lookup (bar) finds the threshold exhausted and reports the error. +// +// RUN: rm -rf %t && mkdir %t +// RUN: %clang_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \ +// RUN: -emit-pch -o %t/simple.cpp.ast \ +// RUN: %S/Inputs/simple.cpp +// RUN: %clang_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \ +// RUN: -emit-pch -o %t/bar.cpp.ast \ +// RUN: %S/Inputs/bar.cpp +// RUN: echo '11:c:@F@foo#I# simple.cpp.ast' > %t/externalDefMap.txt +// RUN: echo '11:c:@F@bar#I# bar.cpp.ast' >> %t/externalDefMap.txt +// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t \ +// RUN: -analyzer-config ctu-import-cpp-threshold=1 \ +// RUN: -verify %s + +// foo is loaded successfully (first load, within threshold). +// bar hits the threshold (no telemetry emitted for it). + +int foo(int); +int bar(int); + +void test() { + foo(1); + // expected-no-diagnostics + bar(1); // no-warning. Ignoring "Load threshold reached." +} diff --git a/clang/test/Analysis/ctu/diag/missing-index.cpp b/clang/test/Analysis/ctu/diag/missing-index.cpp new file mode 100644 index 0000000000000..e09042f9538f7 --- /dev/null +++ b/clang/test/Analysis/ctu/diag/missing-index.cpp @@ -0,0 +1,18 @@ +// Test that missing externalDefMap.txt produces err_ctu_error_opening at call site. +// +// RUN: rm -rf %t && mkdir %t +// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t \ +// RUN: -analyzer-config ctu-index-name=non-existing.txt \ +// RUN: -verify %s + +// We expect an error in this file, but without a location. +// expected-error-re@./missing-index.cpp:*{{error opening '{{.+}}non-existing.txt': required by the CrossTU functionality}} + +int foo(int); + +void test() { + foo(1); +} diff --git a/clang/test/Analysis/ctu/invalid-ast.cpp b/clang/test/Analysis/ctu/invalid-ast.cpp new file mode 100644 index 0000000000000..9d0b850233dbe --- /dev/null +++ b/clang/test/Analysis/ctu/invalid-ast.cpp @@ -0,0 +1,26 @@ +// Test that loading of invalid AST dump leads CTU import failure and a note on stderr. +// RUN: rm -rf %t +// RUN: mkdir %t + +// RUN: touch %t/invalid-ast-other.cpp.ast + +// RUN: cp %S/Inputs/invalid-ast-other.cpp.externalDefMap.ast-dump.txt %t/externalDefMap.txt + +// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -std=c++17 \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t \ +// RUN: -analyzer-config display-ctu-progress=true \ +// RUN: -verify %s 2>&1 | FileCheck %s + +// CHECK: error: unable to load precompiled file + +// FIXME: this is misleading +// CHECK: CTU loaded AST file: invalid-ast-other.cpp.ast + +void external(); + +void trigger() { + // expected-no-diagnostics + external(); // no-warning +} diff --git a/clang/test/Analysis/ctu/missing-ast.cpp b/clang/test/Analysis/ctu/missing-ast.cpp new file mode 100644 index 0000000000000..d39d5d8f05bf6 --- /dev/null +++ b/clang/test/Analysis/ctu/missing-ast.cpp @@ -0,0 +1,24 @@ +// Test that when the referenced AST file is missing, CTU import fails with a note in stderr. +// RUN: rm -rf %t +// RUN: mkdir %t + +// RUN: cp %S/Inputs/missing-ast.cpp.externalDefMap.ast-dump.txt %t/externalDefMap.txt + +// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -std=c++17 \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t \ +// RUN: -analyzer-config display-ctu-progress=true \ +// RUN: -verify %s 2>&1 | FileCheck %s + +// CHECK: error: unable to load precompiled file + +// FIXME: this is misleading +// CHECK: CTU loaded AST file: wrong-missing-ast.cpp.ast + +void external(); + +void trigger() { + // expected-no-diagnostics + external(); // no-warning +} `````````` </details> https://github.com/llvm/llvm-project/pull/188773 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
