Author: Balázs Kéri
Date: 2025-01-28T09:10:02+01:00
New Revision: 8e97f50eed71ff59b5a6fcb31e3e1af3fb30cdb4

URL: 
https://github.com/llvm/llvm-project/commit/8e97f50eed71ff59b5a6fcb31e3e1af3fb30cdb4
DIFF: 
https://github.com/llvm/llvm-project/commit/8e97f50eed71ff59b5a6fcb31e3e1af3fb30cdb4.diff

LOG: [clang][ASTImporter] Fix possible crash at import of function template 
(#124273)

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.

Added: 
    clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp
    
clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp.externalDefMap.ast-dump.txt
    clang/test/Analysis/ctu-test-import-failure.cpp

Modified: 
    clang/lib/AST/ASTImporter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 5433b6120ab9f2..09fa10f716ec1f 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -6759,6 +6759,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>(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 00000000000000..ffe860870a2140
--- /dev/null
+++ b/clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp
@@ -0,0 +1,52 @@
+namespace std {
+inline namespace __cxx11 {
+template <typename _CharT, typename = int, typename = _CharT>
+class basic_string;
+}
+template <typename, typename> class basic_istream;
+template <typename> struct __get_first_arg;
+struct allocator_traits {
+  using type = __get_first_arg<int>;
+};
+} // namespace std
+namespace std {
+inline namespace __cxx11 {
+template <typename, typename, typename> class basic_string {
+  allocator_traits _M_allocated_capacity;
+  void _M_assign();
+};
+} // namespace __cxx11
+} // namespace std
+namespace std {
+template <typename _CharT, typename _Alloc> void operator!=(_Alloc, _CharT);
+template <typename _CharT, typename _Traits, typename _Alloc>
+basic_istream<_CharT, _Traits> &getline(basic_istream<_CharT, _Traits> &,
+                                        basic_string<_CharT, _Traits, _Alloc> 
&,
+                                        _CharT);
+} // namespace std
+namespace std {
+template <typename _CharT, typename _Traits, typename _Alloc>
+void basic_string<_CharT, _Traits, _Alloc>::_M_assign() {
+  this != 0;
+}
+template <typename _CharT, typename _Traits, typename _Alloc>
+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<utf8>;
+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 00000000000000..6ffb3795d3e36a
--- /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 00000000000000..2295a66538fc9e
--- /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 <typename _CharT, typename> class basic_istream;
+struct __get_first_arg;
+inline namespace __cxx11 {
+template <typename, typename, typename> class basic_string;
+}
+template <typename _CharT, typename _Traits, typename _Alloc>
+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: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}}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to