Author: rsmith Date: Wed Dec 14 20:35:39 2016 New Revision: 289754 URL: http://llvm.org/viewvc/llvm-project?rev=289754&view=rev Log: [c++1z] Permit constant evaluation of a call through a function pointer whose type differs from the type of the actual function due to having a different exception specification.
Modified: cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/SemaCXX/constant-expression-cxx1z.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=289754&r1=289753&r2=289754&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Wed Dec 14 20:35:39 2016 @@ -1109,6 +1109,10 @@ public: /// \brief Change the result type of a function type once it is deduced. void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType); + /// \brief Determine whether two function types are the same, ignoring + /// exception specifications in cases where they're part of the type. + bool hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U); + /// \brief Change the exception specification on a function once it is /// delay-parsed, instantiated, or computed. void adjustExceptionSpec(FunctionDecl *FD, Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=289754&r1=289753&r2=289754&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Wed Dec 14 20:35:39 2016 @@ -2382,6 +2382,14 @@ static QualType getFunctionTypeWithExcep Proto->getExtProtoInfo().withExceptionSpec(ESI)); } +bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T, + QualType U) { + return hasSameType(T, U) || + (getLangOpts().CPlusPlus1z && + hasSameType(getFunctionTypeWithExceptionSpec(*this, T, EST_None), + getFunctionTypeWithExceptionSpec(*this, U, EST_None))); +} + void ASTContext::adjustExceptionSpec( FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI, bool AsWritten) { Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=289754&r1=289753&r2=289754&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Dec 14 20:35:39 2016 @@ -4434,8 +4434,11 @@ public: } // Don't call function pointers which have been cast to some other type. - if (!Info.Ctx.hasSameType(CalleeType->getPointeeType(), FD->getType())) + // Per DR (no number yet), the caller and callee can differ in noexcept. + if (!Info.Ctx.hasSameFunctionTypeIgnoringExceptionSpec( + CalleeType->getPointeeType(), FD->getType())) { return Error(E); + } } else return Error(E); Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=289754&r1=289753&r2=289754&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Dec 14 20:35:39 2016 @@ -9076,27 +9076,16 @@ bool Sema::CheckFunctionDeclaration(Scop ASTContext::GetBuiltinTypeError Error; LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier()); QualType T = Context.GetBuiltinType(BuiltinID, Error); - if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) { - auto WithoutExceptionSpec = [&](QualType T) -> QualType { - auto *Proto = T->getAs<FunctionProtoType>(); - if (!Proto) - return T; - return Context.getFunctionType( - Proto->getReturnType(), Proto->getParamTypes(), - Proto->getExtProtoInfo().withExceptionSpec(EST_None)); - }; - - // If the type of the builtin differs only in its exception - // specification, that's OK. - // FIXME: If the types do differ in this way, it would be better to - // retain the 'noexcept' form of the type. - if (!getLangOpts().CPlusPlus1z || - !Context.hasSameType(WithoutExceptionSpec(T), - WithoutExceptionSpec(NewFD->getType()))) - // The type of this function differs from the type of the builtin, - // so forget about the builtin entirely. - Context.BuiltinInfo.forgetBuiltin(BuiltinID, Context.Idents); - } + // If the type of the builtin differs only in its exception + // specification, that's OK. + // FIXME: If the types do differ in this way, it would be better to + // retain the 'noexcept' form of the type. + if (!T.isNull() && + !Context.hasSameFunctionTypeIgnoringExceptionSpec(T, + NewFD->getType())) + // The type of this function differs from the type of the builtin, + // so forget about the builtin entirely. + Context.BuiltinInfo.forgetBuiltin(BuiltinID, Context.Idents); } // If this function is declared as being extern "C", then check to see if Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx1z.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx1z.cpp?rev=289754&r1=289753&r2=289754&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/constant-expression-cxx1z.cpp (original) +++ cfe/trunk/test/SemaCXX/constant-expression-cxx1z.cpp Wed Dec 14 20:35:39 2016 @@ -28,7 +28,9 @@ namespace BaseClassAggregateInit { namespace NoexceptFunctionTypes { template<typename T> constexpr bool f() noexcept(true) { return true; } + constexpr bool (*fp)() = f<int>; static_assert(f<int>()); + static_assert(fp()); template<typename T> struct A { constexpr bool f() noexcept(true) { return true; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits