Esempio n. 1
0
/// CheckAllocatedType - Checks that a type is suitable as the allocated type
/// in a new-expression.
/// dimension off and stores the size expression in ArraySize.
bool Sema::CheckAllocatedType(QualType AllocType, const Declarator &D)
{
  // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an
  //   abstract class type or array thereof.
  if (AllocType->isFunctionType())
    return Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type)
      << AllocType << 0 << D.getSourceRange();
  else if (AllocType->isReferenceType())
    return Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type)
      << AllocType << 1 << D.getSourceRange();
  else if (!AllocType->isDependentType() &&
           RequireCompleteType(D.getSourceRange().getBegin(), AllocType,
                               diag::err_new_incomplete_type,
                               D.getSourceRange()))
    return true;
  else if (RequireNonAbstractType(D.getSourceRange().getBegin(), AllocType,
                                  diag::err_allocation_of_abstract_type))
    return true;

  // Every dimension shall be of constant size.
  unsigned i = 1;
  while (const ArrayType *Array = Context.getAsArrayType(AllocType)) {
    if (!Array->isConstantArrayType()) {
      Diag(D.getTypeObject(i).Loc, diag::err_new_array_nonconst)
        << static_cast<Expr*>(D.getTypeObject(i).Arr.NumElts)->getSourceRange();
      return true;
    }
    AllocType = Array->getElementType();
    ++i;
  }

  return false;
}
Esempio n. 2
0
long long clang_Type_getSizeOf(CXType T) {
  if (T.kind == CXType_Invalid)
    return CXTypeLayoutError_Invalid;
  ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext();
  QualType QT = GetQualType(T);
  // [expr.sizeof] p2: if reference type, return size of referenced type
  if (QT->isReferenceType())
    QT = QT.getNonReferenceType();
  // [expr.sizeof] p1: return -1 on: func, incomplete, bitfield, incomplete
  //                   enumeration
  // Note: We get the cxtype, not the cxcursor, so we can't call
  //       FieldDecl->isBitField()
  // [expr.sizeof] p3: pointer ok, function not ok.
  // [gcc extension] lib/AST/ExprConstant.cpp:1372 HandleSizeof : vla == error
  if (QT->isIncompleteType())
    return CXTypeLayoutError_Incomplete;
  if (QT->isDependentType())
    return CXTypeLayoutError_Dependent;
  if (!QT->isConstantSizeType())
    return CXTypeLayoutError_NotConstantSize;
  // [gcc extension] lib/AST/ExprConstant.cpp:1372
  //                 HandleSizeof : {voidtype,functype} == 1
  // not handled by ASTContext.cpp:1313 getTypeInfoImpl
  if (QT->isVoidType() || QT->isFunctionType())
    return 1;
  return Ctx.getTypeSizeInChars(QT).getQuantity();
}
Esempio n. 3
0
/// \brief Build a function type.
///
/// This routine checks the function type according to C++ rules and
/// under the assumption that the result type and parameter types have
/// just been instantiated from a template. It therefore duplicates
/// some of the behavior of GetTypeForDeclarator, but in a much
/// simpler form that is only suitable for this narrow use case.
///
/// \param T The return type of the function.
///
/// \param ParamTypes The parameter types of the function. This array
/// will be modified to account for adjustments to the types of the
/// function parameters.
///
/// \param NumParamTypes The number of parameter types in ParamTypes.
///
/// \param Variadic Whether this is a variadic function type.
///
/// \param Quals The cvr-qualifiers to be applied to the function type.
///
/// \param Loc The location of the entity whose type involves this
/// function type or, if there is no such entity, the location of the
/// type that will have function type.
///
/// \param Entity The name of the entity that involves the function
/// type, if known.
///
/// \returns A suitable function type, if there are no
/// errors. Otherwise, returns a NULL type.
QualType Sema::BuildFunctionType(QualType T,
                                 QualType *ParamTypes, 
                                 unsigned NumParamTypes,
                                 bool Variadic, unsigned Quals,
                                 SourceLocation Loc, DeclarationName Entity) {
  if (T->isArrayType() || T->isFunctionType()) {
    Diag(Loc, diag::err_func_returning_array_function) << T;
    return QualType();
  }
  
  bool Invalid = false;
  for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) {
    QualType ParamType = adjustParameterType(ParamTypes[Idx]);
    if (ParamType->isVoidType()) {
      Diag(Loc, diag::err_param_with_void_type);
      Invalid = true;
    }

    ParamTypes[Idx] = ParamType;
  }

  if (Invalid)
    return QualType();

  return Context.getFunctionType(T, ParamTypes, NumParamTypes, Variadic, 
                                 Quals);
}
Esempio n. 4
0
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
                                           SourceLocation TemplateKWLoc,
                                           UnqualifiedId &Id,
                                           llvm::InlineAsmIdentifierInfo &Info,
                                           bool IsUnevaluatedContext) {
  Info.clear();

  if (IsUnevaluatedContext)
    PushExpressionEvaluationContext(UnevaluatedAbstract,
                                    ReuseLambdaContextDecl);

  ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
                                        /*trailing lparen*/ false,
                                        /*is & operand*/ false,
                                        /*CorrectionCandidateCallback=*/nullptr,
                                        /*IsInlineAsmIdentifier=*/ true);

  if (IsUnevaluatedContext)
    PopExpressionEvaluationContext();

  if (!Result.isUsable()) return Result;

  Result = CheckPlaceholderExpr(Result.get());
  if (!Result.isUsable()) return Result;

  QualType T = Result.get()->getType();

  // For now, reject dependent types.
  if (T->isDependentType()) {
    Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T;
    return ExprError();
  }

  // Any sort of function type is fine.
  if (T->isFunctionType()) {
    return Result;
  }

  // Otherwise, it needs to be a complete type.
  if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) {
    return ExprError();
  }

  // Compute the type size (and array length if applicable?).
  Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
  if (T->isArrayType()) {
    const ArrayType *ATy = Context.getAsArrayType(T);
    Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
    Info.Length = Info.Size / Info.Type;
  }

  // We can work with the expression as long as it's not an r-value.
  if (!Result.get()->isRValue())
    Info.IsVarDecl = true;

  return Result;
}
Esempio n. 5
0
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
                                           SourceLocation TemplateKWLoc,
                                           UnqualifiedId &Id,
                                           llvm::InlineAsmIdentifierInfo &Info,
                                           bool IsUnevaluatedContext) {
  Info.clear();

  if (IsUnevaluatedContext)
    PushExpressionEvaluationContext(UnevaluatedAbstract,
                                    ReuseLambdaContextDecl);

  ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
                                        /*trailing lparen*/ false,
                                        /*is & operand*/ false,
                                        /*CorrectionCandidateCallback=*/nullptr,
                                        /*IsInlineAsmIdentifier=*/ true);

  if (IsUnevaluatedContext)
    PopExpressionEvaluationContext();

  if (!Result.isUsable()) return Result;

  Result = CheckPlaceholderExpr(Result.get());
  if (!Result.isUsable()) return Result;

  // Referring to parameters is not allowed in naked functions.
  if (CheckNakedParmReference(Result.get(), *this))
    return ExprError();

  QualType T = Result.get()->getType();

  // For now, reject dependent types.
  if (T->isDependentType()) {
    Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T;
    return ExprError();
  }

  // Any sort of function type is fine.
  if (T->isFunctionType()) {
    return Result;
  }

  // Otherwise, it needs to be a complete type.
  if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) {
    return ExprError();
  }

  fillInlineAsmTypeInfo(Context, T, Info);

  // We can work with the expression as long as it's not an r-value.
  if (!Result.get()->isRValue())
    Info.IsVarDecl = true;

  return Result;
}
Esempio n. 6
0
/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
/// C++ if/switch/while/for statement.
/// e.g: "if (int x = f()) {...}"
Action::OwningExprResult
Sema::ActOnCXXConditionDeclarationExpr(Scope *S, SourceLocation StartLoc,
                                       Declarator &D,
                                       SourceLocation EqualLoc,
                                       ExprArg AssignExprVal) {
  assert(AssignExprVal.get() && "Null assignment expression");

  // C++ 6.4p2:
  // The declarator shall not specify a function or an array.
  // The type-specifier-seq shall not contain typedef and shall not declare a
  // new class or enumeration.

  assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
         "Parser allowed 'typedef' as storage class of condition decl.");

  QualType Ty = GetTypeForDeclarator(D, S);
  
  if (Ty->isFunctionType()) { // The declarator shall not specify a function...
    // We exit without creating a CXXConditionDeclExpr because a FunctionDecl
    // would be created and CXXConditionDeclExpr wants a VarDecl.
    return ExprError(Diag(StartLoc, diag::err_invalid_use_of_function_type)
      << SourceRange(StartLoc, EqualLoc));
  } else if (Ty->isArrayType()) { // ...or an array.
    Diag(StartLoc, diag::err_invalid_use_of_array_type)
      << SourceRange(StartLoc, EqualLoc);
  } else if (const RecordType *RT = Ty->getAsRecordType()) {
    RecordDecl *RD = RT->getDecl();
    // The type-specifier-seq shall not declare a new class...
    if (RD->isDefinition() &&
        (RD->getIdentifier() == 0 || S->isDeclScope(DeclPtrTy::make(RD))))
      Diag(RD->getLocation(), diag::err_type_defined_in_condition);
  } else if (const EnumType *ET = Ty->getAsEnumType()) {
    EnumDecl *ED = ET->getDecl();
    // ...or enumeration.
    if (ED->isDefinition() &&
        (ED->getIdentifier() == 0 || S->isDeclScope(DeclPtrTy::make(ED))))
      Diag(ED->getLocation(), diag::err_type_defined_in_condition);
  }

  DeclPtrTy Dcl = ActOnDeclarator(S, D, DeclPtrTy());
  if (!Dcl)
    return ExprError();
  AddInitializerToDecl(Dcl, move(AssignExprVal));

  // Mark this variable as one that is declared within a conditional.
  // We know that the decl had to be a VarDecl because that is the only type of
  // decl that can be assigned and the grammar requires an '='.
  VarDecl *VD = cast<VarDecl>(Dcl.getAs<Decl>());
  VD->setDeclaredInCondition(true);
  return Owned(new (Context) CXXConditionDeclExpr(StartLoc, EqualLoc, VD));
}
Esempio n. 7
0
// <type> ::= <pointer-type>
// <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
void MicrosoftCXXNameMangler::mangleType(const PointerType *T) {
  QualType PointeeTy = T->getPointeeType();
  if (PointeeTy->isArrayType()) {
    // Pointers to arrays are mangled like arrays.
    mangleExtraDimensions(T->getPointeeType());
  } else if (PointeeTy->isFunctionType()) {
    // Function pointers are special.
    Out << '6';
    mangleType(static_cast<const FunctionType *>(PointeeTy.getTypePtr()),
               NULL, false, false);
  } else {
    if (!PointeeTy.hasQualifiers())
      // Lack of qualifiers is mangled as 'A'.
      Out << 'A';
    mangleType(PointeeTy);
  }
}
  // We need to artificially create:
  // cling_PrintValue(void* (ASTContext)C, void* (Expr)E, const void* (&i)
  Expr* ValuePrinterSynthesizer::SynthesizeVP(Expr* E) {
    QualType QT = E->getType();
    // For now we skip void and function pointer types.
    if (!QT.isNull() && (QT->isVoidType() || QT->isFunctionType()))
      return 0;

    // Find cling_PrintValue
    SourceLocation NoSLoc = SourceLocation();
    DeclarationName PVName = &m_Context->Idents.get("cling_PrintValue");
    LookupResult R(*m_Sema, PVName, NoSLoc, Sema::LookupOrdinaryName,
                   Sema::ForRedeclaration);

    Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext);
    m_Sema->LookupName(R, S);
    assert(!R.empty() && "Cannot find cling_PrintValue(...)");

    CXXScopeSpec CSS;
    Expr* UnresolvedLookup
      = m_Sema->BuildDeclarationNameExpr(CSS, R, /*ADL*/ false).take();


    Expr* VoidEArg = utils::Synthesize::CStyleCastPtrExpr(m_Sema, 
                                                          m_Context->VoidPtrTy,
                                                          (uint64_t)E);
    Expr* VoidCArg = utils::Synthesize::CStyleCastPtrExpr(m_Sema, 
                                                          m_Context->VoidPtrTy,
                                                          (uint64_t)m_Context);

    if (!QT->isPointerType()) {
      while(ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(E))
        E = ICE->getSubExpr();
      E = m_Sema->BuildUnaryOp(S, NoSLoc, UO_AddrOf, E).take();
    }

    llvm::SmallVector<Expr*, 4> CallArgs;
    CallArgs.push_back(VoidEArg);
    CallArgs.push_back(VoidCArg);
    CallArgs.push_back(E);

    Expr* Result = m_Sema->ActOnCallExpr(S, UnresolvedLookup, NoSLoc,
                                         CallArgs, NoSLoc).take();
    assert(Result && "Cannot create value printer!");

    return Result;
  }
Esempio n. 9
0
/// \brief Perform adjustment on the parameter type of a function.
///
/// This routine adjusts the given parameter type @p T to the actual
/// parameter type used by semantic analysis (C99 6.7.5.3p[7,8], 
/// C++ [dcl.fct]p3). The adjusted parameter type is returned. 
QualType Sema::adjustParameterType(QualType T) {
  // C99 6.7.5.3p7:
  if (T->isArrayType()) {
    // C99 6.7.5.3p7:
    //   A declaration of a parameter as "array of type" shall be
    //   adjusted to "qualified pointer to type", where the type
    //   qualifiers (if any) are those specified within the [ and ] of
    //   the array type derivation.
    return Context.getArrayDecayedType(T);
  } else if (T->isFunctionType())
    // C99 6.7.5.3p8:
    //   A declaration of a parameter as "function returning type"
    //   shall be adjusted to "pointer to function returning type", as
    //   in 6.3.2.1.
    return Context.getPointerType(T);

  return T;
}
Esempio n. 10
0
bool ExprTypeAnalyser::checkFunction(QualType L, const Expr* expr) const {
    QualType R = expr->getType();

    if (isa<NilExpr>(expr)) return true;

    // NOTE: for now only allow FunctionTypes
    if (!R->isFunctionType()) {
        error(expr->getLocation(), L, R);
        return false;
    }
#if 0
    const FunctionType* FLeft = cast<FunctionType>(L.getTypePtr());
    const FunctionType* FRight = cast<FunctionType>(R.getTypePtr());
    const FunctionDecl* DL = FLeft->getDecl();
    const FunctionDecl* DR = FRight->getDecl();
    // TODO compare
#endif
    return true;
}
Esempio n. 11
0
  // We need to artificially create:
  // cling_PrintValue(void* (ASTContext)C, void* (Expr)E, const void* (&i)
  Expr* ValuePrinterSynthesizer::SynthesizeVP(Expr* E) {
    QualType QT = E->getType();
    // For now we skip void and function pointer types.
    if (!QT.isNull() && (QT->isVoidType() || QT->isFunctionType()))
      return 0;

    // Find cling_PrintValue
    if (!m_LookupResult)
      FindAndCacheRuntimeLookupResult(E->getLocStart());


    Expr* VoidEArg = utils::Synthesize::CStyleCastPtrExpr(m_Sema,
                                                          m_Context->VoidPtrTy,
                                                          (uint64_t)E);
    Expr* VoidCArg = utils::Synthesize::CStyleCastPtrExpr(m_Sema,
                                                          m_Context->VoidPtrTy,
                                                          (uint64_t)m_Context);

    SourceLocation NoSLoc = SourceLocation();
    Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext);
    if (!QT->isPointerType()) {
      while(ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(E))
        E = ICE->getSubExpr();
      E = m_Sema->BuildUnaryOp(S, NoSLoc, UO_AddrOf, E).get();
    }

    llvm::SmallVector<Expr*, 4> CallArgs;
    CallArgs.push_back(VoidEArg);
    CallArgs.push_back(VoidCArg);
    CallArgs.push_back(E);

    CXXScopeSpec CSS;
    Expr* unresolvedLookup
      = m_Sema->BuildDeclarationNameExpr(CSS, *m_LookupResult,
                                         /*ADL*/ false).get();

    Expr* Result = m_Sema->ActOnCallExpr(S, unresolvedLookup, E->getLocStart(),
                                         CallArgs, E->getLocEnd()).get();
    assert(Result && "Cannot create value printer!");

    return Result;
  }
Esempio n. 12
0
/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
/// @code ::delete ptr; @endcode
/// or
/// @code delete [] ptr; @endcode
Action::OwningExprResult
Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
                     bool ArrayForm, ExprArg Operand)
{
  // C++ 5.3.5p1: "The operand shall have a pointer type, or a class type
  //   having a single conversion function to a pointer type. The result has
  //   type void."
  // DR599 amends "pointer type" to "pointer to object type" in both cases.

  Expr *Ex = (Expr *)Operand.get();
  if (!Ex->isTypeDependent()) {
    QualType Type = Ex->getType();

    if (Type->isRecordType()) {
      // FIXME: Find that one conversion function and amend the type.
    }

    if (!Type->isPointerType())
      return ExprError(Diag(StartLoc, diag::err_delete_operand)
        << Type << Ex->getSourceRange());

    QualType Pointee = Type->getAsPointerType()->getPointeeType();
    if (Pointee->isFunctionType() || Pointee->isVoidType())
      return ExprError(Diag(StartLoc, diag::err_delete_operand)
        << Type << Ex->getSourceRange());
    else if (!Pointee->isDependentType() &&
             RequireCompleteType(StartLoc, Pointee, 
                                 diag::warn_delete_incomplete,
                                 Ex->getSourceRange()))
      return ExprError();

    // FIXME: Look up the correct operator delete overload and pass a pointer
    // along.
    // FIXME: Check access and ambiguity of operator delete and destructor.
  }

  Operand.release();
  return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,
                                           0, Ex, StartLoc));
}
Esempio n. 13
0
bool Declarator::isDeclarationOfFunction() const {
  for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
    switch (DeclTypeInfo[i].Kind) {
    case DeclaratorChunk::Function:
      return true;
    case DeclaratorChunk::Paren:
      continue;
    case DeclaratorChunk::Pointer:
    case DeclaratorChunk::Reference:
    case DeclaratorChunk::Array:
    case DeclaratorChunk::BlockPointer:
    case DeclaratorChunk::MemberPointer:
      return false;
    }
    llvm_unreachable("Invalid type chunk");
  }
  
  switch (DS.getTypeSpecType()) {
    case TST_atomic:
    case TST_auto:
    case TST_bool:
    case TST_char:
    case TST_char16:
    case TST_char32:
    case TST_class:
    case TST_decimal128:
    case TST_decimal32:
    case TST_decimal64:
    case TST_double:
    case TST_enum:
    case TST_error:
    case TST_float:
    case TST_half:
    case TST_int:
    case TST_int128:
    case TST_struct:
    case TST_interface:
    case TST_union:
    case TST_unknown_anytype:
    case TST_unspecified:
    case TST_void:
    case TST_wchar:
      return false;

    case TST_decltype_auto:
      // This must have an initializer, so can't be a function declaration,
      // even if the initializer has function type.
      return false;

    case TST_decltype:
    case TST_typeofExpr:
      if (Expr *E = DS.getRepAsExpr())
        return E->getType()->isFunctionType();
      return false;
     
    case TST_underlyingType:
    case TST_typename:
    case TST_typeofType: {
      QualType QT = DS.getRepAsType().get();
      if (QT.isNull())
        return false;
      
      if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT))
        QT = LIT->getType();

      if (QT.isNull())
        return false;
        
      return QT->isFunctionType();
    }
  }

  llvm_unreachable("Invalid TypeSpecType!");
}
Esempio n. 14
0
// FIXME: should rewrite according to the cast kind.
SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
  castTy = Context.getCanonicalType(castTy);
  originalTy = Context.getCanonicalType(originalTy);
  if (val.isUnknownOrUndef() || castTy == originalTy)
    return val;

  if (castTy->isBooleanType()) {
    if (val.isUnknownOrUndef())
      return val;
    if (val.isConstant())
      return makeTruthVal(!val.isZeroConstant(), castTy);
    if (!Loc::isLocType(originalTy) &&
        !originalTy->isIntegralOrEnumerationType() &&
        !originalTy->isMemberPointerType())
      return UnknownVal();
    if (SymbolRef Sym = val.getAsSymbol(true)) {
      BasicValueFactory &BVF = getBasicValueFactory();
      // FIXME: If we had a state here, we could see if the symbol is known to
      // be zero, but we don't.
      return makeNonLoc(Sym, BO_NE, BVF.getValue(0, Sym->getType()), castTy);
    }
    // Loc values are not always true, they could be weakly linked functions.
    if (Optional<Loc> L = val.getAs<Loc>())
      return evalCastFromLoc(*L, castTy);

    Loc L = val.castAs<nonloc::LocAsInteger>().getLoc();
    return evalCastFromLoc(L, castTy);
  }

  // For const casts, casts to void, just propagate the value.
  if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType())
    if (shouldBeModeledWithNoOp(Context, Context.getPointerType(castTy),
                                         Context.getPointerType(originalTy)))
      return val;
  
  // Check for casts from pointers to integers.
  if (castTy->isIntegralOrEnumerationType() && Loc::isLocType(originalTy))
    return evalCastFromLoc(val.castAs<Loc>(), castTy);

  // Check for casts from integers to pointers.
  if (Loc::isLocType(castTy) && originalTy->isIntegralOrEnumerationType()) {
    if (Optional<nonloc::LocAsInteger> LV = val.getAs<nonloc::LocAsInteger>()) {
      if (const MemRegion *R = LV->getLoc().getAsRegion()) {
        StoreManager &storeMgr = StateMgr.getStoreManager();
        R = storeMgr.castRegion(R, castTy);
        return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
      }
      return LV->getLoc();
    }
    return dispatchCast(val, castTy);
  }

  // Just pass through function and block pointers.
  if (originalTy->isBlockPointerType() || originalTy->isFunctionPointerType()) {
    assert(Loc::isLocType(castTy));
    return val;
  }

  // Check for casts from array type to another type.
  if (const ArrayType *arrayT =
                      dyn_cast<ArrayType>(originalTy.getCanonicalType())) {
    // We will always decay to a pointer.
    QualType elemTy = arrayT->getElementType();
    val = StateMgr.ArrayToPointer(val.castAs<Loc>(), elemTy);

    // Are we casting from an array to a pointer?  If so just pass on
    // the decayed value.
    if (castTy->isPointerType() || castTy->isReferenceType())
      return val;

    // Are we casting from an array to an integer?  If so, cast the decayed
    // pointer value to an integer.
    assert(castTy->isIntegralOrEnumerationType());

    // FIXME: Keep these here for now in case we decide soon that we
    // need the original decayed type.
    //    QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
    //    QualType pointerTy = C.getPointerType(elemTy);
    return evalCastFromLoc(val.castAs<Loc>(), castTy);
  }

  // Check for casts from a region to a specific type.
  if (const MemRegion *R = val.getAsRegion()) {
    // Handle other casts of locations to integers.
    if (castTy->isIntegralOrEnumerationType())
      return evalCastFromLoc(loc::MemRegionVal(R), castTy);

    // FIXME: We should handle the case where we strip off view layers to get
    //  to a desugared type.
    if (!Loc::isLocType(castTy)) {
      // FIXME: There can be gross cases where one casts the result of a function
      // (that returns a pointer) to some other value that happens to fit
      // within that pointer value.  We currently have no good way to
      // model such operations.  When this happens, the underlying operation
      // is that the caller is reasoning about bits.  Conceptually we are
      // layering a "view" of a location on top of those bits.  Perhaps
      // we need to be more lazy about mutual possible views, even on an
      // SVal?  This may be necessary for bit-level reasoning as well.
      return UnknownVal();
    }

    // We get a symbolic function pointer for a dereference of a function
    // pointer, but it is of function type. Example:

    //  struct FPRec {
    //    void (*my_func)(int * x);
    //  };
    //
    //  int bar(int x);
    //
    //  int f1_a(struct FPRec* foo) {
    //    int x;
    //    (*foo->my_func)(&x);
    //    return bar(x)+1; // no-warning
    //  }

    assert(Loc::isLocType(originalTy) || originalTy->isFunctionType() ||
           originalTy->isBlockPointerType() || castTy->isReferenceType());

    StoreManager &storeMgr = StateMgr.getStoreManager();

    // Delegate to store manager to get the result of casting a region to a
    // different type.  If the MemRegion* returned is NULL, this expression
    // Evaluates to UnknownVal.
    R = storeMgr.castRegion(R, castTy);
    return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
  }

  return dispatchCast(val, castTy);
}
Esempio n. 15
0
/// \brief Build an array type.
///
/// \param T The type of each element in the array.
///
/// \param ASM C99 array size modifier (e.g., '*', 'static').
///  
/// \param ArraySize Expression describing the size of the array. 
///
/// \param Quals The cvr-qualifiers to be applied to the array's
/// element type.
///
/// \param Loc The location of the entity whose type involves this
/// array type or, if there is no such entity, the location of the
/// type that will have array type.
///
/// \param Entity The name of the entity that involves the array
/// type, if known.
///
/// \returns A suitable array type, if there are no errors. Otherwise,
/// returns a NULL type.
QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
                              Expr *ArraySize, unsigned Quals,
                              SourceLocation Loc, DeclarationName Entity) {
  // C99 6.7.5.2p1: If the element type is an incomplete or function type, 
  // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
  if (RequireCompleteType(Loc, T, 
                             diag::err_illegal_decl_array_incomplete_type))
    return QualType();

  if (T->isFunctionType()) {
    Diag(Loc, diag::err_illegal_decl_array_of_functions)
      << getPrintableNameForEntity(Entity);
    return QualType();
  }
    
  // C++ 8.3.2p4: There shall be no ... arrays of references ...
  if (T->isReferenceType()) {
    Diag(Loc, diag::err_illegal_decl_array_of_references)
      << getPrintableNameForEntity(Entity);
    return QualType();
  } 

  if (const RecordType *EltTy = T->getAsRecordType()) {
    // If the element type is a struct or union that contains a variadic
    // array, accept it as a GNU extension: C99 6.7.2.1p2.
    if (EltTy->getDecl()->hasFlexibleArrayMember())
      Diag(Loc, diag::ext_flexible_array_in_array) << T;
  } else if (T->isObjCInterfaceType()) {
    Diag(Loc, diag::warn_objc_array_of_interfaces) << T;
  }
      
  // C99 6.7.5.2p1: The size expression shall have integer type.
  if (ArraySize && !ArraySize->isTypeDependent() &&
      !ArraySize->getType()->isIntegerType()) {
    Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
      << ArraySize->getType() << ArraySize->getSourceRange();
    ArraySize->Destroy(Context);
    return QualType();
  }
  llvm::APSInt ConstVal(32);
  if (!ArraySize) {
    T = Context.getIncompleteArrayType(T, ASM, Quals);
  } else if (ArraySize->isValueDependent()) {
    T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals);
  } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
             (!T->isDependentType() && !T->isConstantSizeType())) {
    // Per C99, a variable array is an array with either a non-constant
    // size or an element type that has a non-constant-size
    T = Context.getVariableArrayType(T, ArraySize, ASM, Quals);
  } else {
    // C99 6.7.5.2p1: If the expression is a constant expression, it shall
    // have a value greater than zero.
    if (ConstVal.isSigned()) {
      if (ConstVal.isNegative()) {
        Diag(ArraySize->getLocStart(),
             diag::err_typecheck_negative_array_size)
          << ArraySize->getSourceRange();
        return QualType();
      } else if (ConstVal == 0) {
        // GCC accepts zero sized static arrays.
        Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
          << ArraySize->getSourceRange();
      }
    } 
    T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
  }
  // If this is not C99, extwarn about VLA's and C99 array size modifiers.
  if (!getLangOptions().C99) {
    if (ArraySize && !ArraySize->isTypeDependent() && 
        !ArraySize->isValueDependent() && 
        !ArraySize->isIntegerConstantExpr(Context))
      Diag(Loc, diag::ext_vla);
    else if (ASM != ArrayType::Normal || Quals != 0)
      Diag(Loc, diag::ext_c99_array_usage);
  }

  return T;
}
Esempio n. 16
0
void TypePrinter::printAttributedAfter(const AttributedType *T,
                                       raw_ostream &OS) {
  // Prefer the macro forms of the GC and ownership qualifiers.
  if (T->getAttrKind() == AttributedType::attr_objc_gc ||
      T->getAttrKind() == AttributedType::attr_objc_ownership)
    return printAfter(T->getEquivalentType(), OS);

  // TODO: not all attributes are GCC-style attributes.
  OS << " __attribute__((";
  switch (T->getAttrKind()) {
  case AttributedType::attr_address_space:
    OS << "address_space(";
    OS << T->getEquivalentType().getAddressSpace();
    OS << ')';
    break;

  case AttributedType::attr_vector_size: {
    OS << "__vector_size__(";
    if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
      OS << vector->getNumElements();
      OS << " * sizeof(";
      print(vector->getElementType(), OS, StringRef());
      OS << ')';
    }
    OS << ')';
    break;
  }

  case AttributedType::attr_neon_vector_type:
  case AttributedType::attr_neon_polyvector_type: {
    if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
      OS << "neon_vector_type(";
    else
      OS << "neon_polyvector_type(";
    const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
    OS << vector->getNumElements();
    OS << ')';
    break;
  }

  case AttributedType::attr_regparm: {
    OS << "regparm(";
    QualType t = T->getEquivalentType();
    while (!t->isFunctionType())
      t = t->getPointeeType();
    OS << t->getAs<FunctionType>()->getRegParmType();
    OS << ')';
    break;
  }

  case AttributedType::attr_objc_gc: {
    OS << "objc_gc(";

    QualType tmp = T->getEquivalentType();
    while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
      QualType next = tmp->getPointeeType();
      if (next == tmp) break;
      tmp = next;
    }

    if (tmp.isObjCGCWeak())
      OS << "weak";
    else
      OS << "strong";
    OS << ')';
    break;
  }

  case AttributedType::attr_objc_ownership:
    OS << "objc_ownership(";
    switch (T->getEquivalentType().getObjCLifetime()) {
    case Qualifiers::OCL_None: llvm_unreachable("no ownership!");
    case Qualifiers::OCL_ExplicitNone: OS << "none"; break;
    case Qualifiers::OCL_Strong: OS << "strong"; break;
    case Qualifiers::OCL_Weak: OS << "weak"; break;
    case Qualifiers::OCL_Autoreleasing: OS << "autoreleasing"; break;
    }
    OS << ')';
    break;

  case AttributedType::attr_noreturn: OS << "noreturn"; break;
  case AttributedType::attr_cdecl: OS << "cdecl"; break;
  case AttributedType::attr_fastcall: OS << "fastcall"; break;
  case AttributedType::attr_stdcall: OS << "stdcall"; break;
  case AttributedType::attr_thiscall: OS << "thiscall"; break;
  case AttributedType::attr_pascal: OS << "pascal"; break;
  case AttributedType::attr_pcs: {
    OS << "pcs(";
   QualType t = T->getEquivalentType();
   while (!t->isFunctionType())
     t = t->getPointeeType();
   OS << (t->getAs<FunctionType>()->getCallConv() == CC_AAPCS ?
         "\"aapcs\"" : "\"aapcs-vfp\"");
   OS << ')';
   break;
  }
  case AttributedType::attr_pnaclcall: OS << "pnaclcall"; break;
  case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break;
  }
  OS << "))";
}
Esempio n. 17
0
// FIXME: should rewrite according to the cast kind.
SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
  castTy = Context.getCanonicalType(castTy);
  originalTy = Context.getCanonicalType(originalTy);
  if (val.isUnknownOrUndef() || castTy == originalTy)
    return val;

  // For const casts, just propagate the value.
  if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType())
    if (haveSimilarTypes(Context, Context.getPointerType(castTy),
                                  Context.getPointerType(originalTy)))
      return val;
  
  // Check for casts from pointers to integers.
  if (castTy->isIntegerType() && Loc::isLocType(originalTy))
    return evalCastFromLoc(cast<Loc>(val), castTy);

  // Check for casts from integers to pointers.
  if (Loc::isLocType(castTy) && originalTy->isIntegerType()) {
    if (nonloc::LocAsInteger *LV = dyn_cast<nonloc::LocAsInteger>(&val)) {
      if (const MemRegion *R = LV->getLoc().getAsRegion()) {
        StoreManager &storeMgr = StateMgr.getStoreManager();
        R = storeMgr.castRegion(R, castTy);
        return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
      }
      return LV->getLoc();
    }
    return dispatchCast(val, castTy);
  }

  // Just pass through function and block pointers.
  if (originalTy->isBlockPointerType() || originalTy->isFunctionPointerType()) {
    assert(Loc::isLocType(castTy));
    return val;
  }

  // Check for casts from array type to another type.
  if (originalTy->isArrayType()) {
    // We will always decay to a pointer.
    val = StateMgr.ArrayToPointer(cast<Loc>(val));

    // Are we casting from an array to a pointer?  If so just pass on
    // the decayed value.
    if (castTy->isPointerType())
      return val;

    // Are we casting from an array to an integer?  If so, cast the decayed
    // pointer value to an integer.
    assert(castTy->isIntegerType());

    // FIXME: Keep these here for now in case we decide soon that we
    // need the original decayed type.
    //    QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
    //    QualType pointerTy = C.getPointerType(elemTy);
    return evalCastFromLoc(cast<Loc>(val), castTy);
  }

  // Check for casts from a region to a specific type.
  if (const MemRegion *R = val.getAsRegion()) {
    // Handle other casts of locations to integers.
    if (castTy->isIntegerType())
      return evalCastFromLoc(loc::MemRegionVal(R), castTy);

    // FIXME: We should handle the case where we strip off view layers to get
    //  to a desugared type.
    if (!Loc::isLocType(castTy)) {
      // FIXME: There can be gross cases where one casts the result of a function
      // (that returns a pointer) to some other value that happens to fit
      // within that pointer value.  We currently have no good way to
      // model such operations.  When this happens, the underlying operation
      // is that the caller is reasoning about bits.  Conceptually we are
      // layering a "view" of a location on top of those bits.  Perhaps
      // we need to be more lazy about mutual possible views, even on an
      // SVal?  This may be necessary for bit-level reasoning as well.
      return UnknownVal();
    }

    // We get a symbolic function pointer for a dereference of a function
    // pointer, but it is of function type. Example:

    //  struct FPRec {
    //    void (*my_func)(int * x);
    //  };
    //
    //  int bar(int x);
    //
    //  int f1_a(struct FPRec* foo) {
    //    int x;
    //    (*foo->my_func)(&x);
    //    return bar(x)+1; // no-warning
    //  }

    assert(Loc::isLocType(originalTy) || originalTy->isFunctionType() ||
           originalTy->isBlockPointerType() || castTy->isReferenceType());

    StoreManager &storeMgr = StateMgr.getStoreManager();

    // Delegate to store manager to get the result of casting a region to a
    // different type.  If the MemRegion* returned is NULL, this expression
    // Evaluates to UnknownVal.
    R = storeMgr.castRegion(R, castTy);
    return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
  }

  return dispatchCast(val, castTy);
}
  void ValueExtractionSynthesizer::Transform() {
    const CompilationOptions& CO = getTransaction()->getCompilationOpts();
    // If we do not evaluate the result, or printing out the result return.
    if (!(CO.ResultEvaluation || CO.ValuePrinting))
      return;

    FunctionDecl* FD = getTransaction()->getWrapperFD();

    int foundAtPos = -1;
    Expr* lastExpr = utils::Analyze::GetOrCreateLastExpr(FD, &foundAtPos,
                                                         /*omitDS*/false,
                                                         m_Sema);
    if (foundAtPos < 0)
      return;

    typedef llvm::SmallVector<Stmt**, 4> StmtIters;
    StmtIters returnStmts;
    ReturnStmtCollector collector(returnStmts);
    CompoundStmt* CS = cast<CompoundStmt>(FD->getBody());
    collector.VisitStmt(CS);

    if (isa<Expr>(*(CS->body_begin() + foundAtPos)))
      returnStmts.push_back(CS->body_begin() + foundAtPos);

    // We want to support cases such as:
    // gCling->evaluate("if() return 'A' else return 12", V), that puts in V,
    // either A or 12.
    // In this case the void wrapper is compiled with the stmts returning
    // values. Sema would cast them to void, but the code will still be
    // executed. For example:
    // int g(); void f () { return g(); } will still call g().
    //
    for (StmtIters::iterator I = returnStmts.begin(), E = returnStmts.end();
         I != E; ++I) {
      ReturnStmt* RS = dyn_cast<ReturnStmt>(**I);
      if (RS) {
        // When we are handling a return stmt, the last expression must be the
        // return stmt value. Ignore the calculation of the lastStmt because it
        // might be wrong, in cases where the return is not in the end of the 
        // function.
        lastExpr = RS->getRetValue();
        if (lastExpr) {
          assert (lastExpr->getType()->isVoidType() && "Must be void type.");
          // Any return statement will have been "healed" by Sema
          // to correspond to the original void return type of the
          // wrapper, using a ImplicitCastExpr 'void' <ToVoid>.
          // Remove that.
          if (ImplicitCastExpr* VoidCast
              = dyn_cast<ImplicitCastExpr>(lastExpr)) {
            lastExpr = VoidCast->getSubExpr();
          }
        }
        // if no value assume void
        else {
          // We can't PushDeclContext, because we don't have scope.
          Sema::ContextRAII pushedDC(*m_Sema, FD);
          RS->setRetValue(SynthesizeSVRInit(0));
        }

      }
      else
        lastExpr = cast<Expr>(**I);

      if (lastExpr) {
        QualType lastExprTy = lastExpr->getType();
        // May happen on auto types which resolve to dependent.
        if (lastExprTy->isDependentType())
          continue;
        // Set up lastExpr properly.
        // Change the void function's return type
        // We can't PushDeclContext, because we don't have scope.
        Sema::ContextRAII pushedDC(*m_Sema, FD);

        if (lastExprTy->isFunctionType()) {
          // A return type of function needs to be converted to
          // pointer to function.
          lastExprTy = m_Context->getPointerType(lastExprTy);
          lastExpr = m_Sema->ImpCastExprToType(lastExpr, lastExprTy,
                                               CK_FunctionToPointerDecay,
                                               VK_RValue).take();
        }

        //
        // Here we don't want to depend on the JIT runFunction, because of its
        // limitations, when it comes to return value handling. There it is
        // not clear who provides the storage and who cleans it up in a
        // platform independent way.
        //
        // Depending on the type we need to synthesize a call to cling:
        // 0) void : set the value's type to void;
        // 1) enum, integral, float, double, referece, pointer types :
        //      call to cling::internal::setValueNoAlloc(...);
        // 2) object type (alloc on the stack) :
        //      cling::internal::setValueWithAlloc
        //   2.1) constant arrays:
        //          call to cling::runtime::internal::copyArray(...)
        //
        // We need to synthesize later:
        // Wrapper has signature: void w(cling::Value SVR)
        // case 1):
        //   setValueNoAlloc(gCling, &SVR, lastExprTy, lastExpr())
        // case 2):
        //   new (setValueWithAlloc(gCling, &SVR, lastExprTy)) (lastExpr)
        // case 2.1):
        //   copyArray(src, placement, size)

        Expr* SVRInit = SynthesizeSVRInit(lastExpr);
        // if we had return stmt update to execute the SVR init, even if the
        // wrapper returns void.
        if (RS) {
          if (ImplicitCastExpr* VoidCast
              = dyn_cast<ImplicitCastExpr>(RS->getRetValue()))
            VoidCast->setSubExpr(SVRInit);
        }
        else
          **I = SVRInit;
      }
    }
  }
Esempio n. 19
0
/// \brief Convert the specified declspec to the appropriate type
/// object.
/// \param DS  the declaration specifiers
/// \returns The type described by the declaration specifiers, or NULL
/// if there was an error.
QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
  // FIXME: Should move the logic from DeclSpec::Finish to here for validity
  // checking.
  QualType Result;
  
  switch (DS.getTypeSpecType()) {
  case DeclSpec::TST_void:
    Result = Context.VoidTy;
    break;
  case DeclSpec::TST_char:
    if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
      Result = Context.CharTy;
    else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed)
      Result = Context.SignedCharTy;
    else {
      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
             "Unknown TSS value");
      Result = Context.UnsignedCharTy;
    }
    break;
  case DeclSpec::TST_wchar:
    if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
      Result = Context.WCharTy;
    else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
      Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
        << DS.getSpecifierName(DS.getTypeSpecType());
      Result = Context.getSignedWCharType();
    } else {
      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
        "Unknown TSS value");
      Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
        << DS.getSpecifierName(DS.getTypeSpecType());
      Result = Context.getUnsignedWCharType();
    }
    break;
  case DeclSpec::TST_unspecified:
    // "<proto1,proto2>" is an objc qualified ID with a missing id.
    if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
      Result = Context.getObjCQualifiedIdType((ObjCProtocolDecl**)PQ,
                                              DS.getNumProtocolQualifiers());
      break;
    }
      
    // Unspecified typespec defaults to int in C90.  However, the C90 grammar
    // [C90 6.5] only allows a decl-spec if there was *some* type-specifier,
    // type-qualifier, or storage-class-specifier.  If not, emit an extwarn.
    // Note that the one exception to this is function definitions, which are
    // allowed to be completely missing a declspec.  This is handled in the
    // parser already though by it pretending to have seen an 'int' in this
    // case.
    if (getLangOptions().ImplicitInt) {
      // In C89 mode, we only warn if there is a completely missing declspec
      // when one is not allowed.
      if (DS.isEmpty())
        Diag(DS.getSourceRange().getBegin(), diag::warn_missing_declspec)
        << CodeModificationHint::CreateInsertion(DS.getSourceRange().getBegin(),
                                                 "int");
    } else if (!DS.hasTypeSpecifier()) {
      // C99 and C++ require a type specifier.  For example, C99 6.7.2p2 says:
      // "At least one type specifier shall be given in the declaration
      // specifiers in each declaration, and in the specifier-qualifier list in
      // each struct declaration and type name."
      // FIXME: Does Microsoft really have the implicit int extension in C++?
      unsigned DK = getLangOptions().CPlusPlus && !getLangOptions().Microsoft?
          diag::err_missing_type_specifier
        : diag::warn_missing_type_specifier;
      Diag(DS.getSourceRange().getBegin(), DK);

      // FIXME: If we could guarantee that the result would be
      // well-formed, it would be useful to have a code insertion hint
      // here. However, after emitting this warning/error, we often
      // emit other errors.
    }
      
    // FALL THROUGH.  
  case DeclSpec::TST_int: {
    if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
      switch (DS.getTypeSpecWidth()) {
      case DeclSpec::TSW_unspecified: Result = Context.IntTy; break;
      case DeclSpec::TSW_short:       Result = Context.ShortTy; break;
      case DeclSpec::TSW_long:        Result = Context.LongTy; break;
      case DeclSpec::TSW_longlong:    Result = Context.LongLongTy; break;
      }
    } else {
      switch (DS.getTypeSpecWidth()) {
      case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break;
      case DeclSpec::TSW_short:       Result = Context.UnsignedShortTy; break;
      case DeclSpec::TSW_long:        Result = Context.UnsignedLongTy; break;
      case DeclSpec::TSW_longlong:    Result =Context.UnsignedLongLongTy; break;
      }
    }
    break;
  }
  case DeclSpec::TST_float: Result = Context.FloatTy; break;
  case DeclSpec::TST_double:
    if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
      Result = Context.LongDoubleTy;
    else
      Result = Context.DoubleTy;
    break;
  case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool
  case DeclSpec::TST_decimal32:    // _Decimal32
  case DeclSpec::TST_decimal64:    // _Decimal64
  case DeclSpec::TST_decimal128:   // _Decimal128
    assert(0 && "FIXME: GNU decimal extensions not supported yet!"); 
  case DeclSpec::TST_class:
  case DeclSpec::TST_enum:
  case DeclSpec::TST_union:
  case DeclSpec::TST_struct: {
    Decl *D = static_cast<Decl *>(DS.getTypeRep());
    assert(D && "Didn't get a decl for a class/enum/union/struct?");
    assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
           DS.getTypeSpecSign() == 0 &&
           "Can't handle qualifiers on typedef names yet!");
    // TypeQuals handled by caller.
    Result = Context.getTypeDeclType(cast<TypeDecl>(D));
    break;
  }    
  case DeclSpec::TST_typename: {
    assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
           DS.getTypeSpecSign() == 0 &&
           "Can't handle qualifiers on typedef names yet!");
    Result = QualType::getFromOpaquePtr(DS.getTypeRep());

    if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
      // FIXME: Adding a TST_objcInterface clause doesn't seem ideal, so
      // we have this "hack" for now... 
      if (const ObjCInterfaceType *Interface = Result->getAsObjCInterfaceType())
        Result = Context.getObjCQualifiedInterfaceType(Interface->getDecl(),
                                                       (ObjCProtocolDecl**)PQ,
                                               DS.getNumProtocolQualifiers());
      else if (Result == Context.getObjCIdType())
        // id<protocol-list>
        Result = Context.getObjCQualifiedIdType((ObjCProtocolDecl**)PQ,
                                                DS.getNumProtocolQualifiers());
      else if (Result == Context.getObjCClassType())
        // Class<protocol-list>
        Diag(DS.getSourceRange().getBegin(), 
             diag::err_qualified_class_unsupported) << DS.getSourceRange();
      else
        Diag(DS.getSourceRange().getBegin(),
             diag::err_invalid_protocol_qualifiers) << DS.getSourceRange();
    }
    // TypeQuals handled by caller.
    break;
  }
  case DeclSpec::TST_typeofType:
    Result = QualType::getFromOpaquePtr(DS.getTypeRep());
    assert(!Result.isNull() && "Didn't get a type for typeof?");
    // TypeQuals handled by caller.
    Result = Context.getTypeOfType(Result);
    break;
  case DeclSpec::TST_typeofExpr: {
    Expr *E = static_cast<Expr *>(DS.getTypeRep());
    assert(E && "Didn't get an expression for typeof?");
    // TypeQuals handled by caller.
    Result = Context.getTypeOfExprType(E);
    break;
  }
  case DeclSpec::TST_error:
    return QualType();
  }
  
  // Handle complex types.
  if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
    if (getLangOptions().Freestanding)
      Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
    Result = Context.getComplexType(Result);
  }
  
  assert(DS.getTypeSpecComplex() != DeclSpec::TSC_imaginary &&
         "FIXME: imaginary types not supported yet!");
  
  // See if there are any attributes on the declspec that apply to the type (as
  // opposed to the decl).
  if (const AttributeList *AL = DS.getAttributes())
    ProcessTypeAttributeList(Result, AL);
    
  // Apply const/volatile/restrict qualifiers to T.
  if (unsigned TypeQuals = DS.getTypeQualifiers()) {

    // Enforce C99 6.7.3p2: "Types other than pointer types derived from object
    // or incomplete types shall not be restrict-qualified."  C++ also allows
    // restrict-qualified references.
    if (TypeQuals & QualType::Restrict) {
      if (Result->isPointerType() || Result->isReferenceType()) {
        QualType EltTy = Result->isPointerType() ? 
          Result->getAsPointerType()->getPointeeType() :
          Result->getAsReferenceType()->getPointeeType();
      
        // If we have a pointer or reference, the pointee must have an object
        // incomplete type.
        if (!EltTy->isIncompleteOrObjectType()) {
          Diag(DS.getRestrictSpecLoc(),
               diag::err_typecheck_invalid_restrict_invalid_pointee)
            << EltTy << DS.getSourceRange();
          TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier.
        }
      } else {
        Diag(DS.getRestrictSpecLoc(),
             diag::err_typecheck_invalid_restrict_not_pointer)
          << Result << DS.getSourceRange();
        TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier.
      }
    }
    
    // Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification
    // of a function type includes any type qualifiers, the behavior is
    // undefined."
    if (Result->isFunctionType() && TypeQuals) {
      // Get some location to point at, either the C or V location.
      SourceLocation Loc;
      if (TypeQuals & QualType::Const)
        Loc = DS.getConstSpecLoc();
      else {
        assert((TypeQuals & QualType::Volatile) &&
               "Has CV quals but not C or V?");
        Loc = DS.getVolatileSpecLoc();
      }
      Diag(Loc, diag::warn_typecheck_function_qualifiers)
        << Result << DS.getSourceRange();
    }
    
    // C++ [dcl.ref]p1:
    //   Cv-qualified references are ill-formed except when the
    //   cv-qualifiers are introduced through the use of a typedef
    //   (7.1.3) or of a template type argument (14.3), in which
    //   case the cv-qualifiers are ignored.
    // FIXME: Shouldn't we be checking SCS_typedef here?
    if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
        TypeQuals && Result->isReferenceType()) {
      TypeQuals &= ~QualType::Const;
      TypeQuals &= ~QualType::Volatile;
    }      
    
    Result = Result.getQualifiedType(TypeQuals);
  }
  return Result;
}
Esempio n. 20
0
/// GetTypeForDeclarator - Convert the type for the specified
/// declarator to Type instances. Skip the outermost Skip type
/// objects.
QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
  bool OmittedReturnType = false;

  if (D.getContext() == Declarator::BlockLiteralContext
      && Skip == 0
      && !D.getDeclSpec().hasTypeSpecifier()
      && (D.getNumTypeObjects() == 0
          || (D.getNumTypeObjects() == 1
              && D.getTypeObject(0).Kind == DeclaratorChunk::Function)))
    OmittedReturnType = true;

  // long long is a C99 feature.
  if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x &&
      D.getDeclSpec().getTypeSpecWidth() == DeclSpec::TSW_longlong)
    Diag(D.getDeclSpec().getTypeSpecWidthLoc(), diag::ext_longlong);

  // Determine the type of the declarator. Not all forms of declarator
  // have a type.
  QualType T;
  switch (D.getKind()) {
  case Declarator::DK_Abstract:
  case Declarator::DK_Normal:
  case Declarator::DK_Operator: {
    const DeclSpec& DS = D.getDeclSpec();
    if (OmittedReturnType)
      // We default to a dependent type initially.  Can be modified by
      // the first return statement.
      T = Context.DependentTy;
    else {
      T = ConvertDeclSpecToType(DS);
      if (T.isNull())
        return T;
    }
    break;
  }

  case Declarator::DK_Constructor:
  case Declarator::DK_Destructor:
  case Declarator::DK_Conversion:
    // Constructors and destructors don't have return types. Use
    // "void" instead. Conversion operators will check their return
    // types separately.
    T = Context.VoidTy;
    break;
  }

  // The name we're declaring, if any.
  DeclarationName Name;
  if (D.getIdentifier())
    Name = D.getIdentifier();

  // Walk the DeclTypeInfo, building the recursive type as we go.
  // DeclTypeInfos are ordered from the identifier out, which is
  // opposite of what we want :).
  for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) {
    DeclaratorChunk &DeclType = D.getTypeObject(e-i-1+Skip);
    switch (DeclType.Kind) {
    default: assert(0 && "Unknown decltype!");
    case DeclaratorChunk::BlockPointer:
      // If blocks are disabled, emit an error.
      if (!LangOpts.Blocks)
        Diag(DeclType.Loc, diag::err_blocks_disable);
        
      if (DeclType.Cls.TypeQuals)
        Diag(D.getIdentifierLoc(), diag::err_qualified_block_pointer_type);
      if (!T.getTypePtr()->isFunctionType())
        Diag(D.getIdentifierLoc(), diag::err_nonfunction_block_type);
      else
        T = Context.getBlockPointerType(T);
      break;
    case DeclaratorChunk::Pointer:
      T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
      break;
    case DeclaratorChunk::Reference:
      T = BuildReferenceType(T, DeclType.Ref.LValueRef,
                             DeclType.Ref.HasRestrict ? QualType::Restrict : 0,
                             DeclType.Loc, Name);
      break;
    case DeclaratorChunk::Array: {
      DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
      Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
      ArrayType::ArraySizeModifier ASM;
      if (ATI.isStar)
        ASM = ArrayType::Star;
      else if (ATI.hasStatic)
        ASM = ArrayType::Static;
      else
        ASM = ArrayType::Normal;
      T = BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals, DeclType.Loc, Name);
      break;
    }
    case DeclaratorChunk::Function: {
      // If the function declarator has a prototype (i.e. it is not () and
      // does not have a K&R-style identifier list), then the arguments are part
      // of the type, otherwise the argument list is ().
      const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
      
      // C99 6.7.5.3p1: The return type may not be a function or array type.
      if (T->isArrayType() || T->isFunctionType()) {
        Diag(DeclType.Loc, diag::err_func_returning_array_function) << T;
        T = Context.IntTy;
        D.setInvalidType(true);
      }
        
      if (FTI.NumArgs == 0) {
        if (getLangOptions().CPlusPlus) {
          // C++ 8.3.5p2: If the parameter-declaration-clause is empty, the
          // function takes no arguments.
          T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic,FTI.TypeQuals);
        } else if (FTI.isVariadic) {
          // We allow a zero-parameter variadic function in C if the
          // function is marked with the "overloadable"
          // attribute. Scan for this attribute now.
          bool Overloadable = false;
          for (const AttributeList *Attrs = D.getAttributes();
               Attrs; Attrs = Attrs->getNext()) {
            if (Attrs->getKind() == AttributeList::AT_overloadable) {
              Overloadable = true;
              break;
            }
          }

          if (!Overloadable)
            Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg);
          T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, 0);
        } else {
          // Simple void foo(), where the incoming T is the result type.
          T = Context.getFunctionNoProtoType(T);
        }
      } else if (FTI.ArgInfo[0].Param == 0) {
        // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function definition.
        Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);        
      } else {
        // Otherwise, we have a function with an argument list that is
        // potentially variadic.
        llvm::SmallVector<QualType, 16> ArgTys;
        
        for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
          ParmVarDecl *Param =
            cast<ParmVarDecl>(FTI.ArgInfo[i].Param.getAs<Decl>());
          QualType ArgTy = Param->getType();
          assert(!ArgTy.isNull() && "Couldn't parse type?");

          // Adjust the parameter type.
          assert((ArgTy == adjustParameterType(ArgTy)) && "Unadjusted type?");

          // Look for 'void'.  void is allowed only as a single argument to a
          // function with no other parameters (C99 6.7.5.3p10).  We record
          // int(void) as a FunctionProtoType with an empty argument list.
          if (ArgTy->isVoidType()) {
            // If this is something like 'float(int, void)', reject it.  'void'
            // is an incomplete type (C99 6.2.5p19) and function decls cannot
            // have arguments of incomplete type.
            if (FTI.NumArgs != 1 || FTI.isVariadic) {
              Diag(DeclType.Loc, diag::err_void_only_param);
              ArgTy = Context.IntTy;
              Param->setType(ArgTy);
            } else if (FTI.ArgInfo[i].Ident) {
              // Reject, but continue to parse 'int(void abc)'.
              Diag(FTI.ArgInfo[i].IdentLoc,
                   diag::err_param_with_void_type);
              ArgTy = Context.IntTy;
              Param->setType(ArgTy);
            } else {
              // Reject, but continue to parse 'float(const void)'.
              if (ArgTy.getCVRQualifiers())
                Diag(DeclType.Loc, diag::err_void_param_qualified);
              
              // Do not add 'void' to the ArgTys list.
              break;
            }
          } else if (!FTI.hasPrototype) {
            if (ArgTy->isPromotableIntegerType()) {
              ArgTy = Context.IntTy;
            } else if (const BuiltinType* BTy = ArgTy->getAsBuiltinType()) {
              if (BTy->getKind() == BuiltinType::Float)
                ArgTy = Context.DoubleTy;
            }
          }
          
          ArgTys.push_back(ArgTy);
        }
        T = Context.getFunctionType(T, &ArgTys[0], ArgTys.size(),
                                    FTI.isVariadic, FTI.TypeQuals);
      }
      break;
    }
    case DeclaratorChunk::MemberPointer:
      // The scope spec must refer to a class, or be dependent.
      DeclContext *DC = computeDeclContext(DeclType.Mem.Scope());
      QualType ClsType;
      // FIXME: Extend for dependent types when it's actually supported.
      // See ActOnCXXNestedNameSpecifier.
      if (CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC)) {
        ClsType = Context.getTagDeclType(RD);
      } else {
        if (DC) {
          Diag(DeclType.Mem.Scope().getBeginLoc(),
               diag::err_illegal_decl_mempointer_in_nonclass)
            << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
            << DeclType.Mem.Scope().getRange();
        }
        D.setInvalidType(true);
        ClsType = Context.IntTy;
      }

      // C++ 8.3.3p3: A pointer to member shall not pointer to ... a member
      //   with reference type, or "cv void."
      if (T->isReferenceType()) {
        Diag(DeclType.Loc, diag::err_illegal_decl_pointer_to_reference)
          << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
        D.setInvalidType(true);
        T = Context.IntTy;
      }
      if (T->isVoidType()) {
        Diag(DeclType.Loc, diag::err_illegal_decl_mempointer_to_void)
          << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
        T = Context.IntTy;
      }

      // Enforce C99 6.7.3p2: "Types other than pointer types derived from
      // object or incomplete types shall not be restrict-qualified."
      if ((DeclType.Mem.TypeQuals & QualType::Restrict) &&
          !T->isIncompleteOrObjectType()) {
        Diag(DeclType.Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
          << T;
        DeclType.Mem.TypeQuals &= ~QualType::Restrict;
      }

      T = Context.getMemberPointerType(T, ClsType.getTypePtr()).
                    getQualifiedType(DeclType.Mem.TypeQuals);

      break;
    }

    if (T.isNull()) {
      D.setInvalidType(true);
      T = Context.IntTy;
    }

    // See if there are any attributes on this declarator chunk.
    if (const AttributeList *AL = DeclType.getAttrs())
      ProcessTypeAttributeList(T, AL);
  }

  if (getLangOptions().CPlusPlus && T->isFunctionType()) {
    const FunctionProtoType *FnTy = T->getAsFunctionProtoType();
    assert(FnTy && "Why oh why is there not a FunctionProtoType here ?");

    // C++ 8.3.5p4: A cv-qualifier-seq shall only be part of the function type
    // for a nonstatic member function, the function type to which a pointer
    // to member refers, or the top-level function type of a function typedef
    // declaration.
    if (FnTy->getTypeQuals() != 0 &&
        D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
        ((D.getContext() != Declarator::MemberContext &&
          (!D.getCXXScopeSpec().isSet() ||
           !computeDeclContext(D.getCXXScopeSpec())->isRecord())) ||
         D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) {
      if (D.isFunctionDeclarator())
        Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_function_type);
      else
        Diag(D.getIdentifierLoc(),
             diag::err_invalid_qualified_typedef_function_type_use);

      // Strip the cv-quals from the type.
      T = Context.getFunctionType(FnTy->getResultType(), FnTy->arg_type_begin(),
                                  FnTy->getNumArgs(), FnTy->isVariadic(), 0);
    }
  }
  
  // If there were any type attributes applied to the decl itself (not the
  // type, apply the type attribute to the type!)
  if (const AttributeList *Attrs = D.getAttributes())
    ProcessTypeAttributeList(T, Attrs);
  
  return T;
}
Esempio n. 21
0
void TypePrinter::printAttributed(const AttributedType *T,
                                  std::string &S) {
  // Prefer the macro forms of the GC and ownership qualifiers.
  if (T->getAttrKind() == AttributedType::attr_objc_gc ||
      T->getAttrKind() == AttributedType::attr_objc_ownership)
    return print(T->getEquivalentType(), S);

  print(T->getModifiedType(), S);

  // TODO: not all attributes are GCC-style attributes.
  S += " __attribute__((";
  switch (T->getAttrKind()) {
  case AttributedType::attr_address_space:
    S += "address_space(";
    S += T->getEquivalentType().getAddressSpace();
    S += ")";
    break;

  case AttributedType::attr_vector_size: {
    S += "__vector_size__(";
    if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
      S += vector->getNumElements();
      S += " * sizeof(";

      std::string tmp;
      print(vector->getElementType(), tmp);
      S += tmp;
      S += ")";
    }
    S += ")";
    break;
  }

  case AttributedType::attr_neon_vector_type:
  case AttributedType::attr_neon_polyvector_type: {
    if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
      S += "neon_vector_type(";
    else
      S += "neon_polyvector_type(";
    const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
    S += llvm::utostr_32(vector->getNumElements());
    S += ")";
    break;
  }

  case AttributedType::attr_regparm: {
    S += "regparm(";
    QualType t = T->getEquivalentType();
    while (!t->isFunctionType())
      t = t->getPointeeType();
    S += t->getAs<FunctionType>()->getRegParmType();
    S += ")";
    break;
  }

  case AttributedType::attr_objc_gc: {
    S += "objc_gc(";

    QualType tmp = T->getEquivalentType();
    while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
      QualType next = tmp->getPointeeType();
      if (next == tmp) break;
      tmp = next;
    }

    if (tmp.isObjCGCWeak())
      S += "weak";
    else
      S += "strong";
    S += ")";
    break;
  }

  case AttributedType::attr_objc_ownership:
    S += "objc_ownership(";
    switch (T->getEquivalentType().getObjCLifetime()) {
    case Qualifiers::OCL_None: llvm_unreachable("no ownership!"); break;
    case Qualifiers::OCL_ExplicitNone: S += "none"; break;
    case Qualifiers::OCL_Strong: S += "strong"; break;
    case Qualifiers::OCL_Weak: S += "weak"; break;
    case Qualifiers::OCL_Autoreleasing: S += "autoreleasing"; break;
    }
    S += ")";
    break;

  case AttributedType::attr_noreturn: S += "noreturn"; break;
  case AttributedType::attr_cdecl: S += "cdecl"; break;
  case AttributedType::attr_fastcall: S += "fastcall"; break;
  case AttributedType::attr_stdcall: S += "stdcall"; break;
  case AttributedType::attr_thiscall: S += "thiscall"; break;
  case AttributedType::attr_pascal: S += "pascal"; break;
  case AttributedType::attr_pcs: {
   S += "pcs(";
   QualType t = T->getEquivalentType();
   while (!t->isFunctionType())
     t = t->getPointeeType();
   S += (t->getAs<FunctionType>()->getCallConv() == CC_AAPCS ?
         "\"aapcs\"" : "\"aapcs-vfp\"");
   S += ")";
   break;
  }
  }
  S += "))";
}
Esempio n. 22
0
const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
  const clang::Type &Ty = *Context.getCanonicalType(T).getTypePtr();

  switch (Ty.getTypeClass()) {
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
    assert(false && "Non-canonical or dependent types aren't possible.");
    break;

  case Type::Builtin: {
    switch (cast<BuiltinType>(Ty).getKind()) {
    default: assert(0 && "Unknown builtin type!");
    case BuiltinType::Void:
    case BuiltinType::ObjCId:
    case BuiltinType::ObjCClass:
    case BuiltinType::ObjCSel:
      // LLVM void type can only be used as the result of a function call.  Just
      // map to the same as char.
      return llvm::IntegerType::get(getLLVMContext(), 8);

    case BuiltinType::Bool:
      // Note that we always return bool as i1 for use as a scalar type.
      return llvm::Type::getInt1Ty(getLLVMContext());

    case BuiltinType::Char_S:
    case BuiltinType::Char_U:
    case BuiltinType::SChar:
    case BuiltinType::UChar:
    case BuiltinType::Short:
    case BuiltinType::UShort:
    case BuiltinType::Int:
    case BuiltinType::UInt:
    case BuiltinType::Long:
    case BuiltinType::ULong:
    case BuiltinType::LongLong:
    case BuiltinType::ULongLong:
    case BuiltinType::WChar:
    case BuiltinType::Char16:
    case BuiltinType::Char32:
      return llvm::IntegerType::get(getLLVMContext(),
        static_cast<unsigned>(Context.getTypeSize(T)));

    case BuiltinType::Float:
    case BuiltinType::Double:
    case BuiltinType::LongDouble:
      return getTypeForFormat(getLLVMContext(),
                              Context.getFloatTypeSemantics(T));

    case BuiltinType::NullPtr: {
      // Model std::nullptr_t as i8*
      const llvm::Type *Ty = llvm::IntegerType::get(getLLVMContext(), 8);
      return llvm::PointerType::getUnqual(Ty);
    }
        
    case BuiltinType::UInt128:
    case BuiltinType::Int128:
      return llvm::IntegerType::get(getLLVMContext(), 128);
    }
    break;
  }
  case Type::FixedWidthInt:
    return llvm::IntegerType::get(getLLVMContext(),
                                  cast<FixedWidthIntType>(T)->getWidth());
  case Type::Complex: {
    const llvm::Type *EltTy =
      ConvertTypeRecursive(cast<ComplexType>(Ty).getElementType());
    return llvm::StructType::get(TheModule.getContext(), EltTy, EltTy, NULL);
  }
  case Type::LValueReference:
  case Type::RValueReference: {
    const ReferenceType &RTy = cast<ReferenceType>(Ty);
    QualType ETy = RTy.getPointeeType();
    llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext());
    PointersToResolve.push_back(std::make_pair(ETy, PointeeType));
    return llvm::PointerType::get(PointeeType, ETy.getAddressSpace());
  }
  case Type::Pointer: {
    const PointerType &PTy = cast<PointerType>(Ty);
    QualType ETy = PTy.getPointeeType();
    llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext());
    PointersToResolve.push_back(std::make_pair(ETy, PointeeType));
    return llvm::PointerType::get(PointeeType, ETy.getAddressSpace());
  }

  case Type::VariableArray: {
    const VariableArrayType &A = cast<VariableArrayType>(Ty);
    assert(A.getIndexTypeCVRQualifiers() == 0 &&
           "FIXME: We only handle trivial array types so far!");
    // VLAs resolve to the innermost element type; this matches
    // the return of alloca, and there isn't any obviously better choice.
    return ConvertTypeForMemRecursive(A.getElementType());
  }
  case Type::IncompleteArray: {
    const IncompleteArrayType &A = cast<IncompleteArrayType>(Ty);
    assert(A.getIndexTypeCVRQualifiers() == 0 &&
           "FIXME: We only handle trivial array types so far!");
    // int X[] -> [0 x int]
    return llvm::ArrayType::get(ConvertTypeForMemRecursive(A.getElementType()), 0);
  }
  case Type::ConstantArray: {
    const ConstantArrayType &A = cast<ConstantArrayType>(Ty);
    const llvm::Type *EltTy = ConvertTypeForMemRecursive(A.getElementType());
    return llvm::ArrayType::get(EltTy, A.getSize().getZExtValue());
  }
  case Type::ExtVector:
  case Type::Vector: {
    const VectorType &VT = cast<VectorType>(Ty);
    return llvm::VectorType::get(ConvertTypeRecursive(VT.getElementType()),
                                 VT.getNumElements());
  }
  case Type::FunctionNoProto:
  case Type::FunctionProto: {
    // First, check whether we can build the full function type.
    if (const TagType* TT = VerifyFuncTypeComplete(&Ty)) {
      // This function's type depends on an incomplete tag type; make sure
      // we have an opaque type corresponding to the tag type.
      ConvertTagDeclType(TT->getDecl());
      // Create an opaque type for this function type, save it, and return it.
      llvm::Type *ResultType = llvm::OpaqueType::get(getLLVMContext());
      FunctionTypes.insert(std::make_pair(&Ty, ResultType));
      return ResultType;
    }
    // The function type can be built; call the appropriate routines to
    // build it.
    if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(&Ty))
      return GetFunctionType(getFunctionInfo(FPT), FPT->isVariadic());

    const FunctionNoProtoType *FNPT = cast<FunctionNoProtoType>(&Ty);
    return GetFunctionType(getFunctionInfo(FNPT), true);
  }

  case Type::ObjCInterface: {
    // Objective-C interfaces are always opaque (outside of the
    // runtime, which can do whatever it likes); we never refine
    // these.
    const llvm::Type *&T = InterfaceTypes[cast<ObjCInterfaceType>(&Ty)];
    if (!T)
        T = llvm::OpaqueType::get(getLLVMContext());
    return T;
  }

  case Type::ObjCObjectPointer: {
    // Protocol qualifications do not influence the LLVM type, we just return a
    // pointer to the underlying interface type. We don't need to worry about
    // recursive conversion.
    const llvm::Type *T =
      ConvertTypeRecursive(cast<ObjCObjectPointerType>(Ty).getPointeeType());
    return llvm::PointerType::getUnqual(T);
  }

  case Type::Record:
  case Type::Enum: {
    const TagDecl *TD = cast<TagType>(Ty).getDecl();
    const llvm::Type *Res = ConvertTagDeclType(TD);

    std::string TypeName(TD->getKindName());
    TypeName += '.';

    // Name the codegen type after the typedef name
    // if there is no tag type name available
    if (TD->getIdentifier())
      // FIXME: We should not have to check for a null decl context here.
      // Right now we do it because the implicit Obj-C decls don't have one.
      TypeName += TD->getDeclContext() ? TD->getQualifiedNameAsString() :
        TD->getNameAsString();
    else if (const TypedefType *TdT = dyn_cast<TypedefType>(T))
      // FIXME: We should not have to check for a null decl context here.
      // Right now we do it because the implicit Obj-C decls don't have one.
      TypeName += TdT->getDecl()->getDeclContext() ? 
        TdT->getDecl()->getQualifiedNameAsString() :
        TdT->getDecl()->getNameAsString();
    else
      TypeName += "anon";

    TheModule.addTypeName(TypeName, Res);
    return Res;
  }

  case Type::BlockPointer: {
    const QualType FTy = cast<BlockPointerType>(Ty).getPointeeType();
    llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext());
    PointersToResolve.push_back(std::make_pair(FTy, PointeeType));
    return llvm::PointerType::get(PointeeType, FTy.getAddressSpace());
  }

  case Type::MemberPointer: {
    // FIXME: This is ABI dependent. We use the Itanium C++ ABI.
    // http://www.codesourcery.com/public/cxx-abi/abi.html#member-pointers
    // If we ever want to support other ABIs this needs to be abstracted.

    QualType ETy = cast<MemberPointerType>(Ty).getPointeeType();
    const llvm::Type *PtrDiffTy =
        ConvertTypeRecursive(Context.getPointerDiffType());
    if (ETy->isFunctionType()) {
      return llvm::StructType::get(TheModule.getContext(), PtrDiffTy, PtrDiffTy,
                                   NULL);
    } else
      return PtrDiffTy;
  }

  case Type::TemplateSpecialization:
    assert(false && "Dependent types can't get here");
  }

  // FIXME: implement.
  return llvm::OpaqueType::get(getLLVMContext());
}