From: Nick Lewycky Date: Thu, 31 Jan 2013 01:34:31 +0000 (+0000) Subject: Fix ODR-use of a MemberExpr to check before marking a pure function used. Remove X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4ceaf337be78fa89b4a97f351be6d0bda962d7de;p=clang Fix ODR-use of a MemberExpr to check before marking a pure function used. Remove a workaround for this bug from the -Wundefined-internals warning. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174020 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 5dc2a6a700..5764355144 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -396,7 +396,7 @@ static void checkUndefinedInternals(Sema &S) { if (decl->hasAttr()) continue; if (FunctionDecl *fn = dyn_cast(decl)) { - if (fn->isPure() || fn->hasBody()) + if (fn->isDefined()) continue; } else { if (cast(decl)->hasDefinition() != VarDecl::DeclarationOnly) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 60e104cadf..bfbb22ca08 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -10506,8 +10506,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { } // Keep track of used but undefined functions. - if (!Func->isPure() && !Func->hasBody() && - Func->getLinkage() != ExternalLinkage) { + if (!Func->isDefined() && Func->getLinkage() != ExternalLinkage) { SourceLocation &old = UndefinedInternals[Func->getCanonicalDecl()]; if (old.isInvalid()) old = Loc; } @@ -11167,6 +11166,17 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E) { /// \brief Perform reference-marking and odr-use handling for a MemberExpr. void Sema::MarkMemberReferenced(MemberExpr *E) { + // C++11 [basic.def.odr]p2 + // A non-overloaded function whose name appears as a potentially-evaluated + // expression or a member of a set of candidate functions, if selected by + // overload resolution when referred to from a potentially-evaluated + // expression, is odr-used, unless it is a pure virtual function and its + // name is not explicitly qualified. + if (!E->hasQualifier()) { + if (CXXMethodDecl *Method = dyn_cast(E->getMemberDecl())) + if (Method->isPure()) + return; + } MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E); } diff --git a/test/SemaCXX/undefined-internal.cpp b/test/SemaCXX/undefined-internal.cpp index e8ee4c1e90..62c6ff96ca 100644 --- a/test/SemaCXX/undefined-internal.cpp +++ b/test/SemaCXX/undefined-internal.cpp @@ -199,3 +199,16 @@ namespace test8 { } } *A; } + +namespace test9 { + namespace { + struct X { + virtual void notused() = 0; + virtual void used() = 0; // expected-warning {{function 'test9::::X::used' has internal linkage but is not defined}} + }; + } + void test(X &x) { + x.notused(); + x.X::used(); // expected-note {{used here}} + } +}