mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 03:56:16 +08:00
Introduce a second queue of "local" pending implicit instantiation,
which are instantiations of the member functions of local classes. These implicit instantiations have to occur at the same time as---and in the same local instantiation scope as---the enclosing function, since the member functions of the local class can refer to locals within the enclosing function. This should really, really fix PR5764. llvm-svn: 93666
This commit is contained in:
@@ -3165,13 +3165,17 @@ public:
|
||||
/// relevant to this particular scope).
|
||||
LocalInstantiationScope *Outer;
|
||||
|
||||
/// \brief Whether we have already exited this scope.
|
||||
bool Exited;
|
||||
|
||||
// This class is non-copyable
|
||||
LocalInstantiationScope(const LocalInstantiationScope &);
|
||||
LocalInstantiationScope &operator=(const LocalInstantiationScope &);
|
||||
|
||||
public:
|
||||
LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
|
||||
: SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope) {
|
||||
: SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
|
||||
Exited(false) {
|
||||
if (!CombineWithOuterScope)
|
||||
SemaRef.CurrentInstantiationScope = this;
|
||||
else
|
||||
@@ -3180,7 +3184,15 @@ public:
|
||||
}
|
||||
|
||||
~LocalInstantiationScope() {
|
||||
if (!Exited)
|
||||
SemaRef.CurrentInstantiationScope = Outer;
|
||||
}
|
||||
|
||||
/// \brief Exit this local instantiation scope early.
|
||||
void Exit() {
|
||||
SemaRef.CurrentInstantiationScope = Outer;
|
||||
LocalDecls.clear();
|
||||
Exited = true;
|
||||
}
|
||||
|
||||
Decl *getInstantiationOf(const Decl *D) {
|
||||
@@ -3227,7 +3239,16 @@ public:
|
||||
/// but have not yet been performed.
|
||||
std::deque<PendingImplicitInstantiation> PendingImplicitInstantiations;
|
||||
|
||||
void PerformPendingImplicitInstantiations();
|
||||
/// \brief The queue of implicit template instantiations that are required
|
||||
/// and must be performed within the current local scope.
|
||||
///
|
||||
/// This queue is only used for member functions of local classes in
|
||||
/// templates, which must be instantiated in the same scope as their
|
||||
/// enclosing function, so that they can reference function-local
|
||||
/// types, static variables, enumerators, etc.
|
||||
std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations;
|
||||
|
||||
void PerformPendingImplicitInstantiations(bool LocalOnly = false);
|
||||
|
||||
TypeSourceInfo *SubstType(TypeSourceInfo *T,
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
|
||||
@@ -7215,8 +7215,15 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
|
||||
AlreadyInstantiated = true;
|
||||
}
|
||||
|
||||
if (!AlreadyInstantiated)
|
||||
PendingImplicitInstantiations.push_back(std::make_pair(Function, Loc));
|
||||
if (!AlreadyInstantiated) {
|
||||
if (isa<CXXRecordDecl>(Function->getDeclContext()) &&
|
||||
cast<CXXRecordDecl>(Function->getDeclContext())->isLocalClass())
|
||||
PendingLocalImplicitInstantiations.push_back(std::make_pair(Function,
|
||||
Loc));
|
||||
else
|
||||
PendingImplicitInstantiations.push_back(std::make_pair(Function,
|
||||
Loc));
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: keep track of references to static functions
|
||||
|
||||
@@ -1653,8 +1653,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function));
|
||||
|
||||
// Introduce a new scope where local variable instantiations will be
|
||||
// recorded.
|
||||
LocalInstantiationScope Scope(*this);
|
||||
// recorded, unless we're actually a member function within a local
|
||||
// class, in which case we need to merge our results with the parent
|
||||
// scope (of the enclosing function).
|
||||
bool MergeWithParentScope = false;
|
||||
if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext()))
|
||||
MergeWithParentScope = Rec->isLocalClass();
|
||||
|
||||
LocalInstantiationScope Scope(*this, MergeWithParentScope);
|
||||
|
||||
// Introduce the instantiated function parameters into the local
|
||||
// instantiation scope.
|
||||
@@ -1691,6 +1697,11 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
DeclGroupRef DG(Function);
|
||||
Consumer.HandleTopLevelDecl(DG);
|
||||
|
||||
// This class may have local implicit instantiations that need to be
|
||||
// instantiation within this scope.
|
||||
PerformPendingImplicitInstantiations(/*LocalOnly=*/true);
|
||||
Scope.Exit();
|
||||
|
||||
if (Recursive) {
|
||||
// Instantiate any pending implicit instantiations found during the
|
||||
// instantiation of this template.
|
||||
@@ -2223,10 +2234,18 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
|
||||
|
||||
/// \brief Performs template instantiation for all implicit template
|
||||
/// instantiations we have seen until this point.
|
||||
void Sema::PerformPendingImplicitInstantiations() {
|
||||
while (!PendingImplicitInstantiations.empty()) {
|
||||
PendingImplicitInstantiation Inst = PendingImplicitInstantiations.front();
|
||||
PendingImplicitInstantiations.pop_front();
|
||||
void Sema::PerformPendingImplicitInstantiations(bool LocalOnly) {
|
||||
while (!PendingLocalImplicitInstantiations.empty() ||
|
||||
(!LocalOnly && !PendingImplicitInstantiations.empty())) {
|
||||
PendingImplicitInstantiation Inst;
|
||||
|
||||
if (PendingLocalImplicitInstantiations.empty()) {
|
||||
Inst = PendingImplicitInstantiations.front();
|
||||
PendingImplicitInstantiations.pop_front();
|
||||
} else {
|
||||
Inst = PendingLocalImplicitInstantiations.front();
|
||||
PendingLocalImplicitInstantiations.pop_front();
|
||||
}
|
||||
|
||||
// Instantiate function definitions
|
||||
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) {
|
||||
|
||||
@@ -16,8 +16,11 @@ namespace PR5764 {
|
||||
class X {
|
||||
template <typename T>
|
||||
void Bar() {
|
||||
typedef T ValueType;
|
||||
class Y {
|
||||
Y() {}
|
||||
Y() { V = ValueType(); }
|
||||
|
||||
ValueType V;
|
||||
};
|
||||
|
||||
Y y;
|
||||
|
||||
Reference in New Issue
Block a user