From 134af91b0649359a068d30479b66452dd68a23c0 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 7 Feb 2013 05:08:22 +0000 Subject: [PATCH] Apply the pure-virtual odr rule to other constructs which can call overloaded operators. llvm-svn: 174584 --- clang/lib/Sema/SemaOverload.cpp | 39 +++++++++++-------------------- clang/test/SemaCXX/undefined-internal.cpp | 38 ++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 82fe0c9..2d4d159 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -36,16 +36,20 @@ namespace clang { using namespace sema; -/// A convenience routine for creating a decayed reference to a -/// function. +/// A convenience routine for creating a decayed reference to a function. static ExprResult -CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, bool HadMultipleCandidates, +CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl, + bool HadMultipleCandidates, SourceLocation Loc = SourceLocation(), const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){ DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo); if (HadMultipleCandidates) DRE->setHadMultipleCandidates(true); + + S.MarkDeclRefReferenced(DRE); + S.DiagnoseUseOfDecl(FoundDecl, Loc); + ExprResult E = S.Owned(DRE); E = S.DefaultFunctionArrayConversion(E.take()); if (E.isInvalid()) @@ -10092,8 +10096,6 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // We matched an overloaded operator. Build a call to that // operator. - MarkFunctionReferenced(OpLoc, FnDecl); - // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl); @@ -10117,15 +10119,13 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, Input = InputInit.take(); } - DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); - // Determine the result type. QualType ResultTy = FnDecl->getResultType(); ExprValueKind VK = Expr::getValueKindForType(ResultTy); ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, Best->FoundDecl, HadMultipleCandidates, OpLoc); if (FnExpr.isInvalid()) return ExprError(); @@ -10317,8 +10317,6 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // We matched an overloaded operator. Build a call to that // operator. - MarkFunctionReferenced(OpLoc, FnDecl); - // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { // Best->Access is only meaningful for class members. @@ -10359,8 +10357,6 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, Args[1] = RHS = Arg1.takeAs(); } - DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); - // Determine the result type. QualType ResultTy = FnDecl->getResultType(); ExprValueKind VK = Expr::getValueKindForType(ResultTy); @@ -10368,6 +10364,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Build the actual expression node. ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, + Best->FoundDecl, HadMultipleCandidates, OpLoc); if (FnExpr.isInvalid()) return ExprError(); @@ -10544,10 +10541,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // We matched an overloaded operator. Build a call to that // operator. - MarkFunctionReferenced(LLoc, FnDecl); - CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl); - DiagnoseUseOfDecl(Best->FoundDecl, LLoc); // Convert the arguments. CXXMethodDecl *Method = cast(FnDecl); @@ -10579,6 +10573,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, DeclarationNameInfo OpLocInfo(OpName, LLoc); OpLocInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, + Best->FoundDecl, HadMultipleCandidates, OpLocInfo.getLoc(), OpLocInfo.getInfo()); @@ -11071,9 +11066,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, RParenLoc); } - MarkFunctionReferenced(LParenLoc, Best->Function); CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); - DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); // We found an overloaded operator(). Build a CXXOperatorCallExpr // that calls this method, using Object for the implicit object @@ -11107,7 +11100,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, DeclarationNameInfo OpLocInfo( Context.DeclarationNames.getCXXOperatorName(OO_Call), LParenLoc); OpLocInfo.setCXXOperatorNameRange(SourceRange(LParenLoc, RParenLoc)); - ExprResult NewFn = CreateFunctionRefExpr(*this, Method, + ExprResult NewFn = CreateFunctionRefExpr(*this, Method, Best->FoundDecl, HadMultipleCandidates, OpLocInfo.getLoc(), OpLocInfo.getInfo()); @@ -11272,9 +11265,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { return ExprError(); } - MarkFunctionReferenced(OpLoc, Best->Function); CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl); - DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); // Convert the object parameter. CXXMethodDecl *Method = cast(Best->Function); @@ -11286,7 +11277,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { Base = BaseResult.take(); // Build the operator call. - ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, + ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, Best->FoundDecl, HadMultipleCandidates, OpLoc); if (FnExpr.isInvalid()) return ExprError(); @@ -11341,10 +11332,8 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, } FunctionDecl *FD = Best->Function; - MarkFunctionReferenced(UDSuffixLoc, FD); - DiagnoseUseOfDecl(Best->FoundDecl, UDSuffixLoc); - - ExprResult Fn = CreateFunctionRefExpr(*this, FD, HadMultipleCandidates, + ExprResult Fn = CreateFunctionRefExpr(*this, FD, Best->FoundDecl, + HadMultipleCandidates, SuffixInfo.getLoc(), SuffixInfo.getInfo()); if (Fn.isInvalid()) diff --git a/clang/test/SemaCXX/undefined-internal.cpp b/clang/test/SemaCXX/undefined-internal.cpp index 227e6b4..40ab33c 100644 --- a/clang/test/SemaCXX/undefined-internal.cpp +++ b/clang/test/SemaCXX/undefined-internal.cpp @@ -231,3 +231,41 @@ namespace test10 { }; } } + +namespace test11 { + namespace { + struct A { + virtual bool operator()() const = 0; + virtual void operator!() const = 0; + virtual bool operator+(const A&) const = 0; + virtual int operator[](int) const = 0; + virtual const A* operator->() const = 0; + int member; + }; + + struct B { + bool operator()() const; // expected-warning {{function 'test11::::B::operator()' has internal linkage but is not defined}} + void operator!() const; // expected-warning {{function 'test11::::B::operator!' has internal linkage but is not defined}} + bool operator+(const B&) const; // expected-warning {{function 'test11::::B::operator+' has internal linkage but is not defined}} + int operator[](int) const; // expected-warning {{function 'test11::::B::operator[]' has internal linkage but is not defined}} + const B* operator->() const; // expected-warning {{function 'test11::::B::operator->' has internal linkage but is not defined}} + int member; + }; + } + + void test1(A &a1, A &a2) { + a1(); + !a1; + a1 + a2; + a1[0]; + (void)a1->member; + } + + void test2(B &b1, B &b2) { + b1(); // expected-note {{used here}} + !b1; // expected-note {{used here}} + b1 + b2; // expected-note {{used here}} + b1[0]; // expected-note {{used here}} + (void)b1->member; // expected-note {{used here}} + } +} -- 2.7.4