diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-09-21 14:40:46 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-09-21 14:40:46 +0000 |
commit | f250365ce65412d7d4e331fccf042b6e974c2f14 (patch) | |
tree | af6a4e86c2fa7e896b8fb8508dd939192075469f | |
parent | ca82a82082edc982a1fb5fcfef2dd2c8cf9bc824 (diff) |
Diagnose attempts to write a templated data member, from Stepan
Dyatkovskiy! Fixes PR10896.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140250 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 28 | ||||
-rw-r--r-- | test/SemaTemplate/nested-template.cpp | 16 |
3 files changed, 44 insertions, 3 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index aa81c3aa1c..e8cc275b73 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1947,6 +1947,9 @@ def err_template_template_parm_no_parms : Error< def err_template_variable : Error<"variable %0 declared as a template">; def err_template_variable_noparams : Error< "extraneous 'template<>' in declaration of variable %0">; +def err_template_member : Error<"member %0 declared as a template">; +def err_template_member_noparams : Error< + "extraneous 'template<>' in declaration of member %0">; def err_template_tag_noparams : Error< "extraneous 'template<>' in declaration of %0 %1">; def err_template_decl_ref : Error< diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 67b1274c2c..0d83d9fc5f 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1121,6 +1121,30 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (isInstField) { CXXScopeSpec &SS = D.getCXXScopeSpec(); + // FIXME: Check that the name is an identifier! + IdentifierInfo *II = Name.getAsIdentifierInfo(); + + // Member field could not be with "template" keyword. + // So TemplateParameterLists should be empty in this case. + if (TemplateParameterLists.size()) { + TemplateParameterList* TemplateParams = TemplateParameterLists.get()[0]; + if (TemplateParams->size()) { + // There is no such thing as a member field template. + Diag(D.getIdentifierLoc(), diag::err_template_member) + << II + << SourceRange(TemplateParams->getTemplateLoc(), + TemplateParams->getRAngleLoc()); + } else { + // There is an extraneous 'template<>' for this member. + Diag(TemplateParams->getTemplateLoc(), + diag::err_template_member_noparams) + << II + << SourceRange(TemplateParams->getTemplateLoc(), + TemplateParams->getRAngleLoc()); + } + return 0; + } + if (SS.isSet() && !SS.isInvalid()) { // The user provided a superfluous scope specifier inside a class // definition: @@ -1138,9 +1162,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, SS.clear(); } - - // FIXME: Check for template parameters! - // FIXME: Check that the name is an identifier! + Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth, HasDeferredInit, AS); assert(Member && "HandleField never returns null"); diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp index 01ede32f9a..ab647aa226 100644 --- a/test/SemaTemplate/nested-template.cpp +++ b/test/SemaTemplate/nested-template.cpp @@ -125,4 +125,20 @@ X2<int>::Inner<X2_arg> x2i1; X2<float> x2a; // expected-note{{instantiation}} X2<long>::Inner<X2_arg> x2i3; // expected-error{{template template argument has different}} +namespace PR10896 { + template<typename TN> + class Foo { + + public: + void foo() {} + private: + + template<typename T> + T SomeField; // expected-error {{member 'SomeField' declared as a template}} + }; + void g() { + Foo<int> f; + f.foo(); + } +} |