]> granicus.if.org Git - clang/commitdiff
Generalize the checking for qualification of (non-friend) class
authorDouglas Gregor <dgregor@apple.com>
Wed, 13 Oct 2010 22:19:53 +0000 (22:19 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 13 Oct 2010 22:19:53 +0000 (22:19 +0000)
members. Provide a hard error when the qualification doesn't match the
current class type, or a warning + Fix-it if it does match the current
class type. Fixes PR8159.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/nested-name-spec.cpp

index f3541eaba366a205dfc609d2d6c19ea22be80743..bff8c054f1de0bd0f0a788f1a917a04be6af8a68 100644 (file)
@@ -2167,6 +2167,8 @@ def ext_out_of_line_declaration : ExtWarn<
   InGroup<OutOfLineDeclaration>, DefaultError;
 def warn_member_extra_qualification : Warning<
   "extra qualification on member %0">;
+def err_member_qualification : Error<
+  "non-friend class member %0 cannot have a qualified name">;  
 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">;
index a34d7ecf63efa9f7a6aa1809223afcbbaa0a0d06..10785270e5b2d53c24f99df8e6d8c8b9c690579f 100644 (file)
@@ -2265,11 +2265,30 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
         RequireCompleteDeclContext(D.getCXXScopeSpec(), DC))
       return 0;
 
-    if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) {
-      Diag(D.getIdentifierLoc(),
-           diag::err_member_def_undefined_record)
-        << Name << DC << D.getCXXScopeSpec().getRange();
-      D.setInvalidType();
+    if (isa<CXXRecordDecl>(DC)) {
+      if (!cast<CXXRecordDecl>(DC)->hasDefinition()) {
+        Diag(D.getIdentifierLoc(),
+             diag::err_member_def_undefined_record)
+          << Name << DC << D.getCXXScopeSpec().getRange();
+        D.setInvalidType();
+      } else if (isa<CXXRecordDecl>(CurContext) && 
+                 !D.getDeclSpec().isFriendSpecified()) {
+        // The user provided a superfluous scope specifier inside a class
+        // definition:
+        //
+        // class X {
+        //   void X::f();
+        // };
+        if (CurContext->Equals(DC))
+          Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification)
+            << Name << FixItHint::CreateRemoval(D.getCXXScopeSpec().getRange());
+        else
+          Diag(D.getIdentifierLoc(), diag::err_member_qualification)
+            << Name << D.getCXXScopeSpec().getRange();
+        
+        // Pretend that this qualifier was not here.
+        D.getCXXScopeSpec().clear();
+      }
     }
 
     // Check whether we need to rebuild the type of the given
@@ -3684,18 +3703,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
 
   if (NewFD->isInvalidDecl()) {
     // Ignore all the rest of this.
-
-  } else if (CurContext->isRecord() && D.getCXXScopeSpec().isSet() &&
-             !isFriend) {
-    // The user provided a superfluous scope specifier inside a class
-    // definition:
-    //
-    // class X {
-    //   void X::f();
-    // };
-    Diag(NewFD->getLocation(), diag::warn_member_extra_qualification)
-      << Name << FixItHint::CreateRemoval(D.getCXXScopeSpec().getRange());
-
   } else if (!Redeclaration) {
     // Fake up an access specifier if it's supposed to be a class member.
     if (isa<CXXRecordDecl>(NewFD->getDeclContext()))
index 55f668b5c51ad3298d0708ffeb727f7078dff29f..a63f057ae0a87f53ef52bd3f41caf85c65b32dcf 100644 (file)
@@ -896,6 +896,27 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
 
   Decl *Member;
   if (isInstField) {
+    CXXScopeSpec &SS = D.getCXXScopeSpec();
+    
+    
+    if (SS.isSet() && !SS.isInvalid()) {
+      // The user provided a superfluous scope specifier inside a class
+      // definition:
+      //
+      // class X {
+      //   int X::member;
+      // };
+      DeclContext *DC = 0;
+      if ((DC = computeDeclContext(SS, false)) && DC->Equals(CurContext))
+        Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification)
+        << Name << FixItHint::CreateRemoval(SS.getRange());
+      else
+        Diag(D.getIdentifierLoc(), diag::err_member_qualification)
+          << Name << SS.getRange();
+       
+      SS.clear();
+    }
+    
     // FIXME: Check for template parameters!
     Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
                          AS);
index bef8570bffc5106def269349833bd02ba7ba930f..8d33f819af0ecfc83ed11958f5dcc7723771b4d7 100644 (file)
@@ -248,3 +248,13 @@ namespace PR7133 {
 class CLASS {
   void CLASS::foo2(); // expected-warning {{extra qualification on member 'foo2'}}
 };
+
+namespace PR8159 {
+  class B { };
+
+  class A {
+    int A::a; // expected-warning{{extra qualification on member 'a'}}
+    static int A::b; // expected-warning{{extra qualification on member 'b'}}
+    int ::c; // expected-error{{non-friend class member 'c' cannot have a qualified name}}
+  };
+}