]> granicus.if.org Git - clang/commitdiff
Improve diagnostic for using non-class/namespace/scoped enum in a nested name specifier.
authorDavid Blaikie <dblaikie@gmail.com>
Sun, 9 Feb 2014 06:54:23 +0000 (06:54 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Sun, 9 Feb 2014 06:54:23 +0000 (06:54 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@201038 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 0e8e213dc96274d2219b62d646ca6e89c8c5c881..edbf97e500f08e1dca960de69d6d53a3fd10c035 100644 (file)
@@ -5253,9 +5253,10 @@ def err_typecheck_deleted_function : Error<
   "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<
index 9a390a7e266a3d3e2ab83e5c0874e07d0702f66e..ef1eaf2c1460bc6959832f051e9c93554382d695 100644 (file)
@@ -654,20 +654,23 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *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::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
 
   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;
   }
index 1f78a738f38bf2853a5551ab0875db0417921766..b9e83988cfb8258b40219c03f2906bf31cb9571d 100644 (file)
@@ -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}}
index 54da8856fe46001cc5d10ad4fbe1845ff0587485..e29ced19bc4f52e176e3dc4eca9dc008385d1241 100644 (file)
@@ -15,7 +15,7 @@ template <class T> struct Derived: Base<int>, Base<char> {
     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}}
   }
 };
 
index 697f718eabb8a2d5540e4c5ab0f74ca318528841..81dc19ea6dfc0dabdcb9c5bc5fafceaac6577957 100644 (file)
@@ -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}}
 };
 
index 82873d9c7daed59f32487f16542765ab2bc5512f..b8631bcf3efc928d8a722e2e380054bbc261d268 100644 (file)
@@ -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}}
index a0bac059a20d5e58a0a581f524a536d940871dce..8587e70158b06dcd27a71957f46c134d3d826a81 100644 (file)
@@ -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}}
index 2a462e4ffa372df4999fdecd5a535c0e5ccae629..e28204c665fc2e0a2ea230031d4503d8bf7aade5 100644 (file)
@@ -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}}
 }