Author: Chuanqi Xu Date: 2022-07-21T17:25:05+08:00 New Revision: ea623af7c90f0c02fed72010a018cb1e259cca8d
URL: https://github.com/llvm/llvm-project/commit/ea623af7c90f0c02fed72010a018cb1e259cca8d DIFF: https://github.com/llvm/llvm-project/commit/ea623af7c90f0c02fed72010a018cb1e259cca8d.diff LOG: [C++20] [Modules] Avoid inifinite loop when iterating default args Currently, clang may meet an infinite loop in a very tricky case when it iterates the default args. This patch tries to fix this by adding a `fixed` check. Added: clang/test/Modules/inherited_arg.cppm Modified: clang/lib/Sema/SemaLookup.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index aa87a33ce8ae1..242e1f81d75c0 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1615,7 +1615,10 @@ hasAcceptableDefaultArgument(Sema &S, const ParmDecl *D, if (!D->hasDefaultArgument()) return false; - while (D) { + llvm::SmallDenseSet<const ParmDecl *, 4> Visited; + while (D && !Visited.count(D)) { + Visited.insert(D); + auto &DefaultArg = D->getDefaultArgStorage(); if (!DefaultArg.isInherited() && S.isAcceptable(D, Kind)) return true; @@ -1625,7 +1628,8 @@ hasAcceptableDefaultArgument(Sema &S, const ParmDecl *D, Modules->push_back(S.getOwningModule(NonConstD)); } - // If there was a previous default argument, maybe its parameter is visible. + // If there was a previous default argument, maybe its parameter is + // acceptable. D = DefaultArg.getInheritedFrom(); } return false; diff --git a/clang/test/Modules/inherited_arg.cppm b/clang/test/Modules/inherited_arg.cppm new file mode 100644 index 0000000000000..eb66b70cdce33 --- /dev/null +++ b/clang/test/Modules/inherited_arg.cppm @@ -0,0 +1,78 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_cc1 -std=c++20 %t/A-B.cppm -I%t -emit-module-interface -o %t/A-B.pcm +// RUN: %clang_cc1 -std=c++20 %t/A-C.cppm -I%t -emit-module-interface -o %t/A-C.pcm +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -fprebuilt-module-path=%t -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only + +//--- foo.h +template <typename U, typename T> +class pair {}; + +template <typename U> +class allocator {}; + +template <typename T> +class my_traits {}; + +template <class _Key, class _Tp, + class _Alloc = allocator<pair<const _Key, _Tp> > > +class unordered_map +{ +public: + unordered_map() {} +}; + +template<bool, class = void> struct my_enable_if {}; +template<class T> struct my_enable_if<true, T> { using type = T; }; +template<bool B, class T = void> using my_enable_if_t = typename my_enable_if<B, T>::type; + +template<class _InputIterator, + class _Allocator = allocator<my_traits<_InputIterator>>, + class = my_enable_if_t<_InputIterator::value>> +unordered_map(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> unordered_map<my_traits<_InputIterator>, my_traits<_InputIterator>, _Allocator>; + +template <class _CharT, + class _Traits = my_traits<_CharT>, + class _Allocator = allocator<_CharT> > + class basic_string; +typedef basic_string<char, my_traits<char>, allocator<char> > string; + +template<class _CharT, class _Traits, class _Allocator> +class basic_string +{ +public: + basic_string(); + + template<class _InputIterator, class = my_enable_if_t<_InputIterator::value> > + basic_string(_InputIterator __first, _InputIterator __last, const _Allocator& __a); + + void resize(unsigned __n, _CharT __c); +}; + +extern template void basic_string<char>::resize(unsigned, char); + +//--- A-B.cppm +module; +#include "foo.h" +export module A:B; +export using ::string; + +//--- A-C.cppm +module; +#include "foo.h" +export module A:C; + +//--- A.cppm +export module A; +export import :B; +export import :C; + +//--- Use.cpp +import A; +string s; +::unordered_map<int, int> mime_map; // expected-error {{missing '#include'; 'unordered_map' must be declared before it is used}} + // expected-note@* {{declaration here is not visible}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits