DefinedOrUnknownSVal SValBuilder::getConjuredHeapSymbolVal(const Expr *E, const LocationContext *LCtx, unsigned VisitCount) { QualType T = E->getType(); assert(Loc::isLocType(T)); assert(SymbolManager::canSymbolicate(T)); if (T->isNullPtrType()) return makeZeroVal(T); SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount); return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym)); }
DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const Stmt *stmt, const LocationContext *LCtx, QualType type, unsigned visitCount) { if (type->isNullPtrType()) return makeZeroVal(type); if (!SymbolManager::canSymbolicate(type)) return UnknownVal(); SymbolRef sym = SymMgr.conjureSymbol(stmt, LCtx, type, visitCount); if (Loc::isLocType(type)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); return nonloc::SymbolVal(sym); }
DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *SymbolTag, const Expr *Ex, const LocationContext *LCtx, unsigned Count) { QualType T = Ex->getType(); if (T->isNullPtrType()) return makeZeroVal(T); // Compute the type of the result. If the expression is not an R-value, the // result should be a location. QualType ExType = Ex->getType(); if (Ex->isGLValue()) T = LCtx->getAnalysisDeclContext()->getASTContext().getPointerType(ExType); return conjureSymbolVal(SymbolTag, Ex, LCtx, T, Count); }
DefinedOrUnknownSVal SValBuilder::getRegionValueSymbolVal(const TypedValueRegion *region) { QualType T = region->getValueType(); if (T->isNullPtrType()) return makeZeroVal(T); if (!SymbolManager::canSymbolicate(T)) return UnknownVal(); SymbolRef sym = SymMgr.getRegionValueSymbol(region); if (Loc::isLocType(T)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); return nonloc::SymbolVal(sym); }
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!"); }
bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const { switch (K) { case InvalidTy: assert(false && "ArgTypeResult must be valid"); return true; case UnknownTy: return true; case SpecificTy: { argTy = C.getCanonicalType(argTy).getUnqualifiedType(); if (T == argTy) return true; // Check for "compatible types". if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) switch (BT->getKind()) { default: break; case BuiltinType::Char_S: case BuiltinType::SChar: return T == C.UnsignedCharTy; case BuiltinType::Char_U: case BuiltinType::UChar: return T == C.SignedCharTy; case BuiltinType::Short: return T == C.UnsignedShortTy; case BuiltinType::UShort: return T == C.ShortTy; case BuiltinType::Int: return T == C.UnsignedIntTy; case BuiltinType::UInt: return T == C.IntTy; case BuiltinType::Long: return T == C.UnsignedLongTy; case BuiltinType::ULong: return T == C.LongTy; case BuiltinType::LongLong: return T == C.UnsignedLongLongTy; case BuiltinType::ULongLong: return T == C.LongLongTy; } return false; } case CStrTy: { const PointerType *PT = argTy->getAs<PointerType>(); if (!PT) return false; 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 true; default: break; } return false; } case WCStrTy: { const PointerType *PT = argTy->getAs<PointerType>(); if (!PT) return false; QualType pointeeTy = C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); return pointeeTy == C.getWCharType(); } case WIntTy: { // Instead of doing a lookup for the definition of 'wint_t' (which // is defined by the system headers) instead see if wchar_t and // the argument type promote to the same type. QualType PromoWChar = C.getWCharType()->isPromotableIntegerType() ? C.getPromotedIntegerType(C.getWCharType()) : C.getWCharType(); QualType PromoArg = argTy->isPromotableIntegerType() ? C.getPromotedIntegerType(argTy) : argTy; PromoWChar = C.getCanonicalType(PromoWChar).getUnqualifiedType(); PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType(); return PromoWChar == PromoArg; } case CPointerTy: return argTy->isPointerType() || argTy->isObjCObjectPointerType() || argTy->isNullPtrType(); case ObjCPointerTy: return argTy->getAs<ObjCObjectPointerType>() != NULL; } // FIXME: Should be unreachable, but Clang is currently emitting // a warning. return false; }
/// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is /// valid. /// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code /// like this: /// char *bytes = reinterpret_cast\<char*\>(int_ptr); void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, const SourceRange &DestRange) { QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType(); DestType = Self.Context.getCanonicalType(DestType); QualType SrcType = SrcExpr->getType(); if (const LValueReferenceType *DestTypeTmp = DestType->getAsLValueReferenceType()) { if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) { // Cannot cast non-lvalue to reference type. Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue) << "reinterpret_cast" << OrigDestType << SrcExpr->getSourceRange(); return; } // C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the // same effect as the conversion *reinterpret_cast<T*>(&x) with the // built-in & and * operators. // This code does this transformation for the checked types. DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); SrcType = Self.Context.getPointerType(SrcType); } else if (const RValueReferenceType *DestTypeTmp = DestType->getAsRValueReferenceType()) { // Both the reference conversion and the rvalue rules apply. Self.DefaultFunctionArrayConversion(SrcExpr); SrcType = SrcExpr->getType(); DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); SrcType = Self.Context.getPointerType(SrcType); } else { // C++ 5.2.10p1: [...] the lvalue-to-rvalue, array-to-pointer, and // function-to-pointer standard conversions are performed on the // expression v. Self.DefaultFunctionArrayConversion(SrcExpr); SrcType = SrcExpr->getType(); } // Canonicalize source for comparison. SrcType = Self.Context.getCanonicalType(SrcType); const MemberPointerType *DestMemPtr = DestType->getAsMemberPointerType(), *SrcMemPtr = SrcType->getAsMemberPointerType(); if (DestMemPtr && SrcMemPtr) { // C++ 5.2.10p9: An rvalue of type "pointer to member of X of type T1" // can be explicitly converted to an rvalue of type "pointer to member // of Y of type T2" if T1 and T2 are both function types or both object // types. if (DestMemPtr->getPointeeType()->isFunctionType() != SrcMemPtr->getPointeeType()->isFunctionType()) { Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; return; } // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away // constness. if (CastsAwayConstness(Self, SrcType, DestType)) { Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away) << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; return; } // A valid member pointer cast. return; } // See below for the enumeral issue. if (SrcType->isNullPtrType() && DestType->isIntegralType() && !DestType->isEnumeralType()) { // C++0x 5.2.10p4: A pointer can be explicitly converted to any integral // type large enough to hold it. A value of std::nullptr_t can be // converted to an integral type; the conversion has the same meaning // and validity as a conversion of (void*)0 to the integral type. if (Self.Context.getTypeSize(SrcType) > Self.Context.getTypeSize(DestType)) { Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_small_int) << OrigDestType << DestRange; } return; } bool destIsPtr = DestType->isPointerType(); bool srcIsPtr = SrcType->isPointerType(); if (!destIsPtr && !srcIsPtr) { // Except for std::nullptr_t->integer and lvalue->reference, which are // handled above, at least one of the two arguments must be a pointer. Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; return; } if (SrcType == DestType) { // C++ 5.2.10p2 has a note that mentions that, subject to all other // restrictions, a cast to the same type is allowed. The intent is not // entirely clear here, since all other paragraphs explicitly forbid casts // to the same type. However, the behavior of compilers is pretty consistent // on this point: allow same-type conversion if the involved types are // pointers, disallow otherwise. return; } // Note: Clang treats enumeration types as integral types. If this is ever // changed for C++, the additional check here will be redundant. if (DestType->isIntegralType() && !DestType->isEnumeralType()) { assert(srcIsPtr && "One type must be a pointer"); // C++ 5.2.10p4: A pointer can be explicitly converted to any integral // type large enough to hold it. if (Self.Context.getTypeSize(SrcType) > Self.Context.getTypeSize(DestType)) { Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_small_int) << OrigDestType << DestRange; } return; } if (SrcType->isIntegralType() || SrcType->isEnumeralType()) { assert(destIsPtr && "One type must be a pointer"); // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly // converted to a pointer. return; } if (!destIsPtr || !srcIsPtr) { // With the valid non-pointer conversions out of the way, we can be even // more stringent. Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; return; } // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness. if (CastsAwayConstness(Self, SrcType, DestType)) { Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away) << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; return; } // Not casting away constness, so the only remaining check is for compatible // pointer categories. if (SrcType->isFunctionPointerType()) { if (DestType->isFunctionPointerType()) { // C++ 5.2.10p6: A pointer to a function can be explicitly converted to // a pointer to a function of a different type. return; } // C++0x 5.2.10p8: Converting a pointer to a function into a pointer to // an object type or vice versa is conditionally-supported. // Compilers support it in C++03 too, though, because it's necessary for // casting the return value of dlsym() and GetProcAddress(). // FIXME: Conditionally-supported behavior should be configurable in the // TargetInfo or similar. if (!Self.getLangOptions().CPlusPlus0x) { Self.Diag(OpRange.getBegin(), diag::ext_reinterpret_cast_fn_obj) << OpRange; } return; } if (DestType->isFunctionPointerType()) { // See above. if (!Self.getLangOptions().CPlusPlus0x) { Self.Diag(OpRange.getBegin(), diag::ext_reinterpret_cast_fn_obj) << OpRange; } return; } // C++ 5.2.10p7: A pointer to an object can be explicitly converted to // a pointer to an object of different type. // Void pointers are not specified, but supported by every compiler out there. // So we finish by allowing everything that remains - it's got to be two // object pointers. }
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, (uintptr_t)ETy.getAsOpaquePtr()); // Pass whether to Value::dump() or not: Expr* EVPOn = new (*m_Context) CharacterLiteral(getCompilationOpts().ValuePrinting, CharacterLiteral::Ascii, m_Context->CharTy, SourceLocation()); llvm::SmallVector<Expr*, 6> CallArgs; CallArgs.push_back(gClingDRE.get()); CallArgs.push_back(wrapperSVRDRE.get()); CallArgs.push_back(ETyVP); CallArgs.push_back(EVPOn); ExprResult Call; SourceLocation noLoc = locStart; 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, (uintptr_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.get(), E); } else if (desugaredTy->isRecordType() || desugaredTy->isConstantArrayType() || desugaredTy->isMemberPointerType()) { // 2) object types : // check existence of copy constructor before call if (!desugaredTy->isMemberPointerType() && !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.get(); if (const ConstantArrayType* constArray = dyn_cast<ConstantArrayType>(desugaredTy.getTypePtr())) { CallArgs.clear(); CallArgs.push_back(E); CallArgs.push_back(placement); size_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, size_t size) Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedCopyArray, locStart, CallArgs, locEnd); } else { if (!E->getSourceRange().isValid()) { // We cannot do CXXNewExpr::CallInit (see Sema::BuildCXXNew) but // that's what we want. Fail... return E; } 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 ); // Handle possible cleanups: Call = m_Sema->ActOnFinishFullExpr(Call.get()); } } else { // Mark the current number of arguemnts const size_t nArgs = CallArgs.size(); 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).get(); 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).get(); CallArgs.push_back(AddrOfE); } else if (desugaredTy->isAnyPointerType()) { // 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).get(); CallArgs.push_back(castedE); } else if (desugaredTy->isNullPtrType()) { // nullptr should decay to void* just fine. CallArgs.push_back(E); } else if (desugaredTy->isFloatingType()) { // floats and double will fall naturally in the correct // case, because of the overload resolution. CallArgs.push_back(E); } // Test CallArgs.size to make sure an additional argument (the value) // has been pushed on, if not than we didn't know how to handle the type if (CallArgs.size() > nArgs) { Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedNoAlloc, locStart, CallArgs, locEnd); } else { m_Sema->Diag(locStart, diag::err_unsupported_unknown_any_decl) << utils::TypeName::GetFullyQualifiedName(desugaredTy, *m_Context) << SourceRange(locStart, locEnd); } } assert(!Call.isInvalid() && "Invalid Call"); // Extend the scope of the temporary cleaner if applicable. if (Cleanups) { Cleanups->setSubExpr(Call.get()); Cleanups->setValueKind(Call.get()->getValueKind()); Cleanups->setType(Call.get()->getType()); return Cleanups; } return Call.get(); }