[cfe-commits] r131896 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Lookup.h lib/Sema/SemaAccess.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/MicrosoftExtensions.cpp

Francois Pichet pichet2000 at gmail.com
Sun May 22 20:43:44 PDT 2011


Author: fpichet
Date: Sun May 22 22:43:44 2011
New Revision: 131896

URL: http://llvm.org/viewvc/llvm-project?rev=131896&view=rev
Log:
Emulate a MSVC bug where if during an using declaration name lookup, the declaration found is unaccessible (private) and that declaration was bring into scope via another using declaration whose target declaration is accessible (public) then no error is generated.

Example:
class A { public: int f();  };
class B : public A { private: using A::f; };
class C : public B { private: using B::f; };

Here, B::f is private so this should fail in Standard C++, but because B::f refers to A::f which is public MSVC accepts it.

This fixes 1 error when parsing MFC code with clang.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Lookup.h
    cfe/trunk/lib/Sema/SemaAccess.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=131896&r1=131895&r2=131896&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun May 22 22:43:44 2011
@@ -596,6 +596,10 @@
   "%0 redeclared with '%1' access">;
 def err_access : Error<
   "%1 is a %select{private|protected}0 member of %3">, AccessControl;
+def war_ms_using_declaration_inaccessible : ExtWarn<
+  "using declaration refers to inaccessible member '%0', which refers "
+  "to accessible member '%1', accepted for Microsoft compatibility">,
+    AccessControl, InGroup<Microsoft>;
 def err_access_ctor : Error<
   "calling a %select{private|protected}0 constructor of class %2">, 
   AccessControl;

Modified: cfe/trunk/include/clang/Sema/Lookup.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Lookup.h?rev=131896&r1=131895&r2=131896&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Lookup.h (original)
+++ cfe/trunk/include/clang/Sema/Lookup.h Sun May 22 22:43:44 2011
@@ -282,6 +282,18 @@
     return NamingClass != 0;
   }
 
+  /// \brief Set whether the name lookup is triggered by a 
+  /// using declaration.
+  void setUsingDeclaration(bool U) {
+    UsingDeclaration = U;
+  }
+
+  /// \brief Returns whether the name lookup is triggered by a 
+  /// using declaration.
+  bool isUsingDeclaration() const {
+    return UsingDeclaration;
+  }
+
   /// \brief Returns the 'naming class' for this lookup, i.e. the
   /// class which was looked into to find these results.
   ///
@@ -603,6 +615,10 @@
   bool HideTags;
 
   bool Diagnose;
+
+  /// \brief True if the lookup is triggered by a using declaration.
+  /// Necessary to handle a MSVC bug.
+  bool UsingDeclaration;
 };
 
   /// \brief Consumes visible declarations found when searching for

Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=131896&r1=131895&r2=131896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Sun May 22 22:43:44 2011
@@ -146,8 +146,10 @@
                MemberNonce _,
                CXXRecordDecl *NamingClass,
                DeclAccessPair FoundDecl,
-               QualType BaseObjectType)
-    : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) {
+               QualType BaseObjectType,
+               bool IsUsingDecl = false)
+    : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType),
+      IsUsingDeclaration(IsUsingDecl) {
     initialize();
   }
 
@@ -216,6 +218,7 @@
     DeclaringClass = DeclaringClass->getCanonicalDecl();
   }
 
+  bool IsUsingDeclaration : 1;
   bool HasInstanceContext : 1;
   mutable bool CalculatedInstanceContext : 1;
   mutable const CXXRecordDecl *InstanceContext;
@@ -1129,6 +1132,44 @@
   DiagnoseAccessPath(S, EC, Entity);
 }
 
+/// MSVC has a bug where if during an using declaration name lookup, 
+/// the declaration found is unaccessible (private) and that declaration 
+/// was bring into scope via another using declaration whose target
+/// declaration is accessible (public) then no error is generated.
+/// Example:
+///   class A {
+///   public:
+///     int f();
+///   };
+///   class B : public A {
+///   private:
+///     using A::f;
+///   };
+///   class C : public B {
+///   private:
+///     using B::f;
+///   };
+///
+/// Here, B::f is private so this should fail in Standard C++, but 
+/// because B::f refers to A::f which is public MSVC accepts it.
+static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S, 
+                                                 SourceLocation AccessLoc,
+                                                 AccessTarget &Entity) {
+  if (UsingShadowDecl *Shadow =
+                         dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) {
+    const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
+    if (Entity.getTargetDecl()->getAccess() == AS_private && 
+        (OrigDecl->getAccess() == AS_public ||
+         OrigDecl->getAccess() == AS_protected)) {
+      S.Diag(AccessLoc, diag::war_ms_using_declaration_inaccessible) 
+        << Shadow->getUsingDecl()->getQualifiedNameAsString()
+        << OrigDecl->getQualifiedNameAsString();
+      return true;
+    }
+  }
+  return false;
+}
+
 /// Determines whether the accessed entity is accessible.  Public members
 /// have been weeded out by this point.
 static AccessResult IsAccessible(Sema &S,
@@ -1232,6 +1273,10 @@
                                          AccessTarget &Entity) {
   assert(Entity.getAccess() != AS_public && "called for public access!");
 
+  if (S.getLangOptions().Microsoft &&
+      IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
+    return AR_accessible;
+
   switch (IsAccessible(S, EC, Entity)) {
   case AR_dependent:
     DelayDependentAccess(S, EC, Loc, Entity);
@@ -1577,9 +1622,8 @@
     if (I.getAccess() != AS_public) {
       AccessTarget Entity(Context, AccessedEntity::Member,
                           R.getNamingClass(), I.getPair(),
-                          R.getBaseObjectType());
+                          R.getBaseObjectType(), R.isUsingDeclaration());
       Entity.setDiag(diag::err_access);
-
       CheckAccess(*this, R.getNameLoc(), Entity);
     }
   }

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=131896&r1=131895&r2=131896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun May 22 22:43:44 2011
@@ -5345,6 +5345,7 @@
   // Otherwise, look up the target name.
 
   LookupResult R(*this, NameInfo, LookupOrdinaryName);
+  R.setUsingDeclaration(true);
 
   // Unlike most lookups, we don't always want to hide tag
   // declarations: tag names are visible through the using declaration

Modified: cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp?rev=131896&r1=131895&r2=131896&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp (original)
+++ cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp Sun May 22 22:43:44 2011
@@ -197,3 +197,22 @@
    ch = (char)ptr;
    sh = (short)ptr;
 } 
+
+namespace ms_using_declaration_bug {
+
+class A {
+public: 
+  int f(); 
+};
+
+class B : public A {
+private:   
+  using A::f;
+};
+
+class C : public B { 
+private:   
+  using B::f; // expected-warning {{using declaration refers to inaccessible member 'ms_using_declaration_bug::B::f', which refers to accessible member 'ms_using_declaration_bug::A::f', accepted for Microsoft compatibility}}
+};
+
+}
\ No newline at end of file





More information about the cfe-commits mailing list