[clang] [clang] Fix crash when compiling error with invalid decl (PR #77893)

Qizhi Hu via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 12 00:40:20 PST 2024


https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/77893

`APValue::LValueBase::LValueBase` constructs `ValueDecl` with its canonicalDecl, even though it's invalid. And when obtain its type, it also check all redecls and ignore checking if it's valid. This will cause crash in invalid code. This patch fixes this issue by checking its validation and skip invalid decls.
Fix [issue](https://github.com/llvm/llvm-project/issues/69468)

>From 15c32039dfa8613a9ac992166dcb924cdd09ffa8 Mon Sep 17 00:00:00 2001
From: huqizhi <huqizhi at feysh.com>
Date: Thu, 11 Jan 2024 13:02:21 +0800
Subject: [PATCH 1/2] [Clang][SemaCXX] improve sema check of clang::musttail
 attribute

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++
 clang/lib/Sema/SemaStmt.cpp                      | 6 ++++++
 clang/test/SemaCXX/PR76631.cpp                   | 7 +++++++
 3 files changed, 15 insertions(+)
 create mode 100644 clang/test/SemaCXX/PR76631.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1a79892e40030ae..1006e7d65dd868c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3113,6 +3113,8 @@ def err_musttail_scope : Error<
   "cannot perform a tail call from this return statement">;
 def err_musttail_no_variadic : Error<
   "%0 attribute may not be used with variadic functions">;
+def err_musttail_no_return : Error<
+  "%0 attribute may not be used with no-return-attribute functions">;
 
 def err_nsobject_attribute : Error<
   "'NSObject' attribute is for pointer types only">;
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 21efe25ed84a3d2..9e7c8c7e4e8c12c 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -786,6 +786,12 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) {
     return false;
   }
 
+  const auto *CalleeDecl = CE->getCalleeDecl();
+  if (CalleeDecl && CalleeDecl->hasAttr<CXX11NoReturnAttr>()) {
+    Diag(St->getBeginLoc(), diag::err_musttail_no_return) << &MTA;
+    return false;
+  }
+
   // Caller and callee must match in whether they have a "this" parameter.
   if (CallerType.This.isNull() != CalleeType.This.isNull()) {
     if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
diff --git a/clang/test/SemaCXX/PR76631.cpp b/clang/test/SemaCXX/PR76631.cpp
new file mode 100644
index 000000000000000..df89753bd125804
--- /dev/null
+++ b/clang/test/SemaCXX/PR76631.cpp
@@ -0,0 +1,7 @@
+[[noreturn]] void throw_int() {
+  throw int();
+}
+
+void throw_int_wrapper() {
+  [[clang::musttail]] return throw_int(); // expected-error {{'musttail' attribute may not be used with no-return-attribute functions}}
+}

>From 0b3eac94c1eb584f97bbf657960f302db0dabebf Mon Sep 17 00:00:00 2001
From: huqizhi <huqizhi at feysh.com>
Date: Fri, 12 Jan 2024 15:15:37 +0800
Subject: [PATCH 2/2] [clang] Fix crash when compiling error with invalid decl

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td |  2 --
 clang/lib/AST/APValue.cpp                        |  8 ++++++--
 clang/lib/Sema/SemaStmt.cpp                      |  6 ------
 clang/test/AST/invalid-decl-no-crash.cpp         | 12 ++++++++++++
 clang/test/SemaCXX/PR76631.cpp                   |  7 -------
 5 files changed, 18 insertions(+), 17 deletions(-)
 create mode 100644 clang/test/AST/invalid-decl-no-crash.cpp
 delete mode 100644 clang/test/SemaCXX/PR76631.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1006e7d65dd868c..1a79892e40030ae 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3113,8 +3113,6 @@ def err_musttail_scope : Error<
   "cannot perform a tail call from this return statement">;
 def err_musttail_no_variadic : Error<
   "%0 attribute may not be used with variadic functions">;
-def err_musttail_no_return : Error<
-  "%0 attribute may not be used with no-return-attribute functions">;
 
 def err_nsobject_attribute : Error<
   "'NSObject' attribute is for pointer types only">;
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp
index 4eae308ef5b34c6..b1fd93b23f38cc6 100644
--- a/clang/lib/AST/APValue.cpp
+++ b/clang/lib/AST/APValue.cpp
@@ -40,7 +40,11 @@ static_assert(
     "Type is insufficiently aligned");
 
 APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V)
-    : Ptr(P ? cast<ValueDecl>(P->getCanonicalDecl()) : nullptr), Local{I, V} {}
+    : Ptr(P ? cast<ValueDecl>(P->getCanonicalDecl()->isInvalidDecl()
+                                  ? P
+                                  : P->getCanonicalDecl())
+            : nullptr),
+      Local{I, V} {}
 APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V)
     : Ptr(P), Local{I, V} {}
 
@@ -73,7 +77,7 @@ QualType APValue::LValueBase::getType() const {
     for (auto *Redecl = cast<ValueDecl>(D->getMostRecentDecl()); Redecl;
          Redecl = cast_or_null<ValueDecl>(Redecl->getPreviousDecl())) {
       QualType T = Redecl->getType();
-      if (!T->isIncompleteArrayType())
+      if (!T->isIncompleteArrayType() && !Redecl->isInvalidDecl())
         return T;
     }
     return D->getType();
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 9e7c8c7e4e8c12c..21efe25ed84a3d2 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -786,12 +786,6 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) {
     return false;
   }
 
-  const auto *CalleeDecl = CE->getCalleeDecl();
-  if (CalleeDecl && CalleeDecl->hasAttr<CXX11NoReturnAttr>()) {
-    Diag(St->getBeginLoc(), diag::err_musttail_no_return) << &MTA;
-    return false;
-  }
-
   // Caller and callee must match in whether they have a "this" parameter.
   if (CallerType.This.isNull() != CalleeType.This.isNull()) {
     if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
diff --git a/clang/test/AST/invalid-decl-no-crash.cpp b/clang/test/AST/invalid-decl-no-crash.cpp
new file mode 100644
index 000000000000000..2b35ef702ae553f
--- /dev/null
+++ b/clang/test/AST/invalid-decl-no-crash.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only %s -verify
+
+a[i] = b[i]; // expected-error {{use of undeclared identifier 'i'}} \
+                expected-error {{a type specifier is required for all declarations}} \
+                expected-error {{use of undeclared identifier 'b'}} \
+                expected-error {{use of undeclared identifier 'i'}}
+extern char b[];
+extern char a[];
+
+void foo(int j) {
+  a[j] = b[j];
+}
diff --git a/clang/test/SemaCXX/PR76631.cpp b/clang/test/SemaCXX/PR76631.cpp
deleted file mode 100644
index df89753bd125804..000000000000000
--- a/clang/test/SemaCXX/PR76631.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-[[noreturn]] void throw_int() {
-  throw int();
-}
-
-void throw_int_wrapper() {
-  [[clang::musttail]] return throw_int(); // expected-error {{'musttail' attribute may not be used with no-return-attribute functions}}
-}



More information about the cfe-commits mailing list