Skip to content

Commit 4b054b2

Browse files
committed
PR29097: add an update record when we instantiate the default member
initializer of an imported field. llvm-svn: 279667
1 parent eedcd9c commit 4b054b2

File tree

8 files changed

+68
-6
lines changed

8 files changed

+68
-6
lines changed

clang/include/clang/AST/ASTMutationListener.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace clang {
2222
class CXXRecordDecl;
2323
class Decl;
2424
class DeclContext;
25+
class FieldDecl;
2526
class FunctionDecl;
2627
class FunctionTemplateDecl;
2728
class Module;
@@ -93,6 +94,9 @@ class ASTMutationListener {
9394
/// \brief A default argument was instantiated.
9495
virtual void DefaultArgumentInstantiated(const ParmVarDecl *D) {}
9596

97+
/// \brief A default member initializer was instantiated.
98+
virtual void DefaultMemberInitializerInstantiated(const FieldDecl *D) {}
99+
96100
/// \brief A new objc category class was added for an interface.
97101
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
98102
const ObjCInterfaceDecl *IFD) {}

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,7 @@ class ASTWriter : public ASTDeserializationListener,
674674
void CompletedImplicitDefinition(const FunctionDecl *D) override;
675675
void StaticDataMemberInstantiated(const VarDecl *D) override;
676676
void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
677+
void DefaultMemberInitializerInstantiated(const FieldDecl *D) override;
677678
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
678679
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
679680
const ObjCInterfaceDecl *IFD) override;

clang/lib/Frontend/MultiplexConsumer.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ class MultiplexASTMutationListener : public ASTMutationListener {
120120
void CompletedImplicitDefinition(const FunctionDecl *D) override;
121121
void StaticDataMemberInstantiated(const VarDecl *D) override;
122122
void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
123+
void DefaultMemberInitializerInstantiated(const FieldDecl *D) override;
123124
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
124125
const ObjCInterfaceDecl *IFD) override;
125126
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
@@ -201,6 +202,11 @@ void MultiplexASTMutationListener::DefaultArgumentInstantiated(
201202
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
202203
Listeners[i]->DefaultArgumentInstantiated(D);
203204
}
205+
void MultiplexASTMutationListener::DefaultMemberInitializerInstantiated(
206+
const FieldDecl *D) {
207+
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
208+
Listeners[i]->DefaultMemberInitializerInstantiated(D);
209+
}
204210
void MultiplexASTMutationListener::AddedObjCCategoryToInterface(
205211
const ObjCCategoryDecl *CatD,
206212
const ObjCInterfaceDecl *IFD) {

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "clang/AST/ASTConsumer.h"
1616
#include "clang/AST/ASTContext.h"
1717
#include "clang/AST/ASTLambda.h"
18+
#include "clang/AST/ASTMutationListener.h"
1819
#include "clang/AST/DeclTemplate.h"
1920
#include "clang/AST/Expr.h"
2021
#include "clang/Basic/LangOptions.h"
@@ -2215,6 +2216,9 @@ bool Sema::InstantiateInClassInitializer(
22152216
ActOnFinishCXXInClassMemberInitializer(
22162217
Instantiation, Init ? Init->getLocStart() : SourceLocation(), Init);
22172218

2219+
if (auto *L = getASTMutationListener())
2220+
L->DefaultMemberInitializerInstantiated(Instantiation);
2221+
22182222
// Exit the scope of this instantiation.
22192223
SavedContext.pop();
22202224

clang/lib/Serialization/ASTCommon.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ enum DeclUpdateKind {
3030
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
3131
UPD_CXX_INSTANTIATED_CLASS_DEFINITION,
3232
UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT,
33+
UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER,
3334
UPD_CXX_RESOLVED_DTOR_DELETE,
3435
UPD_CXX_RESOLVED_EXCEPTION_SPEC,
3536
UPD_CXX_DEDUCED_RETURN_TYPE,

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3796,6 +3796,23 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
37963796
break;
37973797
}
37983798

3799+
case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER: {
3800+
auto FD = cast<FieldDecl>(D);
3801+
auto DefaultInit = Reader.ReadExpr(F);
3802+
3803+
// Only apply the update if the field still has an uninstantiated
3804+
// default member initializer.
3805+
if (FD->hasInClassInitializer() && !FD->getInClassInitializer()) {
3806+
if (DefaultInit)
3807+
FD->setInClassInitializer(DefaultInit);
3808+
else
3809+
// Instantiation failed. We can get here if we serialized an AST for
3810+
// an invalid program.
3811+
FD->removeInClassInitializer();
3812+
}
3813+
break;
3814+
}
3815+
37993816
case UPD_CXX_ADDED_FUNCTION_DEFINITION: {
38003817
FunctionDecl *FD = cast<FunctionDecl>(D);
38013818
if (Reader.PendingBodies[FD]) {

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4702,6 +4702,11 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
47024702
cast<ParmVarDecl>(Update.getDecl())->getDefaultArg()));
47034703
break;
47044704

4705+
case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER:
4706+
Record.AddStmt(
4707+
cast<FieldDecl>(Update.getDecl())->getInClassInitializer());
4708+
break;
4709+
47054710
case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
47064711
auto *RD = cast<CXXRecordDecl>(D);
47074712
UpdatedDeclContexts.insert(RD->getPrimaryContext());
@@ -5815,6 +5820,15 @@ void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) {
58155820
DeclUpdate(UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT, D));
58165821
}
58175822

5823+
void ASTWriter::DefaultMemberInitializerInstantiated(const FieldDecl *D) {
5824+
assert(!WritingAST && "Already writing the AST!");
5825+
if (!D->isFromASTFile())
5826+
return;
5827+
5828+
DeclUpdates[D].push_back(
5829+
DeclUpdate(UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER, D));
5830+
}
5831+
58185832
void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
58195833
const ObjCInterfaceDecl *IFD) {
58205834
if (Chain && Chain->isProcessingUpdateRecords()) return;

clang/test/PCH/cxx1y-default-initializer.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
// RUN: %clang_cc1 -pedantic -std=c++1y %s -o %t
2-
// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch %s -o %t
3-
// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t -verify %s
1+
// RUN: %clang_cc1 -pedantic -std=c++1y -include %s -include %s -verify %s
2+
// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch -o %t.1 %s
3+
// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.1 -emit-pch -o %t.2 %s
4+
// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.2 -verify %s
45

5-
#ifndef HEADER_INCLUDED
6-
7-
#define HEADER_INCLUDED
6+
#ifndef HEADER_1
7+
#define HEADER_1
88

99
struct A {
1010
int x;
@@ -19,6 +19,20 @@ struct B {
1919
constexpr B(int k) : z1(k) {}
2020
};
2121

22+
template<typename T> struct C {
23+
constexpr C() {}
24+
T c = T();
25+
struct U {};
26+
};
27+
// Instantiate C<int> but not the default initializer.
28+
C<int>::U ciu;
29+
30+
#elif !defined(HEADER_2)
31+
#define HEADER_2
32+
33+
// Instantiate the default initializer now, should create an update record.
34+
C<int> ci;
35+
2236
#else
2337

2438
static_assert(A{}.z == 3, "");
@@ -27,5 +41,6 @@ static_assert(A{.y = 5}.z == 5, ""); // expected-warning {{C99}}
2741
static_assert(A{3, .y = 1}.z == 4, ""); // expected-warning {{C99}}
2842
static_assert(make<int>().z == 3, "");
2943
static_assert(make<int>(12).z == 15, "");
44+
static_assert(C<int>().c == 0, "");
3045

3146
#endif

0 commit comments

Comments
 (0)