]> granicus.if.org Git - clang/commitdiff
Fix ODR-use of a MemberExpr to check before marking a pure function used. Remove
authorNick Lewycky <nicholas@mxc.ca>
Thu, 31 Jan 2013 01:34:31 +0000 (01:34 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Thu, 31 Jan 2013 01:34:31 +0000 (01:34 +0000)
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

lib/Sema/Sema.cpp
lib/Sema/SemaExpr.cpp
test/SemaCXX/undefined-internal.cpp

index 5dc2a6a70028a2b059bdc921c8a2946a75b14634..576435514426851622782a365c4fb49b5fe8905d 100644 (file)
@@ -396,7 +396,7 @@ static void checkUndefinedInternals(Sema &S) {
     if (decl->hasAttr<WeakRefAttr>()) continue;
 
     if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
-      if (fn->isPure() || fn->hasBody())
+      if (fn->isDefined())
         continue;
     } else {
       if (cast<VarDecl>(decl)->hasDefinition() != VarDecl::DeclarationOnly)
index 60e104cadf5fa0ea264dd71308f3c4fc680e3175..bfbb22ca085571858a4ea383e17f36ad998c4c1f 100644 (file)
@@ -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<CXXMethodDecl>(E->getMemberDecl()))
+      if (Method->isPure())
+        return;
+  }
   MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E);
 }
 
index e8ee4c1e90702fb61212b3f0fb6c6f1d7ad5b69c..62c6ff96ca9f428c92d3c952b8465570ad827246 100644 (file)
@@ -199,3 +199,16 @@ namespace test8 {
     }
   } *A;
 }
+
+namespace test9 {
+  namespace {
+    struct X {
+      virtual void notused() = 0;
+      virtual void used() = 0; // expected-warning {{function 'test9::<anonymous namespace>::X::used' has internal linkage but is not defined}}
+    };
+  }
+  void test(X &x) {
+    x.notused();
+    x.X::used(); // expected-note {{used here}}
+  }
+}