forked from OSchip/llvm-project
When parsing typename specifiers (with either the identifier or
simple-template-id form), check whether the scope specifier is computable as a declaration context rather than checking whether it is dependent, so that we properly cope with members of the current instantiation. Improve testing for typename specifiers that terminate in a simpe-template-id. llvm-svn: 80783
This commit is contained in:
parent
4469c164d0
commit
12bbfe1d31
|
@ -530,7 +530,7 @@ const TemplateSpecializationType *
|
|||
Type::getAsTemplateSpecializationType() const {
|
||||
// There is no sugar for class template specialization types, so
|
||||
// just return the canonical type pointer if it is the right class.
|
||||
return dyn_cast<TemplateSpecializationType>(CanonicalType);
|
||||
return this->getAs<TemplateSpecializationType>();
|
||||
}
|
||||
|
||||
bool Type::isIntegerType() const {
|
||||
|
|
|
@ -1137,9 +1137,7 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
|
|||
NestedNameSpecifier *Qualifier
|
||||
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
|
||||
|
||||
// FIXME: member of the current instantiation
|
||||
|
||||
if (!Qualifier->isDependent()) {
|
||||
if (computeDeclContext(SS, false)) {
|
||||
// C++0x [temp.names]p5:
|
||||
// If a name prefixed by the keyword template is not the name of
|
||||
// a template, the program is ill-formed. [Note: the keyword
|
||||
|
@ -3010,10 +3008,16 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
|
|||
= T->getAsTemplateSpecializationType();
|
||||
assert(TemplateId && "Expected a template specialization type");
|
||||
|
||||
if (NNS->isDependent())
|
||||
return Context.getTypenameType(NNS, TemplateId).getAsOpaquePtr();
|
||||
|
||||
return Context.getQualifiedNameType(NNS, T).getAsOpaquePtr();
|
||||
if (computeDeclContext(SS, false)) {
|
||||
// If we can compute a declaration context, then the "typename"
|
||||
// keyword was superfluous. Just build a QualifiedNameType to keep
|
||||
// track of the nested-name-specifier.
|
||||
|
||||
// FIXME: Note that the QualifiedNameType had the "typename" keyword!
|
||||
return Context.getQualifiedNameType(NNS, T).getAsOpaquePtr();
|
||||
}
|
||||
|
||||
return Context.getTypenameType(NNS, TemplateId).getAsOpaquePtr();
|
||||
}
|
||||
|
||||
/// \brief Build the type that describes a C++ typename specifier,
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
template<typename T, typename U>
|
||||
struct is_same {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_same<T, T> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename MetaFun, typename T1, typename T2>
|
||||
struct metafun_apply2 {
|
||||
typedef typename MetaFun::template apply<T1, T2> inner;
|
||||
typedef typename inner::type type;
|
||||
};
|
||||
|
||||
template<typename T, typename U> struct pair;
|
||||
|
||||
struct make_pair {
|
||||
template<typename T1, typename T2>
|
||||
struct apply {
|
||||
typedef pair<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
int a0[is_same<metafun_apply2<make_pair, int, float>::type,
|
||||
pair<int, float> >::value? 1 : -1];
|
||||
int a1[is_same<
|
||||
typename make_pair::template apply<int, float>,
|
||||
make_pair::apply<int, float>
|
||||
>::value? 1 : -1];
|
||||
|
||||
template<typename MetaFun>
|
||||
struct swap_and_apply2 {
|
||||
template<typename T1, typename T2>
|
||||
struct apply {
|
||||
typedef typename MetaFun::template apply<T2, T1> new_metafun;
|
||||
typedef typename new_metafun::type type;
|
||||
};
|
||||
};
|
||||
|
||||
int a2[is_same<swap_and_apply2<make_pair>::apply<int, float>::type,
|
||||
pair<float, int> >::value? 1 : -1];
|
||||
|
||||
template<typename T>
|
||||
struct X0 {
|
||||
template<typename U, typename V>
|
||||
struct Inner;
|
||||
|
||||
void f0(X0<T>::Inner<T*, T&>); // expected-note{{here}}
|
||||
void f0(typename X0<T>::Inner<T*, T&>); // expected-error{{redecl}}
|
||||
|
||||
void f1(X0<T>::Inner<T*, T&>); // expected-note{{here}}
|
||||
void f1(typename X0<T>::template Inner<T*, T&>); // expected-error{{redecl}}
|
||||
};
|
Loading…
Reference in New Issue