本文整理汇总了C++中QualType::isFunctionPointerType方法的典型用法代码示例。如果您正苦于以下问题:C++ QualType::isFunctionPointerType方法的具体用法?C++ QualType::isFunctionPointerType怎么用?C++ QualType::isFunctionPointerType使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类QualType
的用法示例。
在下文中一共展示了QualType::isFunctionPointerType方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: isCallbackArg
static bool isCallbackArg(SVal V, QualType T) {
// If the parameter is 0, it's harmless.
if (V.isZeroConstant())
return false;
// If a parameter is a block or a callback, assume it can modify pointer.
if (T->isBlockPointerType() ||
T->isFunctionPointerType() ||
T->isObjCSelType())
return true;
// Check if a callback is passed inside a struct (for both, struct passed by
// reference and by value). Dig just one level into the struct for now.
if (isa<PointerType>(T) || isa<ReferenceType>(T))
T = T->getPointeeType();
if (const RecordType *RT = T->getAsStructureType()) {
const RecordDecl *RD = RT->getDecl();
for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
I != E; ++I) {
QualType FieldT = I->getType();
if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType())
return true;
}
}
return false;
}
示例2: isCallback
static bool isCallback(QualType T) {
// If a parameter is a block or a callback, assume it can modify pointer.
if (T->isBlockPointerType() ||
T->isFunctionPointerType() ||
T->isObjCSelType())
return true;
// Check if a callback is passed inside a struct (for both, struct passed by
// reference and by value). Dig just one level into the struct for now.
if (T->isAnyPointerType() || T->isReferenceType())
T = T->getPointeeType();
if (const RecordType *RT = T->getAsStructureType()) {
const RecordDecl *RD = RT->getDecl();
for (const auto *I : RD->fields()) {
QualType FieldT = I->getType();
if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType())
return true;
}
}
return false;
}
示例3: getConjuredSymbolVal
SVal ValueManager::getConjuredSymbolVal(const Expr* E, unsigned Count) {
QualType T = E->getType();
SymbolRef sym = SymMgr.getConjuredSymbol(E, Count);
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
if (T->isFunctionPointerType()) {
return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T));
}
if (Loc::IsLocType(T))
return Loc::MakeVal(MemMgr.getSymbolicRegion(sym));
if (T->isIntegerType() && T->isScalarType())
return makeNonLoc(sym);
return UnknownVal();
}
示例4: getConjuredSymbolVal
SVal ValueManager::getConjuredSymbolVal(const Expr* E, unsigned Count) {
QualType T = E->getType();
if (!SymbolManager::canSymbolicate(T))
return UnknownVal();
SymbolRef sym = SymMgr.getConjuredSymbol(E, Count);
// If T is of function pointer type or a block pointer type, create a
// CodeTextRegion wrapping a symbol.
if (T->isFunctionPointerType() || T->isBlockPointerType())
return loc::MemRegionVal(MemMgr.getCodeTextRegion(sym, T));
if (Loc::IsLocType(T))
return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
return nonloc::SymbolVal(sym);
}
示例5: getRegionValueSymbolVal
SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) {
if (T.isNull()) {
const TypedRegion* TR = cast<TypedRegion>(R);
T = TR->getValueType(SymMgr.getContext());
}
if (!SymbolManager::canSymbolicate(T))
return UnknownVal();
SymbolRef sym = SymMgr.getRegionValueSymbol(R, T);
// If T is of function pointer type or a block pointer type, create a
// CodeTextRegion wrapping that symbol.
if (T->isFunctionPointerType() || T->isBlockPointerType())
return loc::MemRegionVal(MemMgr.getCodeTextRegion(sym, T));
if (Loc::IsLocType(T))
return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
return nonloc::SymbolVal(sym);
}
示例6: getRegionValueSymbolVal
SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R) {
SymbolRef sym = SymMgr.getRegionValueSymbol(R);
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
QualType T = TR->getValueType(SymMgr.getContext());
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
if (T->isFunctionPointerType()) {
return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T));
}
if (Loc::IsLocType(T))
return Loc::MakeVal(MemMgr.getSymbolicRegion(sym));
// Only handle integers for now.
if (T->isIntegerType() && T->isScalarType())
return makeNonLoc(sym);
}
return UnknownVal();
}
示例7: evalCast
// FIXME: should rewrite according to the cast kind.
SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
castTy = Context.getCanonicalType(castTy);
originalTy = Context.getCanonicalType(originalTy);
if (val.isUnknownOrUndef() || castTy == originalTy)
return val;
if (castTy->isBooleanType()) {
if (val.isUnknownOrUndef())
return val;
if (val.isConstant())
return makeTruthVal(!val.isZeroConstant(), castTy);
if (!Loc::isLocType(originalTy) &&
!originalTy->isIntegralOrEnumerationType() &&
!originalTy->isMemberPointerType())
return UnknownVal();
if (SymbolRef Sym = val.getAsSymbol(true)) {
BasicValueFactory &BVF = getBasicValueFactory();
// FIXME: If we had a state here, we could see if the symbol is known to
// be zero, but we don't.
return makeNonLoc(Sym, BO_NE, BVF.getValue(0, Sym->getType()), castTy);
}
// Loc values are not always true, they could be weakly linked functions.
if (Optional<Loc> L = val.getAs<Loc>())
return evalCastFromLoc(*L, castTy);
Loc L = val.castAs<nonloc::LocAsInteger>().getLoc();
return evalCastFromLoc(L, castTy);
}
// For const casts, casts to void, just propagate the value.
if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType())
if (shouldBeModeledWithNoOp(Context, Context.getPointerType(castTy),
Context.getPointerType(originalTy)))
return val;
// Check for casts from pointers to integers.
if (castTy->isIntegralOrEnumerationType() && Loc::isLocType(originalTy))
return evalCastFromLoc(val.castAs<Loc>(), castTy);
// Check for casts from integers to pointers.
if (Loc::isLocType(castTy) && originalTy->isIntegralOrEnumerationType()) {
if (Optional<nonloc::LocAsInteger> LV = val.getAs<nonloc::LocAsInteger>()) {
if (const MemRegion *R = LV->getLoc().getAsRegion()) {
StoreManager &storeMgr = StateMgr.getStoreManager();
R = storeMgr.castRegion(R, castTy);
return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
}
return LV->getLoc();
}
return dispatchCast(val, castTy);
}
// Just pass through function and block pointers.
if (originalTy->isBlockPointerType() || originalTy->isFunctionPointerType()) {
assert(Loc::isLocType(castTy));
return val;
}
// Check for casts from array type to another type.
if (const ArrayType *arrayT =
dyn_cast<ArrayType>(originalTy.getCanonicalType())) {
// We will always decay to a pointer.
QualType elemTy = arrayT->getElementType();
val = StateMgr.ArrayToPointer(val.castAs<Loc>(), elemTy);
// Are we casting from an array to a pointer? If so just pass on
// the decayed value.
if (castTy->isPointerType() || castTy->isReferenceType())
return val;
// Are we casting from an array to an integer? If so, cast the decayed
// pointer value to an integer.
assert(castTy->isIntegralOrEnumerationType());
// FIXME: Keep these here for now in case we decide soon that we
// need the original decayed type.
// QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
// QualType pointerTy = C.getPointerType(elemTy);
return evalCastFromLoc(val.castAs<Loc>(), castTy);
}
// Check for casts from a region to a specific type.
if (const MemRegion *R = val.getAsRegion()) {
// Handle other casts of locations to integers.
if (castTy->isIntegralOrEnumerationType())
return evalCastFromLoc(loc::MemRegionVal(R), castTy);
// FIXME: We should handle the case where we strip off view layers to get
// to a desugared type.
if (!Loc::isLocType(castTy)) {
// FIXME: There can be gross cases where one casts the result of a function
// (that returns a pointer) to some other value that happens to fit
// within that pointer value. We currently have no good way to
// model such operations. When this happens, the underlying operation
// is that the caller is reasoning about bits. Conceptually we are
// layering a "view" of a location on top of those bits. Perhaps
// we need to be more lazy about mutual possible views, even on an
// SVal? This may be necessary for bit-level reasoning as well.
return UnknownVal();
//.........这里部分代码省略.........
示例8: evalCast
// FIXME: should rewrite according to the cast kind.
SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
castTy = Context.getCanonicalType(castTy);
originalTy = Context.getCanonicalType(originalTy);
if (val.isUnknownOrUndef() || castTy == originalTy)
return val;
// For const casts, just propagate the value.
if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType())
if (haveSimilarTypes(Context, Context.getPointerType(castTy),
Context.getPointerType(originalTy)))
return val;
// Check for casts from pointers to integers.
if (castTy->isIntegerType() && Loc::isLocType(originalTy))
return evalCastFromLoc(cast<Loc>(val), castTy);
// Check for casts from integers to pointers.
if (Loc::isLocType(castTy) && originalTy->isIntegerType()) {
if (nonloc::LocAsInteger *LV = dyn_cast<nonloc::LocAsInteger>(&val)) {
if (const MemRegion *R = LV->getLoc().getAsRegion()) {
StoreManager &storeMgr = StateMgr.getStoreManager();
R = storeMgr.castRegion(R, castTy);
return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
}
return LV->getLoc();
}
return dispatchCast(val, castTy);
}
// Just pass through function and block pointers.
if (originalTy->isBlockPointerType() || originalTy->isFunctionPointerType()) {
assert(Loc::isLocType(castTy));
return val;
}
// Check for casts from array type to another type.
if (originalTy->isArrayType()) {
// We will always decay to a pointer.
val = StateMgr.ArrayToPointer(cast<Loc>(val));
// Are we casting from an array to a pointer? If so just pass on
// the decayed value.
if (castTy->isPointerType())
return val;
// Are we casting from an array to an integer? If so, cast the decayed
// pointer value to an integer.
assert(castTy->isIntegerType());
// FIXME: Keep these here for now in case we decide soon that we
// need the original decayed type.
// QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
// QualType pointerTy = C.getPointerType(elemTy);
return evalCastFromLoc(cast<Loc>(val), castTy);
}
// Check for casts from a region to a specific type.
if (const MemRegion *R = val.getAsRegion()) {
// Handle other casts of locations to integers.
if (castTy->isIntegerType())
return evalCastFromLoc(loc::MemRegionVal(R), castTy);
// FIXME: We should handle the case where we strip off view layers to get
// to a desugared type.
if (!Loc::isLocType(castTy)) {
// FIXME: There can be gross cases where one casts the result of a function
// (that returns a pointer) to some other value that happens to fit
// within that pointer value. We currently have no good way to
// model such operations. When this happens, the underlying operation
// is that the caller is reasoning about bits. Conceptually we are
// layering a "view" of a location on top of those bits. Perhaps
// we need to be more lazy about mutual possible views, even on an
// SVal? This may be necessary for bit-level reasoning as well.
return UnknownVal();
}
// We get a symbolic function pointer for a dereference of a function
// pointer, but it is of function type. Example:
// struct FPRec {
// void (*my_func)(int * x);
// };
//
// int bar(int x);
//
// int f1_a(struct FPRec* foo) {
// int x;
// (*foo->my_func)(&x);
// return bar(x)+1; // no-warning
// }
assert(Loc::isLocType(originalTy) || originalTy->isFunctionType() ||
originalTy->isBlockPointerType() || castTy->isReferenceType());
StoreManager &storeMgr = StateMgr.getStoreManager();
// Delegate to store manager to get the result of casting a region to a
// different type. If the MemRegion* returned is NULL, this expression
// Evaluates to UnknownVal.
//.........这里部分代码省略.........
示例9: SynthesizeCppVP
// We need to artificially create:
// cling::valuePrinterInternal::Select((void*) raw_ostream,
// (ASTContext)Ctx, (Expr*)E, &i);
Expr* ValuePrinterSynthesizer::SynthesizeCppVP(Expr* E) {
QualType QT = E->getType();
// For now we skip void and function pointer types.
if (QT.isNull() || QT->isVoidType())
return 0;
// 1. Call gCling->getValuePrinterStream()
// 1.1. Find gCling
SourceLocation NoSLoc = SourceLocation();
NamespaceDecl* NSD = utils::Lookup::Namespace(m_Sema, "cling");
NSD = utils::Lookup::Namespace(m_Sema, "valuePrinterInternal", NSD);
DeclarationName PVName = &m_Context->Idents.get("Select");
LookupResult R(*m_Sema, PVName, NoSLoc, Sema::LookupOrdinaryName,
Sema::ForRedeclaration);
assert(NSD && "There must be a valid namespace.");
m_Sema->LookupQualifiedName(R, NSD);
assert(!R.empty() && "Cannot find valuePrinterInternal::Select(...)");
CXXScopeSpec CSS;
Expr* UnresolvedLookup
= m_Sema->BuildDeclarationNameExpr(CSS, R, /*ADL*/ false).take();
// 2.4. Prepare the params
// 2.4.1 Lookup the llvm::raw_ostream
CXXRecordDecl* RawOStreamRD
= dyn_cast<CXXRecordDecl>(utils::Lookup::Named(m_Sema, "raw_ostream",
utils::Lookup::Namespace(m_Sema,
"llvm")));
assert(RawOStreamRD && "Declaration of the expr not found!");
QualType RawOStreamRDTy = m_Context->getTypeDeclType(RawOStreamRD);
// 2.4.2 Lookup the expr type
CXXRecordDecl* ExprRD
= dyn_cast<CXXRecordDecl>(utils::Lookup::Named(m_Sema, "Expr",
utils::Lookup::Namespace(m_Sema,
"clang")));
assert(ExprRD && "Declaration of the expr not found!");
QualType ExprRDTy = m_Context->getTypeDeclType(ExprRD);
// 2.4.3 Lookup ASTContext type
CXXRecordDecl* ASTContextRD
= dyn_cast<CXXRecordDecl>(utils::Lookup::Named(m_Sema, "ASTContext",
utils::Lookup::Namespace(m_Sema,
"clang")));
assert(ASTContextRD && "Declaration of the expr not found!");
QualType ASTContextRDTy = m_Context->getTypeDeclType(ASTContextRD);
Expr* RawOStreamTy
= utils::Synthesize::CStyleCastPtrExpr(m_Sema, RawOStreamRDTy,
(uint64_t)m_ValuePrinterStream.get()
);
Expr* ExprTy = utils::Synthesize::CStyleCastPtrExpr(m_Sema, ExprRDTy,
(uint64_t)E);
Expr* ASTContextTy
= utils::Synthesize::CStyleCastPtrExpr(m_Sema, ASTContextRDTy,
(uint64_t)m_Context);
// E might contain temporaries. This means that the topmost expr is
// ExprWithCleanups. This contains the information about the temporaries and
// signals when they should be destroyed.
// Here we replace E with call to value printer and we must extend the life
// time of those temporaries to the end of the new CallExpr.
bool NeedsCleanup = false;
if (ExprWithCleanups* EWC = dyn_cast<ExprWithCleanups>(E)) {
E = EWC->getSubExpr();
NeedsCleanup = true;
}
if (QT->isFunctionPointerType()) {
// convert func ptr to void*:
E = utils::Synthesize::CStyleCastPtrExpr(m_Sema, m_Context->VoidPtrTy, E);
}
llvm::SmallVector<Expr*, 4> CallArgs;
CallArgs.push_back(RawOStreamTy);
CallArgs.push_back(ExprTy);
CallArgs.push_back(ASTContextTy);
CallArgs.push_back(E);
Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext);
// Here we expect a template instantiation. We need to open the transaction
// that we are currently work with.
Transaction::State oldState = getTransaction()->getState();
getTransaction()->setState(Transaction::kCollecting);
Expr* Result = m_Sema->ActOnCallExpr(S, UnresolvedLookup, NoSLoc,
CallArgs, NoSLoc).take();
getTransaction()->setState(oldState);
Result = m_Sema->ActOnFinishFullExpr(Result).take();
if (NeedsCleanup && !isa<ExprWithCleanups>(Result)) {
llvm::ArrayRef<ExprWithCleanups::CleanupObject> Cleanups;
ExprWithCleanups* EWC
//.........这里部分代码省略.........
示例10: if
//.........这里部分代码省略.........
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.
}
示例11: while
/// CheckConstCast - Check that a const_cast\<DestType\>(SrcExpr) is valid.
/// Refer to C++ 5.2.11 for details. const_cast is typically used in code
/// like this:
/// const char *str = "literal";
/// legacy_function(const_cast\<char*\>(str));
void
CheckConstCast(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 lvalue reference type.
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
<< "const_cast" << OrigDestType << SrcExpr->getSourceRange();
return;
}
// C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2
// [...] if a pointer to T1 can be [cast] to the type pointer to T2.
DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
SrcType = Self.Context.getPointerType(SrcType);
} else {
// C++ 5.2.11p1: Otherwise, the result is an rvalue and the
// lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard
// conversions are performed on the expression.
Self.DefaultFunctionArrayConversion(SrcExpr);
SrcType = SrcExpr->getType();
}
// C++ 5.2.11p5: For a const_cast involving pointers to data members [...]
// the rules for const_cast are the same as those used for pointers.
if (!DestType->isPointerType() && !DestType->isMemberPointerType()) {
// Cannot cast to non-pointer, non-reference type. Note that, if DestType
// was a reference type, we converted it to a pointer above.
// The status of rvalue references isn't entirely clear, but it looks like
// conversion to them is simply invalid.
// C++ 5.2.11p3: For two pointer types [...]
Self.Diag(OpRange.getBegin(), diag::err_bad_const_cast_dest)
<< OrigDestType << DestRange;
return;
}
if (DestType->isFunctionPointerType() ||
DestType->isMemberFunctionPointerType()) {
// Cannot cast direct function pointers.
// C++ 5.2.11p2: [...] where T is any object type or the void type [...]
// T is the ultimate pointee of source and target type.
Self.Diag(OpRange.getBegin(), diag::err_bad_const_cast_dest)
<< OrigDestType << DestRange;
return;
}
SrcType = Self.Context.getCanonicalType(SrcType);
// Unwrap the pointers. Ignore qualifiers. Terminate early if the types are
// completely equal.
// FIXME: const_cast should probably not be able to convert between pointers
// to different address spaces.
// C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers
// in multi-level pointers may change, but the level count must be the same,
// as must be the final pointee type.
while (SrcType != DestType &&
Self.UnwrapSimilarPointerTypes(SrcType, DestType)) {
SrcType = SrcType.getUnqualifiedType();
DestType = DestType.getUnqualifiedType();
}
// Doug Gregor said to disallow this until users complain.
#if 0
// If we end up with constant arrays of equal size, unwrap those too. A cast
// from const int [N] to int (&)[N] is invalid by my reading of the
// standard, but g++ accepts it even with -ansi -pedantic.
// No more than one level, though, so don't embed this in the unwrap loop
// above.
const ConstantArrayType *SrcTypeArr, *DestTypeArr;
if ((SrcTypeArr = Self.Context.getAsConstantArrayType(SrcType)) &&
(DestTypeArr = Self.Context.getAsConstantArrayType(DestType)))
{
if (SrcTypeArr->getSize() != DestTypeArr->getSize()) {
// Different array sizes.
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic)
<< "const_cast" << OrigDestType << OrigSrcType << OpRange;
return;
}
SrcType = SrcTypeArr->getElementType().getUnqualifiedType();
DestType = DestTypeArr->getElementType().getUnqualifiedType();
}
#endif
// Since we're dealing in canonical types, the remainder must be the same.
if (SrcType != DestType) {
// Cast between unrelated types.
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic)
<< "const_cast" << OrigDestType << OrigSrcType << OpRange;
return;
}
//.........这里部分代码省略.........
示例12: TryConstCast
/// TryConstCast - See if a const_cast from source to destination is allowed,
/// and perform it if it is.
static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
bool CStyle, unsigned &msg) {
DestType = Self.Context.getCanonicalType(DestType);
QualType SrcType = SrcExpr->getType();
if (const LValueReferenceType *DestTypeTmp =
DestType->getAs<LValueReferenceType>()) {
if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) {
// Cannot const_cast non-lvalue to lvalue reference type. But if this
// is C-style, static_cast might find a way, so we simply suggest a
// message and tell the parent to keep searching.
msg = diag::err_bad_cxx_cast_rvalue;
return TC_NotApplicable;
}
// C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2
// [...] if a pointer to T1 can be [cast] to the type pointer to T2.
DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
SrcType = Self.Context.getPointerType(SrcType);
}
// C++ 5.2.11p5: For a const_cast involving pointers to data members [...]
// the rules for const_cast are the same as those used for pointers.
if (!DestType->isPointerType() && !DestType->isMemberPointerType()) {
// Cannot cast to non-pointer, non-reference type. Note that, if DestType
// was a reference type, we converted it to a pointer above.
// The status of rvalue references isn't entirely clear, but it looks like
// conversion to them is simply invalid.
// C++ 5.2.11p3: For two pointer types [...]
if (!CStyle)
msg = diag::err_bad_const_cast_dest;
return TC_NotApplicable;
}
if (DestType->isFunctionPointerType() ||
DestType->isMemberFunctionPointerType()) {
// Cannot cast direct function pointers.
// C++ 5.2.11p2: [...] where T is any object type or the void type [...]
// T is the ultimate pointee of source and target type.
if (!CStyle)
msg = diag::err_bad_const_cast_dest;
return TC_NotApplicable;
}
SrcType = Self.Context.getCanonicalType(SrcType);
// Unwrap the pointers. Ignore qualifiers. Terminate early if the types are
// completely equal.
// FIXME: const_cast should probably not be able to convert between pointers
// to different address spaces.
// C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers
// in multi-level pointers may change, but the level count must be the same,
// as must be the final pointee type.
while (SrcType != DestType &&
Self.UnwrapSimilarPointerTypes(SrcType, DestType)) {
SrcType = SrcType.getUnqualifiedType();
DestType = DestType.getUnqualifiedType();
}
// Since we're dealing in canonical types, the remainder must be the same.
if (SrcType != DestType)
return TC_NotApplicable;
return TC_Success;
}