From b697e084341185a08b3946df032fbc75f76a66e0 Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 6 May 2010 18:15:07 +0000 Subject: [PATCH] Diagnose deprecated/unavailable functions selected by overload resolution. Fixes rdar://problem/4232969, or at least the clang parts of it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103191 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaInit.cpp | 4 + lib/Sema/SemaOverload.cpp | 20 ++++- test/SemaCXX/attr-deprecated.cpp | 126 +++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 3 deletions(-) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 0aa3446177..0360b3d965 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3517,6 +3517,7 @@ InitializationSequence::Perform(Sema &S, // Overload resolution determined which function invoke; update the // initializer to reflect that choice. S.CheckAddressOfMemberAccess(CurInitExpr, Step->Function.FoundDecl); + S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation()); CurInit = S.FixOverloadedFunctionReference(move(CurInit), Step->Function.FoundDecl, Step->Function.Function); @@ -3619,6 +3620,7 @@ InitializationSequence::Perform(Sema &S, S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity, FoundFn.getAccess()); + S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()); CastKind = CastExpr::CK_ConstructorConversion; QualType Class = S.Context.getTypeDeclType(Constructor->getParent()); @@ -3633,6 +3635,7 @@ InitializationSequence::Perform(Sema &S, IsLvalue = Conversion->getResultType()->isLValueReferenceType(); S.CheckMemberOperatorAccess(Kind.getLocation(), CurInitExpr, 0, FoundFn); + S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()); // FIXME: Should we move this initialization into a separate // derived-to-base conversion? I believe the answer is "no", because @@ -3772,6 +3775,7 @@ InitializationSequence::Perform(Sema &S, // Only check access if all of that succeeded. S.CheckConstructorAccess(Loc, Constructor, Entity, Step->Function.FoundDecl.getAccess()); + S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Loc); if (shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.takeAs()); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 9a4a8ff712..531ca39a99 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -5500,8 +5500,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, assert(Result != MatchesCopy.end() && "no most-specialized template"); MarkDeclarationReferenced(From->getLocStart(), *Result); FoundResult = Matches[Result - MatchesCopy.begin()].first; - if (Complain) + if (Complain) { CheckUnresolvedAccess(*this, OvlExpr, FoundResult); + DiagnoseUseOfDecl(FoundResult, OvlExpr->getNameLoc()); + } return cast(*Result); } @@ -5521,8 +5523,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, if (Matches.size() == 1) { MarkDeclarationReferenced(From->getLocStart(), Matches[0].second); FoundResult = Matches[0].first; - if (Complain) + if (Complain) { CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first); + DiagnoseUseOfDecl(Matches[0].first, OvlExpr->getNameLoc()); + } return cast(Matches[0].second); } @@ -5801,6 +5805,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, case OR_Success: { FunctionDecl *FDecl = Best->Function; CheckUnresolvedLookupAccess(ULE, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, ULE->getNameLoc()); Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl); return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc); } @@ -5945,6 +5950,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, Input = (Expr *)input.get(); } + DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); + // Determine the result type QualType ResultTy = FnDecl->getResultType().getNonReferenceType(); @@ -5958,7 +5965,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, ExprOwningPtr TheCall(this, new (Context) CXXOperatorCallExpr(Context, Op, FnExpr, Args, NumArgs, ResultTy, OpLoc)); - + if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall.get(), FnDecl)) return ExprError(); @@ -6150,6 +6157,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, Args[1] = RHS = Arg1.takeAs(); } + DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); + // Determine the result type QualType ResultTy = FnDecl->getType()->getAs()->getResultType(); @@ -6286,6 +6295,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // operator. CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, LLoc); // Convert the arguments. CXXMethodDecl *Method = cast(FnDecl); @@ -6452,6 +6462,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Method = cast(Best->Function); FoundDecl = Best->FoundDecl; CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()); break; case OR_No_Viable_Function: @@ -6661,6 +6672,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, Best->Conversions[0].UserDefined.ConversionFunction); CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); // We selected one of the surrogate functions that converts the // object parameter to a function pointer. Perform the conversion @@ -6677,6 +6689,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, } CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); // We found an overloaded operator(). Build a CXXOperatorCallExpr // that calls this method, using Object for the implicit object @@ -6847,6 +6860,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { } CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); // Convert the object parameter. CXXMethodDecl *Method = cast(Best->Function); diff --git a/test/SemaCXX/attr-deprecated.cpp b/test/SemaCXX/attr-deprecated.cpp index d5662d3f63..2164f9dd17 100644 --- a/test/SemaCXX/attr-deprecated.cpp +++ b/test/SemaCXX/attr-deprecated.cpp @@ -64,3 +64,129 @@ void D::f() { } void f(D* d) { d->f(); } + + +// Overloaded namespace members. +namespace test1 { + void foo(int) __attribute__((deprecated)); + void test1() { foo(10); } // expected-warning {{deprecated}} + void foo(short) __attribute__((deprecated)); + void test2(short s) { foo(s); } // expected-warning {{deprecated}} + void foo(long); + void test3(long l) { foo(l); } + struct A { + friend void foo(A*) __attribute__((deprecated)); + }; + void test4(A *a) { foo(a); } // expected-warning {{deprecated}} + + namespace ns { + struct Foo {}; + void foo(const Foo &f) __attribute__((deprecated)); + } + void test5() { + foo(ns::Foo()); // expected-warning {{deprecated}} + } +} + +// Overloaded class members. +namespace test2 { + struct A { + void foo(int) __attribute__((deprecated)); + void foo(long); + static void bar(int) __attribute__((deprecated)); + static void bar(long); + + void test2(int i, long l); + }; + void test1(int i, long l) { + A a; + a.foo(i); // expected-warning {{deprecated}} + a.foo(l); + a.bar(i); // expected-warning {{deprecated}} + a.bar(l); + A::bar(i); // expected-warning {{deprecated}} + A::bar(l); + } + + void A::test2(int i, long l) { + foo(i); // expected-warning {{deprecated}} + foo(l); + bar(i); // expected-warning {{deprecated}} + bar(l); + } +} + +// Overloaded operators. +namespace test3 { + struct A { + void operator*(const A &); + void operator*(int) __attribute__((deprecated)); + void operator-(const A &) const; + }; + void operator+(const A &, const A &); + void operator+(const A &, int) __attribute__((deprecated)); + void operator-(const A &, int) __attribute__((deprecated)); + + void test() { + A a, b; + a + b; + a + 1; // expected-warning {{deprecated}} + a - b; + a - 1; // expected-warning {{deprecated}} + a * b; + a * 1; // expected-warning {{deprecated}} + } +} + +// Overloaded operator call. +namespace test4 { + struct A { + typedef void (*intfn)(int); + typedef void (*unintfn)(unsigned); + operator intfn() __attribute__((deprecated)); + operator unintfn(); + void operator ()(A &) __attribute__((deprecated)); + void operator ()(const A &); + }; + + void test() { + A a; + a(1); // expected-warning {{deprecated}} + a(1U); + + A &b = a; + const A &c = a; + a(b); // expected-warning {{deprecated}} + a(c); + } +} + +namespace test5 { + struct A { + operator int() __attribute__((deprecated)); + operator long(); + }; + void test1(A a) { + int i = a; // expected-warning {{deprecated}} + long l = a; + } + + void foo(int); + void foo(void*); + void bar(long); + void bar(void*); + void test2(A a) { + foo(a); // expected-warning {{deprecated}} + bar(a); + } + + struct B { + int myInt; + long myLong; + + B(A &a) : + myInt(a), // expected-warning {{deprecated}} + myLong(a) + {} + }; +} -- 2.40.0