summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/ASTMutationListener.h7
-rw-r--r--clang/include/clang/AST/DeclCXX.h4
-rw-r--r--clang/include/clang/Serialization/ASTWriter.h2
-rw-r--r--clang/lib/AST/DeclCXX.cpp9
-rw-r--r--clang/lib/Frontend/MultiplexConsumer.cpp7
-rw-r--r--clang/lib/Serialization/ASTCommon.h1
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp22
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp22
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp2
-rw-r--r--clang/test/Modules/Inputs/cxx-dtor/a.h1
-rw-r--r--clang/test/Modules/Inputs/cxx-dtor/b.h3
-rw-r--r--clang/test/Modules/Inputs/cxx-dtor/module.modulemap2
-rw-r--r--clang/test/Modules/cxx-dtor.cpp3
13 files changed, 73 insertions, 12 deletions
diff --git a/clang/include/clang/AST/ASTMutationListener.h b/clang/include/clang/AST/ASTMutationListener.h
index 48eb6292772..27fdeac6b1f 100644
--- a/clang/include/clang/AST/ASTMutationListener.h
+++ b/clang/include/clang/AST/ASTMutationListener.h
@@ -16,9 +16,10 @@
#include "clang/Basic/SourceLocation.h"
namespace clang {
- class CXXRecordDecl;
class ClassTemplateDecl;
class ClassTemplateSpecializationDecl;
+ class CXXDestructorDecl;
+ class CXXRecordDecl;
class Decl;
class DeclContext;
class FunctionDecl;
@@ -72,6 +73,10 @@ public:
/// \brief A function's return type has been deduced.
virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
+ /// \brief A virtual destructor's operator delete has been resolved.
+ virtual void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
+ const FunctionDecl *Delete) {}
+
/// \brief An implicit member got a definition.
virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index ed6e2dc752f..a5b44f4e80a 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -2372,9 +2372,7 @@ public:
bool isImplicitlyDeclared);
static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID);
- void setOperatorDelete(FunctionDecl *OD) {
- cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete = OD;
- }
+ void setOperatorDelete(FunctionDecl *OD);
const FunctionDecl *getOperatorDelete() const {
return cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete;
}
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index 0d7a9c8821c..175ee7a3b39 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -806,6 +806,8 @@ public:
const FunctionDecl *D) override;
void ResolvedExceptionSpec(const FunctionDecl *FD) override;
void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override;
+ void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
+ const FunctionDecl *Delete) override;
void CompletedImplicitDefinition(const FunctionDecl *D) override;
void StaticDataMemberInstantiated(const VarDecl *D) override;
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 87a063438bc..82fb2a6950a 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1886,6 +1886,15 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
isInline, isImplicitlyDeclared);
}
+void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD) {
+ auto *First = cast<CXXDestructorDecl>(getFirstDecl());
+ if (OD && !First->OperatorDelete) {
+ First->OperatorDelete = OD;
+ if (auto *L = getASTMutationListener())
+ L->ResolvedOperatorDelete(First, OD);
+ }
+}
+
void CXXConversionDecl::anchor() { }
CXXConversionDecl *
diff --git a/clang/lib/Frontend/MultiplexConsumer.cpp b/clang/lib/Frontend/MultiplexConsumer.cpp
index 3c4fed1d18e..0d69f570be5 100644
--- a/clang/lib/Frontend/MultiplexConsumer.cpp
+++ b/clang/lib/Frontend/MultiplexConsumer.cpp
@@ -99,6 +99,8 @@ public:
void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
const FunctionDecl *D) override;
void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override;
+ void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
+ const FunctionDecl *Delete) override;
void CompletedImplicitDefinition(const FunctionDecl *D) override;
void StaticDataMemberInstantiated(const VarDecl *D) override;
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
@@ -154,6 +156,11 @@ void MultiplexASTMutationListener::DeducedReturnType(const FunctionDecl *FD,
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->DeducedReturnType(FD, ReturnType);
}
+void MultiplexASTMutationListener::ResolvedOperatorDelete(
+ const CXXDestructorDecl *DD, const FunctionDecl *Delete) {
+ for (auto *L : Listeners)
+ L->ResolvedOperatorDelete(DD, Delete);
+}
void MultiplexASTMutationListener::CompletedImplicitDefinition(
const FunctionDecl *D) {
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
diff --git a/clang/lib/Serialization/ASTCommon.h b/clang/lib/Serialization/ASTCommon.h
index 88cdbcfe179..09e0a40f1c9 100644
--- a/clang/lib/Serialization/ASTCommon.h
+++ b/clang/lib/Serialization/ASTCommon.h
@@ -29,6 +29,7 @@ enum DeclUpdateKind {
UPD_CXX_ADDED_FUNCTION_DEFINITION,
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
UPD_CXX_INSTANTIATED_CLASS_DEFINITION,
+ UPD_CXX_RESOLVED_DTOR_DELETE,
UPD_CXX_RESOLVED_EXCEPTION_SPEC,
UPD_CXX_DEDUCED_RETURN_TYPE,
UPD_DECL_MARKED_USED,
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 5aeb3d1e517..2a01d853c7c 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1620,7 +1620,12 @@ void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
VisitCXXMethodDecl(D);
- D->OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx);
+ if (auto *OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx)) {
+ auto *Canon = cast<CXXDestructorDecl>(D->getCanonicalDecl());
+ // FIXME: Check consistency if we have an old and new operator delete.
+ if (!Canon->OperatorDelete)
+ Canon->OperatorDelete = OperatorDelete;
+ }
}
void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
@@ -3621,10 +3626,6 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
std::tie(CD->CtorInitializers, CD->NumCtorInitializers) =
Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx);
- if (auto *DD = dyn_cast<CXXDestructorDecl>(FD))
- // FIXME: Check consistency.
- DD->setOperatorDelete(Reader.ReadDeclAs<FunctionDecl>(ModuleFile,
- Record, Idx));
// Store the offset of the body so we can lazily load it later.
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
HasPendingBody = true;
@@ -3691,6 +3692,17 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
break;
}
+ case UPD_CXX_RESOLVED_DTOR_DELETE: {
+ // Set the 'operator delete' directly to avoid emitting another update
+ // record.
+ auto *Del = Reader.ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
+ auto *First = cast<CXXDestructorDecl>(D->getCanonicalDecl());
+ // FIXME: Check consistency if we have an old and new operator delete.
+ if (!First->OperatorDelete)
+ First->OperatorDelete = Del;
+ break;
+ }
+
case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
// FIXME: This doesn't send the right notifications if there are
// ASTMutationListeners other than an ASTWriter.
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index f92848ad21f..2e8e590eb53 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4761,6 +4761,10 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
break;
}
+ case UPD_CXX_RESOLVED_DTOR_DELETE:
+ AddDeclRef(Update.getDecl(), Record);
+ break;
+
case UPD_CXX_RESOLVED_EXCEPTION_SPEC:
addExceptionSpec(
*this,
@@ -4792,8 +4796,6 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
Record.push_back(Def->isInlined());
AddSourceLocation(Def->getInnerLocStart(), Record);
AddFunctionDefinition(Def, Record);
- if (auto *DD = dyn_cast<CXXDestructorDecl>(Def))
- Record.push_back(GetDeclRef(DD->getOperatorDelete()));
}
OffsetsRecord.push_back(GetDeclRef(D));
@@ -5810,6 +5812,22 @@ void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
DeclUpdates[FD].push_back(DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType));
}
+void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD,
+ const FunctionDecl *Delete) {
+ assert(!WritingAST && "Already writing the AST!");
+ assert(Delete && "Not given an operator delete");
+ for (auto *D : DD->redecls()) {
+ if (D->isFromASTFile()) {
+ // We added an operator delete that some imported destructor didn't
+ // know about. Add an update record to let importers of us and that
+ // declaration know about it.
+ DeclUpdates[DD].push_back(
+ DeclUpdate(UPD_CXX_RESOLVED_DTOR_DELETE, Delete));
+ return;
+ }
+ }
+}
+
void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
assert(!WritingAST && "Already writing the AST!");
if (!D->isFromASTFile())
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 723f4caea80..ee0d21999b3 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1129,7 +1129,7 @@ void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
VisitCXXMethodDecl(D);
- Writer.AddDeclRef(D->OperatorDelete, Record);
+ Writer.AddDeclRef(D->getOperatorDelete(), Record);
Code = serialization::DECL_CXX_DESTRUCTOR;
}
diff --git a/clang/test/Modules/Inputs/cxx-dtor/a.h b/clang/test/Modules/Inputs/cxx-dtor/a.h
new file mode 100644
index 00000000000..023606eb35a
--- /dev/null
+++ b/clang/test/Modules/Inputs/cxx-dtor/a.h
@@ -0,0 +1 @@
+struct X { X(); virtual ~X(); };
diff --git a/clang/test/Modules/Inputs/cxx-dtor/b.h b/clang/test/Modules/Inputs/cxx-dtor/b.h
new file mode 100644
index 00000000000..75958564cc9
--- /dev/null
+++ b/clang/test/Modules/Inputs/cxx-dtor/b.h
@@ -0,0 +1,3 @@
+struct X { X(); virtual ~X(); };
+inline X::~X() {}
+#include "a.h"
diff --git a/clang/test/Modules/Inputs/cxx-dtor/module.modulemap b/clang/test/Modules/Inputs/cxx-dtor/module.modulemap
new file mode 100644
index 00000000000..61578a1865a
--- /dev/null
+++ b/clang/test/Modules/Inputs/cxx-dtor/module.modulemap
@@ -0,0 +1,2 @@
+module a { header "a.h" export * }
+module b { header "b.h" export * }
diff --git a/clang/test/Modules/cxx-dtor.cpp b/clang/test/Modules/cxx-dtor.cpp
new file mode 100644
index 00000000000..ead67ec334e
--- /dev/null
+++ b/clang/test/Modules/cxx-dtor.cpp
@@ -0,0 +1,3 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -x c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs/cxx-dtor -emit-llvm-only %s
+#include "b.h"
OpenPOWER on IntegriCloud