]> granicus.if.org Git - clang/commitdiff
PR14995: Allow a dependent type as the second parameter of operator++ and
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 30 Jan 2014 22:24:05 +0000 (22:24 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 30 Jan 2014 22:24:05 +0000 (22:24 +0000)
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
test/SemaCXX/overloaded-operator.cpp

index cde6d9dc75249ca8d2c6a8c4a31529b069aab84b..9b6407b0b28c61ee6a9c7f0b7b6804b184cb1bba 100644 (file)
@@ -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<BuiltinType>())
-      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);
index 99105cb5b60bcf60c169f5af44ed206af4feeddc..cd2b2d3e7ae26eb47d44a4769304ae4201002cd0 100644 (file)
@@ -452,3 +452,58 @@ namespace PR7681 {
     Result = 1; // expected-error {{no viable overloaded '='}} // expected-note {{type 'PointerUnion<int *, float *>' is incomplete}}
   }
 }
+
+namespace PR14995 {
+  struct B {};
+  template<typename ...T> void operator++(B, T...) {}
+
+  void f() {
+    B b;
+    b++;  // ok
+    ++b;  // ok
+  }
+
+  template<typename... T>
+  struct C {
+    void operator-- (T...) {}
+  };
+
+  void g() {
+    C<int> postfix;
+    C<> prefix;
+    postfix--;  // ok
+    --prefix;  // ok
+  }
+
+  struct D {};
+  template<typename T> void operator++(D, T) {}
+
+  void h() {
+    D d;
+    d++;  // ok
+    ++d; // expected-error{{cannot increment value of type 'PR14995::D'}}
+  }
+
+  template<typename...T> struct E {
+    void operator++(T...) {} // expected-error{{parameter of overloaded post-increment operator must have type 'int' (not 'char')}}
+  };
+
+  E<char> e; // expected-note {{in instantiation of template class 'PR14995::E<char>' requested here}}
+  
+  struct F {
+    template<typename... T>
+    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++<int, int>' 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++<char>' requested here}}
+  // expected-error@-7 {{no matching member function for call to 'operator++'}}
+  // expected-note@-12 {{candidate template ignored: substitution failure}}
+} // namespace PR14995
+