diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-12-01 16:58:18 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-12-01 16:58:18 +0000 |
commit | 9af2f52fbcb993350f54e57d498e7849ba29c75d (patch) | |
tree | 558e677a3dc78b60131dd5724675d7bffa65705d | |
parent | d3a505827fd8775ce479498e5726b484336eedd8 (diff) |
Don't automatically assume that an id-expression refers to a
ValueDecl, because that isn't always the case in ill-formed
code. Diagnose a common mistake (forgetting to provide a template
argument list for a class template, PR5655) and dyn_cast so that we
handle the general problem of referring to a non-value declaration
gracefully.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90239 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 18 | ||||
-rw-r--r-- | test/SemaCXX/attr-cxx0x.cpp | 4 | ||||
-rw-r--r-- | test/SemaTemplate/class-template-id.cpp | 5 |
5 files changed, 33 insertions, 9 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a0e03fed16..600db621f7 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -441,7 +441,7 @@ def err_implicit_object_parameter_init : Error< "of type %1">; def note_field_decl : Note<"member is declared here">; -def note_previous_class_decl : Note< +def note_previous_decl : Note< "%0 declared here">; def note_member_synthesized_at : Note< "implicit default %select{constructor|copy constructor|" @@ -934,6 +934,8 @@ def err_template_variable_noparams : Error< "extraneous 'template<>' in declaration of variable %0">; def err_template_tag_noparams : Error< "extraneous 'template<>' in declaration of %0 %1">; +def err_template_decl_ref : Error< + "cannot refer to class template %0 without a template argument list">; // C++ Template Argument Lists def err_template_arg_list_different_arity : Error< @@ -1649,6 +1651,7 @@ def warn_printf_nonliteral : Warning< def err_unexpected_interface : Error< "unexpected interface name %0: expected expression">; +def err_ref_non_value : Error<"%0 does not refer to a value">; def err_property_not_found : Error< "property %0 not found on object of type %1">; def ext_gnu_void_ptr : Extension< diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f161cb5546..e27b82d800 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -489,8 +489,8 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // C++0x CWG Issue #817 indicates that [[final]] classes shouldn't be bases. if (CXXBaseDecl->hasAttr<FinalAttr>()) { Diag(BaseLoc, diag::err_final_base) << BaseType.getAsString(); - Diag(CXXBaseDecl->getLocation(), diag::note_previous_class_decl) - << BaseType.getAsString(); + Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl) + << BaseType; return 0; } @@ -1284,7 +1284,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, Diag(Constructor->getLocation(), diag::err_missing_default_ctor) << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) << 0 << VBase->getType(); - Diag(VBaseDecl->getLocation(), diag::note_previous_class_decl) + Diag(VBaseDecl->getLocation(), diag::note_previous_decl) << Context.getTagDeclType(VBaseDecl); HadError = true; continue; @@ -1332,7 +1332,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, Diag(Constructor->getLocation(), diag::err_missing_default_ctor) << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) << 0 << Base->getType(); - Diag(BaseDecl->getLocation(), diag::note_previous_class_decl) + Diag(BaseDecl->getLocation(), diag::note_previous_decl) << Context.getTagDeclType(BaseDecl); HadError = true; continue; @@ -1399,7 +1399,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName(); Diag(Field->getLocation(), diag::note_field_decl); - Diag(RT->getDecl()->getLocation(), diag::note_previous_class_decl) + Diag(RT->getDecl()->getLocation(), diag::note_previous_decl) << Context.getTagDeclType(RT->getDecl()); HadError = true; continue; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index f653cf63d8..bf14d0d303 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1246,7 +1246,23 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, if (CheckDeclInExpr(*this, Loc, D)) return ExprError(); - ValueDecl *VD = cast<ValueDecl>(D); + if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) { + // Specifically diagnose references to class templates that are missing + // a template argument list. + Diag(Loc, diag::err_template_decl_ref) + << Template << SS.getRange(); + Diag(Template->getLocation(), diag::note_template_decl_here); + return ExprError(); + } + + // Make sure that we're referring to a value. + ValueDecl *VD = dyn_cast<ValueDecl>(D); + if (!VD) { + Diag(Loc, diag::err_ref_non_value) + << D << SS.getRange(); + Diag(D->getLocation(), diag::note_previous_decl); + return ExprError(); + } // Check whether this declaration can be used. Note that we suppress // this check when we're going to perform argument-dependent lookup diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp index da52d338cf..d68779cc88 100644 --- a/test/SemaCXX/attr-cxx0x.cpp +++ b/test/SemaCXX/attr-cxx0x.cpp @@ -2,7 +2,7 @@ int final_fail [[final]]; //expected-error {{'final' attribute only applies to virtual method or class types}} -struct [[final]] final_base { }; // expected-note {{struct final_base declared here}} +struct [[final]] final_base { }; // expected-note {{'struct final_base' declared here}} struct final_child : final_base { }; // expected-error {{derivation from 'final' struct final_base}} struct final_member { virtual void quux [[final]] (); }; // expected-note {{overridden virtual function is here}} @@ -33,4 +33,4 @@ struct base { }; struct [[base_check, base_check]] bc : base { // expected-error {{'base_check' attribute cannot be repeated}} -};
\ No newline at end of file +}; diff --git a/test/SemaTemplate/class-template-id.cpp b/test/SemaTemplate/class-template-id.cpp index e74a6f8dcc..98ccbe7db6 100644 --- a/test/SemaTemplate/class-template-id.cpp +++ b/test/SemaTemplate/class-template-id.cpp @@ -36,3 +36,8 @@ namespace N { N::C<int> c1; typedef N::C<float> c2; + +// PR5655 +template<typename T> struct Foo { }; // expected-note{{template is declared here}} + +void f(void) { Foo bar; } // expected-error{{without a template argument list}} |