[clang][modules] Add support for merging lifetime-extended temporaries

Summary: Add support for merging lifetime-extended temporaries

Reviewers: rsmith

Reviewed By: rsmith

Subscribers: xbolva00, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D70190
This commit is contained in:
Tyker 2019-11-30 16:42:33 +01:00
parent 67298d683c
commit a3cbe1a202
10 changed files with 84 additions and 1 deletions

View File

@ -3041,7 +3041,9 @@ public:
/// Implicit declaration of a temporary that was materialized by
/// a MaterializeTemporaryExpr and lifetime-extended by a declaration
class LifetimeExtendedTemporaryDecl final : public Decl {
class LifetimeExtendedTemporaryDecl final
: public Decl,
public Mergeable<LifetimeExtendedTemporaryDecl> {
friend class MaterializeTemporaryExpr;
friend class ASTDeclReader;

View File

@ -346,6 +346,8 @@ public:
void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
void VisitBlockDecl(const BlockDecl *D);
void VisitConceptDecl(const ConceptDecl *D);
void
VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
};
} // namespace clang

View File

@ -551,6 +551,14 @@ private:
llvm::DenseMap<Decl*, llvm::SmallVector<NamedDecl*, 2>>
AnonymousDeclarationsForMerging;
/// Key used to identify LifetimeExtendedTemporaryDecl for merging,
/// containing the lifetime-extending declaration and the mangling number.
using LETemporaryKey = std::pair<Decl *, unsigned>;
/// Map of already deserialiazed temporaries.
llvm::DenseMap<LETemporaryKey, LifetimeExtendedTemporaryDecl *>
LETemporaryForMerging;
struct FileDeclsInfo {
ModuleFile *Mod = nullptr;
ArrayRef<serialization::LocalDeclID> Decls;

View File

@ -1338,6 +1338,17 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) {
OS << " <<<NULL params x " << D->getNumParams() << ">>>";
}
void TextNodeDumper::VisitLifetimeExtendedTemporaryDecl(
const LifetimeExtendedTemporaryDecl *D) {
OS << " extended by ";
dumpBareDeclRef(D->getExtendingDecl());
OS << " mangling ";
{
ColorScope Color(OS, ShowColors, ValueColor);
OS << D->getManglingNumber();
}
}
void TextNodeDumper::VisitFieldDecl(const FieldDecl *D) {
dumpName(D);
dumpType(D->getType());

View File

@ -424,6 +424,8 @@ namespace clang {
template<typename T>
void mergeMergeable(Mergeable<T> *D);
void mergeMergeable(LifetimeExtendedTemporaryDecl *D);
void mergeTemplatePattern(RedeclarableTemplateDecl *D,
RedeclarableTemplateDecl *Existing,
DeclID DsID, bool IsKeyDecl);
@ -2358,6 +2360,7 @@ void ASTDeclReader::VisitLifetimeExtendedTemporaryDecl(
if (Record.readInt())
D->Value = new (D->getASTContext()) APValue(Record.readAPValue());
D->ManglingNumber = Record.readInt();
mergeMergeable(D);
}
std::pair<uint64_t, uint64_t>
@ -2555,6 +2558,25 @@ static bool allowODRLikeMergeInC(NamedDecl *ND) {
return false;
}
/// Attempts to merge LifetimeExtendedTemporaryDecl with
/// identical class definitions from two different modules.
void ASTDeclReader::mergeMergeable(LifetimeExtendedTemporaryDecl *D) {
// If modules are not available, there is no reason to perform this merge.
if (!Reader.getContext().getLangOpts().Modules)
return;
LifetimeExtendedTemporaryDecl *LETDecl = D;
LifetimeExtendedTemporaryDecl *&LookupResult =
Reader.LETemporaryForMerging[std::make_pair(
LETDecl->getExtendingDecl(), LETDecl->getManglingNumber())];
if (LookupResult)
Reader.getContext().setPrimaryMergedDecl(LETDecl,
LookupResult->getCanonicalDecl());
else
LookupResult = LETDecl;
}
/// Attempts to merge the given declaration (D) with another declaration
/// of the same entity, for the case where the entity is not actually
/// redeclarable. This happens, for instance, when merging the fields of

View File

@ -0,0 +1,2 @@
constexpr const int& LETemp = 0;

View File

@ -0,0 +1,4 @@
#include "a.h"
constexpr const int* PtrTemp1 = &LETemp;

View File

@ -0,0 +1,4 @@
#include "a.h"
constexpr const int* PtrTemp2 = &LETemp;

View File

@ -0,0 +1,14 @@
module "a" {
export *
header "a.h"
}
module "b" {
export *
header "b.h"
}
module "c" {
export *
header "c.h"
}

View File

@ -0,0 +1,14 @@
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-lifetime-extended-temporary -verify -std=c++11 %s -DORDER=1
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-lifetime-extended-temporary -verify -std=c++11 %s -DORDER=2
// expected-no-diagnostics
#if ORDER == 1
#include "c.h"
#include "b.h"
#else
#include "b.h"
#include "c.h"
#endif
static_assert(PtrTemp1 == &LETemp, "");
static_assert(PtrTemp1 == PtrTemp2, "");