From 4109a5166b544c33af333505883b414db7c0c14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= Date: Wed, 22 Jan 2025 17:55:51 +0100 Subject: [PATCH 1/3] fix test --- clang/lib/AST/ASTImporter.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 0669aa1b809c3..c25ec82c1ab5f 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6731,6 +6731,13 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (Error Err = importInto(TemplatedFD, D->getTemplatedDecl())) return std::move(Err); + // Fail if TemplatedFD is already part of a template. + // The structural equivalence check should have been found this template. + // If not, there is AST incompatibility that can be caused by previous import + // errors. + if (TemplatedFD->getDescribedTemplate()) + return make_error(ASTImportError::NameConflict); + // At creation of the template the template parameters are "adopted" // (DeclContext is changed). After this possible change the lookup table // must be updated. From f562b00b74ddf011134d5b2c06be95bc9a0fb046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= Date: Fri, 24 Jan 2025 11:43:38 +0100 Subject: [PATCH 2/3] [clang][ASTImporter] Fix possible crash at import of function template During import of a function template at specific conditions an assertion "'TemplateOrSpecialization.isNull()" can be triggered. This can happen when the new AST is already incompatible after import failures. Problem is fixed by returning import failure at the assert condition. --- clang/lib/AST/ASTImporter.cpp | 15 ++--- .../Inputs/ctu-test-import-failure-import.cpp | 56 +++++++++++++++++++ ...ure-import.cpp.externalDefMap.ast-dump.txt | 5 ++ .../test/Analysis/ctu-test-import-failure.cpp | 34 +++++++++++ 4 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp create mode 100644 clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp.externalDefMap.ast-dump.txt create mode 100644 clang/test/Analysis/ctu-test-import-failure.cpp diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index c25ec82c1ab5f..34b49963c00ec 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6731,13 +6731,6 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (Error Err = importInto(TemplatedFD, D->getTemplatedDecl())) return std::move(Err); - // Fail if TemplatedFD is already part of a template. - // The structural equivalence check should have been found this template. - // If not, there is AST incompatibility that can be caused by previous import - // errors. - if (TemplatedFD->getDescribedTemplate()) - return make_error(ASTImportError::NameConflict); - // At creation of the template the template parameters are "adopted" // (DeclContext is changed). After this possible change the lookup table // must be updated. @@ -6762,6 +6755,14 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { Params, TemplatedFD)) return ToFunc; + // Fail if TemplatedFD is already part of a template. + // The template should have been found by structural equivalence check before, + // or ToFunc should be already imported. + // If not, there is AST incompatibility that can be caused by previous import + // errors. (NameConflict is not exact here.) + if (TemplatedFD->getDescribedTemplate()) + return make_error(ASTImportError::NameConflict); + TemplatedFD->setDescribedFunctionTemplate(ToFunc); ToFunc->setAccess(D->getAccess()); diff --git a/clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp b/clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp new file mode 100644 index 0000000000000..d5e6ba8852872 --- /dev/null +++ b/clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp @@ -0,0 +1,56 @@ +namespace std { +inline namespace __cxx11 { +template +class basic_string; +} +template class basic_istream; +template struct __get_first_arg; +template using __ptr_traits_elem_t = __get_first_arg<_Ptr>; +template struct __ptr_traits_impl; +template +struct pointer_traits : __ptr_traits_impl<__ptr_traits_elem_t<_Ptr>> {}; +struct allocator_traits { + using type = pointer_traits; +}; +} // namespace std +namespace std { +inline namespace __cxx11 { +template class basic_string { + allocator_traits _M_allocated_capacity; + void _M_assign(); +}; +} // namespace __cxx11 +} // namespace std +namespace std { +template void operator!=(_Alloc, _CharT); +template +basic_istream<_CharT, _Traits> &getline(basic_istream<_CharT, _Traits> &, + basic_string<_CharT, _Traits, _Alloc> &, + _CharT); +} // namespace std +namespace std { +template +void basic_string<_CharT, _Traits, _Alloc>::_M_assign() { + this != 0; +} +template +basic_istream<_CharT, _Traits> &getline(basic_istream<_CharT, _Traits> &, + basic_string<_CharT, _Traits, _Alloc> &, + _CharT) {} +} // namespace std +struct CommandLineOptionDefinition { + void *OutAddress; +}; +struct CommandLineCommand { + CommandLineOptionDefinition Options; +}; +namespace CommandLine { +extern const CommandLineCommand RootCommands[]; +extern const int RootExamples[]; +} // namespace CommandLine +using utf8 = char; +using u8string = std::basic_string; +u8string _rct2DataPath; +CommandLineOptionDefinition StandardOptions{&_rct2DataPath}; +const CommandLineCommand CommandLine::RootCommands[]{StandardOptions}; +const int CommandLine::RootExamples[]{}; diff --git a/clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp.externalDefMap.ast-dump.txt b/clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp.externalDefMap.ast-dump.txt new file mode 100644 index 0000000000000..6ffb3795d3e36 --- /dev/null +++ b/clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp.externalDefMap.ast-dump.txt @@ -0,0 +1,5 @@ +47:c:@N@std@S@allocator_traits@F@allocator_traits# ctu-test-import-failure-import.cpp.ast +29:c:@N@CommandLine@RootCommands ctu-test-import-failure-import.cpp.ast +55:c:@N@std@N@__cxx11@ST>3#T#T#T@basic_string@F@_M_assign# ctu-test-import-failure-import.cpp.ast +97:c:@S@CommandLineOptionDefinition@F@CommandLineOptionDefinition#&1$@S@CommandLineOptionDefinition# ctu-test-import-failure-import.cpp.ast +29:c:@N@CommandLine@RootExamples ctu-test-import-failure-import.cpp.ast \ No newline at end of file diff --git a/clang/test/Analysis/ctu-test-import-failure.cpp b/clang/test/Analysis/ctu-test-import-failure.cpp new file mode 100644 index 0000000000000..c586b9aa9a310 --- /dev/null +++ b/clang/test/Analysis/ctu-test-import-failure.cpp @@ -0,0 +1,34 @@ +// RUN: rm -rf %t && mkdir %t +// RUN: mkdir -p %t/ctudir +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -std=c++17 \ +// RUN: -emit-pch -o %t/ctudir/ctu-test-import-failure-import.cpp.ast %S/Inputs/ctu-test-import-failure-import.cpp +// RUN: cp %S/Inputs/ctu-test-import-failure-import.cpp.externalDefMap.ast-dump.txt %t/ctudir/externalDefMap.txt +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -std=c++17 -analyze \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config ctu-dir=%t/ctudir \ +// RUN: -verify %s + +// Check that importing this code does not cause crash. +// Import intentionally fails because mismatch of '__get_first_arg'. + +namespace std { +inline namespace __cxx11 {} +template class basic_istream; +struct __get_first_arg; +inline namespace __cxx11 { +template class basic_string; +} +template +basic_istream<_CharT, _Traits> &getline(basic_istream<_CharT, _Traits> &, + basic_string<_CharT, _Traits, _Alloc> &, + _CharT) {} +} // namespace std +namespace CommandLine { +extern const int RootExamples[]; +} + +// expected-warning@Inputs/ctu-test-import-failure-import.cpp:18{{incompatible definitions}} +// expected-warning@Inputs/ctu-test-import-failure-import.cpp:18{{incompatible definitions}} +// expected-note@Inputs/ctu-test-import-failure-import.cpp:18{{no corresponding field here}} +// expected-note@Inputs/ctu-test-import-failure-import.cpp:18{{no corresponding field here}} From 6e82f66029eb64a2a22af55477608c14f7d152ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= Date: Mon, 27 Jan 2025 16:55:49 +0100 Subject: [PATCH 3/3] small simplification of test --- .../Analysis/Inputs/ctu-test-import-failure-import.cpp | 6 +----- clang/test/Analysis/ctu-test-import-failure.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp b/clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp index d5e6ba8852872..ffe860870a214 100644 --- a/clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp +++ b/clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp @@ -5,12 +5,8 @@ class basic_string; } template class basic_istream; template struct __get_first_arg; -template using __ptr_traits_elem_t = __get_first_arg<_Ptr>; -template struct __ptr_traits_impl; -template -struct pointer_traits : __ptr_traits_impl<__ptr_traits_elem_t<_Ptr>> {}; struct allocator_traits { - using type = pointer_traits; + using type = __get_first_arg; }; } // namespace std namespace std { diff --git a/clang/test/Analysis/ctu-test-import-failure.cpp b/clang/test/Analysis/ctu-test-import-failure.cpp index c586b9aa9a310..2295a66538fc9 100644 --- a/clang/test/Analysis/ctu-test-import-failure.cpp +++ b/clang/test/Analysis/ctu-test-import-failure.cpp @@ -28,7 +28,7 @@ namespace CommandLine { extern const int RootExamples[]; } -// expected-warning@Inputs/ctu-test-import-failure-import.cpp:18{{incompatible definitions}} -// expected-warning@Inputs/ctu-test-import-failure-import.cpp:18{{incompatible definitions}} -// expected-note@Inputs/ctu-test-import-failure-import.cpp:18{{no corresponding field here}} -// expected-note@Inputs/ctu-test-import-failure-import.cpp:18{{no corresponding field here}} +// expected-warning@Inputs/ctu-test-import-failure-import.cpp:14{{incompatible definitions}} +// expected-warning@Inputs/ctu-test-import-failure-import.cpp:14{{incompatible definitions}} +// expected-note@Inputs/ctu-test-import-failure-import.cpp:14{{no corresponding field here}} +// expected-note@Inputs/ctu-test-import-failure-import.cpp:14{{no corresponding field here}}