//===--- SemaFixItUtils.cpp - Sema FixIts ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines helper classes for generation of Sema FixItHints.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTContext.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaFixItUtils.h"

using namespace clang;

bool ConversionFixItGenerator::compareTypesSimple(CanQualType From,
                                                  CanQualType To,
                                                  Sema &S,
                                                  SourceLocation Loc,
                                                  ExprValueKind FromVK) {
  if (!To.isAtLeastAsQualifiedAs(From))
    return false;

  From = From.getNonReferenceType();
  To = To.getNonReferenceType();

  // If both are pointer types, work with the pointee types.
  if (isa<PointerType>(From) && isa<PointerType>(To)) {
    From = S.Context.getCanonicalType(
        (cast<PointerType>(From))->getPointeeType());
    To = S.Context.getCanonicalType(
        (cast<PointerType>(To))->getPointeeType());
  }

  const CanQualType FromUnq = From.getUnqualifiedType();
  const CanQualType ToUnq = To.getUnqualifiedType();

  if ((FromUnq == ToUnq || (S.IsDerivedFrom(FromUnq, ToUnq)) ) &&
      To.isAtLeastAsQualifiedAs(From))
    return true;
  return false;
}

bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr,
                                                  const QualType FromTy,
                                                  const QualType ToTy,
                                                  Sema &S) {
  if (!FullExpr)
    return false;

  const CanQualType FromQTy = S.Context.getCanonicalType(FromTy);
  const CanQualType ToQTy = S.Context.getCanonicalType(ToTy);
  const SourceLocation Begin = FullExpr->getSourceRange().getBegin();
  const SourceLocation End = S.PP.getLocForEndOfToken(FullExpr->getSourceRange()
                                                      .getEnd());

  // Strip the implicit casts - those are implied by the compiler, not the
  // original source code.
  const Expr* Expr = FullExpr->IgnoreImpCasts();

  bool NeedParen = true;
  if (isa<ArraySubscriptExpr>(Expr) ||
      isa<CallExpr>(Expr) ||
      isa<DeclRefExpr>(Expr) ||
      isa<CastExpr>(Expr) ||
      isa<CXXNewExpr>(Expr) ||
      isa<CXXConstructExpr>(Expr) ||
      isa<CXXDeleteExpr>(Expr) ||
      isa<CXXNoexceptExpr>(Expr) ||
      isa<CXXPseudoDestructorExpr>(Expr) ||
      isa<CXXScalarValueInitExpr>(Expr) ||
      isa<CXXThisExpr>(Expr) ||
      isa<CXXTypeidExpr>(Expr) ||
      isa<CXXUnresolvedConstructExpr>(Expr) ||
      isa<ObjCMessageExpr>(Expr) ||
      isa<ObjCPropertyRefExpr>(Expr) ||
      isa<ObjCProtocolExpr>(Expr) ||
      isa<MemberExpr>(Expr) ||
      isa<ParenExpr>(FullExpr) ||
      isa<ParenListExpr>(Expr) ||
      isa<SizeOfPackExpr>(Expr) ||
      isa<UnaryOperator>(Expr))
    NeedParen = false;

  // Check if the argument needs to be dereferenced:
  //   (type * -> type) or (type * -> type &).
  if (const PointerType *FromPtrTy = dyn_cast<PointerType>(FromQTy)) {
    OverloadFixItKind FixKind = OFIK_Dereference;

    bool CanConvert = CompareTypes(
      S.Context.getCanonicalType(FromPtrTy->getPointeeType()), ToQTy,
                                 S, Begin, VK_LValue);
    if (CanConvert) {
      // Do not suggest dereferencing a Null pointer.
      if (Expr->IgnoreParenCasts()->
          isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull))
        return false;

      if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) {
        if (UO->getOpcode() == UO_AddrOf) {
          FixKind = OFIK_RemoveTakeAddress;
          Hints.push_back(FixItHint::CreateRemoval(
                            CharSourceRange::getTokenRange(Begin, Begin)));
        }
      } else if (NeedParen) {
        Hints.push_back(FixItHint::CreateInsertion(Begin, "*("));
        Hints.push_back(FixItHint::CreateInsertion(End, ")"));
      } else {
        Hints.push_back(FixItHint::CreateInsertion(Begin, "*"));
      }

      NumConversionsFixed++;
      if (NumConversionsFixed == 1)
        Kind = FixKind;
      return true;
    }
  }

  // Check if the pointer to the argument needs to be passed:
  //   (type -> type *) or (type & -> type *).
  if (isa<PointerType>(ToQTy)) {
    bool CanConvert = false;
    OverloadFixItKind FixKind = OFIK_TakeAddress;

    // Only suggest taking address of L-values.
    if (!Expr->isLValue() || Expr->getObjectKind() != OK_Ordinary)
      return false;

    CanConvert = CompareTypes(S.Context.getPointerType(FromQTy), ToQTy,
                              S, Begin, VK_RValue);
    if (CanConvert) {

      if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) {
        if (UO->getOpcode() == UO_Deref) {
          FixKind = OFIK_RemoveDereference;
          Hints.push_back(FixItHint::CreateRemoval(
                            CharSourceRange::getTokenRange(Begin, Begin)));
        }
      } else if (NeedParen) {
        Hints.push_back(FixItHint::CreateInsertion(Begin, "&("));
        Hints.push_back(FixItHint::CreateInsertion(End, ")"));
      } else {
        Hints.push_back(FixItHint::CreateInsertion(Begin, "&"));
      }

      NumConversionsFixed++;
      if (NumConversionsFixed == 1)
        Kind = FixKind;
      return true;
    }
  }

  return false;
}

static bool isMacroDefined(const Sema &S, StringRef Name) {
  return S.PP.getMacroInfo(&S.getASTContext().Idents.get(Name));
}

static std::string getScalarZeroExpressionForType(const Type& T, const Sema& S) {
  assert(T.isScalarType() && "use scalar types only");
  // Suggest "0" for non-enumeration scalar types, unless we can find a
  // better initializer.
  if (T.isEnumeralType())
    return std::string();
  if ((T.isObjCObjectPointerType() || T.isBlockPointerType()) &&
      isMacroDefined(S, "nil"))
    return "nil";
  if (T.isRealFloatingType())
    return "0.0";
  if (T.isBooleanType() && S.LangOpts.CPlusPlus)
    return "false";
  if (T.isPointerType() || T.isMemberPointerType()) {
    if (S.LangOpts.CPlusPlus0x)
      return "nullptr";
    if (isMacroDefined(S, "NULL"))
      return "NULL";
  }
  if (T.isCharType())
    return "'\\0'";
  if (T.isWideCharType())
    return "L'\\0'";
  if (T.isChar16Type())
    return "u'\\0'";
  if (T.isChar32Type())
    return "U'\\0'";
  return "0";
}

std::string Sema::getFixItZeroInitializerForType(QualType T) const {
  if (T->isScalarType()) {
    std::string s = getScalarZeroExpressionForType(*T, *this);
    if (!s.empty())
      s = " = " + s;
    return s;
  }

  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
  if (!RD || !RD->hasDefinition())
    return std::string();
  if (LangOpts.CPlusPlus0x && !RD->hasUserProvidedDefaultConstructor())
    return "{}";
  if (RD->isAggregate())
    return " = {}";
  return std::string();
}

std::string Sema::getFixItZeroLiteralForType(QualType T) const {
  return getScalarZeroExpressionForType(*T, *this);
}
