Author: dblaikie
Date: Sun Feb  9 00:54:23 2014
New Revision: 201038

URL: http://llvm.org/viewvc/llvm-project?rev=201038&view=rev
Log:
Improve diagnostic for using non-class/namespace/scoped enum in a nested name 
specifier.

Rather than simply saying "X is not a class or namespace", clarify what
X is by providing the aka type in the case where X is a type, or
pointing to the named declaration if there's an unambiguous one to refer
to. In the ambiguous case, the ambiguities are already enumerated
(though could be clarified by describing what kind of entities they are)

Included a few FIXMEs in tests where some further improvements could be
made.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
    cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
    cfe/trunk/test/CXX/temp/temp.res/temp.local/p3.cpp
    cfe/trunk/test/SemaCXX/constructor-initializer.cpp
    cfe/trunk/test/SemaCXX/member-pointer.cpp
    cfe/trunk/test/SemaCXX/nested-name-spec.cpp
    cfe/trunk/test/SemaObjCXX/propert-dot-error.mm

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=201038&r1=201037&r2=201038&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Feb  9 00:54:23 
2014
@@ -5253,9 +5253,10 @@ def err_typecheck_deleted_function : Err
   "conversion function %diff{from $ to $|between types}0,1 "
   "invokes a deleted function">;
   
-def err_expected_class_or_namespace : Error<"expected a class or namespace">;
-def err_expected_class : Error<"%0 is not a class%select{ or namespace|, "
-  "namespace, or scoped enumeration}1">;
+def err_expected_class_or_namespace : Error<"%0 is not a class"
+  "%select{ or namespace|, namespace, or scoped enumeration}1">;
+def note_expected_class_or_namespace_declared_here : Note<
+  "%0 declared here">;
 def err_invalid_declarator_scope : Error<"cannot define or redeclare %0 here "
   "because namespace %1 does not enclose namespace %2">;
 def err_invalid_declarator_global_scope : Error<

Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=201038&r1=201037&r2=201038&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Sun Feb  9 00:54:23 2014
@@ -654,20 +654,23 @@ bool Sema::BuildCXXNestedNameSpecifier(S
     }
   }
 
-  unsigned DiagID;
-  if (!Found.empty())
-    DiagID = diag::err_expected_class_or_namespace;
-  else if (SS.isSet()) {
-    Diag(IdentifierLoc, diag::err_no_member) 
-      << &Identifier << LookupCtx << SS.getRange();
-    return true;
-  } else
-    DiagID = diag::err_undeclared_var_use;
-
-  if (SS.isSet())
-    Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange();
+  if (!Found.empty()) {
+    if (TypeDecl *TD = Found.getAsSingle<TypeDecl>())
+      Diag(IdentifierLoc, diag::err_expected_class_or_namespace)
+          << QualType(TD->getTypeForDecl(), 0) << getLangOpts().CPlusPlus;
+    else {
+      Diag(IdentifierLoc, diag::err_expected_class_or_namespace)
+          << &Identifier << getLangOpts().CPlusPlus;
+      if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
+        Diag(ND->getLocation(),
+             diag::note_expected_class_or_namespace_declared_here)
+          << &Identifier;
+    }
+  } else if (SS.isSet())
+    Diag(IdentifierLoc, diag::err_no_member) << &Identifier << LookupCtx
+                                             << SS.getRange();
   else
-    Diag(IdentifierLoc, DiagID) << &Identifier;
+    Diag(IdentifierLoc, diag::err_undeclared_var_use) << &Identifier;
 
   return true;
 }
@@ -698,7 +701,7 @@ bool Sema::ActOnCXXNestedNameSpecifierDe
 
   QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
   if (!T->isDependentType() && !T->getAs<TagType>()) {
-    Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class) 
+    Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class_or_namespace) 
       << T << getLangOpts().CPlusPlus;
     return true;
   }

Modified: 
cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp?rev=201038&r1=201037&r2=201038&view=diff
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp 
(original)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp 
Sun Feb  9 00:54:23 2014
@@ -105,9 +105,10 @@ namespace InhCtor {
 
   };
 
+  // FIXME: Consider reusing the same diagnostic between dependent and 
non-dependent contexts
   typedef int I;
   struct UsingInt {
-    using I::I; // expected-error {{expected a class or namespace}}
+    using I::I; // expected-error {{'I' (aka 'int') is not a class, namespace, 
or scoped enumeration}}
   };
   template<typename T> struct UsingIntTemplate {
     using T::T; // expected-error {{type 'int' cannot be used prior to '::' 
because it has no members}}

Modified: cfe/trunk/test/CXX/temp/temp.res/temp.local/p3.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.res/temp.local/p3.cpp?rev=201038&r1=201037&r2=201038&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.res/temp.local/p3.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.res/temp.local/p3.cpp Sun Feb  9 00:54:23 2014
@@ -15,7 +15,7 @@ template <class T> struct Derived: Base<
     t->Base<T>::f();
     t->Base::f(); // expected-error{{member 'Base' found in multiple base 
classes of different types}} \
     // expected-error{{no member named 'f' in 'X0'}} \
-    // expected-error{{expected a class or namespace}}
+    // expected-error{{'Base' is not a class, namespace, or scoped 
enumeration}}
   }
 };
 

Modified: cfe/trunk/test/SemaCXX/constructor-initializer.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor-initializer.cpp?rev=201038&r1=201037&r2=201038&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constructor-initializer.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor-initializer.cpp Sun Feb  9 00:54:23 2014
@@ -94,7 +94,7 @@ struct Current : Derived {
                            Derived::Base1(), // expected-error {{type 
'Derived::Base1' is not a direct or virtual base of 'Current'}}
                            Derived::V(),
                            ::NonExisting(), // expected-error {{member 
initializer 'NonExisting' does not name a non-static data member or}}
-                           INT::NonExisting()  {} // expected-error {{expected 
a class or namespace}} \
+                           INT::NonExisting()  {} // expected-error {{'INT' 
(aka 'int') is not a class, namespace, or scoped enumeration}} \
                                                   // expected-error {{member 
initializer 'NonExisting' does not name a non-static data member or}}
 };
 

Modified: cfe/trunk/test/SemaCXX/member-pointer.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-pointer.cpp?rev=201038&r1=201037&r2=201038&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/member-pointer.cpp (original)
+++ cfe/trunk/test/SemaCXX/member-pointer.cpp Sun Feb  9 00:54:23 2014
@@ -13,7 +13,7 @@ int A::*pdi1;
 int (::A::*pdi2);
 int (A::*pfi)(int);
 
-int B::*pbi; // expected-error {{expected a class or namespace}}
+int B::*pbi; // expected-error {{'B' is not a class, namespace, or scoped 
enumeration}}
 int C::*pci; // expected-error {{'pci' does not point into a class}}
 void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}}
 int& A::*pdr; // expected-error {{'pdr' declared as a member pointer to a 
reference}}

Modified: cfe/trunk/test/SemaCXX/nested-name-spec.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/nested-name-spec.cpp?rev=201038&r1=201037&r2=201038&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/nested-name-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/nested-name-spec.cpp Sun Feb  9 00:54:23 2014
@@ -85,10 +85,13 @@ struct A2::CC::NC {
 
 void f3() {
   N::x = 0; // expected-error {{use of undeclared identifier 'N'}}
-  int N;
-  N::x = 0; // expected-error {{expected a class or namespace}}
+  // FIXME: Consider including the kind of entity that 'N' is ("variable 'N'
+  // declared here", "template 'X' declared here", etc) to help explain what it
+  // is if it's 'not a class, namespace, or scoped enumeration'.
+  int N; // expected-note {{'N' declared here}}
+  N::x = 0; // expected-error {{'N' is not a class, namespace, or scoped 
enumeration}}
   { int A;           A::ax = 0; }
-  { typedef int A;   A::ax = 0; } // expected-error{{expected a class or 
namespace}}
+  { typedef int A;   A::ax = 0; } // expected-error{{'A' (aka 'int') is not a 
class, namespace, or scoped enumeration}}
   { typedef A::C A;  A::ax = 0; } // expected-error {{no member named 'ax'}}
   { typedef A::C A;  A::cx = 0; }
 }
@@ -114,7 +117,7 @@ namespace E {
     };
 
     void f() {
-      return E::X; // expected-error{{expected a class or namespace}}
+      return E::X; // expected-error{{'E::Nested::E' is not a class, 
namespace, or scoped enumeration}}
     }
   }
 }
@@ -308,4 +311,4 @@ namespace N {
 }
 
 namespace TypedefNamespace { typedef int F; };
-TypedefNamespace::F::NonexistentName BadNNSWithCXXScopeSpec; // expected-error 
{{expected a class or namespace}}
+TypedefNamespace::F::NonexistentName BadNNSWithCXXScopeSpec; // expected-error 
{{'F' (aka 'int') is not a class, namespace, or scoped enumeration}}

Modified: cfe/trunk/test/SemaObjCXX/propert-dot-error.mm
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/propert-dot-error.mm?rev=201038&r1=201037&r2=201038&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/propert-dot-error.mm (original)
+++ cfe/trunk/test/SemaObjCXX/propert-dot-error.mm Sun Feb  9 00:54:23 2014
@@ -53,7 +53,7 @@ void g(B *b) {
 
 // PR9759
 class Forward;
-@interface D {
+@interface D { // expected-note 2 {{'D' declared here}}
 @public
   int ivar;
 }
@@ -64,6 +64,6 @@ class Forward;
 void testD(D *d) {
   d.Forward::property = 17; // expected-error{{property access cannot be 
qualified with 'Forward::'}}
   d->Forward::ivar = 12; // expected-error{{instance variable access cannot be 
qualified with 'Forward::'}}
-  d.D::property = 17; // expected-error{{expected a class or namespace}}
-  d->D::ivar = 12; // expected-error{{expected a class or namespace}}
+  d.D::property = 17; // expected-error{{'D' is not a class, namespace, or 
scoped enumeration}}
+  d->D::ivar = 12; // expected-error{{'D' is not a class, namespace, or scoped 
enumeration}}
 }


_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to