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:
Douglas Gregor 2010-05-12 17:27:19 +00:00
parent bcc4ff0db0
commit 17158425f2
3 changed files with 59 additions and 0 deletions

View File

@ -1175,6 +1175,8 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
ContextRAII SavedContext(*this, Instantiation);
EnterExpressionEvaluationContext EvalContext(*this,
Action::PotentiallyEvaluated);
// If this is an instantiation of a local class, merge this local
// instantiation scope with the enclosing scope. Otherwise, every

View File

@ -2011,6 +2011,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (Recursive)
PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
EnterExpressionEvaluationContext EvalContext(*this,
Action::PotentiallyEvaluated);
ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function));
// Introduce a new scope where local variable instantiations will be

View File

@ -26,3 +26,58 @@ void test2(const X<float> *xf) {
void test3(const X<int(int)> *xf) {
(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);
}
}