forked from OSchip/llvm-project
Whenever we instantiate a function definition or class, enter a new
potentially-evaluated expression context, to ensure that used declarations get properly marked. Fixes PR7123. llvm-svn: 103624
This commit is contained in:
parent
bcc4ff0db0
commit
17158425f2
|
@ -1175,6 +1175,8 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
||||||
// Enter the scope of this instantiation. We don't use
|
// Enter the scope of this instantiation. We don't use
|
||||||
// PushDeclContext because we don't have a scope.
|
// PushDeclContext because we don't have a scope.
|
||||||
ContextRAII SavedContext(*this, Instantiation);
|
ContextRAII SavedContext(*this, Instantiation);
|
||||||
|
EnterExpressionEvaluationContext EvalContext(*this,
|
||||||
|
Action::PotentiallyEvaluated);
|
||||||
|
|
||||||
// If this is an instantiation of a local class, merge this local
|
// If this is an instantiation of a local class, merge this local
|
||||||
// instantiation scope with the enclosing scope. Otherwise, every
|
// instantiation scope with the enclosing scope. Otherwise, every
|
||||||
|
|
|
@ -2011,6 +2011,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||||
if (Recursive)
|
if (Recursive)
|
||||||
PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
|
PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
|
||||||
|
|
||||||
|
EnterExpressionEvaluationContext EvalContext(*this,
|
||||||
|
Action::PotentiallyEvaluated);
|
||||||
ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function));
|
ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function));
|
||||||
|
|
||||||
// Introduce a new scope where local variable instantiations will be
|
// Introduce a new scope where local variable instantiations will be
|
||||||
|
|
|
@ -26,3 +26,58 @@ void test2(const X<float> *xf) {
|
||||||
void test3(const X<int(int)> *xf) {
|
void test3(const X<int(int)> *xf) {
|
||||||
(void)xf->x; // expected-note{{in instantiation of template class 'X<int (int)>' requested here}}
|
(void)xf->x; // expected-note{{in instantiation of template class 'X<int (int)>' requested here}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace PR7123 {
|
||||||
|
template <class > struct requirement_;
|
||||||
|
|
||||||
|
template <void(*)()> struct instantiate
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template <class > struct requirement ;
|
||||||
|
struct failed ;
|
||||||
|
|
||||||
|
template <class Model> struct requirement<failed *Model::*>
|
||||||
|
{
|
||||||
|
static void failed()
|
||||||
|
{
|
||||||
|
((Model*)0)->~Model(); // expected-note{{in instantiation of}}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Model> struct requirement_<void(*)(Model)> : requirement<failed *Model::*>
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template <int> struct Requires_
|
||||||
|
{ typedef void type; };
|
||||||
|
|
||||||
|
template <class Model> struct usage_requirements
|
||||||
|
{
|
||||||
|
~usage_requirements()
|
||||||
|
{((Model*)0)->~Model(); } // expected-note{{in instantiation of}}
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename TT > struct BidirectionalIterator
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{ value = 0 };
|
||||||
|
|
||||||
|
instantiate< requirement_<void(*)(usage_requirements<BidirectionalIterator>)>::failed> int534; // expected-note{{in instantiation of}}
|
||||||
|
|
||||||
|
~BidirectionalIterator()
|
||||||
|
{ i--; } // expected-error{{cannot decrement value of type 'PR7123::X'}}
|
||||||
|
|
||||||
|
TT i;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template<typename RanIter>
|
||||||
|
typename Requires_< BidirectionalIterator<RanIter>::value >::type sort(RanIter,RanIter){}
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
X x;
|
||||||
|
sort(x,x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue