[clang] 0ec1e99 - Resolve exception specifications after marking the corresponding
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Sun Dec 15 22:10:57 PST 2019
Author: Richard Smith
Date: 2019-12-15T22:02:30-08:00
New Revision: 0ec1e99001291b894de4cd8d7ecc2a283d9a3bfc
URL: https://github.com/llvm/llvm-project/commit/0ec1e99001291b894de4cd8d7ecc2a283d9a3bfc
DIFF: https://github.com/llvm/llvm-project/commit/0ec1e99001291b894de4cd8d7ecc2a283d9a3bfc.diff
LOG: Resolve exception specifications after marking the corresponding
function as referenced, not before.
No functionality change intended. This is groundwork for computing the
exception specification of a defaulted comparison, for which we'd like
to use the implicit body where possible.
Added:
Modified:
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaExprMember.cpp
clang/lib/Sema/SemaOverload.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index a57ee7b0ff21..e1921f0ddf78 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1827,6 +1827,25 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
VK, FoundD, TemplateArgs, getNonOdrUseReasonInCurrentContext(D));
MarkDeclRefReferenced(E);
+ // C++ [except.spec]p17:
+ // An exception-specification is considered to be needed when:
+ // - in an expression, the function is the unique lookup result or
+ // the selected member of a set of overloaded functions.
+ //
+ // We delay doing this until after we've built the function reference and
+ // marked it as used so that:
+ // a) if the function is defaulted, we get errors from defining it before /
+ // instead of errors from computing its exception specification, and
+ // b) if the function is a defaulted comparison, we can use the body we
+ // build when defining it as input to the exception specification
+ // computation rather than computing a new body.
+ if (auto *FPT = Ty->getAs<FunctionProtoType>()) {
+ if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
+ if (auto *NewFPT = ResolveExceptionSpec(NameInfo.getLoc(), FPT))
+ E->setType(Context.getQualifiedType(NewFPT, Ty.getQualifiers()));
+ }
+ }
+
if (getLangOpts().ObjCWeak && isa<VarDecl>(D) &&
Ty.getObjCLifetime() == Qualifiers::OCL_Weak && !isUnevaluatedContext() &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getBeginLoc()))
@@ -3009,14 +3028,6 @@ ExprResult Sema::BuildDeclarationNameExpr(
QualType type = VD->getType();
if (type.isNull())
return ExprError();
- if (auto *FPT = type->getAs<FunctionProtoType>()) {
- // C++ [except.spec]p17:
- // An exception-specification is considered to be needed when:
- // - in an expression, the function is the unique lookup result or
- // the selected member of a set of overloaded functions.
- ResolveExceptionSpec(Loc, FPT);
- type = VD->getType();
- }
ExprValueKind valueKind = VK_RValue;
switch (D->getKind()) {
@@ -15480,19 +15491,6 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
Func->getMemberSpecializationInfo()))
checkSpecializationVisibility(Loc, Func);
- // C++14 [except.spec]p17:
- // An exception-specification is considered to be needed when:
- // - the function is odr-used or, if it appears in an unevaluated operand,
- // would be odr-used if the expression were potentially-evaluated;
- //
- // Note, we do this even if MightBeOdrUse is false. That indicates that the
- // function is a pure virtual function we're calling, and in that case the
- // function was selected by overload resolution and we need to resolve its
- // exception specification for a
diff erent reason.
- const FunctionProtoType *FPT = Func->getType()->getAs<FunctionProtoType>();
- if (FPT && isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
- ResolveExceptionSpec(Loc, FPT);
-
if (getLangOpts().CUDA)
CheckCUDACall(Loc, Func);
@@ -15601,6 +15599,19 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
});
}
+ // C++14 [except.spec]p17:
+ // An exception-specification is considered to be needed when:
+ // - the function is odr-used or, if it appears in an unevaluated operand,
+ // would be odr-used if the expression were potentially-evaluated;
+ //
+ // Note, we do this even if MightBeOdrUse is false. That indicates that the
+ // function is a pure virtual function we're calling, and in that case the
+ // function was selected by overload resolution and we need to resolve its
+ // exception specification for a
diff erent reason.
+ const FunctionProtoType *FPT = Func->getType()->getAs<FunctionProtoType>();
+ if (FPT && isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
+ ResolveExceptionSpec(Loc, FPT);
+
// If this is the first "real" use, act on that.
if (OdrUse == OdrUseContext::Used && !Func->isUsed(/*CheckUsedAttr=*/false)) {
// Keep track of used but undefined functions.
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index 87114a0fac63..ebfc1ec4b974 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -919,6 +919,18 @@ MemberExpr *Sema::BuildMemberExpr(
VK, OK, getNonOdrUseReasonInCurrentContext(Member));
E->setHadMultipleCandidates(HadMultipleCandidates);
MarkMemberReferenced(E);
+
+ // C++ [except.spec]p17:
+ // An exception-specification is considered to be needed when:
+ // - in an expression the function is the unique lookup result or the
+ // selected member of a set of overloaded functions
+ if (auto *FPT = Ty->getAs<FunctionProtoType>()) {
+ if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
+ if (auto *NewFPT = ResolveExceptionSpec(MemberNameInfo.getLoc(), FPT))
+ E->setType(Context.getQualifiedType(NewFPT, Ty.getQualifiers()));
+ }
+ }
+
return E;
}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 9aa338935502..9c784efed1e4 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -60,14 +60,18 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
// being used.
if (FoundDecl != Fn && S.DiagnoseUseOfDecl(Fn, Loc))
return ExprError();
- if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>())
- S.ResolveExceptionSpec(Loc, FPT);
DeclRefExpr *DRE = new (S.Context)
DeclRefExpr(S.Context, Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo);
if (HadMultipleCandidates)
DRE->setHadMultipleCandidates(true);
S.MarkDeclRefReferenced(DRE, Base);
+ if (auto *FPT = DRE->getType()->getAs<FunctionProtoType>()) {
+ if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
+ S.ResolveExceptionSpec(Loc, FPT);
+ DRE->setType(Fn->getType());
+ }
+ }
return S.ImpCastExprToType(DRE, S.Context.getPointerType(DRE->getType()),
CK_FunctionToPointerDecay);
}
@@ -14436,13 +14440,6 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
UnOp->getOperatorLoc(), false);
}
- // C++ [except.spec]p17:
- // An exception-specification is considered to be needed when:
- // - in an expression the function is the unique lookup result or the
- // selected member of a set of overloaded functions
- if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>())
- ResolveExceptionSpec(E->getExprLoc(), FPT);
-
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
// FIXME: avoid copy.
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
More information about the cfe-commits
mailing list