[clang] [Clang] prevent recovery call expression from proceeding with explicit attributes and undeclared templates (PR #107786)
Oleksandr T. via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 23 07:18:40 PDT 2024
https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/107786
>From 19e6556e0fb0add28c502bb82543bcdf820c1877 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Mon, 23 Sep 2024 17:17:30 +0300
Subject: [PATCH] [Clang] prevent recovery call expression from proceeding with
explicit attributes and undeclared templates
---
clang/docs/ReleaseNotes.rst | 2 ++
clang/include/clang/Sema/Sema.h | 4 ++-
clang/lib/Sema/SemaExpr.cpp | 12 +++++--
clang/lib/Sema/SemaOverload.cpp | 2 +-
clang/lib/Sema/SemaTemplate.cpp | 5 +++
.../SemaTemplate/recovery-crash-cxx20.cpp | 32 +++++++++++++++++++
6 files changed, 53 insertions(+), 4 deletions(-)
create mode 100644 clang/test/SemaTemplate/recovery-crash-cxx20.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b47e06cb0c5d68..110f75d739c072 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -424,6 +424,8 @@ Bug Fixes to C++ Support
- Fixed an assertion failure in debug mode, and potential crashes in release mode, when
diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter.
- Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326)
+- Fixed an assertion failure when invoking recovery call expressions with explicit attributes
+ and undeclared templates. (#GH107047, #GH49093)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e1c3a99cfa167e..b2eefdbd1c56d1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6753,7 +6753,9 @@ class Sema final : public SemaBase {
///
/// Return \c true if the error is unrecoverable, or \c false if the caller
/// should attempt to recover using these lookup results.
- bool DiagnoseDependentMemberLookup(const LookupResult &R);
+ bool DiagnoseDependentMemberLookup(
+ const LookupResult &R,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
/// Diagnose an empty lookup.
///
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 66df9c969256a2..a5770ae8848517 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2385,7 +2385,15 @@ static void emitEmptyLookupTypoDiagnostic(
SemaRef.PDiag(NoteID));
}
-bool Sema::DiagnoseDependentMemberLookup(const LookupResult &R) {
+bool Sema::DiagnoseDependentMemberLookup(
+ const LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs) {
+ auto IsTemplated = [](NamedDecl *D) { return D->isTemplated(); };
+ if (ExplicitTemplateArgs && !llvm::all_of(R, IsTemplated)) {
+ Diag(R.getNameLoc(), diag::err_non_template_in_template_id)
+ << R.getLookupName();
+ return true;
+ }
+
// During a default argument instantiation the CurContext points
// to a CXXMethodDecl; but we can't apply a this-> fixit inside a
// function parameter list, hence add an explicit check.
@@ -2487,7 +2495,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
R.resolveKind();
}
- return DiagnoseDependentMemberLookup(R);
+ return DiagnoseDependentMemberLookup(R, ExplicitTemplateArgs);
}
R.clear();
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index d304f322aced64..fe9b16e1890c16 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -13860,7 +13860,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
// enclosing class.
// FIXME: We should also explain why the candidates found by name lookup
// were not viable.
- if (SemaRef.DiagnoseDependentMemberLookup(R))
+ if (SemaRef.DiagnoseDependentMemberLookup(R, ExplicitTemplateArgs))
return ExprError();
} else {
// We had viable candidates and couldn't recover; let the caller diagnose
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 99423b01114cc6..3b3a8220331f76 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4617,6 +4617,11 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
R.getAsSingle<ConceptDecl>(), TemplateArgs);
}
+ if (TemplateArgs && R.getAsSingle<FunctionDecl>() &&
+ R.getAsSingle<FunctionDecl>()->getTemplateSpecializationKind() ==
+ TemplateSpecializationKind::TSK_Undeclared)
+ return ExprError();
+
// We don't want lookup warnings at this point.
R.suppressDiagnostics();
diff --git a/clang/test/SemaTemplate/recovery-crash-cxx20.cpp b/clang/test/SemaTemplate/recovery-crash-cxx20.cpp
new file mode 100644
index 00000000000000..dd92ddcd36ab02
--- /dev/null
+++ b/clang/test/SemaTemplate/recovery-crash-cxx20.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
+
+namespace GH49093 {
+ class B {
+ public:
+ static int a() { return 0; } // expected-note {{member is declared here}}
+ decltype(a< 0 >(0)) test; // expected-error {{member 'a' used before its declaration}}
+ };
+
+ struct C {
+ static int a() { return 0; } // expected-note {{member is declared here}}
+ decltype(a < 0 > (0)) test; // expected-error {{member 'a' used before its declaration}}
+ };
+
+ void test_is_bool(bool t) {}
+ void test_is_bool(int t) {}
+
+ int main() {
+ B b;
+ test_is_bool(b.test);
+
+ C c;
+ test_is_bool(c.test);
+ }
+}
+
+namespace GH107047 {
+ struct A {
+ static constexpr auto test() { return 1; } // expected-note {{member is declared here}}
+ static constexpr int s = test< 1 >(); // expected-error {{member 'test' used before its declaration}}
+ };
+}
More information about the cfe-commits
mailing list