Warn when a 'typename' or a 'template' keyword refers to a
non-dependent type or template name, respectively, in C++98/03. Fixes PR7111 and <rdar://problem/8002682>. llvm-svn: 105968
This commit is contained in:
parent
5a9d1835be
commit
c9d2682df3
|
@ -1611,6 +1611,9 @@ def note_typename_refers_here : Note<
|
|||
"referenced member %0 is declared here">;
|
||||
def err_typename_missing : Error<
|
||||
"missing 'typename' prior to dependent type name '%0%1'">;
|
||||
def ext_typename_nondependent : ExtWarn<
|
||||
"'typename' refers to a non-dependent type name; accepted as a C++0x "
|
||||
"extension">;
|
||||
|
||||
def err_template_kw_refers_to_non_template : Error<
|
||||
"%0 following the 'template' keyword does not refer to a template">;
|
||||
|
@ -1622,6 +1625,9 @@ def note_referenced_class_template : Error<
|
|||
"class template declared here">;
|
||||
def err_template_kw_missing : Error<
|
||||
"missing 'template' keyword prior to dependent template name '%0%1'">;
|
||||
def ext_template_nondependent : ExtWarn<
|
||||
"'template' refers to a non-dependent template name; accepted as a C++0x "
|
||||
"extension">;
|
||||
|
||||
// C++0x Variadic Templates
|
||||
def err_template_param_pack_default_arg : Error<
|
||||
|
|
|
@ -1714,7 +1714,7 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
|
|||
// the "template" keyword prior to a template-name that was not a
|
||||
// dependent name. C++ DR468 relaxed this requirement (the
|
||||
// "template" keyword is now permitted). We follow the C++0x
|
||||
// rules, even in C++03 mode, retroactively applying the DR.
|
||||
// rules, even in C++03 mode with a warning, retroactively applying the DR.
|
||||
TemplateTy Template;
|
||||
bool MemberOfUnknownSpecialization;
|
||||
TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType,
|
||||
|
@ -1733,6 +1733,15 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
|
|||
return TemplateTy();
|
||||
} else {
|
||||
// We found something; return it.
|
||||
if (ActiveTemplateInstantiations.empty() &&
|
||||
!getLangOptions().CPlusPlus0x &&
|
||||
!SS.isEmpty() && !isDependentScopeSpecifier(SS))
|
||||
Diag(TemplateKWLoc.isValid()? TemplateKWLoc
|
||||
: Name.getSourceRange().getBegin(),
|
||||
diag::ext_template_nondependent)
|
||||
<< SourceRange(Name.getSourceRange().getBegin())
|
||||
<< FixItHint::CreateRemoval(TemplateKWLoc);
|
||||
|
||||
return Template;
|
||||
}
|
||||
}
|
||||
|
@ -5368,7 +5377,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
|
|||
// the "typename" keyword itself is superfluous. In C++03, the
|
||||
// program is actually ill-formed. However, DR 382 (in C++0x CD1)
|
||||
// allows such extraneous "typename" keywords, and we retroactively
|
||||
// apply this DR to C++03 code. In any case we continue.
|
||||
// apply this DR to C++03 code with only a warning. In any case we continue.
|
||||
|
||||
if (RequireCompleteDeclContext(SS, Ctx))
|
||||
return QualType();
|
||||
|
@ -5389,6 +5398,14 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
|
|||
|
||||
case LookupResult::Found:
|
||||
if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
|
||||
if (ActiveTemplateInstantiations.empty() &&
|
||||
!getLangOptions().CPlusPlus0x && !SS.isEmpty() &&
|
||||
!isDependentScopeSpecifier(SS))
|
||||
Diag(KeywordLoc.isValid()? KeywordLoc : IILoc,
|
||||
diag::ext_typename_nondependent)
|
||||
<< SourceRange(IILoc)
|
||||
<< FixItHint::CreateRemoval(KeywordLoc);
|
||||
|
||||
// We found a type. Build an ElaboratedType, since the
|
||||
// typename-specifier was just sugar.
|
||||
return Context.getElaboratedType(ETK_Typename, NNS,
|
||||
|
|
|
@ -62,15 +62,15 @@ struct identity {
|
|||
// or typename-specifiers.
|
||||
if (false) {
|
||||
if (true)
|
||||
return [typename identity<I3>::type method];
|
||||
return [typename identity<I3>::type method]; // expected-warning{{'typename' refers to a non-dependent type name; accepted as a C++0x extension}}
|
||||
|
||||
return [::I3 method];
|
||||
}
|
||||
|
||||
int* ip1 = {[super method]};
|
||||
int* ip2 = {[::I3 method]};
|
||||
int* ip3 = {[typename identity<I3>::type method]};
|
||||
int* ip4 = {[typename identity<I2_holder>::type().get() method]};
|
||||
int* ip3 = {[typename identity<I3>::type method]}; // expected-warning{{'typename' refers to a non-dependent type name; accepted as a C++0x extension}}
|
||||
int* ip4 = {[typename identity<I2_holder>::type().get() method]}; // expected-warning{{'typename' refers to a non-dependent type name; accepted as a C++0x extension}}
|
||||
int array[5] = {[3] = 2};
|
||||
return [super method];
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace N {
|
|||
}
|
||||
|
||||
M::Promote<int>::type *ret_intptr3(int* ip) { return ip; }
|
||||
M::template Promote<int>::type *ret_intptr4(int* ip) { return ip; }
|
||||
M::template Promote<int>::type *ret_intptr4(int* ip) { return ip; } // expected-warning{{'template' refers to a non-dependent template name; accepted as a C++0x extension}}
|
||||
}
|
||||
|
||||
N::M::Promote<int>::type *ret_intptr5(int* ip) { return ip; }
|
||||
|
|
|
@ -62,12 +62,12 @@ struct Y0 {
|
|||
|
||||
template<typename U>
|
||||
void f() {
|
||||
Y0::template f1<U>(0);
|
||||
Y0::template f1(0);
|
||||
Y0::template f1<U>(0); // expected-warning{{'template' refers to a non-dependent template name}}
|
||||
Y0::template f1(0); // expected-warning{{'template' refers to a non-dependent template name}}
|
||||
this->template f1(0);
|
||||
|
||||
Y0::template f2<U>(0);
|
||||
Y0::template f2(0);
|
||||
Y0::template f2<U>(0); // expected-warning{{'template' refers to a non-dependent template name}}
|
||||
Y0::template f2(0);// expected-warning{{'template' refers to a non-dependent template name}}
|
||||
|
||||
Y0::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
|
||||
Y0::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
|
||||
|
@ -75,7 +75,8 @@ struct Y0 {
|
|||
int x;
|
||||
x = Y0::f4(0);
|
||||
x = Y0::f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
|
||||
x = Y0::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
|
||||
x = Y0::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} \
|
||||
// expected-warning{{'template' refers to a non-dependent template name}}
|
||||
|
||||
x = this->f4(0);
|
||||
x = this->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
|
||||
|
|
|
@ -27,7 +27,7 @@ struct make_pair {
|
|||
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>,
|
||||
typename make_pair::template apply<int, float>, // expected-warning{{'template' refers to a non-dependent template name}}
|
||||
make_pair::apply<int, float>
|
||||
>::value? 1 : -1];
|
||||
|
||||
|
|
|
@ -15,19 +15,20 @@ namespace N {
|
|||
|
||||
int i;
|
||||
|
||||
typename N::A::type *ip1 = &i;
|
||||
typename N::A::type *ip1 = &i; // expected-warning{{'typename' refers to a non-dependent type name}}
|
||||
typename N::B::type *ip2 = &i; // expected-error{{no type named 'type' in 'N::B'}}
|
||||
typename N::C::type *ip3 = &i; // expected-error{{typename specifier refers to non-type member 'type'}}
|
||||
|
||||
void test(double d) {
|
||||
typename N::A::type f(typename N::A::type(a)); // expected-warning{{parentheses were disambiguated as a function declarator}}
|
||||
typename N::A::type f(typename N::A::type(a)); // expected-warning{{parentheses were disambiguated as a function declarator}} \
|
||||
// expected-warning 2{{'typename' refers to a non-dependent type name}}
|
||||
int five = f(5);
|
||||
|
||||
using namespace N;
|
||||
for (typename A::type i = 0; i < 10; ++i)
|
||||
for (typename A::type i = 0; i < 10; ++i) // expected-warning{{'typename' refers to a non-dependent type name}}
|
||||
five += 1;
|
||||
|
||||
const typename N::A::type f2(d);
|
||||
const typename N::A::type f2(d); // expected-warning{{'typename' refers to a non-dependent type name}}
|
||||
}
|
||||
|
||||
namespace N {
|
||||
|
|
Loading…
Reference in New Issue