From 3a8f13ac23e709244ef45e263d376a2d13b173fa Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 3 Dec 2016 00:29:06 +0000 Subject: PR31244: Use the exception specification from the callee's type directly to compute whether a call is noexcept, even if we can't map the callee expression to a called declaration. llvm-svn: 288558 --- clang/lib/Sema/SemaExceptionSpec.cpp | 45 ++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'clang/lib/Sema/SemaExceptionSpec.cpp') diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index e95482679b7..3561bd02b95 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -944,24 +944,37 @@ static CanThrowResult canSubExprsThrow(Sema &S, const Expr *E) { } static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) { - assert(D && "Expected decl"); - - // See if we can get a function type from the decl somehow. - const ValueDecl *VD = dyn_cast(D); - if (!VD) { - // In C++17, we may have a canonical exception specification. If so, use it. - if (auto *FT = E->getType().getCanonicalType()->getAs()) - return FT->isNothrow(S.Context) ? CT_Cannot : CT_Can; - // If we have no clue what we're calling, assume the worst. - return CT_Can; - } - // As an extension, we assume that __attribute__((nothrow)) functions don't // throw. - if (isa(D) && D->hasAttr()) + if (D && isa(D) && D->hasAttr()) return CT_Cannot; - QualType T = VD->getType(); + QualType T; + + // In C++1z, just look at the function type of the callee. + if (S.getLangOpts().CPlusPlus1z && isa(E)) { + E = cast(E)->getCallee(); + T = E->getType(); + if (T->isSpecificPlaceholderType(BuiltinType::BoundMember)) { + // Sadly we don't preserve the actual type as part of the "bound member" + // placeholder, so we need to reconstruct it. + E = E->IgnoreParenImpCasts(); + + // Could be a call to a pointer-to-member or a plain member access. + if (auto *Op = dyn_cast(E)) { + assert(Op->getOpcode() == BO_PtrMemD || Op->getOpcode() == BO_PtrMemI); + T = Op->getRHS()->getType() + ->castAs()->getPointeeType(); + } else { + T = cast(E)->getMemberDecl()->getType(); + } + } + } else if (const ValueDecl *VD = dyn_cast_or_null(D)) + T = VD->getType(); + else + // If we have no clue what we're calling, assume the worst. + return CT_Can; + const FunctionProtoType *FT; if ((FT = T->getAs())) { } else if (const PointerType *PT = T->getAs()) @@ -1053,10 +1066,8 @@ CanThrowResult Sema::canThrow(const Expr *E) { CT = CT_Dependent; else if (isa(CE->getCallee()->IgnoreParens())) CT = CT_Cannot; - else if (CE->getCalleeDecl()) - CT = canCalleeThrow(*this, E, CE->getCalleeDecl()); else - CT = CT_Can; + CT = canCalleeThrow(*this, E, CE->getCalleeDecl()); if (CT == CT_Can) return CT; return mergeCanThrow(CT, canSubExprsThrow(*this, E)); -- cgit v1.2.3