Esempio n. 1
0
static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
                                               const ParmVarDecl *Callback,
                                               ArrayRef<Expr *> CallArgs) {

  QualType Ty = Callback->getType();
  DeclRefExpr *Call = M.makeDeclRefExpr(Callback);
  Expr *SubExpr;
  if (Ty->isRValueReferenceType()) {
    SubExpr = M.makeImplicitCast(
        Call, Ty.getNonReferenceType(), CK_LValueToRValue);
  } else if (Ty->isLValueReferenceType() &&
             Call->getType()->isFunctionType()) {
    Ty = C.getPointerType(Ty.getNonReferenceType());
    SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay);
  } else if (Ty->isLValueReferenceType()
             && Call->getType()->isPointerType()
             && Call->getType()->getPointeeType()->isFunctionType()){
    SubExpr = Call;
  } else {
    llvm_unreachable("Unexpected state");
  }

  return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_RValue,
                          SourceLocation());
}
bool pointedTypesAreEqual(QualType SourceType, QualType DestType) {
  SourceType = SourceType.getNonReferenceType();
  DestType = DestType.getNonReferenceType();
  while (SourceType->isPointerType() && DestType->isPointerType()) {
    SourceType = SourceType->getPointeeType();
    DestType = DestType->getPointeeType();
  }
  return SourceType.getUnqualifiedType() == DestType.getUnqualifiedType();
}
bool needsConstCast(QualType SourceType, QualType DestType) {
  SourceType = SourceType.getNonReferenceType();
  DestType = DestType.getNonReferenceType();
  while (SourceType->isPointerType() && DestType->isPointerType()) {
    SourceType = SourceType->getPointeeType();
    DestType = DestType->getPointeeType();
    if (SourceType.isConstQualified() && !DestType.isConstQualified())
      return true;
  }
  return false;
}
Esempio n. 4
0
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
Action::OwningExprResult
Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
                        SourceLocation LAngleBracketLoc, TypeTy *Ty,
                        SourceLocation RAngleBracketLoc,
                        SourceLocation LParenLoc, ExprArg E,
                        SourceLocation RParenLoc) {
  Expr *Ex = E.takeAs<Expr>();
  // FIXME: Preserve type source info.
  QualType DestType = GetTypeFromParser(Ty);
  SourceRange OpRange(OpLoc, RParenLoc);
  SourceRange DestRange(LAngleBracketLoc, RAngleBracketLoc);

  // If the type is dependent, we won't do the semantic analysis now.
  // FIXME: should we check this in a more fine-grained manner?
  bool TypeDependent = DestType->isDependentType() || Ex->isTypeDependent();

  switch (Kind) {
  default: assert(0 && "Unknown C++ cast!");

  case tok::kw_const_cast:
    if (!TypeDependent)
      CheckConstCast(*this, Ex, DestType, OpRange, DestRange);
    return Owned(new (Context) CXXConstCastExpr(DestType.getNonReferenceType(),
                                                Ex, DestType, OpLoc));

  case tok::kw_dynamic_cast: {
    CastExpr::CastKind Kind = CastExpr::CK_Unknown;
    if (!TypeDependent)
      CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange, Kind);
    return Owned(new (Context)CXXDynamicCastExpr(DestType.getNonReferenceType(),
                                                 Kind, Ex, DestType, OpLoc));
  }
  case tok::kw_reinterpret_cast:
    if (!TypeDependent)
      CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange);
    return Owned(new (Context) CXXReinterpretCastExpr(
                                  DestType.getNonReferenceType(),
                                  Ex, DestType, OpLoc));

  case tok::kw_static_cast: {
    CastExpr::CastKind Kind = CastExpr::CK_Unknown;
    if (!TypeDependent)
      CheckStaticCast(*this, Ex, DestType, OpRange, Kind);
    return Owned(new (Context) CXXStaticCastExpr(DestType.getNonReferenceType(),
                                                 Kind, Ex, DestType, OpLoc));
  }
  }

  return ExprError();
}
Esempio n. 5
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. 6
0
/// PerformImplicitConversion - Perform an implicit conversion of the
/// expression From to the type ToType using the pre-computed implicit
/// conversion sequence ICS. Returns true if there was an error, false
/// otherwise. The expression From is replaced with the converted
/// expression. Flavor is the kind of conversion we're performing,
/// used in the error message.
bool
Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
                                const ImplicitConversionSequence &ICS,
                                const char* Flavor) {
  switch (ICS.ConversionKind) {
  case ImplicitConversionSequence::StandardConversion:
    if (PerformImplicitConversion(From, ToType, ICS.Standard, Flavor))
      return true;
    break;

  case ImplicitConversionSequence::UserDefinedConversion:
    // FIXME: This is, of course, wrong. We'll need to actually call
    // the constructor or conversion operator, and then cope with the
    // standard conversions.
    ImpCastExprToType(From, ToType.getNonReferenceType(), 
                      ToType->isLValueReferenceType());
    return false;

  case ImplicitConversionSequence::EllipsisConversion:
    assert(false && "Cannot perform an ellipsis conversion");
    return false;

  case ImplicitConversionSequence::BadConversion:
    return true;
  }

  // Everything went well.
  return false;
}
Esempio n. 7
0
/// Model calls to AssertionResult constructors that are not inlined.
void GTestChecker::checkPostCall(const CallEvent &Call,
                                 CheckerContext &C) const {
  /// If the constructor was inlined, there is no need model it.
  if (C.wasInlined)
    return;

  initIdentifierInfo(C.getASTContext());

  auto *CtorCall = dyn_cast<CXXConstructorCall>(&Call);
  if (!CtorCall)
    return;

  const CXXConstructorDecl *CtorDecl = CtorCall->getDecl();
  const CXXRecordDecl *CtorParent = CtorDecl->getParent();
  if (CtorParent->getIdentifier() != AssertionResultII)
    return;

  if (CtorDecl->getNumParams() == 0)
    return;


  // Call the appropriate modeling method based on the type of the first
  // constructor parameter.
  const ParmVarDecl *ParamDecl = CtorDecl->getParamDecl(0);
  QualType ParamType = ParamDecl->getType();
  if (CtorDecl->getNumParams() <= 2 &&
      ParamType.getNonReferenceType()->getCanonicalTypeUnqualified() ==
      C.getASTContext().BoolTy) {
    // The first parameter is either a boolean or reference to a boolean
    modelAssertionResultBoolConstructor(CtorCall, C);

  } else if (CtorDecl->isCopyConstructor()) {
    modelAssertionResultCopyConstructor(CtorCall, C);
  }
}
Esempio n. 8
0
static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
                                               const ParmVarDecl *Callback,
                                               ArrayRef<Expr *> CallArgs) {

  QualType Ty = Callback->getType();
  DeclRefExpr *Call = M.makeDeclRefExpr(Callback);
  CastKind CK;
  if (Ty->isRValueReferenceType()) {
    CK = CK_LValueToRValue;
  } else {
    assert(Ty->isLValueReferenceType());
    CK = CK_FunctionToPointerDecay;
    Ty = C.getPointerType(Ty.getNonReferenceType());
  }

  return new (C)
      CallExpr(C, M.makeImplicitCast(Call, Ty.getNonReferenceType(), CK),
               /*args=*/CallArgs,
               /*QualType=*/C.VoidTy,
               /*ExprValueType=*/VK_RValue,
               /*SourceLocation=*/SourceLocation());
}
Esempio n. 9
0
CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(
                                                 SourceLocation TyBeginLoc,
                                                 QualType T,
                                                 SourceLocation LParenLoc,
                                                 Expr **Args,
                                                 unsigned NumArgs,
                                                 SourceLocation RParenLoc)
  : Expr(CXXUnresolvedConstructExprClass, T.getNonReferenceType(),
         T->isDependentType(), true),
    TyBeginLoc(TyBeginLoc),
    Type(T),
    LParenLoc(LParenLoc),
    RParenLoc(RParenLoc),
    NumArgs(NumArgs) {
  Stmt **StoredArgs = reinterpret_cast<Stmt **>(this + 1);
  memcpy(StoredArgs, Args, sizeof(Expr *) * NumArgs);
}
Esempio n. 10
0
long long clang_Type_getAlignOf(CXType T) {
  if (T.kind == CXType_Invalid)
    return CXTypeLayoutError_Invalid;
  ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext();
  QualType QT = GetQualType(T);
  // [expr.alignof] p1: return size_t value for complete object type, reference
  //                    or array.
  // [expr.alignof] p3: if reference type, return size of referenced type
  if (QT->isReferenceType())
    QT = QT.getNonReferenceType();
  if (QT->isIncompleteType())
    return CXTypeLayoutError_Incomplete;
  if (QT->isDependentType())
    return CXTypeLayoutError_Dependent;
  // Exceptions by GCC extension - see ASTContext.cpp:1313 getTypeInfoImpl
  // if (QT->isFunctionType()) return 4; // Bug #15511 - should be 1
  // if (QT->isVoidType()) return 1;
  return Ctx.getTypeAlignInChars(QT).getQuantity();
}
void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *CastExpr = Result.Nodes.getNodeAs<CStyleCastExpr>("cast");

  // Ignore casts in macros.
  if (CastExpr->getExprLoc().isMacroID())
    return;

  // Casting to void is an idiomatic way to mute "unused variable" and similar
  // warnings.
  if (CastExpr->getCastKind() == CK_ToVoid)
    return;

  auto isFunction = [](QualType T) {
    T = T.getCanonicalType().getNonReferenceType();
    return T->isFunctionType() || T->isFunctionPointerType() ||
           T->isMemberFunctionPointerType();
  };

  const QualType DestTypeAsWritten =
      CastExpr->getTypeAsWritten().getUnqualifiedType();
  const QualType SourceTypeAsWritten =
      CastExpr->getSubExprAsWritten()->getType().getUnqualifiedType();
  const QualType SourceType = SourceTypeAsWritten.getCanonicalType();
  const QualType DestType = DestTypeAsWritten.getCanonicalType();

  auto ReplaceRange = CharSourceRange::getCharRange(
      CastExpr->getLParenLoc(), CastExpr->getSubExprAsWritten()->getBeginLoc());

  bool FnToFnCast =
      isFunction(SourceTypeAsWritten) && isFunction(DestTypeAsWritten);

  if (CastExpr->getCastKind() == CK_NoOp && !FnToFnCast) {
    // Function pointer/reference casts may be needed to resolve ambiguities in
    // case of overloaded functions, so detection of redundant casts is trickier
    // in this case. Don't emit "redundant cast" warnings for function
    // pointer/reference types.
    if (SourceTypeAsWritten == DestTypeAsWritten) {
      diag(CastExpr->getBeginLoc(), "redundant cast to the same type")
          << FixItHint::CreateRemoval(ReplaceRange);
      return;
    }
  }

  // The rest of this check is only relevant to C++.
  // We also disable it for Objective-C++.
  if (!getLangOpts().CPlusPlus || getLangOpts().ObjC1 || getLangOpts().ObjC2)
    return;
  // Ignore code inside extern "C" {} blocks.
  if (!match(expr(hasAncestor(linkageSpecDecl())), *CastExpr, *Result.Context)
           .empty())
    return;
  // Ignore code in .c files and headers included from them, even if they are
  // compiled as C++.
  if (getCurrentMainFile().endswith(".c"))
    return;

  SourceManager &SM = *Result.SourceManager;

  // Ignore code in .c files #included in other files (which shouldn't be done,
  // but people still do this for test and other purposes).
  if (SM.getFilename(SM.getSpellingLoc(CastExpr->getBeginLoc())).endswith(".c"))
    return;

  // Leave type spelling exactly as it was (unlike
  // getTypeAsWritten().getAsString() which would spell enum types 'enum X').
  StringRef DestTypeString =
      Lexer::getSourceText(CharSourceRange::getTokenRange(
                               CastExpr->getLParenLoc().getLocWithOffset(1),
                               CastExpr->getRParenLoc().getLocWithOffset(-1)),
                           SM, getLangOpts());

  auto Diag =
      diag(CastExpr->getBeginLoc(), "C-style casts are discouraged; use %0");

  auto ReplaceWithCast = [&](std::string CastText) {
    const Expr *SubExpr = CastExpr->getSubExprAsWritten()->IgnoreImpCasts();
    if (!isa<ParenExpr>(SubExpr)) {
      CastText.push_back('(');
      Diag << FixItHint::CreateInsertion(
          Lexer::getLocForEndOfToken(SubExpr->getEndLoc(), 0, SM,
                                     getLangOpts()),
          ")");
    }
    Diag << FixItHint::CreateReplacement(ReplaceRange, CastText);
  };
  auto ReplaceWithNamedCast = [&](StringRef CastType) {
    Diag << CastType;
    ReplaceWithCast((CastType + "<" + DestTypeString + ">").str());
  };

  // Suggest appropriate C++ cast. See [expr.cast] for cast notation semantics.
  switch (CastExpr->getCastKind()) {
  case CK_FunctionToPointerDecay:
    ReplaceWithNamedCast("static_cast");
    return;
  case CK_ConstructorConversion:
    if (!CastExpr->getTypeAsWritten().hasQualifiers() &&
        DestTypeAsWritten->isRecordType() &&
        !DestTypeAsWritten->isElaboratedTypeSpecifier()) {
      Diag << "constructor call syntax";
      // FIXME: Validate DestTypeString, maybe.
      ReplaceWithCast(DestTypeString.str());
    } else {
      ReplaceWithNamedCast("static_cast");
    }
    return;
  case CK_NoOp:
    if (FnToFnCast) {
      ReplaceWithNamedCast("static_cast");
      return;
    }
    if (SourceType == DestType) {
      Diag << "static_cast (if needed, the cast may be redundant)";
      ReplaceWithCast(("static_cast<" + DestTypeString + ">").str());
      return;
    }
    if (needsConstCast(SourceType, DestType) &&
        pointedUnqualifiedTypesAreEqual(SourceType, DestType)) {
      ReplaceWithNamedCast("const_cast");
      return;
    }
    if (DestType->isReferenceType()) {
      QualType Dest = DestType.getNonReferenceType();
      QualType Source = SourceType.getNonReferenceType();
      if (Source == Dest.withConst() ||
          SourceType.getNonReferenceType() == DestType.getNonReferenceType()) {
        ReplaceWithNamedCast("const_cast");
        return;
      }
      break;
    }
  // FALLTHROUGH
  case clang::CK_IntegralCast:
    // Convert integral and no-op casts between builtin types and enums to
    // static_cast. A cast from enum to integer may be unnecessary, but it's
    // still retained.
    if ((SourceType->isBuiltinType() || SourceType->isEnumeralType()) &&
        (DestType->isBuiltinType() || DestType->isEnumeralType())) {
      ReplaceWithNamedCast("static_cast");
      return;
    }
    break;
  case CK_BitCast:
    // FIXME: Suggest const_cast<...>(reinterpret_cast<...>(...)) replacement.
    if (!needsConstCast(SourceType, DestType)) {
      if (SourceType->isVoidPointerType())
        ReplaceWithNamedCast("static_cast");
      else
        ReplaceWithNamedCast("reinterpret_cast");
      return;
    }
    break;
  default:
    break;
  }

  Diag << "static_cast/const_cast/reinterpret_cast";
}
Esempio n. 12
0
OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
                                               SourceLocation StartLoc,
                                               SourceLocation LParenLoc,
                                               SourceLocation EndLoc) {
  SmallVector<Expr *, 8> Vars;
  for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
       I != E; ++I) {
    assert(*I && "NULL expr in OpenMP firstprivate clause.");
    if (isa<DependentScopeDeclRefExpr>(*I)) {
      // It will be analyzed later.
      Vars.push_back(*I);
      continue;
    }

    SourceLocation ELoc = (*I)->getExprLoc();
    // OpenMP [2.1, C/C++]
    //  A list item is a variable name.
    // OpenMP  [2.9.3.3, Restrictions, p.1]
    //  A variable that is part of another variable (as an array or
    //  structure element) cannot appear in a private clause.
    DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I);
    if (!DE || !isa<VarDecl>(DE->getDecl())) {
      Diag(ELoc, diag::err_omp_expected_var_name)
        << (*I)->getSourceRange();
      continue;
    }
    Decl *D = DE->getDecl();
    VarDecl *VD = cast<VarDecl>(D);

    QualType Type = VD->getType();
    if (Type->isDependentType() || Type->isInstantiationDependentType()) {
      // It will be analyzed later.
      Vars.push_back(DE);
      continue;
    }

    // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
    //  A variable that appears in a private clause must not have an incomplete
    //  type or a reference type.
    if (RequireCompleteType(ELoc, Type,
                            diag::err_omp_firstprivate_incomplete_type)) {
      continue;
    }
    if (Type->isReferenceType()) {
      Diag(ELoc, diag::err_omp_clause_ref_type_arg)
        << getOpenMPClauseName(OMPC_firstprivate) << Type;
      bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                    VarDecl::DeclarationOnly;
      Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
                                       diag::note_defined_here) << VD;
      continue;
    }

    // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
    //  A variable of class type (or array thereof) that appears in a private
    //  clause requires an accesible, unambiguous copy constructor for the
    //  class type.
    Type = Context.getBaseElementType(Type);
    CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
                          Type.getNonReferenceType()->getAsCXXRecordDecl() : 0;
    if (RD) {
      CXXConstructorDecl *CD = LookupCopyingConstructor(RD, 0);
      PartialDiagnostic PD =
        PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
      if (!CD ||
          CheckConstructorAccess(ELoc, CD,
                                 InitializedEntity::InitializeTemporary(Type),
                                 CD->getAccess(), PD) == AR_inaccessible ||
          CD->isDeleted()) {
        Diag(ELoc, diag::err_omp_required_method)
             << getOpenMPClauseName(OMPC_firstprivate) << 1;
        bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                      VarDecl::DeclarationOnly;
        Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
                                         diag::note_defined_here) << VD;
        Diag(RD->getLocation(), diag::note_previous_decl) << RD;
        continue;
      }
      MarkFunctionReferenced(ELoc, CD);
      DiagnoseUseOfDecl(CD, ELoc);

      CXXDestructorDecl *DD = RD->getDestructor();
      if (DD) {
        if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
            DD->isDeleted()) {
          Diag(ELoc, diag::err_omp_required_method)
               << getOpenMPClauseName(OMPC_firstprivate) << 4;
          bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                        VarDecl::DeclarationOnly;
          Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
                                           diag::note_defined_here) << VD;
          Diag(RD->getLocation(), diag::note_previous_decl) << RD;
          continue;
        }
        MarkFunctionReferenced(ELoc, DD);
        DiagnoseUseOfDecl(DD, ELoc);
      }
    }

    // If StartLoc and EndLoc are invalid - this is an implicit firstprivate
    // variable and it was checked already.
    if (StartLoc.isValid() && EndLoc.isValid()) {
      DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
      Type = Type.getNonReferenceType().getCanonicalType();
      bool IsConstant = Type.isConstant(Context);
      Type = Context.getBaseElementType(Type);
      // OpenMP [2.4.13, Data-sharing Attribute Clauses]
      //  A list item that specifies a given variable may not appear in more
      // than one clause on the same directive, except that a variable may be
      //  specified in both firstprivate and lastprivate clauses.
      //  TODO: add processing for lastprivate.
      if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
          DVar.RefExpr) {
        Diag(ELoc, diag::err_omp_wrong_dsa)
           << getOpenMPClauseName(DVar.CKind)
           << getOpenMPClauseName(OMPC_firstprivate);
        Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
           << getOpenMPClauseName(DVar.CKind);
        continue;
      }

      // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
      // in a Construct]
      //  Variables with the predetermined data-sharing attributes may not be
      //  listed in data-sharing attributes clauses, except for the cases
      //  listed below. For these exceptions only, listing a predetermined
      //  variable in a data-sharing attribute clause is allowed and overrides
      //  the variable's predetermined data-sharing attributes.
      // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
      // in a Construct, C/C++, p.2]
      //  Variables with const-qualified type having no mutable member may be
      //  listed in a firstprivate clause, even if they are static data members.
      if (!(IsConstant || VD->isStaticDataMember()) && !DVar.RefExpr &&
          DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
        Diag(ELoc, diag::err_omp_wrong_dsa)
           << getOpenMPClauseName(DVar.CKind)
           << getOpenMPClauseName(OMPC_firstprivate);
        Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
           << getOpenMPClauseName(DVar.CKind);
        continue;
      }

      // OpenMP [2.9.3.4, Restrictions, p.2]
      //  A list item that is private within a parallel region must not appear
      //  in a firstprivate clause on a worksharing construct if any of the
      //  worksharing regions arising from the worksharing construct ever bind
      //  to any of the parallel regions arising from the parallel construct.
      // OpenMP [2.9.3.4, Restrictions, p.3]
      //  A list item that appears in a reduction clause of a parallel construct
      //  must not appear in a firstprivate clause on a worksharing or task
      //  construct if any of the worksharing or task regions arising from the
      //  worksharing or task construct ever bind to any of the parallel regions
      //  arising from the parallel construct.
      // OpenMP [2.9.3.4, Restrictions, p.4]
      //  A list item that appears in a reduction clause in worksharing
      //  construct must not appear in a firstprivate clause in a task construct
      //  encountered during execution of any of the worksharing regions arising
      //  from the worksharing construct.
      // TODO:
    }

    DSAStack->addDSA(VD, DE, OMPC_firstprivate);
    Vars.push_back(DE);
  }

  if (Vars.empty()) return 0;

  return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
                                       Vars);
}
Esempio n. 13
0
OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
                                          SourceLocation StartLoc,
                                          SourceLocation LParenLoc,
                                          SourceLocation EndLoc) {
  SmallVector<Expr *, 8> Vars;
  for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
       I != E; ++I) {
    assert(*I && "NULL expr in OpenMP private clause.");
    if (isa<DependentScopeDeclRefExpr>(*I)) {
      // It will be analyzed later.
      Vars.push_back(*I);
      continue;
    }

    SourceLocation ELoc = (*I)->getExprLoc();
    // OpenMP [2.1, C/C++]
    //  A list item is a variable name.
    // OpenMP  [2.9.3.3, Restrictions, p.1]
    //  A variable that is part of another variable (as an array or
    //  structure element) cannot appear in a private clause.
    DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I);
    if (!DE || !isa<VarDecl>(DE->getDecl())) {
      Diag(ELoc, diag::err_omp_expected_var_name)
        << (*I)->getSourceRange();
      continue;
    }
    Decl *D = DE->getDecl();
    VarDecl *VD = cast<VarDecl>(D);

    QualType Type = VD->getType();
    if (Type->isDependentType() || Type->isInstantiationDependentType()) {
      // It will be analyzed later.
      Vars.push_back(DE);
      continue;
    }

    // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
    //  A variable that appears in a private clause must not have an incomplete
    //  type or a reference type.
    if (RequireCompleteType(ELoc, Type,
                            diag::err_omp_private_incomplete_type)) {
      continue;
    }
    if (Type->isReferenceType()) {
      Diag(ELoc, diag::err_omp_clause_ref_type_arg)
        << getOpenMPClauseName(OMPC_private) << Type;
      bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                    VarDecl::DeclarationOnly;
      Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
                                       diag::note_defined_here) << VD;
      continue;
    }

    // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
    //  A variable of class type (or array thereof) that appears in a private
    //  clause requires an accesible, unambiguous default constructor for the
    //  class type.
    while (Type.getNonReferenceType()->isArrayType()) {
      Type = cast<ArrayType>(
                 Type.getNonReferenceType().getTypePtr())->getElementType();
    }
    CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
                          Type.getNonReferenceType()->getAsCXXRecordDecl() : 0;
    if (RD) {
      CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
      PartialDiagnostic PD =
        PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
      if (!CD ||
          CheckConstructorAccess(ELoc, CD,
                                 InitializedEntity::InitializeTemporary(Type),
                                 CD->getAccess(), PD) == AR_inaccessible ||
          CD->isDeleted()) {
        Diag(ELoc, diag::err_omp_required_method)
             << getOpenMPClauseName(OMPC_private) << 0;
        bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                      VarDecl::DeclarationOnly;
        Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
                                         diag::note_defined_here) << VD;
        Diag(RD->getLocation(), diag::note_previous_decl) << RD;
        continue;
      }
      MarkFunctionReferenced(ELoc, CD);
      DiagnoseUseOfDecl(CD, ELoc);

      CXXDestructorDecl *DD = RD->getDestructor();
      if (DD) {
        if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
            DD->isDeleted()) {
          Diag(ELoc, diag::err_omp_required_method)
               << getOpenMPClauseName(OMPC_private) << 4;
          bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                        VarDecl::DeclarationOnly;
          Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
                                           diag::note_defined_here) << VD;
          Diag(RD->getLocation(), diag::note_previous_decl) << RD;
          continue;
        }
        MarkFunctionReferenced(ELoc, DD);
        DiagnoseUseOfDecl(DD, ELoc);
      }
    }

    // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
    // in a Construct]
    //  Variables with the predetermined data-sharing attributes may not be
    //  listed in data-sharing attributes clauses, except for the cases
    //  listed below. For these exceptions only, listing a predetermined
    //  variable in a data-sharing attribute clause is allowed and overrides
    //  the variable's predetermined data-sharing attributes.
    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
    if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
      Diag(ELoc, diag::err_omp_wrong_dsa)
         << getOpenMPClauseName(DVar.CKind)
         << getOpenMPClauseName(OMPC_private);
      if (DVar.RefExpr) {
        Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
             << getOpenMPClauseName(DVar.CKind);
      } else {
        Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
             << getOpenMPClauseName(DVar.CKind);
      }
      continue;
    }

    DSAStack->addDSA(VD, DE, OMPC_private);
    Vars.push_back(DE);
  }

  if (Vars.empty()) return 0;

  return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
}
Esempio n. 14
0
DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
  DSAVarData DVar;

  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
  // in a Construct, C/C++, predetermined, p.1]
  //  Variables appearing in threadprivate directives are threadprivate.
  if (D->getTLSKind() != VarDecl::TLS_None) {
    DVar.CKind = OMPC_threadprivate;
    return DVar;
  }
  if (Stack[0].SharingMap.count(D)) {
    DVar.RefExpr = Stack[0].SharingMap[D].RefExpr;
    DVar.CKind = OMPC_threadprivate;
    return DVar;
  }

  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
  // in a Construct, C/C++, predetermined, p.1]
  // Variables with automatic storage duration that are declared in a scope
  // inside the construct are private.
  OpenMPDirectiveKind Kind = getCurrentDirective();
  if (Kind != OMPD_parallel) {
    if (isOpenMPLocal(D, llvm::next(Stack.rbegin())) && D->isLocalVarDecl() &&
        (D->getStorageClass() == SC_Auto ||
         D->getStorageClass() == SC_None))
      DVar.CKind = OMPC_private;
      return DVar;
  }

  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
  // in a Construct, C/C++, predetermined, p.4]
  //  Static data memebers are shared.
  if (D->isStaticDataMember()) {
    // Variables with const-qualified type having no mutable member may be listed
    // in a firstprivate clause, even if they are static data members.
    DSAVarData DVarTemp = hasDSA(D, OMPC_firstprivate);
    if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
      return DVar;

    DVar.CKind = OMPC_shared;
    return DVar;
  }

  QualType Type = D->getType().getNonReferenceType().getCanonicalType();
  bool IsConstant = Type.isConstant(Actions.getASTContext());
  while (Type->isArrayType()) {
    QualType ElemType = cast<ArrayType>(Type.getTypePtr())->getElementType();
    Type = ElemType.getNonReferenceType().getCanonicalType();
  }
  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
  // in a Construct, C/C++, predetermined, p.6]
  //  Variables with const qualified type having no mutable member are
  //  shared.
  CXXRecordDecl *RD = Actions.getLangOpts().CPlusPlus ?
                                Type->getAsCXXRecordDecl() : 0;
  if (IsConstant &&
      !(Actions.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) {
    // Variables with const-qualified type having no mutable member may be
    // listed in a firstprivate clause, even if they are static data members.
    DSAVarData DVarTemp = hasDSA(D, OMPC_firstprivate);
    if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
      return DVar;

    DVar.CKind = OMPC_shared;
    return DVar;
  }

  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
  // in a Construct, C/C++, predetermined, p.7]
  //  Variables with static storage duration that are declared in a scope
  //  inside the construct are shared.
  if (D->isStaticLocal()) {
    DVar.CKind = OMPC_shared;
    return DVar;
  }

  // Explicitly specified attributes and local variables with predetermined
  // attributes.
  if (Stack.back().SharingMap.count(D)) {
    DVar.RefExpr = Stack.back().SharingMap[D].RefExpr;
    DVar.CKind = Stack.back().SharingMap[D].Attributes;
  }

  return DVar;
}
Esempio n. 15
0
llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
  QualType AllocType = E->getAllocatedType();
  FunctionDecl *NewFD = E->getOperatorNew();
  const FunctionProtoType *NewFTy = NewFD->getType()->getAs<FunctionProtoType>();

  CallArgList NewArgs;

  // The allocation size is the first argument.
  QualType SizeTy = getContext().getSizeType();

  llvm::Value *NumElements = 0;
  llvm::Value *AllocSize = EmitCXXNewAllocSize(*this, E, NumElements);
  
  NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy));

  // Emit the rest of the arguments.
  // FIXME: Ideally, this should just use EmitCallArgs.
  CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin();

  // First, use the types from the function type.
  // We start at 1 here because the first argument (the allocation size)
  // has already been emitted.
  for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) {
    QualType ArgType = NewFTy->getArgType(i);

    assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
           getTypePtr() ==
           getContext().getCanonicalType(NewArg->getType()).getTypePtr() &&
           "type mismatch in call argument!");

    NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
                                     ArgType));

  }

  // Either we've emitted all the call args, or we have a call to a
  // variadic function.
  assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) &&
         "Extra arguments in non-variadic function!");

  // If we still have any arguments, emit them using the type of the argument.
  for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end();
       NewArg != NewArgEnd; ++NewArg) {
    QualType ArgType = NewArg->getType();
    NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
                                     ArgType));
  }

  // Emit the call to new.
  RValue RV =
    EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs),
             CGM.GetAddrOfFunction(NewFD), NewArgs, NewFD);

  // If an allocation function is declared with an empty exception specification
  // it returns null to indicate failure to allocate storage. [expr.new]p13.
  // (We don't need to check for null when there's no new initializer and
  // we're allocating a POD type).
  bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() &&
    !(AllocType->isPODType() && !E->hasInitializer());

  llvm::BasicBlock *NewNull = 0;
  llvm::BasicBlock *NewNotNull = 0;
  llvm::BasicBlock *NewEnd = 0;

  llvm::Value *NewPtr = RV.getScalarVal();

  if (NullCheckResult) {
    NewNull = createBasicBlock("new.null");
    NewNotNull = createBasicBlock("new.notnull");
    NewEnd = createBasicBlock("new.end");

    llvm::Value *IsNull =
      Builder.CreateICmpEQ(NewPtr,
                           llvm::Constant::getNullValue(NewPtr->getType()),
                           "isnull");

    Builder.CreateCondBr(IsNull, NewNull, NewNotNull);
    EmitBlock(NewNotNull);
  }

  if (uint64_t CookiePadding = CalculateCookiePadding(getContext(), E)) {
    uint64_t CookieOffset = 
      CookiePadding - getContext().getTypeSize(SizeTy) / 8;
    
    llvm::Value *NumElementsPtr = 
      Builder.CreateConstInBoundsGEP1_64(NewPtr, CookieOffset);
    
    NumElementsPtr = Builder.CreateBitCast(NumElementsPtr, 
                                           ConvertType(SizeTy)->getPointerTo());
    Builder.CreateStore(NumElements, NumElementsPtr);

    // Now add the padding to the new ptr.
    NewPtr = Builder.CreateConstInBoundsGEP1_64(NewPtr, CookiePadding);
  }
  
  NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType()));

  EmitNewInitializer(*this, E, NewPtr, NumElements);

  if (NullCheckResult) {
    Builder.CreateBr(NewEnd);
    NewNotNull = Builder.GetInsertBlock();
    EmitBlock(NewNull);
    Builder.CreateBr(NewEnd);
    EmitBlock(NewEnd);

    llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType());
    PHI->reserveOperandSpace(2);
    PHI->addIncoming(NewPtr, NewNotNull);
    PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull);

    NewPtr = PHI;
  }

  return NewPtr;
}
Esempio n. 16
0
/// PerformImplicitConversion - Perform an implicit conversion of the
/// expression From to the type ToType by following the standard
/// conversion sequence SCS. Returns true if there was an error, false
/// otherwise. The expression From is replaced with the converted
/// expression. Flavor is the context in which we're performing this
/// conversion, for use in error messages.
bool 
Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
                                const StandardConversionSequence& SCS,
                                const char *Flavor) {
  // Overall FIXME: we are recomputing too many types here and doing
  // far too much extra work. What this means is that we need to keep
  // track of more information that is computed when we try the
  // implicit conversion initially, so that we don't need to recompute
  // anything here.
  QualType FromType = From->getType();

  if (SCS.CopyConstructor) {
    // FIXME: Create a temporary object by calling the copy
    // constructor.
    ImpCastExprToType(From, ToType.getNonReferenceType(), 
                      ToType->isLValueReferenceType());
    return false;
  }

  // Perform the first implicit conversion.
  switch (SCS.First) {
  case ICK_Identity:
  case ICK_Lvalue_To_Rvalue:
    // Nothing to do.
    break;

  case ICK_Array_To_Pointer:
    FromType = Context.getArrayDecayedType(FromType);
    ImpCastExprToType(From, FromType);
    break;

  case ICK_Function_To_Pointer:
    if (Context.getCanonicalType(FromType) == Context.OverloadTy) {
      FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, true);
      if (!Fn)
        return true;

      if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))
        return true;

      FixOverloadedFunctionReference(From, Fn);
      FromType = From->getType();
    }
    FromType = Context.getPointerType(FromType);
    ImpCastExprToType(From, FromType);
    break;

  default:
    assert(false && "Improper first standard conversion");
    break;
  }

  // Perform the second implicit conversion
  switch (SCS.Second) {
  case ICK_Identity:
    // Nothing to do.
    break;

  case ICK_Integral_Promotion:
  case ICK_Floating_Promotion:
  case ICK_Complex_Promotion:
  case ICK_Integral_Conversion:
  case ICK_Floating_Conversion:
  case ICK_Complex_Conversion:
  case ICK_Floating_Integral:
  case ICK_Complex_Real:
  case ICK_Compatible_Conversion:
      // FIXME: Go deeper to get the unqualified type!
    FromType = ToType.getUnqualifiedType();
    ImpCastExprToType(From, FromType);
    break;

  case ICK_Pointer_Conversion:
    if (SCS.IncompatibleObjC) {
      // Diagnose incompatible Objective-C conversions
      Diag(From->getSourceRange().getBegin(), 
           diag::ext_typecheck_convert_incompatible_pointer)
        << From->getType() << ToType << Flavor
        << From->getSourceRange();
    }

    if (CheckPointerConversion(From, ToType))
      return true;
    ImpCastExprToType(From, ToType);
    break;

  case ICK_Pointer_Member:
    if (CheckMemberPointerConversion(From, ToType))
      return true;
    ImpCastExprToType(From, ToType);
    break;

  case ICK_Boolean_Conversion:
    FromType = Context.BoolTy;
    ImpCastExprToType(From, FromType);
    break;

  default:
    assert(false && "Improper second standard conversion");
    break;
  }

  switch (SCS.Third) {
  case ICK_Identity:
    // Nothing to do.
    break;

  case ICK_Qualification:
    // FIXME: Not sure about lvalue vs rvalue here in the presence of
    // rvalue references.
    ImpCastExprToType(From, ToType.getNonReferenceType(), 
                      ToType->isLValueReferenceType());
    break;

  default:
    assert(false && "Improper second standard conversion");
    break;
  }

  return false;
}
Esempio n. 17
0
/// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
/// Can be interpreted either as function-style casting ("int(x)")
/// or class type construction ("ClassType(x,y,z)")
/// or creation of a value-initialized type ("int()").
Action::OwningExprResult
Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
                                SourceLocation LParenLoc,
                                MultiExprArg exprs,
                                SourceLocation *CommaLocs,
                                SourceLocation RParenLoc) {
  assert(TypeRep && "Missing type!");
  QualType Ty = QualType::getFromOpaquePtr(TypeRep);
  unsigned NumExprs = exprs.size();
  Expr **Exprs = (Expr**)exprs.get();
  SourceLocation TyBeginLoc = TypeRange.getBegin();
  SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc);

  if (Ty->isDependentType() ||
      CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) {
    exprs.release();
    return Owned(new (Context) CXXTemporaryObjectExpr(0, Ty, TyBeginLoc,
                                                      Exprs, NumExprs,
                                                      RParenLoc));
  }


  // C++ [expr.type.conv]p1:
  // If the expression list is a single expression, the type conversion
  // expression is equivalent (in definedness, and if defined in meaning) to the
  // corresponding cast expression.
  //
  if (NumExprs == 1) {
    if (CheckCastTypes(TypeRange, Ty, Exprs[0]))
      return ExprError();
    exprs.release();
    return Owned(new (Context) CXXFunctionalCastExpr(Ty.getNonReferenceType(),
                                                     Ty, TyBeginLoc, Exprs[0],
                                                     RParenLoc));
  }

  if (const RecordType *RT = Ty->getAsRecordType()) {
    CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl());

    if (NumExprs > 1 || Record->hasUserDeclaredConstructor()) {
      CXXConstructorDecl *Constructor
        = PerformInitializationByConstructor(Ty, Exprs, NumExprs,
                                             TypeRange.getBegin(),
                                             SourceRange(TypeRange.getBegin(),
                                                         RParenLoc),
                                             DeclarationName(),
                                             IK_Direct);

      if (!Constructor)
        return ExprError();

      exprs.release();
      return Owned(new (Context) CXXTemporaryObjectExpr(Constructor, Ty,
                                                        TyBeginLoc,  Exprs,
                                                        NumExprs, RParenLoc));
    }

    // Fall through to value-initialize an object of class type that
    // doesn't have a user-declared default constructor.
  }

  // C++ [expr.type.conv]p1:
  // If the expression list specifies more than a single value, the type shall
  // be a class with a suitably declared constructor.
  //
  if (NumExprs > 1)
    return ExprError(Diag(CommaLocs[0],
                          diag::err_builtin_func_cast_more_than_one_arg)
      << FullRange);

  assert(NumExprs == 0 && "Expected 0 expressions");

  // C++ [expr.type.conv]p2:
  // The expression T(), where T is a simple-type-specifier for a non-array
  // complete object type or the (possibly cv-qualified) void type, creates an
  // rvalue of the specified type, which is value-initialized.
  //
  if (Ty->isArrayType())
    return ExprError(Diag(TyBeginLoc,
                          diag::err_value_init_for_array_type) << FullRange);
  if (!Ty->isDependentType() && !Ty->isVoidType() &&
      RequireCompleteType(TyBeginLoc, Ty,
                          diag::err_invalid_incomplete_type_use, FullRange))
    return ExprError();

  if (RequireNonAbstractType(TyBeginLoc, Ty,
                             diag::err_allocation_of_abstract_type))
    return ExprError();
  
  exprs.release();
  return Owned(new (Context) CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc));
}
Esempio n. 18
0
void CodeGenFunction::EmitStartEHSpec(const Decl *D) {
  const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
  if (FD == 0)
    return;
  const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
  if (Proto == 0)
    return;

  assert(!Proto->hasAnyExceptionSpec() && "function with parameter pack");

  if (!Proto->hasExceptionSpec())
    return;

  llvm::Constant *Personality =
    CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
                                                      (VMContext),
                                                      true),
                              "__gxx_personality_v0");
  Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
  llvm::Value *llvm_eh_exception =
    CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
  llvm::Value *llvm_eh_selector =
    CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
  const llvm::IntegerType *Int8Ty;
  const llvm::PointerType *PtrToInt8Ty;
  Int8Ty = llvm::Type::getInt8Ty(VMContext);
  // C string type.  Used in lots of places.
  PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
  llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
  llvm::SmallVector<llvm::Value*, 8> SelectorArgs;

  llvm::BasicBlock *PrevLandingPad = getInvokeDest();
  llvm::BasicBlock *EHSpecHandler = createBasicBlock("ehspec.handler");
  llvm::BasicBlock *Match = createBasicBlock("match");
  llvm::BasicBlock *Unwind = 0;

  assert(PrevLandingPad == 0 && "EHSpec has invoke context");
  (void)PrevLandingPad;

  llvm::BasicBlock *Cont = createBasicBlock("cont");

  EmitBranchThroughCleanup(Cont);

  // Emit the statements in the try {} block
  setInvokeDest(EHSpecHandler);

  EmitBlock(EHSpecHandler);
  // Exception object
  llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
  llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow");

  SelectorArgs.push_back(Exc);
  SelectorArgs.push_back(Personality);
  SelectorArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
                                                Proto->getNumExceptions()+1));

  for (unsigned i = 0; i < Proto->getNumExceptions(); ++i) {
    QualType Ty = Proto->getExceptionType(i);
    llvm::Value *EHType
      = CGM.GenerateRTTI(Ty.getNonReferenceType());
    SelectorArgs.push_back(EHType);
  }
  if (Proto->getNumExceptions())
    SelectorArgs.push_back(Null);

  // Find which handler was matched.
  llvm::Value *Selector
    = Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(),
                         SelectorArgs.end(), "selector");
  if (Proto->getNumExceptions()) {
    Unwind = createBasicBlock("Unwind");

    Builder.CreateStore(Exc, RethrowPtr);
    Builder.CreateCondBr(Builder.CreateICmpSLT(Selector,
                                               llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
                                                                      0)),
                         Match, Unwind);

    EmitBlock(Match);
  }
  Builder.CreateCall(getUnexpectedFn(*this), Exc)->setDoesNotReturn();
  Builder.CreateUnreachable();

  if (Proto->getNumExceptions()) {
    EmitBlock(Unwind);
    Builder.CreateCall(getUnwindResumeOrRethrowFn(*this),
                       Builder.CreateLoad(RethrowPtr));
    Builder.CreateUnreachable();
  }

  EmitBlock(Cont);
}
Esempio n. 19
0
void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *CastExpr = Result.Nodes.getNodeAs<CStyleCastExpr>("cast");

  auto ParenRange = CharSourceRange::getTokenRange(CastExpr->getLParenLoc(),
                                                   CastExpr->getRParenLoc());
  // Ignore casts in macros.
  if (ParenRange.getBegin().isMacroID() || ParenRange.getEnd().isMacroID())
    return;

  // Casting to void is an idiomatic way to mute "unused variable" and similar
  // warnings.
  if (CastExpr->getTypeAsWritten()->isVoidType())
    return;

  QualType SourceType =
      CastExpr->getSubExprAsWritten()->getType().getCanonicalType();
  QualType DestType = CastExpr->getTypeAsWritten().getCanonicalType();

  if (SourceType == DestType) {
    diag(CastExpr->getLocStart(), "Redundant cast to the same type.")
        << FixItHint::CreateRemoval(ParenRange);
    return;
  }

  // The rest of this check is only relevant to C++.
  if (!Result.Context->getLangOpts().CPlusPlus)
    return;

  // Leave type spelling exactly as it was (unlike
  // getTypeAsWritten().getAsString() which would spell enum types 'enum X').
  StringRef DestTypeString = Lexer::getSourceText(
      CharSourceRange::getTokenRange(
          CastExpr->getLParenLoc().getLocWithOffset(1),
          CastExpr->getRParenLoc().getLocWithOffset(-1)),
      *Result.SourceManager, Result.Context->getLangOpts());

  auto diag_builder =
      diag(CastExpr->getLocStart(), "C-style casts are discouraged. %0");

  auto ReplaceWithCast = [&](StringRef CastType) {
    diag_builder << ("Use " + CastType + ".").str();

    const Expr *SubExpr = CastExpr->getSubExprAsWritten()->IgnoreImpCasts();
    std::string CastText = (CastType + "<" + DestTypeString + ">").str();
    if (!isa<ParenExpr>(SubExpr)) {
      CastText.push_back('(');
      diag_builder << FixItHint::CreateInsertion(
          Lexer::getLocForEndOfToken(SubExpr->getLocEnd(), 0,
                                     *Result.SourceManager,
                                     Result.Context->getLangOpts()),
          ")");
    }
    diag_builder << FixItHint::CreateReplacement(ParenRange, CastText);
  };
  // Suggest appropriate C++ cast. See [expr.cast] for cast notation semantics.
  switch (CastExpr->getCastKind()) {
  case CK_NoOp:
    if (needsConstCast(SourceType, DestType) &&
        pointedTypesAreEqual(SourceType, DestType)) {
      ReplaceWithCast("const_cast");
      return;
    }
    if (DestType->isReferenceType() &&
        (SourceType.getNonReferenceType() ==
             DestType.getNonReferenceType().withConst() ||
         SourceType.getNonReferenceType() == DestType.getNonReferenceType())) {
      ReplaceWithCast("const_cast");
      return;
    }
    // FALLTHROUGH
  case clang::CK_IntegralCast:
    // Convert integral and no-op casts between builtin types and enums to
    // static_cast. A cast from enum to integer may be unnecessary, but it's
    // still retained.
    if ((SourceType->isBuiltinType() || SourceType->isEnumeralType()) &&
        (DestType->isBuiltinType() || DestType->isEnumeralType())) {
      ReplaceWithCast("static_cast");
      return;
    }
    break;
  case CK_BitCast:
    // FIXME: Suggest const_cast<...>(reinterpret_cast<...>(...)) replacement.
    if (!needsConstCast(SourceType, DestType)) {
      ReplaceWithCast("reinterpret_cast");
      return;
    }
    break;
  default:
    break;
  }

  diag_builder << "Use static_cast/const_cast/reinterpret_cast.";
}
Esempio n. 20
0
void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{
  switch (getKind()) {
  case APValue::Uninitialized:
    Out << "<uninitialized>";
    return;
  case APValue::Int:
    if (Ty->isBooleanType())
      Out << (getInt().getBoolValue() ? "true" : "false");
    else
      Out << getInt();
    return;
  case APValue::Float:
    Out << GetApproxValue(getFloat());
    return;
  case APValue::Vector: {
    Out << '{';
    QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
    getVectorElt(0).printPretty(Out, Ctx, ElemTy);
    for (unsigned i = 1; i != getVectorLength(); ++i) {
      Out << ", ";
      getVectorElt(i).printPretty(Out, Ctx, ElemTy);
    }
    Out << '}';
    return;
  }
  case APValue::ComplexInt:
    Out << getComplexIntReal() << "+" << getComplexIntImag() << "i";
    return;
  case APValue::ComplexFloat:
    Out << GetApproxValue(getComplexFloatReal()) << "+"
        << GetApproxValue(getComplexFloatImag()) << "i";
    return;
  case APValue::LValue: {
    LValueBase Base = getLValueBase();
    if (!Base) {
      Out << "0";
      return;
    }

    bool IsReference = Ty->isReferenceType();
    QualType InnerTy
      = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType();
    if (InnerTy.isNull())
      InnerTy = Ty;

    if (!hasLValuePath()) {
      // No lvalue path: just print the offset.
      CharUnits O = getLValueOffset();
      CharUnits S = Ctx.getTypeSizeInChars(InnerTy);
      if (!O.isZero()) {
        if (IsReference)
          Out << "*(";
        if (O % S) {
          Out << "(char*)";
          S = CharUnits::One();
        }
        Out << '&';
      } else if (!IsReference)
        Out << '&';

      if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())
        Out << *VD;
      else {
        assert(Base.get<const Expr *>() != nullptr &&
               "Expecting non-null Expr");
        Base.get<const Expr*>()->printPretty(Out, nullptr,
                                             Ctx.getPrintingPolicy());
      }

      if (!O.isZero()) {
        Out << " + " << (O / S);
        if (IsReference)
          Out << ')';
      }
      return;
    }

    // We have an lvalue path. Print it out nicely.
    if (!IsReference)
      Out << '&';
    else if (isLValueOnePastTheEnd())
      Out << "*(&";

    QualType ElemTy;
    if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
      Out << *VD;
      ElemTy = VD->getType();
    } else {
      const Expr *E = Base.get<const Expr*>();
      assert(E != nullptr && "Expecting non-null Expr");
      E->printPretty(Out, nullptr, Ctx.getPrintingPolicy());
      ElemTy = E->getType();
    }

    ArrayRef<LValuePathEntry> Path = getLValuePath();
    const CXXRecordDecl *CastToBase = nullptr;
    for (unsigned I = 0, N = Path.size(); I != N; ++I) {
      if (ElemTy->getAs<RecordType>()) {
        // The lvalue refers to a class type, so the next path entry is a base
        // or member.
        const Decl *BaseOrMember =
        BaseOrMemberType::getFromOpaqueValue(Path[I].BaseOrMember).getPointer();
        if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
          CastToBase = RD;
          ElemTy = Ctx.getRecordType(RD);
        } else {
          const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
          Out << ".";
          if (CastToBase)
            Out << *CastToBase << "::";
          Out << *VD;
          ElemTy = VD->getType();
        }
      } else {
        // The lvalue must refer to an array.
        Out << '[' << Path[I].ArrayIndex << ']';
        ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType();
      }
    }

    // Handle formatting of one-past-the-end lvalues.
    if (isLValueOnePastTheEnd()) {
      // FIXME: If CastToBase is non-0, we should prefix the output with
      // "(CastToBase*)".
      Out << " + 1";
      if (IsReference)
        Out << ')';
    }
    return;
  }
  case APValue::Array: {
    const ArrayType *AT = Ctx.getAsArrayType(Ty);
    QualType ElemTy = AT->getElementType();
    Out << '{';
    if (unsigned N = getArrayInitializedElts()) {
      getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy);
      for (unsigned I = 1; I != N; ++I) {
        Out << ", ";
        if (I == 10) {
          // Avoid printing out the entire contents of large arrays.
          Out << "...";
          break;
        }
        getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy);
      }
    }
    Out << '}';
    return;
  }
  case APValue::Struct: {
    Out << '{';
    const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl();
    bool First = true;
    if (unsigned N = getStructNumBases()) {
      const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD);
      CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin();
      for (unsigned I = 0; I != N; ++I, ++BI) {
        assert(BI != CD->bases_end());
        if (!First)
          Out << ", ";
        getStructBase(I).printPretty(Out, Ctx, BI->getType());
        First = false;
      }
    }
    for (const auto *FI : RD->fields()) {
      if (!First)
        Out << ", ";
      if (FI->isUnnamedBitfield()) continue;
      getStructField(FI->getFieldIndex()).
        printPretty(Out, Ctx, FI->getType());
      First = false;
    }
    Out << '}';
    return;
  }
  case APValue::Union:
    Out << '{';
    if (const FieldDecl *FD = getUnionField()) {
      Out << "." << *FD << " = ";
      getUnionValue().printPretty(Out, Ctx, FD->getType());
    }
    Out << '}';
    return;
  case APValue::MemberPointer:
    // FIXME: This is not enough to unambiguously identify the member in a
    // multiple-inheritance scenario.
    if (const ValueDecl *VD = getMemberPointerDecl()) {
      Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD;
      return;
    }
    Out << "0";
    return;
  case APValue::AddrLabelDiff:
    Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName();
    Out << " - ";
    Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName();
    return;
  }
  llvm_unreachable("Unknown APValue kind!");
}
// The following is common part for 'cilk vector functions' and
// 'omp declare simd' functions metadata generation.
//
void CodeGenModule::EmitVectorVariantsMetadata(const CGFunctionInfo &FnInfo,
                                               const FunctionDecl *FD,
                                               llvm::Function *Fn,
                                               GroupMap &Groups) {

  // Do not emit any vector variant if there is an unsupported feature.
  bool HasImplicitThis = false;
  if (!CheckElementalArguments(*this, FD, Fn, HasImplicitThis))
    return;

  llvm::LLVMContext &Context = getLLVMContext();
  ASTContext &C = getContext();

  // Common metadata nodes.
  llvm::NamedMDNode *CilkElementalMetadata =
    getModule().getOrInsertNamedMetadata("cilk.functions");
  llvm::Metadata *ElementalMDArgs[] = {
    llvm::MDString::get(Context, "elemental")
  };
  llvm::MDNode *ElementalNode = llvm::MDNode::get(Context, ElementalMDArgs);
  llvm::Metadata *MaskMDArgs[] = {
    llvm::MDString::get(Context, "mask"),
    llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
      llvm::IntegerType::getInt1Ty(Context), 1))
  };
  llvm::MDNode *MaskNode = llvm::MDNode::get(Context, MaskMDArgs);
  MaskMDArgs[1] = llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
                    llvm::IntegerType::getInt1Ty(Context), 0));
  llvm::MDNode *NoMaskNode = llvm::MDNode::get(Context, MaskMDArgs);
  SmallVector<llvm::Metadata*, 8> ParameterNameArgs;
  ParameterNameArgs.push_back(llvm::MDString::get(Context, "arg_name"));
  llvm::MDNode *ParameterNameNode = 0;

//  // Vector variant metadata.
//  llvm::Value *VariantMDArgs[] = {
//    llvm::MDString::get(Context, "variant"),
//    llvm::UndefValue::get(llvm::Type::getVoidTy(Context))
//  };
//  llvm::MDNode *VariantNode = llvm::MDNode::get(Context, VariantMDArgs);

  for (GroupMap::iterator GI = Groups.begin(), GE = Groups.end();
       GI != GE;
       ++GI) {
    CilkElementalGroup &G = GI->second;

    // Parameter information.
    QualType FirstNonStepParmType;
    SmallVector<llvm::Metadata *, 8> AligArgs;
    SmallVector<llvm::Metadata *, 8> StepArgs;
    AligArgs.push_back(llvm::MDString::get(Context, "arg_alig"));
    StepArgs.push_back(llvm::MDString::get(Context, "arg_step"));

    // Handle implicit 'this' parameter if necessary.
    if (HasImplicitThis) {
      ParameterNameArgs.push_back(llvm::MDString::get(Context, "this"));
      bool IsNonStepParm = handleParameter(*this, G, "this",
                                           StepArgs, AligArgs);
      if (IsNonStepParm)
        FirstNonStepParmType = cast<CXXMethodDecl>(FD)->getThisType(C);
    }

    // Handle explicit paramenters.
    for (unsigned I = 0; I != FD->getNumParams(); ++I) {
      const ParmVarDecl *Parm = FD->getParamDecl(I);
      StringRef ParmName = Parm->getName();
      if (!ParameterNameNode)
        ParameterNameArgs.push_back(llvm::MDString::get(Context, ParmName));
      bool IsNonStepParm = handleParameter(*this, G, ParmName,
                                           StepArgs, AligArgs);
      if (IsNonStepParm && FirstNonStepParmType.isNull())
        FirstNonStepParmType = Parm->getType();
    }

    llvm::MDNode *StepNode = llvm::MDNode::get(Context, StepArgs);
    llvm::MDNode *AligNode = llvm::MDNode::get(Context, AligArgs);
    if (!ParameterNameNode)
      ParameterNameNode = llvm::MDNode::get(Context, ParameterNameArgs);

    // If there is no vectorlengthfor() in this group, determine the
    // characteristic type. This can depend on the linear/uniform attributes,
    // so it can differ between groups.
    //
    // The rules for computing the characteristic type are:
    //
    // a) For a non-void function, the characteristic data type is the
    //    return type.
    //
    // b) If the function has any non-uniform, non-linear parameters, the
    //    the characteristic data type is the type of the first such parameter.
    //
    // c) If the characteristic data type determined by a) or b) above is
    //    struct, union, or class type which is pass-by-value (except fo
    //    the type that maps to the built-in complex data type)
    //    the characteristic data type is int.
    //
    // d) If none of the above three cases is applicable,
    //    the characteristic data type is int.
    //
    // e) For Intel Xeon Phi native and offload compilation, if the resulting
    //    characteristic data type is 8-bit or 16-bit integer data type
    //    the characteristic data type is int.
    //
    // These rules missed the reference types and we use their pointer types.
    //
    if (G.VecLengthFor.empty()) {
      QualType FnRetTy = FD->getReturnType();
      QualType CharacteristicType;
      if (!FnRetTy->isVoidType())
        CharacteristicType = FnRetTy;
      else if (!FirstNonStepParmType.isNull())
        CharacteristicType = FirstNonStepParmType.getCanonicalType();
      else
        CharacteristicType = C.IntTy;

      if (CharacteristicType->isReferenceType()) {
        QualType BaseTy = CharacteristicType.getNonReferenceType();
        CharacteristicType = C.getPointerType(BaseTy);
      } else if (CharacteristicType->isAggregateType())
        CharacteristicType = C.IntTy;
      // FIXME: handle Xeon Phi targets.
      G.VecLengthFor.push_back(CharacteristicType);
    }

//    // If no mask variants are specified, generate both.
//    if (G.Mask.empty()) {
//      G.Mask.push_back(1);
//      G.Mask.push_back(0);
//    }

    // If no vector length is specified, push a dummy value to iterate over.
    if (G.VecLength.empty())
      G.VecLength.push_back(0);

    for (CilkElementalGroup::VecLengthForVector::iterator
          TI = G.VecLengthFor.begin(),
          TE = G.VecLengthFor.end();
          TI != TE;
          ++TI) {


        uint64_t VectorRegisterBytes = 0;
        // Inspect the current target features to determine the
        // appropriate vector size.
        // This is currently X86 specific.
        if (Target.hasFeature("avx2"))
          VectorRegisterBytes = 64;
        else if (Target.hasFeature("avx"))
          VectorRegisterBytes = 32;
        else if (Target.hasFeature("sse2"))
          VectorRegisterBytes = 16;
        else if (Target.hasFeature("sse") &&
                (*TI)->isFloatingType() &&
                C.getTypeSizeInChars(*TI).getQuantity() == 4)
          VectorRegisterBytes = 16;
        else if (Target.hasFeature("mmx") && (*TI)->isIntegerType())
          VectorRegisterBytes = 8;
        for (CilkElementalGroup::VecLengthVector::iterator
              LI = G.VecLength.begin(),
              LE = G.VecLength.end();
             LI != LE;
             ++LI) {

          uint64_t VL = *LI ? *LI :
            (CharUnits::fromQuantity(VectorRegisterBytes)
             / C.getTypeSizeInChars(*TI));

          llvm::MDNode *VecTypeNode
            = MakeVecLengthMetadata(*this, "vec_length", *TI, VL);

          {
            SmallVector <llvm::Metadata*, 7> kernelMDArgs;
            kernelMDArgs.push_back(llvm::ValueAsMetadata::get(Fn));
            kernelMDArgs.push_back(ElementalNode);
            kernelMDArgs.push_back(ParameterNameNode);
            kernelMDArgs.push_back(StepNode);
            kernelMDArgs.push_back(AligNode);
            kernelMDArgs.push_back(VecTypeNode);
            if (!G.Mask.empty())
              kernelMDArgs.push_back((G.Mask.back()==0)?(NoMaskNode):(MaskNode));
            llvm::MDNode *KernelMD = llvm::MDNode::get(Context, kernelMDArgs);
            CilkElementalMetadata->addOperand(KernelMD);
          }
//          for (CilkElementalGroup::MaskVector::iterator
//                MI = G.Mask.begin(),
//                ME = G.Mask.end();
//               MI != ME;
//               ++MI) {
//
//            SmallVector <llvm::Value*, 7> kernelMDArgs;
//            kernelMDArgs.push_back(Fn);
//            kernelMDArgs.push_back(ElementalNode);
//            kernelMDArgs.push_back(ParameterNameNode);
//            kernelMDArgs.push_back(StepNode);
//            kernelMDArgs.push_back(AligNode);
//            kernelMDArgs.push_back(VecTypeNode);
//            kernelMDArgs.push_back((*MI==0)?(NoMaskNode):(MaskNode));
//            if (ProcessorNode)
//              kernelMDArgs.push_back(ProcessorNode);
//            kernelMDArgs.push_back(VariantNode);
//            llvm::MDNode *KernelMD = llvm::MDNode::get(Context, kernelMDArgs);
//            CilkElementalMetadata->addOperand(KernelMD);
//            ElementalVariantToEmit.push_back(
//                ElementalVariantInfo(&FnInfo, FD, Fn, KernelMD));
//          }
        }
      }
  }
}
llvm::Constant *
CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
                                   GlobalDecl GD, bool Extern,
                                   const CovariantThunkAdjustment &Adjustment) {
  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
  const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
  QualType ResultType = FPT->getResultType();

  FunctionArgList Args;
  ImplicitParamDecl *ThisDecl =
    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
                              MD->getThisType(getContext()));
  Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType()));
  for (FunctionDecl::param_const_iterator i = MD->param_begin(),
         e = MD->param_end();
       i != e; ++i) {
    ParmVarDecl *D = *i;
    Args.push_back(std::make_pair(D, D->getType()));
  }
  IdentifierInfo *II
    = &CGM.getContext().Idents.get("__thunk_named_foo_");
  FunctionDecl *FD = FunctionDecl::Create(getContext(),
                                          getContext().getTranslationUnitDecl(),
                                          SourceLocation(), II, ResultType, 0,
                                          Extern
                                            ? FunctionDecl::Extern
                                            : FunctionDecl::Static,
                                          false, true);
  StartFunction(FD, ResultType, Fn, Args, SourceLocation());

  // generate body
  const llvm::Type *Ty =
    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
                                   FPT->isVariadic());
  llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty);

  CallArgList CallArgs;

  bool ShouldAdjustReturnPointer = true;
  QualType ArgType = MD->getThisType(getContext());
  llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this");
  if (!Adjustment.ThisAdjustment.isEmpty()) {
    // Do the this adjustment.
    const llvm::Type *OrigTy = Callee->getType();
    Arg = DynamicTypeAdjust(Arg, Adjustment.ThisAdjustment);
    
    if (!Adjustment.ReturnAdjustment.isEmpty()) {
      const CovariantThunkAdjustment &ReturnAdjustment = 
        CovariantThunkAdjustment(ThunkAdjustment(),
                                 Adjustment.ReturnAdjustment);
      
      Callee = CGM.BuildCovariantThunk(GD, Extern, ReturnAdjustment);
      
      Callee = Builder.CreateBitCast(Callee, OrigTy);
      ShouldAdjustReturnPointer = false;
    }
  }    

  CallArgs.push_back(std::make_pair(RValue::get(Arg), ArgType));

  for (FunctionDecl::param_const_iterator i = MD->param_begin(),
         e = MD->param_end();
       i != e; ++i) {
    ParmVarDecl *D = *i;
    QualType ArgType = D->getType();

    // llvm::Value *Arg = CGF.GetAddrOfLocalVar(Dst);
    Expr *Arg = new (getContext()) DeclRefExpr(D, ArgType.getNonReferenceType(),
                                               SourceLocation());
    CallArgs.push_back(std::make_pair(EmitCallArg(Arg, ArgType), ArgType));
  }

  RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs,
                                                      FPT->getCallConv(),
                                                      FPT->getNoReturnAttr()),
                       Callee, ReturnValueSlot(), CallArgs, MD);
  if (ShouldAdjustReturnPointer && !Adjustment.ReturnAdjustment.isEmpty()) {
    bool CanBeZero = !(ResultType->isReferenceType()
    // FIXME: attr nonnull can't be zero either
                       /* || ResultType->hasAttr<NonNullAttr>() */ );
    // Do the return result adjustment.
    if (CanBeZero) {
      llvm::BasicBlock *NonZeroBlock = createBasicBlock();
      llvm::BasicBlock *ZeroBlock = createBasicBlock();
      llvm::BasicBlock *ContBlock = createBasicBlock();

      const llvm::Type *Ty = RV.getScalarVal()->getType();
      llvm::Value *Zero = llvm::Constant::getNullValue(Ty);
      Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero),
                           NonZeroBlock, ZeroBlock);
      EmitBlock(NonZeroBlock);
      llvm::Value *NZ = 
        DynamicTypeAdjust(RV.getScalarVal(), Adjustment.ReturnAdjustment);
      EmitBranch(ContBlock);
      EmitBlock(ZeroBlock);
      llvm::Value *Z = RV.getScalarVal();
      EmitBlock(ContBlock);
      llvm::PHINode *RVOrZero = Builder.CreatePHI(Ty);
      RVOrZero->reserveOperandSpace(2);
      RVOrZero->addIncoming(NZ, NonZeroBlock);
      RVOrZero->addIncoming(Z, ZeroBlock);
      RV = RValue::get(RVOrZero);
    } else
      RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), 
                                         Adjustment.ReturnAdjustment));
  }

  if (!ResultType->isVoidType())
    EmitReturnOfRValue(RV, ResultType);

  FinishFunction();
  return Fn;
}