[PATCH] D72103: [Sema] Avoid using an invalid InsertPos
Mark de Wever via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 2 12:59:30 PST 2020
Mordante created this revision.
Mordante added reviewers: lvoufo, rsmith.
Mordante added a project: clang.
The function `Sema::CheckVarTemplateId` tries to find a template specialization. If that fails it gets an `InsertPos` where the specialization should be added in a `FoldingSet`. Then it tries to resolve dependant arguments. This may add an item to the same `FoldingSet`. If this happens the set may be resized, which invalidates `InsertPos`.
It would be possible to send a `nullptr` to the call to `BuildVarTemplateInstantiation`, but that changes the behavior and fixing that seemed quite intrusive. Therefore the `InsertPos` is determined again before making the call.
Fixes PR43221: Assertion failure in translation unit with exactly 1 less than a power of 2 (starting at 127) operator== overloads combined with at least one operator== template with a substitution failure
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D72103
Files:
clang/lib/Sema/SemaTemplate.cpp
clang/test/SemaTemplate/instantiate-var-template.cpp
Index: clang/test/SemaTemplate/instantiate-var-template.cpp
===================================================================
--- clang/test/SemaTemplate/instantiate-var-template.cpp
+++ clang/test/SemaTemplate/instantiate-var-template.cpp
@@ -40,3 +40,64 @@
template<typename... T> A<T...> models;
template<> struct B models<>; // expected-error {{incomplete type 'struct B'}} expected-note {{forward declaration}}
}
+
+namespace PR43221 {
+// This test crashed before so the main reason for the test is to see that it
+// no longer will crash.
+
+template <bool>
+struct enable_if;
+
+template <>
+struct enable_if<true> { using type = void; };
+
+template <typename T, typename = void>
+constexpr bool always_false = false;
+
+// expected-note at +2 {{in instantiation of member function}}
+template <typename T>
+constexpr bool always_false<T, decltype(foo(T()))> = T() == T();
+
+template <typename T, typename = typename enable_if<always_false<T>>::type>
+bool operator==(T, T);
+
+// expected-note at +2 {{candidate template ignored: substitution failure}}
+template <typename T, typename = typename enable_if<always_false<T>>::type>
+void data(T);
+
+template <int>
+struct S {};
+template <int x>
+constexpr bool operator==(S<x>, S<x>) { return false; }
+
+template <int x>
+constexpr bool s = S<x>() == S<x>() and s<x - 1>;
+
+template <>
+constexpr bool s<0> = S<0>() == S<0>();
+
+void test() { s<127>; } // expected-warning {{expression result unused}}
+
+// expected-note at +2 {{while substituting deduced template arguments into function template}}
+template <typename T>
+struct wrapper {
+ wrapper() = default;
+ wrapper(wrapper &&) = default;
+
+ // expected-note at +2 {{during template argument deduction for variable template partial specialization}}
+ // expected-note at +2 {{in instantiation of default argument}}
+ template <typename U, typename = typename enable_if<always_false<U>>::type>
+ explicit wrapper(U);
+
+ // expected-error at +1 {{no matching function for call to 'data'}}
+ friend auto foo(wrapper w) { data(w.m); }
+
+ int m;
+};
+
+// expected-note at +1 {{while declaring the implicit copy constructor for}}
+struct wrapper2 {
+ wrapper<void> m;
+};
+
+} // namespace PR43221
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -4160,6 +4160,17 @@
}
}
+ // The InsertPos needs to be reloaded:
+ // The call to TemplateSpecializationType::anyDependentTemplateArguments
+ // above may call ASTContext::getSubstTemplateTypeParmType. This function
+ // adds a new element in the FoldingSet InsertPos points at. If the
+ // FoldingSet resizes due to this insertion the 'iterator' is no longer
+ // valid.
+ VarTemplateSpecializationDecl *Spec =
+ Template->findSpecialization(Converted, InsertPos);
+ assert(!Spec && "Reloading InsertPos found a template specialization");
+ (void)Spec;
+
// 2. Create the canonical declaration.
// Note that we do not instantiate a definition until we see an odr-use
// in DoMarkVarDeclReferenced().
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D72103.235930.patch
Type: text/x-patch
Size: 3133 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200102/56a6c35d/attachment.bin>
More information about the cfe-commits
mailing list