[cfe-commits] r115347 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/FixIt/fixit.cpp test/SemaCXX/class.cpp test/SemaCXX/nested-name-spec.cpp

Francois Pichet pichet2000 at gmail.com
Fri Oct 1 14:19:28 PDT 2010


Author: fpichet
Date: Fri Oct  1 16:19:28 2010
New Revision: 115347

URL: http://llvm.org/viewvc/llvm-project?rev=115347&view=rev
Log:
Better diagnostic for superfluous scope specifier inside a class definition for member functions. + Fixit.

Example: 
class A {
   void A::foo(); //warning: extra qualification on member 'foo'
};

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/FixIt/fixit.cpp
    cfe/trunk/test/SemaCXX/class.cpp
    cfe/trunk/test/SemaCXX/nested-name-spec.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=115347&r1=115346&r2=115347&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Oct  1 16:19:28 2010
@@ -2140,6 +2140,8 @@
 def ext_out_of_line_declaration : ExtWarn<
   "out-of-line declaration of a member must be a definition">,
   InGroup<OutOfLineDeclaration>, DefaultError;
+def warn_member_extra_qualification : Warning<
+  "extra qualification on member %0">;
 def note_member_def_close_match : Note<"member declaration nearly matches">;
 def err_typecheck_ivar_variable_size : Error<
   "instance variables must have a constant size">;

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=115347&r1=115346&r2=115347&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Oct  1 16:19:28 2010
@@ -3687,51 +3687,61 @@
   }
 
   if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
-    // Fake up an access specifier if it's supposed to be a class member.
-    if (!Redeclaration && isa<CXXRecordDecl>(NewFD->getDeclContext()))
-      NewFD->setAccess(AS_public);
-
-    // An out-of-line member function declaration must also be a
-    // definition (C++ [dcl.meaning]p1).
-    // Note that this is not the case for explicit specializations of
-    // function templates or member functions of class templates, per
-    // C++ [temp.expl.spec]p2. We also allow these declarations as an extension
-    // for compatibility with old SWIG code which likes to generate them.
-    if (!IsFunctionDefinition && !isFriend &&
-        !isFunctionTemplateSpecialization && !isExplicitSpecialization) {
-      Diag(NewFD->getLocation(), diag::ext_out_of_line_declaration)
-        << D.getCXXScopeSpec().getRange();
-    }
-    if (!Redeclaration && !(isFriend && CurContext->isDependentContext())) {
-      // The user tried to provide an out-of-line definition for a
-      // function that is a member of a class or namespace, but there
-      // was no such member function declared (C++ [class.mfct]p2,
-      // C++ [namespace.memdef]p2). For example:
+    if (!CurContext->isRecord()) {
+      // Fake up an access specifier if it's supposed to be a class member.
+      if (!Redeclaration && isa<CXXRecordDecl>(NewFD->getDeclContext()))
+        NewFD->setAccess(AS_public);
+
+      // An out-of-line member function declaration must also be a
+      // definition (C++ [dcl.meaning]p1).
+      // Note that this is not the case for explicit specializations of
+      // function templates or member functions of class templates, per
+      // C++ [temp.expl.spec]p2. We also allow these declarations as an extension
+      // for compatibility with old SWIG code which likes to generate them.
+      if (!IsFunctionDefinition && !isFriend &&
+          !isFunctionTemplateSpecialization && !isExplicitSpecialization) {
+        Diag(NewFD->getLocation(), diag::ext_out_of_line_declaration)
+          << D.getCXXScopeSpec().getRange();
+      }
+      if (!Redeclaration && !(isFriend && CurContext->isDependentContext())) {
+        // The user tried to provide an out-of-line definition for a
+        // function that is a member of a class or namespace, but there
+        // was no such member function declared (C++ [class.mfct]p2,
+        // C++ [namespace.memdef]p2). For example:
+        //
+        // class X {
+        //   void f() const;
+        // };
+        //
+        // void X::f() { } // ill-formed
+        //
+        // Complain about this problem, and attempt to suggest close
+        // matches (e.g., those that differ only in cv-qualifiers and
+        // whether the parameter types are references).
+        Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match)
+          << Name << DC << D.getCXXScopeSpec().getRange();
+        NewFD->setInvalidDecl();
+
+        LookupResult Prev(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
+                          ForRedeclaration);
+        LookupQualifiedName(Prev, DC);
+        assert(!Prev.isAmbiguous() &&
+               "Cannot have an ambiguity in previous-declaration lookup");
+        for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
+             Func != FuncEnd; ++Func) {
+          if (isa<FunctionDecl>(*Func) &&
+              isNearlyMatchingFunction(Context, cast<FunctionDecl>(*Func), NewFD))
+            Diag((*Func)->getLocation(), diag::note_member_def_close_match);
+        }
+      }
+    } else if (!isFriend) { 
+      // The user provided a superfluous scope specifier inside a class definition:
       //
       // class X {
-      //   void f() const;
+      //   void X::f();
       // };
-      //
-      // void X::f() { } // ill-formed
-      //
-      // Complain about this problem, and attempt to suggest close
-      // matches (e.g., those that differ only in cv-qualifiers and
-      // whether the parameter types are references).
-      Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match)
-        << Name << DC << D.getCXXScopeSpec().getRange();
-      NewFD->setInvalidDecl();
-
-      LookupResult Prev(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
-                        ForRedeclaration);
-      LookupQualifiedName(Prev, DC);
-      assert(!Prev.isAmbiguous() &&
-             "Cannot have an ambiguity in previous-declaration lookup");
-      for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
-           Func != FuncEnd; ++Func) {
-        if (isa<FunctionDecl>(*Func) &&
-            isNearlyMatchingFunction(Context, cast<FunctionDecl>(*Func), NewFD))
-          Diag((*Func)->getLocation(), diag::note_member_def_close_match);
-      }
+      Diag(NewFD->getLocation(), diag::warn_member_extra_qualification)
+        << Name << FixItHint::CreateRemoval(D.getCXXScopeSpec().getRange());
     }
   }
 

Modified: cfe/trunk/test/FixIt/fixit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit.cpp?rev=115347&r1=115346&r2=115347&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/fixit.cpp (original)
+++ cfe/trunk/test/FixIt/fixit.cpp Fri Oct  1 16:19:28 2010
@@ -66,3 +66,8 @@
 // typedef CT<1> mainT(void);
 // mainT main; // TODO
 
+// extra qualification on member
+class C {
+  int C::foo();
+};
+

Modified: cfe/trunk/test/SemaCXX/class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class.cpp?rev=115347&r1=115346&r2=115347&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/class.cpp (original)
+++ cfe/trunk/test/SemaCXX/class.cpp Fri Oct  1 16:19:28 2010
@@ -117,7 +117,7 @@
 struct S
 {
   void f(); // expected-note 1 {{previous declaration}}
-  void S::f() {} // expected-error {{class member cannot be redeclared}} expected-note {{previous declaration}} expected-note {{previous definition}}
+  void S::f() {} // expected-warning {{extra qualification on member}} expected-error {{class member cannot be redeclared}} expected-note {{previous declaration}} expected-note {{previous definition}}
   void f() {} // expected-error {{class member cannot be redeclared}} expected-error {{redefinition}}
 };
 

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=115347&r1=115346&r2=115347&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/nested-name-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/nested-name-spec.cpp Fri Oct  1 16:19:28 2010
@@ -244,3 +244,7 @@
     return false;
   }
 }
+
+class CLASS {
+  void CLASS::foo2(); // expected-warning {{extra qualification on member 'foo2'}}
+};





More information about the cfe-commits mailing list