Author: sberg Date: Thu Jan 4 23:57:12 2018 New Revision: 321859 URL: http://llvm.org/viewvc/llvm-project?rev=321859&view=rev Log: No -fsanitize=function warning when calling noexcept function through non-noexcept pointer in C++17
As discussed in the mail thread <https://groups.google.com/a/isocpp.org/forum/ #!topic/std-discussion/T64_dW3WKUk> "Calling noexcept function throug non- noexcept pointer is undefined behavior?", such a call should not be UB. However, Clang currently warns about it. This change removes exception specifications from the function types recorded for -fsanitize=function, both in the functions themselves and at the call sites. That means that calling a non-noexcept function through a noexcept pointer will also not be flagged as UB. In the review of this change, that was deemed acceptable, at least for now. (See the "TODO" in compiler-rt test/ubsan/TestCases/TypeCheck/Function/function.cpp.) To remove exception specifications from types, the existing internal ASTContext::getFunctionTypeWithExceptionSpec was made public, and some places otherwise unrelated to this change have been adapted to call it, too. This is the cfe part of a patch covering both cfe and compiler-rt. Differential Revision: https://reviews.llvm.org/D40720 Modified: cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/lib/CodeGen/CGExpr.cpp cfe/trunk/lib/CodeGen/CodeGenFunction.cpp cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp cfe/trunk/lib/Sema/SemaOverload.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=321859&r1=321858&r2=321859&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Thu Jan 4 23:57:12 2018 @@ -1162,6 +1162,13 @@ public: /// \brief Change the result type of a function type once it is deduced. void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType); + /// Get a function type and produce the equivalent function type with the + /// specified exception specification. Type sugar that can be present on a + /// declaration of a function with an exception specification is permitted + /// and preserved. Other type sugar (for instance, typedefs) is not. + QualType getFunctionTypeWithExceptionSpec( + QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI); + /// \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); Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=321859&r1=321858&r2=321859&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Thu Jan 4 23:57:12 2018 @@ -2582,26 +2582,24 @@ void ASTContext::adjustDeducedFunctionRe /// specified exception specification. Type sugar that can be present on a /// declaration of a function with an exception specification is permitted /// and preserved. Other type sugar (for instance, typedefs) is not. -static QualType getFunctionTypeWithExceptionSpec( - ASTContext &Context, QualType Orig, - const FunctionProtoType::ExceptionSpecInfo &ESI) { +QualType ASTContext::getFunctionTypeWithExceptionSpec( + QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) { // Might have some parens. if (auto *PT = dyn_cast<ParenType>(Orig)) - return Context.getParenType( - getFunctionTypeWithExceptionSpec(Context, PT->getInnerType(), ESI)); + return getParenType( + getFunctionTypeWithExceptionSpec(PT->getInnerType(), ESI)); // Might have a calling-convention attribute. if (auto *AT = dyn_cast<AttributedType>(Orig)) - return Context.getAttributedType( + return getAttributedType( AT->getAttrKind(), - getFunctionTypeWithExceptionSpec(Context, AT->getModifiedType(), ESI), - getFunctionTypeWithExceptionSpec(Context, AT->getEquivalentType(), - ESI)); + getFunctionTypeWithExceptionSpec(AT->getModifiedType(), ESI), + getFunctionTypeWithExceptionSpec(AT->getEquivalentType(), ESI)); // Anything else must be a function type. Rebuild it with the new exception // specification. const FunctionProtoType *Proto = cast<FunctionProtoType>(Orig); - return Context.getFunctionType( + return getFunctionType( Proto->getReturnType(), Proto->getParamTypes(), Proto->getExtProtoInfo().withExceptionSpec(ESI)); } @@ -2610,8 +2608,8 @@ bool ASTContext::hasSameFunctionTypeIgno QualType U) { return hasSameType(T, U) || (getLangOpts().CPlusPlus17 && - hasSameType(getFunctionTypeWithExceptionSpec(*this, T, EST_None), - getFunctionTypeWithExceptionSpec(*this, U, EST_None))); + hasSameType(getFunctionTypeWithExceptionSpec(T, EST_None), + getFunctionTypeWithExceptionSpec(U, EST_None))); } void ASTContext::adjustExceptionSpec( @@ -2619,7 +2617,7 @@ void ASTContext::adjustExceptionSpec( bool AsWritten) { // Update the type. QualType Updated = - getFunctionTypeWithExceptionSpec(*this, FD->getType(), ESI); + getFunctionTypeWithExceptionSpec(FD->getType(), ESI); FD->setType(Updated); if (!AsWritten) @@ -2630,7 +2628,7 @@ void ASTContext::adjustExceptionSpec( // If the type and the type-as-written differ, we may need to update // the type-as-written too. if (TSInfo->getType() != FD->getType()) - Updated = getFunctionTypeWithExceptionSpec(*this, TSInfo->getType(), ESI); + Updated = getFunctionTypeWithExceptionSpec(TSInfo->getType(), ESI); // FIXME: When we get proper type location information for exceptions, // we'll also have to rebuild the TypeSourceInfo. For now, we just patch Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=321859&r1=321858&r2=321859&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Jan 4 23:57:12 2018 @@ -4479,8 +4479,7 @@ RValue CodeGenFunction::EmitCall(QualTyp CalleeType = getContext().getCanonicalType(CalleeType); - const auto *FnType = - cast<FunctionType>(cast<PointerType>(CalleeType)->getPointeeType()); + auto PointeeType = cast<PointerType>(CalleeType)->getPointeeType(); CGCallee Callee = OrigCallee; @@ -4489,8 +4488,12 @@ RValue CodeGenFunction::EmitCall(QualTyp if (llvm::Constant *PrefixSig = CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) { SanitizerScope SanScope(this); + // Remove any (C++17) exception specifications, to allow calling e.g. a + // noexcept function through a non-noexcept pointer. + auto ProtoTy = + getContext().getFunctionTypeWithExceptionSpec(PointeeType, EST_None); llvm::Constant *FTRTTIConst = - CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), /*ForEH=*/true); + CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true); llvm::Type *PrefixStructTyElems[] = {PrefixSig->getType(), Int32Ty}; llvm::StructType *PrefixStructTy = llvm::StructType::get( CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true); @@ -4530,6 +4533,8 @@ RValue CodeGenFunction::EmitCall(QualTyp } } + const auto *FnType = cast<FunctionType>(PointeeType); + // If we are checking indirect calls and this call is indirect, check that the // function pointer is a member of the bit set for the function type. if (SanOpts.has(SanitizerKind::CFIICall) && Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=321859&r1=321858&r2=321859&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original) +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Thu Jan 4 23:57:12 2018 @@ -924,8 +924,13 @@ void CodeGenFunction::StartFunction(Glob if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) { if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) { if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) { + // Remove any (C++17) exception specifications, to allow calling e.g. a + // noexcept function through a non-noexcept pointer. + auto ProtoTy = + getContext().getFunctionTypeWithExceptionSpec(FD->getType(), + EST_None); llvm::Constant *FTRTTIConst = - CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true); + CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true); llvm::Constant *FTRTTIConstEncoded = EncodeAddrForUseInPrologue(Fn, FTRTTIConst); llvm::Constant *PrologueStructElems[] = {PrologueSig, Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=321859&r1=321858&r2=321859&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original) +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Thu Jan 4 23:57:12 2018 @@ -3435,9 +3435,7 @@ static unsigned extractPBaseFlags(ASTCon if (auto *Proto = Type->getAs<FunctionProtoType>()) { if (Proto->isNothrow(Ctx)) { Flags |= ItaniumRTTIBuilder::PTI_Noexcept; - Type = Ctx.getFunctionType( - Proto->getReturnType(), Proto->getParamTypes(), - Proto->getExtProtoInfo().withExceptionSpec(EST_None)); + Type = Ctx.getFunctionTypeWithExceptionSpec(Type, EST_None); } } Modified: cfe/trunk/lib/Sema/SemaOverload.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=321859&r1=321858&r2=321859&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) +++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Jan 4 23:57:12 2018 @@ -1475,10 +1475,8 @@ bool Sema::IsFunctionConversion(QualType const auto *ToFPT = cast<FunctionProtoType>(ToFn); if (FromFPT->isNothrow(Context) && !ToFPT->isNothrow(Context)) { FromFn = cast<FunctionType>( - Context.getFunctionType(FromFPT->getReturnType(), - FromFPT->getParamTypes(), - FromFPT->getExtProtoInfo().withExceptionSpec( - FunctionProtoType::ExceptionSpecInfo())) + Context.getFunctionTypeWithExceptionSpec(QualType(FromFPT, 0), + EST_None) .getTypePtr()); Changed = true; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits