forked from OSchip/llvm-project
Apply the pure-virtual odr rule to other constructs which can call overloaded
operators. llvm-svn: 174584
This commit is contained in:
parent
4a230ffa96
commit
134af91b06
|
@ -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())
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue