r313906 - [Sema] Prevent InstantiateClass from checking unrelated exception specs.
Volodymyr Sapsai via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 21 12:54:12 PDT 2017
Author: vsapsai
Date: Thu Sep 21 12:54:12 2017
New Revision: 313906
URL: http://llvm.org/viewvc/llvm-project?rev=313906&view=rev
Log:
[Sema] Prevent InstantiateClass from checking unrelated exception specs.
Sema::InstantiateClass should check only exception specs added during
class instantiation and ignore already present delayed specs. This fixes
a case where we instantiate a class before parsing member initializers,
check exceptions for a different class and fail to find a member
initializer. Which is required for comparing exception specs for
explicitly-defaulted and implicit default constructor. With the fix we
are still checking exception specs but only after member initializers
are present.
Removing errors in crash-unparsed-exception.cpp is acceptable according
to discussion in PR24000 because other compilers accept code in
crash-unparsed-exception.cpp as valid.
rdar://problem/34167492
Reviewers: davide, rsmith
Reviewed By: rsmith
Subscribers: dim, cfe-commits
Differential Revision: https://reviews.llvm.org/D37881
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/test/SemaTemplate/crash-unparsed-exception.cpp
cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=313906&r1=313905&r2=313906&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Sep 21 12:54:12 2017
@@ -10503,6 +10503,36 @@ public:
SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses;
private:
+ class SavePendingParsedClassStateRAII {
+ public:
+ SavePendingParsedClassStateRAII(Sema &S) : S(S) { swapSavedState(); }
+
+ ~SavePendingParsedClassStateRAII() {
+ assert(S.DelayedExceptionSpecChecks.empty() &&
+ "there shouldn't be any pending delayed exception spec checks");
+ assert(S.DelayedDefaultedMemberExceptionSpecs.empty() &&
+ "there shouldn't be any pending delayed defaulted member "
+ "exception specs");
+ assert(S.DelayedDllExportClasses.empty() &&
+ "there shouldn't be any pending delayed DLL export classes");
+ swapSavedState();
+ }
+
+ private:
+ Sema &S;
+ decltype(DelayedExceptionSpecChecks) SavedExceptionSpecChecks;
+ decltype(DelayedDefaultedMemberExceptionSpecs)
+ SavedDefaultedMemberExceptionSpecs;
+ decltype(DelayedDllExportClasses) SavedDllExportClasses;
+
+ void swapSavedState() {
+ SavedExceptionSpecChecks.swap(S.DelayedExceptionSpecChecks);
+ SavedDefaultedMemberExceptionSpecs.swap(
+ S.DelayedDefaultedMemberExceptionSpecs);
+ SavedDllExportClasses.swap(S.DelayedDllExportClasses);
+ }
+ };
+
/// \brief Helper class that collects misaligned member designations and
/// their location info for delayed diagnostics.
struct MisalignedMember {
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=313906&r1=313905&r2=313906&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Sep 21 12:54:12 2017
@@ -2026,12 +2026,11 @@ Sema::InstantiateClass(SourceLocation Po
bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod();
LocalInstantiationScope Scope(*this, MergeWithParentScope);
- // All dllexported classes created during instantiation should be fully
- // emitted after instantiation completes. We may not be ready to emit any
- // delayed classes already on the stack, so save them away and put them back
- // later.
- decltype(DelayedDllExportClasses) ExportedClasses;
- std::swap(ExportedClasses, DelayedDllExportClasses);
+ // Some class state isn't processed immediately but delayed till class
+ // instantiation completes. We may not be ready to handle any delayed state
+ // already on the stack as it might correspond to a different class, so save
+ // it now and put it back later.
+ SavePendingParsedClassStateRAII SavedPendingParsedClassState(*this);
// Pull attributes from the pattern onto the instantiation.
InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
@@ -2118,9 +2117,6 @@ Sema::InstantiateClass(SourceLocation Po
// default arg exprs for default constructors if necessary now.
ActOnFinishCXXNonNestedClass(Instantiation);
- // Put back the delayed exported classes that we moved out of the way.
- std::swap(ExportedClasses, DelayedDllExportClasses);
-
// Instantiate late parsed attributes, and attach them to their decls.
// See Sema::InstantiateAttrs
for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
Modified: cfe/trunk/test/SemaTemplate/crash-unparsed-exception.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/crash-unparsed-exception.cpp?rev=313906&r1=313905&r2=313906&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/crash-unparsed-exception.cpp (original)
+++ cfe/trunk/test/SemaTemplate/crash-unparsed-exception.cpp Thu Sep 21 12:54:12 2017
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -fcxx-exceptions -fexceptions %s
+// expected-no-diagnostics
struct A {
virtual ~A();
@@ -11,7 +12,7 @@ struct C {
~D() throw();
};
struct E : A {
- D<int> d; //expected-error{{exception specification is not available until end of class definition}}
+ D<int> d;
};
- B<int> b; //expected-note{{in instantiation of template class 'B<int>' requested here}}
+ B<int> b;
};
Modified: cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp?rev=313906&r1=313905&r2=313906&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp (original)
+++ cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp Thu Sep 21 12:54:12 2017
@@ -87,3 +87,30 @@ namespace PR13986 {
A<1> m_target;
};
}
+
+// rdar://problem/34167492
+// Template B is instantiated during checking if defaulted A copy constructor
+// is constexpr. For this we check if S<int> copy constructor is constexpr. And
+// for this we check S constructor template with default argument that mentions
+// template B. In turn, template instantiation triggers checking defaulted
+// members exception spec. The problem is that it checks defaulted members not
+// for instantiated class only, but all defaulted members so far. In this case
+// we try to check exception spec for A default constructor which requires
+// initializer for the field _a. But initializers are added after constexpr
+// check so we reject the code because cannot find _a initializer.
+namespace rdar34167492 {
+ template <typename T> struct B { using type = bool; };
+
+ template <typename T> struct S {
+ S() noexcept;
+
+ template <typename U, typename B<U>::type = true>
+ S(const S<U>&) noexcept;
+ };
+
+ class A {
+ A() noexcept = default;
+ A(const A&) noexcept = default;
+ S<int> _a{};
+ };
+}
More information about the cfe-commits
mailing list