[PATCH] D118744: [clang] Don't cache function type after clearing clang->llvm type cache

Arthur Eubanks via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 1 16:58:06 PST 2022


aeubanks created this revision.
aeubanks requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

We clear the type cache when SkippedLayout is true and we're converting
a function type. However, we then immediately put the computed entry in
the cache. A later query with different context may incorrectly use the
cached entry. So don't cache the entry in that case.

For example in the test case we give up converting the exact function
type when seeing z(*)() in the context of z::p, but not g().

I've added a check that the cached type matches what we compute. It
triggered in this test case without the fix. It's currently not
check-clang clean so it's not on by default for something like expensive
checks builds.

Fixes PR53465.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D118744

Files:
  clang/lib/CodeGen/CodeGenTypes.cpp
  clang/test/CodeGenCXX/pr53465.cpp


Index: clang/test/CodeGenCXX/pr53465.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/pr53465.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -mllvm -verify-type-cache -emit-llvm %s -o - -triple i386-pc-windows-msvc19.16.0 | FileCheck %s
+// REQUIRES: asserts
+
+// CHECK: call {}* @"?f@@YA?AUz@@XZ"()
+
+struct z {
+  z (*p)();
+};
+
+z f();
+
+void g() {
+  f();
+}
Index: clang/lib/CodeGen/CodeGenTypes.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenTypes.cpp
+++ clang/lib/CodeGen/CodeGenTypes.cpp
@@ -25,9 +25,20 @@
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Support/CommandLine.h"
+
 using namespace clang;
 using namespace CodeGen;
 
+#ifndef NDEBUG
+// TODO: turn on by default when defined(EXPENSIVE_CHECKS) once check-clang is
+// clean
+static llvm::cl::opt<bool> VerifyTypeCache(
+    "verify-type-cache",
+    llvm::cl::desc("Verify that the type cache matches the computed type"),
+    llvm::cl::init(false), llvm::cl::Hidden);
+#endif
+
 CodeGenTypes::CodeGenTypes(CodeGenModule &cgm)
   : CGM(cgm), Context(cgm.getContext()), TheModule(cgm.getModule()),
     Target(cgm.getTarget()), TheCXXABI(cgm.getCXXABI()),
@@ -382,12 +393,10 @@
 
   RecordsBeingLaidOut.erase(Ty);
 
-  if (SkippedLayout)
-    TypeCache.clear();
-
   if (RecordsBeingLaidOut.empty())
     while (!DeferredRecords.empty())
       ConvertRecordDeclType(DeferredRecords.pop_back_val());
+
   return ResultType;
 }
 
@@ -418,8 +427,16 @@
   // See if type is already cached.
   llvm::DenseMap<const Type *, llvm::Type *>::iterator TCI = TypeCache.find(Ty);
   // If type is found in map then use it. Otherwise, convert type T.
-  if (TCI != TypeCache.end())
-    return TCI->second;
+
+  llvm::Type *CachedType = TCI != TypeCache.end() ? TCI->second : nullptr;
+  if (CachedType) {
+#ifndef NDEBUG
+    if (!VerifyTypeCache)
+      return CachedType;
+#else
+    return CachedType;
+#endif
+  }
 
   // If we don't have it in the cache, convert it now.
   llvm::Type *ResultType = nullptr;
@@ -797,7 +814,18 @@
 
   assert(ResultType && "Didn't convert a type?");
 
-  TypeCache[Ty] = ResultType;
+#ifndef NDEBUG
+  if (CachedType) {
+    assert(CachedType == ResultType &&
+           "Cached type doesn't match computed type");
+  }
+#endif
+
+  if (SkippedLayout && (Ty->getTypeClass() == Type::FunctionNoProto ||
+                        Ty->getTypeClass() == Type::FunctionProto))
+    TypeCache.clear();
+  else
+    TypeCache[Ty] = ResultType;
   return ResultType;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D118744.405125.patch
Type: text/x-patch
Size: 2642 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220202/ce3c4490/attachment.bin>


More information about the cfe-commits mailing list