void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCInterfaceDecl *D) { for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end(); M != MEnd; ++M) { ObjCMethodDecl *Method = (*M); if (Method->isPropertyAccessor() || Method->param_size() != 0) continue; // Is this method candidate to be a getter? QualType GRT = Method->getResultType(); if (GRT->isVoidType()) continue; Selector GetterSelector = Method->getSelector(); IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0); Selector SetterSelector = SelectorTable::constructSetterSelector(PP.getIdentifierTable(), PP.getSelectorTable(), getterName); if (ObjCMethodDecl *SetterMethod = D->lookupMethod(SetterSelector, true)) { // Is this a valid setter, matching the target getter? QualType SRT = SetterMethod->getResultType(); if (!SRT->isVoidType()) continue; const ParmVarDecl *argDecl = *SetterMethod->param_begin(); QualType ArgType = argDecl->getType(); if (!Ctx.hasSameType(ArgType, GRT)) continue; edit::Commit commit(*Editor); edit::rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit); Editor->commit(commit); } } }
void ReturnSynthesizer::Transform() { if (!getTransaction()->getCompilationOpts().ResultEvaluation) return; FunctionDecl* FD = getTransaction()->getWrapperFD(); int foundAtPos = -1; Expr* lastExpr = utils::Analyze::GetOrCreateLastExpr(FD, &foundAtPos, /*omitDS*/false, m_Sema); if (lastExpr) { QualType RetTy = lastExpr->getType(); if (!RetTy->isVoidType() && RetTy.isTriviallyCopyableType(*m_Context)) { // Change the void function's return type // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, FD); FunctionProtoType::ExtProtoInfo EPI; QualType FnTy = m_Context->getFunctionType(RetTy, llvm::ArrayRef<QualType>(), EPI); FD->setType(FnTy); CompoundStmt* CS = cast<CompoundStmt>(FD->getBody()); assert(CS && "Missing body?"); // Change it to a return stmt (Avoid dealloc/alloc of all el.) *(CS->body_begin() + foundAtPos) = m_Sema->ActOnReturnStmt(lastExpr->getExprLoc(), lastExpr).take(); } } else if (foundAtPos >= 0) { // check for non-void return statement CompoundStmt* CS = cast<CompoundStmt>(FD->getBody()); Stmt* CSS = *(CS->body_begin() + foundAtPos); if (ReturnStmt* RS = dyn_cast<ReturnStmt>(CSS)) { if (Expr* RetV = RS->getRetValue()) { QualType RetTy = RetV->getType(); // 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 (RetTy->isVoidType()) { ImplicitCastExpr* VoidCast = dyn_cast<ImplicitCastExpr>(RetV); if (VoidCast) { RS->setRetValue(VoidCast->getSubExpr()); RetTy = VoidCast->getSubExpr()->getType(); } } if (!RetTy->isVoidType() && RetTy.isTriviallyCopyableType(*m_Context)) { Sema::ContextRAII pushedDC(*m_Sema, FD); FunctionProtoType::ExtProtoInfo EPI; QualType FnTy = m_Context->getFunctionType(RetTy, llvm::ArrayRef<QualType>(), EPI); FD->setType(FnTy); } // not returning void } // have return value } // is a return statement } // have a statement }
SVal StoreManager::evalDynamicCast(SVal Base, QualType DerivedType, bool &Failed) { Failed = false; loc::MemRegionVal *BaseRegVal = dyn_cast<loc::MemRegionVal>(&Base); if (!BaseRegVal) return UnknownVal(); const MemRegion *BaseRegion = BaseRegVal->stripCasts(/*StripBases=*/false); // Assume the derived class is a pointer or a reference to a CXX record. DerivedType = DerivedType->getPointeeType(); assert(!DerivedType.isNull()); const CXXRecordDecl *DerivedDecl = DerivedType->getAsCXXRecordDecl(); if (!DerivedDecl && !DerivedType->isVoidType()) return UnknownVal(); // Drill down the CXXBaseObject chains, which represent upcasts (casts from // derived to base). const MemRegion *SR = BaseRegion; while (const TypedRegion *TSR = dyn_cast_or_null<TypedRegion>(SR)) { QualType BaseType = TSR->getLocationType()->getPointeeType(); assert(!BaseType.isNull()); const CXXRecordDecl *SRDecl = BaseType->getAsCXXRecordDecl(); if (!SRDecl) return UnknownVal(); // If found the derived class, the cast succeeds. if (SRDecl == DerivedDecl) return loc::MemRegionVal(TSR); if (!DerivedType->isVoidType()) { // Static upcasts are marked as DerivedToBase casts by Sema, so this will // only happen when multiple or virtual inheritance is involved. CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true, /*DetectVirtual=*/false); if (SRDecl->isDerivedFrom(DerivedDecl, Paths)) return evalDerivedToBase(loc::MemRegionVal(TSR), Paths.front()); } if (const CXXBaseObjectRegion *R = dyn_cast<CXXBaseObjectRegion>(TSR)) // Drill down the chain to get the derived classes. SR = R->getSuperRegion(); else { // We reached the bottom of the hierarchy. // If this is a cast to void*, return the region. if (DerivedType->isVoidType()) return loc::MemRegionVal(TSR); // We did not find the derived class. We we must be casting the base to // derived, so the cast should fail. Failed = true; return UnknownVal(); } } return UnknownVal(); }
void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const { const Expr *RetE = RS->getRetValue(); if (!RetE) return; SVal RetVal = C.getSVal(RetE); const StackFrameContext *SFC = C.getStackFrame(); QualType RT = CallEvent::getDeclaredResultType(SFC->getDecl()); if (RetVal.isUndef()) { // "return;" is modeled to evaluate to an UndefinedVal. Allow UndefinedVal // to be returned in functions returning void to support this pattern: // void foo() { // return; // } // void test() { // return foo(); // } if (RT.isNull() || !RT->isVoidType()) emitUndef(C, RetE); return; } if (RT.isNull()) return; if (RT->isReferenceType()) { checkReference(C, RetE, RetVal.castAs<DefinedOrUnknownSVal>()); return; } }
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(); }
/// \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); }
/// Recursively check if the pointer types are equal modulo const, volatile, /// and restrict qualifiers. Also, assume that all types are similar to 'void'. /// Assumes the input types are canonical. static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy, QualType FromTy) { while (Context.UnwrapSimilarPointerTypes(ToTy, FromTy)) { Qualifiers Quals1, Quals2; ToTy = Context.getUnqualifiedArrayType(ToTy, Quals1); FromTy = Context.getUnqualifiedArrayType(FromTy, Quals2); // Make sure that non-cvr-qualifiers the other qualifiers (e.g., address // spaces) are identical. Quals1.removeCVRQualifiers(); Quals2.removeCVRQualifiers(); if (Quals1 != Quals2) return false; } // If we are casting to void, the 'From' value can be used to represent the // 'To' value. if (ToTy->isVoidType()) return true; if (ToTy != FromTy) return false; return true; }
/// Recursively check if the pointer types are equal modulo const, volatile, /// and restrict qualifiers. Also, assume that all types are similar to 'void'. /// Assumes the input types are canonical. static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy, QualType FromTy) { while (Context.UnwrapSimilarTypes(ToTy, FromTy)) { Qualifiers Quals1, Quals2; ToTy = Context.getUnqualifiedArrayType(ToTy, Quals1); FromTy = Context.getUnqualifiedArrayType(FromTy, Quals2); // Make sure that non-cvr-qualifiers the other qualifiers (e.g., address // spaces) are identical. Quals1.removeCVRQualifiers(); Quals2.removeCVRQualifiers(); if (Quals1 != Quals2) return false; } // If we are casting to void, the 'From' value can be used to represent the // 'To' value. // // FIXME: Doing this after unwrapping the types doesn't make any sense. A // cast from 'int**' to 'void**' is not special in the way that a cast from // 'int*' to 'void*' is. if (ToTy->isVoidType()) return true; if (ToTy != FromTy) return false; return true; }
SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder) const { for (;;) { switch (E->getStmtClass()) { case Stmt::AddrLabelExprClass: return svalBuilder.makeLoc(cast<AddrLabelExpr>(E)); case Stmt::ParenExprClass: // ParenExprs are no-ops. E = cast<ParenExpr>(E)->getSubExpr(); continue; case Stmt::CharacterLiteralClass: { const CharacterLiteral* C = cast<CharacterLiteral>(E); return svalBuilder.makeIntVal(C->getValue(), C->getType()); } case Stmt::CXXBoolLiteralExprClass: { const SVal *X = ExprBindings.lookup(E); if (X) return *X; else return svalBuilder.makeIntVal(cast<CXXBoolLiteralExpr>(E)); } case Stmt::IntegerLiteralClass: { // In C++, this expression may have been bound to a temporary object. SVal const *X = ExprBindings.lookup(E); if (X) return *X; else return svalBuilder.makeIntVal(cast<IntegerLiteral>(E)); } case Stmt::ImplicitCastExprClass: case Stmt::CStyleCastExprClass: { // We blast through no-op casts to get the descendant // subexpression that has a value. const CastExpr* C = cast<CastExpr>(E); QualType CT = C->getType(); if (CT->isVoidType()) return UnknownVal(); if (C->getCastKind() == CK_NoOp) { E = C->getSubExpr(); continue; } break; } case Stmt::ExprWithCleanupsClass: E = cast<ExprWithCleanups>(E)->getSubExpr(); continue; case Stmt::CXXBindTemporaryExprClass: E = cast<CXXBindTemporaryExpr>(E)->getSubExpr(); continue; case Stmt::CXXFunctionalCastExprClass: E = cast<CXXFunctionalCastExpr>(E)->getSubExpr(); continue; // Handle all other Stmt* using a lookup. default: break; }; break; } return lookupExpr(E); }
static bool isVoidPointerToNonConst(QualType T) { if (const PointerType *PT = T->getAs<PointerType>()) { QualType PointeeTy = PT->getPointeeType(); if (PointeeTy.isConstQualified()) return false; return PointeeTy->isVoidType(); } else return false; }
void AdjustedReturnValueChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { // Get the result type of the call. QualType expectedResultTy = CE->getType(); // Fetch the signature of the called function. const ProgramState *state = C.getState(); const LocationContext *LCtx = C.getLocationContext(); SVal V = state->getSVal(CE, LCtx); if (V.isUnknown()) return; // Casting to void? Discard the value. if (expectedResultTy->isVoidType()) { C.addTransition(state->BindExpr(CE, LCtx, UnknownVal())); return; } const MemRegion *callee = state->getSVal(CE->getCallee(), LCtx).getAsRegion(); if (!callee) return; QualType actualResultTy; if (const FunctionTextRegion *FT = dyn_cast<FunctionTextRegion>(callee)) { const FunctionDecl *FD = FT->getDecl(); actualResultTy = FD->getResultType(); } else if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(callee)) { const BlockTextRegion *BR = BD->getCodeRegion(); const BlockPointerType *BT=BR->getLocationType()->getAs<BlockPointerType>(); const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>(); actualResultTy = FT->getResultType(); } // Can this happen? if (actualResultTy.isNull()) return; // For now, ignore references. if (actualResultTy->getAs<ReferenceType>()) return; // Are they the same? if (expectedResultTy != actualResultTy) { // FIXME: Do more checking and actual emit an error. At least performing // the cast avoids some assertion failures elsewhere. SValBuilder &svalBuilder = C.getSValBuilder(); V = svalBuilder.evalCast(V, expectedResultTy, actualResultTy); C.addTransition(state->BindExpr(CE, LCtx, V)); } }
SVal Environment::GetSVal(const Stmt *E, ValueManager& ValMgr) const { for (;;) { switch (E->getStmtClass()) { case Stmt::AddrLabelExprClass: return ValMgr.makeLoc(cast<AddrLabelExpr>(E)); // ParenExprs are no-ops. case Stmt::ParenExprClass: E = cast<ParenExpr>(E)->getSubExpr(); continue; case Stmt::CharacterLiteralClass: { const CharacterLiteral* C = cast<CharacterLiteral>(E); return ValMgr.makeIntVal(C->getValue(), C->getType()); } case Stmt::IntegerLiteralClass: { return ValMgr.makeIntVal(cast<IntegerLiteral>(E)); } // Casts where the source and target type are the same // are no-ops. We blast through these to get the descendant // subexpression that has a value. case Stmt::ImplicitCastExprClass: case Stmt::CStyleCastExprClass: { const CastExpr* C = cast<CastExpr>(E); QualType CT = C->getType(); if (CT->isVoidType()) return UnknownVal(); break; } // Handle all other Stmt* using a lookup. default: break; }; break; } return LookupExpr(E); }
// 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; }
bool GetFuncType(const FunctionType * f, Obj * typ) { Obj returns,parameters; resulttable->newlist(&returns); resulttable->newlist(¶meters); bool valid = true; //decisions about whether this function can be exported or not are delayed until we have seen all the potential problems QualType RT = f->getResultType(); if(!RT->isVoidType()) { Obj rt; if(!GetType(RT,&rt)) { valid = false; } else { rt.push(); returns.addentry(); } } const FunctionProtoType * proto = f->getAs<FunctionProtoType>(); //proto is null if the function was declared without an argument list (e.g. void foo() and not void foo(void)) //we don't support old-style C parameter lists, we just treat them as empty if(proto) { for(size_t i = 0; i < proto->getNumArgs(); i++) { QualType PT = proto->getArgType(i); Obj pt; if(!GetType(PT,&pt)) { valid = false; //keep going with attempting to parse type to make sure we see all the reasons why we cannot support this function } else if(valid) { pt.push(); parameters.addentry(); } } } if(valid) { PushTypeFunction("functype"); parameters.push(); returns.push(); lua_pushboolean(L, proto ? proto->isVariadic() : false); lua_call(L, 3, 1); typ->initFromStack(L,ref_table); } return valid; }
bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, CastExpr::CastKind &Kind, bool FunctionalStyle) { // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (CastTy->isVoidType()) return false; // If the type is dependent, we won't do any other semantic analysis now. if (CastTy->isDependentType() || CastExpr->isTypeDependent()) return false; if (!CastTy->isLValueReferenceType()) DefaultFunctionArrayConversion(CastExpr); // C++ [expr.cast]p5: The conversions performed by // - a const_cast, // - a static_cast, // - a static_cast followed by a const_cast, // - a reinterpret_cast, or // - a reinterpret_cast followed by a const_cast, // can be performed using the cast notation of explicit type conversion. // [...] If a conversion can be interpreted in more than one of the ways // listed above, the interpretation that appears first in the list is used, // even if a cast resulting from that interpretation is ill-formed. // In plain language, this means trying a const_cast ... unsigned msg = diag::err_bad_cxx_cast_generic; TryCastResult tcr = TryConstCast(*this, CastExpr, CastTy, /*CStyle*/true,msg); if (tcr == TC_NotApplicable) { // ... or if that is not possible, a static_cast, ignoring const, ... tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, Kind, msg); if (tcr == TC_NotApplicable) { // ... and finally a reinterpret_cast, ignoring const. tcr = TryReinterpretCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg); } } if (tcr != TC_Success && msg != 0) Diag(R.getBegin(), msg) << (FunctionalStyle ? CT_Functional : CT_CStyle) << CastExpr->getType() << CastTy << R; return tcr != TC_Success; }
// 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; }
void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const { const Expr *RetE = RS->getRetValue(); if (!RetE) return; SVal RetVal = C.getSVal(RetE); const StackFrameContext *SFC = C.getStackFrame(); QualType RT = CallEvent::getDeclaredResultType(SFC->getDecl()); if (RetVal.isUndef()) { // "return;" is modeled to evaluate to an UndefinedVal. Allow UndefinedVal // to be returned in functions returning void to support this pattern: // void foo() { // return; // } // void test() { // return foo(); // } if (!RT.isNull() && RT->isVoidType()) return; // Not all blocks have explicitly-specified return types; if the return type // is not available, but the return value expression has 'void' type, assume // Sema already checked it. if (RT.isNull() && isa<BlockDecl>(SFC->getDecl()) && RetE->getType()->isVoidType()) return; emitUndef(C, RetE); return; } if (RT.isNull()) return; if (RT->isReferenceType()) { checkReference(C, RetE, RetVal.castAs<DefinedOrUnknownSVal>()); return; } }
/// CheckStaticCast - Check that a static_cast\<DestType\>(SrcExpr) is valid. /// Refer to C++ 5.2.9 for details. Static casts are mostly used for making /// implicit conversions explicit and getting rid of data loss warnings. void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, CastExpr::CastKind &Kind) { // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (DestType->isVoidType()) { return; } if (!DestType->isLValueReferenceType()) Self.DefaultFunctionArrayConversion(SrcExpr); unsigned msg = diag::err_bad_cxx_cast_generic; if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, Kind, msg) != TC_Success && msg != 0) Self.Diag(OpRange.getBegin(), msg) << CT_Static << SrcExpr->getType() << DestType << OpRange; }
/// 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)); }
/// CheckSpecifiedExceptionType - Check if the given type is valid in an /// exception specification. Incomplete types, or pointers to incomplete types /// other than void are not allowed. bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) { // This check (and the similar one below) deals with issue 437, that changes // C++ 9.2p2 this way: // Within the class member-specification, the class is regarded as complete // within function bodies, default arguments, exception-specifications, and // constructor ctor-initializers (including such things in nested classes). if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined()) return false; // C++ 15.4p2: A type denoted in an exception-specification shall not denote // an incomplete type. if (RequireCompleteType(Range.getBegin(), T, PDiag(diag::err_incomplete_in_exception_spec) << /*direct*/0 << Range)) return true; // C++ 15.4p2: A type denoted in an exception-specification shall not denote // an incomplete type a pointer or reference to an incomplete type, other // than (cv) void*. int kind; if (const PointerType* IT = T->getAs<PointerType>()) { T = IT->getPointeeType(); kind = 1; } else if (const ReferenceType* IT = T->getAs<ReferenceType>()) { T = IT->getPointeeType(); kind = 2; } else return false; // Again as before if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined()) return false; if (!T->isVoidType() && RequireCompleteType(Range.getBegin(), T, PDiag(diag::err_incomplete_in_exception_spec) << kind << Range)) return true; return false; }
void CastToStructChecker::checkPreStmt(const CastExpr *CE, CheckerContext &C) const { const Expr *E = CE->getSubExpr(); ASTContext &Ctx = C.getASTContext(); QualType OrigTy = Ctx.getCanonicalType(E->getType()); QualType ToTy = Ctx.getCanonicalType(CE->getType()); const PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr()); const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr()); if (!ToPTy || !OrigPTy) return; QualType OrigPointeeTy = OrigPTy->getPointeeType(); QualType ToPointeeTy = ToPTy->getPointeeType(); if (!ToPointeeTy->isStructureOrClassType()) return; // We allow cast from void*. if (OrigPointeeTy->isVoidType()) return; // Now the cast-to-type is struct pointer, the original type is not void*. if (!OrigPointeeTy->isRecordType()) { if (ExplodedNode *N = C.addTransition()) { if (!BT) BT.reset( new BuiltinBug(this, "Cast from non-struct type to struct type", "Casting a non-structure type to a structure type " "and accessing a field can lead to memory access " "errors or data corruption.")); BugReport *R = new BugReport(*BT,BT->getDescription(), N); R->addRange(CE->getSourceRange()); C.emitReport(R); } } }
Optional<SVal> GenericTaintChecker::getPointedToSVal(CheckerContext &C, const Expr *Arg) { ProgramStateRef State = C.getState(); SVal AddrVal = C.getSVal(Arg->IgnoreParens()); if (AddrVal.isUnknownOrUndef()) return None; Optional<Loc> AddrLoc = AddrVal.getAs<Loc>(); if (!AddrLoc) return None; QualType ArgTy = Arg->getType().getCanonicalType(); if (!ArgTy->isPointerType()) return None; QualType ValTy = ArgTy->getPointeeType(); // Do not dereference void pointers. Treat them as byte pointers instead. // FIXME: we might want to consider more than just the first byte. if (ValTy->isVoidType()) ValTy = C.getASTContext().CharTy; return State->getSVal(*AddrLoc, ValTy); }
bool GetFuncType(const FunctionType * f, Obj * typ) { Obj returntype,parameters; resulttable->newlist(¶meters); bool valid = true; //decisions about whether this function can be exported or not are delayed until we have seen all the potential problems #if LLVM_VERSION <= 34 QualType RT = f->getResultType(); #else QualType RT = f->getReturnType(); #endif if(RT->isVoidType()) { PushTypeField("unit"); returntype.initFromStack(L, ref_table); } else { if(!GetType(RT,&returntype)) valid = false; } const FunctionProtoType * proto = f->getAs<FunctionProtoType>(); //proto is null if the function was declared without an argument list (e.g. void foo() and not void foo(void)) //we don't support old-style C parameter lists, we just treat them as empty if(proto) { #if LLVM_VERSION >= 35 for(size_t i = 0; i < proto->getNumParams(); i++) { QualType PT = proto->getParamType(i); #else for(size_t i = 0; i < proto->getNumArgs(); i++) { QualType PT = proto->getArgType(i); #endif Obj pt; if(!GetType(PT,&pt)) { valid = false; //keep going with attempting to parse type to make sure we see all the reasons why we cannot support this function } else if(valid) { pt.push(); parameters.addentry(); } } } if(valid) { PushTypeField("functype"); parameters.push(); returntype.push(); lua_pushboolean(L, proto ? proto->isVariadic() : false); lua_call(L, 3, 1); typ->initFromStack(L,ref_table); } return valid; } bool TraverseFunctionDecl(FunctionDecl *f) { // Function name DeclarationName DeclName = f->getNameInfo().getName(); std::string FuncName = DeclName.getAsString(); const FunctionType * fntyp = f->getType()->getAs<FunctionType>(); if(!fntyp) return true; if(f->getStorageClass() == clang::SC_Static) { ImportError("cannot import static functions."); SetErrorReport(FuncName.c_str()); return true; } Obj typ; if(!GetFuncType(fntyp,&typ)) { SetErrorReport(FuncName.c_str()); return true; } std::string InternalName = FuncName; AsmLabelAttr * asmlabel = f->getAttr<AsmLabelAttr>(); if(asmlabel) { InternalName = asmlabel->getLabel(); #ifndef __linux__ //In OSX and Windows LLVM mangles assembler labels by adding a '\01' prefix InternalName.insert(InternalName.begin(), '\01'); #endif } CreateFunction(FuncName,InternalName,&typ); KeepFunctionLive(f);//make sure this function is live in codegen by creating a dummy reference to it (void) is to suppress unused warnings return true; }
void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Constant *CalleePtr, const ThunkInfo *Thunk) { assert(isa<CXXMethodDecl>(CurGD.getDecl()) && "Please use a new CGF for this thunk"); const CXXMethodDecl *MD = cast<CXXMethodDecl>(CurGD.getDecl()); // Adjust the 'this' pointer if necessary llvm::Value *AdjustedThisPtr = Thunk ? CGM.getCXXABI().performThisAdjustment( *this, LoadCXXThisAddress(), Thunk->This) : LoadCXXThis(); if (CurFnInfo->usesInAlloca()) { // We don't handle return adjusting thunks, because they require us to call // the copy constructor. For now, fall through and pretend the return // adjustment was empty so we don't crash. if (Thunk && !Thunk->Return.isEmpty()) { CGM.ErrorUnsupported( MD, "non-trivial argument copy for return-adjusting thunk"); } EmitMustTailThunk(MD, AdjustedThisPtr, CalleePtr); return; } // Start building CallArgs. CallArgList CallArgs; QualType ThisType = MD->getThisType(getContext()); CallArgs.add(RValue::get(AdjustedThisPtr), ThisType); if (isa<CXXDestructorDecl>(MD)) CGM.getCXXABI().adjustCallArgsForDestructorThunk(*this, CurGD, CallArgs); #ifndef NDEBUG unsigned PrefixArgs = CallArgs.size() - 1; #endif // Add the rest of the arguments. for (const ParmVarDecl *PD : MD->parameters()) EmitDelegateCallArg(CallArgs, PD, SourceLocation()); const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); #ifndef NDEBUG const CGFunctionInfo &CallFnInfo = CGM.getTypes().arrangeCXXMethodCall( CallArgs, FPT, RequiredArgs::forPrototypePlus(FPT, 1, MD), PrefixArgs); assert(CallFnInfo.getRegParm() == CurFnInfo->getRegParm() && CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() && CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention()); assert(isa<CXXDestructorDecl>(MD) || // ignore dtor return types similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(), CurFnInfo->getReturnInfo(), CurFnInfo->getReturnType())); assert(CallFnInfo.arg_size() == CurFnInfo->arg_size()); for (unsigned i = 0, e = CurFnInfo->arg_size(); i != e; ++i) assert(similar(CallFnInfo.arg_begin()[i].info, CallFnInfo.arg_begin()[i].type, CurFnInfo->arg_begin()[i].info, CurFnInfo->arg_begin()[i].type)); #endif // Determine whether we have a return value slot to use. QualType ResultType = CGM.getCXXABI().HasThisReturn(CurGD) ? ThisType : CGM.getCXXABI().hasMostDerivedReturn(CurGD) ? CGM.getContext().VoidPtrTy : FPT->getReturnType(); ReturnValueSlot Slot; if (!ResultType->isVoidType() && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && !hasScalarEvaluationKind(CurFnInfo->getReturnType())) Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified()); // Now emit our call. llvm::Instruction *CallOrInvoke; CGCallee Callee = CGCallee::forDirect(CalleePtr, MD); RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, &CallOrInvoke); // Consider return adjustment if we have ThunkInfo. if (Thunk && !Thunk->Return.isEmpty()) RV = PerformReturnAdjustment(*this, ResultType, RV, *Thunk); else if (llvm::CallInst* Call = dyn_cast<llvm::CallInst>(CallOrInvoke)) Call->setTailCallKind(llvm::CallInst::TCK_Tail); // Emit return. if (!ResultType->isVoidType() && Slot.isNull()) CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType); // Disable the final ARC autorelease. AutoreleaseResult = false; FinishThunk(); }
void CodeGenFunction::EmitCallAndReturnForThunk(GlobalDecl GD, llvm::Value *Callee, const ThunkInfo *Thunk) { assert(isa<CXXMethodDecl>(CurGD.getDecl()) && "Please use a new CGF for this thunk"); const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); // Adjust the 'this' pointer if necessary llvm::Value *AdjustedThisPtr = Thunk ? CGM.getCXXABI().performThisAdjustment( *this, LoadCXXThis(), Thunk->This) : LoadCXXThis(); // Start building CallArgs. CallArgList CallArgs; QualType ThisType = MD->getThisType(getContext()); CallArgs.add(RValue::get(AdjustedThisPtr), ThisType); if (isa<CXXDestructorDecl>(MD)) CGM.getCXXABI().adjustCallArgsForDestructorThunk(*this, GD, CallArgs); // Add the rest of the arguments. for (FunctionDecl::param_const_iterator I = MD->param_begin(), E = MD->param_end(); I != E; ++I) EmitDelegateCallArg(CallArgs, *I, (*I)->getLocStart()); const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); #ifndef NDEBUG const CGFunctionInfo &CallFnInfo = CGM.getTypes().arrangeCXXMethodCall(CallArgs, FPT, RequiredArgs::forPrototypePlus(FPT, 1)); assert(CallFnInfo.getRegParm() == CurFnInfo->getRegParm() && CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() && CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention()); assert(isa<CXXDestructorDecl>(MD) || // ignore dtor return types similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(), CurFnInfo->getReturnInfo(), CurFnInfo->getReturnType())); assert(CallFnInfo.arg_size() == CurFnInfo->arg_size()); for (unsigned i = 0, e = CurFnInfo->arg_size(); i != e; ++i) assert(similar(CallFnInfo.arg_begin()[i].info, CallFnInfo.arg_begin()[i].type, CurFnInfo->arg_begin()[i].info, CurFnInfo->arg_begin()[i].type)); #endif // Determine whether we have a return value slot to use. QualType ResultType = CGM.getCXXABI().HasThisReturn(GD) ? ThisType : FPT->getReturnType(); ReturnValueSlot Slot; if (!ResultType->isVoidType() && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && !hasScalarEvaluationKind(CurFnInfo->getReturnType())) Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified()); // Now emit our call. RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, MD); // Consider return adjustment if we have ThunkInfo. if (Thunk && !Thunk->Return.isEmpty()) RV = PerformReturnAdjustment(*this, ResultType, RV, *Thunk); // Emit return. if (!ResultType->isVoidType() && Slot.isNull()) CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType); // Disable the final ARC autorelease. AutoreleaseResult = false; FinishFunction(); }
clang::analyze_format_string::ArgType::MatchKind ArgType::matchesType(ASTContext &C, QualType argTy) const { if (Ptr) { // It has to be a pointer. const PointerType *PT = argTy->getAs<PointerType>(); if (!PT) return NoMatch; // We cannot write through a const qualified pointer. if (PT->getPointeeType().isConstQualified()) return NoMatch; argTy = PT->getPointeeType(); } switch (K) { case InvalidTy: llvm_unreachable("ArgType must be valid"); case UnknownTy: return Match; case AnyCharTy: { if (const EnumType *ETy = argTy->getAs<EnumType>()) argTy = ETy->getDecl()->getIntegerType(); if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) switch (BT->getKind()) { default: break; case BuiltinType::Char_S: case BuiltinType::SChar: case BuiltinType::UChar: case BuiltinType::Char_U: return Match; } return NoMatch; } case SpecificTy: { if (const EnumType *ETy = argTy->getAs<EnumType>()) argTy = ETy->getDecl()->getIntegerType(); argTy = C.getCanonicalType(argTy).getUnqualifiedType(); if (T == argTy) return Match; // Check for "compatible types". if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) switch (BT->getKind()) { default: break; case BuiltinType::Char_S: case BuiltinType::SChar: case BuiltinType::Char_U: case BuiltinType::UChar: return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match : NoMatch; case BuiltinType::Short: return T == C.UnsignedShortTy ? Match : NoMatch; case BuiltinType::UShort: return T == C.ShortTy ? Match : NoMatch; case BuiltinType::Int: return T == C.UnsignedIntTy ? Match : NoMatch; case BuiltinType::UInt: return T == C.IntTy ? Match : NoMatch; case BuiltinType::Long: return T == C.UnsignedLongTy ? Match : NoMatch; case BuiltinType::ULong: return T == C.LongTy ? Match : NoMatch; case BuiltinType::LongLong: return T == C.UnsignedLongLongTy ? Match : NoMatch; case BuiltinType::ULongLong: return T == C.LongLongTy ? Match : NoMatch; } return NoMatch; } case CStrTy: { const PointerType *PT = argTy->getAs<PointerType>(); if (!PT) return NoMatch; QualType pointeeTy = PT->getPointeeType(); if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>()) switch (BT->getKind()) { case BuiltinType::Void: case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::Char_S: case BuiltinType::SChar: return Match; default: break; } return NoMatch; } case WCStrTy: { const PointerType *PT = argTy->getAs<PointerType>(); if (!PT) return NoMatch; QualType pointeeTy = C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); return pointeeTy == C.getWideCharType() ? Match : NoMatch; } case WIntTy: { QualType PromoArg = argTy->isPromotableIntegerType() ? C.getPromotedIntegerType(argTy) : argTy; QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType(); PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType(); // If the promoted argument is the corresponding signed type of the // wint_t type, then it should match. if (PromoArg->hasSignedIntegerRepresentation() && C.getCorrespondingUnsignedType(PromoArg) == WInt) return Match; return WInt == PromoArg ? Match : NoMatch; } case CPointerTy: if (argTy->isVoidPointerType()) { return Match; } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() || argTy->isBlockPointerType() || argTy->isNullPtrType()) { return NoMatchPedantic; } else { return NoMatch; } case ObjCPointerTy: { if (argTy->getAs<ObjCObjectPointerType>() || argTy->getAs<BlockPointerType>()) return Match; // Handle implicit toll-free bridging. if (const PointerType *PT = argTy->getAs<PointerType>()) { // Things such as CFTypeRef are really just opaque pointers // to C structs representing CF types that can often be bridged // to Objective-C objects. Since the compiler doesn't know which // structs can be toll-free bridged, we just accept them all. QualType pointee = PT->getPointeeType(); if (pointee->getAsStructureType() || pointee->isVoidType()) return Match; } return NoMatch; } } llvm_unreachable("Invalid ArgType Kind!"); }
Expr* ValueExtractionSynthesizer::SynthesizeSVRInit(Expr* E) { if (!m_gClingVD) FindAndCacheRuntimeDecls(); // Build a reference to gCling ExprResult gClingDRE = m_Sema->BuildDeclRefExpr(m_gClingVD, m_Context->VoidPtrTy, VK_RValue, SourceLocation()); // We have the wrapper as Sema's CurContext FunctionDecl* FD = cast<FunctionDecl>(m_Sema->CurContext); ExprWithCleanups* Cleanups = 0; // In case of ExprWithCleanups we need to extend its 'scope' to the call. if (E && isa<ExprWithCleanups>(E)) { Cleanups = cast<ExprWithCleanups>(E); E = Cleanups->getSubExpr(); } // Build a reference to Value* in the wrapper, should be // the only argument of the wrapper. SourceLocation locStart = (E) ? E->getLocStart() : FD->getLocStart(); SourceLocation locEnd = (E) ? E->getLocEnd() : FD->getLocEnd(); ExprResult wrapperSVRDRE = m_Sema->BuildDeclRefExpr(FD->getParamDecl(0), m_Context->VoidPtrTy, VK_RValue, locStart); QualType ETy = (E) ? E->getType() : m_Context->VoidTy; QualType desugaredTy = ETy.getDesugaredType(*m_Context); // The expr result is transported as reference, pointer, array, float etc // based on the desugared type. We should still expose the typedef'ed // (sugared) type to the cling::Value. if (desugaredTy->isRecordType() && E->getValueKind() == VK_LValue) { // returning a lvalue (not a temporary): the value should contain // a reference to the lvalue instead of copying it. desugaredTy = m_Context->getLValueReferenceType(desugaredTy); ETy = m_Context->getLValueReferenceType(ETy); } Expr* ETyVP = utils::Synthesize::CStyleCastPtrExpr(m_Sema, m_Context->VoidPtrTy, (uint64_t)ETy.getAsOpaquePtr()); Expr* ETransaction = utils::Synthesize::CStyleCastPtrExpr(m_Sema, m_Context->VoidPtrTy, (uint64_t)getTransaction()); llvm::SmallVector<Expr*, 6> CallArgs; CallArgs.push_back(gClingDRE.take()); CallArgs.push_back(wrapperSVRDRE.take()); CallArgs.push_back(ETyVP); CallArgs.push_back(ETransaction); ExprResult Call; SourceLocation noLoc; if (desugaredTy->isVoidType()) { // In cases where the cling::Value gets reused we need to reset the // previous settings to void. // We need to synthesize setValueNoAlloc(...), E, because we still need // to run E. // FIXME: Suboptimal: this discards the already created AST nodes. QualType vpQT = m_Context->VoidPtrTy; QualType vQT = m_Context->VoidTy; Expr* vpQTVP = utils::Synthesize::CStyleCastPtrExpr(m_Sema, vpQT, (uint64_t)vQT.getAsOpaquePtr()); CallArgs[2] = vpQTVP; Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedNoAlloc, locStart, CallArgs, locEnd); if (E) Call = m_Sema->CreateBuiltinBinOp(locStart, BO_Comma, Call.take(), E); } else if (desugaredTy->isRecordType() || desugaredTy->isConstantArrayType()){ // 2) object types : // check existance of copy constructor before call if (!availableCopyConstructor(desugaredTy, m_Sema)) return E; // call new (setValueWithAlloc(gCling, &SVR, ETy)) (E) Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedWithAlloc, locStart, CallArgs, locEnd); Expr* placement = Call.take(); if (const ConstantArrayType* constArray = dyn_cast<ConstantArrayType>(desugaredTy.getTypePtr())) { CallArgs.clear(); CallArgs.push_back(E); CallArgs.push_back(placement); uint64_t arrSize = m_Context->getConstantArrayElementCount(constArray); Expr* arrSizeExpr = utils::Synthesize::IntegerLiteralExpr(*m_Context, arrSize); CallArgs.push_back(arrSizeExpr); // 2.1) arrays: // call copyArray(T* src, void* placement, int size) Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedCopyArray, locStart, CallArgs, locEnd); } else { TypeSourceInfo* ETSI = m_Context->getTrivialTypeSourceInfo(ETy, noLoc); Call = m_Sema->BuildCXXNew(E->getSourceRange(), /*useGlobal ::*/true, /*placementLParen*/ noLoc, MultiExprArg(placement), /*placementRParen*/ noLoc, /*TypeIdParens*/ SourceRange(), /*allocType*/ ETSI->getType(), /*allocTypeInfo*/ETSI, /*arraySize*/0, /*directInitRange*/E->getSourceRange(), /*initializer*/E, /*mayContainAuto*/false ); } } else if (desugaredTy->isIntegralOrEnumerationType() || desugaredTy->isReferenceType() || desugaredTy->isPointerType() || desugaredTy->isFloatingType()) { if (desugaredTy->isIntegralOrEnumerationType()) { // 1) enum, integral, float, double, referece, pointer types : // call to cling::internal::setValueNoAlloc(...); // If the type is enum or integral we need to force-cast it into // uint64 in order to pick up the correct overload. if (desugaredTy->isIntegralOrEnumerationType()) { QualType UInt64Ty = m_Context->UnsignedLongLongTy; TypeSourceInfo* TSI = m_Context->getTrivialTypeSourceInfo(UInt64Ty, noLoc); Expr* castedE = m_Sema->BuildCStyleCastExpr(noLoc, TSI, noLoc, E).take(); CallArgs.push_back(castedE); } } else if (desugaredTy->isReferenceType()) { // we need to get the address of the references Expr* AddrOfE = m_Sema->BuildUnaryOp(/*Scope*/0, noLoc, UO_AddrOf, E).take(); CallArgs.push_back(AddrOfE); } else if (desugaredTy->isPointerType()) { // function pointers need explicit void* cast. QualType VoidPtrTy = m_Context->VoidPtrTy; TypeSourceInfo* TSI = m_Context->getTrivialTypeSourceInfo(VoidPtrTy, noLoc); Expr* castedE = m_Sema->BuildCStyleCastExpr(noLoc, TSI, noLoc, E).take(); CallArgs.push_back(castedE); } else if (desugaredTy->isFloatingType()) { // floats and double will fall naturally in the correct // case, because of the overload resolution. CallArgs.push_back(E); } Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedNoAlloc, locStart, CallArgs, locEnd); } else assert(0 && "Unhandled code path?"); assert(!Call.isInvalid() && "Invalid Call"); // Extend the scope of the temporary cleaner if applicable. if (Cleanups) { Cleanups->setSubExpr(Call.take()); Cleanups->setValueKind(Call.take()->getValueKind()); Cleanups->setType(Call.take()->getType()); return Cleanups; } return Call.take(); }
llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE) { QualType CastTy = DCE->getTypeAsWritten(); QualType InnerType = CastTy->getPointeeType(); QualType ArgTy = DCE->getSubExpr()->getType(); const llvm::Type *LArgTy = ConvertType(ArgTy); const llvm::Type *LTy = ConvertType(DCE->getType()); bool CanBeZero = false; bool ToVoid = false; bool ThrowOnBad = false; if (CastTy->isPointerType()) { // FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this CanBeZero = true; if (InnerType->isVoidType()) ToVoid = true; } else { LTy = LTy->getPointerTo(); ThrowOnBad = true; } CXXRecordDecl *SrcTy; QualType Ty = ArgTy; if (ArgTy.getTypePtr()->isPointerType() || ArgTy.getTypePtr()->isReferenceType()) Ty = Ty.getTypePtr()->getPointeeType(); CanQualType CanTy = CGM.getContext().getCanonicalType(Ty); Ty = CanTy.getUnqualifiedType(); SrcTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl()); llvm::BasicBlock *ContBlock = createBasicBlock(); llvm::BasicBlock *NullBlock = 0; llvm::BasicBlock *NonZeroBlock = 0; if (CanBeZero) { NonZeroBlock = createBasicBlock(); NullBlock = createBasicBlock(); llvm::Value *Zero = llvm::Constant::getNullValue(LArgTy); Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero), NonZeroBlock, NullBlock); EmitBlock(NonZeroBlock); } llvm::BasicBlock *BadCastBlock = 0; const llvm::Type *PtrDiffTy = ConvertType(getContext().getSizeType()); // See if this is a dynamic_cast(void*) if (ToVoid) { llvm::Value *This = V; V = Builder.CreateBitCast(This, PtrDiffTy->getPointerTo()->getPointerTo()); V = Builder.CreateLoad(V, "vtable"); V = Builder.CreateConstInBoundsGEP1_64(V, -2ULL); V = Builder.CreateLoad(V, "offset to top"); This = Builder.CreateBitCast(This, llvm::Type::getInt8PtrTy(VMContext)); V = Builder.CreateInBoundsGEP(This, V); V = Builder.CreateBitCast(V, LTy); } else { /// Call __dynamic_cast const llvm::Type *ResultType = llvm::Type::getInt8PtrTy(VMContext); const llvm::FunctionType *FTy; std::vector<const llvm::Type*> ArgTys; const llvm::Type *PtrToInt8Ty = llvm::Type::getInt8Ty(VMContext)->getPointerTo(); ArgTys.push_back(PtrToInt8Ty); ArgTys.push_back(PtrToInt8Ty); ArgTys.push_back(PtrToInt8Ty); ArgTys.push_back(PtrDiffTy); FTy = llvm::FunctionType::get(ResultType, ArgTys, false); CXXRecordDecl *DstTy; Ty = CastTy.getTypePtr()->getPointeeType(); CanTy = CGM.getContext().getCanonicalType(Ty); Ty = CanTy.getUnqualifiedType(); DstTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl()); // FIXME: Calculate better hint. llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL); llvm::Value *SrcArg = CGM.GenerateRttiRef(SrcTy); llvm::Value *DstArg = CGM.GenerateRttiRef(DstTy); V = Builder.CreateBitCast(V, PtrToInt8Ty); V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"), V, SrcArg, DstArg, hint); V = Builder.CreateBitCast(V, LTy); if (ThrowOnBad) { BadCastBlock = createBasicBlock(); llvm::Value *Zero = llvm::Constant::getNullValue(LTy); Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero), ContBlock, BadCastBlock); EmitBlock(BadCastBlock); /// Call __cxa_bad_cast ResultType = llvm::Type::getVoidTy(VMContext); const llvm::FunctionType *FBadTy; FBadTy = llvm::FunctionType::get(ResultType, false); llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast"); Builder.CreateCall(F)->setDoesNotReturn(); Builder.CreateUnreachable(); } } if (CanBeZero) { Builder.CreateBr(ContBlock); EmitBlock(NullBlock); Builder.CreateBr(ContBlock); } EmitBlock(ContBlock); if (CanBeZero) { llvm::PHINode *PHI = Builder.CreatePHI(LTy); PHI->reserveOperandSpace(2); PHI->addIncoming(V, NonZeroBlock); PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock); V = PHI; } return V; }
bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C, const CallExpr *CE) { // Not enough arguments to match OSAtomicCompareAndSwap? if (CE->getNumArgs() != 3) return false; ASTContext &Ctx = C.getASTContext(); const Expr *oldValueExpr = CE->getArg(0); QualType oldValueType = Ctx.getCanonicalType(oldValueExpr->getType()); const Expr *newValueExpr = CE->getArg(1); QualType newValueType = Ctx.getCanonicalType(newValueExpr->getType()); // Do the types of 'oldValue' and 'newValue' match? if (oldValueType != newValueType) return false; const Expr *theValueExpr = CE->getArg(2); const PointerType *theValueType=theValueExpr->getType()->getAs<PointerType>(); // theValueType not a pointer? if (!theValueType) return false; QualType theValueTypePointee = Ctx.getCanonicalType(theValueType->getPointeeType()).getUnqualifiedType(); // The pointee must match newValueType and oldValueType. if (theValueTypePointee != newValueType) return false; static SimpleProgramPointTag OSAtomicLoadTag("OSAtomicChecker : Load"); static SimpleProgramPointTag OSAtomicStoreTag("OSAtomicChecker : Store"); // Load 'theValue'. ExprEngine &Engine = C.getEngine(); const ProgramState *state = C.getState(); ExplodedNodeSet Tmp; SVal location = state->getSVal(theValueExpr); // Here we should use the value type of the region as the load type, because // we are simulating the semantics of the function, not the semantics of // passing argument. So the type of theValue expr is not we are loading. // But usually the type of the varregion is not the type we want either, // we still need to do a CastRetrievedVal in store manager. So actually this // LoadTy specifying can be omitted. But we put it here to emphasize the // semantics. QualType LoadTy; if (const TypedValueRegion *TR = dyn_cast_or_null<TypedValueRegion>(location.getAsRegion())) { LoadTy = TR->getValueType(); } Engine.evalLoad(Tmp, theValueExpr, C.getPredecessor(), state, location, &OSAtomicLoadTag, LoadTy); if (Tmp.empty()) { // If no nodes were generated, other checkers must generated sinks. But // since the builder state was restored, we set it manually to prevent // auto transition. // FIXME: there should be a better approach. C.getNodeBuilder().BuildSinks = true; return true; } for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) { ExplodedNode *N = *I; const ProgramState *stateLoad = N->getState(); // Use direct bindings from the environment since we are forcing a load // from a location that the Environment would typically not be used // to bind a value. SVal theValueVal_untested = stateLoad->getSVal(theValueExpr, true); SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr); // FIXME: Issue an error. if (theValueVal_untested.isUndef() || oldValueVal_untested.isUndef()) { return false; } DefinedOrUnknownSVal theValueVal = cast<DefinedOrUnknownSVal>(theValueVal_untested); DefinedOrUnknownSVal oldValueVal = cast<DefinedOrUnknownSVal>(oldValueVal_untested); SValBuilder &svalBuilder = Engine.getSValBuilder(); // Perform the comparison. DefinedOrUnknownSVal Cmp = svalBuilder.evalEQ(stateLoad,theValueVal,oldValueVal); const ProgramState *stateEqual = stateLoad->assume(Cmp, true); // Were they equal? if (stateEqual) { // Perform the store. ExplodedNodeSet TmpStore; SVal val = stateEqual->getSVal(newValueExpr); // Handle implicit value casts. if (const TypedValueRegion *R = dyn_cast_or_null<TypedValueRegion>(location.getAsRegion())) { val = svalBuilder.evalCast(val,R->getValueType(), newValueExpr->getType()); } Engine.evalStore(TmpStore, NULL, theValueExpr, N, stateEqual, location, val, &OSAtomicStoreTag); if (TmpStore.empty()) { // If no nodes were generated, other checkers must generated sinks. But // since the builder state was restored, we set it manually to prevent // auto transition. // FIXME: there should be a better approach. C.getNodeBuilder().BuildSinks = true; return true; } // Now bind the result of the comparison. for (ExplodedNodeSet::iterator I2 = TmpStore.begin(), E2 = TmpStore.end(); I2 != E2; ++I2) { ExplodedNode *predNew = *I2; const ProgramState *stateNew = predNew->getState(); // Check for 'void' return type if we have a bogus function prototype. SVal Res = UnknownVal(); QualType T = CE->getType(); if (!T->isVoidType()) Res = Engine.getSValBuilder().makeTruthVal(true, T); C.generateNode(stateNew->BindExpr(CE, Res), predNew); } } // Were they not equal? if (const ProgramState *stateNotEqual = stateLoad->assume(Cmp, false)) { // Check for 'void' return type if we have a bogus function prototype. SVal Res = UnknownVal(); QualType T = CE->getType(); if (!T->isVoidType()) Res = Engine.getSValBuilder().makeTruthVal(false, CE->getType()); C.generateNode(stateNotEqual->BindExpr(CE, Res), N); } } return true; }
/// 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)); }