summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancois Pichet <pichet2000@gmail.com>2011-05-23 03:43:44 +0000
committerFrancois Pichet <pichet2000@gmail.com>2011-05-23 03:43:44 +0000
commitefb1af9ae83fc28702b3b946fa05b3960f689d5c (patch)
tree65ba40b51909cb74660dee2b710d5dd316a082aa
parentbc90690b24bdbc7d6d2f795bb77038a6c14d6120 (diff)
downloadbcm5719-llvm-efb1af9ae83fc28702b3b946fa05b3960f689d5c.tar.gz
bcm5719-llvm-efb1af9ae83fc28702b3b946fa05b3960f689d5c.zip
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. llvm-svn: 131896
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--clang/include/clang/Sema/Lookup.h16
-rw-r--r--clang/lib/Sema/SemaAccess.cpp52
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp1
-rw-r--r--clang/test/SemaCXX/MicrosoftExtensions.cpp19
5 files changed, 88 insertions, 4 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 00cd81f7e35..e5354b64248 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -596,6 +596,10 @@ def err_class_redeclared_with_different_access : Error<
"%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;
diff --git a/clang/include/clang/Sema/Lookup.h b/clang/include/clang/Sema/Lookup.h
index 400a7cc9194..dceed4efc97 100644
--- a/clang/include/clang/Sema/Lookup.h
+++ b/clang/include/clang/Sema/Lookup.h
@@ -282,6 +282,18 @@ public:
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 @@ private:
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
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index e92d19d13d3..0eb98545627 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -146,8 +146,10 @@ struct AccessTarget : public AccessedEntity {
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 @@ private:
DeclaringClass = DeclaringClass->getCanonicalDecl();
}
+ bool IsUsingDeclaration : 1;
bool HasInstanceContext : 1;
mutable bool CalculatedInstanceContext : 1;
mutable const CXXRecordDecl *InstanceContext;
@@ -1129,6 +1132,44 @@ static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
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 @@ static AccessResult CheckEffectiveAccess(Sema &S,
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 @@ void Sema::CheckLookupAccess(const LookupResult &R) {
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);
}
}
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 4fc9bf1fdd5..8bf7cb67b88 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5345,6 +5345,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
// 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
diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp
index 88e39226708..3391e7afb00 100644
--- a/clang/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp
@@ -197,3 +197,22 @@ void pointer_to_integral_type_conv(char* ptr) {
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
OpenPOWER on IntegriCloud