forked from OSchip/llvm-project
Generalize "static data member instantiated" notification to cover variable templates too.
While here, split the "point of instantiation changed" notification out from it; these two really are orthogonal changes. llvm-svn: 319727
This commit is contained in:
parent
913b42b0e1
commit
891fc7f37a
|
@ -36,6 +36,7 @@ namespace clang {
|
|||
class QualType;
|
||||
class RecordDecl;
|
||||
class TagDecl;
|
||||
class ValueDecl;
|
||||
class VarDecl;
|
||||
class VarTemplateDecl;
|
||||
class VarTemplateSpecializationDecl;
|
||||
|
@ -87,8 +88,13 @@ public:
|
|||
/// \brief An implicit member got a definition.
|
||||
virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
|
||||
|
||||
/// \brief A static data member was implicitly instantiated.
|
||||
virtual void StaticDataMemberInstantiated(const VarDecl *D) {}
|
||||
/// \brief The instantiation of a templated function or variable was
|
||||
/// requested. In particular, the point of instantiation and template
|
||||
/// specialization kind of \p D may have changed.
|
||||
virtual void InstantiationRequested(const ValueDecl *D) {}
|
||||
|
||||
/// \brief A templated variable's definition was implicitly instantiated.
|
||||
virtual void VariableDefinitionInstantiated(const VarDecl *D) {}
|
||||
|
||||
/// \brief A function template's definition was instantiated.
|
||||
virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {}
|
||||
|
|
|
@ -7790,11 +7790,6 @@ public:
|
|||
VarDecl *Var, bool Recursive = false,
|
||||
bool DefinitionRequired = false,
|
||||
bool AtEndOfTU = false);
|
||||
void InstantiateStaticDataMemberDefinition(
|
||||
SourceLocation PointOfInstantiation,
|
||||
VarDecl *Var,
|
||||
bool Recursive = false,
|
||||
bool DefinitionRequired = false);
|
||||
|
||||
void InstantiateMemInitializers(CXXConstructorDecl *New,
|
||||
const CXXConstructorDecl *Tmpl,
|
||||
|
|
|
@ -727,10 +727,11 @@ private:
|
|||
const FunctionDecl *Delete,
|
||||
Expr *ThisArg) override;
|
||||
void CompletedImplicitDefinition(const FunctionDecl *D) override;
|
||||
void StaticDataMemberInstantiated(const VarDecl *D) override;
|
||||
void InstantiationRequested(const ValueDecl *D) override;
|
||||
void VariableDefinitionInstantiated(const VarDecl *D) override;
|
||||
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
|
||||
void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
|
||||
void DefaultMemberInitializerInstantiated(const FieldDecl *D) override;
|
||||
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
|
||||
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
|
||||
const ObjCInterfaceDecl *IFD) override;
|
||||
void DeclarationMarkedUsed(const Decl *D) override;
|
||||
|
|
|
@ -2418,15 +2418,21 @@ void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
|
|||
dyn_cast<VarTemplateSpecializationDecl>(this)) {
|
||||
Spec->setSpecializationKind(TSK);
|
||||
if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
|
||||
Spec->getPointOfInstantiation().isInvalid())
|
||||
Spec->getPointOfInstantiation().isInvalid()) {
|
||||
Spec->setPointOfInstantiation(PointOfInstantiation);
|
||||
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
|
||||
L->InstantiationRequested(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) {
|
||||
MSI->setTemplateSpecializationKind(TSK);
|
||||
if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
|
||||
MSI->getPointOfInstantiation().isInvalid())
|
||||
MSI->getPointOfInstantiation().isInvalid()) {
|
||||
MSI->setPointOfInstantiation(PointOfInstantiation);
|
||||
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
|
||||
L->InstantiationRequested(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3442,15 +3448,21 @@ FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
|
|||
FTSInfo->setTemplateSpecializationKind(TSK);
|
||||
if (TSK != TSK_ExplicitSpecialization &&
|
||||
PointOfInstantiation.isValid() &&
|
||||
FTSInfo->getPointOfInstantiation().isInvalid())
|
||||
FTSInfo->getPointOfInstantiation().isInvalid()) {
|
||||
FTSInfo->setPointOfInstantiation(PointOfInstantiation);
|
||||
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
|
||||
L->InstantiationRequested(this);
|
||||
}
|
||||
} else if (MemberSpecializationInfo *MSInfo
|
||||
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) {
|
||||
MSInfo->setTemplateSpecializationKind(TSK);
|
||||
if (TSK != TSK_ExplicitSpecialization &&
|
||||
PointOfInstantiation.isValid() &&
|
||||
MSInfo->getPointOfInstantiation().isInvalid())
|
||||
MSInfo->getPointOfInstantiation().isInvalid()) {
|
||||
MSInfo->setPointOfInstantiation(PointOfInstantiation);
|
||||
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
|
||||
L->InstantiationRequested(this);
|
||||
}
|
||||
} else
|
||||
llvm_unreachable("Function cannot have a template specialization kind");
|
||||
}
|
||||
|
|
|
@ -119,12 +119,13 @@ public:
|
|||
const FunctionDecl *Delete,
|
||||
Expr *ThisArg) override;
|
||||
void CompletedImplicitDefinition(const FunctionDecl *D) override;
|
||||
void StaticDataMemberInstantiated(const VarDecl *D) override;
|
||||
void InstantiationRequested(const ValueDecl *D) override;
|
||||
void VariableDefinitionInstantiated(const VarDecl *D) override;
|
||||
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
|
||||
void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
|
||||
void DefaultMemberInitializerInstantiated(const FieldDecl *D) override;
|
||||
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
|
||||
const ObjCInterfaceDecl *IFD) override;
|
||||
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
|
||||
void DeclarationMarkedUsed(const Decl *D) override;
|
||||
void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
|
||||
void DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
|
||||
|
@ -193,10 +194,19 @@ void MultiplexASTMutationListener::CompletedImplicitDefinition(
|
|||
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
|
||||
Listeners[i]->CompletedImplicitDefinition(D);
|
||||
}
|
||||
void MultiplexASTMutationListener::StaticDataMemberInstantiated(
|
||||
const VarDecl *D) {
|
||||
void MultiplexASTMutationListener::InstantiationRequested(const ValueDecl *D) {
|
||||
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
|
||||
Listeners[i]->StaticDataMemberInstantiated(D);
|
||||
Listeners[i]->InstantiationRequested(D);
|
||||
}
|
||||
void MultiplexASTMutationListener::VariableDefinitionInstantiated(
|
||||
const VarDecl *D) {
|
||||
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
|
||||
Listeners[i]->VariableDefinitionInstantiated(D);
|
||||
}
|
||||
void MultiplexASTMutationListener::FunctionDefinitionInstantiated(
|
||||
const FunctionDecl *D) {
|
||||
for (auto &Listener : Listeners)
|
||||
Listener->FunctionDefinitionInstantiated(D);
|
||||
}
|
||||
void MultiplexASTMutationListener::DefaultArgumentInstantiated(
|
||||
const ParmVarDecl *D) {
|
||||
|
@ -214,11 +224,6 @@ void MultiplexASTMutationListener::AddedObjCCategoryToInterface(
|
|||
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
|
||||
Listeners[i]->AddedObjCCategoryToInterface(CatD, IFD);
|
||||
}
|
||||
void MultiplexASTMutationListener::FunctionDefinitionInstantiated(
|
||||
const FunctionDecl *D) {
|
||||
for (auto &Listener : Listeners)
|
||||
Listener->FunctionDefinitionInstantiated(D);
|
||||
}
|
||||
void MultiplexASTMutationListener::DeclarationMarkedUsed(const Decl *D) {
|
||||
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
|
||||
Listeners[i]->DeclarationMarkedUsed(D);
|
||||
|
|
|
@ -13960,29 +13960,21 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
|
|||
// Implicit instantiation of function templates and member functions of
|
||||
// class templates.
|
||||
if (Func->isImplicitlyInstantiable()) {
|
||||
bool AlreadyInstantiated = false;
|
||||
SourceLocation PointOfInstantiation = Loc;
|
||||
if (FunctionTemplateSpecializationInfo *SpecInfo
|
||||
= Func->getTemplateSpecializationInfo()) {
|
||||
if (SpecInfo->getPointOfInstantiation().isInvalid())
|
||||
SpecInfo->setPointOfInstantiation(Loc);
|
||||
else if (SpecInfo->getTemplateSpecializationKind()
|
||||
== TSK_ImplicitInstantiation) {
|
||||
AlreadyInstantiated = true;
|
||||
PointOfInstantiation = SpecInfo->getPointOfInstantiation();
|
||||
}
|
||||
} else if (MemberSpecializationInfo *MSInfo
|
||||
= Func->getMemberSpecializationInfo()) {
|
||||
if (MSInfo->getPointOfInstantiation().isInvalid())
|
||||
MSInfo->setPointOfInstantiation(Loc);
|
||||
else if (MSInfo->getTemplateSpecializationKind()
|
||||
== TSK_ImplicitInstantiation) {
|
||||
AlreadyInstantiated = true;
|
||||
PointOfInstantiation = MSInfo->getPointOfInstantiation();
|
||||
}
|
||||
TemplateSpecializationKind TSK = Func->getTemplateSpecializationKind();
|
||||
SourceLocation PointOfInstantiation = Func->getPointOfInstantiation();
|
||||
bool FirstInstantiation = PointOfInstantiation.isInvalid();
|
||||
if (FirstInstantiation) {
|
||||
PointOfInstantiation = Loc;
|
||||
Func->setTemplateSpecializationKind(TSK, PointOfInstantiation);
|
||||
} else if (TSK != TSK_ImplicitInstantiation) {
|
||||
// Use the point of use as the point of instantiation, instead of the
|
||||
// point of explicit instantiation (which we track as the actual point of
|
||||
// instantiation). This gives better backtraces in diagnostics.
|
||||
PointOfInstantiation = Loc;
|
||||
}
|
||||
|
||||
if (!AlreadyInstantiated || Func->isConstexpr()) {
|
||||
if (FirstInstantiation || TSK != TSK_ImplicitInstantiation ||
|
||||
Func->isConstexpr()) {
|
||||
if (isa<CXXRecordDecl>(Func->getDeclContext()) &&
|
||||
cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass() &&
|
||||
CodeSynthesisContexts.size())
|
||||
|
@ -14859,22 +14851,14 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
|
|||
TSK == TSK_ImplicitInstantiation ||
|
||||
(TSK == TSK_ExplicitInstantiationDeclaration && UsableInConstantExpr);
|
||||
|
||||
if (TryInstantiating && !isa<VarTemplateSpecializationDecl>(Var)) {
|
||||
if (Var->getPointOfInstantiation().isInvalid()) {
|
||||
// This is a modification of an existing AST node. Notify listeners.
|
||||
if (ASTMutationListener *L = SemaRef.getASTMutationListener())
|
||||
L->StaticDataMemberInstantiated(Var);
|
||||
} else if (!UsableInConstantExpr)
|
||||
// Don't bother trying to instantiate it again, unless we might need
|
||||
// its initializer before we get to the end of the TU.
|
||||
TryInstantiating = false;
|
||||
}
|
||||
|
||||
if (Var->getPointOfInstantiation().isInvalid())
|
||||
Var->setTemplateSpecializationKind(TSK, Loc);
|
||||
|
||||
if (TryInstantiating) {
|
||||
SourceLocation PointOfInstantiation = Var->getPointOfInstantiation();
|
||||
bool FirstInstantiation = PointOfInstantiation.isInvalid();
|
||||
if (FirstInstantiation) {
|
||||
PointOfInstantiation = Loc;
|
||||
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
|
||||
}
|
||||
|
||||
bool InstantiationDependent = false;
|
||||
bool IsNonDependent =
|
||||
VarSpec ? !TemplateSpecializationType::anyDependentTemplateArguments(
|
||||
|
@ -14884,10 +14868,16 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
|
|||
// Do not instantiate specializations that are still type-dependent.
|
||||
if (IsNonDependent) {
|
||||
if (UsableInConstantExpr) {
|
||||
// Do not defer instantiations of variables which could be used in a
|
||||
// Do not defer instantiations of variables that could be used in a
|
||||
// constant expression.
|
||||
SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var);
|
||||
} else {
|
||||
} else if (FirstInstantiation ||
|
||||
isa<VarTemplateSpecializationDecl>(Var)) {
|
||||
// FIXME: For a specialization of a variable template, we don't
|
||||
// distinguish between "declaration and type implicitly instantiated"
|
||||
// and "implicit instantiation of definition requested", so we have
|
||||
// no direct way to avoid enqueueing the pending instantiation
|
||||
// multiple times.
|
||||
SemaRef.PendingInstantiations
|
||||
.push_back(std::make_pair(Var, PointOfInstantiation));
|
||||
}
|
||||
|
|
|
@ -9071,7 +9071,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
|
||||
if (!HasNoEffect) {
|
||||
// Instantiate static data member or variable template.
|
||||
|
||||
Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
|
||||
if (PrevTemplate) {
|
||||
// Merge attributes.
|
||||
|
|
|
@ -2613,7 +2613,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
|||
continue;
|
||||
|
||||
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
|
||||
InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
|
||||
InstantiateVariableDefinition(PointOfInstantiation, Var);
|
||||
} else {
|
||||
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
|
||||
}
|
||||
|
|
|
@ -4142,6 +4142,9 @@ void Sema::BuildVariableInstantiation(
|
|||
void Sema::InstantiateVariableInitializer(
|
||||
VarDecl *Var, VarDecl *OldVar,
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
||||
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
|
||||
L->VariableDefinitionInstantiated(Var);
|
||||
|
||||
// We propagate the 'inline' flag with the initializer, because it
|
||||
// would otherwise imply that the variable is a definition for a
|
||||
// non-static data member.
|
||||
|
@ -4204,36 +4207,22 @@ void Sema::InstantiateVariableInitializer(
|
|||
///
|
||||
/// \param PointOfInstantiation the point at which the instantiation was
|
||||
/// required. Note that this is not precisely a "point of instantiation"
|
||||
/// for the function, but it's close.
|
||||
/// for the variable, but it's close.
|
||||
///
|
||||
/// \param Var the already-instantiated declaration of a static member
|
||||
/// variable of a class template specialization.
|
||||
/// \param Var the already-instantiated declaration of a templated variable.
|
||||
///
|
||||
/// \param Recursive if true, recursively instantiates any functions that
|
||||
/// are required by this instantiation.
|
||||
///
|
||||
/// \param DefinitionRequired if true, then we are performing an explicit
|
||||
/// instantiation where an out-of-line definition of the member variable
|
||||
/// is required. Complain if there is no such definition.
|
||||
void Sema::InstantiateStaticDataMemberDefinition(
|
||||
SourceLocation PointOfInstantiation,
|
||||
VarDecl *Var,
|
||||
bool Recursive,
|
||||
bool DefinitionRequired) {
|
||||
InstantiateVariableDefinition(PointOfInstantiation, Var, Recursive,
|
||||
DefinitionRequired);
|
||||
}
|
||||
|
||||
/// instantiation where a definition of the variable is required. Complain
|
||||
/// if there is no such definition.
|
||||
void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
||||
VarDecl *Var, bool Recursive,
|
||||
bool DefinitionRequired, bool AtEndOfTU) {
|
||||
if (Var->isInvalidDecl())
|
||||
return;
|
||||
|
||||
// FIXME: We're missing ASTMutationListener notifications for all of the work
|
||||
// done here. (Some of our callers notify the listeners for the static data
|
||||
// member case, but not in general.)
|
||||
|
||||
VarTemplateSpecializationDecl *VarSpec =
|
||||
dyn_cast<VarTemplateSpecializationDecl>(Var);
|
||||
VarDecl *PatternDecl = nullptr, *Def = nullptr;
|
||||
|
@ -4284,6 +4273,11 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
|||
// If this is a static data member template, there might be an
|
||||
// uninstantiated initializer on the declaration. If so, instantiate
|
||||
// it now.
|
||||
//
|
||||
// FIXME: This largely duplicates what we would do below. The difference
|
||||
// is that along this path we may instantiate an initializer from an
|
||||
// in-class declaration of the template and instantiate the definition
|
||||
// from a separate out-of-class definition.
|
||||
if (PatternDecl->isStaticDataMember() &&
|
||||
(PatternDecl = PatternDecl->getFirstDecl())->hasInit() &&
|
||||
!Var->hasInit()) {
|
||||
|
|
|
@ -7268,32 +7268,28 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
|
|||
void Sema::completeExprArrayBound(Expr *E) {
|
||||
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
|
||||
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
|
||||
if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
|
||||
if (isTemplateInstantiation(Var->getTemplateSpecializationKind()) &&
|
||||
!Var->getDefinition()) {
|
||||
SourceLocation PointOfInstantiation = E->getExprLoc();
|
||||
|
||||
if (MemberSpecializationInfo *MSInfo =
|
||||
Var->getMemberSpecializationInfo()) {
|
||||
// If we don't already have a point of instantiation, this is it.
|
||||
if (MSInfo->getPointOfInstantiation().isInvalid()) {
|
||||
MSInfo->setPointOfInstantiation(PointOfInstantiation);
|
||||
|
||||
// This is a modification of an existing AST node. Notify
|
||||
// listeners.
|
||||
if (ASTMutationListener *L = getASTMutationListener())
|
||||
L->StaticDataMemberInstantiated(Var);
|
||||
}
|
||||
} else {
|
||||
VarTemplateSpecializationDecl *VarSpec =
|
||||
cast<VarTemplateSpecializationDecl>(Var);
|
||||
if (VarSpec->getPointOfInstantiation().isInvalid())
|
||||
VarSpec->setPointOfInstantiation(PointOfInstantiation);
|
||||
}
|
||||
|
||||
InstantiateVariableDefinition(PointOfInstantiation, Var);
|
||||
auto *Def = Var->getDefinition();
|
||||
|
||||
// If we don't already have a point of instantiation, and we managed to
|
||||
// instantiate a definition, this is the point of instantiation.
|
||||
// Otherwise, we don't request an end-of-TU instantiation, so this is
|
||||
// not a point of instantiation.
|
||||
// FIXME: Is this really the right behavior?
|
||||
if (Var->getPointOfInstantiation().isInvalid() && Def) {
|
||||
assert(Var->getTemplateSpecializationKind() ==
|
||||
TSK_ImplicitInstantiation &&
|
||||
"explicit instantiation with no point of instantiation");
|
||||
Var->setTemplateSpecializationKind(
|
||||
Var->getTemplateSpecializationKind(), PointOfInstantiation);
|
||||
}
|
||||
|
||||
// Update the type to the newly instantiated definition's type both
|
||||
// here and within the expression.
|
||||
if (VarDecl *Def = Var->getDefinition()) {
|
||||
if (Def) {
|
||||
DRE->setDecl(Def);
|
||||
QualType T = Def->getType();
|
||||
DRE->setType(T);
|
||||
|
|
|
@ -27,7 +27,8 @@ enum DeclUpdateKind {
|
|||
UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
|
||||
UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
|
||||
UPD_CXX_ADDED_FUNCTION_DEFINITION,
|
||||
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
|
||||
UPD_CXX_ADDED_VAR_DEFINITION,
|
||||
UPD_CXX_POINT_OF_INSTANTIATION,
|
||||
UPD_CXX_INSTANTIATED_CLASS_DEFINITION,
|
||||
UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT,
|
||||
UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER,
|
||||
|
|
|
@ -3984,10 +3984,8 @@ void ASTDeclReader::UpdateDecl(Decl *D,
|
|||
break;
|
||||
}
|
||||
|
||||
case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: {
|
||||
case UPD_CXX_ADDED_VAR_DEFINITION: {
|
||||
VarDecl *VD = cast<VarDecl>(D);
|
||||
VD->getMemberSpecializationInfo()->setPointOfInstantiation(
|
||||
ReadSourceLocation());
|
||||
VD->NonParmVarDeclBits.IsInline = Record.readInt();
|
||||
VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt();
|
||||
uint64_t Val = Record.readInt();
|
||||
|
@ -4002,6 +4000,25 @@ void ASTDeclReader::UpdateDecl(Decl *D,
|
|||
break;
|
||||
}
|
||||
|
||||
case UPD_CXX_POINT_OF_INSTANTIATION: {
|
||||
SourceLocation POI = Record.readSourceLocation();
|
||||
if (VarTemplateSpecializationDecl *VTSD =
|
||||
dyn_cast<VarTemplateSpecializationDecl>(D)) {
|
||||
VTSD->setPointOfInstantiation(POI);
|
||||
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
|
||||
VD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
|
||||
} else {
|
||||
auto *FD = cast<FunctionDecl>(D);
|
||||
if (auto *FTSInfo = FD->TemplateOrSpecialization
|
||||
.dyn_cast<FunctionTemplateSpecializationInfo *>())
|
||||
FTSInfo->setPointOfInstantiation(POI);
|
||||
else
|
||||
FD->TemplateOrSpecialization.get<MemberSpecializationInfo *>()
|
||||
->setPointOfInstantiation(POI);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: {
|
||||
auto Param = cast<ParmVarDecl>(D);
|
||||
|
||||
|
|
|
@ -5135,9 +5135,13 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
|
|||
case UPD_CXX_ADDED_FUNCTION_DEFINITION:
|
||||
break;
|
||||
|
||||
case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: {
|
||||
const VarDecl *VD = cast<VarDecl>(D);
|
||||
case UPD_CXX_POINT_OF_INSTANTIATION:
|
||||
// FIXME: Do we need to also save the template specialization kind here?
|
||||
Record.AddSourceLocation(Update.getLoc());
|
||||
break;
|
||||
|
||||
case UPD_CXX_ADDED_VAR_DEFINITION: {
|
||||
const VarDecl *VD = cast<VarDecl>(D);
|
||||
Record.push_back(VD->isInline());
|
||||
Record.push_back(VD->isInlineSpecified());
|
||||
if (VD->getInit()) {
|
||||
|
@ -6256,6 +6260,15 @@ void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
|
|||
DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));
|
||||
}
|
||||
|
||||
void ASTWriter::VariableDefinitionInstantiated(const VarDecl *D) {
|
||||
if (Chain && Chain->isProcessingUpdateRecords()) return;
|
||||
assert(!WritingAST && "Already writing the AST!");
|
||||
if (!D->isFromASTFile())
|
||||
return;
|
||||
|
||||
DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_VAR_DEFINITION));
|
||||
}
|
||||
|
||||
void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
|
||||
if (Chain && Chain->isProcessingUpdateRecords()) return;
|
||||
assert(!WritingAST && "Already writing the AST!");
|
||||
|
@ -6265,7 +6278,7 @@ void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
|
|||
DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));
|
||||
}
|
||||
|
||||
void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
|
||||
void ASTWriter::InstantiationRequested(const ValueDecl *D) {
|
||||
if (Chain && Chain->isProcessingUpdateRecords()) return;
|
||||
assert(!WritingAST && "Already writing the AST!");
|
||||
if (!D->isFromASTFile())
|
||||
|
@ -6273,9 +6286,12 @@ void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
|
|||
|
||||
// Since the actual instantiation is delayed, this really means that we need
|
||||
// to update the instantiation location.
|
||||
DeclUpdates[D].push_back(
|
||||
DeclUpdate(UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
|
||||
D->getMemberSpecializationInfo()->getPointOfInstantiation()));
|
||||
SourceLocation POI;
|
||||
if (auto *VD = dyn_cast<VarDecl>(D))
|
||||
POI = VD->getPointOfInstantiation();
|
||||
else
|
||||
POI = cast<FunctionDecl>(D)->getPointOfInstantiation();
|
||||
DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_POINT_OF_INSTANTIATION, POI));
|
||||
}
|
||||
|
||||
void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// RUN: %clang_cc1 -fmodules -std=c++14 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
#pragma clang module build A
|
||||
module A {}
|
||||
#pragma clang module contents
|
||||
#pragma clang module begin A
|
||||
template<int> int n = 42;
|
||||
decltype(n<0>) f();
|
||||
#pragma clang module end
|
||||
#pragma clang module endbuild
|
||||
|
||||
#pragma clang module build B
|
||||
module B {}
|
||||
#pragma clang module contents
|
||||
#pragma clang module begin B
|
||||
#pragma clang module import A
|
||||
inline int f() { return n<0>; }
|
||||
#pragma clang module end
|
||||
#pragma clang module endbuild
|
||||
|
||||
#pragma clang module import B
|
||||
|
||||
// CHECK: @_Z1nILi0EE = linkonce_odr global i32 42, comdat
|
||||
int g() { return f(); }
|
Loading…
Reference in New Issue