//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides Sema routines for C++ access control semantics.
//
//===----------------------------------------------------------------------===//

#include "Sema.h"
#include "Lookup.h"
#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.
/// Returns true on error (when the previous member decl access specifier
/// is different from the new member decl access specifier).
bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
                                    NamedDecl *PrevMemberDecl,
                                    AccessSpecifier LexicalAS) {
  if (!PrevMemberDecl) {
    // Use the lexical access specifier.
    MemberDecl->setAccess(LexicalAS);
    return false;
  }

  // C++ [class.access.spec]p3: When a member is redeclared its access
  // specifier must be same as its initial declaration.
  if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
    Diag(MemberDecl->getLocation(),
         diag::err_class_redeclared_with_different_access)
      << MemberDecl << LexicalAS;
    Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
      << PrevMemberDecl << PrevMemberDecl->getAccess();

    MemberDecl->setAccess(LexicalAS);
    return true;
  }

  MemberDecl->setAccess(PrevMemberDecl->getAccess());
  return false;
}

/// Find a class on the derivation path between Derived and Base that is
/// inaccessible. If @p NoPrivileges is true, special access rights (members
/// and friends) are not considered.
const CXXBaseSpecifier *Sema::FindInaccessibleBase(
    QualType Derived, QualType Base, CXXBasePaths &Paths, bool NoPrivileges) {
  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 *InaccessibleBase = 0;

  const CXXRecordDecl *CurrentClassDecl = 0;
  if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(getCurFunctionDecl()))
    CurrentClassDecl = MD->getParent();

  for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathsEnd = Paths.end();
      Path != PathsEnd; ++Path) {

    bool FoundInaccessibleBase = false;

    for (CXXBasePath::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/class is a friend.
        if (NoPrivileges || CurrentClassDecl != Element->Class)
          FoundInaccessibleBase = true;
        break;
      case AS_protected:
        // FIXME: Implement
        break;
      }

      if (FoundInaccessibleBase) {
        InaccessibleBase = Base;
        break;
      }
    }

    if (!FoundInaccessibleBase) {
      // We found a path to the base, our work here is done.
      return 0;
    }
  }

  assert(InaccessibleBase && "no path found, but no inaccessible base");
  return InaccessibleBase;
}

/// CheckBaseClassAccess - Check that a derived class can access its base class
/// and report an error if it can't. [class.access.base]
bool Sema::CheckBaseClassAccess(QualType Derived, QualType Base,
                                unsigned InaccessibleBaseID,
                                CXXBasePaths &Paths, SourceLocation AccessLoc,
                                DeclarationName Name) {

  if (!getLangOptions().AccessControl)
    return false;
  const CXXBaseSpecifier *InaccessibleBase = FindInaccessibleBase(
                                               Derived, Base, Paths);

  if (InaccessibleBase) {
    Diag(AccessLoc, InaccessibleBaseID)
      << Derived << Base << Name;

    AccessSpecifier AS = InaccessibleBase->getAccessSpecifierAsWritten();

    // If there's no written access specifier, then the inheritance specifier
    // is implicitly private.
    if (AS == AS_none)
      Diag(InaccessibleBase->getSourceRange().getBegin(),
           diag::note_inheritance_implicitly_private_here);
    else
      Diag(InaccessibleBase->getSourceRange().getBegin(),
           diag::note_inheritance_specifier_here) << AS;

    return true;
  }

  return false;
}

/// Diagnose the path which caused the given declaration to become
/// inaccessible.
static void DiagnoseAccessPath(Sema &S, const LookupResult &R, NamedDecl *D,
                               AccessSpecifier Access) {
  // Easy case: the decl's natural access determined its path access.
  if (Access == D->getAccess() || D->getAccess() == AS_private) {
    S.Diag(D->getLocation(), diag::note_access_natural)
      << (unsigned) (Access == AS_protected);
    return;
  }

  // TODO: flesh this out
  S.Diag(D->getLocation(), diag::note_access_constrained_by_path)
    << (unsigned) (Access == AS_protected);
}

/// Checks access to the given declaration in the current context.
///
/// \param R the means via which the access was made; must have a naming
///   class set
/// \param D the declaration accessed
/// \param Access the best access along any inheritance path from the
///   naming class to the declaration.  AS_none means the path is impossible
bool Sema::CheckAccess(const LookupResult &R, NamedDecl *D,
                       AccessSpecifier Access) {
  assert(R.getNamingClass() && "performing access check without naming class");

  // If the access path is public, it's accessible everywhere.
  if (Access == AS_public)
    return false;

  // If we're currently parsing a top-level declaration, delay
  // diagnostics.  This is the only case where parsing a declaration
  // can actually change our effective context for the purposes of
  // access control.
  if (CurContext->isFileContext() && ParsingDeclDepth) {
    DelayedDiagnostics.push_back(
        DelayedDiagnostic::makeAccess(R.getNameLoc(), D, Access,
                                      R.getNamingClass()));
    return false;
  }

  return CheckEffectiveAccess(CurContext, R, D, Access);
}

/// Checks access from the given effective context.
bool Sema::CheckEffectiveAccess(DeclContext *EffectiveContext,
                                const LookupResult &R,
                                NamedDecl *D, AccessSpecifier Access) {
  DeclContext *DC = EffectiveContext;
  while (isa<CXXRecordDecl>(DC) &&
         cast<CXXRecordDecl>(DC)->isAnonymousStructOrUnion())
    DC = DC->getParent();

  CXXRecordDecl *CurRecord;
  if (isa<CXXRecordDecl>(DC))
    CurRecord = cast<CXXRecordDecl>(DC);
  else if (isa<CXXMethodDecl>(DC))
    CurRecord = cast<CXXMethodDecl>(DC)->getParent();
  else {
    Diag(R.getNameLoc(), diag::err_access_outside_class)
      << (Access == AS_protected);
    DiagnoseAccessPath(*this, R, D, Access);
    return true;
  }

  CXXRecordDecl *NamingClass = R.getNamingClass();
  while (NamingClass->isAnonymousStructOrUnion())
    // This should be guaranteed by the fact that the decl has
    // non-public access.  If not, we should make it guaranteed!
    NamingClass = cast<CXXRecordDecl>(NamingClass);

  // White-list accesses from within the declaring class.
  if (Access != AS_none &&
      CurRecord->getCanonicalDecl() == NamingClass->getCanonicalDecl())
    return false;

  // Protected access.
  if (Access == AS_protected) {
    // FIXME: implement [class.protected]p1
    if (CurRecord->isDerivedFrom(NamingClass))
      return false;

    // FIXME: dependent classes
  }

  // FIXME: friends

  // Okay, it's a bad access, reject it.

  
  CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(D->getDeclContext());

  if (Access == AS_protected) {
    Diag(R.getNameLoc(), diag::err_access_protected)
      << Context.getTypeDeclType(DeclaringClass)
      << Context.getTypeDeclType(CurRecord);
    DiagnoseAccessPath(*this, R, D, Access);
    return true;
  }

  assert(Access == AS_private || Access == AS_none);
  Diag(R.getNameLoc(), diag::err_access_private)
    << Context.getTypeDeclType(DeclaringClass)
    << Context.getTypeDeclType(CurRecord);
  DiagnoseAccessPath(*this, R, D, Access);
  return true;
}

void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) {
  NamedDecl *D = DD.AccessData.Decl;

  // Fake up a lookup result.
  LookupResult R(*this, D->getDeclName(), DD.Loc, LookupOrdinaryName);
  R.suppressDiagnostics();
  R.setNamingClass(DD.AccessData.NamingClass);

  // Pretend we did this from the context of the newly-parsed
  // declaration.
  DeclContext *EffectiveContext = Ctx->getDeclContext();

  if (CheckEffectiveAccess(EffectiveContext, R, D, DD.AccessData.Access))
    DD.Triggered = 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;
}

bool Sema::CheckDestructorAccess(SourceLocation Loc, const RecordType *RT) {
  if (!getLangOptions().AccessControl)
    return false;

  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
  CXXDestructorDecl *Dtor = NamingClass->getDestructor(Context);

  AccessSpecifier Access = Dtor->getAccess();
  if (Access == AS_public)
    return false;

  LookupResult R(*this, Dtor->getDeclName(), Loc, LookupOrdinaryName);
  R.suppressDiagnostics();

  R.setNamingClass(NamingClass);
  return CheckAccess(R, Dtor, Access);

  // FIXME: protected check
}

/// Checks access to a constructor.
bool Sema::CheckConstructorAccess(SourceLocation UseLoc,
                                  CXXConstructorDecl *Constructor,
                                  AccessSpecifier Access) {
  if (!getLangOptions().AccessControl)
    return false;

  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Constructor->getParent());

  LookupResult R(*this, Constructor->getDeclName(), UseLoc, LookupOrdinaryName);
  R.suppressDiagnostics();

  R.setNamingClass(NamingClass);
  return CheckAccess(R, Constructor, Access);
}

/// Checks access to an overloaded member operator, including
/// conversion operators.
bool Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
                                     Expr *ObjectExpr,
                                     NamedDecl *MemberOperator,
                                     AccessSpecifier Access) {
  if (!getLangOptions().AccessControl)
    return false;

  const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>();
  assert(RT && "found member operator but object expr not of record type");
  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());

  LookupResult R(*this, DeclarationName(), OpLoc, LookupOrdinaryName);
  R.suppressDiagnostics();

  R.setNamingClass(NamingClass);
  if (CheckAccess(R, MemberOperator, 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)
    CheckAccess(R, *I, I.getAccess());
}
