[clang] [llvm] Return available function types for BindingDecls. (PR #102196)

Samira Bazuzi via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 7 09:49:47 PDT 2024


https://github.com/bazuzi updated https://github.com/llvm/llvm-project/pull/102196

>From 052eff82638bdfbc8c7b8a2b90bcd9a0c46e52c4 Mon Sep 17 00:00:00 2001
From: Samira Bazuzi <bazuzi at google.com>
Date: Tue, 6 Aug 2024 14:11:46 -0400
Subject: [PATCH 1/2] Return available function types for BindingDecls.

Only return nullptr when we don't have an available QualType.
---
 clang/lib/AST/DeclBase.cpp | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 98a7746b7d997..129a119267890 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -1161,15 +1161,20 @@ int64_t Decl::getID() const {
 
 const FunctionType *Decl::getFunctionType(bool BlocksToo) const {
   QualType Ty;
-  if (isa<BindingDecl>(this))
-    return nullptr;
-  else if (const auto *D = dyn_cast<ValueDecl>(this))
+  if (const auto *D = dyn_cast<ValueDecl>(this))
     Ty = D->getType();
   else if (const auto *D = dyn_cast<TypedefNameDecl>(this))
     Ty = D->getUnderlyingType();
   else
     return nullptr;
 
+  if (Ty.isNull()) {
+    // BindingDecls do not have types during parsing, so return nullptr. This is
+    // the only known case where `Ty` is null.
+    assert(isa<BindingDecl>(this));
+    return nullptr;
+  }
+
   if (Ty->isFunctionPointerType())
     Ty = Ty->castAs<PointerType>()->getPointeeType();
   else if (Ty->isFunctionReferenceType())

>From 56a9d3d2e29289323f30b6dbed2b43a6a76a6b08 Mon Sep 17 00:00:00 2001
From: Samira Bazuzi <bazuzi at google.com>
Date: Wed, 7 Aug 2024 12:37:24 -0400
Subject: [PATCH 2/2] Add unit test for BindingDecl.getFunctionType().

---
 clang/unittests/AST/CMakeLists.txt            |  1 +
 clang/unittests/AST/DeclBaseTest.cpp          | 59 +++++++++++++++++++
 .../gn/secondary/clang/unittests/AST/BUILD.gn |  1 +
 3 files changed, 61 insertions(+)
 create mode 100644 clang/unittests/AST/DeclBaseTest.cpp

diff --git a/clang/unittests/AST/CMakeLists.txt b/clang/unittests/AST/CMakeLists.txt
index dcc9bc0f39ac2..51245599736cf 100644
--- a/clang/unittests/AST/CMakeLists.txt
+++ b/clang/unittests/AST/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_unittest(ASTTests
   CommentTextTest.cpp
   ConceptPrinterTest.cpp
   DataCollectionTest.cpp
+  DeclBaseTest.cpp
   DeclPrinterTest.cpp
   DeclTest.cpp
   EvaluateAsRValueTest.cpp
diff --git a/clang/unittests/AST/DeclBaseTest.cpp b/clang/unittests/AST/DeclBaseTest.cpp
new file mode 100644
index 0000000000000..39e97aa731196
--- /dev/null
+++ b/clang/unittests/AST/DeclBaseTest.cpp
@@ -0,0 +1,59 @@
+//===- unittests/AST/DeclBaseTest.cpp --- Declaration tests----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Unit tests for Decl class in the AST.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+using ::clang::BindingDecl;
+using ::clang::ast_matchers::bindingDecl;
+using ::clang::ast_matchers::hasName;
+using ::clang::ast_matchers::match;
+using ::clang::ast_matchers::selectFirst;
+
+TEST(DeclGetFunctionType, BindingDecl) {
+  llvm::StringRef Code = R"cpp(
+    template <typename A, typename B>
+    struct Pair {
+      A AnA;
+      B AB;
+    };
+
+    void target(int *i) {
+      Pair<void (*)(int *), bool> P;
+      auto [FunctionPointer, B] = P;
+      FunctionPointer(i);
+    }
+  )cpp";
+
+  auto AST =
+      clang::tooling::buildASTFromCodeWithArgs(Code, /*Args=*/{"-std=c++20"});
+  clang::ASTContext &Ctx = AST->getASTContext();
+
+  auto *BD = selectFirst<clang::BindingDecl>(
+      "FunctionPointer",
+      match(bindingDecl(hasName("FunctionPointer")).bind("FunctionPointer"),
+            Ctx));
+  ASSERT_NE(BD, nullptr);
+
+  EXPECT_NE(BD->getFunctionType(), nullptr);
+
+  // Emulate a call before the BindingDecl has a bound type.
+  const_cast<clang::BindingDecl *>(BD)->setBinding(clang::QualType(), nullptr);
+  EXPECT_EQ(BD->getFunctionType(), nullptr);
+}
diff --git a/llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn
index 7451c406d2ac8..4b905c17eea44 100644
--- a/llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn
@@ -34,6 +34,7 @@ unittest("ASTTests") {
     "CommentTextTest.cpp",
     "ConceptPrinterTest.cpp",
     "DataCollectionTest.cpp",
+    "DeclBaseTest.cpp",
     "DeclPrinterTest.cpp",
     "DeclTest.cpp",
     "EvaluateAsRValueTest.cpp",



More information about the cfe-commits mailing list