[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