From: Nick Lewycky Date: Tue, 12 Feb 2013 08:08:54 +0000 (+0000) Subject: The meat of this patch is in BuildCXXMemberCalLExpr where we make it use X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3c86a5c2f60d4f68afde96e2138b6933b30d6aa8;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174951 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 4c8d098158..97d1ea2cf1 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index f6c6fe118e..191683d33d 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 7f24af8be1..49d66113dc 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/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/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 0612c73f89..1b69872417 100644 --- a/lib/Sema/SemaInit.cpp +++ b/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/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 6fa4137970..c2e0d6f809 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/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/test/Sema/attr-cleanup.c b/test/Sema/attr-cleanup.c index 59ebbfc459..991822e402 100644 --- a/test/Sema/attr-cleanup.c +++ b/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/test/SemaCXX/attr-deprecated.cpp b/test/SemaCXX/attr-deprecated.cpp index f3d818a75f..2d730a8eed 100644 --- a/test/SemaCXX/attr-deprecated.cpp +++ b/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/test/SemaCXX/undefined-internal.cpp b/test/SemaCXX/undefined-internal.cpp index 40ab33cac4..e8810adadf 100644 --- a/test/SemaCXX/undefined-internal.cpp +++ b/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}} + } +}