Avoid undefined behavior with std::minmax and rvalues.

The behavior of std::minmax with rvalue arguments is undefined after the
end of the expression that contains the call to minmax. This code to
special-case the comparisons for ARM vs. Thumb and macOS vs. Darwin was a
little overly clever anyway. Rewrite it to use straightforward comparisons.
This fixes a test failure in Serialization/target-incompatible.swift when
building with a recent version of clang, because these checks were completely
optimized away due to the undefined behavior. rdar://problem/28700005
This commit is contained in:
Bob Wilson
2016-10-11 11:04:52 -07:00
parent a4dd11c337
commit 3d67d824ed

View File

@@ -716,10 +716,14 @@ static bool areCompatibleArchitectures(const llvm::Triple &moduleTarget,
if (moduleTarget.getArch() == ctxTarget.getArch())
return true;
auto archPair = std::minmax(moduleTarget.getArch(), ctxTarget.getArch());
if (archPair == std::minmax(llvm::Triple::arm, llvm::Triple::thumb))
// Special case: ARM and Thumb are compatible.
const llvm::Triple::ArchType moduleArch = moduleTarget.getArch();
const llvm::Triple::ArchType ctxArch = ctxTarget.getArch();
if ((moduleArch == llvm::Triple::arm && ctxArch == llvm::Triple::thumb) ||
(moduleArch == llvm::Triple::thumb && ctxArch == llvm::Triple::arm))
return true;
if (archPair == std::minmax(llvm::Triple::armeb, llvm::Triple::thumbeb))
if ((moduleArch == llvm::Triple::armeb && ctxArch == llvm::Triple::thumbeb) ||
(moduleArch == llvm::Triple::thumbeb && ctxArch == llvm::Triple::armeb))
return true;
return false;
@@ -730,8 +734,11 @@ static bool areCompatibleOSs(const llvm::Triple &moduleTarget,
if (moduleTarget.getOS() == ctxTarget.getOS())
return true;
auto osPair = std::minmax(moduleTarget.getOS(), ctxTarget.getOS());
if (osPair == std::minmax(llvm::Triple::Darwin, llvm::Triple::MacOSX))
// Special case: macOS and Darwin are compatible.
const llvm::Triple::OSType moduleOS = moduleTarget.getOS();
const llvm::Triple::OSType ctxOS = ctxTarget.getOS();
if ((moduleOS == llvm::Triple::Darwin && ctxOS == llvm::Triple::MacOSX) ||
(moduleOS == llvm::Triple::MacOSX && ctxOS == llvm::Triple::Darwin))
return true;
return false;