Apply the pure-virtual odr rule to other constructs which can call overloaded

operators.

llvm-svn: 174584
This commit is contained in:
Nick Lewycky 2013-02-07 05:08:22 +00:00
parent 4a230ffa96
commit 134af91b06
2 changed files with 52 additions and 25 deletions

View File

@ -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<CXXMethodDecl>(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<CXXMethodDecl>(FnDecl)) {
// Best->Access is only meaningful for class members.
@ -10359,8 +10357,6 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Args[1] = RHS = Arg1.takeAs<Expr>();
}
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<CXXMethodDecl>(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<CXXMethodDecl>(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())

View File

@ -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::<anonymous namespace>::B::operator()' has internal linkage but is not defined}}
void operator!() const; // expected-warning {{function 'test11::<anonymous namespace>::B::operator!' has internal linkage but is not defined}}
bool operator+(const B&) const; // expected-warning {{function 'test11::<anonymous namespace>::B::operator+' has internal linkage but is not defined}}
int operator[](int) const; // expected-warning {{function 'test11::<anonymous namespace>::B::operator[]' has internal linkage but is not defined}}
const B* operator->() const; // expected-warning {{function 'test11::<anonymous namespace>::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}}
}
}