forked from OSchip/llvm-project
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:
parent
c9f727bb85
commit
1d73d1aaa1
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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); }();
|
||||
}
|
Loading…
Reference in New Issue