Don't build a call expression referring to a function which we're not allowed

to use. This makes very little difference right now (other than suppressing
follow-on errors in some cases), but will matter more once we support deduced
return types (we don't want expressions with undeduced return types in the
AST).

llvm-svn: 181107
This commit is contained in:
Richard Smith 2013-05-04 06:44:46 +00:00
parent 513db4d9f4
commit 22262abd78
4 changed files with 40 additions and 19 deletions

View File

@ -684,7 +684,8 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
MarkFunctionReferenced(E->getExprLoc(), Destructor);
CheckDestructorAccess(E->getExprLoc(), Destructor,
PDiag(diag::err_access_dtor_exception) << Ty);
DiagnoseUseOfDecl(Destructor, E->getExprLoc());
if (DiagnoseUseOfDecl(Destructor, E->getExprLoc()))
return ExprError();
return Owned(E);
}
@ -1426,11 +1427,13 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// Mark the new and delete operators as referenced.
if (OperatorNew) {
DiagnoseUseOfDecl(OperatorNew, StartLoc);
if (DiagnoseUseOfDecl(OperatorNew, StartLoc))
return ExprError();
MarkFunctionReferenced(StartLoc, OperatorNew);
}
if (OperatorDelete) {
DiagnoseUseOfDecl(OperatorDelete, StartLoc);
if (DiagnoseUseOfDecl(OperatorDelete, StartLoc))
return ExprError();
MarkFunctionReferenced(StartLoc, OperatorDelete);
}
@ -1446,7 +1449,8 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
CheckDestructorAccess(StartLoc, dtor,
PDiag(diag::err_access_dtor)
<< BaseAllocType);
DiagnoseUseOfDecl(dtor, StartLoc);
if (DiagnoseUseOfDecl(dtor, StartLoc))
return ExprError();
}
}
}
@ -2204,7 +2208,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
MarkFunctionReferenced(StartLoc,
const_cast<CXXDestructorDecl*>(Dtor));
DiagnoseUseOfDecl(Dtor, StartLoc);
if (DiagnoseUseOfDecl(Dtor, StartLoc))
return ExprError();
}
// C++ [expr.delete]p3:
@ -4819,7 +4824,8 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
CheckDestructorAccess(E->getExprLoc(), Destructor,
PDiag(diag::err_access_dtor_temp)
<< E->getType());
DiagnoseUseOfDecl(Destructor, E->getExprLoc());
if (DiagnoseUseOfDecl(Destructor, E->getExprLoc()))
return ExprError();
// If destructor is trivial, we can avoid the extra copy.
if (Destructor->isTrivial())
@ -4974,7 +4980,8 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
CheckDestructorAccess(Bind->getExprLoc(), Destructor,
PDiag(diag::err_access_dtor_temp)
<< Bind->getType());
DiagnoseUseOfDecl(Destructor, Bind->getExprLoc());
if (DiagnoseUseOfDecl(Destructor, Bind->getExprLoc()))
return ExprError();
// We need a cleanup, but we don't need to remember the temporary.
ExprNeedsCleanups = true;

View File

@ -4867,7 +4867,8 @@ PerformConstructorInitialization(Sema &S,
Kind.getKind() == InitializationKind::IK_Value)))) {
// An explicitly-constructed temporary, e.g., X(1, 2).
S.MarkFunctionReferenced(Loc, Constructor);
S.DiagnoseUseOfDecl(Constructor, Loc);
if (S.DiagnoseUseOfDecl(Constructor, Loc))
return ExprError();
TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
if (!TSInfo)
@ -4926,7 +4927,8 @@ PerformConstructorInitialization(Sema &S,
// Only check access if all of that succeeded.
S.CheckConstructorAccess(Loc, Constructor, Entity,
Step.Function.FoundDecl.getAccess());
S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc);
if (S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc))
return ExprError();
if (shouldBindAsTemporary(Entity))
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
@ -5129,7 +5131,8 @@ InitializationSequence::Perform(Sema &S,
// Overload resolution determined which function invoke; update the
// initializer to reflect that choice.
S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl);
S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation());
if (S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation()))
return ExprError();
CurInit = S.FixOverloadedFunctionReference(CurInit,
Step->Function.FoundDecl,
Step->Function.Function);
@ -5265,7 +5268,8 @@ InitializationSequence::Perform(Sema &S,
S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity,
FoundFn.getAccess());
S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()))
return ExprError();
CastKind = CK_ConstructorConversion;
QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
@ -5279,7 +5283,8 @@ InitializationSequence::Perform(Sema &S,
CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), 0,
FoundFn);
S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()))
return ExprError();
// FIXME: Should we move this initialization into a separate
// derived-to-base conversion? I believe the answer is "no", because
@ -5313,7 +5318,8 @@ InitializationSequence::Perform(Sema &S,
S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor,
S.PDiag(diag::err_access_dtor_temp) << T);
S.MarkFunctionReferenced(CurInit.get()->getLocStart(), Destructor);
S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart());
if (S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart()))
return ExprError();
}
}
@ -5595,7 +5601,8 @@ InitializationSequence::Perform(Sema &S,
S.MarkFunctionReferenced(Kind.getLocation(), Destructor);
S.CheckDestructorAccess(Kind.getLocation(), Destructor,
S.PDiag(diag::err_access_dtor_temp) << E);
S.DiagnoseUseOfDecl(Destructor, Kind.getLocation());
if (S.DiagnoseUseOfDecl(Destructor, Kind.getLocation()))
return ExprError();
}
}
}

View File

@ -42,13 +42,15 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
bool HadMultipleCandidates,
SourceLocation Loc = SourceLocation(),
const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){
if (S.DiagnoseUseOfDecl(FoundDecl, Loc))
return ExprError();
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());
@ -9963,7 +9965,8 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
case OR_Success: {
FunctionDecl *FDecl = (*Best)->Function;
SemaRef.CheckUnresolvedLookupAccess(ULE, (*Best)->FoundDecl);
SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc());
if (SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc()))
return ExprError();
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs,
RParenLoc, ExecConfig);
@ -10846,7 +10849,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Method = cast<CXXMethodDecl>(Best->Function);
FoundDecl = Best->FoundDecl;
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc());
if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()))
return ExprError();
break;
case OR_No_Viable_Function:
@ -11098,7 +11102,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
Best->Conversions[0].UserDefined.ConversionFunction);
CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc);
if (DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc))
return ExprError();
// We selected one of the surrogate functions that converts the
// object parameter to a function pointer. Perform the conversion

View File

@ -41,7 +41,9 @@ decltype(
PD(), // expected-error {{private destructor}}
PD()) pd1; // expected-error {{private destructor}}
decltype(DD(), // expected-error {{deleted function}}
DD()) dd1; // expected-error {{deleted function}}
DD()) dd1;
decltype(A(),
DD()) dd2; // expected-error {{deleted function}}
decltype(
PD(), // expected-error {{temporary of type 'PD' has private destructor}}
0) pd2;