]> granicus.if.org Git - clang/commitdiff
Don't automatically assume that an id-expression refers to a
authorDouglas Gregor <dgregor@apple.com>
Tue, 1 Dec 2009 16:58:18 +0000 (16:58 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 1 Dec 2009 16:58:18 +0000 (16:58 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExpr.cpp
test/SemaCXX/attr-cxx0x.cpp
test/SemaTemplate/class-template-id.cpp

index a0e03fed16009526e2990d991c3766c8f0a10721..600db621f77396f29411e6eb171edee237aecbc7 100644 (file)
@@ -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<
index f161cb5546a2abf699622aab7bcd29eb5bcd593c..e27b82d800064b95a9bcb82ebc5d710b9cb7dc84 100644 (file)
@@ -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;
index f653cf63d803b010a0d638cbcae998d37aec8705..bf14d0d3032be07d6b96542a310ca48eafae136a 100644 (file)
@@ -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
index da52d338cfbc450252e8ebb09f1380689d1f68e1..d68779cc88869b840b81d1636bc38302741863b5 100644 (file)
@@ -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
+};
index e74a6f8dcca92a57da5e1b1c97e4826026366dfd..98ccbe7db6f854bc82ad39266f1450af7b340ebb 100644 (file)
@@ -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}}