diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/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 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::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; } diff --git a/clang/test/CodeGenCXX/type-cache.cpp b/clang/test/CodeGenCXX/type-cache.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/type-cache.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(); +}