]> granicus.if.org Git - clang/commitdiff
When computing the effective context for access control,
authorJohn McCall <rjmccall@apple.com>
Fri, 24 Aug 2012 22:54:02 +0000 (22:54 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 24 Aug 2012 22:54:02 +0000 (22:54 +0000)
make sure we walk up the DC chain for the current context,
rather than allowing ourselves to get switched over to the
canonical DC chain.  Fixes PR13642.

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

lib/Sema/SemaAccess.cpp
test/CXX/class.access/class.friend/p1.cpp
test/CXX/class.access/class.protected/p1.cpp

index ed72a5600b7277cafd8e3cf62b14530a369c69fb..58b1a51ae573bf7278f50986b1ebc82392d8bd6c 100644 (file)
@@ -97,14 +97,19 @@ struct EffectiveContext {
     // functions (which can gain privileges through friendship), but we
     // take that as an oversight.
     while (true) {
+      // We want to add canonical declarations to the EC lists for
+      // simplicity of checking, but we need to walk up through the
+      // actual current DC chain.  Otherwise, something like a local
+      // extern or friend which happens to be the canonical
+      // declaration will really mess us up.
+
       if (isa<CXXRecordDecl>(DC)) {
-        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
-        Records.push_back(Record);
+        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+        Records.push_back(Record->getCanonicalDecl());
         DC = Record->getDeclContext();
       } else if (isa<FunctionDecl>(DC)) {
-        FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl();
-        Functions.push_back(Function);
-        
+        FunctionDecl *Function = cast<FunctionDecl>(DC);
+        Functions.push_back(Function->getCanonicalDecl());
         if (Function->getFriendObjectKind())
           DC = Function->getLexicalDeclContext();
         else
index 3d3c5f789acc3c600da474e29d85b8fa076d4675..19d94cfdd5f6f2c923ec40ebab0e516ec9787f38 100644 (file)
@@ -356,3 +356,19 @@ namespace PR9103 {
     }
   };
 }
+
+// PR13642.  When computing the effective context, we were walking up
+// the DC chain for the canonical decl, which is unfortunate if that's
+// (e.g.) a friend declaration.
+namespace test14 {
+  class A {
+    class B { // expected-note {{implicitly declared private here}}
+      static int i;
+      friend void c();
+    };
+  };
+
+  void c() {
+    A::B::i = 5; // expected-error {{'B' is a private member of 'test14::A'}}
+  }
+}
index c9491e1196f9a8ab1f1f0f661a02d1ac21f35d3b..132ff6176c01bb88291154bcde3715f278965684 100644 (file)
@@ -423,7 +423,7 @@ namespace test12 {
 // This friendship is not considered because a public member of A is
 // inaccessible in C.
 namespace test13 {
-  class A { protected: int foo(); }; // expected-note {{can only access this member on an object of type}}
+  class A { protected: int foo(); }; // expected-note {{declared protected here}}
   class B : private virtual A {};
   class C : private B { friend void test(); };
   class D : public virtual A {};