Skip to content
SemaExpr.cpp 124 KiB
Newer Older
//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for expressions.
//
//===----------------------------------------------------------------------===//

#include "Sema.h"
#include "clang/AST/ASTContext.h"
Daniel Dunbar's avatar
Daniel Dunbar committed
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/Preprocessor.h"
Steve Naroff's avatar
Steve Naroff committed
#include "clang/Lex/LiteralSupport.h"
Daniel Dunbar's avatar
Daniel Dunbar committed
#include "clang/Basic/Diagnostic.h"
Steve Naroff's avatar
Steve Naroff committed
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
//===----------------------------------------------------------------------===//
//  Standard Promotions and Conversions
//===----------------------------------------------------------------------===//

/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
void Sema::DefaultFunctionArrayConversion(Expr *&E) {
  QualType Ty = E->getType();
  assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");

  if (const ReferenceType *ref = Ty->getAsReferenceType()) {
    ImpCastExprToType(E, ref->getPointeeType()); // C++ [expr]
    Ty = E->getType();
  }
  if (Ty->isFunctionType())
    ImpCastExprToType(E, Context.getPointerType(Ty));
  else if (Ty->isArrayType()) {
    // In C90 mode, arrays only promote to pointers if the array expression is
    // an lvalue.  The relevant legalese is C90 6.2.2.1p3: "an lvalue that has
    // type 'array of type' is converted to an expression that has type 'pointer
    // to type'...".  In C99 this was changed to: C99 6.3.2.1p3: "an expression
    // that has type 'array of type' ...".  The relevant change is "an lvalue"
    // (C90) to "an expression" (C99).
    //
    // C++ 4.2p1:
    // An lvalue or rvalue of type "array of N T" or "array of unknown bound of
    // T" can be converted to an rvalue of type "pointer to T".
    //
    if (getLangOptions().C99 || getLangOptions().CPlusPlus ||
        E->isLvalue(Context) == Expr::LV_Valid)
      ImpCastExprToType(E, Context.getArrayDecayedType(Ty));
  }
}

/// UsualUnaryConversions - Performs various conversions that are common to most
/// operators (C99 6.3). The conversions of array and function types are 
/// sometimes surpressed. For example, the array->pointer conversion doesn't
/// apply if the array is an argument to the sizeof or address (&) operators.
/// In these instances, this routine should *not* be called.
Expr *Sema::UsualUnaryConversions(Expr *&Expr) {
  QualType Ty = Expr->getType();
  assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
  
  if (const ReferenceType *Ref = Ty->getAsReferenceType()) {
    ImpCastExprToType(Expr, Ref->getPointeeType()); // C++ [expr]
    Ty = Expr->getType();
  }
  if (Ty->isPromotableIntegerType()) // C99 6.3.1.1p2
    ImpCastExprToType(Expr, Context.IntTy);
  else
    DefaultFunctionArrayConversion(Expr);
  
  return Expr;
}

Chris Lattner's avatar
Chris Lattner committed
/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
/// do not have a prototype. Arguments that have type float are promoted to 
/// double. All other argument types are converted by UsualUnaryConversions().
void Sema::DefaultArgumentPromotion(Expr *&Expr) {
  QualType Ty = Expr->getType();
  assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type");
  
  // If this is a 'float' (CVR qualified or typedef) promote to double.
  if (const BuiltinType *BT = Ty->getAsBuiltinType())
    if (BT->getKind() == BuiltinType::Float)
      return ImpCastExprToType(Expr, Context.DoubleTy);
  
  UsualUnaryConversions(Expr);
}

/// UsualArithmeticConversions - Performs various conversions that are common to
/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
/// routine returns the first non-arithmetic type found. The client is 
/// responsible for emitting appropriate error diagnostics.
/// FIXME: verify the conversion rules for "complex int" are consistent with
/// GCC.
QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
                                          bool isCompAssign) {
  if (!isCompAssign) {
    UsualUnaryConversions(lhsExpr);
    UsualUnaryConversions(rhsExpr);
  }
  // For conversion purposes, we ignore any qualifiers. 
  // For example, "const float" and "float" are equivalent.
  QualType lhs =
    Context.getCanonicalType(lhsExpr->getType()).getUnqualifiedType();
  QualType rhs = 
    Context.getCanonicalType(rhsExpr->getType()).getUnqualifiedType();
  
  // If both types are identical, no conversion is needed.
  if (lhs == rhs)
    return lhs;
  
  // If either side is a non-arithmetic type (e.g. a pointer), we are done.
  // The caller can deal with this (e.g. pointer + int).
  if (!lhs->isArithmeticType() || !rhs->isArithmeticType())
    return lhs;
    
  // At this point, we have two different arithmetic types. 
  
  // Handle complex types first (C99 6.3.1.8p1).
  if (lhs->isComplexType() || rhs->isComplexType()) {
    // if we have an integer operand, the result is the complex type.
    if (rhs->isIntegerType() || rhs->isComplexIntegerType()) { 
      // convert the rhs to the lhs complex type.
      if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
      return lhs;
    }
    if (lhs->isIntegerType() || lhs->isComplexIntegerType()) { 
      // convert the lhs to the rhs complex type.
      if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs);
      return rhs;
    }
    // This handles complex/complex, complex/float, or float/complex.
    // When both operands are complex, the shorter operand is converted to the 
    // type of the longer, and that is the type of the result. This corresponds 
    // to what is done when combining two real floating-point operands. 
    // The fun begins when size promotion occur across type domains. 
    // From H&S 6.3.4: When one operand is complex and the other is a real
    // floating-point type, the less precise type is converted, within it's 
    // real or complex domain, to the precision of the other type. For example,
    // when combining a "long double" with a "double _Complex", the 
    // "double _Complex" is promoted to "long double _Complex".
    int result = Context.getFloatingTypeOrder(lhs, rhs);
    
    if (result > 0) { // The left side is bigger, convert rhs. 
      rhs = Context.getFloatingTypeOfSizeWithinDomain(lhs, rhs);
      if (!isCompAssign)
        ImpCastExprToType(rhsExpr, rhs);
    } else if (result < 0) { // The right side is bigger, convert lhs. 
      lhs = Context.getFloatingTypeOfSizeWithinDomain(rhs, lhs);
      if (!isCompAssign)
        ImpCastExprToType(lhsExpr, lhs);
    } 
    // At this point, lhs and rhs have the same rank/size. Now, make sure the
    // domains match. This is a requirement for our implementation, C99
    // does not require this promotion.
    if (lhs != rhs) { // Domains don't match, we have complex/float mix.
      if (lhs->isRealFloatingType()) { // handle "double, _Complex double".
        if (!isCompAssign)
          ImpCastExprToType(lhsExpr, rhs);
        return rhs;
      } else { // handle "_Complex double, double".
        if (!isCompAssign)
          ImpCastExprToType(rhsExpr, lhs);
        return lhs;
      }
    }
    return lhs; // The domain/size match exactly.
  }
  // Now handle "real" floating types (i.e. float, double, long double).
  if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
    // if we have an integer operand, the result is the real floating type.
    if (rhs->isIntegerType() || rhs->isComplexIntegerType()) { 
      // convert rhs to the lhs floating point type.
      if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
      return lhs;
    }
    if (lhs->isIntegerType() || lhs->isComplexIntegerType()) { 
      // convert lhs to the rhs floating point type.
      if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs);
      return rhs;
    }
    // We have two real floating types, float/complex combos were handled above.
    // Convert the smaller operand to the bigger result.
    int result = Context.getFloatingTypeOrder(lhs, rhs);
    
    if (result > 0) { // convert the rhs
      if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
      return lhs;
    }
    if (result < 0) { // convert the lhs
      if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs); // convert the lhs
      return rhs;
    }
    assert(0 && "Sema::UsualArithmeticConversions(): illegal float comparison");
  }
  if (lhs->isComplexIntegerType() || rhs->isComplexIntegerType()) {
    // Handle GCC complex int extension.
    const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType();
    const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType();

    if (lhsComplexInt && rhsComplexInt) {
      if (Context.getIntegerTypeOrder(lhsComplexInt->getElementType(), 
                                      rhsComplexInt->getElementType()) >= 0) {
        // convert the rhs
        if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
        return lhs;
      }
      if (!isCompAssign) 
        ImpCastExprToType(lhsExpr, rhs); // convert the lhs
      return rhs;
    } else if (lhsComplexInt && rhs->isIntegerType()) {
      // convert the rhs to the lhs complex type.
      if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
      return lhs;
    } else if (rhsComplexInt && lhs->isIntegerType()) {
      // convert the lhs to the rhs complex type.
      if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs);
      return rhs;
    }
  }
  // Finally, we have two differing integer types.
  // The rules for this case are in C99 6.3.1.8
  int compare = Context.getIntegerTypeOrder(lhs, rhs);
  bool lhsSigned = lhs->isSignedIntegerType(),
       rhsSigned = rhs->isSignedIntegerType();
  QualType destType;
  if (lhsSigned == rhsSigned) {
    // Same signedness; use the higher-ranked type
    destType = compare >= 0 ? lhs : rhs;
  } else if (compare != (lhsSigned ? 1 : -1)) {
    // The unsigned type has greater than or equal rank to the
    // signed type, so use the unsigned type
    destType = lhsSigned ? rhs : lhs;
  } else if (Context.getIntWidth(lhs) != Context.getIntWidth(rhs)) {
    // The two types are different widths; if we are here, that
    // means the signed type is larger than the unsigned type, so
    // use the signed type.
    destType = lhsSigned ? lhs : rhs;
  } else {
    // The signed type is higher-ranked than the unsigned type,
    // but isn't actually any bigger (like unsigned int and long
    // on most 32-bit systems).  Use the unsigned type corresponding
    // to the signed type.
    destType = Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs);
  }
  if (!isCompAssign) {
    ImpCastExprToType(lhsExpr, destType);
    ImpCastExprToType(rhsExpr, destType);
  }
  return destType;
}

//===----------------------------------------------------------------------===//
//  Semantic Analysis for various Expression Types
//===----------------------------------------------------------------------===//


/// ActOnStringLiteral - The specified tokens were lexed as pasted string
/// fragments (e.g. "foo" "bar" L"baz").  The result string has to handle string
/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
/// multiple tokens.  However, the common case is that StringToks points to one
/// string.
/// 
Action::ExprResult
Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
  assert(NumStringToks && "Must have at least one string!");

Steve Naroff's avatar
Steve Naroff committed
  StringLiteralParser Literal(StringToks, NumStringToks, PP, Context.Target);
  if (Literal.hadError)
    return ExprResult(true);
  llvm::SmallVector<SourceLocation, 4> StringTokLocs;
  for (unsigned i = 0; i != NumStringToks; ++i)
    StringTokLocs.push_back(StringToks[i].getLocation());

  // Verify that pascal strings aren't too large.
  if (Literal.Pascal && Literal.GetStringLength() > 256)
    return Diag(StringToks[0].getLocation(), diag::err_pascal_string_too_long,
                SourceRange(StringToks[0].getLocation(),
                            StringToks[NumStringToks-1].getLocation()));
Steve Naroff's avatar
Steve Naroff committed
  
  QualType StrTy = Context.CharTy;
  if (Literal.AnyWide) StrTy = Context.getWCharType();
  if (Literal.Pascal) StrTy = Context.UnsignedCharTy;

  // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
  if (getLangOptions().CPlusPlus)
    StrTy.addConst();
  
  // Get an array type for the string, according to C99 6.4.5.  This includes
  // the nul terminator character as well as the string length for pascal
  // strings.
  StrTy = Context.getConstantArrayType(StrTy,
                                   llvm::APInt(32, Literal.GetStringLength()+1),
                                       ArrayType::Normal, 0);
  
  // Pass &StringTokLocs[0], StringTokLocs.size() to factory!
Steve Naroff's avatar
Steve Naroff committed
  return new StringLiteral(Literal.GetString(), Literal.GetStringLength(), 
                           StringToks[0].getLocation(),
Steve Naroff's avatar
Steve Naroff committed
                           StringToks[NumStringToks-1].getLocation());
/// DeclDefinedWithinScope - Return true if the specified decl is defined at or
/// within the 'Within' scope.  The current Scope is CurScope.
///
/// FIXME: This method is extremely inefficient (linear scan), this should not
/// be used in common cases. Replace with the more modern DeclContext. We need
/// to make sure both assignments below produce an error.
///
/// int main(int argc) {
///   int xx;
///   ^(int X) {
///     xx = 4; // error (variable is not assignable)
///     argc = 3; // no error.
///   };
/// }
///
static bool DeclDefinedWithinScope(ScopedDecl *D, Scope *Within,
                                   Scope *CurScope) {
  while (1) {
    assert(CurScope && "CurScope not nested within 'Within'?");

    // Check this scope for the decl.
    if (CurScope->isDeclScope(D)) return true;
    
    if (CurScope == Within) return false;
    CurScope = CurScope->getParent();
  }
}
Steve Naroff's avatar
 
Steve Naroff committed
/// ActOnIdentifierExpr - The parser read an identifier in expression context,
/// validate it per-C99 6.5.1.  HasTrailingLParen indicates whether this
Steve Naroff's avatar
Steve Naroff committed
/// identifier is used in a function call context.
Steve Naroff's avatar
 
Steve Naroff committed
Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
                                           IdentifierInfo &II,
                                           bool HasTrailingLParen) {
  // Could be enum-constant, value decl, instance variable, etc.
Steve Naroff's avatar
 
Steve Naroff committed
  Decl *D = LookupDecl(&II, Decl::IDNS_Ordinary, S);
  
  // If this reference is in an Objective-C method, then ivar lookup happens as
  // well.
    ScopedDecl *SD = dyn_cast_or_null<ScopedDecl>(D);
    // There are two cases to handle here.  1) scoped lookup could have failed,
    // in which case we should look for an ivar.  2) scoped lookup could have
    // found a decl, but that decl is outside the current method (i.e. a global
    // variable).  In these two cases, we do a lookup for an ivar with this
    // name, if the lookup suceeds, we replace it our current decl.
    if (SD == 0 || SD->isDefinedOutsideFunctionOrMethod()) {
      ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
      if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(&II)) {
        // FIXME: This should use a new expr for a direct reference, don't turn
        // this into Self->ivar, just return a BareIVarExpr or something.
        IdentifierInfo &II = Context.Idents.get("self");
        ExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false);
        return new ObjCIvarRefExpr(IV, IV->getType(), Loc, 
                                 static_cast<Expr*>(SelfExpr.Val), true, true);
      }
    }
    // Needed to implement property "super.method" notation.
    if (SD == 0 && &II == SuperID) {
      QualType T = Context.getPointerType(Context.getObjCInterfaceType(
                     getCurMethodDecl()->getClassInterface()));
      return new PredefinedExpr(Loc, T, PredefinedExpr::ObjCSuper);
  // If we are parsing a block, check the block parameter list.
  if (CurBlock) {
    BlockSemaInfo *BLK = CurBlock;
    do {
      for (unsigned i = 0, e = BLK->Params.size(); i != e && D == 0; ++i)
        if (BLK->Params[i]->getIdentifier() == &II)
          D = BLK->Params[i];
      if (D) 
        break; // Found!
    } while ((BLK = BLK->PrevBlockInfo));  // Look through any enclosing blocks.
    // Otherwise, this could be an implicitly declared function reference (legal
    if (HasTrailingLParen &&
        !getLangOptions().CPlusPlus) // Not in C++.
      D = ImplicitlyDefineFunction(Loc, II, S);
Steve Naroff's avatar
Steve Naroff committed
    else {
      // If this name wasn't predeclared and if this is not a function call,
      // diagnose the problem.
Steve Naroff's avatar
Steve Naroff committed
      return Diag(Loc, diag::err_undeclared_var_use, II.getName());
Steve Naroff's avatar
Steve Naroff committed
    }
  if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D)) {
    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
      if (MD->isStatic())
        // "invalid use of member 'x' in static member function"
        return Diag(Loc, diag::err_invalid_member_use_in_static_method,
                    FD->getName());
      if (cast<CXXRecordDecl>(MD->getParent()) != FD->getParent())
        // "invalid use of nonstatic data member 'x'"
        return Diag(Loc, diag::err_invalid_non_static_member_use,
                    FD->getName());

      if (FD->isInvalidDecl())
        return true;

      // FIXME: Use DeclRefExpr or a new Expr for a direct CXXField reference.
      ExprResult ThisExpr = ActOnCXXThis(SourceLocation());
      return new MemberExpr(static_cast<Expr*>(ThisExpr.Val),
                            true, FD, Loc, FD->getType());
    }

    return Diag(Loc, diag::err_invalid_non_static_member_use, FD->getName());
  }
Steve Naroff's avatar
Steve Naroff committed
  if (isa<TypedefDecl>(D))
Steve Naroff's avatar
Steve Naroff committed
    return Diag(Loc, diag::err_unexpected_typedef, II.getName());
    return Diag(Loc, diag::err_unexpected_interface, II.getName());
  if (isa<NamespaceDecl>(D))
    return Diag(Loc, diag::err_unexpected_namespace, II.getName());
Steve Naroff's avatar
Steve Naroff committed

  // Make the DeclRefExpr or BlockDeclRefExpr for the decl.
  ValueDecl *VD = cast<ValueDecl>(D);
  
  // check if referencing an identifier with __attribute__((deprecated)).
  if (VD->getAttr<DeprecatedAttr>())
    Diag(Loc, diag::warn_deprecated, VD->getName());

  // Only create DeclRefExpr's for valid Decl's.
  if (VD->isInvalidDecl())
    return true;
    
  // If this reference is not in a block or if the referenced variable is
  // within the block, create a normal DeclRefExpr.
  //
  // FIXME: This will create BlockDeclRefExprs for global variables,
  // function references, etc which is suboptimal :) and breaks
  // things like "integer constant expression" tests.
  //
  if (!CurBlock || DeclDefinedWithinScope(VD, CurBlock->TheScope, S) ||
      isa<EnumConstantDecl>(VD) || isa<ParmVarDecl>(VD))
    return new DeclRefExpr(VD, VD->getType(), Loc);
  
  // If we are in a block and the variable is outside the current block,
  // bind the variable reference with a BlockDeclRefExpr.
  
  // The BlocksAttr indicates the variable is bound by-reference.
  if (VD->getAttr<BlocksAttr>())
    return new BlockDeclRefExpr(VD, VD->getType(), Loc, true);
  // Variable will be bound by-copy, make it const within the closure.
  VD->getType().addConst();
  return new BlockDeclRefExpr(VD, VD->getType(), Loc, false);
Sema::ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
  PredefinedExpr::IdentType IT;
  default: assert(0 && "Unknown simple primary expr!");
  case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
  case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
  case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;

  // Verify that this is in a function context.
  if (getCurFunctionDecl() == 0 && getCurMethodDecl() == 0)
    return Diag(Loc, diag::err_predef_outside_function);
  // Pre-defined identifiers are of type char[x], where x is the length of the
  // string.
  unsigned Length;
  if (getCurFunctionDecl())
    Length = getCurFunctionDecl()->getIdentifier()->getLength();
    Length = getCurMethodDecl()->getSynthesizedMethodSize();
  llvm::APInt LengthI(32, Length + 1);
  QualType ResTy = Context.CharTy.getQualifiedType(QualType::Const);
  ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
  return new PredefinedExpr(Loc, ResTy, IT);
Sema::ExprResult Sema::ActOnCharacterConstant(const Token &Tok) {
Steve Naroff's avatar
Steve Naroff committed
  CharBuffer.resize(Tok.getLength());
  const char *ThisTokBegin = &CharBuffer[0];
  unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
  
  CharLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
                            Tok.getLocation(), PP);
  if (Literal.hadError())
    return ExprResult(true);

  QualType type = getLangOptions().CPlusPlus ? Context.CharTy : Context.IntTy;

  return new CharacterLiteral(Literal.getValue(), Literal.isWide(), type,
                              Tok.getLocation());
Steve Naroff's avatar
Steve Naroff committed
}

Action::ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
Steve Naroff's avatar
Steve Naroff committed
  // fast path for a single digit (which is quite common). A single digit 
  // cannot have a trigraph, escaped newline, radix prefix, or type suffix.
  if (Tok.getLength() == 1) {
    const char *Ty = PP.getSourceManager().getCharacterData(Tok.getLocation());
    unsigned IntSize =static_cast<unsigned>(Context.getTypeSize(Context.IntTy));
    return ExprResult(new IntegerLiteral(llvm::APInt(IntSize, *Ty-'0'),
Steve Naroff's avatar
Steve Naroff committed
                                         Tok.getLocation()));
Steve Naroff's avatar
Steve Naroff committed
  }
  llvm::SmallString<512> IntegerBuffer;
Steve Naroff's avatar
Steve Naroff committed
  IntegerBuffer.resize(Tok.getLength());
  const char *ThisTokBegin = &IntegerBuffer[0];
  
  // Get the spelling of the token, which eliminates trigraphs, etc.
Steve Naroff's avatar
Steve Naroff committed
  unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
Steve Naroff's avatar
Steve Naroff committed
  NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength, 
Steve Naroff's avatar
Steve Naroff committed
                               Tok.getLocation(), PP);
Steve Naroff's avatar
Steve Naroff committed
  if (Literal.hadError)
    return ExprResult(true);
  Expr *Res;
  
  if (Literal.isFloatingLiteral()) {
    if (Literal.isFloat)
    else if (!Literal.isLong)

    const llvm::fltSemantics &Format = Context.getFloatTypeSemantics(Ty);

    // isExact will be set by GetFloatValue().
    bool isExact = false;
    Res = new FloatingLiteral(Literal.GetFloatValue(Format, &isExact), &isExact,
  } else if (!Literal.isIntegerLiteral()) {
    return ExprResult(true);
  } else {
    // long long is a C99 feature.
    if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x &&
Neil Booth's avatar
Neil Booth committed
        Literal.isLongLong)
      Diag(Tok.getLocation(), diag::ext_longlong);

    // Get the value in the widest-possible width.
    llvm::APInt ResultVal(Context.Target.getIntMaxTWidth(), 0);
   
    if (Literal.GetIntegerValue(ResultVal)) {
      // If this value didn't fit into uintmax_t, warn and force to ull.
      Diag(Tok.getLocation(), diag::warn_integer_too_large);
      Ty = Context.UnsignedLongLongTy;
      assert(Context.getTypeSize(Ty) == ResultVal.getBitWidth() &&
Steve Naroff's avatar
Steve Naroff committed
    } else {
      // If this value fits into a ULL, try to figure out what else it fits into
      // according to the rules of C99 6.4.4.1p5.
      
      // Octal, Hexadecimal, and integers with a U suffix are allowed to
      // be an unsigned int.
      bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10;

      // Check from smallest to largest, picking the smallest type we can.
      if (!Literal.isLong && !Literal.isLongLong) {
        // Are int/unsigned possibilities?
        unsigned IntSize = Context.Target.getIntWidth();
        
        // Does it fit in a unsigned int?
        if (ResultVal.isIntN(IntSize)) {
          // Does it fit in a signed int?
          if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0)
            Ty = Context.UnsignedIntTy;
      if (Ty.isNull() && !Literal.isLongLong) {
        unsigned LongSize = Context.Target.getLongWidth();
     
        // Does it fit in a unsigned long?
        if (ResultVal.isIntN(LongSize)) {
          // Does it fit in a signed long?
          if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0)
            Ty = Context.LongTy;
            Ty = Context.UnsignedLongTy;
        unsigned LongLongSize = Context.Target.getLongLongWidth();
        
        // Does it fit in a unsigned long long?
        if (ResultVal.isIntN(LongLongSize)) {
          // Does it fit in a signed long long?
          if (!Literal.isUnsigned && ResultVal[LongLongSize-1] == 0)
            Ty = Context.LongLongTy;
            Ty = Context.UnsignedLongLongTy;
        }
      }
      
      // If we still couldn't decide a type, we probably have something that
      // does not fit in a signed long long, but has no U suffix.
        Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
        Ty = Context.UnsignedLongLongTy;
        Width = Context.Target.getLongLongWidth();
      
      if (ResultVal.getBitWidth() != Width)
        ResultVal.trunc(Width);
Steve Naroff's avatar
Steve Naroff committed
    }
    Res = new IntegerLiteral(ResultVal, Ty, Tok.getLocation());
Steve Naroff's avatar
Steve Naroff committed
  }
  
  // If this is an imaginary literal, create the ImaginaryLiteral wrapper.
  if (Literal.isImaginary)
    Res = new ImaginaryLiteral(Res, Context.getComplexType(Res->getType()));
  
  return Res;
Action::ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R,
  Expr *E = (Expr *)Val;
  assert((E != 0) && "ActOnParenExpr() missing expr");
  return new ParenExpr(L, R, E);
Steve Naroff's avatar
Steve Naroff committed
/// The UsualUnaryConversions() function is *not* called by this routine.
Steve Naroff's avatar
Steve Naroff committed
/// See C99 6.3.2.1p[2-4] for more details.
Steve Naroff's avatar
Steve Naroff committed
QualType Sema::CheckSizeOfAlignOfOperand(QualType exprType, 
                                         SourceLocation OpLoc,
                                         const SourceRange &ExprRange,
                                         bool isSizeof) {
Steve Naroff's avatar
Steve Naroff committed
  // C99 6.5.3.4p1:
  if (isa<FunctionType>(exprType) && isSizeof)
    // alignof(function) is allowed.
    Diag(OpLoc, diag::ext_sizeof_function_type, ExprRange);
Steve Naroff's avatar
Steve Naroff committed
  else if (exprType->isVoidType())
    Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof",
         ExprRange);
Steve Naroff's avatar
Steve Naroff committed
  else if (exprType->isIncompleteType()) {
    Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type : 
                           diag::err_alignof_incomplete_type,
Steve Naroff's avatar
Steve Naroff committed
    return QualType(); // error
  }
  // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
  return Context.getSizeType();
}

ActOnSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof, 
Steve Naroff's avatar
Steve Naroff committed
                           SourceLocation LPLoc, TypeTy *Ty,
                           SourceLocation RPLoc) {
  // If error parsing type, ignore.
  if (Ty == 0) return true;
  
  // Verify that this is a valid expression.
Steve Naroff's avatar
Steve Naroff committed
  QualType ArgTy = QualType::getFromOpaquePtr(Ty);
  QualType resultType =
    CheckSizeOfAlignOfOperand(ArgTy, OpLoc, SourceRange(LPLoc, RPLoc),isSizeof);
Steve Naroff's avatar
Steve Naroff committed

  if (resultType.isNull())
    return true;
Steve Naroff's avatar
Steve Naroff committed
  return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, resultType, OpLoc, RPLoc);
Chris Lattner's avatar
Chris Lattner committed
QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc) {
  DefaultFunctionArrayConversion(V);
  
  // These operators return the element type of a complex type.
  if (const ComplexType *CT = V->getType()->getAsComplexType())
    return CT->getElementType();
  
  // Otherwise they pass through real integer and floating point types here.
  if (V->getType()->isArithmeticType())
    return V->getType();
  
  // Reject anything else.
  Diag(Loc, diag::err_realimag_invalid_type, V->getType().getAsString());
  return QualType();
Action::ExprResult Sema::ActOnPostfixUnaryOp(SourceLocation OpLoc, 
                                             tok::TokenKind Kind,
                                             ExprTy *Input) {
  UnaryOperator::Opcode Opc;
  switch (Kind) {
  default: assert(0 && "Unknown unary op!");
  case tok::plusplus:   Opc = UnaryOperator::PostInc; break;
  case tok::minusminus: Opc = UnaryOperator::PostDec; break;
  }
Steve Naroff's avatar
Steve Naroff committed
  QualType result = CheckIncrementDecrementOperand((Expr *)Input, OpLoc);
Steve Naroff's avatar
Steve Naroff committed
  if (result.isNull())
    return true;
Steve Naroff's avatar
Steve Naroff committed
  return new UnaryOperator((Expr *)Input, Opc, result, OpLoc);
ActOnArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
  Expr *LHSExp = static_cast<Expr*>(Base), *RHSExp = static_cast<Expr*>(Idx);

  // Perform default conversions.
  DefaultFunctionArrayConversion(LHSExp);
  DefaultFunctionArrayConversion(RHSExp);
  QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
Steve Naroff's avatar
Steve Naroff committed

Steve Naroff's avatar
Steve Naroff committed
  // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
  // to the expression *((e1)+(e2)). This means the array "Base" may actually be
Steve Naroff's avatar
Steve Naroff committed
  // in the subscript position. As a result, we need to derive the array base 
  // and index from the expression types.
  Expr *BaseExpr, *IndexExpr;
  QualType ResultType;
  if (const PointerType *PTy = LHSTy->getAsPointerType()) {
    BaseExpr = LHSExp;
    IndexExpr = RHSExp;
    // FIXME: need to deal with const...
    ResultType = PTy->getPointeeType();
  } else if (const PointerType *PTy = RHSTy->getAsPointerType()) {
     // Handle the uncommon case of "123[Ptr]".
    BaseExpr = RHSExp;
    IndexExpr = LHSExp;
    // FIXME: need to deal with const...
    ResultType = PTy->getPointeeType();
  } else if (const VectorType *VTy = LHSTy->getAsVectorType()) {
    BaseExpr = LHSExp;    // vectors: V[123]
    
    // Component access limited to variables (reject vec4.rg[1]).
    if (!isa<DeclRefExpr>(BaseExpr) && !isa<ArraySubscriptExpr>(BaseExpr) &&
        !isa<ExtVectorElementExpr>(BaseExpr))
      return Diag(LLoc, diag::err_ext_vector_component_access, 
    // FIXME: need to deal with const...
    ResultType = VTy->getElementType();
Steve Naroff's avatar
Steve Naroff committed
  } else {
    return Diag(LHSExp->getLocStart(), diag::err_typecheck_subscript_value, 
                RHSExp->getSourceRange());
Steve Naroff's avatar
Steve Naroff committed
  }              
Steve Naroff's avatar
Steve Naroff committed
  // C99 6.5.2.1p1
  if (!IndexExpr->getType()->isIntegerType())
    return Diag(IndexExpr->getLocStart(), diag::err_typecheck_subscript,
                IndexExpr->getSourceRange());

  // C99 6.5.2.1p1: "shall have type "pointer to *object* type".  In practice,
  // the following check catches trying to index a pointer to a function (e.g.
  // void (*)(int)) and pointers to incomplete types.  Functions are not
  // objects in C99.
  if (!ResultType->isObjectType())
    return Diag(BaseExpr->getLocStart(), 
                diag::err_typecheck_subscript_not_object,
                BaseExpr->getType().getAsString(), BaseExpr->getSourceRange());
Steve Naroff's avatar
Steve Naroff committed

  return new ArraySubscriptExpr(LHSExp, RHSExp, ResultType, RLoc);
CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
                        IdentifierInfo &CompName, SourceLocation CompLoc) {
  const ExtVectorType *vecType = baseType->getAsExtVectorType();

  // This flag determines whether or not the component is to be treated as a 
  // special name, or a regular GLSL-style component access.
  bool SpecialComponent = false;
  
  // The vector accessor can't exceed the number of elements.
  const char *compStr = CompName.getName();
  if (strlen(compStr) > vecType->getNumElements()) {
    Diag(OpLoc, diag::err_ext_vector_component_exceeds_length, 
                baseType.getAsString(), SourceRange(CompLoc));
    return QualType();
  }

  // Check that we've found one of the special components, or that the component
  // names must come from the same set.
  if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") || 
      !strcmp(compStr, "e") || !strcmp(compStr, "o")) {
    SpecialComponent = true;
  } else if (vecType->getPointAccessorIdx(*compStr) != -1) {
    do
      compStr++;
    while (*compStr && vecType->getPointAccessorIdx(*compStr) != -1);
  } else if (vecType->getColorAccessorIdx(*compStr) != -1) {
    do
      compStr++;
    while (*compStr && vecType->getColorAccessorIdx(*compStr) != -1);
  } else if (vecType->getTextureAccessorIdx(*compStr) != -1) {
    do 
      compStr++;
    while (*compStr && vecType->getTextureAccessorIdx(*compStr) != -1);
  }
    // We didn't get to the end of the string. This means the component names
    // didn't come from the same set *or* we encountered an illegal name.
    Diag(OpLoc, diag::err_ext_vector_component_name_illegal, 
         std::string(compStr,compStr+1), SourceRange(CompLoc));
    return QualType();
  }
  // Each component accessor can't exceed the vector type.
  compStr = CompName.getName();
  while (*compStr) {
    if (vecType->isAccessorWithinNumElements(*compStr))
      compStr++;
    else
      break;
  }
    // We didn't get to the end of the string. This means a component accessor
    // exceeds the number of elements in the vector.
    Diag(OpLoc, diag::err_ext_vector_component_exceeds_length, 
                baseType.getAsString(), SourceRange(CompLoc));
    return QualType();
  }

  // If we have a special component name, verify that the current vector length
  // is an even number, since all special component names return exactly half
  // the elements.
  if (SpecialComponent && (vecType->getNumElements() & 1U)) {
    return QualType();
  }
  
  // The component accessor looks fine - now we need to compute the actual type.
  // The vector type is implied by the component accessor. For example, 
  // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.
  // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.
  unsigned CompSize = SpecialComponent ? vecType->getNumElements() / 2
                                       : strlen(CompName.getName());
  if (CompSize == 1)
    return vecType->getElementType();
Steve Naroff's avatar
 
Steve Naroff committed
    
  QualType VT = Context.getExtVectorType(vecType->getElementType(), CompSize);
Steve Naroff's avatar
 
Steve Naroff committed
  // Now look up the TypeDefDecl from the vector type. Without this, 
  // diagostics look bad. We want extended vector types to appear built-in.
  for (unsigned i = 0, E = ExtVectorDecls.size(); i != E; ++i) {
    if (ExtVectorDecls[i]->getUnderlyingType() == VT)
      return Context.getTypedefType(ExtVectorDecls[i]);
Steve Naroff's avatar
 
Steve Naroff committed
  }
  return VT; // should never get here (a typedef type should always be found).
/// constructSetterName - Return the setter name for the given
/// identifier, i.e. "set" + Name where the initial character of Name
/// has been capitalized.
// FIXME: Merge with same routine in Parser. But where should this
// live?
static IdentifierInfo *constructSetterName(IdentifierTable &Idents,
                                           const IdentifierInfo *Name) {
  unsigned N = Name->getLength();
  char *SelectorName = new char[3 + N];
  memcpy(SelectorName, "set", 3);
  memcpy(&SelectorName[3], Name->getName(), N);
  SelectorName[3] = toupper(SelectorName[3]);

  IdentifierInfo *Setter = 
    &Idents.get(SelectorName, &SelectorName[3 + N]);
  delete[] SelectorName;
  return Setter;
}

ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
                         tok::TokenKind OpKind, SourceLocation MemberLoc,
                         IdentifierInfo &Member) {
Steve Naroff's avatar
 
Steve Naroff committed
  Expr *BaseExpr = static_cast<Expr *>(Base);
  assert(BaseExpr && "no record expression");
Steve Naroff's avatar
 
Steve Naroff committed

  // Perform default conversions.
  DefaultFunctionArrayConversion(BaseExpr);
Steve Naroff's avatar
Steve Naroff committed
  
Steve Naroff's avatar
 
Steve Naroff committed
  QualType BaseType = BaseExpr->getType();
  assert(!BaseType.isNull() && "no type for member expression");
Steve Naroff's avatar
Steve Naroff committed
  
  // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr
  // must have pointer type, and the accessed type is the pointee.
Steve Naroff's avatar
Steve Naroff committed
  if (OpKind == tok::arrow) {
    if (const PointerType *PT = BaseType->getAsPointerType())
Steve Naroff's avatar
 
Steve Naroff committed
      BaseType = PT->getPointeeType();
    else
      return Diag(MemberLoc, diag::err_typecheck_member_reference_arrow,
                  BaseType.getAsString(), BaseExpr->getSourceRange());
Steve Naroff's avatar
Steve Naroff committed
  }
  // Handle field access to simple records.  This also handles access to fields
  // of the ObjC 'id' struct.
  if (const RecordType *RTy = BaseType->getAsRecordType()) {
Steve Naroff's avatar
 
Steve Naroff committed
    RecordDecl *RDecl = RTy->getDecl();
    if (RTy->isIncompleteType())
      return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RDecl->getName(),
                  BaseExpr->getSourceRange());
    // The record definition is complete, now make sure the member is valid.
    FieldDecl *MemberDecl = RDecl->getMember(&Member);
    if (!MemberDecl)
      return Diag(MemberLoc, diag::err_typecheck_no_member, Member.getName(),
                  BaseExpr->getSourceRange());

    // Figure out the type of the member; see C99 6.5.2.3p3
    // FIXME: Handle address space modifiers
    QualType MemberType = MemberDecl->getType();
    unsigned combinedQualifiers =
        MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
    MemberType = MemberType.getQualifiedType(combinedQualifiers);

    return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl,
  // Handle access to Objective-C instance variables, such as "Obj->ivar" and
  // (*Obj).ivar.
  if (const ObjCInterfaceType *IFTy = BaseType->getAsObjCInterfaceType()) {
    if (ObjCIvarDecl *IV = IFTy->getDecl()->lookupInstanceVariable(&Member))
      return new ObjCIvarRefExpr(IV, IV->getType(), MemberLoc, BaseExpr, 
                                 OpKind == tok::arrow);
    return Diag(MemberLoc, diag::err_typecheck_member_reference_ivar,
                IFTy->getDecl()->getName(), Member.getName(),
  // Handle Objective-C property access, which is "Obj.property" where Obj is a
  // pointer to a (potentially qualified) interface type.
  const PointerType *PTy;
  const ObjCInterfaceType *IFTy;
  if (OpKind == tok::period && (PTy = BaseType->getAsPointerType()) &&
      (IFTy = PTy->getPointeeType()->getAsObjCInterfaceType())) {
    ObjCInterfaceDecl *IFace = IFTy->getDecl();
    // Search for a declared property first.
    if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(&Member))
      return new ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr);
    
    // Check protocols on qualified interfaces.
    for (ObjCInterfaceType::qual_iterator I = IFTy->qual_begin(),
         E = IFTy->qual_end(); I != E; ++I)
      if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member))
        return new ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr);

    // If that failed, look for an "implicit" property by seeing if the nullary
    // selector is implemented.

    // FIXME: The logic for looking up nullary and unary selectors should be
    // shared with the code in ActOnInstanceMessage.

    Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
    ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
    
    // If this reference is in an @implementation, check for 'private' methods.
    if (!Getter)
      if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
        if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
          if (ObjCImplementationDecl *ImpDecl = 
              ObjCImplementations[ClassDecl->getIdentifier()])
            Getter = ImpDecl->getInstanceMethod(Sel);

    if (Getter) {
      // If we found a getter then this may be a valid dot-reference, we
      // need to also look for the matching setter.
      IdentifierInfo *SetterName = constructSetterName(PP.getIdentifierTable(),
                                                       &Member);
      Selector SetterSel = PP.getSelectorTable().getUnarySelector(SetterName);
      ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);

      if (!Setter) {
        if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
          if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
            if (ObjCImplementationDecl *ImpDecl = 
                ObjCImplementations[ClassDecl->getIdentifier()])
              Setter = ImpDecl->getInstanceMethod(SetterSel);
      }

      // FIXME: There are some issues here. First, we are not
      // diagnosing accesses to read-only properties because we do not