forked from OSchip/llvm-project
[Sema] Fix a crash on variadic enable_if functions.
Currently, when trying to evaluate an enable_if condition, we try to evaluate all arguments a user passes to a function. Given that we can't use variadic arguments from said condition anyway, not converting them is a reasonable thing to do. So, this patch makes us ignore any varargs when attempting to check an enable_if condition. We'd crash because, in order to convert an argument, we need its ParmVarDecl. Variadic arguments don't have ParmVarDecls. llvm-svn: 278471
This commit is contained in:
parent
4f7500bfc2
commit
53b938da5a
|
@ -5974,8 +5974,12 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
|
|||
SmallVector<Expr *, 16> ConvertedArgs;
|
||||
bool InitializationFailed = false;
|
||||
|
||||
// Ignore any variadic parameters. Converting them is pointless, since the
|
||||
// user can't refer to them in the enable_if condition.
|
||||
unsigned ArgSizeNoVarargs = std::min(Function->param_size(), Args.size());
|
||||
|
||||
// Convert the arguments.
|
||||
for (unsigned I = 0, E = Args.size(); I != E; ++I) {
|
||||
for (unsigned I = 0; I != ArgSizeNoVarargs; ++I) {
|
||||
ExprResult R;
|
||||
if (I == 0 && !MissingImplicitThis && isa<CXXMethodDecl>(Function) &&
|
||||
!cast<CXXMethodDecl>(Function)->isStatic() &&
|
||||
|
|
|
@ -149,4 +149,25 @@ void PR27122_ext() {
|
|||
regular_enable_if(1, 2); // expected-error{{too many arguments}}
|
||||
regular_enable_if(); // expected-error{{too few arguments}}
|
||||
}
|
||||
|
||||
// We had a bug where we'd crash upon trying to evaluate varargs.
|
||||
void variadic_enable_if(int a, ...) __attribute__((enable_if(a, ""))); // expected-note 6 {{disabled}}
|
||||
void variadic_test() {
|
||||
variadic_enable_if(1);
|
||||
variadic_enable_if(1, 2);
|
||||
variadic_enable_if(1, "c", 3);
|
||||
|
||||
variadic_enable_if(0); // expected-error{{no matching}}
|
||||
variadic_enable_if(0, 2); // expected-error{{no matching}}
|
||||
variadic_enable_if(0, "c", 3); // expected-error{{no matching}}
|
||||
|
||||
int m;
|
||||
variadic_enable_if(1);
|
||||
variadic_enable_if(1, m);
|
||||
variadic_enable_if(1, m, "c");
|
||||
|
||||
variadic_enable_if(0); // expected-error{{no matching}}
|
||||
variadic_enable_if(0, m); // expected-error{{no matching}}
|
||||
variadic_enable_if(0, m, 3); // expected-error{{no matching}}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -417,3 +417,26 @@ template <int N> constexpr int callTemplated() { return templated<N>(); }
|
|||
constexpr int B = callTemplated<0>(); // expected-error{{initialized by a constant expression}} expected-error@-2{{no matching function for call to 'templated'}} expected-note{{in instantiation of function template}} expected-note@-9{{candidate disabled}}
|
||||
static_assert(callTemplated<1>() == 1, "");
|
||||
}
|
||||
|
||||
namespace variadic {
|
||||
void foo(int a, int b = 0, ...) __attribute__((enable_if(a && b, ""))); // expected-note 6{{disabled}}
|
||||
|
||||
void testFoo() {
|
||||
foo(1, 1);
|
||||
foo(1, 1, 2);
|
||||
foo(1, 1, 2, 3);
|
||||
|
||||
foo(1, 0); // expected-error{{no matching}}
|
||||
foo(1, 0, 2); // expected-error{{no matching}}
|
||||
foo(1, 0, 2, 3); // expected-error{{no matching}}
|
||||
|
||||
int m;
|
||||
foo(1, 1);
|
||||
foo(1, 1, m);
|
||||
foo(1, 1, m, 3);
|
||||
|
||||
foo(1, 0); // expected-error{{no matching}}
|
||||
foo(1, 0, m); // expected-error{{no matching}}
|
||||
foo(1, 0, m, 3); // expected-error{{no matching}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue