From 38a24084d06d939965ffc598fe1be1e8a4e63c81 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 30 Jan 2014 22:24:05 +0000 Subject: [PATCH] PR14995: Allow a dependent type as the second parameter of operator++ and operator--, since it might instantiate as 'int' (or, if it's a pack, it might instantiate as an empty pack). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@200496 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclCXX.cpp | 7 ++-- test/SemaCXX/overloaded-operator.cpp | 55 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index cde6d9dc75..9b6407b0b2 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -10909,11 +10909,10 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { // increment operator ++ for objects of that type. if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) { ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1); - bool ParamIsInt = false; - if (const BuiltinType *BT = LastParam->getType()->getAs()) - ParamIsInt = BT->getKind() == BuiltinType::Int; + QualType ParamType = LastParam->getType(); - if (!ParamIsInt) + if (!ParamType->isSpecificBuiltinType(BuiltinType::Int) && + !ParamType->isDependentType()) return Diag(LastParam->getLocation(), diag::err_operator_overload_post_incdec_must_be_int) << LastParam->getType() << (Op == OO_MinusMinus); diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index 99105cb5b6..cd2b2d3e7a 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -452,3 +452,58 @@ namespace PR7681 { Result = 1; // expected-error {{no viable overloaded '='}} // expected-note {{type 'PointerUnion' is incomplete}} } } + +namespace PR14995 { + struct B {}; + template void operator++(B, T...) {} + + void f() { + B b; + b++; // ok + ++b; // ok + } + + template + struct C { + void operator-- (T...) {} + }; + + void g() { + C postfix; + C<> prefix; + postfix--; // ok + --prefix; // ok + } + + struct D {}; + template void operator++(D, T) {} + + void h() { + D d; + d++; // ok + ++d; // expected-error{{cannot increment value of type 'PR14995::D'}} + } + + template struct E { + void operator++(T...) {} // expected-error{{parameter of overloaded post-increment operator must have type 'int' (not 'char')}} + }; + + E e; // expected-note {{in instantiation of template class 'PR14995::E' requested here}} + + struct F { + template + int operator++ (T...) {} + }; + + int k1 = F().operator++(0, 0); + int k2 = F().operator++('0'); + // expected-error@-5 {{overloaded 'operator++' must be a unary or binary operator}} + // expected-note@-3 {{in instantiation of function template specialization 'PR14995::F::operator++' requested here}} + // expected-error@-4 {{no matching member function for call to 'operator++'}} + // expected-note@-8 {{candidate template ignored: substitution failure}} + // expected-error@-9 {{parameter of overloaded post-increment operator must have type 'int' (not 'char')}} + // expected-note@-6 {{in instantiation of function template specialization 'PR14995::F::operator++' requested here}} + // expected-error@-7 {{no matching member function for call to 'operator++'}} + // expected-note@-12 {{candidate template ignored: substitution failure}} +} // namespace PR14995 + -- 2.40.0