[cfe-commits] r67722 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/SemaCXX/access.cpp

Anders Carlsson andersca at mac.com
Wed Mar 25 17:24:25 PDT 2009


Author: andersca
Date: Wed Mar 25 19:24:17 2009
New Revision: 67722

URL: http://llvm.org/viewvc/llvm-project?rev=67722&view=rev
Log:
Check that the access specifier of a member redeclaration is the same as the original declaration.

Added:
    cfe/trunk/test/SemaCXX/access.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDecl.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=67722&r1=67721&r2=67722&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Mar 25 19:24:17 2009
@@ -234,6 +234,12 @@
 def err_deleted_decl_not_first : Error<
   "deleted definition must be first declaration">;
 
+// C++ access checking
+def err_class_redeclared_with_different_access : Error<
+  "%0 redeclared with '%1' access">;
+def note_previous_access_declaration : Note<
+  "previously declared '%1' here">;
+  
 // C++ name lookup
 def err_incomplete_nested_name_spec : Error<
   "incomplete type %0 named in nested name specifier">;

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=67722&r1=67721&r2=67722&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Mar 25 19:24:17 2009
@@ -3083,6 +3083,21 @@
   return NewTD;
 }
 
+static const char *getAccessName(AccessSpecifier AS) {
+  switch (AS) {
+    default:
+    case AS_none:
+      assert("Invalid access specifier!");
+      return 0;
+    case AS_public:
+      return "public";
+    case AS_private:
+      return "private";
+    case AS_protected:
+      return "protected";
+  }
+}
+
 /// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'.  In the
 /// former case, Name will be non-null.  In the later case, Name will be null.
 /// TagSpec indicates what kind of tag this is. TK indicates whether this is a
@@ -3384,9 +3399,17 @@
   // lexical context will be different from the semantic context.
   New->setLexicalDeclContext(CurContext);
 
-  if (PrevDecl)
-    New->setAccess(PrevDecl->getAccess());
-  else
+  if (PrevDecl) {
+    // C++ [class.access.spec]p3: When a member is redeclared its access
+    // specifier must be same as its initial declaration.
+    if (AS != AS_none && AS != PrevDecl->getAccess()) {
+      Diag(Loc, diag::err_class_redeclared_with_different_access) 
+        << New << getAccessName(AS);
+      Diag(PrevDecl->getLocation(), diag::note_previous_access_declaration)
+        << PrevDecl << getAccessName(PrevDecl->getAccess());
+    } else 
+      New->setAccess(PrevDecl->getAccess());
+  } else
     New->setAccess(AS);
 
   if (TK == TK_Definition)

Added: cfe/trunk/test/SemaCXX/access.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/access.cpp?rev=67722&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/access.cpp (added)
+++ cfe/trunk/test/SemaCXX/access.cpp Wed Mar 25 19:24:17 2009
@@ -0,0 +1,15 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+class C {
+    struct S; // expected-note {{previously declared 'private' here}}
+    
+public:
+    struct S {}; // expected-error {{'S' redeclared with 'public' access}}
+};
+
+struct S {
+    class C; // expected-note {{previously declared 'public' here}}
+    
+private:
+    class C { }; // expected-error {{'C' redeclared with 'private' access}}
+};
\ No newline at end of file





More information about the cfe-commits mailing list