[cfe-commits] r67827 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaAccess.cpp test/SemaCXX/access-base-class.cpp
Anders Carlsson
andersca at mac.com
Thu Mar 26 23:03:27 PDT 2009
Author: andersca
Date: Fri Mar 27 01:03:27 2009
New Revision: 67827
URL: http://llvm.org/viewvc/llvm-project?rev=67827&view=rev
Log:
Implement checking for base class access. Right now it's overly conservative but that will change. (Also, protected isn't implemented right now).
Added:
cfe/trunk/test/SemaCXX/access-base-class.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaAccess.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=67827&r1=67826&r2=67827&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Mar 27 01:03:27 2009
@@ -1297,6 +1297,13 @@
"conversion from pointer to member of class %0 to pointer to member "
"of class %1 via virtual base %2 is not allowed">;
+// C++ access control
+def err_conv_to_inaccessible_base : Error<
+ "conversion from %0 to inaccessible base class %1">;
+def note_inheritance_specifier_here : Note<
+ "'%0' inheritance specifier here">;
+def note_inheritance_implicitly_private_here : Note<
+ "inheritance is implicitly 'private'">;
// C++ member name lookup
def err_ambiguous_member_multiple_subobjects : Error<
Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=67827&r1=67826&r2=67827&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Fri Mar 27 01:03:27 2009
@@ -11,7 +11,9 @@
//
//===----------------------------------------------------------------------===//
+#include "SemaInherit.h"
#include "Sema.h"
+#include "clang/AST/ASTContext.h"
using namespace clang;
/// SetMemberAccessSpecifier - Set the access specifier of a member.
@@ -45,5 +47,68 @@
/// and report an error if it can't. [class.access.base]
bool Sema::CheckBaseClassAccess(QualType Derived, QualType Base,
BasePaths& Paths, SourceLocation AccessLoc) {
+ Base = Context.getCanonicalType(Base).getUnqualifiedType();
+ assert(!Paths.isAmbiguous(Base) &&
+ "Can't check base class access if set of paths is ambiguous");
+ assert(Paths.isRecordingPaths() &&
+ "Can't check base class access without recorded paths");
+
+ const CXXBaseSpecifier *InacessibleBase = 0;
+
+ for (BasePaths::paths_iterator Path = Paths.begin(), PathsEnd = Paths.end();
+ Path != PathsEnd; ++Path) {
+
+ bool FoundInaccessibleBase = false;
+
+ for (BasePath::const_iterator Element = Path->begin(),
+ ElementEnd = Path->end(); Element != ElementEnd; ++Element) {
+ const CXXBaseSpecifier *Base = Element->Base;
+
+ switch (Base->getAccessSpecifier()) {
+ default:
+ assert(0 && "invalid access specifier");
+ case AS_public:
+ // Nothing to do.
+ break;
+ case AS_private:
+ // FIXME: Check if the current function is a member or friend.
+ FoundInaccessibleBase = true;
+ break;
+ case AS_protected:
+ // FIXME: Implement
+ break;
+ }
+
+ if (FoundInaccessibleBase) {
+ InacessibleBase = Base;
+ break;
+ }
+ }
+
+ if (!FoundInaccessibleBase) {
+ // We found a path to the base, our work here is done.
+ InacessibleBase = 0;
+ break;
+ }
+ }
+
+ if (InacessibleBase) {
+ Diag(AccessLoc, diag::err_conv_to_inaccessible_base)
+ << Derived << Base;
+
+ AccessSpecifier AS = InacessibleBase->getAccessSpecifierAsWritten();
+
+ // If there's no written access specifier, then the inheritance specifier
+ // is implicitly private.
+ if (AS == AS_none)
+ Diag(InacessibleBase->getSourceRange().getBegin(),
+ diag::note_inheritance_implicitly_private_here);
+ else
+ Diag(InacessibleBase->getSourceRange().getBegin(),
+ diag::note_inheritance_specifier_here) << AS;
+
+ return true;
+ }
+
return false;
}
Added: cfe/trunk/test/SemaCXX/access-base-class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/access-base-class.cpp?rev=67827&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/access-base-class.cpp (added)
+++ cfe/trunk/test/SemaCXX/access-base-class.cpp Fri Mar 27 01:03:27 2009
@@ -0,0 +1,51 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+namespace T1 {
+
+class A { };
+class B : private A { }; // expected-note {{'private' inheritance specifier here}}
+
+void f(B* b) {
+ A *a = b; // expected-error{{conversion from 'class T1::B' to inaccessible base class 'class T1::A'}} \
+ expected-error{{incompatible type initializing 'class T1::B *', expected 'class T1::A *'}}
+}
+
+}
+
+namespace T2 {
+
+class A { };
+class B : A { }; // expected-note {{inheritance is implicitly 'private'}}
+
+void f(B* b) {
+ A *a = b; // expected-error {{conversion from 'class T2::B' to inaccessible base class 'class T2::A'}} \
+ expected-error {{incompatible type initializing 'class T2::B *', expected 'class T2::A *'}}
+}
+
+}
+
+namespace T3 {
+
+class A { };
+class B : public A { };
+
+void f(B* b) {
+ A *a = b;
+}
+
+}
+
+namespace T4 {
+
+class A {};
+
+class B : private virtual A {};
+class C : public virtual A {};
+
+class D : public B, public C {};
+
+void f(D *d) {
+ // This takes the D->C->B->A path.
+ A *a = d;
+}
+
+}
More information about the cfe-commits
mailing list