From a096b14d1d973f2bc40b2108cfbeedeacdcc42d1 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Tue, 12 Feb 2013 08:08:54 +0000 Subject: [PATCH] The meat of this patch is in BuildCXXMemberCalLExpr where we make it use MarkMemberReferenced instead of marking functions referenced directly. An audit of callers to MarkFunctionReferenced and DiagnoseUseOfDecl also caused a few other changes: * don't mark functions odr-used when considering them for an initialization sequence. Do mark them referenced though. * the function nominated by the cleanup attribute should be diagnosed. * operator new/delete should be diagnosed when building a 'new' expression. llvm-svn: 174951 --- clang/lib/Sema/SemaDeclAttr.cpp | 1 + clang/lib/Sema/SemaExpr.cpp | 4 +++- clang/lib/Sema/SemaExprCXX.cpp | 10 ++++++--- clang/lib/Sema/SemaInit.cpp | 11 ++++----- clang/lib/Sema/SemaOverload.cpp | 2 -- clang/test/Sema/attr-cleanup.c | 4 ++++ clang/test/SemaCXX/attr-deprecated.cpp | 13 ++++++++++- clang/test/SemaCXX/undefined-internal.cpp | 37 +++++++++++++++++++++++++++++++ 8 files changed, 68 insertions(+), 14 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 4c8d098..97d1ea2 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2849,6 +2849,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { CleanupAttr(Attr.getRange(), S.Context, FD, Attr.getAttributeSpellingListIndex())); S.MarkFunctionReferenced(Attr.getParameterLoc(), FD); + S.DiagnoseUseOfDecl(FD, Attr.getParameterLoc()); } /// Handle __attribute__((format_arg((idx)))) attribute based on diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f6c6fe1..191683d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -11210,7 +11210,9 @@ void Sema::MarkMemberReferenced(MemberExpr *E) { if (Method->isPure()) OdrUse = false; } - MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E, OdrUse); + SourceLocation Loc = E->getMemberLoc().isValid() ? + E->getMemberLoc() : E->getLocStart(); + MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, OdrUse); } /// \brief Perform marking for a reference to an arbitrary declaration. It diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 7f24af8..49d6611 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1376,10 +1376,14 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, } // Mark the new and delete operators as referenced. - if (OperatorNew) + if (OperatorNew) { + DiagnoseUseOfDecl(OperatorNew, StartLoc); MarkFunctionReferenced(StartLoc, OperatorNew); - if (OperatorDelete) + } + if (OperatorDelete) { + DiagnoseUseOfDecl(OperatorDelete, StartLoc); MarkFunctionReferenced(StartLoc, OperatorDelete); + } // C++0x [expr.new]p17: // If the new expression creates an array of objects of class type, @@ -5335,12 +5339,12 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, VK_RValue, OK_Ordinary); if (HadMultipleCandidates) ME->setHadMultipleCandidates(true); + MarkMemberReferenced(ME); QualType ResultType = Method->getResultType(); ExprValueKind VK = Expr::getValueKindForType(ResultType); ResultType = ResultType.getNonLValueExprType(Context); - MarkFunctionReferenced(Exp.get()->getLocStart(), Method); CXXMemberCallExpr *CE = new (Context) CXXMemberCallExpr(Context, ME, MultiExprArg(), ResultType, VK, Exp.get()->getLocEnd()); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 0612c73..1b69872 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3262,10 +3262,9 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, return Result; FunctionDecl *Function = Best->Function; - - // This is the overload that will actually be used for the initialization, so - // mark it as used. - S.MarkFunctionReferenced(DeclLoc, Function); + // This is the overload that will be used for this initialization step if we + // use this initialization. Mark it as referenced. + Function->setReferenced(); // Compute the returned type of the conversion. if (isa(Function)) @@ -3831,7 +3830,7 @@ static void TryUserDefinedConversion(Sema &S, } FunctionDecl *Function = Best->Function; - S.MarkFunctionReferenced(DeclLoc, Function); + Function->setReferenced(); bool HadMultipleCandidates = (CandidateSet.size() > 1); if (isa(Function)) { @@ -4609,8 +4608,6 @@ static ExprResult CopyObject(Sema &S, return S.Owned(CurInitExpr); } - S.MarkFunctionReferenced(Loc, Constructor); - // Determine the arguments required to actually perform the // constructor call (we might have derived-to-base conversions, or // the copy constructor may have default arguments). diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 6fa41379..c2e0d6f 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -9916,7 +9916,6 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, switch (OverloadResult) { case OR_Success: { FunctionDecl *FDecl = (*Best)->Function; - SemaRef.MarkFunctionReferenced(Fn->getExprLoc(), FDecl); SemaRef.CheckUnresolvedLookupAccess(ULE, (*Best)->FoundDecl); SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc()); Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); @@ -10799,7 +10798,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Best)) { case OR_Success: Method = cast(Best->Function); - MarkFunctionReferenced(UnresExpr->getMemberLoc(), Method); FoundDecl = Best->FoundDecl; CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()); diff --git a/clang/test/Sema/attr-cleanup.c b/clang/test/Sema/attr-cleanup.c index 59ebbfc..991822e 100644 --- a/clang/test/Sema/attr-cleanup.c +++ b/clang/test/Sema/attr-cleanup.c @@ -38,3 +38,7 @@ void t4() { __attribute((cleanup(c4))) void* g; } +void c5(void*) __attribute__((deprecated)); // expected-note{{'c5' declared here}} +void t5() { + int i __attribute__((cleanup(c5))); // expected-warning {{'c5' is deprecated}} +} diff --git a/clang/test/SemaCXX/attr-deprecated.cpp b/clang/test/SemaCXX/attr-deprecated.cpp index f3d818a..2d730a8 100644 --- a/clang/test/SemaCXX/attr-deprecated.cpp +++ b/clang/test/SemaCXX/attr-deprecated.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -verify -fsyntax-only +// RUN: %clang_cc1 %s -verify -fexceptions class A { void f() __attribute__((deprecated)); // expected-note 2 {{declared here}} void g(A* a); @@ -233,3 +233,14 @@ namespace test6 { x = D::d1; // expected-warning {{'d1' is deprecated}} } } + +namespace test7 { + struct X { + void* operator new(unsigned long) __attribute__((deprecated)); // expected-note{{'operator new' declared here}} + void operator delete(void *) __attribute__((deprecated)); // expected-note{{'operator delete' declared here}} + }; + + void test() { + X *x = new X; // expected-warning{{'operator new' is deprecated}} expected-warning{{'operator delete' is deprecated}} + } +} diff --git a/clang/test/SemaCXX/undefined-internal.cpp b/clang/test/SemaCXX/undefined-internal.cpp index 40ab33c..e8810ad 100644 --- a/clang/test/SemaCXX/undefined-internal.cpp +++ b/clang/test/SemaCXX/undefined-internal.cpp @@ -269,3 +269,40 @@ namespace test11 { (void)b1->member; // expected-note {{used here}} } } + +namespace test12 { + class T1 {}; class T2 {}; class T3 {}; class T4 {}; class T5 {}; class T6 {}; + class T7 {}; + + namespace { + struct Cls { + virtual void f(int) = 0; + virtual void f(int, double) = 0; + void g(int); // expected-warning {{function 'test12::::Cls::g' has internal linkage but is not defined}} + void g(int, double); + virtual operator T1() = 0; + virtual operator T2() = 0; + virtual operator T3&() = 0; + operator T4(); // expected-warning {{function 'test12::::Cls::operator T4' has internal linkage but is not defined}} + operator T5(); // expected-warning {{function 'test12::::Cls::operator T5' has internal linkage but is not defined}} + operator T6&(); // expected-warning {{function 'test12::::Cls::operator class test12::T6 &' has internal linkage but is not defined}} + }; + + struct Cls2 { + Cls2(T7); // expected-warning {{function 'test12::::Cls2::Cls2' has internal linkage but is not defined}} + }; + } + + void test(Cls &c) { + c.f(7); + c.g(7); // expected-note {{used here}} + (void)static_cast(c); + T2 t2 = c; + T3 &t3 = c; + (void)static_cast(c); // expected-note {{used here}} + T5 t5 = c; // expected-note {{used here}} + T6 &t6 = c; // expected-note {{used here}} + + Cls2 obj1((T7())); // expected-note {{used here}} + } +} -- 2.7.4