[cfe-commits] r94647 - in /cfe/trunk: include/clang/AST/ExprCXX.h include/clang/AST/UnresolvedSet.h lib/AST/ExprCXX.cpp lib/Sema/Sema.h lib/Sema/SemaAccess.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateDeduction.cpp test/CXX/class.access/p4.cpp

John McCall rjmccall at apple.com
Tue Jan 26 17:50:19 PST 2010


Author: rjmccall
Date: Tue Jan 26 19:50:18 2010
New Revision: 94647

URL: http://llvm.org/viewvc/llvm-project?rev=94647&view=rev
Log:
Implement access control for overloaded functions.  Suppress access control
diagnostics in "early" lookups, such as during typename checks and when building
unresolved lookup expressions.


Added:
    cfe/trunk/test/CXX/class.access/p4.cpp
Modified:
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/UnresolvedSet.h
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaAccess.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=94647&r1=94646&r2=94647&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Tue Jan 26 19:50:18 2010
@@ -1077,6 +1077,13 @@
   /// The name declared.
   DeclarationName Name;
 
+  /// The naming class (C++ [class.access.base]p5) of the lookup, if
+  /// any.  This can generally be recalculated from the context chain,
+  /// but that can be fairly expensive for unqualified lookups.  If we
+  /// want to improve memory use here, this could go in a union
+  /// against the qualified-lookup bits.
+  CXXRecordDecl *NamingClass;
+
   /// The qualifier given, if any.
   NestedNameSpecifier *Qualifier;
 
@@ -1099,12 +1106,13 @@
   /// This requires all the results to be function templates.  
   bool HasExplicitTemplateArgs;
 
-  UnresolvedLookupExpr(QualType T, bool Dependent,
+  UnresolvedLookupExpr(QualType T, bool Dependent, CXXRecordDecl *NamingClass,
                        NestedNameSpecifier *Qualifier, SourceRange QRange,
                        DeclarationName Name, SourceLocation NameLoc,
                        bool RequiresADL, bool Overloaded, bool HasTemplateArgs)
     : Expr(UnresolvedLookupExprClass, T, Dependent, Dependent),
-      Name(Name), Qualifier(Qualifier), QualifierRange(QRange),
+      Name(Name), NamingClass(NamingClass),
+      Qualifier(Qualifier), QualifierRange(QRange),
       NameLoc(NameLoc), RequiresADL(RequiresADL), Overloaded(Overloaded),
       HasExplicitTemplateArgs(HasTemplateArgs)
   {}
@@ -1112,18 +1120,21 @@
 public:
   static UnresolvedLookupExpr *Create(ASTContext &C,
                                       bool Dependent,
+                                      CXXRecordDecl *NamingClass,
                                       NestedNameSpecifier *Qualifier,
                                       SourceRange QualifierRange,
                                       DeclarationName Name,
                                       SourceLocation NameLoc,
                                       bool ADL, bool Overloaded) {
     return new(C) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy,
-                                       Dependent, Qualifier, QualifierRange,
+                                       Dependent, NamingClass,
+                                       Qualifier, QualifierRange,
                                        Name, NameLoc, ADL, Overloaded, false);
   }
 
   static UnresolvedLookupExpr *Create(ASTContext &C,
                                       bool Dependent,
+                                      CXXRecordDecl *NamingClass,
                                       NestedNameSpecifier *Qualifier,
                                       SourceRange QualifierRange,
                                       DeclarationName Name,
@@ -1141,10 +1152,6 @@
     Results.append(Begin, End);
   }
 
-  void addDecl(NamedDecl *Decl) {
-    Results.addDecl(Decl);
-  }
-
   typedef UnresolvedSetImpl::iterator decls_iterator;
   decls_iterator decls_begin() const { return Results.begin(); }
   decls_iterator decls_end() const { return Results.end(); }
@@ -1165,6 +1172,11 @@
   /// Gets the location of the name.
   SourceLocation getNameLoc() const { return NameLoc; }
 
+  /// Gets the 'naming class' (in the sense of C++0x
+  /// [class.access.base]p5) of the lookup.  This is the scope
+  /// that was looked in to find these results.
+  CXXRecordDecl *getNamingClass() const { return NamingClass; }
+
   /// Fetches the nested-name qualifier, if one was given.
   NestedNameSpecifier *getQualifier() const { return Qualifier; }
 
@@ -1798,8 +1810,8 @@
   /// Adds a declaration to the unresolved set.  By assumption, all of
   /// these happen at initialization time and properties like
   /// 'Dependent' and 'HasUnresolvedUsing' take them into account.
-  void addDecl(NamedDecl *Decl) {
-    Results.addDecl(Decl);
+  void addDecls(UnresolvedSetIterator Begin, UnresolvedSetIterator End) {
+    Results.append(Begin, End);
   }
 
   typedef UnresolvedSetImpl::iterator decls_iterator;
@@ -1843,6 +1855,9 @@
   /// that qualifies the member name.
   SourceRange getQualifierRange() const { return QualifierRange; }
 
+  /// \brief Retrieves the naming class of this lookup.
+  CXXRecordDecl *getNamingClass() const;
+
   /// \brief Retrieve the name of the member that this expression
   /// refers to.
   DeclarationName getMemberName() const { return MemberName; }

Modified: cfe/trunk/include/clang/AST/UnresolvedSet.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/UnresolvedSet.h?rev=94647&r1=94646&r2=94647&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/UnresolvedSet.h (original)
+++ cfe/trunk/include/clang/AST/UnresolvedSet.h Tue Jan 26 19:50:18 2010
@@ -137,6 +137,11 @@
     *I.ir = DeclEntry(New, AS);
   }
 
+  void erase(unsigned I) {
+    decls()[I] = decls().back();
+    decls().pop_back();
+  }
+
   void erase(iterator I) {
     *I.ir = decls().back();
     decls().pop_back();

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=94647&r1=94646&r2=94647&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Tue Jan 26 19:50:18 2010
@@ -116,6 +116,7 @@
 // UnresolvedLookupExpr
 UnresolvedLookupExpr *
 UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
+                             CXXRecordDecl *NamingClass,
                              NestedNameSpecifier *Qualifier,
                              SourceRange QualifierRange, DeclarationName Name,
                              SourceLocation NameLoc, bool ADL,
@@ -125,7 +126,8 @@
                          ExplicitTemplateArgumentList::sizeFor(Args));
   UnresolvedLookupExpr *ULE
     = new (Mem) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy,
-                                     Dependent, Qualifier, QualifierRange,
+                                     Dependent, NamingClass,
+                                     Qualifier, QualifierRange,
                                      Name, NameLoc, ADL,
                                      /*Overload*/ true,
                                      /*ExplicitTemplateArgs*/ true);
@@ -651,6 +653,35 @@
                              Member, MemberLoc, TemplateArgs);
 }
 
+CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
+  // Unlike for UnresolvedLookupExpr, it is very easy to re-derive this.
+
+  // If there was a nested name specifier, it names the naming class.
+  // It can't be dependent: after all, we were actually able to do the
+  // lookup.
+  const RecordType *RT;
+  if (Qualifier) {
+    Type *T = Qualifier->getAsType();
+    assert(T && "qualifier in member expression does not name type");
+    RT = T->getAs<RecordType>();
+    assert(RT && "qualifier in member expression does not name record");
+
+  // Otherwise the naming class must have been the base class.
+  } else {
+    QualType BaseType = getBaseType().getNonReferenceType();
+    if (isArrow()) {
+      const PointerType *PT = BaseType->getAs<PointerType>();
+      assert(PT && "base of arrow member access is not pointer");
+      BaseType = PT->getPointeeType();
+    }
+    
+    RT = BaseType->getAs<RecordType>();
+    assert(RT && "base of member expression does not name record");
+  }
+  
+  return cast<CXXRecordDecl>(RT->getDecl());
+}
+
 Stmt::child_iterator UnresolvedMemberExpr::child_begin() {
   return child_iterator(&Base);
 }

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=94647&r1=94646&r2=94647&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Jan 26 19:50:18 2010
@@ -60,6 +60,7 @@
   class CallExpr;
   class DeclRefExpr;
   class UnresolvedLookupExpr;
+  class UnresolvedMemberExpr;
   class VarDecl;
   class ParmVarDecl;
   class TypedefDecl;
@@ -2376,8 +2377,14 @@
                                                CXXBasePaths &Paths,
                                                bool NoPrivileges = false);
 
-  void CheckAccess(const LookupResult &R);
+  bool CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
+                                   NamedDecl *D,
+                                   AccessSpecifier Access);
+  bool CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
+                                   NamedDecl *D,
+                                   AccessSpecifier Access);
   bool CheckAccess(const LookupResult &R, NamedDecl *D, AccessSpecifier Access);
+  void CheckAccess(const LookupResult &R);
 
   bool CheckBaseClassAccess(QualType Derived, QualType Base,
                             unsigned InaccessibleBaseID,
@@ -2882,14 +2889,13 @@
   FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
                                                    FunctionTemplateDecl *FT2,
                                            TemplatePartialOrderingContext TPOC);
-  FunctionDecl *getMostSpecialized(FunctionDecl **Specializations,
-                                   unsigned NumSpecializations,
-                                   TemplatePartialOrderingContext TPOC,
-                                   SourceLocation Loc,
-                                   const PartialDiagnostic &NoneDiag,
-                                   const PartialDiagnostic &AmbigDiag,
-                                   const PartialDiagnostic &CandidateDiag,
-                                   unsigned *Index = 0);
+  UnresolvedSetIterator getMostSpecialized(UnresolvedSetIterator SBegin,
+                                           UnresolvedSetIterator SEnd,
+                                           TemplatePartialOrderingContext TPOC,
+                                           SourceLocation Loc,
+                                           const PartialDiagnostic &NoneDiag,
+                                           const PartialDiagnostic &AmbigDiag,
+                                        const PartialDiagnostic &CandidateDiag);
                                    
   ClassTemplatePartialSpecializationDecl *
   getMoreSpecializedPartialSpecialization(

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Tue Jan 26 19:50:18 2010
@@ -16,6 +16,8 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
+
 using namespace clang;
 
 /// SetMemberAccessSpecifier - Set the access specifier of a member.
@@ -231,6 +233,46 @@
   return true;
 }
 
+bool Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
+                                       NamedDecl *D, AccessSpecifier Access) {
+  if (!getLangOptions().AccessControl || !E->getNamingClass())
+    return false;
+
+  // Fake up a lookup result.
+  LookupResult R(*this, E->getName(), E->getNameLoc(), LookupOrdinaryName);
+  R.suppressDiagnostics();
+
+  R.setNamingClass(E->getNamingClass());
+  R.addDecl(D, Access);
+
+  // FIXME: protected check (triggers for member-address expressions)
+
+  return CheckAccess(R, D, Access);
+}
+
+/// Perform access-control checking on a previously-unresolved member
+/// access which has now been resolved to a member.
+bool Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
+                                       NamedDecl *D, AccessSpecifier Access) {
+  if (!getLangOptions().AccessControl)
+    return false;
+
+  // Fake up a lookup result.
+  LookupResult R(*this, E->getMemberName(), E->getMemberLoc(),
+                 LookupOrdinaryName);
+  R.suppressDiagnostics();
+
+  R.setNamingClass(E->getNamingClass());
+  R.addDecl(D, Access);
+
+  if (CheckAccess(R, D, Access))
+    return true;
+
+  // FIXME: protected check
+
+  return false;
+}
+
 /// Checks access to all the declarations in the given result set.
 void Sema::CheckAccess(const LookupResult &R) {
   for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jan 26 19:50:18 2010
@@ -135,6 +135,7 @@
   case LookupResult::NotFoundInCurrentInstantiation:
   case LookupResult::FoundOverloaded:
   case LookupResult::FoundUnresolvedValue:
+    Result.suppressDiagnostics();
     return 0;
 
   case LookupResult::Ambiguous:

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jan 26 19:50:18 2010
@@ -1497,16 +1497,20 @@
       CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl()))
     return ExprError();
 
+  // Otherwise, just build an unresolved lookup expression.  Suppress
+  // any lookup-related diagnostics; we'll hash these out later, when
+  // we've picked a target.
+  R.suppressDiagnostics();
+
   bool Dependent
     = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), 0);
   UnresolvedLookupExpr *ULE
-    = UnresolvedLookupExpr::Create(Context, Dependent,
+    = UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(),
                                    (NestedNameSpecifier*) SS.getScopeRep(),
                                    SS.getRange(),
                                    R.getLookupName(), R.getNameLoc(),
                                    NeedsADL, R.isOverloadedResult());
-  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
-    ULE->addDecl(*I);
+  ULE->addDecls(R.begin(), R.end());
 
   return Owned(ULE);
 }
@@ -2544,6 +2548,10 @@
       R.isUnresolvableResult() ||
       UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), TemplateArgs);
 
+    // Suppress any lookup-related diagnostics; we'll do these when we
+    // pick a member.
+    R.suppressDiagnostics();
+
     UnresolvedMemberExpr *MemExpr
       = UnresolvedMemberExpr::Create(Context, Dependent,
                                      R.isUnresolvableResult(),
@@ -2552,8 +2560,7 @@
                                      Qualifier, SS.getRange(),
                                      MemberName, MemberLoc,
                                      TemplateArgs);
-    for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
-      MemExpr->addDecl(*I);
+    MemExpr->addDecls(R.begin(), R.end());
 
     return Owned(MemExpr);
   }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Jan 26 19:50:18 2010
@@ -4851,6 +4851,14 @@
   }
 }
 
+static bool CheckUnresolvedAccess(Sema &S, Expr *E, NamedDecl *D,
+                                  AccessSpecifier AS) {
+  if (isa<UnresolvedLookupExpr>(E))
+    return S.CheckUnresolvedLookupAccess(cast<UnresolvedLookupExpr>(E), D, AS);
+
+  return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D, AS);
+}
+
 /// ResolveAddressOfOverloadedFunction - Try to resolve the address of
 /// an overloaded function (C++ [over.over]), where @p From is an
 /// expression with overloaded function type and @p ToType is the type
@@ -4928,7 +4936,7 @@
 
   // Look through all of the overloaded functions, searching for one
   // whose type matches exactly.
-  llvm::SmallPtrSet<FunctionDecl *, 4> Matches;
+  UnresolvedSet<4> Matches;  // contains only FunctionDecls
   bool FoundNonTemplateFunction = false;
   for (UnresolvedSetIterator I = Fns->begin(), E = Fns->end(); I != E; ++I) {
     // Look through any using declarations to find the underlying function.
@@ -4972,8 +4980,8 @@
         // a candidate? Find a testcase before changing the code.
         assert(FunctionType
                  == Context.getCanonicalType(Specialization->getType()));
-        Matches.insert(
-                cast<FunctionDecl>(Specialization->getCanonicalDecl()));
+        Matches.addDecl(cast<FunctionDecl>(Specialization->getCanonicalDecl()),
+                        I.getAccess());
       }
 
       continue;
@@ -4996,7 +5004,8 @@
       if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) ||
           IsNoReturnConversion(Context, FunDecl->getType(), FunctionType, 
                                ResultTy)) {
-        Matches.insert(cast<FunctionDecl>(FunDecl->getCanonicalDecl()));
+        Matches.addDecl(cast<FunctionDecl>(FunDecl->getCanonicalDecl()),
+                        I.getAccess());
         FoundNonTemplateFunction = true;
       }
     }
@@ -5006,14 +5015,15 @@
   if (Matches.empty())
     return 0;
   else if (Matches.size() == 1) {
-    FunctionDecl *Result = *Matches.begin();
+    FunctionDecl *Result = cast<FunctionDecl>(*Matches.begin());
     MarkDeclarationReferenced(From->getLocStart(), Result);
+    if (Complain)
+      CheckUnresolvedAccess(*this, OvlExpr, Result, Matches.begin().getAccess());
     return Result;
   }
 
   // C++ [over.over]p4:
   //   If more than one function is selected, [...]
-  typedef llvm::SmallPtrSet<FunctionDecl *, 4>::iterator MatchIter;
   if (!FoundNonTemplateFunction) {
     //   [...] and any given function template specialization F1 is
     //   eliminated if the set contains a second function template
@@ -5025,41 +5035,50 @@
     // two-pass algorithm (similar to the one used to identify the
     // best viable function in an overload set) that identifies the
     // best function template (if it exists).
-    llvm::SmallVector<FunctionDecl *, 8> TemplateMatches(Matches.begin(),
-                                                         Matches.end());
-    FunctionDecl *Result =
-        getMostSpecialized(TemplateMatches.data(), TemplateMatches.size(),
+    
+    UnresolvedSetIterator Result =
+        getMostSpecialized(Matches.begin(), Matches.end(),
                            TPOC_Other, From->getLocStart(),
                            PDiag(),
                            PDiag(diag::err_addr_ovl_ambiguous)
-                               << TemplateMatches[0]->getDeclName(),
+                               << Matches[0]->getDeclName(),
                            PDiag(diag::note_ovl_candidate)
                                << (unsigned) oc_function_template);
-    MarkDeclarationReferenced(From->getLocStart(), Result);
-    return Result;
+    assert(Result != Matches.end() && "no most-specialized template");
+    MarkDeclarationReferenced(From->getLocStart(), *Result);
+    if (Complain)
+      CheckUnresolvedAccess(*this, OvlExpr, *Result, Result.getAccess());
+    return cast<FunctionDecl>(*Result);
   }
 
   //   [...] any function template specializations in the set are
   //   eliminated if the set also contains a non-template function, [...]
-  llvm::SmallVector<FunctionDecl *, 4> RemainingMatches;
-  for (MatchIter M = Matches.begin(), MEnd = Matches.end(); M != MEnd; ++M)
-    if ((*M)->getPrimaryTemplate() == 0)
-      RemainingMatches.push_back(*M);
+  for (unsigned I = 0, N = Matches.size(); I != N; ) {
+    if (cast<FunctionDecl>(Matches[I].getDecl())->getPrimaryTemplate() == 0)
+      ++I;
+    else {
+      Matches.erase(I);
+      --N;
+    }
+  }
   
   // [...] After such eliminations, if any, there shall remain exactly one
   // selected function.
-  if (RemainingMatches.size() == 1) {
-    FunctionDecl *Result = RemainingMatches.front();
-    MarkDeclarationReferenced(From->getLocStart(), Result);
-    return Result;
+  if (Matches.size() == 1) {
+    UnresolvedSetIterator Match = Matches.begin();
+    MarkDeclarationReferenced(From->getLocStart(), *Match);
+    if (Complain)
+      CheckUnresolvedAccess(*this, OvlExpr, *Match, Match.getAccess());
+    return cast<FunctionDecl>(*Match);
   }
 
   // FIXME: We should probably return the same thing that BestViableFunction
   // returns (even if we issue the diagnostics here).
   Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
-    << RemainingMatches[0]->getDeclName();
-  for (unsigned I = 0, N = RemainingMatches.size(); I != N; ++I)
-    NoteOverloadCandidate(RemainingMatches[I]);
+    << Matches[0]->getDeclName();
+  for (UnresolvedSetIterator I = Matches.begin(),
+         E = Matches.end(); I != E; ++I)
+    NoteOverloadCandidate(cast<FunctionDecl>(*I));
   return 0;
 }
 
@@ -5345,6 +5364,7 @@
   switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) {
   case OR_Success: {
     FunctionDecl *FDecl = Best->Function;
+    CheckUnresolvedLookupAccess(ULE, FDecl, Best->getAccess());
     Fn = FixOverloadedFunctionReference(Fn, FDecl);
     return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc);
   }
@@ -5425,8 +5445,9 @@
   }
 
   if (Input->isTypeDependent()) {
+    CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
     UnresolvedLookupExpr *Fn
-      = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true,
+      = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
                                      0, SourceRange(), OpName, OpLoc,
                                      /*ADL*/ true, IsOverloaded(Fns));
     Fn->addDecls(Fns.begin(), Fns.end());
@@ -5467,6 +5488,8 @@
       // We matched an overloaded operator. Build a call to that
       // operator.
 
+      // FIXME: access control
+
       // Convert the arguments.
       if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
         if (PerformObjectArgumentInitialization(Input, Method))
@@ -5592,8 +5615,9 @@
     }
 
     // FIXME: save results of ADL from here?
+    CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
     UnresolvedLookupExpr *Fn
-      = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true,
+      = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
                                      0, SourceRange(), OpName, OpLoc,
                                      /*ADL*/ true, IsOverloaded(Fns));
 
@@ -5647,6 +5671,8 @@
         // We matched an overloaded operator. Build a call to that
         // operator.
 
+        // FIXME: access control
+
         // Convert the arguments.
         if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
           OwningExprResult Arg1
@@ -5783,8 +5809,9 @@
   // expression.
   if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
 
+    CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
     UnresolvedLookupExpr *Fn
-      = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true,
+      = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
                                      0, SourceRange(), OpName, LLoc,
                                      /*ADL*/ true, /*Overloaded*/ false);
     // Can't add any actual overloads yet
@@ -5819,6 +5846,8 @@
         // We matched an overloaded operator. Build a call to that
         // operator.
 
+        // FIXME: access control
+
         // Convert the arguments.
         CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
         if (PerformObjectArgumentInitialization(Args[0], Method) ||
@@ -5968,6 +5997,7 @@
     switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) {
     case OR_Success:
       Method = cast<CXXMethodDecl>(Best->Function);
+      CheckUnresolvedMemberAccess(UnresExpr, Method, Best->getAccess());
       break;
 
     case OR_No_Viable_Function:

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Jan 26 19:50:18 2010
@@ -1525,17 +1525,19 @@
     Qualifier = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
     QualifierRange = SS.getRange();
   }
+
+  // We don't want lookup warnings at this point.
+  R.suppressDiagnostics();
   
   bool Dependent
     = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(),
                                               &TemplateArgs);
   UnresolvedLookupExpr *ULE
-    = UnresolvedLookupExpr::Create(Context, Dependent,
+    = UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(),
                                    Qualifier, QualifierRange,
                                    R.getLookupName(), R.getNameLoc(),
                                    RequiresADL, TemplateArgs);
-  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
-    ULE->addDecl(*I);
+  ULE->addDecls(R.begin(), R.end());
 
   return Owned(ULE);
 }
@@ -3817,8 +3819,7 @@
                                           LookupResult &Previous) {
   // The set of function template specializations that could match this
   // explicit function template specialization.
-  typedef llvm::SmallVector<FunctionDecl *, 8> CandidateSet;
-  CandidateSet Candidates;
+  UnresolvedSet<8> Candidates;
   
   DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext();
   for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
@@ -3851,22 +3852,24 @@
       }
       
       // Record this candidate.
-      Candidates.push_back(Specialization);
+      Candidates.addDecl(Specialization, I.getAccess());
     }
   }
   
   // Find the most specialized function template.
-  FunctionDecl *Specialization = getMostSpecialized(Candidates.data(),
-                                                    Candidates.size(),
-                                                    TPOC_Other,
-                                                    FD->getLocation(),
+  UnresolvedSetIterator Result
+    = getMostSpecialized(Candidates.begin(), Candidates.end(),
+                         TPOC_Other, FD->getLocation(),
                   PartialDiagnostic(diag::err_function_template_spec_no_match) 
                     << FD->getDeclName(),
                   PartialDiagnostic(diag::err_function_template_spec_ambiguous)
                     << FD->getDeclName() << (ExplicitTemplateArgs != 0),
                   PartialDiagnostic(diag::note_function_template_spec_matched));
-  if (!Specialization)
+  if (Result == Candidates.end())
     return true;
+
+  // Ignore access information;  it doesn't figure into redeclaration checking.
+  FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
   
   // FIXME: Check if the prior specialization has a point of instantiation.
   // If so, we have run afoul of .
@@ -4568,7 +4571,7 @@
   //   A member function [...] of a class template can be explicitly 
   //  instantiated from the member definition associated with its class 
   //  template.
-  llvm::SmallVector<FunctionDecl *, 8> Matches;
+  UnresolvedSet<8> Matches;
   for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
        P != PEnd; ++P) {
     NamedDecl *Prev = *P;
@@ -4577,7 +4580,7 @@
         if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
           Matches.clear();
 
-          Matches.push_back(Method);
+          Matches.addDecl(Method, P.getAccess());
           if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
             break;
         }
@@ -4599,19 +4602,22 @@
       continue;
     }
     
-    Matches.push_back(Specialization);
+    Matches.addDecl(Specialization, P.getAccess());
   }
   
   // Find the most specialized function template specialization.
-  FunctionDecl *Specialization
-    = getMostSpecialized(Matches.data(), Matches.size(), TPOC_Other, 
+  UnresolvedSetIterator Result
+    = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, 
                          D.getIdentifierLoc(), 
           PartialDiagnostic(diag::err_explicit_instantiation_not_known) << Name,
           PartialDiagnostic(diag::err_explicit_instantiation_ambiguous) << Name,
                 PartialDiagnostic(diag::note_explicit_instantiation_candidate));
 
-  if (!Specialization)
+  if (Result == Matches.end())
     return true;
+
+  // Ignore access control bits, we don't need them for redeclaration checking.
+  FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
   
   if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) {
     Diag(D.getIdentifierLoc(), 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Jan 26 19:50:18 2010
@@ -1987,11 +1987,11 @@
 /// \brief Retrieve the most specialized of the given function template
 /// specializations.
 ///
-/// \param Specializations the set of function template specializations that
-/// we will be comparing.
+/// \param SpecBegin the start iterator of the function template
+/// specializations that we will be comparing.
 ///
-/// \param NumSpecializations the number of function template specializations in
-/// \p Specializations
+/// \param SpecEnd the end iterator of the function template
+/// specializations, paired with \p SpecBegin.
 ///
 /// \param TPOC the partial ordering context to use to compare the function
 /// template specializations.
@@ -2015,41 +2015,37 @@
 /// specialization.
 ///
 /// \returns the most specialized function template specialization, if 
-/// found. Otherwise, returns NULL.
+/// found. Otherwise, returns SpecEnd.
 ///
 /// \todo FIXME: Consider passing in the "also-ran" candidates that failed 
 /// template argument deduction.
-FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations,
-                                       unsigned NumSpecializations,
-                                       TemplatePartialOrderingContext TPOC,
-                                       SourceLocation Loc,
-                                       const PartialDiagnostic &NoneDiag,
-                                       const PartialDiagnostic &AmbigDiag,
-                                       const PartialDiagnostic &CandidateDiag,
-                                       unsigned *Index) {
-  if (NumSpecializations == 0) {
+UnresolvedSetIterator
+Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
+                         UnresolvedSetIterator SpecEnd,
+                         TemplatePartialOrderingContext TPOC,
+                         SourceLocation Loc,
+                         const PartialDiagnostic &NoneDiag,
+                         const PartialDiagnostic &AmbigDiag,
+                         const PartialDiagnostic &CandidateDiag) {
+  if (SpecBegin == SpecEnd) {
     Diag(Loc, NoneDiag);
-    return 0;
+    return SpecEnd;
   }
   
-  if (NumSpecializations == 1) {
-    if (Index)
-      *Index = 0;
-    
-    return Specializations[0];
-  }
-    
+  if (SpecBegin + 1 == SpecEnd)    
+    return SpecBegin;
   
   // Find the function template that is better than all of the templates it
   // has been compared to.
-  unsigned Best = 0;
+  UnresolvedSetIterator Best = SpecBegin;
   FunctionTemplateDecl *BestTemplate 
-    = Specializations[Best]->getPrimaryTemplate();
+    = cast<FunctionDecl>(*Best)->getPrimaryTemplate();
   assert(BestTemplate && "Not a function template specialization?");
-  for (unsigned I = 1; I != NumSpecializations; ++I) {
-    FunctionTemplateDecl *Challenger = Specializations[I]->getPrimaryTemplate();
+  for (UnresolvedSetIterator I = SpecBegin + 1; I != SpecEnd; ++I) {
+    FunctionTemplateDecl *Challenger
+      = cast<FunctionDecl>(*I)->getPrimaryTemplate();
     assert(Challenger && "Not a function template specialization?");
-    if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, 
+    if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
                                                   TPOC),
                        Challenger)) {
       Best = I;
@@ -2060,8 +2056,9 @@
   // Make sure that the "best" function template is more specialized than all
   // of the others.
   bool Ambiguous = false;
-  for (unsigned I = 0; I != NumSpecializations; ++I) {
-    FunctionTemplateDecl *Challenger = Specializations[I]->getPrimaryTemplate();
+  for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) {
+    FunctionTemplateDecl *Challenger
+      = cast<FunctionDecl>(*I)->getPrimaryTemplate();
     if (I != Best &&
         !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, 
                                                   TPOC),
@@ -2073,22 +2070,20 @@
   
   if (!Ambiguous) {
     // We found an answer. Return it.
-    if (Index)
-      *Index = Best;
-    return Specializations[Best];
+    return Best;
   }
   
   // Diagnose the ambiguity.
   Diag(Loc, AmbigDiag);
   
   // FIXME: Can we order the candidates in some sane way?
-  for (unsigned I = 0; I != NumSpecializations; ++I)
-    Diag(Specializations[I]->getLocation(), CandidateDiag)
+  for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I)
+    Diag((*I)->getLocation(), CandidateDiag)
       << getTemplateArgumentBindingsText(
-            Specializations[I]->getPrimaryTemplate()->getTemplateParameters(),
-                         *Specializations[I]->getTemplateSpecializationArgs());
+        cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
+                    *cast<FunctionDecl>(*I)->getTemplateSpecializationArgs());
   
-  return 0;
+  return SpecEnd;
 }
 
 /// \brief Returns the more specialized class template partial specialization

Added: cfe/trunk/test/CXX/class.access/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/p4.cpp?rev=94647&view=auto

==============================================================================
--- cfe/trunk/test/CXX/class.access/p4.cpp (added)
+++ cfe/trunk/test/CXX/class.access/p4.cpp Tue Jan 26 19:50:18 2010
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fsyntax-only -faccess-control -verify %s
+
+// C++0x [class.access]p4:
+
+//   Access control is applied uniformly to all names, whether the
+//   names are referred to from declarations or expressions.  In the
+//   case of overloaded function names, access control is applied to
+//   the function selected by overload resolution.
+
+class Public {} PublicInst;
+class Protected {} ProtectedInst;
+class Private {} PrivateInst;
+
+namespace test0 {
+  class A {
+  public:
+    void foo(Public&);
+  protected:
+    void foo(Protected&); // expected-note 2 {{declared protected here}}
+  private:
+    void foo(Private&); // expected-note 2 {{declared private here}}
+  };
+
+  void test(A *op) {
+    op->foo(PublicInst);
+    op->foo(ProtectedInst); // expected-error {{access to protected member outside any class}}
+    op->foo(PrivateInst); // expected-error {{access to private member outside any class}}
+
+    void (A::*a)(Public&) = &A::foo;
+    void (A::*b)(Protected&) = &A::foo; // expected-error {{access to protected member outside any class}}
+    void (A::*c)(Private&) = &A::foo; // expected-error {{access to private member outside any class}}
+  }
+}





More information about the cfe-commits mailing list