Skip to content

[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

Merged
merged 5 commits into from
Jun 20, 2024

Conversation

MitalAshok
Copy link
Contributor

3ad31e1 changed it so that not all potentially-evaluated typeids 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.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jun 17, 2024
@llvmbot
Copy link
Member

llvmbot commented Jun 17, 2024

@llvm/pr-subscribers-clang

Author: Mital Ashok (MitalAshok)

Changes

3ad31e1 changed it so that not all potentially-evaluated typeids 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.


Full diff: https://github.com/llvm/llvm-project/pull/95846.diff

2 Files Affected:

  • (modified) clang/lib/Sema/SemaExceptionSpec.cpp (+7-2)
  • (modified) clang/test/SemaCXX/cxx0x-noexcept-expression.cpp (+18)
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>{})));

@MitalAshok
Copy link
Contributor Author

CC @Endilll @Sirraide

Copy link
Member

@Sirraide Sirraide left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

MitalAshok and others added 2 commits June 18, 2024 06:05
…ion (which might become potentially evaluated once types are known)
@Sirraide
Copy link
Member

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.

@MitalAshok
Copy link
Contributor Author

@Sirraide Yes, the tests did pass because there were no tests for this.

For reference:

Copy link
Member

@Sirraide Sirraide left a 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 f1f3, indicating why they’re dependent, because it took me a bit of thinking to figure that out just now...

Copy link
Member

@Sirraide Sirraide left a 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.

@Sirraide
Copy link
Member

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.

@Sirraide Sirraide merged commit b608b22 into llvm:main Jun 20, 2024
7 checks passed
AlexisPerry pushed a commit to llvm-project-tlp/llvm-project that referenced this pull request Jul 9, 2024
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants