Add a new attribute, fortify_stdlib

This attribute applies to declarations of C stdlib functions
(sprintf, memcpy...) that have known fortified variants
(__sprintf_chk, __memcpy_chk, ...). When applied, clang will emit
calls to the fortified variant functions instead of calls to the
defaults.

In GCC, this is done by adding gnu_inline-style wrapper functions,
but that doesn't work for us for variadic functions because we don't
support __builtin_va_arg_pack (and have no intention to).

This attribute takes two arguments, the first is 'type' argument
passed through to __builtin_object_size, and the second is a flag
argument that gets passed through to the variadic checking variants.

rdar://47905754

Differential revision: https://reviews.llvm.org/D57918

llvm-svn: 353765
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index a528bff..fd5a6ab 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -1474,6 +1474,86 @@
   return RValue::get(Builder.CreateCall(F, { Src, Src, ShiftAmt }));
 }
 
+/// For a call to a builtin C standard library function, emit a call to a
+/// fortified variant using __builtin_object_size. For instance, instead of
+/// emitting `sprintf(buf, "%d", 32)`, this function would emit
+/// `__sprintf_chk(buf, Flag, __builtin_object_size(buf, 0), "%d", 32)`.
+RValue CodeGenFunction::emitFortifiedStdLibCall(CodeGenFunction &CGF,
+                                                const CallExpr *CE,
+                                                unsigned BuiltinID,
+                                                unsigned BOSType,
+                                                unsigned Flag) {
+  SmallVector<llvm::Value *, 8> ArgVals;
+  for (const Expr *Arg : CE->arguments())
+    ArgVals.push_back(EmitScalarExpr(Arg));
+
+  llvm::Value *FlagVal = llvm::ConstantInt::get(IntTy, Flag);
+  auto emitObjSize = [&]() {
+    return evaluateOrEmitBuiltinObjectSize(CE->getArg(0), BOSType, SizeTy,
+                                           ArgVals[0], false);
+  };
+
+  unsigned FortifiedVariantID = Builtin::getFortifiedVariantFunction(BuiltinID);
+  assert(FortifiedVariantID != 0 && "Should be diagnosed in Sema");
+
+  // Adjust ArgVals to include a __builtin_object_size(n) or flag argument at
+  // the right position. Variadic printf-like functions take a flag and object
+  // size (if they're printing to a string) before the format string, and all
+  // other functions just take the object size as their last argument. The
+  // object size, if present, always corresponds to the first argument.
+  switch (BuiltinID) {
+  case Builtin::BImemcpy:
+  case Builtin::BImemmove:
+  case Builtin::BImemset:
+  case Builtin::BIstpcpy:
+  case Builtin::BIstrcat:
+  case Builtin::BIstrcpy:
+  case Builtin::BIstrlcat:
+  case Builtin::BIstrlcpy:
+  case Builtin::BIstrncat:
+  case Builtin::BIstrncpy:
+  case Builtin::BIstpncpy:
+    ArgVals.push_back(emitObjSize());
+    break;
+
+  case Builtin::BIsnprintf:
+  case Builtin::BIvsnprintf:
+    ArgVals.insert(ArgVals.begin() + 2, FlagVal);
+    ArgVals.insert(ArgVals.begin() + 3, emitObjSize());
+    break;
+
+  case Builtin::BIsprintf:
+  case Builtin::BIvsprintf:
+    ArgVals.insert(ArgVals.begin() + 1, FlagVal);
+    ArgVals.insert(ArgVals.begin() + 2, emitObjSize());
+    break;
+
+  case Builtin::BIfprintf:
+  case Builtin::BIvfprintf:
+    ArgVals.insert(ArgVals.begin() + 1, FlagVal);
+    break;
+
+  case Builtin::BIprintf:
+  case Builtin::BIvprintf:
+    ArgVals.insert(ArgVals.begin(), FlagVal);
+    break;
+
+  default:
+    llvm_unreachable("Unknown fortified builtin?");
+  }
+
+  ASTContext::GetBuiltinTypeError Err;
+  QualType VariantTy = getContext().GetBuiltinType(FortifiedVariantID, Err);
+  assert(Err == ASTContext::GE_None && "Should not codegen an error");
+  auto *LLVMVariantTy = cast<llvm::FunctionType>(ConvertType(VariantTy));
+  StringRef VariantName = getContext().BuiltinInfo.getName(FortifiedVariantID) +
+                          strlen("__builtin_");
+
+  llvm::Value *V = Builder.CreateCall(
+      CGM.CreateRuntimeFunction(LLVMVariantTy, VariantName), ArgVals);
+  return RValue::get(V);
+}
+
 RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
                                         const CallExpr *E,
                                         ReturnValueSlot ReturnValue) {
@@ -1490,6 +1570,10 @@
                                                Result.Val.getFloat()));
   }
 
+  if (const auto *FortifyAttr = FD->getAttr<FortifyStdLibAttr>())
+    return emitFortifiedStdLibCall(*this, E, BuiltinID, FortifyAttr->getType(),
+                                   FortifyAttr->getFlag());
+
   // There are LLVM math intrinsics/instructions corresponding to math library
   // functions except the LLVM op will never set errno while the math library
   // might. Also, math builtins have the same semantics as their math library