aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaInit.cpp4
-rw-r--r--lib/Sema/SemaOverload.cpp20
-rw-r--r--test/SemaCXX/attr-deprecated.cpp126
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<Expr>());
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<FunctionDecl>(*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<FunctionDecl>(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<CallExpr> 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<Expr>();
}
+ DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
+
// Determine the result type
QualType ResultTy
= FnDecl->getType()->getAs<FunctionType>()->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<CXXMethodDecl>(FnDecl);
@@ -6452,6 +6462,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Method = cast<CXXMethodDecl>(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<CXXMethodDecl>(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)
+ {}
+ };
+}