Correct behavior of __builtin_*_overflow and constexpr.

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

llvm-svn: 334597
This commit is contained in:
Erich Keane 2018-06-13 13:25:11 +00:00
parent c9f727bb85
commit 1d73d1aaa1
2 changed files with 36 additions and 9 deletions

View 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;
}

View File

@ -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); }();
}