diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-05-27 15:17:06 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-05-27 15:17:06 +0000 |
commit | 53992adde3eda3ccf9da63bc7e45673f043de18f (patch) | |
tree | 3558f327a6f9ab59c5d7a06528d84e1560445247 /lib/Sema/SemaExpr.cpp | |
parent | 7e411337c0ed226dace6e07f1420486768161308 (diff) | |
download | FreeBSD-src-53992adde3eda3ccf9da63bc7e45673f043de18f.zip FreeBSD-src-53992adde3eda3ccf9da63bc7e45673f043de18f.tar.gz |
Update clang to r104832.
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 258 |
1 files changed, 156 insertions, 102 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 869d6df..f745352 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -22,6 +22,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" @@ -160,16 +161,19 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, ++sentinel; } Expr *sentinelExpr = Args[sentinel]; - if (sentinelExpr && (!isa<GNUNullExpr>(sentinelExpr) && - !sentinelExpr->isTypeDependent() && - !sentinelExpr->isValueDependent() && - (!sentinelExpr->getType()->isPointerType() || - !sentinelExpr->isNullPointerConstant(Context, - Expr::NPC_ValueDependentIsNull)))) { - Diag(Loc, diag::warn_missing_sentinel) << isMethod; - Diag(D->getLocation(), diag::note_sentinel_here) << isMethod; - } - return; + if (!sentinelExpr) return; + if (sentinelExpr->isTypeDependent()) return; + if (sentinelExpr->isValueDependent()) return; + if (sentinelExpr->getType()->isPointerType() && + sentinelExpr->IgnoreParenCasts()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) + return; + + // Unfortunately, __null has type 'int'. + if (isa<GNUNullExpr>(sentinelExpr)) return; + + Diag(Loc, diag::warn_missing_sentinel) << isMethod; + Diag(D->getLocation(), diag::note_sentinel_here) << isMethod; } SourceRange Sema::getExprRange(ExprTy *E) const { @@ -275,10 +279,9 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) { assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type"); // If this is a 'float' (CVR qualified or typedef) promote to double. - if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) - if (BT->getKind() == BuiltinType::Float) - return ImpCastExprToType(Expr, Context.DoubleTy, - CastExpr::CK_FloatingCast); + if (Ty->isSpecificBuiltinType(BuiltinType::Float)) + return ImpCastExprToType(Expr, Context.DoubleTy, + CastExpr::CK_FloatingCast); UsualUnaryConversions(Expr); } @@ -287,10 +290,17 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) { /// will warn if the resulting type is not a POD type, and rejects ObjC /// interfaces passed by value. This returns true if the argument type is /// completely illegal. -bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) { +bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT, + FunctionDecl *FDecl) { DefaultArgumentPromotion(Expr); - if (Expr->getType()->isObjCInterfaceType() && + // __builtin_va_start takes the second argument as a "varargs" argument, but + // it doesn't actually do anything with it. It doesn't need to be non-pod + // etc. + if (FDecl && FDecl->getBuiltinID() == Builtin::BI__builtin_va_start) + return false; + + if (Expr->getType()->isObjCObjectType() && DiagRuntimeBehavior(Expr->getLocStart(), PDiag(diag::err_cannot_pass_objc_interface_to_vararg) << Expr->getType() << CT)) @@ -486,35 +496,6 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc, D, Loc, Ty)); } -/// getObjectForAnonymousRecordDecl - Retrieve the (unnamed) field or -/// variable corresponding to the anonymous union or struct whose type -/// is Record. -static Decl *getObjectForAnonymousRecordDecl(ASTContext &Context, - RecordDecl *Record) { - 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(), - DEnd = Ctx->decls_end(); - D != DEnd; ++D) { - if (*D == Record) { - // The object for the anonymous struct/union directly - // follows its type in the list of declarations. - ++D; - assert(D != DEnd && "Missing object for anonymous record"); - assert(!cast<NamedDecl>(*D)->getDeclName() && "Decl should be unnamed"); - return *D; - } - } - - assert(false && "Missing object for anonymous record"); - return 0; -} - /// \brief Given a field that represents a member of an anonymous /// struct/union, build the path from that field's context to the /// actual member. @@ -539,7 +520,7 @@ VarDecl *Sema::BuildAnonymousStructUnionMemberPath(FieldDecl *Field, DeclContext *Ctx = Field->getDeclContext(); do { RecordDecl *Record = cast<RecordDecl>(Ctx); - Decl *AnonObject = getObjectForAnonymousRecordDecl(Context, Record); + ValueDecl *AnonObject = Record->getAnonymousStructOrUnionObject(); if (FieldDecl *AnonField = dyn_cast<FieldDecl>(AnonObject)) Path.push_back(AnonField); else { @@ -592,7 +573,8 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, // 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)) { + DeclContext *DC = getFunctionLevelDeclContext(); + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) { if (!MD->isStatic()) { QualType AnonFieldType = Context.getTagDeclType( @@ -828,9 +810,10 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, const LookupResult &R) { assert(!R.empty() && (*R.begin())->isCXXClassMember()); + DeclContext *DC = SemaRef.getFunctionLevelDeclContext(); bool isStaticContext = - (!isa<CXXMethodDecl>(SemaRef.CurContext) || - cast<CXXMethodDecl>(SemaRef.CurContext)->isStatic()); + (!isa<CXXMethodDecl>(DC) || + cast<CXXMethodDecl>(DC)->isStatic()); if (R.isUnresolvableResult()) return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved; @@ -870,7 +853,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, // declaring classes, it can't be an implicit member reference (in // which case it's an error if any of those members are selected). if (IsProvablyNotDerivedFrom(SemaRef, - cast<CXXMethodDecl>(SemaRef.CurContext)->getParent(), + cast<CXXMethodDecl>(DC)->getParent(), Classes)) return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); @@ -907,7 +890,7 @@ static void DiagnoseInstanceReference(Sema &SemaRef, /// /// \return false if new lookup candidates were found bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, - LookupResult &R) { + LookupResult &R, CorrectTypoContext CTC) { DeclarationName Name = R.getLookupName(); unsigned diagnostic = diag::err_undeclared_var_use; @@ -958,7 +941,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, // We didn't find anything, so try to correct for a typo. DeclarationName Corrected; - if (S && (Corrected = CorrectTypo(R, S, &SS))) { + if (S && (Corrected = CorrectTypo(R, S, &SS, false, CTC))) { if (!R.empty()) { if (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin())) { if (SS.isEmpty()) @@ -1067,17 +1050,14 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, // Perform the required lookup. LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); if (TemplateArgs) { - // Just re-use the lookup done by isTemplateName. - DecomposeTemplateName(R, Id); - - // Re-derive the naming class. - if (SS.isSet()) { - NestedNameSpecifier *Qualifier - = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - if (const Type *Ty = Qualifier->getAsType()) - if (CXXRecordDecl *NamingClass = Ty->getAsCXXRecordDecl()) - R.setNamingClass(NamingClass); - } + // Lookup the template name again to correctly establish the context in + // which it was found. This is really unfortunate as we already did the + // lookup to determine that it was a template name in the first place. If + // this becomes a performance hit, we can work harder to preserve those + // results until we get here but it's likely not worth it. + bool MemberOfUnknownSpecialization; + LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false, + MemberOfUnknownSpecialization); } else { bool IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl()); LookupParsedName(R, S, &SS, !IvarLookupFollowUp); @@ -1112,7 +1092,7 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, // If this name wasn't predeclared and if this is not a function // call, diagnose the problem. if (R.empty()) { - if (DiagnoseEmptyLookup(S, SS, R)) + if (DiagnoseEmptyLookup(S, SS, R, CTC_Unknown)) return ExprError(); assert(!R.empty() && @@ -1166,7 +1146,8 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, QualType T = Func->getType(); QualType NoProtoType = T; if (const FunctionProtoType *Proto = T->getAs<FunctionProtoType>()) - NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType()); + NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType(), + Proto->getExtInfo()); return BuildDeclRefExpr(Func, NoProtoType, NameLoc, &SS); } } @@ -1423,6 +1404,9 @@ Sema::PerformObjectMemberConversion(Expr *&From, SourceRange FromRange = From->getSourceRange(); SourceLocation FromLoc = FromRange.getBegin(); + bool isLvalue + = (From->isLvalue(Context) == Expr::LV_Valid) && !PointerConversions; + // C++ [class.member.lookup]p8: // [...] Ambiguities can often be resolved by qualifying a name with its // class name. @@ -1460,7 +1444,7 @@ Sema::PerformObjectMemberConversion(Expr *&From, if (PointerConversions) QType = Context.getPointerType(QType); ImpCastExprToType(From, QType, CastExpr::CK_UncheckedDerivedToBase, - /*isLvalue=*/!PointerConversions, BasePath); + isLvalue, BasePath); FromType = QType; FromRecordType = QRecordType; @@ -1497,7 +1481,7 @@ Sema::PerformObjectMemberConversion(Expr *&From, if (PointerConversions) UType = Context.getPointerType(UType); ImpCastExprToType(From, UType, CastExpr::CK_UncheckedDerivedToBase, - /*isLvalue=*/!PointerConversions, BasePath); + isLvalue, BasePath); FromType = UType; FromRecordType = URecordType; } @@ -1514,7 +1498,7 @@ Sema::PerformObjectMemberConversion(Expr *&From, return true; ImpCastExprToType(From, DestType, CastExpr::CK_UncheckedDerivedToBase, - /*isLvalue=*/!PointerConversions, BasePath); + isLvalue, BasePath); return false; } @@ -1558,7 +1542,8 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, // If this is known to be an instance access, go ahead and build a // 'this' expression now. - QualType ThisType = cast<CXXMethodDecl>(CurContext)->getThisType(Context); + DeclContext *DC = getFunctionLevelDeclContext(); + QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType(Context); Expr *This = 0; // null signifies implicit access if (IsKnownInstance) { SourceLocation Loc = R.getNameLoc(); @@ -1682,8 +1667,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, (NestedNameSpecifier*) SS.getScopeRep(), SS.getRange(), R.getLookupName(), R.getNameLoc(), - NeedsADL, R.isOverloadedResult()); - ULE->addDecls(R.begin(), R.end()); + NeedsADL, R.isOverloadedResult(), + R.begin(), R.end()); return Owned(ULE); } @@ -2036,12 +2021,18 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType, return true; // Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode. - if (LangOpts.ObjCNonFragileABI && exprType->isObjCInterfaceType()) { + if (LangOpts.ObjCNonFragileABI && exprType->isObjCObjectType()) { Diag(OpLoc, diag::err_sizeof_nonfragile_interface) << exprType << isSizeof << ExprRange; return true; } + if (Context.hasSameUnqualifiedType(exprType, Context.OverloadTy)) { + Diag(OpLoc, diag::err_sizeof_alignof_overloaded_function_type) + << !isSizeof << ExprRange; + return true; + } + return false; } @@ -2312,7 +2303,7 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc, return ExprError(); // Diagnose bad cases where we step over interface counts. - if (ResultType->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { + if (ResultType->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { Diag(LLoc, diag::err_subscript_nonfragile_interface) << ResultType << BaseExpr->getSourceRange(); return ExprError(); @@ -2665,6 +2656,9 @@ Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType, if (Result.get()) return move(Result); + + // LookupMemberExpr can modify Base, and thus change BaseType + BaseType = Base->getType(); } return BuildMemberReferenceExpr(ExprArg(*this, Base), BaseType, @@ -2741,8 +2735,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, IsArrow, OpLoc, Qualifier, SS.getRange(), MemberName, MemberLoc, - TemplateArgs); - MemExpr->addDecls(R.begin(), R.end()); + TemplateArgs, R.begin(), R.end()); return Owned(MemExpr); } @@ -2917,7 +2910,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // Handle the following exceptional case PObj->isa. if (const ObjCObjectPointerType *OPT = BaseType->getAs<ObjCObjectPointerType>()) { - if (OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && + if (OPT->getObjectType()->isObjCId() && MemberName.getAsIdentifierInfo()->isStr("isa")) return Owned(new (Context) ObjCIsaExpr(BaseExpr, true, MemberLoc, Context.getObjCClassType())); @@ -3041,8 +3034,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, } } - // Handle field access to simple records. This also handles access - // to fields of the ObjC 'id' struct. + // Handle field access to simple records. if (const RecordType *RTy = BaseType->getAs<RecordType>()) { if (LookupMemberExprInRecord(*this, R, BaseExpr->getSourceRange(), RTy, OpLoc, SS)) @@ -3053,14 +3045,14 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // Handle access to Objective-C instance variables, such as "Obj->ivar" and // (*Obj).ivar. if ((IsArrow && BaseType->isObjCObjectPointerType()) || - (!IsArrow && BaseType->isObjCInterfaceType())) { + (!IsArrow && BaseType->isObjCObjectType())) { const ObjCObjectPointerType *OPT = BaseType->getAs<ObjCObjectPointerType>(); - const ObjCInterfaceType *IFaceT = - OPT ? OPT->getInterfaceType() : BaseType->getAs<ObjCInterfaceType>(); - if (IFaceT) { + ObjCInterfaceDecl *IDecl = + OPT ? OPT->getInterfaceDecl() + : BaseType->getAs<ObjCObjectType>()->getInterface(); + if (IDecl) { IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); - ObjCInterfaceDecl *IDecl = IFaceT->getDecl(); ObjCInterfaceDecl *ClassDeclared; ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); @@ -3173,7 +3165,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // Handle the following exceptional case (*Obj).isa. if (!IsArrow && - BaseType->isSpecificBuiltinType(BuiltinType::ObjCId) && + BaseType->isObjCObjectType() && + BaseType->getAs<ObjCObjectType>()->isObjCId() && MemberName.getAsIdentifierInfo()->isStr("isa")) return Owned(new (Context) ObjCIsaExpr(BaseExpr, false, MemberLoc, Context.getObjCClassType())); @@ -3471,9 +3464,9 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, // If this is a variadic call, handle args passed through "...". if (CallType != VariadicDoesNotApply) { // Promote the arguments (C99 6.5.2.2p7). - for (unsigned i = ArgIx; i < NumArgs; i++) { + for (unsigned i = ArgIx; i != NumArgs; ++i) { Expr *Arg = Args[i]; - Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType); + Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType, FDecl); AllArgs.push_back(Arg); } } @@ -4081,8 +4074,6 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (getLangOptions().CPlusPlus) return CXXCheckConditionalOperands(Cond, LHS, RHS, QuestionLoc); - CheckSignCompare(LHS, RHS, QuestionLoc); - UsualUnaryConversions(Cond); UsualUnaryConversions(LHS); UsualUnaryConversions(RHS); @@ -4659,7 +4650,8 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { return Incompatible; } - if (lhsType->isArithmeticType() && rhsType->isArithmeticType()) + if (lhsType->isArithmeticType() && rhsType->isArithmeticType() && + !(getLangOptions().CPlusPlus && lhsType->isEnumeralType())) return Compatible; if (isa<PointerType>(lhsType)) { @@ -4917,7 +4909,13 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { if (const VectorType *RV = rhsType->getAs<VectorType>()) if (LV->getElementType() == RV->getElementType() && LV->getNumElements() == RV->getNumElements()) { - return lhsType->isExtVectorType() ? lhsType : rhsType; + if (lhsType->isExtVectorType()) { + ImpCastExprToType(rex, lhsType, CastExpr::CK_BitCast); + return lhsType; + } + + ImpCastExprToType(lex, rhsType, CastExpr::CK_BitCast); + return rhsType; } } } @@ -5059,7 +5057,7 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 return QualType(); } // Diagnose bad cases where we step over interface counts. - if (PointeeTy->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { + if (PointeeTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { Diag(Loc, diag::err_arithmetic_nonfragile_interface) << PointeeTy << PExp->getSourceRange(); return QualType(); @@ -5135,7 +5133,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, return QualType(); // Diagnose bad cases where we step over interface counts. - if (lpointee->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { + if (lpointee->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { Diag(Loc, diag::err_arithmetic_nonfragile_interface) << lpointee << lex->getSourceRange(); return QualType(); @@ -5274,8 +5272,6 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) return CheckVectorCompareOperands(lex, rex, Loc, isRelational); - CheckSignCompare(lex, rex, Loc, &Opc); - // C99 6.5.8p3 / C99 6.5.9p4 if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType()) UsualArithmeticConversions(lex, rex); @@ -5904,7 +5900,7 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc, << ResType)) return QualType(); // Diagnose bad cases where we step over interface counts. - else if (PointeeTy->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { + else if (PointeeTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { Diag(OpLoc, diag::err_arithmetic_nonfragile_interface) << PointeeTy << Op->getSourceRange(); return QualType(); @@ -6626,7 +6622,7 @@ Sema::OwningExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, SourceLocation RParenLoc) { QualType ArgTy = TInfo->getType(); bool Dependent = ArgTy->isDependentType(); - SourceRange TypeRange = TInfo->getTypeLoc().getSourceRange(); + SourceRange TypeRange = TInfo->getTypeLoc().getLocalSourceRange(); // We must have at least one component that refers to the type, and the first // one is known to be a field designator. Verify that the ArgTy represents @@ -7018,7 +7014,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { QualType RetTy = T.getTypePtr()->getAs<FunctionType>()->getResultType(); // Do not allow returning a objc interface by-value. - if (RetTy->isObjCInterfaceType()) { + if (RetTy->isObjCObjectType()) { Diag(ParamInfo.getSourceRange().getBegin(), diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; return; @@ -7090,7 +7086,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { QualType RetTy = T->getAs<FunctionType>()->getResultType(); // Do not allow returning a objc interface by-value. - if (RetTy->isObjCInterfaceType()) { + if (RetTy->isObjCObjectType()) { Diag(ParamInfo.getSourceRange().getBegin(), diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; } else if (!RetTy->isDependentType()) @@ -7500,22 +7496,24 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals); } - MaybeMarkVirtualMembersReferenced(Loc, Constructor); + MarkVTableUsed(Loc, Constructor->getParent()); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { if (Destructor->isImplicit() && !Destructor->isUsed()) DefineImplicitDestructor(Loc, Destructor); - + if (Destructor->isVirtual()) + MarkVTableUsed(Loc, Destructor->getParent()); } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) { if (MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() && MethodDecl->getOverloadedOperator() == OO_Equal) { if (!MethodDecl->isUsed()) DefineImplicitCopyAssignment(Loc, MethodDecl); - } + } else if (MethodDecl->isVirtual()) + MarkVTableUsed(Loc, MethodDecl->getParent()); } if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { // Implicit instantiation of function templates and member functions of // class templates. - if (!Function->getBody() && Function->isImplicitlyInstantiable()) { + if (Function->isImplicitlyInstantiable()) { bool AlreadyInstantiated = false; if (FunctionTemplateSpecializationInfo *SpecInfo = Function->getTemplateSpecializationInfo()) { @@ -7570,6 +7568,48 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { } } +namespace { + // Mark all of the declarations referenced + // FIXME: Not fully implemented yet! We need to have a better understanding + // of when we're entering + class MarkReferencedDecls : public RecursiveASTVisitor<MarkReferencedDecls> { + Sema &S; + SourceLocation Loc; + + public: + typedef RecursiveASTVisitor<MarkReferencedDecls> Inherited; + + MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { } + + bool VisitTemplateArgument(const TemplateArgument &Arg); + bool VisitRecordType(RecordType *T); + }; +} + +bool MarkReferencedDecls::VisitTemplateArgument(const TemplateArgument &Arg) { + if (Arg.getKind() == TemplateArgument::Declaration) { + S.MarkDeclarationReferenced(Loc, Arg.getAsDecl()); + } + + return Inherited::VisitTemplateArgument(Arg); +} + +bool MarkReferencedDecls::VisitRecordType(RecordType *T) { + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) { + const TemplateArgumentList &Args = Spec->getTemplateArgs(); + return VisitTemplateArguments(Args.getFlatArgumentList(), + Args.flat_size()); + } + + return false; +} + +void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) { + MarkReferencedDecls Marker(*this, Loc); + Marker.Visit(Context.getCanonicalType(T)); +} + /// \brief Emit a diagnostic that describes an effect on the run-time behavior /// of the program being compiled. /// @@ -7698,3 +7738,17 @@ bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) { return false; } + +Sema::OwningExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc, + ExprArg SubExpr) { + Expr *Sub = SubExpr.takeAs<Expr>(); + if (!Sub) + return ExprError(); + + if (CheckBooleanCondition(Sub, Loc)) { + Sub->Destroy(Context); + return ExprError(); + } + + return Owned(Sub); +} |