-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[Clang] [Sema] Ensure noexcept(typeid(E)) checks if E throws when needed #95846
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Mital Ashok (MitalAshok) Changes3ad31e1 changed it so that not all potentially-evaluated Full diff: https://github.com/llvm/llvm-project/pull/95846.diff 2 Files Affected:
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 67e0c7c63909e..ef1128cedf994 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1111,13 +1111,18 @@ static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) {
}
static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) {
- if (DC->isTypeOperand())
+ // Operand is not evaluated, cannot possibly throw
+ if (!DC->isPotentiallyEvaluated())
return CT_Cannot;
if (DC->isValueDependent())
return CT_Dependent;
- return DC->hasNullCheck() ? CT_Can : CT_Cannot;
+ // Can throw std::bad_typeid if a nullptr is dereferenced
+ if (DC->hasNullCheck())
+ return CT_Can;
+
+ return S.canThrow(DC->getExprOperand());
}
CanThrowResult Sema::canThrow(const Stmt *S) {
diff --git a/clang/test/SemaCXX/cxx0x-noexcept-expression.cpp b/clang/test/SemaCXX/cxx0x-noexcept-expression.cpp
index c2b2244c117a0..1e86a31fffcbf 100644
--- a/clang/test/SemaCXX/cxx0x-noexcept-expression.cpp
+++ b/clang/test/SemaCXX/cxx0x-noexcept-expression.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s -fexceptions -fcxx-exceptions -Wno-unevaluated-expression
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s -fexceptions -fcxx-exceptions -Wno-unevaluated-expression -fexperimental-new-constant-interpreter
+namespace std {
+struct type_info;
+}
+
void f(); // expected-note {{possible target for call}}
void f(int); // expected-note {{possible target for call}}
@@ -97,3 +101,17 @@ void j() noexcept(0);
void k() noexcept(1);
void l() noexcept(2); // expected-error {{noexcept specifier argument evaluates to 2, which cannot be narrowed to type 'bool'}}
} // namespace P1401
+
+template<bool NoexceptConstructor, bool NoexceptDestructor>
+struct Polymorphic {
+ Polymorphic() noexcept(NoexceptConstructor) {}
+ virtual ~Polymorphic() noexcept(NoexceptDestructor) {}
+};
+
+static_assert(noexcept(typeid(Polymorphic<false, false>{}))); // Not evaluated (not glvalue)
+static_assert(noexcept(typeid((Polymorphic<true, true>&&) Polymorphic<true, true>{})));
+static_assert(!noexcept(typeid((Polymorphic<false, true>&&) Polymorphic<false, true>{})));
+static_assert(!noexcept(typeid((Polymorphic<true, false>&&) Polymorphic<true, false>{})));
+static_assert(!noexcept(typeid(*&(const Polymorphic<true, true>&) Polymorphic<true, true>{})));
+static_assert(!noexcept(typeid(*&(const Polymorphic<false, true>&) Polymorphic<false, true>{})));
+static_assert(!noexcept(typeid(*&(const Polymorphic<true, false>&) Polymorphic<true, false>{})));
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Co-authored-by: Timm Baeder <[email protected]>
…ion (which might become potentially evaluated once types are known)
Do we already have tests for your most recent commit (i.e. dependent expressions)? Because I recall CI passing even when that wasn’t there, but that may have been my imagination. |
@Sirraide Yes, the tests did pass because there were no tests for this. For reference:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, this does look like we’re handling all cases now (that I can think of at least).
However, I’d like to see some comments added to f1
–f3
, indicating why they’re dependent, because it took me a bit of thinking to figure that out just now...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, the comments are pretty much exactly what I had in mind.
In case anyone ends up being confused by the lack of a release note here: #95718 already added one that still covers everything done in this pr seeing as this is mostly a follow-up to that one. |
…ded (llvm#95846) 3ad31e1 changed it so that not all potentially-evaluated `typeid`s were marked as potentially-throwing, but I forgot to check the subexpression if the null check of the `typeid` didn't potentially-throw. This adds that check.
3ad31e1 changed it so that not all potentially-evaluated
typeid
s were marked as potentially-throwing, but I forgot to check the subexpression if the null check of thetypeid
didn't potentially-throw. This adds that check.