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