Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6755,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>(ASTImportError::NameConflict);

TemplatedFD->setDescribedFunctionTemplate(ToFunc);

ToFunc->setAccess(D->getAccess());
Expand Down
56 changes: 56 additions & 0 deletions clang/test/Analysis/Inputs/ctu-test-import-failure-import.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
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;
template <typename _Ptr> using __ptr_traits_elem_t = __get_first_arg<_Ptr>;
template <typename> struct __ptr_traits_impl;
template <typename _Ptr>
struct pointer_traits : __ptr_traits_impl<__ptr_traits_elem_t<_Ptr>> {};
struct allocator_traits {
using type = pointer_traits<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[]{};
Original file line number Diff line number Diff line change
@@ -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
34 changes: 34 additions & 0 deletions clang/test/Analysis/ctu-test-import-failure.cpp
Original file line number Diff line number Diff line change
@@ -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: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}}
Loading