r174242 - This patch makes "&Cls::purevfn" not an odr use. This isn't what the standard

Nick Lewycky nicholas at mxc.ca
Fri Feb 1 16:25:55 PST 2013


Author: nicholas
Date: Fri Feb  1 18:25:55 2013
New Revision: 174242

URL: http://llvm.org/viewvc/llvm-project?rev=174242&view=rev
Log:
This patch makes "&Cls::purevfn" not an odr use. This isn't what the standard
says, but that's a defect (to be filed). "Cls::purevfn()" is still an odr use.

Also fixes a bug that caused us to not mark the function referenced just
because we didn't want to mark it odr used.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
    cfe/trunk/test/SemaCXX/address-of.cpp
    cfe/trunk/test/SemaCXX/undefined-internal.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=174242&r1=174241&r2=174242&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Feb  1 18:25:55 2013
@@ -2863,7 +2863,7 @@ public:
   // for expressions referring to a decl; these exist because odr-use marking
   // needs to be delayed for some constant variables when we build one of the
   // named expressions.
-  void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D);
+  void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse);
   void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func);
   void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var);
   void MarkDeclRefReferenced(DeclRefExpr *E);

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=174242&r1=174241&r2=174242&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Feb  1 18:25:55 2013
@@ -2025,7 +2025,7 @@ Sema::LookupInObjCMethod(LookupResult &L
       if (SelfExpr.isInvalid())
         return ExprError();
 
-      MarkAnyDeclReferenced(Loc, IV);
+      MarkAnyDeclReferenced(Loc, IV, true);
       
       ObjCMethodFamily MF = CurMethod->getMethodFamily();
       if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize)
@@ -11152,13 +11152,13 @@ void Sema::MarkVariableReferenced(Source
 }
 
 static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
-                               Decl *D, Expr *E) {
+                               Decl *D, Expr *E, bool OdrUse) {
   if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
     DoMarkVarDeclReferenced(SemaRef, Loc, Var, E);
     return;
   }
 
-  SemaRef.MarkAnyDeclReferenced(Loc, D);
+  SemaRef.MarkAnyDeclReferenced(Loc, D, OdrUse);
 
   // If this is a call to a method via a cast, also mark the method in the
   // derived class used in case codegen can devirtualize the call.
@@ -11175,12 +11175,19 @@ static void MarkExprReferenced(Sema &Sem
   CXXMethodDecl *DM = MD->getCorrespondingMethodInClass(MostDerivedClassDecl);
   if (!DM)
     return;
-  SemaRef.MarkAnyDeclReferenced(Loc, DM);
+  SemaRef.MarkAnyDeclReferenced(Loc, DM, OdrUse);
 } 
 
 /// \brief Perform reference-marking and odr-use handling for a DeclRefExpr.
 void Sema::MarkDeclRefReferenced(DeclRefExpr *E) {
-  MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E);
+  // TODO: update this with DR# once a defect report is filed.
+  // C++11 defect. The address of a pure member should not be an ODR use, even
+  // if it's a qualified reference.
+  bool OdrUse = true;
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getDecl()))
+    if (Method->isPure())
+      OdrUse = false;
+  MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse);
 }
 
 /// \brief Perform reference-marking and odr-use handling for a MemberExpr.
@@ -11191,25 +11198,31 @@ void Sema::MarkMemberReferenced(MemberEx
   //   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.
+  bool OdrUse = true;
   if (!E->hasQualifier()) {
     if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getMemberDecl()))
       if (Method->isPure())
-        return;
+        OdrUse = false;
   }
-  MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E);
+  MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E, OdrUse);
 }
 
 /// \brief Perform marking for a reference to an arbitrary declaration.  It
 /// marks the declaration referenced, and performs odr-use checking for functions
 /// and variables. This method should not be used when building an normal
 /// expression which refers to a variable.
-void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D) {
-  if (VarDecl *VD = dyn_cast<VarDecl>(D))
-    MarkVariableReferenced(Loc, VD);
-  else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
-    MarkFunctionReferenced(Loc, FD);
-  else
-    D->setReferenced();
+void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse) {
+  if (OdrUse) {
+    if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+      MarkVariableReferenced(Loc, VD);
+      return;
+    }
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+      MarkFunctionReferenced(Loc, FD);
+      return;
+    }
+  }
+  D->setReferenced();
 }
 
 namespace {
@@ -11234,7 +11247,7 @@ bool MarkReferencedDecls::TraverseTempla
   const TemplateArgument &Arg) {
   if (Arg.getKind() == TemplateArgument::Declaration) {
     if (Decl *D = Arg.getAsDecl())
-      S.MarkAnyDeclReferenced(Loc, D);
+      S.MarkAnyDeclReferenced(Loc, D, true);
   }
 
   return Inherited::TraverseTemplateArgument(Arg);

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=174242&r1=174241&r2=174242&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Feb  1 18:25:55 2013
@@ -3950,7 +3950,7 @@ CheckTemplateArgumentAddressOfObjectOrFu
   // Create the template argument.
   Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
                                ParamType->isReferenceType());
-  S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity);
+  S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity, false);
   return false;
 }
 

Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=174242&r1=174241&r2=174242&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Fri Feb  1 18:25:55 2013
@@ -844,7 +844,7 @@ ExprResult Sema::ActOnSizeofParameterPac
     return ExprError();
   }
 
-  MarkAnyDeclReferenced(OpLoc, ParameterPack);
+  MarkAnyDeclReferenced(OpLoc, ParameterPack, true);
 
   return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc, 
                                       ParameterPack, NameLoc, RParenLoc);

Modified: cfe/trunk/test/SemaCXX/address-of.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/address-of.cpp?rev=174242&r1=174241&r2=174242&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/address-of.cpp (original)
+++ cfe/trunk/test/SemaCXX/address-of.cpp Fri Feb  1 18:25:55 2013
@@ -44,3 +44,11 @@ void PR11066::test() {
   int (PR11066::*ptr)(int) = & &PR11066::foo; // expected-error{{address expression must be an lvalue or a function designator}}
 }
 
+namespace test3 {
+  // emit no error
+  template<typename T> struct S {
+    virtual void f() = 0;
+  };
+  template<typename T> void S<T>::f() { T::error; }
+  void (S<int>::*p)() = &S<int>::f;
+}

Modified: cfe/trunk/test/SemaCXX/undefined-internal.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/undefined-internal.cpp?rev=174242&r1=174241&r2=174242&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/undefined-internal.cpp (original)
+++ cfe/trunk/test/SemaCXX/undefined-internal.cpp Fri Feb  1 18:25:55 2013
@@ -212,3 +212,22 @@ namespace test9 {
     x.X::used(); // expected-note {{used here}}
   }
 }
+
+namespace test10 {
+  namespace {
+    struct X {
+      virtual void notused() = 0;
+      virtual void used() = 0; // expected-warning {{function 'test10::<anonymous namespace>::X::used' has internal linkage but is not defined}}
+
+      void test() {
+        notused();
+        (void)&X::notused;
+        (this->*&X::notused)();
+        X::used();  // expected-note {{used here}}
+      }
+    };
+    struct Y : X {
+      using X::notused;
+    };
+  }
+}





More information about the cfe-commits mailing list