From f032001b6e2f297a50502fe7aa545b12afa74cf2 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 20 Jun 2013 02:18:31 +0000 Subject: Add a workaround for a libstdc++-4.2 bug. This header uses return false; in a function returning a pointer. 'false' was a null pointer constant in C++98 but is not in C++11. Punch a very small hole in the initialization rules in C++11 mode to allow this specific case in system headers. llvm-svn: 184395 --- clang/lib/Sema/SemaInit.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'clang/lib/Sema/SemaInit.cpp') diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 4e55da328a9..9d7fcda8fdd 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4135,6 +4135,24 @@ static void TryUserDefinedConversion(Sema &S, } } +/// An egregious hack for compatibility with libstdc++-4.2: in , +/// a function with a pointer return type contains a 'return false;' statement. +/// In C++11, 'false' is not a null pointer, so this breaks the build of any +/// code using that header. +/// +/// Work around this by treating 'return false;' as zero-initializing the result +/// if it's used in a pointer-returning function in a system header. +static bool isLibstdcxxPointerReturnFalseHack(Sema &S, + const InitializedEntity &Entity, + const Expr *Init) { + return S.getLangOpts().CPlusPlus11 && + Entity.getKind() == InitializedEntity::EK_Result && + Entity.getType()->isPointerType() && + isa(Init) && + !cast(Init)->getValue() && + S.getSourceManager().isInSystemHeader(Init->getExprLoc()); +} + /// The non-zero enum values here are indexes into diagnostic alternatives. enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar }; @@ -4571,9 +4589,11 @@ InitializationSequence::InitializationSequence(Sema &S, AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy); } else if (ICS.isBad()) { DeclAccessPair dap; - if (Initializer->getType() == Context.OverloadTy && - !S.ResolveAddressOfOverloadedFunction(Initializer - , DestType, false, dap)) + if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) { + AddZeroInitializationStep(Entity.getType()); + } else if (Initializer->getType() == Context.OverloadTy && + !S.ResolveAddressOfOverloadedFunction(Initializer, DestType, + false, dap)) SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else SetFailed(InitializationSequence::FK_ConversionFailed); -- cgit v1.2.3