]> granicus.if.org Git - clang/commitdiff
Correct behavior of __builtin_*_overflow and constexpr.
authorErich Keane <erich.keane@intel.com>
Wed, 13 Jun 2018 13:25:11 +0000 (13:25 +0000)
committerErich Keane <erich.keane@intel.com>
Wed, 13 Jun 2018 13:25:11 +0000 (13:25 +0000)
Enable these builtins to be called across a lambda
boundary with captureless const/constexpr, as brought up by
Eli here: https://reviews.llvm.org/D48040

Differential Revision: https://reviews.llvm.org/D48053

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334597 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaChecking.cpp
test/SemaCXX/builtins-overflow.cpp [new file with mode: 0644]

index 6a1cbdf621003665a0e99cce36faaa68ba01d8af..dfe4373f33b10a740bb3ff3067a05e1bf2abfa7d 100644 (file)
@@ -197,30 +197,42 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
 
   // First two arguments should be integers.
   for (unsigned I = 0; I < 2; ++I) {
-    Expr *Arg = TheCall->getArg(I);
-    QualType Ty = Arg->getType();
+    ExprResult Arg = TheCall->getArg(I);
+    QualType Ty = Arg.get()->getType();
     if (!Ty->isIntegerType()) {
-      S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_int)
-          << Ty << Arg->getSourceRange();
+      S.Diag(Arg.get()->getLocStart(), diag::err_overflow_builtin_must_be_int)
+          << Ty << Arg.get()->getSourceRange();
       return true;
     }
+    InitializedEntity Entity = InitializedEntity::InitializeParameter(
+        S.getASTContext(), Ty, /*consume*/ false);
+    Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg);
+    if (Arg.isInvalid())
+      return true;
+    TheCall->setArg(I, Arg.get());
   }
 
   // Third argument should be a pointer to a non-const integer.
   // IRGen correctly handles volatile, restrict, and address spaces, and
   // the other qualifiers aren't possible.
   {
-    Expr *Arg = TheCall->getArg(2);
-    QualType Ty = Arg->getType();
+    ExprResult Arg = TheCall->getArg(2);
+    QualType Ty = Arg.get()->getType();
     const auto *PtrTy = Ty->getAs<PointerType>();
     if (!(PtrTy && PtrTy->getPointeeType()->isIntegerType() &&
           !PtrTy->getPointeeType().isConstQualified())) {
-      S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_ptr_int)
-          << Ty << Arg->getSourceRange();
+      S.Diag(Arg.get()->getLocStart(),
+             diag::err_overflow_builtin_must_be_ptr_int)
+          << Ty << Arg.get()->getSourceRange();
       return true;
     }
+    InitializedEntity Entity = InitializedEntity::InitializeParameter(
+        S.getASTContext(), Ty, /*consume*/ false);
+    Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg);
+    if (Arg.isInvalid())
+      return true;
+    TheCall->setArg(2, Arg.get());
   }
-
   return false;
 }
 
diff --git a/test/SemaCXX/builtins-overflow.cpp b/test/SemaCXX/builtins-overflow.cpp
new file mode 100644 (file)
index 0000000..9054cce
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// expected-no-diagnostics
+
+int a() {
+  const int x = 3;
+  static int z;
+  constexpr int *y = &z;
+  return []() { return __builtin_sub_overflow((int)x, (int)x, (int *)y); }();
+}
+int a2() {
+  const int x = 3;
+  static int z;
+  constexpr int *y = &z;
+  return []() { return __builtin_sub_overflow(x, x, y); }();
+}