本文整理汇总了C++中ASTContext::getCanonicalType方法的典型用法代码示例。如果您正苦于以下问题:C++ ASTContext::getCanonicalType方法的具体用法?C++ ASTContext::getCanonicalType怎么用?C++ ASTContext::getCanonicalType使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类ASTContext
的用法示例。
在下文中一共展示了ASTContext::getCanonicalType方法的14个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: addedAssignmentOperator
void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
CXXMethodDecl *OpDecl) {
// We're interested specifically in copy assignment operators.
// Unlike addedConstructor, this method is not called for implicit
// declarations.
const FunctionProtoType *FnType = OpDecl->getType()->getAsFunctionProtoType();
assert(FnType && "Overloaded operator has no proto function type.");
assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
QualType ArgType = FnType->getArgType(0);
if (const LValueReferenceType *Ref = ArgType->getAsLValueReferenceType())
ArgType = Ref->getPointeeType();
ArgType = ArgType.getUnqualifiedType();
QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
const_cast<CXXRecordDecl*>(this)));
if (ClassType != Context.getCanonicalType(ArgType))
return;
// This is a copy assignment operator.
// Suppress the implicit declaration of a copy constructor.
UserDeclaredCopyAssignment = true;
// C++ [class]p4:
// A POD-struct is an aggregate class that [...] has no user-defined copy
// assignment operator [...].
PlainOldData = false;
}
示例2: ClassifyImpl
Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const {
assert(!TR->isReferenceType() && "Expressions can't have reference type.");
Cl::Kinds kind = ClassifyInternal(Ctx, this);
// C99 6.3.2.1: An lvalue is an expression with an object type or an
// incomplete type other than void.
if (!Ctx.getLangOptions().CPlusPlus) {
// Thus, no functions.
if (TR->isFunctionType() || TR == Ctx.OverloadTy)
kind = Cl::CL_Function;
// No void either, but qualified void is OK because it is "other than void".
else if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers())
kind = Cl::CL_Void;
}
// Enable this assertion for testing.
switch (kind) {
case Cl::CL_LValue: assert(getValueKind() == VK_LValue); break;
case Cl::CL_XValue: assert(getValueKind() == VK_XValue); break;
case Cl::CL_Function:
case Cl::CL_Void:
case Cl::CL_DuplicateVectorComponents:
case Cl::CL_MemberFunction:
case Cl::CL_SubObjCPropertySetting:
case Cl::CL_ClassTemporary:
case Cl::CL_PRValue: assert(getValueKind() == VK_RValue); break;
}
Cl::ModifiableType modifiable = Cl::CM_Untested;
if (Loc)
modifiable = IsModifiable(Ctx, this, kind, *Loc);
return Classification(kind, modifiable);
}
示例3: getParamDecl
bool
CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
unsigned &TypeQuals) const {
// C++ [class.copy]p2:
// A non-template constructor for class X is a copy constructor
// if its first parameter is of type X&, const X&, volatile X& or
// const volatile X&, and either there are no other parameters
// or else all other parameters have default arguments (8.3.6).
if ((getNumParams() < 1) ||
(getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
return false;
const ParmVarDecl *Param = getParamDecl(0);
// Do we have a reference type? Rvalue references don't count.
const LValueReferenceType *ParamRefType =
Param->getType()->getAsLValueReferenceType();
if (!ParamRefType)
return false;
// Is it a reference to our class type?
QualType PointeeType
= Context.getCanonicalType(ParamRefType->getPointeeType());
QualType ClassTy
= Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
if (PointeeType.getUnqualifiedType() != ClassTy)
return false;
// We have a copy constructor.
TypeQuals = PointeeType.getCVRQualifiers();
return true;
}
示例4: IsModifiable
static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
Cl::Kinds Kind, SourceLocation &Loc) {
// As a general rule, we only care about lvalues. But there are some rvalues
// for which we want to generate special results.
if (Kind == Cl::CL_PRValue) {
// For the sake of better diagnostics, we want to specifically recognize
// use of the GCC cast-as-lvalue extension.
if (const ExplicitCastExpr *CE =
dyn_cast<ExplicitCastExpr>(E->IgnoreParens())) {
if (CE->getSubExpr()->IgnoreParenImpCasts()->isLValue()) {
Loc = CE->getExprLoc();
return Cl::CM_LValueCast;
}
}
}
if (Kind != Cl::CL_LValue)
return Cl::CM_RValue;
// This is the lvalue case.
// Functions are lvalues in C++, but not modifiable. (C++ [basic.lval]p6)
if (Ctx.getLangOpts().CPlusPlus && E->getType()->isFunctionType())
return Cl::CM_Function;
// Assignment to a property in ObjC is an implicit setter access. But a
// setter might not exist.
if (const ObjCPropertyRefExpr *Expr = dyn_cast<ObjCPropertyRefExpr>(E)) {
if (Expr->isImplicitProperty() && Expr->getImplicitPropertySetter() == 0)
return Cl::CM_NoSetterProperty;
}
CanQualType CT = Ctx.getCanonicalType(E->getType());
// Const stuff is obviously not modifiable.
if (CT.isConstQualified())
return Cl::CM_ConstQualified;
if (CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant)
return Cl::CM_ConstQualified;
// Arrays are not modifiable, only their elements are.
if (CT->isArrayType())
return Cl::CM_ArrayType;
// Incomplete types are not modifiable.
if (CT->isIncompleteType())
return Cl::CM_IncompleteType;
// Records with any const fields (recursively) are not modifiable.
if (const RecordType *R = CT->getAs<RecordType>()) {
assert((E->getObjectKind() == OK_ObjCProperty ||
!Ctx.getLangOpts().CPlusPlus) &&
"C++ struct assignment should be resolved by the "
"copy assignment operator.");
if (R->hasConstFields())
return Cl::CM_ConstQualified;
}
return Cl::CM_Modifiable;
}
示例5: GetConversionType
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
QualType T;
if (isa<UsingShadowDecl>(Conv))
Conv = cast<UsingShadowDecl>(Conv)->getTargetDecl();
if (FunctionTemplateDecl *ConvTemp = dyn_cast<FunctionTemplateDecl>(Conv))
T = ConvTemp->getTemplatedDecl()->getResultType();
else
T = cast<CXXConversionDecl>(Conv)->getConversionType();
return Context.getCanonicalType(T);
}
示例6: hasConstCopyAssignment
bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
const_cast<CXXRecordDecl*>(this)));
DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal);
DeclContext::lookup_const_iterator Op, OpEnd;
for (llvm::tie(Op, OpEnd) = this->lookup(Context, OpName);
Op != OpEnd; ++Op) {
// C++ [class.copy]p9:
// A user-declared copy assignment operator is a non-static non-template
// member function of class X with exactly one parameter of type X, X&,
// const X&, volatile X& or const volatile X&.
const CXXMethodDecl* Method = cast<CXXMethodDecl>(*Op);
if (Method->isStatic())
continue;
// TODO: Skip templates? Or is this implicitly done due to parameter types?
const FunctionProtoType *FnType =
Method->getType()->getAsFunctionProtoType();
assert(FnType && "Overloaded operator has no prototype.");
// Don't assert on this; an invalid decl might have been left in the AST.
if (FnType->getNumArgs() != 1 || FnType->isVariadic())
continue;
bool AcceptsConst = true;
QualType ArgType = FnType->getArgType(0);
if (const LValueReferenceType *Ref = ArgType->getAsLValueReferenceType()) {
ArgType = Ref->getPointeeType();
// Is it a non-const lvalue reference?
if (!ArgType.isConstQualified())
AcceptsConst = false;
}
if (Context.getCanonicalType(ArgType).getUnqualifiedType() != ClassType)
continue;
// We have a single argument of type cv X or cv X&, i.e. we've found the
// copy assignment operator. Return whether it accepts const arguments.
return AcceptsConst;
}
assert(isInvalidDecl() &&
"No copy assignment operator declared in valid code.");
return false;
}
示例7: hasConstCopyConstructor
bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
QualType ClassType
= Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ClassType));
unsigned TypeQuals;
DeclContext::lookup_const_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = this->lookup(Context, ConstructorName);
Con != ConEnd; ++Con) {
if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
(TypeQuals & QualType::Const) != 0)
return true;
}
return false;
}
示例8: ClassifyImpl
Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const {
assert(!TR->isReferenceType() && "Expressions can't have reference type.");
Cl::Kinds kind = ClassifyInternal(Ctx, this);
// C99 6.3.2.1: An lvalue is an expression with an object type or an
// incomplete type other than void.
if (!Ctx.getLangOptions().CPlusPlus) {
// Thus, no functions.
if (TR->isFunctionType() || TR == Ctx.OverloadTy)
kind = Cl::CL_Function;
// No void either, but qualified void is OK because it is "other than void".
else if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers())
kind = Cl::CL_Void;
}
Cl::ModifiableType modifiable = Cl::CM_Untested;
if (Loc)
modifiable = IsModifiable(Ctx, this, kind, *Loc);
return Classification(kind, modifiable);
}
示例9: isHigherOrderRawPtr
static bool isHigherOrderRawPtr(QualType T, ASTContext &C) {
bool foundPointer = false;
while (1) {
const PointerType *PT = T->getAs<PointerType>();
if (!PT) {
if (!foundPointer)
return false;
// intptr_t* or intptr_t**, etc?
if (T->isIntegerType() && C.getTypeSize(T) == C.getTypeSize(C.VoidPtrTy))
return true;
QualType X = C.getCanonicalType(T).getUnqualifiedType();
return X == C.VoidTy;
}
foundPointer = true;
T = PT->getPointeeType();
}
}
示例10: addedAssignmentOperator
void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
CXXMethodDecl *OpDecl) {
// We're interested specifically in copy assignment operators.
const FunctionProtoType *FnType = OpDecl->getType()->getAs<FunctionProtoType>();
assert(FnType && "Overloaded operator has no proto function type.");
assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
// Copy assignment operators must be non-templates.
if (OpDecl->getPrimaryTemplate() || OpDecl->getDescribedFunctionTemplate())
return;
QualType ArgType = FnType->getArgType(0);
if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>())
ArgType = Ref->getPointeeType();
ArgType = ArgType.getUnqualifiedType();
QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
const_cast<CXXRecordDecl*>(this)));
if (!Context.hasSameUnqualifiedType(ClassType, ArgType))
return;
// This is a copy assignment operator.
// Note on the decl that it is a copy assignment operator.
OpDecl->setCopyAssignment(true);
// Suppress the implicit declaration of a copy constructor.
data().UserDeclaredCopyAssignment = true;
data().DeclaredCopyAssignment = true;
// C++ [class.copy]p11:
// A copy assignment operator is trivial if it is implicitly declared.
// FIXME: C++0x: don't do this for "= default" copy operators.
data().HasTrivialCopyAssignment = false;
// C++ [class]p4:
// A POD-struct is an aggregate class that [...] has no user-defined copy
// assignment operator [...].
data().PlainOldData = false;
}
示例11: lookupInBases
bool CXXBasePaths::lookupInBases(ASTContext &Context,
const CXXRecordDecl *Record,
CXXRecordDecl::BaseMatchesCallback *BaseMatches,
void *UserData) {
bool FoundPath = false;
// The access of the path down to this record.
AccessSpecifier AccessToHere = ScratchPath.Access;
bool IsFirstStep = ScratchPath.empty();
for (CXXRecordDecl::base_class_const_iterator BaseSpec = Record->bases_begin(),
BaseSpecEnd = Record->bases_end();
BaseSpec != BaseSpecEnd;
++BaseSpec) {
// Find the record of the base class subobjects for this type.
QualType BaseType = Context.getCanonicalType(BaseSpec->getType())
.getUnqualifiedType();
// C++ [temp.dep]p3:
// In the definition of a class template or a member of a class template,
// if a base class of the class template depends on a template-parameter,
// the base class scope is not examined during unqualified name lookup
// either at the point of definition of the class template or member or
// during an instantiation of the class tem- plate or member.
if (BaseType->isDependentType())
continue;
// Determine whether we need to visit this base class at all,
// updating the count of subobjects appropriately.
std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
bool VisitBase = true;
bool SetVirtual = false;
if (BaseSpec->isVirtual()) {
VisitBase = !Subobjects.first;
Subobjects.first = true;
if (isDetectingVirtual() && DetectedVirtual == 0) {
// If this is the first virtual we find, remember it. If it turns out
// there is no base path here, we'll reset it later.
DetectedVirtual = BaseType->getAs<RecordType>();
SetVirtual = true;
}
} else
++Subobjects.second;
if (isRecordingPaths()) {
// Add this base specifier to the current path.
CXXBasePathElement Element;
Element.Base = &*BaseSpec;
Element.Class = Record;
if (BaseSpec->isVirtual())
Element.SubobjectNumber = 0;
else
Element.SubobjectNumber = Subobjects.second;
ScratchPath.push_back(Element);
// Calculate the "top-down" access to this base class.
// The spec actually describes this bottom-up, but top-down is
// equivalent because the definition works out as follows:
// 1. Write down the access along each step in the inheritance
// chain, followed by the access of the decl itself.
// For example, in
// class A { public: int foo; };
// class B : protected A {};
// class C : public B {};
// class D : private C {};
// we would write:
// private public protected public
// 2. If 'private' appears anywhere except far-left, access is denied.
// 3. Otherwise, overall access is determined by the most restrictive
// access in the sequence.
if (IsFirstStep)
ScratchPath.Access = BaseSpec->getAccessSpecifier();
else
ScratchPath.Access = CXXRecordDecl::MergeAccess(AccessToHere,
BaseSpec->getAccessSpecifier());
}
// Track whether there's a path involving this specific base.
bool FoundPathThroughBase = false;
if (BaseMatches(BaseSpec, ScratchPath, UserData)) {
// We've found a path that terminates at this base.
FoundPath = FoundPathThroughBase = true;
if (isRecordingPaths()) {
// We have a path. Make a copy of it before moving on.
Paths.push_back(ScratchPath);
} else if (!isFindingAmbiguities()) {
// We found a path and we don't care about ambiguities;
// return immediately.
return FoundPath;
}
} else if (VisitBase) {
CXXRecordDecl *BaseRecord
= cast<CXXRecordDecl>(BaseSpec->getType()->castAs<RecordType>()
->getDecl());
if (lookupInBases(Context, BaseRecord, BaseMatches, UserData)) {
// C++ [class.member.lookup]p2:
// A member name f in one sub-object B hides a member name f in
// a sub-object A if A is a base class sub-object of B. Any
// declarations that are so hidden are eliminated from
//.........这里部分代码省略.........
示例12: switch
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)
//.........这里部分代码省略.........
示例13: IsModifiable
static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
Cl::Kinds Kind, SourceLocation &Loc) {
// As a general rule, we only care about lvalues. But there are some rvalues
// for which we want to generate special results.
if (Kind == Cl::CL_PRValue) {
// For the sake of better diagnostics, we want to specifically recognize
// use of the GCC cast-as-lvalue extension.
if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(E->IgnoreParens())){
if (CE->getSubExpr()->Classify(Ctx).isLValue()) {
Loc = CE->getLParenLoc();
return Cl::CM_LValueCast;
}
}
}
if (Kind != Cl::CL_LValue)
return Cl::CM_RValue;
// This is the lvalue case.
// Functions are lvalues in C++, but not modifiable. (C++ [basic.lval]p6)
if (Ctx.getLangOptions().CPlusPlus && E->getType()->isFunctionType())
return Cl::CM_Function;
// You cannot assign to a variable outside a block from within the block if
// it is not marked __block, e.g.
// void takeclosure(void (^C)(void));
// void func() { int x = 1; takeclosure(^{ x = 7; }); }
if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(E)) {
if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl()))
return Cl::CM_NotBlockQualified;
}
// Assignment to a property in ObjC is an implicit setter access. But a
// setter might not exist.
if (const ObjCImplicitSetterGetterRefExpr *Expr =
dyn_cast<ObjCImplicitSetterGetterRefExpr>(E)) {
if (Expr->getSetterMethod() == 0)
return Cl::CM_NoSetterProperty;
}
CanQualType CT = Ctx.getCanonicalType(E->getType());
// Const stuff is obviously not modifiable.
if (CT.isConstQualified())
return Cl::CM_ConstQualified;
// Arrays are not modifiable, only their elements are.
if (CT->isArrayType())
return Cl::CM_ArrayType;
// Incomplete types are not modifiable.
if (CT->isIncompleteType())
return Cl::CM_IncompleteType;
// Records with any const fields (recursively) are not modifiable.
if (const RecordType *R = CT->getAs<RecordType>()) {
assert(!Ctx.getLangOptions().CPlusPlus &&
"C++ struct assignment should be resolved by the "
"copy assignment operator.");
if (R->hasConstFields())
return Cl::CM_ConstQualified;
}
return Cl::CM_Modifiable;
}
示例14: matchesType
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.
//.........这里部分代码省略.........