diff options
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 2800 |
1 files changed, 1703 insertions, 1097 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index a5e5083964222..d8e49c7d69410 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -14,18 +14,20 @@ #include "Sema.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Lex/LiteralSupport.h" +#include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/LiteralSupport.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Parse/DeclSpec.h" #include "clang/Parse/Designator.h" #include "clang/Parse/Scope.h" using namespace clang; + /// \brief Determine whether the use of this declaration is valid, and /// emit any corresponding diagnostics. /// @@ -44,12 +46,12 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { // stuff. Don't warn if we are implementing a deprecated // construct. bool isSilenced = false; - + if (NamedDecl *ND = getCurFunctionOrMethodDecl()) { // If this reference happens *in* a deprecated function or method, don't // warn. isSilenced = ND->getAttr<DeprecatedAttr>(); - + // If this is an Objective-C method implementation, check to see if the // method was deprecated on the declaration, not the definition. if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ND)) { @@ -57,14 +59,14 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { // ObjCImplementationDecl. if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(MD->getParent())) { - + MD = Impl->getClassInterface()->getMethod(MD->getSelector(), MD->isInstanceMethod()); isSilenced |= MD && MD->getAttr<DeprecatedAttr>(); } } } - + if (!isSilenced) Diag(Loc, diag::warn_deprecated) << D->getDeclName(); } @@ -88,18 +90,17 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { } /// DiagnoseSentinelCalls - This routine checks on method dispatch calls -/// (and other functions in future), which have been declared with sentinel +/// (and other functions in future), which have been declared with sentinel /// attribute. It warns if call does not have the sentinel argument. /// void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, - Expr **Args, unsigned NumArgs) -{ + Expr **Args, unsigned NumArgs) { const SentinelAttr *attr = D->getAttr<SentinelAttr>(); - if (!attr) + if (!attr) return; int sentinelPos = attr->getSentinel(); int nullPos = attr->getNullPos(); - + // FIXME. ObjCMethodDecl and FunctionDecl need be derived from the same common // base class. Then we won't be needing two versions of the same code. unsigned int i = 0; @@ -116,8 +117,7 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, } warnNotEnoughArgs = (P != E || i >= NumArgs); isMethod = 1; - } - else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // skip over named parameters. ObjCMethodDecl::param_iterator P, E = FD->param_end(); for (P = FD->param_begin(); (P != E && i < NumArgs); ++P) { @@ -127,14 +127,13 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, ++i; } warnNotEnoughArgs = (P != E || i >= NumArgs); - } - else if (VarDecl *V = dyn_cast<VarDecl>(D)) { + } else if (VarDecl *V = dyn_cast<VarDecl>(D)) { // block or function pointer call. QualType Ty = V->getType(); if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { - const FunctionType *FT = Ty->isFunctionPointerType() - ? Ty->getAsPointerType()->getPointeeType()->getAsFunctionType() - : Ty->getAsBlockPointerType()->getPointeeType()->getAsFunctionType(); + const FunctionType *FT = Ty->isFunctionPointerType() + ? Ty->getAs<PointerType>()->getPointeeType()->getAs<FunctionType>() + : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>(); if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) { unsigned NumArgsInProto = Proto->getNumArgs(); unsigned k; @@ -148,11 +147,9 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, } if (Ty->isBlockPointerType()) isMethod = 2; - } - else + } else return; - } - else + } else return; if (warnNotEnoughArgs) { @@ -176,7 +173,8 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, } Expr *sentinelExpr = Args[sentinel]; if (sentinelExpr && (!sentinelExpr->getType()->isPointerType() || - !sentinelExpr->isNullPointerConstant(Context))) { + !sentinelExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull))) { Diag(Loc, diag::warn_missing_sentinel) << isMethod; Diag(D->getLocation(), diag::note_sentinel_here) << isMethod; } @@ -198,7 +196,8 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) { assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type"); if (Ty->isFunctionType()) - ImpCastExprToType(E, Context.getPointerType(Ty)); + ImpCastExprToType(E, Context.getPointerType(Ty), + CastExpr::CK_FunctionToPointerDecay); else if (Ty->isArrayType()) { // In C90 mode, arrays only promote to pointers if the array expression is // an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has @@ -213,54 +212,20 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) { // if (getLangOptions().C99 || getLangOptions().CPlusPlus || E->isLvalue(Context) == Expr::LV_Valid) - ImpCastExprToType(E, Context.getArrayDecayedType(Ty)); + ImpCastExprToType(E, Context.getArrayDecayedType(Ty), + CastExpr::CK_ArrayToPointerDecay); } } -/// \brief Whether this is a promotable bitfield reference according -/// to C99 6.3.1.1p2, bullet 2. -/// -/// \returns the type this bit-field will promote to, or NULL if no -/// promotion occurs. -static QualType isPromotableBitField(Expr *E, ASTContext &Context) { - FieldDecl *Field = E->getBitField(); - if (!Field) - return QualType(); - - const BuiltinType *BT = Field->getType()->getAsBuiltinType(); - if (!BT) - return QualType(); - - if (BT->getKind() != BuiltinType::Bool && - BT->getKind() != BuiltinType::Int && - BT->getKind() != BuiltinType::UInt) - return QualType(); - - llvm::APSInt BitWidthAP; - if (!Field->getBitWidth()->isIntegerConstantExpr(BitWidthAP, Context)) - return QualType(); - - uint64_t BitWidth = BitWidthAP.getZExtValue(); - uint64_t IntSize = Context.getTypeSize(Context.IntTy); - if (BitWidth < IntSize || - (Field->getType()->isSignedIntegerType() && BitWidth == IntSize)) - return Context.IntTy; - - if (BitWidth == IntSize && Field->getType()->isUnsignedIntegerType()) - return Context.UnsignedIntTy; - - return QualType(); -} - /// UsualUnaryConversions - Performs various conversions that are common to most -/// operators (C99 6.3). The conversions of array and function types are +/// operators (C99 6.3). The conversions of array and function types are /// sometimes surpressed. For example, the array->pointer conversion doesn't /// apply if the array is an argument to the sizeof or address (&) operators. /// In these instances, this routine should *not* be called. Expr *Sema::UsualUnaryConversions(Expr *&Expr) { QualType Ty = Expr->getType(); assert(!Ty.isNull() && "UsualUnaryConversions - missing type"); - + // C99 6.3.1.1p2: // // The following may be used in an expression wherever an int or @@ -274,33 +239,33 @@ Expr *Sema::UsualUnaryConversions(Expr *&Expr) { // value is converted to an int; otherwise, it is converted to an // unsigned int. These are called the integer promotions. All // other types are unchanged by the integer promotions. + QualType PTy = Context.isPromotableBitField(Expr); + if (!PTy.isNull()) { + ImpCastExprToType(Expr, PTy); + return Expr; + } if (Ty->isPromotableIntegerType()) { - ImpCastExprToType(Expr, Context.IntTy); + QualType PT = Context.getPromotedIntegerType(Ty); + ImpCastExprToType(Expr, PT); return Expr; - } else { - QualType T = isPromotableBitField(Expr, Context); - if (!T.isNull()) { - ImpCastExprToType(Expr, T); - return Expr; - } - } - + } + DefaultFunctionArrayConversion(Expr); return Expr; } /// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that -/// do not have a prototype. Arguments that have type float are promoted to +/// do not have a prototype. Arguments that have type float are promoted to /// double. All other argument types are converted by UsualUnaryConversions(). void Sema::DefaultArgumentPromotion(Expr *&Expr) { QualType Ty = Expr->getType(); assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type"); - + // If this is a 'float' (CVR qualified or typedef) promote to double. - if (const BuiltinType *BT = Ty->getAsBuiltinType()) + if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) if (BT->getKind() == BuiltinType::Float) return ImpCastExprToType(Expr, Context.DoubleTy); - + UsualUnaryConversions(Expr); } @@ -310,14 +275,14 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) { /// completely illegal. bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) { DefaultArgumentPromotion(Expr); - + if (Expr->getType()->isObjCInterfaceType()) { Diag(Expr->getLocStart(), diag::err_cannot_pass_objc_interface_to_vararg) << Expr->getType() << CT; return true; } - + if (!Expr->getType()->isPODType()) Diag(Expr->getLocStart(), diag::warn_cannot_pass_non_pod_arg_to_vararg) << Expr->getType() << CT; @@ -328,7 +293,7 @@ bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) { /// UsualArithmeticConversions - Performs various conversions that are common to /// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this -/// routine returns the first non-arithmetic type found. The client is +/// routine returns the first non-arithmetic type found. The client is /// responsible for emitting appropriate error diagnostics. /// FIXME: verify the conversion rules for "complex int" are consistent with /// GCC. @@ -339,11 +304,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, UsualUnaryConversions(rhsExpr); - // For conversion purposes, we ignore any qualifiers. + // For conversion purposes, we ignore any qualifiers. // For example, "const float" and "float" are equivalent. QualType lhs = Context.getCanonicalType(lhsExpr->getType()).getUnqualifiedType(); - QualType rhs = + QualType rhs = Context.getCanonicalType(rhsExpr->getType()).getUnqualifiedType(); // If both types are identical, no conversion is needed. @@ -356,159 +321,20 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, return lhs; // Perform bitfield promotions. - QualType LHSBitfieldPromoteTy = isPromotableBitField(lhsExpr, Context); + QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr); if (!LHSBitfieldPromoteTy.isNull()) lhs = LHSBitfieldPromoteTy; - QualType RHSBitfieldPromoteTy = isPromotableBitField(rhsExpr, Context); + QualType RHSBitfieldPromoteTy = Context.isPromotableBitField(rhsExpr); if (!RHSBitfieldPromoteTy.isNull()) rhs = RHSBitfieldPromoteTy; - QualType destType = UsualArithmeticConversionsType(lhs, rhs); + QualType destType = Context.UsualArithmeticConversionsType(lhs, rhs); if (!isCompAssign) ImpCastExprToType(lhsExpr, destType); ImpCastExprToType(rhsExpr, destType); return destType; } -QualType Sema::UsualArithmeticConversionsType(QualType lhs, QualType rhs) { - // Perform the usual unary conversions. We do this early so that - // integral promotions to "int" can allow us to exit early, in the - // lhs == rhs check. Also, for conversion purposes, we ignore any - // qualifiers. For example, "const float" and "float" are - // equivalent. - if (lhs->isPromotableIntegerType()) - lhs = Context.IntTy; - else - lhs = lhs.getUnqualifiedType(); - if (rhs->isPromotableIntegerType()) - rhs = Context.IntTy; - else - rhs = rhs.getUnqualifiedType(); - - // If both types are identical, no conversion is needed. - if (lhs == rhs) - return lhs; - - // If either side is a non-arithmetic type (e.g. a pointer), we are done. - // The caller can deal with this (e.g. pointer + int). - if (!lhs->isArithmeticType() || !rhs->isArithmeticType()) - return lhs; - - // At this point, we have two different arithmetic types. - - // Handle complex types first (C99 6.3.1.8p1). - if (lhs->isComplexType() || rhs->isComplexType()) { - // if we have an integer operand, the result is the complex type. - if (rhs->isIntegerType() || rhs->isComplexIntegerType()) { - // convert the rhs to the lhs complex type. - return lhs; - } - if (lhs->isIntegerType() || lhs->isComplexIntegerType()) { - // convert the lhs to the rhs complex type. - return rhs; - } - // This handles complex/complex, complex/float, or float/complex. - // When both operands are complex, the shorter operand is converted to the - // type of the longer, and that is the type of the result. This corresponds - // to what is done when combining two real floating-point operands. - // The fun begins when size promotion occur across type domains. - // From H&S 6.3.4: When one operand is complex and the other is a real - // floating-point type, the less precise type is converted, within it's - // real or complex domain, to the precision of the other type. For example, - // when combining a "long double" with a "double _Complex", the - // "double _Complex" is promoted to "long double _Complex". - int result = Context.getFloatingTypeOrder(lhs, rhs); - - if (result > 0) { // The left side is bigger, convert rhs. - rhs = Context.getFloatingTypeOfSizeWithinDomain(lhs, rhs); - } else if (result < 0) { // The right side is bigger, convert lhs. - lhs = Context.getFloatingTypeOfSizeWithinDomain(rhs, lhs); - } - // At this point, lhs and rhs have the same rank/size. Now, make sure the - // domains match. This is a requirement for our implementation, C99 - // does not require this promotion. - if (lhs != rhs) { // Domains don't match, we have complex/float mix. - if (lhs->isRealFloatingType()) { // handle "double, _Complex double". - return rhs; - } else { // handle "_Complex double, double". - return lhs; - } - } - return lhs; // The domain/size match exactly. - } - // Now handle "real" floating types (i.e. float, double, long double). - if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) { - // if we have an integer operand, the result is the real floating type. - if (rhs->isIntegerType()) { - // convert rhs to the lhs floating point type. - return lhs; - } - if (rhs->isComplexIntegerType()) { - // convert rhs to the complex floating point type. - return Context.getComplexType(lhs); - } - if (lhs->isIntegerType()) { - // convert lhs to the rhs floating point type. - return rhs; - } - if (lhs->isComplexIntegerType()) { - // convert lhs to the complex floating point type. - return Context.getComplexType(rhs); - } - // We have two real floating types, float/complex combos were handled above. - // Convert the smaller operand to the bigger result. - int result = Context.getFloatingTypeOrder(lhs, rhs); - if (result > 0) // convert the rhs - return lhs; - assert(result < 0 && "illegal float comparison"); - return rhs; // convert the lhs - } - if (lhs->isComplexIntegerType() || rhs->isComplexIntegerType()) { - // Handle GCC complex int extension. - const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType(); - const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType(); - - if (lhsComplexInt && rhsComplexInt) { - if (Context.getIntegerTypeOrder(lhsComplexInt->getElementType(), - rhsComplexInt->getElementType()) >= 0) - return lhs; // convert the rhs - return rhs; - } else if (lhsComplexInt && rhs->isIntegerType()) { - // convert the rhs to the lhs complex type. - return lhs; - } else if (rhsComplexInt && lhs->isIntegerType()) { - // convert the lhs to the rhs complex type. - return rhs; - } - } - // Finally, we have two differing integer types. - // The rules for this case are in C99 6.3.1.8 - int compare = Context.getIntegerTypeOrder(lhs, rhs); - bool lhsSigned = lhs->isSignedIntegerType(), - rhsSigned = rhs->isSignedIntegerType(); - QualType destType; - if (lhsSigned == rhsSigned) { - // Same signedness; use the higher-ranked type - destType = compare >= 0 ? lhs : rhs; - } else if (compare != (lhsSigned ? 1 : -1)) { - // The unsigned type has greater than or equal rank to the - // signed type, so use the unsigned type - destType = lhsSigned ? rhs : lhs; - } else if (Context.getIntWidth(lhs) != Context.getIntWidth(rhs)) { - // The two types are different widths; if we are here, that - // means the signed type is larger than the unsigned type, so - // use the signed type. - destType = lhsSigned ? lhs : rhs; - } else { - // The signed type is higher-ranked than the unsigned type, - // but isn't actually any bigger (like unsigned int and long - // on most 32-bit systems). Use the unsigned type corresponding - // to the signed type. - destType = Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs); - } - return destType; -} - //===----------------------------------------------------------------------===// // Semantic Analysis for various Expression Types //===----------------------------------------------------------------------===// @@ -546,9 +372,9 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Literal.GetNumStringChars()+1), ArrayType::Normal, 0); - + // Pass &StringTokLocs[0], StringTokLocs.size() to factory! - return Owned(StringLiteral::Create(Context, Literal.GetString(), + return Owned(StringLiteral::Create(Context, Literal.GetString(), Literal.GetStringLength(), Literal.AnyWide, StrTy, &StringTokLocs[0], @@ -569,7 +395,7 @@ static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock, // we wanted to. if (CurBlock->TheDecl == VD->getDeclContext()) return false; - + // If this is an enum constant or function, it is constant, don't snapshot. if (isa<EnumConstantDecl>(VD) || isa<FunctionDecl>(VD)) return false; @@ -580,7 +406,7 @@ static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock, if (const VarDecl *Var = dyn_cast<VarDecl>(VD)) if (!Var->hasLocalStorage()) return false; - + // Blocks that have these can't be constant. CurBlock->hasBlockDeclRefExprs = true; @@ -594,15 +420,15 @@ static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock, // having a reference outside it. if (NextBlock->TheDecl == VD->getDeclContext()) break; - + // Otherwise, the DeclRef from the inner block causes the outer one to need // a snapshot as well. NextBlock->hasBlockDeclRefExprs = true; } - + return true; -} - +} + /// ActOnIdentifierExpr - The parser read an identifier in expression context, @@ -628,35 +454,35 @@ Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, const CXXScopeSpec *SS) { if (Context.getCanonicalType(Ty) == Context.UndeducedAutoTy) { Diag(Loc, - diag::err_auto_variable_cannot_appear_in_own_initializer) + diag::err_auto_variable_cannot_appear_in_own_initializer) << D->getDeclName(); return ExprError(); } - + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) { if (const FunctionDecl *FD = MD->getParent()->isLocalClass()) { if (VD->hasLocalStorage() && VD->getDeclContext() != CurContext) { - Diag(Loc, diag::err_reference_to_local_var_in_enclosing_function) + Diag(Loc, diag::err_reference_to_local_var_in_enclosing_function) << D->getIdentifier() << FD->getDeclName(); - Diag(D->getLocation(), diag::note_local_variable_declared_here) + Diag(D->getLocation(), diag::note_local_variable_declared_here) << D->getIdentifier(); return ExprError(); } } } } - + MarkDeclarationReferenced(Loc, D); - + Expr *E; if (SS && !SS->isEmpty()) { - E = new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent, + E = new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent, SS->getRange(), static_cast<NestedNameSpecifier *>(SS->getScopeRep())); } else E = new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent); - + return Owned(E); } @@ -665,14 +491,14 @@ Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, /// is Record. static Decl *getObjectForAnonymousRecordDecl(ASTContext &Context, RecordDecl *Record) { - assert(Record->isAnonymousStructOrUnion() && + assert(Record->isAnonymousStructOrUnion() && "Record must be an anonymous struct or union!"); - + // FIXME: Once Decls are directly linked together, this will be an O(1) // operation rather than a slow walk through DeclContext's vector (which // itself will be eliminated). DeclGroups might make this even better. DeclContext *Ctx = Record->getDeclContext(); - for (DeclContext::decl_iterator D = Ctx->decls_begin(), + for (DeclContext::decl_iterator D = Ctx->decls_begin(), DEnd = Ctx->decls_end(); D != DEnd; ++D) { if (*D == Record) { @@ -721,7 +547,7 @@ VarDecl *Sema::BuildAnonymousStructUnionMemberPath(FieldDecl *Field, break; } Ctx = Ctx->getParent(); - } while (Ctx->isRecord() && + } while (Ctx->isRecord() && cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion()); return BaseObject; @@ -733,7 +559,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, Expr *BaseObjectExpr, SourceLocation OpLoc) { llvm::SmallVector<FieldDecl *, 4> AnonFields; - VarDecl *BaseObject = BuildAnonymousStructUnionMemberPath(Field, + VarDecl *BaseObject = BuildAnonymousStructUnionMemberPath(Field, AnonFields); // Build the expression that refers to the base object, from @@ -741,7 +567,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, // of the anonymous union objects and, eventually, the field we // found via name lookup. bool BaseObjectIsPointer = false; - unsigned ExtraQuals = 0; + Qualifiers BaseQuals; if (BaseObject) { // BaseObject is an anonymous struct/union variable (and is, // therefore, not part of another non-anonymous record). @@ -749,29 +575,30 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, MarkDeclarationReferenced(Loc, BaseObject); BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(), SourceLocation()); - ExtraQuals - = Context.getCanonicalType(BaseObject->getType()).getCVRQualifiers(); + BaseQuals + = Context.getCanonicalType(BaseObject->getType()).getQualifiers(); } else if (BaseObjectExpr) { // The caller provided the base object expression. Determine // whether its a pointer and whether it adds any qualifiers to the // anonymous struct/union fields we're looking into. QualType ObjectType = BaseObjectExpr->getType(); - if (const PointerType *ObjectPtr = ObjectType->getAsPointerType()) { + if (const PointerType *ObjectPtr = ObjectType->getAs<PointerType>()) { BaseObjectIsPointer = true; ObjectType = ObjectPtr->getPointeeType(); } - ExtraQuals = Context.getCanonicalType(ObjectType).getCVRQualifiers(); + BaseQuals + = Context.getCanonicalType(ObjectType).getQualifiers(); } else { // We've found a member of an anonymous struct/union that is // inside a non-anonymous struct/union, so in a well-formed // program our base object expression is "this". if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) { if (!MD->isStatic()) { - QualType AnonFieldType + QualType AnonFieldType = Context.getTagDeclType( cast<RecordDecl>(AnonFields.back()->getDeclContext())); QualType ThisType = Context.getTagDeclType(MD->getParent()); - if ((Context.getCanonicalType(AnonFieldType) + if ((Context.getCanonicalType(AnonFieldType) == Context.getCanonicalType(ThisType)) || IsDerivedFrom(ThisType, AnonFieldType)) { // Our base object expression is "this". @@ -783,10 +610,10 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, return ExprError(Diag(Loc,diag::err_invalid_member_use_in_static_method) << Field->getDeclName()); } - ExtraQuals = MD->getTypeQualifiers(); + BaseQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers()); } - if (!BaseObjectExpr) + if (!BaseObjectExpr) return ExprError(Diag(Loc, diag::err_invalid_non_static_member_use) << Field->getDeclName()); } @@ -794,20 +621,35 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, // Build the implicit member references to the field of the // anonymous struct/union. Expr *Result = BaseObjectExpr; + Qualifiers ResultQuals = BaseQuals; for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator FI = AnonFields.rbegin(), FIEnd = AnonFields.rend(); FI != FIEnd; ++FI) { QualType MemberType = (*FI)->getType(); - if (!(*FI)->isMutable()) { - unsigned combinedQualifiers - = MemberType.getCVRQualifiers() | ExtraQuals; - MemberType = MemberType.getQualifiedType(combinedQualifiers); - } + Qualifiers MemberTypeQuals = + Context.getCanonicalType(MemberType).getQualifiers(); + + // CVR attributes from the base are picked up by members, + // except that 'mutable' members don't pick up 'const'. + if ((*FI)->isMutable()) + ResultQuals.removeConst(); + + // GC attributes are never picked up by members. + ResultQuals.removeObjCGCAttr(); + + // TR 18037 does not allow fields to be declared with address spaces. + assert(!MemberTypeQuals.hasAddressSpace()); + + Qualifiers NewQuals = ResultQuals + MemberTypeQuals; + if (NewQuals != MemberTypeQuals) + MemberType = Context.getQualifiedType(MemberType, NewQuals); + MarkDeclarationReferenced(Loc, *FI); + // FIXME: Might this end up being a qualified name? Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI, OpLoc, MemberType); BaseObjectIsPointer = false; - ExtraQuals = Context.getCanonicalType(MemberType).getCVRQualifiers(); + ResultQuals = NewQuals; } return Owned(Result); @@ -835,7 +677,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, Sema::OwningExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, DeclarationName Name, bool HasTrailingLParen, - const CXXScopeSpec *SS, + const CXXScopeSpec *SS, bool isAddressOfOperand) { // Could be enum-constant, value decl, instance variable, etc. if (SS && SS->isInvalid()) @@ -848,12 +690,13 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // FIXME: Member of the current instantiation. if (SS && isDependentScopeSpecifier(*SS)) { return Owned(new (Context) UnresolvedDeclRefExpr(Name, Context.DependentTy, - Loc, SS->getRange(), - static_cast<NestedNameSpecifier *>(SS->getScopeRep()))); + Loc, SS->getRange(), + static_cast<NestedNameSpecifier *>(SS->getScopeRep()), + isAddressOfOperand)); } - LookupResult Lookup = LookupParsedName(S, SS, Name, LookupOrdinaryName, - false, true, Loc); + LookupResult Lookup; + LookupParsedName(Lookup, S, SS, Name, LookupOrdinaryName, false, true, Loc); if (Lookup.isAmbiguous()) { DiagnoseAmbiguousLookup(Lookup, Name, Loc, @@ -861,8 +704,8 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, : SourceRange()); return ExprError(); } - - NamedDecl *D = Lookup.getAsDecl(); + + NamedDecl *D = Lookup.getAsSingleDecl(Context); // If this reference is in an Objective-C method, then ivar lookup happens as // well. @@ -870,8 +713,8 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, if (II && getCurMethodDecl()) { // There are two cases to handle here. 1) scoped lookup could have failed, // in which case we should look for an ivar. 2) scoped lookup could have - // found a decl, but that decl is outside the current instance method (i.e. - // a global variable). In these two cases, we do a lookup for an ivar with + // found a decl, but that decl is outside the current instance method (i.e. + // a global variable). In these two cases, we do a lookup for an ivar with // this name, if the lookup sucedes, we replace it our current decl. if (D == 0 || D->isDefinedOutsideFunctionOrMethod()) { ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); @@ -880,12 +723,12 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // Check if referencing a field with __attribute__((deprecated)). if (DiagnoseUseOfDecl(IV, Loc)) return ExprError(); - + // If we're referencing an invalid decl, just return this as a silent // error node. The error diagnostic was already emitted on the decl. if (IV->isInvalidDecl()) return ExprError(); - + bool IsClsMethod = getCurMethodDecl()->isClassMethod(); // If a class method attemps to use a free standing ivar, this is // an error. @@ -901,15 +744,15 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // FIXME: This should use a new expr for a direct reference, don't // turn this into Self->ivar, just return a BareIVarExpr or something. IdentifierInfo &II = Context.Idents.get("self"); - OwningExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false); + OwningExprResult SelfExpr = ActOnIdentifierExpr(S, SourceLocation(), + II, false); MarkDeclarationReferenced(Loc, IV); - return Owned(new (Context) - ObjCIvarRefExpr(IV, IV->getType(), Loc, + return Owned(new (Context) + ObjCIvarRefExpr(IV, IV->getType(), Loc, SelfExpr.takeAs<Expr>(), true, true)); } } - } - else if (getCurMethodDecl()->isInstanceMethod()) { + } else if (getCurMethodDecl()->isInstanceMethod()) { // We should warn if a local variable hides an ivar. ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); ObjCInterfaceDecl *ClassDeclared; @@ -922,10 +765,10 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // Needed to implement property "super.method" notation. if (D == 0 && II->isStr("super")) { QualType T; - + if (getCurMethodDecl()->isInstanceMethod()) - T = Context.getPointerType(Context.getObjCInterfaceType( - getCurMethodDecl()->getClassInterface())); + T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType( + getCurMethodDecl()->getClassInterface())); else T = Context.getObjCClassType(); return Owned(new (Context) ObjCSuperExpr(Loc, T)); @@ -934,7 +777,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // Determine whether this name might be a candidate for // argument-dependent lookup. - bool ADL = getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && + bool ADL = getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && HasTrailingLParen; if (ADL && D == 0) { @@ -960,8 +803,9 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // If this name wasn't predeclared and if this is not a function call, // diagnose the problem. if (SS && !SS->isEmpty()) - return ExprError(Diag(Loc, diag::err_typecheck_no_member) - << Name << SS->getRange()); + return ExprError(Diag(Loc, diag::err_no_member) + << Name << computeDeclContext(*SS, false) + << SS->getRange()); else if (Name.getNameKind() == DeclarationName::CXXOperatorName || Name.getNameKind() == DeclarationName::CXXConversionFunctionName) return ExprError(Diag(Loc, diag::err_undeclared_use) @@ -970,18 +814,18 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, return ExprError(Diag(Loc, diag::err_undeclared_var_use) << Name); } } - + if (VarDecl *Var = dyn_cast<VarDecl>(D)) { // Warn about constructs like: // if (void *X = foo()) { ... } else { X }. // In the else block, the pointer is always false. - + // FIXME: In a template instantiation, we don't have scope // information to check this property. if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) { Scope *CheckS = S; while (CheckS) { - if (CheckS->isWithinElse() && + if (CheckS->isWithinElse() && CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) { if (Var->getType()->isBooleanType()) ExprError(Diag(Loc, diag::warn_value_always_false) @@ -991,7 +835,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, << Var->getDeclName()); break; } - + // Move up one more control parent to check again. CheckS = CheckS->getControlParent(); if (CheckS) @@ -1010,24 +854,66 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, QualType T = Func->getType(); QualType NoProtoType = T; - if (const FunctionProtoType *Proto = T->getAsFunctionProtoType()) + if (const FunctionProtoType *Proto = T->getAs<FunctionProtoType>()) NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType()); return BuildDeclRefExpr(Func, NoProtoType, Loc, false, false, SS); } } - + return BuildDeclarationNameExpr(Loc, D, HasTrailingLParen, SS, isAddressOfOperand); } +/// \brief Cast member's object to its own class if necessary. +bool +Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) { + if (FieldDecl *FD = dyn_cast<FieldDecl>(Member)) + if (CXXRecordDecl *RD = + dyn_cast<CXXRecordDecl>(FD->getDeclContext())) { + QualType DestType = + Context.getCanonicalType(Context.getTypeDeclType(RD)); + if (DestType->isDependentType() || From->getType()->isDependentType()) + return false; + QualType FromRecordType = From->getType(); + QualType DestRecordType = DestType; + if (FromRecordType->getAs<PointerType>()) { + DestType = Context.getPointerType(DestType); + FromRecordType = FromRecordType->getPointeeType(); + } + if (!Context.hasSameUnqualifiedType(FromRecordType, DestRecordType) && + CheckDerivedToBaseConversion(FromRecordType, + DestRecordType, + From->getSourceRange().getBegin(), + From->getSourceRange())) + return true; + ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, + /*isLvalue=*/true); + } + return false; +} + +/// \brief Build a MemberExpr AST node. +static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, + const CXXScopeSpec *SS, NamedDecl *Member, + SourceLocation Loc, QualType Ty) { + if (SS && SS->isSet()) + return MemberExpr::Create(C, Base, isArrow, + (NestedNameSpecifier *)SS->getScopeRep(), + SS->getRange(), Member, Loc, + // FIXME: Explicit template argument lists + false, SourceLocation(), 0, 0, SourceLocation(), + Ty); + + return new (C) MemberExpr(Base, isArrow, Member, Loc, Ty); +} /// \brief Complete semantic analysis for a reference to the given declaration. Sema::OwningExprResult Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, bool HasTrailingLParen, - const CXXScopeSpec *SS, + const CXXScopeSpec *SS, bool isAddressOfOperand) { assert(D && "Cannot refer to a NULL declaration"); DeclarationName Name = D->getDeclName(); - + // If this is an expression of the form &Class::member, don't build an // implicit member ref, because we want a pointer to the member in general, // not any specific instance's member. @@ -1060,7 +946,7 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) { if (!MD->isStatic()) { - // C++ [class.mfct.nonstatic]p2: + // C++ [class.mfct.nonstatic]p2: // [...] if name lookup (3.4.1) resolves the name in the // id-expression to a nonstatic nontype member of class X or of // a base class of X, the id-expression is transformed into a @@ -1072,45 +958,74 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, Ctx = FD->getDeclContext(); MemberType = FD->getType(); - if (const ReferenceType *RefType = MemberType->getAsReferenceType()) + if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>()) MemberType = RefType->getPointeeType(); - else if (!FD->isMutable()) { - unsigned combinedQualifiers - = MemberType.getCVRQualifiers() | MD->getTypeQualifiers(); - MemberType = MemberType.getQualifiedType(combinedQualifiers); - } + else if (!FD->isMutable()) + MemberType + = Context.getQualifiedType(MemberType, + Qualifiers::fromCVRMask(MD->getTypeQualifiers())); } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { if (!Method->isStatic()) { Ctx = Method->getParent(); MemberType = Method->getType(); } - } else if (OverloadedFunctionDecl *Ovl + } else if (FunctionTemplateDecl *FunTmpl + = dyn_cast<FunctionTemplateDecl>(D)) { + if (CXXMethodDecl *Method + = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())) { + if (!Method->isStatic()) { + Ctx = Method->getParent(); + MemberType = Context.OverloadTy; + } + } + } else if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) { - for (OverloadedFunctionDecl::function_iterator + // FIXME: We need an abstraction for iterating over one or more function + // templates or functions. This code is far too repetitive! + for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(), FuncEnd = Ovl->function_end(); Func != FuncEnd; ++Func) { - if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(*Func)) - if (!DMethod->isStatic()) { - Ctx = Ovl->getDeclContext(); - MemberType = Context.OverloadTy; - break; - } + CXXMethodDecl *DMethod = 0; + if (FunctionTemplateDecl *FunTmpl + = dyn_cast<FunctionTemplateDecl>(*Func)) + DMethod = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); + else + DMethod = dyn_cast<CXXMethodDecl>(*Func); + + if (DMethod && !DMethod->isStatic()) { + Ctx = DMethod->getDeclContext(); + MemberType = Context.OverloadTy; + break; + } } } if (Ctx && Ctx->isRecord()) { QualType CtxType = Context.getTagDeclType(cast<CXXRecordDecl>(Ctx)); QualType ThisType = Context.getTagDeclType(MD->getParent()); - if ((Context.getCanonicalType(CtxType) + if ((Context.getCanonicalType(CtxType) == Context.getCanonicalType(ThisType)) || IsDerivedFrom(ThisType, CtxType)) { // Build the implicit member access expression. Expr *This = new (Context) CXXThisExpr(SourceLocation(), MD->getThisType(Context)); MarkDeclarationReferenced(Loc, D); - return Owned(new (Context) MemberExpr(This, true, D, - Loc, MemberType)); + if (PerformObjectMemberConversion(This, D)) + return ExprError(); + + bool ShouldCheckUse = true; + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + // Don't diagnose the use of a virtual member function unless it's + // explicitly qualified. + if (MD->isVirtual() && (!SS || !SS->isSet())) + ShouldCheckUse = false; + } + + if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc)) + return ExprError(); + return Owned(BuildMemberExpr(Context, This, true, SS, D, + Loc, MemberType)); } } } @@ -1145,13 +1060,18 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, else if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) return BuildDeclRefExpr(Template, Context.OverloadTy, Loc, false, false, SS); + else if (UnresolvedUsingDecl *UD = dyn_cast<UnresolvedUsingDecl>(D)) + return BuildDeclRefExpr(UD, Context.DependentTy, Loc, + /*TypeDependent=*/true, + /*ValueDependent=*/true, SS); + ValueDecl *VD = cast<ValueDecl>(D); // Check whether this declaration can be used. Note that we suppress // this check when we're going to perform argument-dependent lookup // on this function name, because this might not be the function // that overload resolution actually selects. - bool ADL = getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && + bool ADL = getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && HasTrailingLParen; if (!(ADL && isa<FunctionDecl>(VD)) && DiagnoseUseOfDecl(VD, Loc)) return ExprError(); @@ -1177,9 +1097,9 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, // This is to record that a 'const' was actually synthesize and added. bool constAdded = !ExprTy.isConstQualified(); // Variable will be bound by-copy, make it const within the closure. - + ExprTy.addConst(); - return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false, + return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false, constAdded)); } // If this reference is not in a block or if the referenced variable is @@ -1189,7 +1109,7 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, bool ValueDependent = false; if (getLangOptions().CPlusPlus) { // C++ [temp.dep.expr]p3: - // An id-expression is type-dependent if it contains: + // An id-expression is type-dependent if it contains: // - an identifier that was declared with a dependent type, if (VD->getType()->isDependentType()) TypeDependent = true; @@ -1226,7 +1146,7 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, // - a constant with integral or enumeration type and is // initialized with an expression that is value-dependent else if (const VarDecl *Dcl = dyn_cast<VarDecl>(VD)) { - if (Dcl->getType().getCVRQualifiers() == QualType::Const && + if (Dcl->getType().getCVRQualifiers() == Qualifiers::Const && Dcl->getInit()) { ValueDependent = Dcl->getInit()->isValueDependent(); } @@ -1250,21 +1170,24 @@ Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, // Pre-defined identifiers are of type char[x], where x is the length of the // string. - unsigned Length; - if (FunctionDecl *FD = getCurFunctionDecl()) - Length = FD->getIdentifier()->getLength(); - else if (ObjCMethodDecl *MD = getCurMethodDecl()) - Length = MD->getSynthesizedMethodSize(); - else { + + Decl *currentDecl = getCurFunctionOrMethodDecl(); + if (!currentDecl) { Diag(Loc, diag::ext_predef_outside_function); - // __PRETTY_FUNCTION__ -> "top level", the others produce an empty string. - Length = IT == PredefinedExpr::PrettyFunction ? strlen("top level") : 0; + currentDecl = Context.getTranslationUnitDecl(); } + QualType ResTy; + if (cast<DeclContext>(currentDecl)->isDependentContext()) { + ResTy = Context.DependentTy; + } else { + unsigned Length = + PredefinedExpr::ComputeName(Context, IT, currentDecl).length(); - llvm::APInt LengthI(32, Length + 1); - QualType ResTy = Context.CharTy.getQualifiedType(QualType::Const); - ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0); + llvm::APInt LengthI(32, Length + 1); + ResTy = Context.CharTy.withConst(); + ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0); + } return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT)); } @@ -1304,7 +1227,7 @@ Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) { // Get the spelling of the token, which eliminates trigraphs, etc. unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin); - NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength, + NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength, Tok.getLocation(), PP); if (Literal.hadError) return ExprError(); @@ -1417,7 +1340,7 @@ Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) { // If this is an imaginary literal, create the ImaginaryLiteral wrapper. if (Literal.isImaginary) - Res = new (Context) ImaginaryLiteral(Res, + Res = new (Context) ImaginaryLiteral(Res, Context.getComplexType(Res->getType())); return Owned(Res); @@ -1446,27 +1369,27 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType, Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange; return false; } - + // Allow sizeof(void)/alignof(void) as an extension. if (exprType->isVoidType()) { Diag(OpLoc, diag::ext_sizeof_void_type) << (isSizeof ? "sizeof" : "__alignof") << ExprRange; return false; } - + if (RequireCompleteType(OpLoc, exprType, - isSizeof ? diag::err_sizeof_incomplete_type : - diag::err_alignof_incomplete_type, - ExprRange)) + isSizeof ? diag::err_sizeof_incomplete_type : + PDiag(diag::err_alignof_incomplete_type) + << ExprRange)) return true; - + // Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode. if (LangOpts.ObjCNonFragileABI && exprType->isObjCInterfaceType()) { Diag(OpLoc, diag::err_sizeof_nonfragile_interface) << exprType << isSizeof << ExprRange; return true; } - + return false; } @@ -1474,7 +1397,7 @@ bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, const SourceRange &ExprRange) { E = E->IgnoreParens(); - // alignof decl is always ok. + // alignof decl is always ok. if (isa<DeclRefExpr>(E)) return false; @@ -1490,15 +1413,15 @@ bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, // Alignment of a field access is always okay, so long as it isn't a // bit-field. if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) - if (dyn_cast<FieldDecl>(ME->getMemberDecl())) + if (isa<FieldDecl>(ME->getMemberDecl())) return false; return CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false); } /// \brief Build a sizeof or alignof expression given a type operand. -Action::OwningExprResult -Sema::CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc, +Action::OwningExprResult +Sema::CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc, bool isSizeOf, SourceRange R) { if (T.isNull()) return ExprError(); @@ -1515,8 +1438,8 @@ Sema::CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc, /// \brief Build a sizeof or alignof expression given an expression /// operand. -Action::OwningExprResult -Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, +Action::OwningExprResult +Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, bool isSizeOf, SourceRange R) { // Verify that the operand is valid. bool isInvalid = false; @@ -1550,9 +1473,10 @@ Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, if (TyOrEx == 0) return ExprError(); if (isType) { - QualType ArgTy = QualType::getFromOpaquePtr(TyOrEx); + // FIXME: Preserve type source info. + QualType ArgTy = GetTypeFromParser(TyOrEx); return CreateSizeOfAlignOfExpr(ArgTy, OpLoc, isSizeof, ArgRange); - } + } // Get the end location. Expr *ArgEx = (Expr *)TyOrEx; @@ -1568,15 +1492,15 @@ Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) { if (V->isTypeDependent()) return Context.DependentTy; - + // These operators return the element type of a complex type. - if (const ComplexType *CT = V->getType()->getAsComplexType()) + if (const ComplexType *CT = V->getType()->getAs<ComplexType>()) return CT->getElementType(); - + // Otherwise they pass through real integer and floating point types here. if (V->getType()->isArithmeticType()) return V->getType(); - + // Reject anything else. Diag(Loc, diag::err_realimag_invalid_type) << V->getType() << (isReal ? "__real" : "__imag"); @@ -1588,6 +1512,8 @@ QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) { Action::OwningExprResult Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Kind, ExprArg Input) { + // Since this might be a postfix expression, get rid of ParenListExprs. + Input = MaybeConvertParenListExprToParenExpr(S, move(Input)); Expr *Arg = (Expr *)Input.get(); UnaryOperator::Opcode Opc; @@ -1612,9 +1538,9 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, // for objects of that type. When the postfix increment is // called as a result of using the ++ operator, the int // argument will have value zero. - Expr *Args[2] = { - Arg, - new (Context) IntegerLiteral(llvm::APInt(Context.Target.getIntWidth(), 0, + Expr *Args[2] = { + Arg, + new (Context) IntegerLiteral(llvm::APInt(Context.Target.getIntWidth(), 0, /*isSigned=*/true), Context.IntTy, SourceLocation()) }; @@ -1646,9 +1572,7 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, } // Determine the result type - QualType ResultTy - = FnDecl->getType()->getAsFunctionType()->getResultType(); - ResultTy = ResultTy.getNonReferenceType(); + QualType ResultTy = FnDecl->getResultType().getNonReferenceType(); // Build the actual expression node. Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), @@ -1657,9 +1581,17 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, Input.release(); Args[0] = Arg; - return Owned(new (Context) CXXOperatorCallExpr(Context, OverOp, FnExpr, - Args, 2, ResultTy, - OpLoc)); + + ExprOwningPtr<CXXOperatorCallExpr> + TheCall(this, new (Context) CXXOperatorCallExpr(Context, OverOp, + FnExpr, Args, 2, + ResultTy, OpLoc)); + + if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall.get(), + FnDecl)) + return ExprError(); + return Owned(TheCall.release()); + } else { // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in @@ -1672,11 +1604,19 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, } } - case OR_No_Viable_Function: - // No viable function; fall through to handling this as a - // built-in operator, which will produce an error message for us. - break; - + case OR_No_Viable_Function: { + // No viable function; try checking this as a built-in operator, which + // will fail and provide a diagnostic. Then, print the overload + // candidates. + OwningExprResult Result = CreateBuiltinUnaryOp(OpLoc, Opc, move(Input)); + assert(Result.isInvalid() && + "C++ postfix-unary operator overloading is missing candidates!"); + if (Result.isInvalid()) + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); + + return move(Result); + } + case OR_Ambiguous: Diag(OpLoc, diag::err_ovl_ambiguous_oper) << UnaryOperator::getOpcodeStr(Opc) @@ -1698,17 +1638,17 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, // build a built-in operation. } - QualType result = CheckIncrementDecrementOperand(Arg, OpLoc, - Opc == UnaryOperator::PostInc); - if (result.isNull()) - return ExprError(); Input.release(); - return Owned(new (Context) UnaryOperator(Arg, Opc, result, OpLoc)); + Input = Arg; + return CreateBuiltinUnaryOp(OpLoc, Opc, move(Input)); } Action::OwningExprResult Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, ExprArg Idx, SourceLocation RLoc) { + // Since this might be a postfix expression, get rid of ParenListExprs. + Base = MaybeConvertParenListExprToParenExpr(S, move(Base)); + Expr *LHSExp = static_cast<Expr*>(Base.get()), *RHSExp = static_cast<Expr*>(Idx.get()); @@ -1720,12 +1660,12 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, Context.DependentTy, RLoc)); } - if (getLangOptions().CPlusPlus && + if (getLangOptions().CPlusPlus && (LHSExp->getType()->isRecordType() || LHSExp->getType()->isEnumeralType() || RHSExp->getType()->isRecordType() || RHSExp->getType()->isEnumeralType())) { - // Add the appropriate overloaded operators (C++ [over.match.oper]) + // Add the appropriate overloaded operators (C++ [over.match.oper]) // to the candidate set. OverloadCandidateSet CandidateSet; Expr *Args[2] = { LHSExp, RHSExp }; @@ -1746,7 +1686,7 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { if (PerformObjectArgumentInitialization(LHSExp, Method) || - PerformCopyInitialization(RHSExp, + PerformCopyInitialization(RHSExp, FnDecl->getParamDecl(0)->getType(), "passing")) return ExprError(); @@ -1762,9 +1702,7 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, } // Determine the result type - QualType ResultTy - = FnDecl->getType()->getAsFunctionType()->getResultType(); - ResultTy = ResultTy.getNonReferenceType(); + QualType ResultTy = FnDecl->getResultType().getNonReferenceType(); // Build the actual expression node. Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), @@ -1775,9 +1713,16 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, Idx.release(); Args[0] = LHSExp; Args[1] = RHSExp; - return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, - FnExpr, Args, 2, - ResultTy, LLoc)); + + ExprOwningPtr<CXXOperatorCallExpr> + TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Subscript, + FnExpr, Args, 2, + ResultTy, RLoc)); + if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall.get(), + FnDecl)) + return ExprError(); + + return Owned(TheCall.release()); } else { // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in @@ -1834,16 +1779,27 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, BaseExpr = LHSExp; IndexExpr = RHSExp; ResultType = Context.DependentTy; - } else if (const PointerType *PTy = LHSTy->getAsPointerType()) { + } else if (const PointerType *PTy = LHSTy->getAs<PointerType>()) { + BaseExpr = LHSExp; + IndexExpr = RHSExp; + ResultType = PTy->getPointeeType(); + } else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) { + // Handle the uncommon case of "123[Ptr]". + BaseExpr = RHSExp; + IndexExpr = LHSExp; + ResultType = PTy->getPointeeType(); + } else if (const ObjCObjectPointerType *PTy = + LHSTy->getAs<ObjCObjectPointerType>()) { BaseExpr = LHSExp; IndexExpr = RHSExp; ResultType = PTy->getPointeeType(); - } else if (const PointerType *PTy = RHSTy->getAsPointerType()) { + } else if (const ObjCObjectPointerType *PTy = + RHSTy->getAs<ObjCObjectPointerType>()) { // Handle the uncommon case of "123[Ptr]". BaseExpr = RHSExp; IndexExpr = LHSExp; ResultType = PTy->getPointeeType(); - } else if (const VectorType *VTy = LHSTy->getAsVectorType()) { + } else if (const VectorType *VTy = LHSTy->getAs<VectorType>()) { BaseExpr = LHSExp; // vectors: V[123] IndexExpr = RHSExp; @@ -1862,7 +1818,7 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, BaseExpr = LHSExp; IndexExpr = RHSExp; - ResultType = LHSTy->getAsPointerType()->getPointeeType(); + ResultType = LHSTy->getAs<PointerType>()->getPointeeType(); } else if (RHSTy->isArrayType()) { // Same as previous, except for 123[f().a] case Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << @@ -1872,38 +1828,45 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, BaseExpr = RHSExp; IndexExpr = LHSExp; - ResultType = RHSTy->getAsPointerType()->getPointeeType(); + ResultType = RHSTy->getAs<PointerType>()->getPointeeType(); } else { return ExprError(Diag(LLoc, diag::err_typecheck_subscript_value) << LHSExp->getSourceRange() << RHSExp->getSourceRange()); } // C99 6.5.2.1p1 - if (!IndexExpr->getType()->isIntegerType() && !IndexExpr->isTypeDependent()) + if (!(IndexExpr->getType()->isIntegerType() && + IndexExpr->getType()->isScalarType()) && !IndexExpr->isTypeDependent()) return ExprError(Diag(LLoc, diag::err_typecheck_subscript_not_integer) << IndexExpr->getSourceRange()); + if ((IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || + IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) + && !IndexExpr->isTypeDependent()) + Diag(LLoc, diag::warn_subscript_is_char) << IndexExpr->getSourceRange(); + // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly, - // C++ [expr.sub]p1: The type "T" shall be a completely-defined object - // type. Note that Functions are not objects, and that (in C99 parlance) + // C++ [expr.sub]p1: The type "T" shall be a completely-defined object + // type. Note that Functions are not objects, and that (in C99 parlance) // incomplete types are not object types. if (ResultType->isFunctionType()) { Diag(BaseExpr->getLocStart(), diag::err_subscript_function_type) << ResultType << BaseExpr->getSourceRange(); return ExprError(); } - + if (!ResultType->isDependentType() && - RequireCompleteType(LLoc, ResultType, diag::err_subscript_incomplete_type, - BaseExpr->getSourceRange())) + RequireCompleteType(LLoc, ResultType, + PDiag(diag::err_subscript_incomplete_type) + << BaseExpr->getSourceRange())) return ExprError(); - + // Diagnose bad cases where we step over interface counts. if (ResultType->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { Diag(LLoc, diag::err_subscript_nonfragile_interface) << ResultType << BaseExpr->getSourceRange(); return ExprError(); } - + Base.release(); Idx.release(); return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp, @@ -1912,11 +1875,12 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, QualType Sema:: CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc, - IdentifierInfo &CompName, SourceLocation CompLoc) { - const ExtVectorType *vecType = baseType->getAsExtVectorType(); + const IdentifierInfo *CompName, + SourceLocation CompLoc) { + const ExtVectorType *vecType = baseType->getAs<ExtVectorType>(); // The vector accessor can't exceed the number of elements. - const char *compStr = CompName.getName(); + const char *compStr = CompName->getName(); // This flag determines whether or not the component is one of the four // special names that indicate a subset of exactly half the elements are @@ -1953,7 +1917,7 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc, // Ensure no component accessor exceeds the width of the vector type it // operates on. if (!HalvingSwizzle) { - compStr = CompName.getName(); + compStr = CompName->getName(); if (HexSwizzle) compStr++; @@ -1981,7 +1945,7 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc, // vec4.s0 is a float, vec4.s23 is a vec3, etc. // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2. unsigned CompSize = HalvingSwizzle ? vecType->getNumElements() / 2 - : CompName.getLength(); + : CompName->getLength(); if (HexSwizzle) CompSize--; @@ -1999,18 +1963,18 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc, } static Decl *FindGetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl, - IdentifierInfo &Member, + IdentifierInfo *Member, const Selector &Sel, ASTContext &Context) { - - if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(&Member)) + + if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Member)) return PD; if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel)) return OMD; - + for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(), E = PDecl->protocol_end(); I != E; ++I) { - if (Decl *D = FindGetterNameDeclFromProtocolList(*I, Member, Sel, + if (Decl *D = FindGetterNameDeclFromProtocolList(*I, Member, Sel, Context)) return D; } @@ -2018,14 +1982,14 @@ static Decl *FindGetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl, } static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy, - IdentifierInfo &Member, + IdentifierInfo *Member, const Selector &Sel, ASTContext &Context) { // Check protocols on qualified interfaces. Decl *GDecl = 0; for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), E = QIdTy->qual_end(); I != E; ++I) { - if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member)) { + if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { GDecl = PD; break; } @@ -2047,101 +2011,213 @@ static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy, return GDecl; } -/// FindMethodInNestedImplementations - Look up a method in current and -/// all base class implementations. -/// -ObjCMethodDecl *Sema::FindMethodInNestedImplementations( - const ObjCInterfaceDecl *IFace, - const Selector &Sel) { - ObjCMethodDecl *Method = 0; - if (ObjCImplementationDecl *ImpDecl - = LookupObjCImplementation(IFace->getIdentifier())) - Method = ImpDecl->getInstanceMethod(Sel); - - if (!Method && IFace->getSuperClass()) - return FindMethodInNestedImplementations(IFace->getSuperClass(), Sel); - return Method; -} - Action::OwningExprResult -Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, +Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, tok::TokenKind OpKind, SourceLocation MemberLoc, - IdentifierInfo &Member, - DeclPtrTy ObjCImpDecl) { + DeclarationName MemberName, + bool HasExplicitTemplateArgs, + SourceLocation LAngleLoc, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + SourceLocation RAngleLoc, + DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS, + NamedDecl *FirstQualifierInScope) { + if (SS && SS->isInvalid()) + return ExprError(); + + // Since this might be a postfix expression, get rid of ParenListExprs. + Base = MaybeConvertParenListExprToParenExpr(S, move(Base)); + Expr *BaseExpr = Base.takeAs<Expr>(); - assert(BaseExpr && "no record expression"); + assert(BaseExpr && "no base expression"); // Perform default conversions. DefaultFunctionArrayConversion(BaseExpr); QualType BaseType = BaseExpr->getType(); + // If this is an Objective-C pseudo-builtin and a definition is provided then + // use that. + if (BaseType->isObjCIdType()) { + // We have an 'id' type. Rather than fall through, we check if this + // is a reference to 'isa'. + if (BaseType != Context.ObjCIdRedefinitionType) { + BaseType = Context.ObjCIdRedefinitionType; + ImpCastExprToType(BaseExpr, BaseType); + } + } assert(!BaseType.isNull() && "no type for member expression"); + // Handle properties on ObjC 'Class' types. + if (OpKind == tok::period && BaseType->isObjCClassType()) { + // Also must look for a getter name which uses property syntax. + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + Selector Sel = PP.getSelectorTable().getNullarySelector(Member); + if (ObjCMethodDecl *MD = getCurMethodDecl()) { + ObjCInterfaceDecl *IFace = MD->getClassInterface(); + ObjCMethodDecl *Getter; + // FIXME: need to also look locally in the implementation. + if ((Getter = IFace->lookupClassMethod(Sel))) { + // Check the use of this method. + if (DiagnoseUseOfDecl(Getter, MemberLoc)) + return ExprError(); + } + // If we found a getter then this may be a valid dot-reference, we + // will look for the matching setter, in case it is needed. + Selector SetterSel = + SelectorTable::constructSetterName(PP.getIdentifierTable(), + PP.getSelectorTable(), Member); + ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); + if (!Setter) { + // If this reference is in an @implementation, also check for 'private' + // methods. + Setter = IFace->lookupPrivateInstanceMethod(SetterSel); + } + // Look through local category implementations associated with the class. + if (!Setter) + Setter = IFace->getCategoryClassMethod(SetterSel); + + if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) + return ExprError(); + + if (Getter || Setter) { + QualType PType; + + if (Getter) + PType = Getter->getResultType(); + else + // Get the expression type from Setter's incoming parameter. + PType = (*(Setter->param_end() -1))->getType(); + // FIXME: we must check that the setter has property type. + return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, + PType, + Setter, MemberLoc, BaseExpr)); + } + return ExprError(Diag(MemberLoc, diag::err_property_not_found) + << MemberName << BaseType); + } + } + + if (BaseType->isObjCClassType() && + BaseType != Context.ObjCClassRedefinitionType) { + BaseType = Context.ObjCClassRedefinitionType; + ImpCastExprToType(BaseExpr, BaseType); + } + // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr // must have pointer type, and the accessed type is the pointee. if (OpKind == tok::arrow) { - if (BaseType->isDependentType()) - return Owned(new (Context) CXXUnresolvedMemberExpr(Context, - BaseExpr, true, - OpLoc, - DeclarationName(&Member), - MemberLoc)); - else if (const PointerType *PT = BaseType->getAsPointerType()) + if (BaseType->isDependentType()) { + NestedNameSpecifier *Qualifier = 0; + if (SS) { + Qualifier = static_cast<NestedNameSpecifier *>(SS->getScopeRep()); + if (!FirstQualifierInScope) + FirstQualifierInScope = FindFirstQualifierInScope(S, Qualifier); + } + + return Owned(CXXUnresolvedMemberExpr::Create(Context, BaseExpr, true, + OpLoc, Qualifier, + SS? SS->getRange() : SourceRange(), + FirstQualifierInScope, + MemberName, + MemberLoc, + HasExplicitTemplateArgs, + LAngleLoc, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + RAngleLoc)); + } + else if (const PointerType *PT = BaseType->getAs<PointerType>()) BaseType = PT->getPointeeType(); - else if (getLangOptions().CPlusPlus && BaseType->isRecordType()) - return Owned(BuildOverloadedArrowExpr(S, BaseExpr, OpLoc, - MemberLoc, Member)); + else if (BaseType->isObjCObjectPointerType()) + ; else return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) << BaseType << BaseExpr->getSourceRange()); - } else { - if (BaseType->isDependentType()) { - // Require that the base type isn't a pointer type + } else if (BaseType->isDependentType()) { + // Require that the base type isn't a pointer type // (so we'll report an error for) // T* t; // t.f; - // + // // In Obj-C++, however, the above expression is valid, since it could be // accessing the 'f' property if T is an Obj-C interface. The extra check // allows this, while still reporting an error if T is a struct pointer. - const PointerType *PT = BaseType->getAsPointerType(); + const PointerType *PT = BaseType->getAs<PointerType>(); + + if (!PT || (getLangOptions().ObjC1 && + !PT->getPointeeType()->isRecordType())) { + NestedNameSpecifier *Qualifier = 0; + if (SS) { + Qualifier = static_cast<NestedNameSpecifier *>(SS->getScopeRep()); + if (!FirstQualifierInScope) + FirstQualifierInScope = FindFirstQualifierInScope(S, Qualifier); + } - if (!PT || (getLangOptions().ObjC1 && - !PT->getPointeeType()->isRecordType())) - return Owned(new (Context) CXXUnresolvedMemberExpr(Context, - BaseExpr, false, - OpLoc, - DeclarationName(&Member), - MemberLoc)); + return Owned(CXXUnresolvedMemberExpr::Create(Context, + BaseExpr, false, + OpLoc, + Qualifier, + SS? SS->getRange() : SourceRange(), + FirstQualifierInScope, + MemberName, + MemberLoc, + HasExplicitTemplateArgs, + LAngleLoc, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + RAngleLoc)); + } } - } // Handle field access to simple records. This also handles access to fields // of the ObjC 'id' struct. - if (const RecordType *RTy = BaseType->getAsRecordType()) { + if (const RecordType *RTy = BaseType->getAs<RecordType>()) { RecordDecl *RDecl = RTy->getDecl(); if (RequireCompleteType(OpLoc, BaseType, - diag::err_typecheck_incomplete_tag, - BaseExpr->getSourceRange())) + PDiag(diag::err_typecheck_incomplete_tag) + << BaseExpr->getSourceRange())) return ExprError(); + DeclContext *DC = RDecl; + if (SS && SS->isSet()) { + // If the member name was a qualified-id, look into the + // nested-name-specifier. + DC = computeDeclContext(*SS, false); + + // FIXME: If DC is not computable, we should build a + // CXXUnresolvedMemberExpr. + assert(DC && "Cannot handle non-computable dependent contexts in lookup"); + } + // The record definition is complete, now make sure the member is valid. - // FIXME: Qualified name lookup for C++ is a bit more complicated than this. - LookupResult Result - = LookupQualifiedName(RDecl, DeclarationName(&Member), - LookupMemberName, false); - - if (!Result) - return ExprError(Diag(MemberLoc, diag::err_typecheck_no_member) - << &Member << BaseExpr->getSourceRange()); + LookupResult Result; + LookupQualifiedName(Result, DC, MemberName, LookupMemberName, false); + + if (Result.empty()) + return ExprError(Diag(MemberLoc, diag::err_no_member) + << MemberName << DC << BaseExpr->getSourceRange()); if (Result.isAmbiguous()) { - DiagnoseAmbiguousLookup(Result, DeclarationName(&Member), - MemberLoc, BaseExpr->getSourceRange()); + DiagnoseAmbiguousLookup(Result, MemberName, MemberLoc, + BaseExpr->getSourceRange()); return ExprError(); } - - NamedDecl *MemberDecl = Result; + + NamedDecl *MemberDecl = Result.getAsSingleDecl(Context); + + if (SS && SS->isSet()) { + TypeDecl* TyD = cast<TypeDecl>(MemberDecl->getDeclContext()); + QualType BaseTypeCanon + = Context.getCanonicalType(BaseType).getUnqualifiedType(); + QualType MemberTypeCanon + = Context.getCanonicalType(Context.getTypeDeclType(TyD)); + + if (BaseTypeCanon != MemberTypeCanon && + !IsDerivedFrom(BaseTypeCanon, MemberTypeCanon)) + return ExprError(Diag(SS->getBeginLoc(), + diag::err_not_direct_base_or_virtual) + << MemberTypeCanon << BaseTypeCanon); + } // If the decl being referenced had an error, return an error for this // sub-expr without emitting another error, in order to avoid cascading @@ -2149,8 +2225,16 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, if (MemberDecl->isInvalidDecl()) return ExprError(); + bool ShouldCheckUse = true; + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) { + // Don't diagnose the use of a virtual member function unless it's + // explicitly qualified. + if (MD->isVirtual() && (!SS || !SS->isSet())) + ShouldCheckUse = false; + } + // Check the use of this field - if (DiagnoseUseOfDecl(MemberDecl, MemberLoc)) + if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) return ExprError(); if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) { @@ -2161,137 +2245,253 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, BaseExpr, OpLoc); // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref] - // FIXME: Handle address space modifiers QualType MemberType = FD->getType(); - if (const ReferenceType *Ref = MemberType->getAsReferenceType()) + if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) MemberType = Ref->getPointeeType(); else { - unsigned combinedQualifiers = - MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers(); - if (FD->isMutable()) - combinedQualifiers &= ~QualType::Const; - MemberType = MemberType.getQualifiedType(combinedQualifiers); + Qualifiers BaseQuals = BaseType.getQualifiers(); + BaseQuals.removeObjCGCAttr(); + if (FD->isMutable()) BaseQuals.removeConst(); + + Qualifiers MemberQuals + = Context.getCanonicalType(MemberType).getQualifiers(); + + Qualifiers Combined = BaseQuals + MemberQuals; + if (Combined != MemberQuals) + MemberType = Context.getQualifiedType(MemberType, Combined); } MarkDeclarationReferenced(MemberLoc, FD); - return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, FD, - MemberLoc, MemberType)); + if (PerformObjectMemberConversion(BaseExpr, FD)) + return ExprError(); + return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, + FD, MemberLoc, MemberType)); } - + if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, - Var, MemberLoc, - Var->getType().getNonReferenceType())); + return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, + Var, MemberLoc, + Var->getType().getNonReferenceType())); } if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) { MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, - MemberFn, MemberLoc, - MemberFn->getType())); + return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, + MemberFn, MemberLoc, + MemberFn->getType())); + } + if (FunctionTemplateDecl *FunTmpl + = dyn_cast<FunctionTemplateDecl>(MemberDecl)) { + MarkDeclarationReferenced(MemberLoc, MemberDecl); + + if (HasExplicitTemplateArgs) + return Owned(MemberExpr::Create(Context, BaseExpr, OpKind == tok::arrow, + (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0), + SS? SS->getRange() : SourceRange(), + FunTmpl, MemberLoc, true, + LAngleLoc, ExplicitTemplateArgs, + NumExplicitTemplateArgs, RAngleLoc, + Context.OverloadTy)); + + return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, + FunTmpl, MemberLoc, + Context.OverloadTy)); } if (OverloadedFunctionDecl *Ovl - = dyn_cast<OverloadedFunctionDecl>(MemberDecl)) - return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, Ovl, - MemberLoc, Context.OverloadTy)); + = dyn_cast<OverloadedFunctionDecl>(MemberDecl)) { + if (HasExplicitTemplateArgs) + return Owned(MemberExpr::Create(Context, BaseExpr, OpKind == tok::arrow, + (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0), + SS? SS->getRange() : SourceRange(), + Ovl, MemberLoc, true, + LAngleLoc, ExplicitTemplateArgs, + NumExplicitTemplateArgs, RAngleLoc, + Context.OverloadTy)); + + return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, + Ovl, MemberLoc, Context.OverloadTy)); + } if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, - Enum, MemberLoc, Enum->getType())); + return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, + Enum, MemberLoc, Enum->getType())); } if (isa<TypeDecl>(MemberDecl)) return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type) - << DeclarationName(&Member) << int(OpKind == tok::arrow)); + << MemberName << int(OpKind == tok::arrow)); // We found a declaration kind that we didn't expect. This is a // generic error message that tells the user that she can't refer // to this member with '.' or '->'. return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_unknown) - << DeclarationName(&Member) << int(OpKind == tok::arrow)); + << MemberName << int(OpKind == tok::arrow)); + } + + // Handle pseudo-destructors (C++ [expr.pseudo]). Since anything referring + // into a record type was handled above, any destructor we see here is a + // pseudo-destructor. + if (MemberName.getNameKind() == DeclarationName::CXXDestructorName) { + // C++ [expr.pseudo]p2: + // The left hand side of the dot operator shall be of scalar type. The + // left hand side of the arrow operator shall be of pointer to scalar + // type. + if (!BaseType->isScalarType()) + return Owned(Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar) + << BaseType << BaseExpr->getSourceRange()); + + // [...] The type designated by the pseudo-destructor-name shall be the + // same as the object type. + if (!MemberName.getCXXNameType()->isDependentType() && + !Context.hasSameUnqualifiedType(BaseType, MemberName.getCXXNameType())) + return Owned(Diag(OpLoc, diag::err_pseudo_dtor_type_mismatch) + << BaseType << MemberName.getCXXNameType() + << BaseExpr->getSourceRange() << SourceRange(MemberLoc)); + + // [...] Furthermore, the two type-names in a pseudo-destructor-name of + // the form + // + // ::[opt] nested-name-specifier[opt] type-name :: ̃ type-name + // + // shall designate the same scalar type. + // + // FIXME: DPG can't see any way to trigger this particular clause, so it + // isn't checked here. + + // FIXME: We've lost the precise spelling of the type by going through + // DeclarationName. Can we do better? + return Owned(new (Context) CXXPseudoDestructorExpr(Context, BaseExpr, + OpKind == tok::arrow, + OpLoc, + (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0), + SS? SS->getRange() : SourceRange(), + MemberName.getCXXNameType(), + MemberLoc)); } // Handle access to Objective-C instance variables, such as "Obj->ivar" and // (*Obj).ivar. - if (const ObjCInterfaceType *IFTy = BaseType->getAsObjCInterfaceType()) { - ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFTy->getDecl()->lookupInstanceVariable(&Member, - ClassDeclared)) { - // If the decl being referenced had an error, return an error for this - // sub-expr without emitting another error, in order to avoid cascading - // error cases. - if (IV->isInvalidDecl()) - return ExprError(); + if ((OpKind == tok::arrow && BaseType->isObjCObjectPointerType()) || + (OpKind == tok::period && BaseType->isObjCInterfaceType())) { + const ObjCObjectPointerType *OPT = BaseType->getAs<ObjCObjectPointerType>(); + const ObjCInterfaceType *IFaceT = + OPT ? OPT->getInterfaceType() : BaseType->getAs<ObjCInterfaceType>(); + if (IFaceT) { + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + + ObjCInterfaceDecl *IDecl = IFaceT->getDecl(); + ObjCInterfaceDecl *ClassDeclared; + ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); - // Check whether we can reference this field. - if (DiagnoseUseOfDecl(IV, MemberLoc)) - return ExprError(); - if (IV->getAccessControl() != ObjCIvarDecl::Public && - IV->getAccessControl() != ObjCIvarDecl::Package) { - ObjCInterfaceDecl *ClassOfMethodDecl = 0; - if (ObjCMethodDecl *MD = getCurMethodDecl()) - ClassOfMethodDecl = MD->getClassInterface(); - else if (ObjCImpDecl && getCurFunctionDecl()) { - // Case of a c-function declared inside an objc implementation. - // FIXME: For a c-style function nested inside an objc implementation - // class, there is no implementation context available, so we pass - // down the context as argument to this routine. Ideally, this context - // need be passed down in the AST node and somehow calculated from the - // AST for a function decl. - Decl *ImplDecl = ObjCImpDecl.getAs<Decl>(); - if (ObjCImplementationDecl *IMPD = - dyn_cast<ObjCImplementationDecl>(ImplDecl)) - ClassOfMethodDecl = IMPD->getClassInterface(); - else if (ObjCCategoryImplDecl* CatImplClass = - dyn_cast<ObjCCategoryImplDecl>(ImplDecl)) - ClassOfMethodDecl = CatImplClass->getClassInterface(); - } - - if (IV->getAccessControl() == ObjCIvarDecl::Private) { - if (ClassDeclared != IFTy->getDecl() || - ClassOfMethodDecl != ClassDeclared) - Diag(MemberLoc, diag::error_private_ivar_access) << IV->getDeclName(); + if (IV) { + // If the decl being referenced had an error, return an error for this + // sub-expr without emitting another error, in order to avoid cascading + // error cases. + if (IV->isInvalidDecl()) + return ExprError(); + + // Check whether we can reference this field. + if (DiagnoseUseOfDecl(IV, MemberLoc)) + return ExprError(); + if (IV->getAccessControl() != ObjCIvarDecl::Public && + IV->getAccessControl() != ObjCIvarDecl::Package) { + ObjCInterfaceDecl *ClassOfMethodDecl = 0; + if (ObjCMethodDecl *MD = getCurMethodDecl()) + ClassOfMethodDecl = MD->getClassInterface(); + else if (ObjCImpDecl && getCurFunctionDecl()) { + // Case of a c-function declared inside an objc implementation. + // FIXME: For a c-style function nested inside an objc implementation + // class, there is no implementation context available, so we pass + // down the context as argument to this routine. Ideally, this context + // need be passed down in the AST node and somehow calculated from the + // AST for a function decl. + Decl *ImplDecl = ObjCImpDecl.getAs<Decl>(); + if (ObjCImplementationDecl *IMPD = + dyn_cast<ObjCImplementationDecl>(ImplDecl)) + ClassOfMethodDecl = IMPD->getClassInterface(); + else if (ObjCCategoryImplDecl* CatImplClass = + dyn_cast<ObjCCategoryImplDecl>(ImplDecl)) + ClassOfMethodDecl = CatImplClass->getClassInterface(); + } + + if (IV->getAccessControl() == ObjCIvarDecl::Private) { + if (ClassDeclared != IDecl || + ClassOfMethodDecl != ClassDeclared) + Diag(MemberLoc, diag::error_private_ivar_access) + << IV->getDeclName(); + } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl)) + // @protected + Diag(MemberLoc, diag::error_protected_ivar_access) + << IV->getDeclName(); } - // @protected - else if (!IFTy->getDecl()->isSuperClassOf(ClassOfMethodDecl)) - Diag(MemberLoc, diag::error_protected_ivar_access) << IV->getDeclName(); - } - return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), - MemberLoc, BaseExpr, - OpKind == tok::arrow)); + return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), + MemberLoc, BaseExpr, + OpKind == tok::arrow)); + } + return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) + << IDecl->getDeclName() << MemberName + << BaseExpr->getSourceRange()); } - return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) - << IFTy->getDecl()->getDeclName() << &Member - << BaseExpr->getSourceRange()); } + // Handle properties on 'id' and qualified "id". + if (OpKind == tok::period && (BaseType->isObjCIdType() || + BaseType->isObjCQualifiedIdType())) { + const ObjCObjectPointerType *QIdTy = BaseType->getAs<ObjCObjectPointerType>(); + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + // Check protocols on qualified interfaces. + Selector Sel = PP.getSelectorTable().getNullarySelector(Member); + if (Decl *PMDecl = FindGetterNameDecl(QIdTy, Member, Sel, Context)) { + if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) { + // Check the use of this declaration + if (DiagnoseUseOfDecl(PD, MemberLoc)) + return ExprError(); + + return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), + MemberLoc, BaseExpr)); + } + if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) { + // Check the use of this method. + if (DiagnoseUseOfDecl(OMD, MemberLoc)) + return ExprError(); + + return Owned(new (Context) ObjCMessageExpr(BaseExpr, Sel, + OMD->getResultType(), + OMD, OpLoc, MemberLoc, + NULL, 0)); + } + } + + return ExprError(Diag(MemberLoc, diag::err_property_not_found) + << MemberName << BaseType); + } // Handle Objective-C property access, which is "Obj.property" where Obj is a // pointer to a (potentially qualified) interface type. - const PointerType *PTy; - const ObjCInterfaceType *IFTy; - if (OpKind == tok::period && (PTy = BaseType->getAsPointerType()) && - (IFTy = PTy->getPointeeType()->getAsObjCInterfaceType())) { - ObjCInterfaceDecl *IFace = IFTy->getDecl(); + const ObjCObjectPointerType *OPT; + if (OpKind == tok::period && + (OPT = BaseType->getAsObjCInterfacePointerType())) { + const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); + ObjCInterfaceDecl *IFace = IFaceT->getDecl(); + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); // Search for a declared property first. - if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(&Member)) { + if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); QualType ResTy = PD->getType(); - Selector Sel = PP.getSelectorTable().getNullarySelector(&Member); + Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)) ResTy = Getter->getResultType(); return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, MemberLoc, BaseExpr)); } - // Check protocols on qualified interfaces. - for (ObjCInterfaceType::qual_iterator I = IFTy->qual_begin(), - E = IFTy->qual_end(); I != E; ++I) - if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member)) { + for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), + E = OPT->qual_end(); I != E; ++I) + if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); @@ -2299,27 +2499,32 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr)); } + for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), + E = OPT->qual_end(); I != E; ++I) + if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { + // Check whether we can reference this property. + if (DiagnoseUseOfDecl(PD, MemberLoc)) + return ExprError(); + return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), + MemberLoc, BaseExpr)); + } // If that failed, look for an "implicit" property by seeing if the nullary // selector is implemented. // FIXME: The logic for looking up nullary and unary selectors should be // shared with the code in ActOnInstanceMessage. - Selector Sel = PP.getSelectorTable().getNullarySelector(&Member); + Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); // If this reference is in an @implementation, check for 'private' methods. if (!Getter) - Getter = FindMethodInNestedImplementations(IFace, Sel); + Getter = IFace->lookupPrivateInstanceMethod(Sel); // Look through local category implementations associated with the class. - if (!Getter) { - for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Getter; i++) { - if (ObjCCategoryImpls[i]->getClassInterface() == IFace) - Getter = ObjCCategoryImpls[i]->getInstanceMethod(Sel); - } - } + if (!Getter) + Getter = IFace->getCategoryInstanceMethod(Sel); if (Getter) { // Check if we can reference this property. if (DiagnoseUseOfDecl(Getter, MemberLoc)) @@ -2327,22 +2532,18 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, } // If we found a getter then this may be a valid dot-reference, we // will look for the matching setter, in case it is needed. - Selector SetterSel = - SelectorTable::constructSetterName(PP.getIdentifierTable(), - PP.getSelectorTable(), &Member); + Selector SetterSel = + SelectorTable::constructSetterName(PP.getIdentifierTable(), + PP.getSelectorTable(), Member); ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); if (!Setter) { // If this reference is in an @implementation, also check for 'private' // methods. - Setter = FindMethodInNestedImplementations(IFace, SetterSel); + Setter = IFace->lookupPrivateInstanceMethod(SetterSel); } // Look through local category implementations associated with the class. - if (!Setter) { - for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Setter; i++) { - if (ObjCCategoryImpls[i]->getClassInterface() == IFace) - Setter = ObjCCategoryImpls[i]->getInstanceMethod(SetterSel); - } - } + if (!Setter) + Setter = IFace->getCategoryInstanceMethod(SetterSel); if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) return ExprError(); @@ -2352,107 +2553,31 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, if (Getter) PType = Getter->getResultType(); - else { - for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(), - E = Setter->param_end(); PI != E; ++PI) - PType = (*PI)->getType(); - } + else + // Get the expression type from Setter's incoming parameter. + PType = (*(Setter->param_end() -1))->getType(); // FIXME: we must check that the setter has property type. - return Owned(new (Context) ObjCKVCRefExpr(Getter, PType, + return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType, Setter, MemberLoc, BaseExpr)); } return ExprError(Diag(MemberLoc, diag::err_property_not_found) - << &Member << BaseType); - } - // Handle properties on qualified "id" protocols. - const ObjCObjectPointerType *QIdTy; - if (OpKind == tok::period && (QIdTy = BaseType->getAsObjCQualifiedIdType())) { - // Check protocols on qualified interfaces. - Selector Sel = PP.getSelectorTable().getNullarySelector(&Member); - if (Decl *PMDecl = FindGetterNameDecl(QIdTy, Member, Sel, Context)) { - if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) { - // Check the use of this declaration - if (DiagnoseUseOfDecl(PD, MemberLoc)) - return ExprError(); - - return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), - MemberLoc, BaseExpr)); - } - if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) { - // Check the use of this method. - if (DiagnoseUseOfDecl(OMD, MemberLoc)) - return ExprError(); - - return Owned(new (Context) ObjCMessageExpr(BaseExpr, Sel, - OMD->getResultType(), - OMD, OpLoc, MemberLoc, - NULL, 0)); - } - } - - return ExprError(Diag(MemberLoc, diag::err_property_not_found) - << &Member << BaseType); + << MemberName << BaseType); } - // Handle properties on ObjC 'Class' types. - if (OpKind == tok::period && (BaseType == Context.getObjCClassType())) { - // Also must look for a getter name which uses property syntax. - Selector Sel = PP.getSelectorTable().getNullarySelector(&Member); - if (ObjCMethodDecl *MD = getCurMethodDecl()) { - ObjCInterfaceDecl *IFace = MD->getClassInterface(); - ObjCMethodDecl *Getter; - // FIXME: need to also look locally in the implementation. - if ((Getter = IFace->lookupClassMethod(Sel))) { - // Check the use of this method. - if (DiagnoseUseOfDecl(Getter, MemberLoc)) - return ExprError(); - } - // If we found a getter then this may be a valid dot-reference, we - // will look for the matching setter, in case it is needed. - Selector SetterSel = - SelectorTable::constructSetterName(PP.getIdentifierTable(), - PP.getSelectorTable(), &Member); - ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); - if (!Setter) { - // If this reference is in an @implementation, also check for 'private' - // methods. - Setter = FindMethodInNestedImplementations(IFace, SetterSel); - } - // Look through local category implementations associated with the class. - if (!Setter) { - for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Setter; i++) { - if (ObjCCategoryImpls[i]->getClassInterface() == IFace) - Setter = ObjCCategoryImpls[i]->getClassMethod(SetterSel); - } - } - if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) - return ExprError(); + // Handle the following exceptional case (*Obj).isa. + if (OpKind == tok::period && + BaseType->isSpecificBuiltinType(BuiltinType::ObjCId) && + MemberName.getAsIdentifierInfo()->isStr("isa")) + return Owned(new (Context) ObjCIsaExpr(BaseExpr, false, MemberLoc, + Context.getObjCIdType())); - if (Getter || Setter) { - QualType PType; - - if (Getter) - PType = Getter->getResultType(); - else { - for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(), - E = Setter->param_end(); PI != E; ++PI) - PType = (*PI)->getType(); - } - // FIXME: we must check that the setter has property type. - return Owned(new (Context) ObjCKVCRefExpr(Getter, PType, - Setter, MemberLoc, BaseExpr)); - } - return ExprError(Diag(MemberLoc, diag::err_property_not_found) - << &Member << BaseType); - } - } - // Handle 'field access' to vectors, such as 'V.xx'. if (BaseType->isExtVectorType()) { + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); QualType ret = CheckExtVectorComponent(BaseType, OpLoc, Member, MemberLoc); if (ret.isNull()) return ExprError(); - return Owned(new (Context) ExtVectorElementExpr(ret, BaseExpr, Member, + return Owned(new (Context) ExtVectorElementExpr(ret, BaseExpr, *Member, MemberLoc)); } @@ -2462,10 +2587,10 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // If the user is trying to apply -> or . to a function or function // pointer, it's probably because they forgot parentheses to call // the function. Suggest the addition of those parentheses. - if (BaseType == Context.OverloadTy || + if (BaseType == Context.OverloadTy || BaseType->isFunctionType() || - (BaseType->isPointerType() && - BaseType->getAsPointerType()->isFunctionType())) { + (BaseType->isPointerType() && + BaseType->getAs<PointerType>()->isFunctionType())) { SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd()); Diag(Loc, diag::note_member_reference_needs_call) << CodeModificationHint::CreateInsertion(Loc, "()"); @@ -2474,6 +2599,63 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, return ExprError(); } +Action::OwningExprResult +Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, + tok::TokenKind OpKind, SourceLocation MemberLoc, + IdentifierInfo &Member, + DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS) { + return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, MemberLoc, + DeclarationName(&Member), ObjCImpDecl, SS); +} + +Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, + FunctionDecl *FD, + ParmVarDecl *Param) { + if (Param->hasUnparsedDefaultArg()) { + Diag (CallLoc, + diag::err_use_of_default_argument_to_function_declared_later) << + FD << cast<CXXRecordDecl>(FD->getDeclContext())->getDeclName(); + Diag(UnparsedDefaultArgLocs[Param], + diag::note_default_argument_declared_here); + } else { + if (Param->hasUninstantiatedDefaultArg()) { + Expr *UninstExpr = Param->getUninstantiatedDefaultArg(); + + // Instantiate the expression. + MultiLevelTemplateArgumentList ArgList = getTemplateInstantiationArgs(FD); + + InstantiatingTemplate Inst(*this, CallLoc, Param, + ArgList.getInnermost().getFlatArgumentList(), + ArgList.getInnermost().flat_size()); + + OwningExprResult Result = SubstExpr(UninstExpr, ArgList); + if (Result.isInvalid()) + return ExprError(); + + if (SetParamDefaultArgument(Param, move(Result), + /*FIXME:EqualLoc*/ + UninstExpr->getSourceRange().getBegin())) + return ExprError(); + } + + Expr *DefaultExpr = Param->getDefaultArg(); + + // If the default expression creates temporaries, we need to + // push them to the current stack of expression temporaries so they'll + // be properly destroyed. + if (CXXExprWithTemporaries *E + = dyn_cast_or_null<CXXExprWithTemporaries>(DefaultExpr)) { + assert(!E->shouldDestroyTemporaries() && + "Can't destroy temporaries in a default argument expr!"); + for (unsigned I = 0, N = E->getNumTemporaries(); I != N; ++I) + ExprTemporaries.push_back(E->getTemporary(I)); + } + } + + // We already type-checked the argument, so we know it works. + return Owned(CXXDefaultArgExpr::Create(Context, Param)); +} + /// ConvertArgumentsForCall - Converts the arguments specified in /// Args/NumArgs to the parameter types of the function FDecl with /// function prototype Proto. Call is the call expression itself, and @@ -2529,40 +2711,24 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, if (RequireCompleteType(Arg->getSourceRange().getBegin(), ProtoArgType, - diag::err_call_incomplete_argument, - Arg->getSourceRange())) + PDiag(diag::err_call_incomplete_argument) + << Arg->getSourceRange())) return true; // Pass the argument. if (PerformCopyInitialization(Arg, ProtoArgType, "passing")) return true; } else { - if (FDecl->getParamDecl(i)->hasUnparsedDefaultArg()) { - Diag (Call->getSourceRange().getBegin(), - diag::err_use_of_default_argument_to_function_declared_later) << - FDecl << cast<CXXRecordDecl>(FDecl->getDeclContext())->getDeclName(); - Diag(UnparsedDefaultArgLocs[FDecl->getParamDecl(i)], - diag::note_default_argument_declared_here); - } else { - Expr *DefaultExpr = FDecl->getParamDecl(i)->getDefaultArg(); - - // If the default expression creates temporaries, we need to - // push them to the current stack of expression temporaries so they'll - // be properly destroyed. - if (CXXExprWithTemporaries *E - = dyn_cast_or_null<CXXExprWithTemporaries>(DefaultExpr)) { - assert(!E->shouldDestroyTemporaries() && - "Can't destroy temporaries in a default argument expr!"); - for (unsigned I = 0, N = E->getNumTemporaries(); I != N; ++I) - ExprTemporaries.push_back(E->getTemporary(I)); - } - } - - // We already type-checked the argument, so we know it works. - Arg = new (Context) CXXDefaultArgExpr(FDecl->getParamDecl(i)); + ParmVarDecl *Param = FDecl->getParamDecl(i); + + OwningExprResult ArgExpr = + BuildCXXDefaultArgExpr(Call->getSourceRange().getBegin(), + FDecl, Param); + if (ArgExpr.isInvalid()) + return true; + + Arg = ArgExpr.takeAs<Expr>(); } - - QualType ArgType = Arg->getType(); Call->setArg(i, Arg); } @@ -2586,6 +2752,96 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, return Invalid; } +/// \brief "Deconstruct" the function argument of a call expression to find +/// the underlying declaration (if any), the name of the called function, +/// whether argument-dependent lookup is available, whether it has explicit +/// template arguments, etc. +void Sema::DeconstructCallFunction(Expr *FnExpr, + NamedDecl *&Function, + DeclarationName &Name, + NestedNameSpecifier *&Qualifier, + SourceRange &QualifierRange, + bool &ArgumentDependentLookup, + bool &HasExplicitTemplateArguments, + const TemplateArgument *&ExplicitTemplateArgs, + unsigned &NumExplicitTemplateArgs) { + // Set defaults for all of the output parameters. + Function = 0; + Name = DeclarationName(); + Qualifier = 0; + QualifierRange = SourceRange(); + ArgumentDependentLookup = getLangOptions().CPlusPlus; + HasExplicitTemplateArguments = false; + + // If we're directly calling a function, get the appropriate declaration. + // Also, in C++, keep track of whether we should perform argument-dependent + // lookup and whether there were any explicitly-specified template arguments. + while (true) { + if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr)) + FnExpr = IcExpr->getSubExpr(); + else if (ParenExpr *PExpr = dyn_cast<ParenExpr>(FnExpr)) { + // Parentheses around a function disable ADL + // (C++0x [basic.lookup.argdep]p1). + ArgumentDependentLookup = false; + FnExpr = PExpr->getSubExpr(); + } else if (isa<UnaryOperator>(FnExpr) && + cast<UnaryOperator>(FnExpr)->getOpcode() + == UnaryOperator::AddrOf) { + FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr(); + } else if (QualifiedDeclRefExpr *QDRExpr + = dyn_cast<QualifiedDeclRefExpr>(FnExpr)) { + // Qualified names disable ADL (C++0x [basic.lookup.argdep]p1). + ArgumentDependentLookup = false; + Qualifier = QDRExpr->getQualifier(); + QualifierRange = QDRExpr->getQualifierRange(); + Function = dyn_cast<NamedDecl>(QDRExpr->getDecl()); + break; + } else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) { + Function = dyn_cast<NamedDecl>(DRExpr->getDecl()); + break; + } else if (UnresolvedFunctionNameExpr *DepName + = dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) { + Name = DepName->getName(); + break; + } else if (TemplateIdRefExpr *TemplateIdRef + = dyn_cast<TemplateIdRefExpr>(FnExpr)) { + Function = TemplateIdRef->getTemplateName().getAsTemplateDecl(); + if (!Function) + Function = TemplateIdRef->getTemplateName().getAsOverloadedFunctionDecl(); + HasExplicitTemplateArguments = true; + ExplicitTemplateArgs = TemplateIdRef->getTemplateArgs(); + NumExplicitTemplateArgs = TemplateIdRef->getNumTemplateArgs(); + + // C++ [temp.arg.explicit]p6: + // [Note: For simple function names, argument dependent lookup (3.4.2) + // applies even when the function name is not visible within the + // scope of the call. This is because the call still has the syntactic + // form of a function call (3.4.1). But when a function template with + // explicit template arguments is used, the call does not have the + // correct syntactic form unless there is a function template with + // that name visible at the point of the call. If no such name is + // visible, the call is not syntactically well-formed and + // argument-dependent lookup does not apply. If some such name is + // visible, argument dependent lookup applies and additional function + // templates may be found in other namespaces. + // + // The summary of this paragraph is that, if we get to this point and the + // template-id was not a qualified name, then argument-dependent lookup + // is still possible. + if ((Qualifier = TemplateIdRef->getQualifier())) { + ArgumentDependentLookup = false; + QualifierRange = TemplateIdRef->getQualifierRange(); + } + break; + } else { + // Any kind of name that does not refer to a declaration (or + // set of declarations) disables ADL (C++0x [basic.lookup.argdep]p3). + ArgumentDependentLookup = false; + break; + } + } +} + /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma /// locations. @@ -2594,6 +2850,10 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, MultiExprArg args, SourceLocation *CommaLocs, SourceLocation RParenLoc) { unsigned NumArgs = args.size(); + + // Since this might be a postfix expression, get rid of ParenListExprs. + fn = MaybeConvertParenListExprToParenExpr(S, move(fn)); + Expr *Fn = fn.takeAs<Expr>(); Expr **Args = reinterpret_cast<Expr**>(args.release()); assert(Fn && "no function call expression"); @@ -2602,6 +2862,25 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, DeclarationName UnqualifiedName; if (getLangOptions().CPlusPlus) { + // If this is a pseudo-destructor expression, build the call immediately. + if (isa<CXXPseudoDestructorExpr>(Fn)) { + if (NumArgs > 0) { + // Pseudo-destructor calls should not have any arguments. + Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args) + << CodeModificationHint::CreateRemoval( + SourceRange(Args[0]->getLocStart(), + Args[NumArgs-1]->getLocEnd())); + + for (unsigned I = 0; I != NumArgs; ++I) + Args[I]->Destroy(Context); + + NumArgs = 0; + } + + return Owned(new (Context) CallExpr(Context, Fn, 0, 0, Context.VoidTy, + RParenLoc)); + } + // Determine whether this is a dependent call inside a C++ template, // in which case we won't do any semantic analysis now. // FIXME: Will need to cache the results of name lookup (including ADL) in @@ -2632,70 +2911,42 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, return Owned(BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, CommaLocs, RParenLoc)); } + + // Determine whether this is a call to a pointer-to-member function. + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Fn->IgnoreParens())) { + if (BO->getOpcode() == BinaryOperator::PtrMemD || + BO->getOpcode() == BinaryOperator::PtrMemI) { + const FunctionProtoType *FPT = cast<FunctionProtoType>(BO->getType()); + QualType ReturnTy = FPT->getResultType(); + + CXXMemberCallExpr *CE = + new (Context) CXXMemberCallExpr(Context, BO, Args, NumArgs, + ReturnTy.getNonReferenceType(), + RParenLoc); + + ExprOwningPtr<CXXMemberCallExpr> TheCall(this, CE); + + if (ConvertArgumentsForCall(&*TheCall, BO, 0, FPT, Args, NumArgs, + RParenLoc)) + return ExprError(); + + return Owned(MaybeBindToTemporary(TheCall.release()).release()); + } + } } // If we're directly calling a function, get the appropriate declaration. - // Also, in C++, keep track of whether we should perform argument-dependent + // Also, in C++, keep track of whether we should perform argument-dependent // lookup and whether there were any explicitly-specified template arguments. - Expr *FnExpr = Fn; bool ADL = true; bool HasExplicitTemplateArgs = 0; const TemplateArgument *ExplicitTemplateArgs = 0; unsigned NumExplicitTemplateArgs = 0; - while (true) { - if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr)) - FnExpr = IcExpr->getSubExpr(); - else if (ParenExpr *PExpr = dyn_cast<ParenExpr>(FnExpr)) { - // Parentheses around a function disable ADL - // (C++0x [basic.lookup.argdep]p1). - ADL = false; - FnExpr = PExpr->getSubExpr(); - } else if (isa<UnaryOperator>(FnExpr) && - cast<UnaryOperator>(FnExpr)->getOpcode() - == UnaryOperator::AddrOf) { - FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr(); - } else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) { - // Qualified names disable ADL (C++0x [basic.lookup.argdep]p1). - ADL &= !isa<QualifiedDeclRefExpr>(DRExpr); - NDecl = dyn_cast<NamedDecl>(DRExpr->getDecl()); - break; - } else if (UnresolvedFunctionNameExpr *DepName - = dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) { - UnqualifiedName = DepName->getName(); - break; - } else if (TemplateIdRefExpr *TemplateIdRef - = dyn_cast<TemplateIdRefExpr>(FnExpr)) { - NDecl = TemplateIdRef->getTemplateName().getAsTemplateDecl(); - HasExplicitTemplateArgs = true; - ExplicitTemplateArgs = TemplateIdRef->getTemplateArgs(); - NumExplicitTemplateArgs = TemplateIdRef->getNumTemplateArgs(); - - // C++ [temp.arg.explicit]p6: - // [Note: For simple function names, argument dependent lookup (3.4.2) - // applies even when the function name is not visible within the - // scope of the call. This is because the call still has the syntactic - // form of a function call (3.4.1). But when a function template with - // explicit template arguments is used, the call does not have the - // correct syntactic form unless there is a function template with - // that name visible at the point of the call. If no such name is - // visible, the call is not syntactically well-formed and - // argument-dependent lookup does not apply. If some such name is - // visible, argument dependent lookup applies and additional function - // templates may be found in other namespaces. - // - // The summary of this paragraph is that, if we get to this point and the - // template-id was not a qualified name, then argument-dependent lookup - // is still possible. - if (TemplateIdRef->getQualifier()) - ADL = false; - break; - } else { - // Any kind of name that does not refer to a declaration (or - // set of declarations) disables ADL (C++0x [basic.lookup.argdep]p3). - ADL = false; - break; - } - } + NestedNameSpecifier *Qualifier = 0; + SourceRange QualifierRange; + DeconstructCallFunction(Fn, NDecl, UnqualifiedName, Qualifier, QualifierRange, + ADL,HasExplicitTemplateArgs, ExplicitTemplateArgs, + NumExplicitTemplateArgs); OverloadedFunctionDecl *Ovl = 0; FunctionTemplateDecl *FunctionTemplate = 0; @@ -2708,10 +2959,10 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, Ovl = dyn_cast<OverloadedFunctionDecl>(NDecl); } - if (Ovl || FunctionTemplate || + if (Ovl || FunctionTemplate || (getLangOptions().CPlusPlus && (FDecl || UnqualifiedName))) { // We don't perform ADL for implicit declarations of builtins. - if (FDecl && FDecl->getBuiltinID(Context) && FDecl->isImplicit()) + if (FDecl && FDecl->getBuiltinID() && FDecl->isImplicit()) ADL = false; // We don't perform ADL in C. @@ -2719,27 +2970,26 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, ADL = false; if (Ovl || FunctionTemplate || ADL) { - FDecl = ResolveOverloadedCallFn(Fn, NDecl, UnqualifiedName, + FDecl = ResolveOverloadedCallFn(Fn, NDecl, UnqualifiedName, HasExplicitTemplateArgs, ExplicitTemplateArgs, NumExplicitTemplateArgs, - LParenLoc, Args, NumArgs, CommaLocs, + LParenLoc, Args, NumArgs, CommaLocs, RParenLoc, ADL); if (!FDecl) return ExprError(); // Update Fn to refer to the actual function selected. Expr *NewFn = 0; - if (QualifiedDeclRefExpr *QDRExpr - = dyn_cast<QualifiedDeclRefExpr>(FnExpr)) + if (Qualifier) NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(), - QDRExpr->getLocation(), + Fn->getLocStart(), false, false, - QDRExpr->getQualifierRange(), - QDRExpr->getQualifier()); + QualifierRange, + Qualifier); else NewFn = new (Context) DeclRefExpr(FDecl, FDecl->getType(), - Fn->getSourceRange().getBegin()); + Fn->getLocStart()); Fn->Destroy(Context); Fn = NewFn; } @@ -2759,25 +3009,23 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, if (!Fn->getType()->isBlockPointerType()) { // C99 6.5.2.2p1 - "The expression that denotes the called function shall // have type pointer to function". - const PointerType *PT = Fn->getType()->getAsPointerType(); + const PointerType *PT = Fn->getType()->getAs<PointerType>(); if (PT == 0) return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) << Fn->getType() << Fn->getSourceRange()); - FuncT = PT->getPointeeType()->getAsFunctionType(); + FuncT = PT->getPointeeType()->getAs<FunctionType>(); } else { // This is a block call. - FuncT = Fn->getType()->getAsBlockPointerType()->getPointeeType()-> - getAsFunctionType(); + FuncT = Fn->getType()->getAs<BlockPointerType>()->getPointeeType()-> + getAs<FunctionType>(); } if (FuncT == 0) return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) << Fn->getType() << Fn->getSourceRange()); // Check for a valid return type - if (!FuncT->getResultType()->isVoidType() && - RequireCompleteType(Fn->getSourceRange().getBegin(), - FuncT->getResultType(), - diag::err_call_incomplete_return, - TheCall->getSourceRange())) + if (CheckCallReturnType(FuncT->getResultType(), + Fn->getSourceRange().getBegin(), TheCall.get(), + FDecl)) return ExprError(); // We know the result type of the call, set it. @@ -2796,7 +3044,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, const FunctionDecl *Def = 0; if (FDecl->getBody(Def) && NumArgs != Def->param_size()) { const FunctionProtoType *Proto = - Def->getType()->getAsFunctionProtoType(); + Def->getType()->getAs<FunctionProtoType>(); if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) { Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments) << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange(); @@ -2810,8 +3058,8 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, DefaultArgumentPromotion(Arg); if (RequireCompleteType(Arg->getSourceRange().getBegin(), Arg->getType(), - diag::err_call_incomplete_argument, - Arg->getSourceRange())) + PDiag(diag::err_call_incomplete_argument) + << Arg->getSourceRange())) return ExprError(); TheCall->setArg(i, Arg); } @@ -2825,20 +3073,28 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // Check for sentinels if (NDecl) DiagnoseSentinelCalls(NDecl, LParenLoc, Args, NumArgs); + // Do special checking on direct calls to functions. - if (FDecl) - return CheckFunctionCall(FDecl, TheCall.take()); - if (NDecl) - return CheckBlockCall(NDecl, TheCall.take()); + if (FDecl) { + if (CheckFunctionCall(FDecl, TheCall.get())) + return ExprError(); - return Owned(TheCall.take()); + if (unsigned BuiltinID = FDecl->getBuiltinID()) + return CheckBuiltinFunctionCall(BuiltinID, TheCall.take()); + } else if (NDecl) { + if (CheckBlockCall(NDecl, TheCall.get())) + return ExprError(); + } + + return MaybeBindToTemporary(TheCall.take()); } Action::OwningExprResult Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty, SourceLocation RParenLoc, ExprArg InitExpr) { assert((Ty != 0) && "ActOnCompoundLiteral(): missing type"); - QualType literalType = QualType::getFromOpaquePtr(Ty); + //FIXME: Preserve type source info. + QualType literalType = GetTypeFromParser(Ty); // FIXME: put back this assert when initializers are worked out. //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression"); Expr *literalExpr = static_cast<Expr*>(InitExpr.get()); @@ -2849,8 +3105,9 @@ Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty, << SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd())); } else if (!literalType->isDependentType() && RequireCompleteType(LParenLoc, literalType, - diag::err_typecheck_decl_incomplete_type, - SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd()))) + PDiag(diag::err_typecheck_decl_incomplete_type) + << SourceRange(LParenLoc, + literalExpr->getSourceRange().getEnd()))) return ExprError(); if (CheckInitializerTypes(literalExpr, literalType, LParenLoc, @@ -2883,15 +3140,20 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist, } /// CheckCastTypes - Check type constraints for casting between types. -bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr) { - UsualUnaryConversions(castExpr); +bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr, + CastExpr::CastKind& Kind, + CXXMethodDecl *& ConversionDecl, + bool FunctionalStyle) { + if (getLangOptions().CPlusPlus) + return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, FunctionalStyle, + ConversionDecl); + + DefaultFunctionArrayConversion(castExpr); // C99 6.5.4p2: the cast type needs to be void or scalar and the expression // type needs to be scalar. if (castType->isVoidType()) { // Cast to void allows any expr type. - } else if (castType->isDependentType() || castExpr->isTypeDependent()) { - // We can't check any more until template instantiation time. } else if (!castType->isScalarType() && !castType->isVectorType()) { if (Context.getCanonicalType(castType).getUnqualifiedType() == Context.getCanonicalType(castExpr->getType().getUnqualifiedType()) && @@ -2900,9 +3162,10 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr) { // FIXME: Check that the cast destination type is complete. Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar) << castType << castExpr->getSourceRange(); + Kind = CastExpr::CK_NoOp; } else if (castType->isUnionType()) { // GCC cast to union extension - RecordDecl *RD = castType->getAsRecordType()->getDecl(); + RecordDecl *RD = castType->getAs<RecordType>()->getDecl(); RecordDecl::field_iterator Field, FieldEnd; for (Field = RD->field_begin(), FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { @@ -2916,6 +3179,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr) { if (Field == FieldEnd) return Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type) << castExpr->getType() << castExpr->getSourceRange(); + Kind = CastExpr::CK_ToUnion; } else { // Reject any other conversions to non-scalar types. return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar) @@ -2974,7 +3238,7 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty) { bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) { assert(DestTy->isExtVectorType() && "Not an extended vector type!"); - + // If SrcTy is a VectorType, the total size must match to explicitly cast to // an ExtVectorType. if (SrcTy->isVectorType()) { @@ -2995,20 +3259,104 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) { } Action::OwningExprResult -Sema::ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty, +Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, TypeTy *Ty, SourceLocation RParenLoc, ExprArg Op) { + CastExpr::CastKind Kind = CastExpr::CK_Unknown; + assert((Ty != 0) && (Op.get() != 0) && "ActOnCastExpr(): missing type or expr"); - Expr *castExpr = Op.takeAs<Expr>(); - QualType castType = QualType::getFromOpaquePtr(Ty); + Expr *castExpr = (Expr *)Op.get(); + //FIXME: Preserve type source info. + QualType castType = GetTypeFromParser(Ty); - if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), castType, castExpr)) + // If the Expr being casted is a ParenListExpr, handle it specially. + if (isa<ParenListExpr>(castExpr)) + return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, move(Op),castType); + CXXMethodDecl *Method = 0; + if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), castType, castExpr, + Kind, Method)) return ExprError(); - return Owned(new (Context) CStyleCastExpr(castType, castExpr, castType, + + if (Method) { + OwningExprResult CastArg = BuildCXXCastArgument(LParenLoc, castType, Kind, + Method, move(Op)); + + if (CastArg.isInvalid()) + return ExprError(); + + castExpr = CastArg.takeAs<Expr>(); + } else { + Op.release(); + } + + return Owned(new (Context) CStyleCastExpr(castType.getNonReferenceType(), + Kind, castExpr, castType, LParenLoc, RParenLoc)); } +/// This is not an AltiVec-style cast, so turn the ParenListExpr into a sequence +/// of comma binary operators. +Action::OwningExprResult +Sema::MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg EA) { + Expr *expr = EA.takeAs<Expr>(); + ParenListExpr *E = dyn_cast<ParenListExpr>(expr); + if (!E) + return Owned(expr); + + OwningExprResult Result(*this, E->getExpr(0)); + + for (unsigned i = 1, e = E->getNumExprs(); i != e && !Result.isInvalid(); ++i) + Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, move(Result), + Owned(E->getExpr(i))); + + return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), move(Result)); +} + +Action::OwningExprResult +Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, + SourceLocation RParenLoc, ExprArg Op, + QualType Ty) { + ParenListExpr *PE = (ParenListExpr *)Op.get(); + + // If this is an altivec initializer, '(' type ')' '(' init, ..., init ')' + // then handle it as such. + if (getLangOptions().AltiVec && Ty->isVectorType()) { + if (PE->getNumExprs() == 0) { + Diag(PE->getExprLoc(), diag::err_altivec_empty_initializer); + return ExprError(); + } + + llvm::SmallVector<Expr *, 8> initExprs; + for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i) + initExprs.push_back(PE->getExpr(i)); + + // FIXME: This means that pretty-printing the final AST will produce curly + // braces instead of the original commas. + Op.release(); + InitListExpr *E = new (Context) InitListExpr(LParenLoc, &initExprs[0], + initExprs.size(), RParenLoc); + E->setType(Ty); + return ActOnCompoundLiteral(LParenLoc, Ty.getAsOpaquePtr(), RParenLoc, + Owned(E)); + } else { + // This is not an AltiVec-style cast, so turn the ParenListExpr into a + // sequence of BinOp comma operators. + Op = MaybeConvertParenListExprToParenExpr(S, move(Op)); + return ActOnCastExpr(S, LParenLoc, Ty.getAsOpaquePtr(), RParenLoc,move(Op)); + } +} + +Action::OwningExprResult Sema::ActOnParenListExpr(SourceLocation L, + SourceLocation R, + MultiExprArg Val) { + unsigned nexprs = Val.size(); + Expr **exprs = reinterpret_cast<Expr**>(Val.release()); + assert((exprs != 0) && "ActOnParenListExpr() missing expr list"); + Expr *expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R); + return Owned(expr); +} + /// Note that lhs is not null here, even if this is the gnu "x ?: y" extension. /// In that case, lhs = cond. /// C99 6.5.15 @@ -3033,6 +3381,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, } // Now check the two expressions. + if (LHSTy->isVectorType() || RHSTy->isVectorType()) + return CheckVectorOperands(QuestionLoc, LHS, RHS); // If both operands have arithmetic type, do the usual arithmetic conversions // to find a common type: C99 6.5.15p3,5. @@ -3043,8 +3393,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // If both operands are the same structure or union type, the result is that // type. - if (const RecordType *LHSRT = LHSTy->getAsRecordType()) { // C99 6.5.15p3 - if (const RecordType *RHSRT = RHSTy->getAsRecordType()) + if (const RecordType *LHSRT = LHSTy->getAs<RecordType>()) { // C99 6.5.15p3 + if (const RecordType *RHSRT = RHSTy->getAs<RecordType>()) if (LHSRT->getDecl() == RHSRT->getDecl()) // "If both the operands have structure or union type, the result has // that type." This implies that CV qualifiers are dropped. @@ -3067,24 +3417,46 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, } // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has // the type of the other operand." - if ((LHSTy->isPointerType() || LHSTy->isBlockPointerType() || - Context.isObjCObjectPointerType(LHSTy)) && - RHS->isNullPointerConstant(Context)) { + if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) && + RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { ImpCastExprToType(RHS, LHSTy); // promote the null to a pointer. return LHSTy; } - if ((RHSTy->isPointerType() || RHSTy->isBlockPointerType() || - Context.isObjCObjectPointerType(RHSTy)) && - LHS->isNullPointerConstant(Context)) { + if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) && + LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { ImpCastExprToType(LHS, RHSTy); // promote the null to a pointer. return RHSTy; } + // Handle things like Class and struct objc_class*. Here we case the result + // to the pseudo-builtin, because that will be implicitly cast back to the + // redefinition type if an attempt is made to access its fields. + if (LHSTy->isObjCClassType() && + (RHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) { + ImpCastExprToType(RHS, LHSTy); + return LHSTy; + } + if (RHSTy->isObjCClassType() && + (LHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) { + ImpCastExprToType(LHS, RHSTy); + return RHSTy; + } + // And the same for struct objc_object* / id + if (LHSTy->isObjCIdType() && + (RHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) { + ImpCastExprToType(RHS, LHSTy); + return LHSTy; + } + if (RHSTy->isObjCIdType() && + (LHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) { + ImpCastExprToType(LHS, RHSTy); + return RHSTy; + } // Handle block pointer types. if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) { if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) { if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) { QualType destType = Context.getPointerType(Context.VoidTy); - ImpCastExprToType(LHS, destType); + ImpCastExprToType(LHS, destType); ImpCastExprToType(RHS, destType); return destType; } @@ -3098,8 +3470,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, return LHSTy; } // The block pointer types aren't identical, continue checking. - QualType lhptee = LHSTy->getAsBlockPointerType()->getPointeeType(); - QualType rhptee = RHSTy->getAsBlockPointerType()->getPointeeType(); + QualType lhptee = LHSTy->getAs<BlockPointerType>()->getPointeeType(); + QualType rhptee = RHSTy->getAs<BlockPointerType>()->getPointeeType(); if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), rhptee.getUnqualifiedType())) { @@ -3118,48 +3490,17 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, ImpCastExprToType(RHS, LHSTy); return LHSTy; } - // Need to handle "id<xx>" explicitly. Unlike "id", whose canonical type - // evaluates to "struct objc_object *" (and is handled above when comparing - // id with statically typed objects). - if (LHSTy->isObjCQualifiedIdType() || RHSTy->isObjCQualifiedIdType()) { - // GCC allows qualified id and any Objective-C type to devolve to - // id. Currently localizing to here until clear this should be - // part of ObjCQualifiedIdTypesAreCompatible. - if (ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true) || - (LHSTy->isObjCQualifiedIdType() && - Context.isObjCObjectPointerType(RHSTy)) || - (RHSTy->isObjCQualifiedIdType() && - Context.isObjCObjectPointerType(LHSTy))) { - // FIXME: This is not the correct composite type. This only happens to - // work because id can more or less be used anywhere, however this may - // change the type of method sends. - - // FIXME: gcc adds some type-checking of the arguments and emits - // (confusing) incompatible comparison warnings in some - // cases. Investigate. - QualType compositeType = Context.getObjCIdType(); - ImpCastExprToType(LHS, compositeType); - ImpCastExprToType(RHS, compositeType); - return compositeType; - } - } // Check constraints for Objective-C object pointers types. - if (Context.isObjCObjectPointerType(LHSTy) && - Context.isObjCObjectPointerType(RHSTy)) { - + if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) { + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { // Two identical object pointer types are always compatible. return LHSTy; } - // No need to check for block pointer types or qualified id types (they - // were handled above). - assert((LHSTy->isPointerType() && RHSTy->isPointerType()) && - "Sema::CheckConditionalOperands(): Unexpected type"); - QualType lhptee = LHSTy->getAsPointerType()->getPointeeType(); - QualType rhptee = RHSTy->getAsPointerType()->getPointeeType(); - + const ObjCObjectPointerType *LHSOPT = LHSTy->getAs<ObjCObjectPointerType>(); + const ObjCObjectPointerType *RHSOPT = RHSTy->getAs<ObjCObjectPointerType>(); QualType compositeType = LHSTy; - + // If both operands are interfaces and either operand can be // assigned to the other, use that type as the composite // type. This allows @@ -3173,16 +3514,19 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // FIXME: Consider unifying with 'areComparableObjCPointerTypes'. // It could return the composite type. - const ObjCInterfaceType* LHSIface = lhptee->getAsObjCInterfaceType(); - const ObjCInterfaceType* RHSIface = rhptee->getAsObjCInterfaceType(); - if (LHSIface && RHSIface && - Context.canAssignObjCInterfaces(LHSIface, RHSIface)) { - compositeType = LHSTy; - } else if (LHSIface && RHSIface && - Context.canAssignObjCInterfaces(RHSIface, LHSIface)) { - compositeType = RHSTy; - } else if (Context.isObjCIdStructType(lhptee) || - Context.isObjCIdStructType(rhptee)) { + if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) { + compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy; + } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) { + compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy; + } else if ((LHSTy->isObjCQualifiedIdType() || + RHSTy->isObjCQualifiedIdType()) && + Context.ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) { + // Need to handle "id<xx>" explicitly. + // GCC allows qualified id and any Objective-C type to devolve to + // id. Currently localizing to here until clear this should be + // part of ObjCQualifiedIdTypesAreCompatible. + compositeType = Context.getObjCIdType(); + } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) { compositeType = Context.getObjCIdType(); } else { Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) @@ -3198,23 +3542,46 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, ImpCastExprToType(RHS, compositeType); return compositeType; } + // Check Objective-C object pointer types and 'void *' + if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) { + QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType(); + QualType rhptee = RHSTy->getAs<ObjCObjectPointerType>()->getPointeeType(); + QualType destPointee + = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); + QualType destType = Context.getPointerType(destPointee); + ImpCastExprToType(LHS, destType); // add qualifiers if necessary + ImpCastExprToType(RHS, destType); // promote to void* + return destType; + } + if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { + QualType lhptee = LHSTy->getAs<ObjCObjectPointerType>()->getPointeeType(); + QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType(); + QualType destPointee + = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); + QualType destType = Context.getPointerType(destPointee); + ImpCastExprToType(RHS, destType); // add qualifiers if necessary + ImpCastExprToType(LHS, destType); // promote to void* + return destType; + } // Check constraints for C object pointers types (C99 6.5.15p3,6). if (LHSTy->isPointerType() && RHSTy->isPointerType()) { // get the "pointed to" types - QualType lhptee = LHSTy->getAsPointerType()->getPointeeType(); - QualType rhptee = RHSTy->getAsPointerType()->getPointeeType(); + QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType(); + QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType(); // ignore qualifiers on void (C99 6.5.15p3, clause 6) if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) { // Figure out necessary qualifiers (C99 6.5.15p6) - QualType destPointee=lhptee.getQualifiedType(rhptee.getCVRQualifiers()); + QualType destPointee + = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); ImpCastExprToType(LHS, destType); // add qualifiers if necessary ImpCastExprToType(RHS, destType); // promote to void* return destType; } if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) { - QualType destPointee=rhptee.getQualifiedType(lhptee.getCVRQualifiers()); + QualType destPointee + = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); ImpCastExprToType(LHS, destType); // add qualifiers if necessary ImpCastExprToType(RHS, destType); // promote to void* @@ -3248,7 +3615,7 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, ImpCastExprToType(RHS, LHSTy); return LHSTy; } - + // GCC compatibility: soften pointer/integer mismatch. if (RHSTy->isPointerType() && LHSTy->isIntegerType()) { Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch) @@ -3292,12 +3659,11 @@ Action::OwningExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, Cond.release(); LHS.release(); RHS.release(); - return Owned(new (Context) ConditionalOperator(CondExpr, + return Owned(new (Context) ConditionalOperator(CondExpr, QuestionLoc, isLHSNull ? 0 : LHSExpr, - RHSExpr, result)); + ColonLoc, RHSExpr, result)); } - // CheckPointerTypesForAssignment - This is a very tricky routine (despite // being closely modeled after the C99 spec:-). The odd characteristic of this // routine is it effectively iqnores the qualifiers on the top level pointee. @@ -3307,9 +3673,16 @@ Sema::AssignConvertType Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) { QualType lhptee, rhptee; + if ((lhsType->isObjCClassType() && + (rhsType.getDesugaredType() == Context.ObjCClassRedefinitionType)) || + (rhsType->isObjCClassType() && + (lhsType.getDesugaredType() == Context.ObjCClassRedefinitionType))) { + return Compatible; + } + // get the "pointed to" type (ignoring qualifiers at the top level) - lhptee = lhsType->getAsPointerType()->getPointeeType(); - rhptee = rhsType->getAsPointerType()->getPointeeType(); + lhptee = lhsType->getAs<PointerType>()->getPointeeType(); + rhptee = rhsType->getAs<PointerType>()->getPointeeType(); // make sure we operate on the canonical type lhptee = Context.getCanonicalType(lhptee); @@ -3371,7 +3744,7 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) { return IncompatiblePointerSign; } // General pointer incompatibility takes priority over qualifiers. - return IncompatiblePointer; + return IncompatiblePointer; } return ConvTy; } @@ -3386,8 +3759,8 @@ Sema::CheckBlockPointerTypesForAssignment(QualType lhsType, QualType lhptee, rhptee; // get the "pointed to" type (ignoring qualifiers at the top level) - lhptee = lhsType->getAsBlockPointerType()->getPointeeType(); - rhptee = rhsType->getAsBlockPointerType()->getPointeeType(); + lhptee = lhsType->getAs<BlockPointerType>()->getPointeeType(); + rhptee = rhsType->getAs<BlockPointerType>()->getPointeeType(); // make sure we operate on the canonical type lhptee = Context.getCanonicalType(lhptee); @@ -3430,6 +3803,13 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { if (lhsType == rhsType) return Compatible; // Common case: fast path an exact match. + if ((lhsType->isObjCClassType() && + (rhsType.getDesugaredType() == Context.ObjCClassRedefinitionType)) || + (rhsType->isObjCClassType() && + (lhsType.getDesugaredType() == Context.ObjCClassRedefinitionType))) { + return Compatible; + } + // If the left-hand side is a reference type, then we are in a // (rare!) case where we've allowed the use of references in C, // e.g., as a parameter type in a built-in function. In this case, @@ -3437,23 +3817,11 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { // right-hand side type. The caller is responsible for adjusting // lhsType so that the resulting expression does not have reference // type. - if (const ReferenceType *lhsTypeRef = lhsType->getAsReferenceType()) { + if (const ReferenceType *lhsTypeRef = lhsType->getAs<ReferenceType>()) { if (Context.typesAreCompatible(lhsTypeRef->getPointeeType(), rhsType)) return Compatible; return Incompatible; } - - if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType()) { - if (ObjCQualifiedIdTypesAreCompatible(lhsType, rhsType, false)) - return Compatible; - // Relax integer conversions like we do for pointers below. - if (rhsType->isIntegerType()) - return IntToPointer; - if (lhsType->isIntegerType()) - return PointerToInt; - return IncompatibleObjCQualifiedId; - } - // Allow scalar to ExtVector assignments, and assignments of an ExtVector type // to the same ExtVector type. if (lhsType->isExtVectorType()) { @@ -3462,7 +3830,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { if (!rhsType->isVectorType() && rhsType->isArithmeticType()) return Compatible; } - + if (lhsType->isVectorType() || rhsType->isVectorType()) { // If we are allowing lax vector conversions, and LHS and RHS are both // vectors, the total size only needs to be the same. This is a bitcast; @@ -3485,13 +3853,18 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { if (isa<PointerType>(rhsType)) return CheckPointerTypesForAssignment(lhsType, rhsType); - if (rhsType->getAsBlockPointerType()) { - if (lhsType->getAsPointerType()->getPointeeType()->isVoidType()) + // In general, C pointers are not compatible with ObjC object pointers. + if (isa<ObjCObjectPointerType>(rhsType)) { + if (lhsType->isVoidPointerType()) // an exception to the rule. + return Compatible; + return IncompatiblePointer; + } + if (rhsType->getAs<BlockPointerType>()) { + if (lhsType->getAs<PointerType>()->getPointeeType()->isVoidType()) return Compatible; // Treat block pointers as objects. - if (getLangOptions().ObjC1 && - lhsType == Context.getCanonicalType(Context.getObjCIdType())) + if (getLangOptions().ObjC1 && lhsType->isObjCIdType()) return Compatible; } return Incompatible; @@ -3502,20 +3875,47 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { return IntToBlockPointer; // Treat block pointers as objects. - if (getLangOptions().ObjC1 && - rhsType == Context.getCanonicalType(Context.getObjCIdType())) + if (getLangOptions().ObjC1 && rhsType->isObjCIdType()) return Compatible; if (rhsType->isBlockPointerType()) return CheckBlockPointerTypesForAssignment(lhsType, rhsType); - if (const PointerType *RHSPT = rhsType->getAsPointerType()) { + if (const PointerType *RHSPT = rhsType->getAs<PointerType>()) { if (RHSPT->getPointeeType()->isVoidType()) return Compatible; } return Incompatible; } + if (isa<ObjCObjectPointerType>(lhsType)) { + if (rhsType->isIntegerType()) + return IntToPointer; + + // In general, C pointers are not compatible with ObjC object pointers. + if (isa<PointerType>(rhsType)) { + if (rhsType->isVoidPointerType()) // an exception to the rule. + return Compatible; + return IncompatiblePointer; + } + if (rhsType->isObjCObjectPointerType()) { + if (lhsType->isObjCBuiltinType() || rhsType->isObjCBuiltinType()) + return Compatible; + if (Context.typesAreCompatible(lhsType, rhsType)) + return Compatible; + if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType()) + return IncompatibleObjCQualifiedId; + return IncompatiblePointer; + } + if (const PointerType *RHSPT = rhsType->getAs<PointerType>()) { + if (RHSPT->getPointeeType()->isVoidType()) + return Compatible; + } + // Treat block pointers as objects. + if (rhsType->isBlockPointerType()) + return Compatible; + return Incompatible; + } if (isa<PointerType>(rhsType)) { // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer. if (lhsType == Context.BoolTy) @@ -3528,7 +3928,26 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { return CheckPointerTypesForAssignment(lhsType, rhsType); if (isa<BlockPointerType>(lhsType) && - rhsType->getAsPointerType()->getPointeeType()->isVoidType()) + rhsType->getAs<PointerType>()->getPointeeType()->isVoidType()) + return Compatible; + return Incompatible; + } + if (isa<ObjCObjectPointerType>(rhsType)) { + // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer. + if (lhsType == Context.BoolTy) + return Compatible; + + if (lhsType->isIntegerType()) + return PointerToInt; + + // In general, C pointers are not compatible with ObjC object pointers. + if (isa<PointerType>(lhsType)) { + if (lhsType->isVoidPointerType()) // an exception to the rule. + return Compatible; + return IncompatiblePointer; + } + if (isa<BlockPointerType>(lhsType) && + rhsType->getAs<PointerType>()->getPointeeType()->isVoidType()) return Compatible; return Incompatible; } @@ -3542,7 +3961,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { /// \brief Constructs a transparent union from an expression that is /// used to initialize the transparent union. -static void ConstructTransparentUnion(ASTContext &C, Expr *&E, +static void ConstructTransparentUnion(ASTContext &C, Expr *&E, QualType UnionType, FieldDecl *Field) { // Build an initializer list that designates the appropriate member // of the transparent union. @@ -3562,7 +3981,7 @@ Sema::AssignConvertType Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { QualType FromType = rExpr->getType(); - // If the ArgType is a Union type, we want to handle a potential + // If the ArgType is a Union type, we want to handle a potential // transparent_union GCC extension. const RecordType *UT = ArgType->getAsUnionType(); if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>()) @@ -3580,13 +3999,14 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { // 1) void pointer // 2) null pointer constant if (FromType->isPointerType()) - if (FromType->getAsPointerType()->getPointeeType()->isVoidType()) { + if (FromType->getAs<PointerType>()->getPointeeType()->isVoidType()) { ImpCastExprToType(rExpr, it->getType()); InitField = *it; break; } - - if (rExpr->isNullPointerConstant(Context)) { + + if (rExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { ImpCastExprToType(rExpr, it->getType()); InitField = *it; break; @@ -3626,10 +4046,11 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { // C99 6.5.16.1p1: the left operand is a pointer and the right is // a null pointer constant. - if ((lhsType->isPointerType() || - lhsType->isObjCQualifiedIdType() || + if ((lhsType->isPointerType() || + lhsType->isObjCObjectPointerType() || lhsType->isBlockPointerType()) - && rExpr->isNullPointerConstant(Context)) { + && rExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { ImpCastExprToType(rExpr, lhsType); return Compatible; } @@ -3681,8 +4102,8 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, // type. It would be nice if we only had one vector type someday. if (getLangOptions().LaxVectorConversions) { // FIXME: Should we warn here? - if (const VectorType *LV = lhsType->getAsVectorType()) { - if (const VectorType *RV = rhsType->getAsVectorType()) + if (const VectorType *LV = lhsType->getAs<VectorType>()) { + if (const VectorType *RV = rhsType->getAs<VectorType>()) if (LV->getElementType() == RV->getElementType() && LV->getNumElements() == RV->getNumElements()) { return lhsType->isExtVectorType() ? lhsType : rhsType; @@ -3698,9 +4119,9 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, std::swap(rex, lex); std::swap(rhsType, lhsType); } - + // Handle the case of an ext vector and scalar. - if (const ExtVectorType *LV = lhsType->getAsExtVectorType()) { + if (const ExtVectorType *LV = lhsType->getAs<ExtVectorType>()) { QualType EltTy = LV->getElementType(); if (EltTy->isIntegralType() && rhsType->isIntegralType()) { if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) { @@ -3718,7 +4139,7 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, } } } - + // Vectors of different size or scalar and non-ext-vector are errors. Diag(Loc, diag::err_typecheck_vector_not_convertable) << lex->getType() << rex->getType() @@ -3727,8 +4148,7 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, } inline QualType Sema::CheckMultiplyDivideOperands( - Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) -{ + Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) { if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) return CheckVectorOperands(Loc, lex, rex); @@ -3740,8 +4160,7 @@ inline QualType Sema::CheckMultiplyDivideOperands( } inline QualType Sema::CheckRemainderOperands( - Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) -{ + Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) { if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) { if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType()) return CheckVectorOperands(Loc, lex, rex); @@ -3756,8 +4175,7 @@ inline QualType Sema::CheckRemainderOperands( } inline QualType Sema::CheckAdditionOperands( // C99 6.5.6 - Expr *&lex, Expr *&rex, SourceLocation Loc, QualType* CompLHSTy) -{ + Expr *&lex, Expr *&rex, SourceLocation Loc, QualType* CompLHSTy) { if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) { QualType compType = CheckVectorOperands(Loc, lex, rex); if (CompLHSTy) *CompLHSTy = compType; @@ -3775,12 +4193,14 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6 // Put any potential pointer into PExp Expr* PExp = lex, *IExp = rex; - if (IExp->getType()->isPointerType()) + if (IExp->getType()->isAnyPointerType()) std::swap(PExp, IExp); - if (const PointerType *PTy = PExp->getType()->getAsPointerType()) { + if (PExp->getType()->isAnyPointerType()) { + if (IExp->getType()->isIntegerType()) { - QualType PointeeTy = PTy->getPointeeType(); + QualType PointeeTy = PExp->getType()->getPointeeType(); + // Check for arithmetic on pointers to incomplete types. if (PointeeTy->isVoidType()) { if (getLangOptions().CPlusPlus) { @@ -3802,30 +4222,31 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6 // GNU extension: arithmetic on pointer to function Diag(Loc, diag::ext_gnu_ptr_func_arith) << lex->getType() << lex->getSourceRange(); - } else if (!PTy->isDependentType() && - RequireCompleteType(Loc, PointeeTy, - diag::err_typecheck_arithmetic_incomplete_type, - PExp->getSourceRange(), SourceRange(), - PExp->getType())) - return QualType(); - + } else { + // Check if we require a complete type. + if (((PExp->getType()->isPointerType() && + !PExp->getType()->isDependentType()) || + PExp->getType()->isObjCObjectPointerType()) && + RequireCompleteType(Loc, PointeeTy, + PDiag(diag::err_typecheck_arithmetic_incomplete_type) + << PExp->getSourceRange() + << PExp->getType())) + return QualType(); + } // Diagnose bad cases where we step over interface counts. if (PointeeTy->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { Diag(Loc, diag::err_arithmetic_nonfragile_interface) << PointeeTy << PExp->getSourceRange(); return QualType(); } - + if (CompLHSTy) { - QualType LHSTy = lex->getType(); - if (LHSTy->isPromotableIntegerType()) - LHSTy = Context.IntTy; - else { - QualType T = isPromotableBitField(lex, Context); - if (!T.isNull()) - LHSTy = T; + QualType LHSTy = Context.isPromotableBitField(lex); + if (LHSTy.isNull()) { + LHSTy = lex->getType(); + if (LHSTy->isPromotableIntegerType()) + LHSTy = Context.getPromotedIntegerType(LHSTy); } - *CompLHSTy = LHSTy; } return PExp->getType(); @@ -3856,8 +4277,8 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, } // Either ptr - int or ptr - ptr. - if (const PointerType *LHSPTy = lex->getType()->getAsPointerType()) { - QualType lpointee = LHSPTy->getPointeeType(); + if (lex->getType()->isAnyPointerType()) { + QualType lpointee = lex->getType()->getPointeeType(); // The LHS must be an completely-defined object type. @@ -3882,11 +4303,10 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, // GNU C extension: arithmetic on pointer to function ComplainAboutFunc = lex; } else if (!lpointee->isDependentType() && - RequireCompleteType(Loc, lpointee, - diag::err_typecheck_sub_ptr_object, - lex->getSourceRange(), - SourceRange(), - lex->getType())) + RequireCompleteType(Loc, lpointee, + PDiag(diag::err_typecheck_sub_ptr_object) + << lex->getSourceRange() + << lex->getType())) return QualType(); // Diagnose bad cases where we step over interface counts. @@ -3895,7 +4315,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, << lpointee << lex->getSourceRange(); return QualType(); } - + // The result type of a pointer-int computation is the pointer type. if (rex->getType()->isIntegerType()) { if (ComplainAboutVoid) @@ -3903,7 +4323,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, << lex->getSourceRange() << rex->getSourceRange(); if (ComplainAboutFunc) Diag(Loc, diag::ext_gnu_ptr_func_arith) - << ComplainAboutFunc->getType() + << ComplainAboutFunc->getType() << ComplainAboutFunc->getSourceRange(); if (CompLHSTy) *CompLHSTy = lex->getType(); @@ -3911,7 +4331,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, } // Handle pointer-pointer subtractions. - if (const PointerType *RHSPTy = rex->getType()->getAsPointerType()) { + if (const PointerType *RHSPTy = rex->getType()->getAs<PointerType>()) { QualType rpointee = RHSPTy->getPointeeType(); // RHS must be a completely-type object type. @@ -3936,10 +4356,9 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, ComplainAboutFunc = rex; } else if (!rpointee->isDependentType() && RequireCompleteType(Loc, rpointee, - diag::err_typecheck_sub_ptr_object, - rex->getSourceRange(), - SourceRange(), - rex->getType())) + PDiag(diag::err_typecheck_sub_ptr_object) + << rex->getSourceRange() + << rex->getType())) return QualType(); if (getLangOptions().CPlusPlus) { @@ -3967,7 +4386,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, << lex->getSourceRange() << rex->getSourceRange(); if (ComplainAboutFunc) Diag(Loc, diag::ext_gnu_ptr_func_arith) - << ComplainAboutFunc->getType() + << ComplainAboutFunc->getType() << ComplainAboutFunc->getSourceRange(); if (CompLHSTy) *CompLHSTy = lex->getType(); @@ -3987,19 +4406,32 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, // Shifts don't perform usual arithmetic conversions, they just do integer // promotions on each operand. C99 6.5.7p3 - QualType LHSTy; - if (lex->getType()->isPromotableIntegerType()) - LHSTy = Context.IntTy; - else { - LHSTy = isPromotableBitField(lex, Context); - if (LHSTy.isNull()) - LHSTy = lex->getType(); + QualType LHSTy = Context.isPromotableBitField(lex); + if (LHSTy.isNull()) { + LHSTy = lex->getType(); + if (LHSTy->isPromotableIntegerType()) + LHSTy = Context.getPromotedIntegerType(LHSTy); } if (!isCompAssign) ImpCastExprToType(lex, LHSTy); UsualUnaryConversions(rex); + // Sanity-check shift operands + llvm::APSInt Right; + // Check right/shifter operand + if (!rex->isValueDependent() && + rex->isIntegerConstantExpr(Right, Context)) { + if (Right.isNegative()) + Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange(); + else { + llvm::APInt LeftBits(Right.getBitWidth(), + Context.getTypeSize(lex->getType())); + if (Right.uge(LeftBits)) + Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange(); + } + } + // "The type of the result is that of the promoted left operand." return LHSTy; } @@ -4027,7 +4459,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, // For non-floating point types, check for self-comparisons of the form // x == x, x != x, x < x, etc. These always evaluate to a constant, and // often indicate logic errors in the program. - // NOTE: Don't warn about comparisons of enum constants. These can arise + // NOTE: Don't warn about comparisons of enum constants. These can arise // from macro expansions, and are usually quite deliberate. Expr *LHSStripped = lex->IgnoreParens(); Expr *RHSStripped = rex->IgnoreParens(); @@ -4036,24 +4468,25 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (DRL->getDecl() == DRR->getDecl() && !isa<EnumConstantDecl>(DRL->getDecl())) Diag(Loc, diag::warn_selfcomparison); - + if (isa<CastExpr>(LHSStripped)) LHSStripped = LHSStripped->IgnoreParenCasts(); if (isa<CastExpr>(RHSStripped)) RHSStripped = RHSStripped->IgnoreParenCasts(); - + // Warn about comparisons against a string constant (unless the other // operand is null), the user probably wants strcmp. Expr *literalString = 0; Expr *literalStringStripped = 0; if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) && - !RHSStripped->isNullPointerConstant(Context)) { + !RHSStripped->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { literalString = lex; literalStringStripped = LHSStripped; - } - else if ((isa<StringLiteral>(RHSStripped) || - isa<ObjCEncodeExpr>(RHSStripped)) && - !LHSStripped->isNullPointerConstant(Context)) { + } else if ((isa<StringLiteral>(RHSStripped) || + isa<ObjCEncodeExpr>(RHSStripped)) && + !LHSStripped->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { literalString = rex; literalStringStripped = RHSStripped; } @@ -4098,41 +4531,31 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, return ResultTy; } - bool LHSIsNull = lex->isNullPointerConstant(Context); - bool RHSIsNull = rex->isNullPointerConstant(Context); + bool LHSIsNull = lex->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); + bool RHSIsNull = rex->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); // All of the following pointer related warnings are GCC extensions, except // when handling null pointer constants. One day, we can consider making them // errors (when -pedantic-errors is enabled). if (lType->isPointerType() && rType->isPointerType()) { // C99 6.5.8p2 QualType LCanPointeeTy = - Context.getCanonicalType(lType->getAsPointerType()->getPointeeType()); + Context.getCanonicalType(lType->getAs<PointerType>()->getPointeeType()); QualType RCanPointeeTy = - Context.getCanonicalType(rType->getAsPointerType()->getPointeeType()); - - if (rType->isFunctionPointerType() || lType->isFunctionPointerType()) { - if (isRelational) { - Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - } - } - if (((!LHSIsNull || isRelational) && LCanPointeeTy->isVoidType()) != - ((!RHSIsNull || isRelational) && RCanPointeeTy->isVoidType())) { - Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - } - // Simple check: if the pointee types are identical, we're done. - if (LCanPointeeTy == RCanPointeeTy) - return ResultTy; + Context.getCanonicalType(rType->getAs<PointerType>()->getPointeeType()); if (getLangOptions().CPlusPlus) { + if (LCanPointeeTy == RCanPointeeTy) + return ResultTy; + // C++ [expr.rel]p2: // [...] Pointer conversions (4.10) and qualification // conversions (4.4) are performed on pointer operands (or on // a pointer operand and a null pointer constant) to bring // them to their composite pointer type. [...] // - // C++ [expr.eq]p2 uses the same notion for (in)equality + // C++ [expr.eq]p1 uses the same notion for (in)equality // comparisons of pointers. QualType T = FindCompositePointerType(lex, rex); if (T.isNull()) { @@ -4145,36 +4568,82 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, ImpCastExprToType(rex, T); return ResultTy; } - - if (!LHSIsNull && !RHSIsNull && // C99 6.5.9p2 - !LCanPointeeTy->isVoidType() && !RCanPointeeTy->isVoidType() && - !Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(), - RCanPointeeTy.getUnqualifiedType()) && - !Context.areComparableObjCPointerTypes(lType, rType)) { + // C99 6.5.9p2 and C99 6.5.8p2 + if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(), + RCanPointeeTy.getUnqualifiedType())) { + // Valid unless a relational comparison of function pointers + if (isRelational && LCanPointeeTy->isFunctionType()) { + Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers) + << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + } + } else if (!isRelational && + (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { + // Valid unless comparison between non-null pointer and function pointer + if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) + && !LHSIsNull && !RHSIsNull) { + Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void) + << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + } + } else { + // Invalid Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); } - ImpCastExprToType(rex, lType); // promote the pointer to pointer + if (LCanPointeeTy != RCanPointeeTy) + ImpCastExprToType(rex, lType); // promote the pointer to pointer return ResultTy; } - // C++ allows comparison of pointers with null pointer constants. + if (getLangOptions().CPlusPlus) { - if (lType->isPointerType() && RHSIsNull) { - ImpCastExprToType(rex, lType); + // Comparison of pointers with null pointer constants and equality + // comparisons of member pointers to null pointer constants. + if (RHSIsNull && + (lType->isPointerType() || + (!isRelational && lType->isMemberPointerType()))) { + ImpCastExprToType(rex, lType, CastExpr::CK_NullToMemberPointer); + return ResultTy; + } + if (LHSIsNull && + (rType->isPointerType() || + (!isRelational && rType->isMemberPointerType()))) { + ImpCastExprToType(lex, rType, CastExpr::CK_NullToMemberPointer); return ResultTy; } - if (rType->isPointerType() && LHSIsNull) { - ImpCastExprToType(lex, rType); + + // Comparison of member pointers. + if (!isRelational && + lType->isMemberPointerType() && rType->isMemberPointerType()) { + // C++ [expr.eq]p2: + // In addition, pointers to members can be compared, or a pointer to + // member and a null pointer constant. Pointer to member conversions + // (4.11) and qualification conversions (4.4) are performed to bring + // them to a common type. If one operand is a null pointer constant, + // the common type is the type of the other operand. Otherwise, the + // common type is a pointer to member type similar (4.4) to the type + // of one of the operands, with a cv-qualification signature (4.4) + // that is the union of the cv-qualification signatures of the operand + // types. + QualType T = FindCompositePointerType(lex, rex); + if (T.isNull()) { + Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers) + << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + return QualType(); + } + + ImpCastExprToType(lex, T); + ImpCastExprToType(rex, T); return ResultTy; } - // And comparison of nullptr_t with itself. + + // Comparison of nullptr_t with itself. if (lType->isNullPtrType() && rType->isNullPtrType()) return ResultTy; } + // Handle block pointer types. if (!isRelational && lType->isBlockPointerType() && rType->isBlockPointerType()) { - QualType lpointee = lType->getAsBlockPointerType()->getPointeeType(); - QualType rpointee = rType->getAsBlockPointerType()->getPointeeType(); + QualType lpointee = lType->getAs<BlockPointerType>()->getPointeeType(); + QualType rpointee = rType->getAs<BlockPointerType>()->getPointeeType(); if (!LHSIsNull && !RHSIsNull && !Context.typesAreCompatible(lpointee, rpointee)) { @@ -4189,9 +4658,9 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, && ((lType->isBlockPointerType() && rType->isPointerType()) || (lType->isPointerType() && rType->isBlockPointerType()))) { if (!LHSIsNull && !RHSIsNull) { - if (!((rType->isPointerType() && rType->getAsPointerType() + if (!((rType->isPointerType() && rType->getAs<PointerType>() ->getPointeeType()->isVoidType()) - || (lType->isPointerType() && lType->getAsPointerType() + || (lType->isPointerType() && lType->getAs<PointerType>() ->getPointeeType()->isVoidType()))) Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); @@ -4200,10 +4669,10 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, return ResultTy; } - if ((lType->isObjCQualifiedIdType() || rType->isObjCQualifiedIdType())) { + if ((lType->isObjCObjectPointerType() || rType->isObjCObjectPointerType())) { if (lType->isPointerType() || rType->isPointerType()) { - const PointerType *LPT = lType->getAsPointerType(); - const PointerType *RPT = rType->getAsPointerType(); + const PointerType *LPT = lType->getAs<PointerType>(); + const PointerType *RPT = rType->getAs<PointerType>(); bool LPtrToVoid = LPT ? Context.getCanonicalType(LPT->getPointeeType())->isVoidType() : false; bool RPtrToVoid = RPT ? @@ -4213,43 +4682,49 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, !Context.typesAreCompatible(lType, rType)) { Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - ImpCastExprToType(rex, lType); - return ResultTy; } ImpCastExprToType(rex, lType); return ResultTy; } - if (ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) { + if (lType->isObjCObjectPointerType() && rType->isObjCObjectPointerType()) { + if (!Context.areComparableObjCPointerTypes(lType, rType)) + Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) + << lType << rType << lex->getSourceRange() << rex->getSourceRange(); ImpCastExprToType(rex, lType); return ResultTy; - } else { - if ((lType->isObjCQualifiedIdType() && rType->isObjCQualifiedIdType())) { - Diag(Loc, diag::warn_incompatible_qualified_id_operands) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - ImpCastExprToType(rex, lType); - return ResultTy; - } } } - if ((lType->isPointerType() || lType->isObjCQualifiedIdType()) && - rType->isIntegerType()) { - if (isRelational) - Diag(Loc, diag::ext_typecheck_ordered_comparison_of_pointer_integer) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - else if (!RHSIsNull) - Diag(Loc, diag::ext_typecheck_comparison_of_pointer_integer) + if (lType->isAnyPointerType() && rType->isIntegerType()) { + unsigned DiagID = 0; + if (RHSIsNull) { + if (isRelational) + DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero; + } else if (isRelational) + DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer; + else + DiagID = diag::ext_typecheck_comparison_of_pointer_integer; + + if (DiagID) { + Diag(Loc, DiagID) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + } ImpCastExprToType(rex, lType); // promote the integer to pointer return ResultTy; } - if (lType->isIntegerType() && - (rType->isPointerType() || rType->isObjCQualifiedIdType())) { - if (isRelational) - Diag(Loc, diag::ext_typecheck_ordered_comparison_of_pointer_integer) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - else if (!LHSIsNull) - Diag(Loc, diag::ext_typecheck_comparison_of_pointer_integer) + if (lType->isIntegerType() && rType->isAnyPointerType()) { + unsigned DiagID = 0; + if (LHSIsNull) { + if (isRelational) + DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero; + } else if (isRelational) + DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer; + else + DiagID = diag::ext_typecheck_comparison_of_pointer_integer; + + if (DiagID) { + Diag(Loc, DiagID) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + } ImpCastExprToType(lex, rType); // promote the integer to pointer return ResultTy; } @@ -4299,21 +4774,13 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, CheckFloatComparison(Loc,lex,rex); } - // FIXME: Vector compare support in the LLVM backend is not fully reliable, - // just reject all vector comparisons for now. - if (1) { - Diag(Loc, diag::err_typecheck_vector_comparison) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - return QualType(); - } - // Return the type for the comparison, which is the same as vector type for // integer vectors, or an integer type of identical size and number of // elements for floating point vectors. if (lType->isIntegerType()) return lType; - const VectorType *VTy = lType->getAsVectorType(); + const VectorType *VTy = lType->getAs<VectorType>(); unsigned TypeSize = Context.getTypeSize(VTy->getElementType()); if (TypeSize == Context.getTypeSize(Context.IntTy)) return Context.getExtVectorType(Context.IntTy, VTy->getNumElements()); @@ -4326,8 +4793,7 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, } inline QualType Sema::CheckBitwiseOperands( - Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) -{ + Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) { if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) return CheckVectorOperands(Loc, lex, rex); @@ -4339,8 +4805,7 @@ inline QualType Sema::CheckBitwiseOperands( } inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] - Expr *&lex, Expr *&rex, SourceLocation Loc) -{ + Expr *&lex, Expr *&rex, SourceLocation Loc) { UsualUnaryConversions(lex); UsualUnaryConversions(rex); @@ -4353,18 +4818,16 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] /// is a read-only property; return true if so. A readonly property expression /// depends on various declarations and thus must be treated specially. /// -static bool IsReadonlyProperty(Expr *E, Sema &S) -{ +static bool IsReadonlyProperty(Expr *E, Sema &S) { if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) { const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E); if (ObjCPropertyDecl *PDecl = PropExpr->getProperty()) { QualType BaseType = PropExpr->getBase()->getType(); - if (const PointerType *PTy = BaseType->getAsPointerType()) - if (const ObjCInterfaceType *IFTy = - PTy->getPointeeType()->getAsObjCInterfaceType()) - if (ObjCInterfaceDecl *IFace = IFTy->getDecl()) - if (S.isPropertyReadonly(PDecl, IFace)) - return true; + if (const ObjCObjectPointerType *OPT = + BaseType->getAsObjCInterfacePointerType()) + if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl()) + if (S.isPropertyReadonly(PDecl, IFace)) + return true; } } return false; @@ -4374,7 +4837,7 @@ static bool IsReadonlyProperty(Expr *E, Sema &S) /// emit an error and return true. If so, return false. static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { SourceLocation OrigLoc = Loc; - Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context, + Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context, &Loc); if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S)) IsLV = Expr::MLV_ReadonlyProperty; @@ -4403,8 +4866,8 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { case Expr::MLV_IncompleteType: case Expr::MLV_IncompleteVoidType: return S.RequireCompleteType(Loc, E->getType(), - diag::err_typecheck_incomplete_type_not_modifiable_lvalue, - E->getSourceRange()); + PDiag(diag::err_typecheck_incomplete_type_not_modifiable_lvalue) + << E->getSourceRange()); case Expr::MLV_DuplicateVectorComponents: Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue; break; @@ -4425,7 +4888,7 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { if (NeedType) S.Diag(Loc, Diag) << E->getType() << E->getSourceRange() << Assign; else - S.Diag(Loc, Diag) << E->getSourceRange() << Assign; + S.Diag(Loc, Diag) << E->getSourceRange() << Assign; return true; } @@ -4449,9 +4912,9 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, // Special case of NSObject attributes on c-style pointer types. if (ConvTy == IncompatiblePointer && ((Context.isObjCNSObjectType(LHSType) && - Context.isObjCObjectPointerType(RHSType)) || + RHSType->isObjCObjectPointerType()) || (Context.isObjCNSObjectType(RHSType) && - Context.isObjCObjectPointerType(LHSType)))) + LHSType->isObjCObjectPointerType()))) ConvTy = Compatible; // If the RHS is a unary plus or minus, check to see if they = and + are @@ -4525,9 +4988,11 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc, Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange(); } else if (ResType->isRealType()) { // OK! - } else if (const PointerType *PT = ResType->getAsPointerType()) { + } else if (ResType->isAnyPointerType()) { + QualType PointeeTy = ResType->getPointeeType(); + // C99 6.5.2.4p2, 6.5.6p2 - if (PT->getPointeeType()->isVoidType()) { + if (PointeeTy->isVoidType()) { if (getLangOptions().CPlusPlus) { Diag(OpLoc, diag::err_typecheck_pointer_arith_void_type) << Op->getSourceRange(); @@ -4536,7 +5001,7 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc, // Pointer to void is a GNU extension in C. Diag(OpLoc, diag::ext_gnu_void_ptr) << Op->getSourceRange(); - } else if (PT->getPointeeType()->isFunctionType()) { + } else if (PointeeTy->isFunctionType()) { if (getLangOptions().CPlusPlus) { Diag(OpLoc, diag::err_typecheck_pointer_arith_function_type) << Op->getType() << Op->getSourceRange(); @@ -4545,11 +5010,17 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc, Diag(OpLoc, diag::ext_gnu_ptr_func_arith) << ResType << Op->getSourceRange(); - } else if (RequireCompleteType(OpLoc, PT->getPointeeType(), - diag::err_typecheck_arithmetic_incomplete_type, - Op->getSourceRange(), SourceRange(), - ResType)) + } else if (RequireCompleteType(OpLoc, PointeeTy, + PDiag(diag::err_typecheck_arithmetic_incomplete_type) + << Op->getSourceRange() + << ResType)) return QualType(); + // Diagnose bad cases where we step over interface counts. + else if (PointeeTy->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { + Diag(OpLoc, diag::err_arithmetic_nonfragile_interface) + << PointeeTy << Op->getSourceRange(); + return QualType(); + } } else if (ResType->isComplexType()) { // C99 does not support ++/-- on complex types, we allow as an extension. Diag(OpLoc, diag::ext_integer_increment_complex) @@ -4672,6 +5143,15 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { Diag(OpLoc, diag::err_typecheck_address_of) << "vector element" << op->getSourceRange(); return QualType(); + } else if (isa<ObjCPropertyRefExpr>(op)) { + // cannot take address of a property expression. + Diag(OpLoc, diag::err_typecheck_address_of) + << "property expression" << op->getSourceRange(); + return QualType(); + } else if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(op)) { + // FIXME: Can LHS ever be null here? + if (!CheckAddressOfOperand(CO->getTrueExpr(), OpLoc).isNull()) + return CheckAddressOfOperand(CO->getFalseExpr(), OpLoc); } else if (dcl) { // C99 6.5.3.2p1 // We have an lvalue with a decl. Make sure the decl is not declared // with the register storage-class specifier. @@ -4681,17 +5161,26 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { << "register variable" << op->getSourceRange(); return QualType(); } - } else if (isa<OverloadedFunctionDecl>(dcl)) { + } else if (isa<OverloadedFunctionDecl>(dcl) || + isa<FunctionTemplateDecl>(dcl)) { return Context.OverloadTy; - } else if (isa<FieldDecl>(dcl)) { + } else if (FieldDecl *FD = dyn_cast<FieldDecl>(dcl)) { // Okay: we can take the address of a field. // Could be a pointer to member, though, if there is an explicit // scope qualifier for the class. if (isa<QualifiedDeclRefExpr>(op)) { DeclContext *Ctx = dcl->getDeclContext(); - if (Ctx && Ctx->isRecord()) + if (Ctx && Ctx->isRecord()) { + if (FD->getType()->isReferenceType()) { + Diag(OpLoc, + diag::err_cannot_form_pointer_to_member_of_reference_type) + << FD->getDeclName() << FD->getType(); + return QualType(); + } + return Context.getMemberPointerType(op->getType(), Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr()); + } } } else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(dcl)) { // Okay: we can take the address of a function. @@ -4725,9 +5214,12 @@ QualType Sema::CheckIndirectionOperand(Expr *Op, SourceLocation OpLoc) { // incomplete type or void. It would be possible to warn about dereferencing // a void pointer, but it's completely well-defined, and such a warning is // unlikely to catch any mistakes. - if (const PointerType *PT = Ty->getAsPointerType()) + if (const PointerType *PT = Ty->getAs<PointerType>()) return PT->getPointeeType(); + if (const ObjCObjectPointerType *OPT = Ty->getAs<ObjCObjectPointerType>()) + return OPT->getPointeeType(); + Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer) << Ty << Op->getSourceRange(); return QualType(); @@ -4914,7 +5406,7 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, assert((rhs != 0) && "ActOnBinOp(): missing right expression"); if (getLangOptions().CPlusPlus && - (lhs->getType()->isOverloadableType() || + (lhs->getType()->isOverloadableType() || rhs->getType()->isOverloadableType())) { // Find all of the overloaded operators visible from this // point. We perform both an operator-name lookup from the local @@ -4926,7 +5418,7 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(), Functions); Expr *Args[2] = { lhs, rhs }; - DeclarationName OpName + DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OverOp); ArgumentDependentLookup(OpName, Args, 2, Functions); } @@ -4941,7 +5433,7 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, } Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, - unsigned OpcIn, + unsigned OpcIn, ExprArg InputArg) { UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn); @@ -4949,16 +5441,17 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, Expr *Input = (Expr *)InputArg.get(); QualType resultType; switch (Opc) { - case UnaryOperator::PostInc: - case UnaryOperator::PostDec: case UnaryOperator::OffsetOf: assert(false && "Invalid unary operator"); break; case UnaryOperator::PreInc: case UnaryOperator::PreDec: + case UnaryOperator::PostInc: + case UnaryOperator::PostDec: resultType = CheckIncrementDecrementOperand(Input, OpLoc, - Opc == UnaryOperator::PreInc); + Opc == UnaryOperator::PreInc || + Opc == UnaryOperator::PostInc); break; case UnaryOperator::AddrOf: resultType = CheckAddressOfOperand(Input, OpLoc); @@ -5043,7 +5536,7 @@ Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, if (OverOp != OO_None) { LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(), Functions); - DeclarationName OpName + DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OverOp); ArgumentDependentLookup(OpName, &Input, 1, Functions); } @@ -5116,7 +5609,8 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, SourceLocation RPLoc) { // FIXME: This function leaks all expressions in the offset components on // error. - QualType ArgTy = QualType::getFromOpaquePtr(argty); + // FIXME: Preserve type source info. + QualType ArgTy = GetTypeFromParser(argty); assert(!ArgTy.isNull() && "Missing type argument!"); bool Dependent = ArgTy->isDependentType(); @@ -5147,7 +5641,7 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, if (!Dependent) { bool DidWarnAboutNonPOD = false; - + // FIXME: Dependent case loses a lot of information here. And probably // leaks like a sieve. for (unsigned i = 0; i != NumComponents; ++i) { @@ -5180,7 +5674,7 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, continue; } - const RecordType *RC = Res->getType()->getAsRecordType(); + const RecordType *RC = Res->getType()->getAs<RecordType>(); if (!RC) { Res->Destroy(Context); return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type) @@ -5197,15 +5691,16 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, DidWarnAboutNonPOD = true; } } - + + LookupResult R; + LookupQualifiedName(R, RD, OC.U.IdentInfo, LookupMemberName); + FieldDecl *MemberDecl - = dyn_cast_or_null<FieldDecl>(LookupQualifiedName(RD, OC.U.IdentInfo, - LookupMemberName) - .getAsDecl()); + = dyn_cast_or_null<FieldDecl>(R.getAsSingleDecl(Context)); // FIXME: Leaks Res if (!MemberDecl) - return ExprError(Diag(BuiltinLoc, diag::err_typecheck_no_member) - << OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd)); + return ExprError(Diag(BuiltinLoc, diag::err_no_member) + << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, OC.LocEnd)); // FIXME: C++: Verify that MemberDecl isn't a static field. // FIXME: Verify that MemberDecl isn't a bitfield. @@ -5229,8 +5724,9 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, Sema::OwningExprResult Sema::ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc, TypeTy *arg1,TypeTy *arg2, SourceLocation RPLoc) { - QualType argT1 = QualType::getFromOpaquePtr(arg1); - QualType argT2 = QualType::getFromOpaquePtr(arg2); + // FIXME: Preserve type source info. + QualType argT1 = GetTypeFromParser(arg1); + QualType argT2 = GetTypeFromParser(arg2); assert((!argT1.isNull() && !argT2.isNull()) && "Missing type argument(s)"); @@ -5255,8 +5751,10 @@ Sema::OwningExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)"); QualType resType; + bool ValueDependent = false; if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) { resType = Context.DependentTy; + ValueDependent = true; } else { // The conditional expression is required to be a constant expression. llvm::APSInt condEval(32); @@ -5268,11 +5766,15 @@ Sema::OwningExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, // If the condition is > zero, then the AST type is the same as the LSHExpr. resType = condEval.getZExtValue() ? LHSExpr->getType() : RHSExpr->getType(); + ValueDependent = condEval.getZExtValue() ? LHSExpr->isValueDependent() + : RHSExpr->isValueDependent(); } cond.release(); expr1.release(); expr2.release(); return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, - resType, RPLoc)); + resType, RPLoc, + resType->isDependentType(), + ValueDependent)); } //===----------------------------------------------------------------------===// @@ -5291,6 +5793,7 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) { BSI->ReturnType = QualType(); BSI->TheScope = BlockScope; BSI->hasBlockDeclRefExprs = false; + BSI->hasPrototype = false; BSI->SavedFunctionNeedsScopeChecking = CurFunctionNeedsScopeChecking; CurFunctionNeedsScopeChecking = false; @@ -5320,12 +5823,12 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { CurBlock->isVariadic = false; // Check for a valid sentinel attribute on this block. if (CurBlock->TheDecl->getAttr<SentinelAttr>()) { - Diag(ParamInfo.getAttributes()->getLoc(), + Diag(ParamInfo.getAttributes()->getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; // FIXME: remove the attribute. } - QualType RetTy = T.getTypePtr()->getAsFunctionType()->getResultType(); - + QualType RetTy = T.getTypePtr()->getAs<FunctionType>()->getResultType(); + // Do not allow returning a objc interface by-value. if (RetTy->isObjCInterfaceType()) { Diag(ParamInfo.getSourceRange().getBegin(), @@ -5367,17 +5870,17 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { PushOnScopeChains(*AI, CurBlock->TheScope); // Check for a valid sentinel attribute on this block. - if (!CurBlock->isVariadic && + if (!CurBlock->isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) { - Diag(ParamInfo.getAttributes()->getLoc(), + Diag(ParamInfo.getAttributes()->getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; // FIXME: remove the attribute. } - + // Analyze the return type. QualType T = GetTypeForDeclarator(ParamInfo, CurScope); - QualType RetTy = T->getAsFunctionType()->getResultType(); - + QualType RetTy = T->getAs<FunctionType>()->getResultType(); + // Do not allow returning a objc interface by-value. if (RetTy->isObjCInterfaceType()) { Diag(ParamInfo.getSourceRange().getBegin(), @@ -5407,7 +5910,7 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, // If blocks are disabled, emit an error. if (!LangOpts.Blocks) Diag(CaretLoc, diag::err_blocks_disable); - + // Ensure that CurBlock is deleted. llvm::OwningPtr<BlockSemaInfo> BSI(CurBlock); @@ -5424,12 +5927,15 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i) ArgTypes.push_back(BSI->Params[i]->getType()); + bool NoReturn = BSI->TheDecl->getAttr<NoReturnAttr>(); QualType BlockTy; if (!BSI->hasPrototype) - BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0); + BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0, false, false, 0, 0, + NoReturn); else BlockTy = Context.getFunctionType(RetTy, ArgTypes.data(), ArgTypes.size(), - BSI->isVariadic, 0); + BSI->isVariadic, 0, false, false, 0, 0, + NoReturn); // FIXME: Check that return/parameter types are complete/non-abstract DiagnoseUnusedParameters(BSI->Params.begin(), BSI->Params.end()); @@ -5439,8 +5945,9 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (CurFunctionNeedsScopeChecking) DiagnoseInvalidJumps(static_cast<CompoundStmt*>(body.get())); CurFunctionNeedsScopeChecking = BSI->SavedFunctionNeedsScopeChecking; - + BSI->TheDecl->setBody(body.takeAs<CompoundStmt>()); + CheckFallThroughForBlock(BlockTy, BSI->TheDecl->getBody()); return Owned(new (Context) BlockExpr(BSI->TheDecl, BlockTy, BSI->hasBlockDeclRefExprs)); } @@ -5448,10 +5955,10 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, Sema::OwningExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, ExprArg expr, TypeTy *type, SourceLocation RPLoc) { - QualType T = QualType::getFromOpaquePtr(type); + QualType T = GetTypeFromParser(type); Expr *E = static_cast<Expr*>(expr.get()); Expr *OrigExpr = E; - + InitBuiltinVaListType(); // Get the va_list type @@ -5466,7 +5973,7 @@ Sema::OwningExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, } else { // Otherwise, the va_list argument must be an l-value because // it is modified by va_arg. - if (!E->isTypeDependent() && + if (!E->isTypeDependent() && CheckForModifiableLvalue(E, BuiltinLoc, *this)) return ExprError(); } @@ -5600,17 +6107,17 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){ return false; } -Sema::ExpressionEvaluationContext -Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { +Sema::ExpressionEvaluationContext +Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { // Introduce a new set of potentially referenced declarations to the stack. if (NewContext == PotentiallyPotentiallyEvaluated) PotentiallyReferencedDeclStack.push_back(PotentiallyReferencedDecls()); - + std::swap(ExprEvalContext, NewContext); return NewContext; } -void +void Sema::PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext, ExpressionEvaluationContext NewContext) { ExprEvalContext = NewContext; @@ -5622,7 +6129,7 @@ Sema::PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext, PotentiallyReferencedDecls RemainingDecls; RemainingDecls.swap(PotentiallyReferencedDeclStack.back()); PotentiallyReferencedDeclStack.pop_back(); - + for (PotentiallyReferencedDecls::iterator I = RemainingDecls.begin(), IEnd = RemainingDecls.end(); I != IEnd; ++I) @@ -5642,30 +6149,33 @@ Sema::PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext, /// \param D the declaration that has been referenced by the source code. void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { assert(D && "No declaration?"); - + if (D->isUsed()) return; - - // Mark a parameter declaration "used", regardless of whether we're in a - // template or not. - if (isa<ParmVarDecl>(D)) + + // Mark a parameter or variable declaration "used", regardless of whether we're in a + // template or not. The reason for this is that unevaluated expressions + // (e.g. (void)sizeof()) constitute a use for warning purposes (-Wunused-variables and + // -Wunused-parameters) + if (isa<ParmVarDecl>(D) || + (isa<VarDecl>(D) && D->getDeclContext()->isFunctionOrMethod())) D->setUsed(true); - + // Do not mark anything as "used" within a dependent context; wait for // an instantiation. if (CurContext->isDependentContext()) return; - + switch (ExprEvalContext) { case Unevaluated: // We are in an expression that is not potentially evaluated; do nothing. return; - + case PotentiallyEvaluated: // We are in a potentially-evaluated expression, so this declaration is // "used"; handle this below. break; - + case PotentiallyPotentiallyEvaluated: // We are in an expression that may be potentially evaluated; queue this // declaration reference until we know whether the expression is @@ -5673,23 +6183,22 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { PotentiallyReferencedDeclStack.back().push_back(std::make_pair(Loc, D)); return; } - + // Note that this declaration has been used. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { unsigned TypeQuals; if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) { if (!Constructor->isUsed()) DefineImplicitDefaultConstructor(Loc, Constructor); - } - else if (Constructor->isImplicit() && - Constructor->isCopyConstructor(Context, TypeQuals)) { + } else if (Constructor->isImplicit() && + Constructor->isCopyConstructor(Context, TypeQuals)) { if (!Constructor->isUsed()) DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals); } } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { if (Destructor->isImplicit() && !Destructor->isUsed()) DefineImplicitDestructor(Loc, Destructor); - + } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) { if (MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() && MethodDecl->getOverloadedOperator() == OO_Equal) { @@ -5698,28 +6207,125 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { } } if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { - // Implicit instantiation of function templates and member functions of + // Implicit instantiation of function templates and member functions of // class templates. - if (!Function->getBody()) { - // FIXME: distinguish between implicit instantiations of function - // templates and explicit specializations (the latter don't get - // instantiated, naturally). - if (Function->getInstantiatedFromMemberFunction() || - Function->getPrimaryTemplate()) + if (!Function->getBody() && + Function->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) { + bool AlreadyInstantiated = false; + if (FunctionTemplateSpecializationInfo *SpecInfo + = Function->getTemplateSpecializationInfo()) { + if (SpecInfo->getPointOfInstantiation().isInvalid()) + SpecInfo->setPointOfInstantiation(Loc); + else + AlreadyInstantiated = true; + } else if (MemberSpecializationInfo *MSInfo + = Function->getMemberSpecializationInfo()) { + if (MSInfo->getPointOfInstantiation().isInvalid()) + MSInfo->setPointOfInstantiation(Loc); + else + AlreadyInstantiated = true; + } + + if (!AlreadyInstantiated) PendingImplicitInstantiations.push_back(std::make_pair(Function, Loc)); } - // FIXME: keep track of references to static functions Function->setUsed(true); return; } - + if (VarDecl *Var = dyn_cast<VarDecl>(D)) { - (void)Var; - // FIXME: implicit template instantiation + // Implicit instantiation of static data members of class templates. + if (Var->isStaticDataMember() && + Var->getInstantiatedFromStaticDataMember()) { + MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); + assert(MSInfo && "Missing member specialization information?"); + if (MSInfo->getPointOfInstantiation().isInvalid() && + MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) { + MSInfo->setPointOfInstantiation(Loc); + PendingImplicitInstantiations.push_back(std::make_pair(Var, Loc)); + } + } + // FIXME: keep track of references to static data? + D->setUsed(true); + return; + } +} + +bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, + CallExpr *CE, FunctionDecl *FD) { + if (ReturnType->isVoidType() || !ReturnType->isIncompleteType()) + return false; + + PartialDiagnostic Note = + FD ? PDiag(diag::note_function_with_incomplete_return_type_declared_here) + << FD->getDeclName() : PDiag(); + SourceLocation NoteLoc = FD ? FD->getLocation() : SourceLocation(); + + if (RequireCompleteType(Loc, ReturnType, + FD ? + PDiag(diag::err_call_function_incomplete_return) + << CE->getSourceRange() << FD->getDeclName() : + PDiag(diag::err_call_incomplete_return) + << CE->getSourceRange(), + std::make_pair(NoteLoc, Note))) + return true; + + return false; +} + +// Diagnose the common s/=/==/ typo. Note that adding parentheses +// will prevent this condition from triggering, which is what we want. +void Sema::DiagnoseAssignmentAsCondition(Expr *E) { + SourceLocation Loc; + + if (isa<BinaryOperator>(E)) { + BinaryOperator *Op = cast<BinaryOperator>(E); + if (Op->getOpcode() != BinaryOperator::Assign) + return; + + Loc = Op->getOperatorLoc(); + } else if (isa<CXXOperatorCallExpr>(E)) { + CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(E); + if (Op->getOperator() != OO_Equal) + return; + + Loc = Op->getOperatorLoc(); + } else { + // Not an assignment. + return; } + + SourceLocation Open = E->getSourceRange().getBegin(); + SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd()); + + Diag(Loc, diag::warn_condition_is_assignment) + << E->getSourceRange() + << CodeModificationHint::CreateInsertion(Open, "(") + << CodeModificationHint::CreateInsertion(Close, ")"); } +bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) { + DiagnoseAssignmentAsCondition(E); + + if (!E->isTypeDependent()) { + DefaultFunctionArrayConversion(E); + + QualType T = E->getType(); + + if (getLangOptions().CPlusPlus) { + if (CheckCXXBooleanCondition(E)) // C++ 6.4p4 + return true; + } else if (!T->isScalarType()) { // C99 6.8.4.1p1 + Diag(Loc, diag::err_typecheck_statement_requires_scalar) + << T << E->getSourceRange(); + return true; + } + } + + return false; +} |