diff options
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 575 |
1 files changed, 334 insertions, 241 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 383edec..a5e5083 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -39,7 +39,7 @@ using namespace clang; /// referenced), false otherwise. bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { // See if the decl is deprecated. - if (D->getAttr<DeprecatedAttr>(Context)) { + if (D->getAttr<DeprecatedAttr>()) { // Implementing deprecated stuff requires referencing deprecated // stuff. Don't warn if we are implementing a deprecated // construct. @@ -48,7 +48,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { if (NamedDecl *ND = getCurFunctionOrMethodDecl()) { // If this reference happens *in* a deprecated function or method, don't // warn. - isSilenced = ND->getAttr<DeprecatedAttr>(Context); + 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. @@ -58,10 +58,9 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(MD->getParent())) { - MD = Impl->getClassInterface()->getMethod(Context, - MD->getSelector(), + MD = Impl->getClassInterface()->getMethod(MD->getSelector(), MD->isInstanceMethod()); - isSilenced |= MD && MD->getAttr<DeprecatedAttr>(Context); + isSilenced |= MD && MD->getAttr<DeprecatedAttr>(); } } } @@ -80,7 +79,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { } // See if the decl is unavailable - if (D->getAttr<UnavailableAttr>(Context)) { + if (D->getAttr<UnavailableAttr>()) { Diag(Loc, diag::warn_unavailable) << D->getDeclName(); Diag(D->getLocation(), diag::note_unavailable_here) << 0; } @@ -95,7 +94,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, Expr **Args, unsigned NumArgs) { - const SentinelAttr *attr = D->getAttr<SentinelAttr>(Context); + const SentinelAttr *attr = D->getAttr<SentinelAttr>(); if (!attr) return; int sentinelPos = attr->getSentinel(); @@ -673,8 +672,8 @@ static Decl *getObjectForAnonymousRecordDecl(ASTContext &Context, // 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(Context), - DEnd = Ctx->decls_end(Context); + for (DeclContext::decl_iterator D = Ctx->decls_begin(), + DEnd = Ctx->decls_end(); D != DEnd; ++D) { if (*D == Record) { // The object for the anonymous struct/union directly @@ -877,8 +876,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, if (D == 0 || D->isDefinedOutsideFunctionOrMethod()) { ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(Context, II, - ClassDeclared)) { + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { // Check if referencing a field with __attribute__((deprecated)). if (DiagnoseUseOfDecl(IV, Loc)) return ExprError(); @@ -915,8 +913,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // We should warn if a local variable hides an ivar. ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(Context, II, - ClassDeclared)) { + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { if (IV->getAccessControl() != ObjCIvarDecl::Private || IFace == ClassDeclared) Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); @@ -973,7 +970,64 @@ 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() && + CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) { + if (Var->getType()->isBooleanType()) + ExprError(Diag(Loc, diag::warn_value_always_false) + << Var->getDeclName()); + else + ExprError(Diag(Loc, diag::warn_value_always_zero) + << Var->getDeclName()); + break; + } + + // Move up one more control parent to check again. + CheckS = CheckS->getControlParent(); + if (CheckS) + CheckS = CheckS->getParent(); + } + } + } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) { + if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) { + // C99 DR 316 says that, if a function type comes from a + // function definition (without a prototype), that type is only + // used for checking compatibility. Therefore, when referencing + // the function, we pretend that we don't have the full function + // type. + if (DiagnoseUseOfDecl(Func, Loc)) + return ExprError(); + + QualType T = Func->getType(); + QualType NoProtoType = T; + if (const FunctionProtoType *Proto = T->getAsFunctionProtoType()) + NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType()); + return BuildDeclRefExpr(Func, NoProtoType, Loc, false, false, SS); + } + } + + return BuildDeclarationNameExpr(Loc, D, HasTrailingLParen, SS, isAddressOfOperand); +} +/// \brief Complete semantic analysis for a reference to the given declaration. +Sema::OwningExprResult +Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, + bool HasTrailingLParen, + 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. @@ -1097,51 +1151,11 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // 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()) && + HasTrailingLParen; if (!(ADL && isa<FunctionDecl>(VD)) && DiagnoseUseOfDecl(VD, Loc)) return ExprError(); - if (VarDecl *Var = dyn_cast<VarDecl>(VD)) { - // 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() && - CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) { - if (Var->getType()->isBooleanType()) - ExprError(Diag(Loc, diag::warn_value_always_false) - << Var->getDeclName()); - else - ExprError(Diag(Loc, diag::warn_value_always_zero) - << Var->getDeclName()); - break; - } - - // Move up one more control parent to check again. - CheckS = CheckS->getControlParent(); - if (CheckS) - CheckS = CheckS->getParent(); - } - } - } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(VD)) { - if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) { - // C99 DR 316 says that, if a function type comes from a - // function definition (without a prototype), that type is only - // used for checking compatibility. Therefore, when referencing - // the function, we pretend that we don't have the full function - // type. - QualType T = Func->getType(); - QualType NoProtoType = T; - if (const FunctionProtoType *Proto = T->getAsFunctionProtoType()) - NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType()); - return BuildDeclRefExpr(VD, NoProtoType, Loc, false, false, SS); - } - } - // Only create DeclRefExpr's for valid Decl's. if (VD->isInvalidDecl()) return ExprError(); @@ -1158,7 +1172,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, MarkDeclarationReferenced(Loc, VD); QualType ExprTy = VD->getType().getNonReferenceType(); // The BlocksAttr indicates the variable is bound by-reference. - if (VD->getAttr<BlocksAttr>(Context)) + if (VD->getAttr<BlocksAttr>()) return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, true)); // This is to record that a 'const' was actually synthesize and added. bool constAdded = !ExprTy.isConstQualified(); @@ -1310,8 +1324,8 @@ Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) { // isExact will be set by GetFloatValue(). bool isExact = false; - Res = new (Context) FloatingLiteral(Literal.GetFloatValue(Format, &isExact), - &isExact, Ty, Tok.getLocation()); + llvm::APFloat Val = Literal.GetFloatValue(Format, &isExact); + Res = new (Context) FloatingLiteral(Val, isExact, Ty, Tok.getLocation()); } else if (!Literal.isIntegerLiteral()) { return ExprError(); @@ -1989,9 +2003,9 @@ static Decl *FindGetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl, const Selector &Sel, ASTContext &Context) { - if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Context, &Member)) + if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(&Member)) return PD; - if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Context, Sel)) + if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel)) return OMD; for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(), @@ -2011,12 +2025,12 @@ static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy, Decl *GDecl = 0; for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), E = QIdTy->qual_end(); I != E; ++I) { - if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Context, &Member)) { + if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member)) { GDecl = PD; break; } // Also must look for a getter name which uses property syntax. - if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Context, Sel)) { + if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) { GDecl = OMD; break; } @@ -2042,7 +2056,7 @@ ObjCMethodDecl *Sema::FindMethodInNestedImplementations( ObjCMethodDecl *Method = 0; if (ObjCImplementationDecl *ImpDecl = LookupObjCImplementation(IFace->getIdentifier())) - Method = ImpDecl->getInstanceMethod(Context, Sel); + Method = ImpDecl->getInstanceMethod(Sel); if (!Method && IFace->getSuperClass()) return FindMethodInNestedImplementations(IFace->getSuperClass(), Sel); @@ -2201,8 +2215,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // (*Obj).ivar. if (const ObjCInterfaceType *IFTy = BaseType->getAsObjCInterfaceType()) { ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFTy->getDecl()->lookupInstanceVariable(Context, - &Member, + 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 @@ -2262,14 +2275,13 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, ObjCInterfaceDecl *IFace = IFTy->getDecl(); // Search for a declared property first. - if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Context, - &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); - ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Context, Sel); + ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)) ResTy = Getter->getResultType(); return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, @@ -2279,8 +2291,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // 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(Context, - &Member)) { + if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); @@ -2296,7 +2307,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // shared with the code in ActOnInstanceMessage. Selector Sel = PP.getSelectorTable().getNullarySelector(&Member); - ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Context, Sel); + ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); // If this reference is in an @implementation, check for 'private' methods. if (!Getter) @@ -2306,7 +2317,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, if (!Getter) { for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Getter; i++) { if (ObjCCategoryImpls[i]->getClassInterface() == IFace) - Getter = ObjCCategoryImpls[i]->getInstanceMethod(Context, Sel); + Getter = ObjCCategoryImpls[i]->getInstanceMethod(Sel); } } if (Getter) { @@ -2319,7 +2330,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, Selector SetterSel = SelectorTable::constructSetterName(PP.getIdentifierTable(), PP.getSelectorTable(), &Member); - ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(Context, SetterSel); + ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); if (!Setter) { // If this reference is in an @implementation, also check for 'private' // methods. @@ -2329,7 +2340,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, if (!Setter) { for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Setter; i++) { if (ObjCCategoryImpls[i]->getClassInterface() == IFace) - Setter = ObjCCategoryImpls[i]->getInstanceMethod(Context, SetterSel); + Setter = ObjCCategoryImpls[i]->getInstanceMethod(SetterSel); } } @@ -2390,7 +2401,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, ObjCInterfaceDecl *IFace = MD->getClassInterface(); ObjCMethodDecl *Getter; // FIXME: need to also look locally in the implementation. - if ((Getter = IFace->lookupClassMethod(Context, Sel))) { + if ((Getter = IFace->lookupClassMethod(Sel))) { // Check the use of this method. if (DiagnoseUseOfDecl(Getter, MemberLoc)) return ExprError(); @@ -2400,7 +2411,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, Selector SetterSel = SelectorTable::constructSetterName(PP.getIdentifierTable(), PP.getSelectorTable(), &Member); - ObjCMethodDecl *Setter = IFace->lookupClassMethod(Context, SetterSel); + ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); if (!Setter) { // If this reference is in an @implementation, also check for 'private' // methods. @@ -2410,7 +2421,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, if (!Setter) { for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Setter; i++) { if (ObjCCategoryImpls[i]->getClassInterface() == IFace) - Setter = ObjCCategoryImpls[i]->getClassMethod(Context, SetterSel); + Setter = ObjCCategoryImpls[i]->getClassMethod(SetterSel); } } @@ -2624,9 +2635,13 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, } // If we're directly calling a function, get the appropriate declaration. - DeclRefExpr *DRExpr = NULL; + // 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(); @@ -2639,14 +2654,41 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, cast<UnaryOperator>(FnExpr)->getOpcode() == UnaryOperator::AddrOf) { FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr(); - } else if ((DRExpr = dyn_cast<DeclRefExpr>(FnExpr))) { + } 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). @@ -2657,14 +2699,13 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, OverloadedFunctionDecl *Ovl = 0; FunctionTemplateDecl *FunctionTemplate = 0; - if (DRExpr) { - FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()); - if ((FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DRExpr->getDecl()))) + if (NDecl) { + FDecl = dyn_cast<FunctionDecl>(NDecl); + if ((FunctionTemplate = dyn_cast<FunctionTemplateDecl>(NDecl))) FDecl = FunctionTemplate->getTemplatedDecl(); else - FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()); - Ovl = dyn_cast<OverloadedFunctionDecl>(DRExpr->getDecl()); - NDecl = dyn_cast<NamedDecl>(DRExpr->getDecl()); + FDecl = dyn_cast<FunctionDecl>(NDecl); + Ovl = dyn_cast<OverloadedFunctionDecl>(NDecl); } if (Ovl || FunctionTemplate || @@ -2678,16 +2719,19 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, ADL = false; if (Ovl || FunctionTemplate || ADL) { - FDecl = ResolveOverloadedCallFn(Fn, DRExpr? DRExpr->getDecl() : 0, - UnqualifiedName, LParenLoc, Args, - NumArgs, CommaLocs, RParenLoc, ADL); + FDecl = ResolveOverloadedCallFn(Fn, NDecl, UnqualifiedName, + HasExplicitTemplateArgs, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + 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_or_null<QualifiedDeclRefExpr>(DRExpr)) + = dyn_cast<QualifiedDeclRefExpr>(FnExpr)) NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(), QDRExpr->getLocation(), false, false, @@ -2750,7 +2794,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // Check if we have too few/too many template arguments, based // on our knowledge of the function definition. const FunctionDecl *Def = 0; - if (FDecl->getBody(Context, Def) && NumArgs != Def->param_size()) { + if (FDecl->getBody(Def) && NumArgs != Def->param_size()) { const FunctionProtoType *Proto = Def->getType()->getAsFunctionProtoType(); if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) { @@ -2860,7 +2904,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr) { // GCC cast to union extension RecordDecl *RD = castType->getAsRecordType()->getDecl(); RecordDecl::field_iterator Field, FieldEnd; - for (Field = RD->field_begin(Context), FieldEnd = RD->field_end(Context); + for (Field = RD->field_begin(), FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { if (Context.getCanonicalType(Field->getType()).getUnqualifiedType() == Context.getCanonicalType(castExpr->getType()).getUnqualifiedType()) { @@ -2931,19 +2975,8 @@ 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 also an ExtVectorType, the types must be identical unless - // lax vector conversions is enabled. - if (SrcTy->isExtVectorType()) { - if (getLangOptions().LaxVectorConversions && - Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy)) - return false; - if (DestTy != SrcTy) - return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) - << DestTy << SrcTy << R; - return false; - } - - // If SrcTy is a VectorType, then only the total size must match. + // If SrcTy is a VectorType, the total size must match to explicitly cast to + // an ExtVectorType. if (SrcTy->isVectorType()) { if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)) return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) @@ -2951,9 +2984,13 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) { return false; } - // All scalar -> ext vector "c-style" casts are legal; the appropriate + // All non-pointer scalars can be cast to ExtVector type. The appropriate // conversion will take place first from scalar to elt type, and then // splat from elt type to vector. + if (SrcTy->isPointerType()) + return Diag(R.getBegin(), + diag::err_invalid_conversion_between_vector_and_scalar) + << DestTy << SrcTy << R; return false; } @@ -3042,24 +3079,133 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, ImpCastExprToType(LHS, RHSTy); // promote the null to a pointer. 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(RHS, destType); + return destType; + } + Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + return QualType(); + } + // We have 2 block pointer types. + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { + // Two identical block pointer types are always compatible. + return LHSTy; + } + // The block pointer types aren't identical, continue checking. + QualType lhptee = LHSTy->getAsBlockPointerType()->getPointeeType(); + QualType rhptee = RHSTy->getAsBlockPointerType()->getPointeeType(); - const PointerType *LHSPT = LHSTy->getAsPointerType(); - const PointerType *RHSPT = RHSTy->getAsPointerType(); - const BlockPointerType *LHSBPT = LHSTy->getAsBlockPointerType(); - const BlockPointerType *RHSBPT = RHSTy->getAsBlockPointerType(); + if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), + rhptee.getUnqualifiedType())) { + Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers) + << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + // In this situation, we assume void* type. No especially good + // reason, but this is what gcc does, and we do have to pick + // to get a consistent AST. + QualType incompatTy = Context.getPointerType(Context.VoidTy); + ImpCastExprToType(LHS, incompatTy); + ImpCastExprToType(RHS, incompatTy); + return incompatTy; + } + // The block pointer types are compatible. + ImpCastExprToType(LHS, LHSTy); + 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. - // Handle the case where both operands are pointers before we handle null - // pointer constants in case both operands are null pointer constants. - if ((LHSPT || LHSBPT) && (RHSPT || RHSBPT)) { // C99 6.5.15p3,6 + // 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 (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(); + + 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 + // xxx ? (A*) a : (B*) b + // where B is a subclass of A. + // + // Additionally, as for assignment, if either type is 'id' + // allow silent coercion. Finally, if the types are + // incompatible then make sure to use 'id' as the composite + // type so the result is acceptable for sending messages to. + + // 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)) { + compositeType = Context.getObjCIdType(); + } else { + Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy + << LHS->getSourceRange() << RHS->getSourceRange(); + QualType incompatTy = Context.getObjCIdType(); + ImpCastExprToType(LHS, incompatTy); + ImpCastExprToType(RHS, incompatTy); + return incompatTy; + } + // The object pointer types are compatible. + ImpCastExprToType(LHS, compositeType); + ImpCastExprToType(RHS, compositeType); + return compositeType; + } + // Check constraints for C object pointers types (C99 6.5.15p3,6). + if (LHSTy->isPointerType() && RHSTy->isPointerType()) { // get the "pointed to" types - QualType lhptee = (LHSPT ? LHSPT->getPointeeType() - : LHSBPT->getPointeeType()); - QualType rhptee = (RHSPT ? RHSPT->getPointeeType() - : RHSBPT->getPointeeType()); + QualType lhptee = LHSTy->getAsPointerType()->getPointeeType(); + QualType rhptee = RHSTy->getAsPointerType()->getPointeeType(); // ignore qualifiers on void (C99 6.5.15p3, clause 6) - if (lhptee->isVoidType() - && (RHSBPT || rhptee->isIncompleteOrObjectType())) { + if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) { // Figure out necessary qualifiers (C99 6.5.15p6) QualType destPointee=lhptee.getQualifiedType(rhptee.getCVRQualifiers()); QualType destType = Context.getPointerType(destPointee); @@ -3067,8 +3213,7 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, ImpCastExprToType(RHS, destType); // promote to void* return destType; } - if (rhptee->isVoidType() - && (LHSBPT || lhptee->isIncompleteOrObjectType())) { + if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) { QualType destPointee=rhptee.getQualifiedType(lhptee.getCVRQualifiers()); QualType destType = Context.getPointerType(destPointee); ImpCastExprToType(LHS, destType); // add qualifiers if necessary @@ -3076,62 +3221,12 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, return destType; } - bool sameKind = (LHSPT && RHSPT) || (LHSBPT && RHSBPT); - if (sameKind - && Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { // Two identical pointer types are always compatible. return LHSTy; } - - QualType compositeType = LHSTy; - - // If either type is an Objective-C object type then check - // compatibility according to Objective-C. - if (Context.isObjCObjectPointerType(LHSTy) || - Context.isObjCObjectPointerType(RHSTy)) { - // If both operands are interfaces and either operand can be - // assigned to the other, use that type as the composite - // type. This allows - // xxx ? (A*) a : (B*) b - // where B is a subclass of A. - // - // Additionally, as for assignment, if either type is 'id' - // allow silent coercion. Finally, if the types are - // incompatible then make sure to use 'id' as the composite - // type so the result is acceptable for sending messages to. - - // 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)) { - compositeType = Context.getObjCIdType(); - } else if (LHSBPT || RHSBPT) { - if (!sameKind - || !Context.typesAreCompatible(lhptee.getUnqualifiedType(), - rhptee.getUnqualifiedType())) - Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); - return QualType(); - } else { - Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) - << LHSTy << RHSTy - << LHS->getSourceRange() << RHS->getSourceRange(); - QualType incompatTy = Context.getObjCIdType(); - ImpCastExprToType(LHS, incompatTy); - ImpCastExprToType(RHS, incompatTy); - return incompatTy; - } - } else if (!sameKind - || !Context.typesAreCompatible(lhptee.getUnqualifiedType(), - rhptee.getUnqualifiedType())) { + if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), + rhptee.getUnqualifiedType())) { Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers) << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); // In this situation, we assume void* type. No especially good @@ -3149,11 +3244,11 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // type. // FIXME: Need to calculate the composite type. // FIXME: Need to add qualifiers - ImpCastExprToType(LHS, compositeType); - ImpCastExprToType(RHS, compositeType); - return compositeType; + ImpCastExprToType(LHS, LHSTy); + 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) @@ -3168,32 +3263,6 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, 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; - } - } - // Otherwise, the operands are not compatible. Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); @@ -3385,12 +3454,16 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { return IncompatibleObjCQualifiedId; } + // Allow scalar to ExtVector assignments, and assignments of an ExtVector type + // to the same ExtVector type. + if (lhsType->isExtVectorType()) { + if (rhsType->isExtVectorType()) + return lhsType == rhsType ? Compatible : Incompatible; + if (!rhsType->isVectorType() && rhsType->isArithmeticType()) + return Compatible; + } + if (lhsType->isVectorType() || rhsType->isVectorType()) { - // For ExtVector, allow vector splats; float -> <n x float> - if (const ExtVectorType *LV = lhsType->getAsExtVectorType()) - if (LV->getElementType() == rhsType) - return Compatible; - // 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; // no bits are changed but the result type is different. @@ -3492,15 +3565,15 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { // 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>(Context)) + if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>()) return Incompatible; // The field to initialize within the transparent union. RecordDecl *UD = UT->getDecl(); FieldDecl *InitField = 0; // It's compatible if the expression matches any of the fields. - for (RecordDecl::field_iterator it = UD->field_begin(Context), - itend = UD->field_end(Context); + for (RecordDecl::field_iterator it = UD->field_begin(), + itend = UD->field_end(); it != itend; ++it) { if (it->getType()->isPointerType()) { // If the transparent union contains a pointer type, we allow: @@ -3617,33 +3690,36 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, } } - // If the lhs is an extended vector and the rhs is a scalar of the same type - // or a literal, promote the rhs to the vector type. - if (const ExtVectorType *V = lhsType->getAsExtVectorType()) { - QualType eltType = V->getElementType(); - - if ((eltType->getAsBuiltinType() == rhsType->getAsBuiltinType()) || - (eltType->isIntegerType() && isa<IntegerLiteral>(rex)) || - (eltType->isFloatingType() && isa<FloatingLiteral>(rex))) { - ImpCastExprToType(rex, lhsType); - return lhsType; - } + // Canonicalize the ExtVector to the LHS, remember if we swapped so we can + // swap back (so that we don't reverse the inputs to a subtract, for instance. + bool swapped = false; + if (rhsType->isExtVectorType()) { + swapped = true; + std::swap(rex, lex); + std::swap(rhsType, lhsType); } - - // If the rhs is an extended vector and the lhs is a scalar of the same type, - // promote the lhs to the vector type. - if (const ExtVectorType *V = rhsType->getAsExtVectorType()) { - QualType eltType = V->getElementType(); - - if ((eltType->getAsBuiltinType() == lhsType->getAsBuiltinType()) || - (eltType->isIntegerType() && isa<IntegerLiteral>(lex)) || - (eltType->isFloatingType() && isa<FloatingLiteral>(lex))) { - ImpCastExprToType(lex, rhsType); - return rhsType; + + // Handle the case of an ext vector and scalar. + if (const ExtVectorType *LV = lhsType->getAsExtVectorType()) { + QualType EltTy = LV->getElementType(); + if (EltTy->isIntegralType() && rhsType->isIntegralType()) { + if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) { + ImpCastExprToType(rex, lhsType); + if (swapped) std::swap(rex, lex); + return lhsType; + } + } + if (EltTy->isRealFloatingType() && rhsType->isScalarType() && + rhsType->isRealFloatingType()) { + if (Context.getFloatingTypeOrder(EltTy, rhsType) >= 0) { + ImpCastExprToType(rex, lhsType); + if (swapped) std::swap(rex, lex); + return lhsType; + } } } - - // You cannot convert between vector values of different size. + + // Vectors of different size or scalar and non-ext-vector are errors. Diag(Loc, diag::err_typecheck_vector_not_convertable) << lex->getType() << rex->getType() << lex->getSourceRange() << rex->getSourceRange(); @@ -4034,6 +4110,17 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, 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; @@ -4146,7 +4233,10 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, } if ((lType->isPointerType() || lType->isObjCQualifiedIdType()) && rType->isIntegerType()) { - if (!RHSIsNull) + 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) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); ImpCastExprToType(rex, lType); // promote the integer to pointer @@ -4154,7 +4244,10 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, } if (lType->isIntegerType() && (rType->isPointerType() || rType->isObjCQualifiedIdType())) { - if (!LHSIsNull) + 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) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); ImpCastExprToType(lex, rType); // promote the integer to pointer @@ -5226,7 +5319,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { CurBlock->hasPrototype = true; CurBlock->isVariadic = false; // Check for a valid sentinel attribute on this block. - if (CurBlock->TheDecl->getAttr<SentinelAttr>(Context)) { + if (CurBlock->TheDecl->getAttr<SentinelAttr>()) { Diag(ParamInfo.getAttributes()->getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; // FIXME: remove the attribute. @@ -5275,7 +5368,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { // Check for a valid sentinel attribute on this block. if (!CurBlock->isVariadic && - CurBlock->TheDecl->getAttr<SentinelAttr>(Context)) { + CurBlock->TheDecl->getAttr<SentinelAttr>()) { Diag(ParamInfo.getAttributes()->getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; // FIXME: remove the attribute. @@ -5607,13 +5700,13 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { // Implicit instantiation of function templates and member functions of // class templates. - if (!Function->getBody(Context)) { + 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()) - PendingImplicitInstantiations.push(std::make_pair(Function, Loc)); + PendingImplicitInstantiations.push_back(std::make_pair(Function, Loc)); } |