Implement a little bit of cleanup and a lot more of the base work
behind implicit moves. We now correctly identify move constructors and
assignment operators and update bits on the record correctly. Generation
of implicit moves (declarations or definitions) is not yet supported.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132080 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 4f4d949..c28e354 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -1546,6 +1546,13 @@
   /// which declarations were built.
   static unsigned NumImplicitCopyConstructorsDeclared;
 
+  /// \brief The number of implicitly-declared move constructors.
+  static unsigned NumImplicitMoveConstructors;
+
+  /// \brief The number of implicitly-declared move constructors for
+  /// which declarations were built.
+  static unsigned NumImplicitMoveConstructorsDeclared;
+
   /// \brief The number of implicitly-declared copy assignment operators.
   static unsigned NumImplicitCopyAssignmentOperators;
   
@@ -1553,6 +1560,13 @@
   /// which declarations were built.
   static unsigned NumImplicitCopyAssignmentOperatorsDeclared;
 
+  /// \brief The number of implicitly-declared move assignment operators.
+  static unsigned NumImplicitMoveAssignmentOperators;
+  
+  /// \brief The number of implicitly-declared move assignment operators for 
+  /// which declarations were built.
+  static unsigned NumImplicitMoveAssignmentOperatorsDeclared;
+
   /// \brief The number of implicitly-declared destructors.
   static unsigned NumImplicitDestructors;
   
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 51fc729..096ace7 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -278,10 +278,18 @@
     /// user-declared copy constructor.
     bool UserDeclaredCopyConstructor : 1;
 
+    /// UserDeclareMoveConstructor - True when this class has a
+    /// user-declared move constructor.
+    bool UserDeclaredMoveConstructor : 1;
+
     /// UserDeclaredCopyAssignment - True when this class has a
     /// user-declared copy assignment operator.
     bool UserDeclaredCopyAssignment : 1;
 
+    /// UserDeclareMoveAssignment - True when this class has a
+    /// user-declared move assignment.
+    bool UserDeclaredMoveAssignment : 1;
+
     /// UserDeclaredDestructor - True when this class has a
     /// user-declared destructor.
     bool UserDeclaredDestructor : 1;
@@ -448,9 +456,15 @@
 
     /// \brief Whether we have already declared the copy constructor.
     bool DeclaredCopyConstructor : 1;
+
+    /// \brief Whether we have already declared the move constructor.
+    bool DeclaredMoveConstructor : 1;
     
     /// \brief Whether we have already declared the copy-assignment operator.
     bool DeclaredCopyAssignment : 1;
+
+    /// \brief Whether we have already declared the move-assignment operator.
+    bool DeclaredMoveAssignment : 1;
     
     /// \brief Whether we have already declared a destructor within the class.
     bool DeclaredDestructor : 1;
@@ -695,11 +709,13 @@
 
   /// hasConstCopyConstructor - Determines whether this class has a
   /// copy constructor that accepts a const-qualified argument.
-  bool hasConstCopyConstructor(const ASTContext &Context) const;
+  bool hasConstCopyConstructor() const;
 
   /// getCopyConstructor - Returns the copy constructor for this class
-  CXXConstructorDecl *getCopyConstructor(const ASTContext &Context,
-                                         unsigned TypeQuals) const;
+  CXXConstructorDecl *getCopyConstructor(unsigned TypeQuals) const;
+
+  /// getMoveConstructor - Returns the move constructor for this class
+  CXXConstructorDecl *getMoveConstructor() const; 
 
   /// \brief Retrieve the copy-assignment operator for this class, if available.
   ///
@@ -712,6 +728,10 @@
   /// \returns The copy-assignment operator that can be invoked, or NULL if
   /// a unique copy-assignment operator could not be found.
   CXXMethodDecl *getCopyAssignmentOperator(bool ArgIsConst) const;
+
+  /// getMoveAssignmentOperator - Returns the move assignment operator for this
+  /// class
+  CXXMethodDecl *getMoveAssignmentOperator() const;
   
   /// hasUserDeclaredConstructor - Whether this class has any
   /// user-declared constructors. When true, a default constructor
@@ -740,7 +760,27 @@
   bool hasDeclaredCopyConstructor() const {
     return data().DeclaredCopyConstructor;
   }
-  
+
+  /// hasUserDeclaredMoveOperation - Whether this class has a user-
+  /// declared move constructor or assignment operator. When false, a
+  /// move constructor and assignment operator may be implicitly declared.
+  bool hasUserDeclaredMoveOperation() const {
+    return data().UserDeclaredMoveConstructor ||
+           data().UserDeclaredMoveAssignment;
+  }
+
+  /// \brief Determine whether this class has had a move constructor
+  /// declared by the user.
+  bool hasUserDeclaredMoveConstructor() const {
+    return data().UserDeclaredMoveConstructor;
+  }
+
+  /// \brief Determine whether this class has had a move constructor
+  /// declared.
+  bool hasDeclaredMoveConstructor() const {
+    return data().DeclaredMoveConstructor;
+  }
+
   /// hasUserDeclaredCopyAssignment - Whether this class has a
   /// user-declared copy assignment operator. When false, a copy
   /// assigment operator will be implicitly declared.
@@ -755,7 +795,19 @@
   bool hasDeclaredCopyAssignment() const {
     return data().DeclaredCopyAssignment;
   }
-  
+
+  /// \brief Determine whether this class has had a move assignment
+  /// declared by the user.
+  bool hasUserDeclaredMoveAssignment() const {
+    return data().UserDeclaredMoveAssignment;
+  }
+
+  /// hasDeclaredMoveAssignment - Whether this class has a
+  /// declared move assignment operator.
+  bool hasDeclaredMoveAssignment() const {
+    return data().DeclaredMoveAssignment;
+  }
+
   /// hasUserDeclaredDestructor - Whether this class has a
   /// user-declared destructor. When false, a destructor will be
   /// implicitly declared.
@@ -1225,6 +1277,9 @@
   /// \brief Determine whether this is a copy-assignment operator, regardless
   /// of whether it was declared implicitly or explicitly.
   bool isCopyAssignmentOperator() const;
+
+  /// \brief Determine whether this is a move assignment operator.
+  bool isMoveAssignmentOperator() const;
   
   const CXXMethodDecl *getCanonicalDecl() const {
     return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 2cbfd9f..be76a4a 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1118,7 +1118,9 @@
     CXXDefaultConstructor = 0,
     CXXCopyConstructor = 1,
     CXXCopyAssignment = 2,
-    CXXDestructor = 3
+    CXXDestructor = 3,
+    CXXMoveConstructor = 4,
+    CXXMoveAssignment = 5
   };
   bool CheckNontrivialField(FieldDecl *FD);
   void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem);
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index d5003be..1535efe 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -39,8 +39,12 @@
 unsigned ASTContext::NumImplicitDefaultConstructorsDeclared;
 unsigned ASTContext::NumImplicitCopyConstructors;
 unsigned ASTContext::NumImplicitCopyConstructorsDeclared;
+unsigned ASTContext::NumImplicitMoveConstructors;
+unsigned ASTContext::NumImplicitMoveConstructorsDeclared;
 unsigned ASTContext::NumImplicitCopyAssignmentOperators;
 unsigned ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
+unsigned ASTContext::NumImplicitMoveAssignmentOperators;
+unsigned ASTContext::NumImplicitMoveAssignmentOperatorsDeclared;
 unsigned ASTContext::NumImplicitDestructors;
 unsigned ASTContext::NumImplicitDestructorsDeclared;
 
@@ -318,9 +322,17 @@
   fprintf(stderr, "  %u/%u implicit copy constructors created\n",
           NumImplicitCopyConstructorsDeclared, 
           NumImplicitCopyConstructors);
+  if (getLangOptions().CPlusPlus)
+    fprintf(stderr, "  %u/%u implicit move constructors created\n",
+            NumImplicitMoveConstructorsDeclared, 
+            NumImplicitMoveConstructors);
   fprintf(stderr, "  %u/%u implicit copy assignment operators created\n",
           NumImplicitCopyAssignmentOperatorsDeclared, 
           NumImplicitCopyAssignmentOperators);
+  if (getLangOptions().CPlusPlus)
+    fprintf(stderr, "  %u/%u implicit move assignment operators created\n",
+            NumImplicitMoveAssignmentOperatorsDeclared, 
+            NumImplicitMoveAssignmentOperators);
   fprintf(stderr, "  %u/%u implicit destructors created\n",
           NumImplicitDestructorsDeclared, NumImplicitDestructors);
   
@@ -3717,7 +3729,7 @@
   if (getLangOptions().CPlusPlus) {
     if (const RecordType *RT = Ty->getAs<RecordType>()) {
       CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-      return RD->hasConstCopyConstructor(*this);
+      return RD->hasConstCopyConstructor();
       
     }
   }
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 43cea51..9e82a1a 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -29,7 +29,8 @@
 
 CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
   : UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
-    UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
+    UserDeclaredMoveConstructor(false), UserDeclaredCopyAssignment(false),
+    UserDeclaredMoveAssignment(false), UserDeclaredDestructor(false),
     Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
     Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),
     HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false),
@@ -39,7 +40,8 @@
     HasTrivialMoveAssignment(true), HasTrivialDestructor(true),
     HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
     UserProvidedDefaultConstructor(false), DeclaredDefaultConstructor(false),
-    DeclaredCopyConstructor(false), DeclaredCopyAssignment(false),
+    DeclaredCopyConstructor(false), DeclaredMoveConstructor(false),
+    DeclaredCopyAssignment(false), DeclaredMoveAssignment(false),
     DeclaredDestructor(false), NumBases(0), NumVBases(0), Bases(), VBases(),
     Definition(D), FirstFriend(0) {
 }
@@ -268,8 +270,8 @@
   return !forallBases(SawBase, 0);
 }
 
-bool CXXRecordDecl::hasConstCopyConstructor(const ASTContext &Context) const {
-  return getCopyConstructor(Context, Qualifiers::Const) != 0;
+bool CXXRecordDecl::hasConstCopyConstructor() const {
+  return getCopyConstructor(Qualifiers::Const) != 0;
 }
 
 bool CXXRecordDecl::isTriviallyCopyable() const {
@@ -312,8 +314,8 @@
   return Cands[Best].first;
 }
 
-CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(const ASTContext &Context,
-                                                      unsigned TypeQuals) const{
+CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(unsigned TypeQuals) const{
+  ASTContext &Context = getASTContext();
   QualType ClassType
     = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
   DeclarationName ConstructorName
@@ -343,6 +345,14 @@
                                         GetBestOverloadCandidateSimple(Found));
 }
 
+CXXConstructorDecl *CXXRecordDecl::getMoveConstructor() const {
+  for (ctor_iterator I = ctor_begin(), E = ctor_end(); I != E; ++I)
+    if (I->isMoveConstructor())
+      return *I;
+
+  return 0;
+}
+
 CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const {
   ASTContext &Context = getASTContext();
   QualType Class = Context.getTypeDeclType(const_cast<CXXRecordDecl *>(this));
@@ -393,6 +403,14 @@
   return GetBestOverloadCandidateSimple(Found);
 }
 
+CXXMethodDecl *CXXRecordDecl::getMoveAssignmentOperator() const {
+  for (method_iterator I = method_begin(), E = method_end(); I != E; ++I)
+    if (I->isMoveAssignmentOperator())
+      return *I;
+
+  return 0;
+}
+
 void CXXRecordDecl::markedVirtualFunctionPure() {
   // C++ [class.abstract]p2: 
   //   A class is abstract if it has at least one pure virtual function.
@@ -459,33 +477,32 @@
       if (ASTMutationListener *L = getASTMutationListener())
         L->AddedCXXImplicitMember(data().Definition, D);
 
+    // If this is a special member function, note that it was added and then
+    // return early.
     if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
-      // If this is the implicit default constructor, note that we have now
-      // declared it.
-      if (Constructor->isDefaultConstructor()) {
+      if (Constructor->isDefaultConstructor())
         data().DeclaredDefaultConstructor = true;
-      }
-      // If this is the implicit copy constructor, note that we have now
-      // declared it.
       else if (Constructor->isCopyConstructor())
         data().DeclaredCopyConstructor = true;
+      else if (Constructor->isMoveConstructor())
+        data().DeclaredMoveConstructor = true;
+      else
+        goto NotASpecialMember;
       return;
-    } 
-
-    if (isa<CXXDestructorDecl>(D)) {
+    } else if (isa<CXXDestructorDecl>(D)) {
       data().DeclaredDestructor = true;
       return;
-    } 
-
-    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
-      // If this is the implicit copy constructor, note that we have now
-      // declared it.
-      // FIXME: Move constructors
-      if (Method->getOverloadedOperator() == OO_Equal)
+    } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+      if (Method->isCopyAssignmentOperator())
         data().DeclaredCopyAssignment = true;
+      else if (Method->isMoveAssignmentOperator())
+        data().DeclaredMoveAssignment = true;
+      else
+        goto NotASpecialMember;
       return;
     }
 
+NotASpecialMember:;
     // Any other implicit declarations are handled like normal declarations.
   }
   
@@ -524,6 +541,9 @@
           UserProvided = true;
         }
       } else if (Constructor->isMoveConstructor()) {
+        data().UserDeclaredMoveConstructor = true;
+        data().DeclaredMoveConstructor = true;
+
         // C++0x [class.copy]p13:
         //   A copy/move constructor for class X is trivial if it is not
         //   user-provided [...]
@@ -579,61 +599,42 @@
   
   // Handle (user-declared) member functions.
   if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
-    if (Method->getOverloadedOperator() == OO_Equal) {
-      // We're interested specifically in copy assignment operators.
-      const FunctionProtoType *FnType 
-        = Method->getType()->getAs<FunctionProtoType>();
-      assert(FnType && "Overloaded operator has no proto function type.");
-      assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
-      
-      // Copy assignment operators must be non-templates.
-      if (Method->getPrimaryTemplate() || FunTmpl)
-        return;
-      
-      ASTContext &Context = getASTContext();
-      QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
-                                             const_cast<CXXRecordDecl*>(this)));
-
-      bool isRValueRefArg = false;
-      QualType ArgType = FnType->getArgType(0);
-      if (const LValueReferenceType *Ref =
-          ArgType->getAs<LValueReferenceType>()) {
-        ArgType = Ref->getPointeeType();
-      } else if (const RValueReferenceType *Ref =
-               ArgType->getAs<RValueReferenceType>()) {
-        ArgType = Ref->getPointeeType();
-        isRValueRefArg = true;
-      }
-      if (!Context.hasSameUnqualifiedType(ClassType, ArgType))
-        return;
-
+    if (Method->isCopyAssignmentOperator()) {
       // C++ [class]p4:
       //   A POD-struct is an aggregate class that [...] has no user-defined
       //   copy assignment operator [...].
       // This is the C++03 bit only.
       data().PlainOldData = false;
 
-      if (!isRValueRefArg) {
-        // This is a copy assignment operator.
+      // This is a copy assignment operator.
 
-        // Suppress the implicit declaration of a copy constructor.
-        data().UserDeclaredCopyAssignment = true;
-        data().DeclaredCopyAssignment = true;
+      // Suppress the implicit declaration of a copy constructor.
+      data().UserDeclaredCopyAssignment = true;
+      data().DeclaredCopyAssignment = true;
 
-        // C++0x [class.copy]p27:
-        //   A copy/move assignment operator for class X is trivial if it is
-        //   neither user-provided nor deleted [...]
-        if (Method->isUserProvided())
-          data().HasTrivialCopyAssignment = false;
-      } else {
-        // This is a move assignment operator.
+      // C++0x [class.copy]p27:
+      //   A copy/move assignment operator for class X is trivial if it is
+      //   neither user-provided nor deleted [...]
+      if (Method->isUserProvided())
+        data().HasTrivialCopyAssignment = false;
 
-        // C++0x [class.copy]p27:
-        //   A copy/move assignment operator for class X is trivial if it is
-        //   neither user-provided nor deleted [...]
-        if (Method->isUserProvided())
-          data().HasTrivialMoveAssignment = false;
-      }
+      return;
+    }
+    
+    if (Method->isMoveAssignmentOperator()) {
+      // This is an extension in C++03 mode, but we'll keep consistency by
+      // taking a move assignment operator to induce non-POD-ness
+      data().PlainOldData = false;
+
+      // This is a move assignment operator.
+      data().UserDeclaredMoveAssignment = true;
+      data().DeclaredMoveAssignment = true;
+
+      // C++0x [class.copy]p27:
+      //   A copy/move assignment operator for class X is trivial if it is
+      //   neither user-provided nor deleted [...]
+      if (Method->isUserProvided())
+        data().HasTrivialMoveAssignment = false;
     }
 
     // Keep the list of conversion functions up-to-date.
@@ -1170,14 +1171,13 @@
 }
 
 bool CXXMethodDecl::isCopyAssignmentOperator() const {
-  // C++0x [class.copy]p19:
+  // C++0x [class.copy]p17:
   //  A user-declared copy assignment operator X::operator= is a non-static 
   //  non-template member function of class X with exactly one parameter of 
   //  type X, X&, const X&, volatile X& or const volatile X&.
   if (/*operator=*/getOverloadedOperator() != OO_Equal ||
       /*non-static*/ isStatic() || 
-      /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() ||
-      /*exactly one parameter*/getNumParams() != 1)
+      /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate())
     return false;
       
   QualType ParamType = getParamDecl(0)->getType();
@@ -1190,6 +1190,26 @@
   return Context.hasSameUnqualifiedType(ClassType, ParamType);
 }
 
+bool CXXMethodDecl::isMoveAssignmentOperator() const {
+  // C++0x [class.copy]p19:
+  //  A user-declared move assignment operator X::operator= is a non-static
+  //  non-template member function of class X with exactly one parameter of type
+  //  X&&, const X&&, volatile X&&, or const volatile X&&.
+  if (getOverloadedOperator() != OO_Equal || isStatic() ||
+      getPrimaryTemplate() || getDescribedFunctionTemplate())
+    return false;
+
+  QualType ParamType = getParamDecl(0)->getType();
+  if (!isa<RValueReferenceType>(ParamType))
+    return false;
+  ParamType = ParamType->getPointeeType();
+
+  ASTContext &Context = getASTContext();
+  QualType ClassType
+    = Context.getCanonicalType(Context.getTypeDeclType(getParent()));
+  return Context.hasSameUnqualifiedType(ClassType, ParamType);
+}
+
 void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) {
   assert(MD->isCanonicalDecl() && "Method is not canonical!");
   assert(!MD->getParent()->isDependentContext() &&
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 41e05d5..8b0ee70 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -7736,7 +7736,15 @@
   case CXXCopyConstructor:
     if (RD->hasUserDeclaredCopyConstructor()) {
       SourceLocation CtorLoc =
-        RD->getCopyConstructor(Context, 0)->getLocation();
+        RD->getCopyConstructor(0)->getLocation();
+      Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+      return;
+    }
+    break;
+
+  case CXXMoveConstructor:
+    if (RD->hasUserDeclaredMoveConstructor()) {
+      SourceLocation CtorLoc = RD->getMoveConstructor()->getLocation();
       Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
       return;
     }
@@ -7752,6 +7760,14 @@
     }
     break;
 
+  case CXXMoveAssignment:
+    if (RD->hasUserDeclaredMoveAssignment()) {
+      SourceLocation AssignLoc = RD->getMoveAssignmentOperator()->getLocation();
+      Diag(AssignLoc, diag::note_nontrivial_user_defined) << QT << member;
+      return;
+    }
+    break;
+
   case CXXDestructor:
     if (RD->hasUserDeclaredDestructor()) {
       SourceLocation DtorLoc = LookupDestructor(RD)->getLocation();
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index e8f2f57..1e3baa2 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -7069,8 +7069,7 @@
     if (!BaseClassDecl->hasDeclaredCopyConstructor())
       DeclareImplicitCopyConstructor(BaseClassDecl);
   
-    HasConstCopyConstructor
-      = BaseClassDecl->hasConstCopyConstructor(Context);
+    HasConstCopyConstructor = BaseClassDecl->hasConstCopyConstructor();
   }
 
   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
@@ -7082,8 +7081,7 @@
     if (!BaseClassDecl->hasDeclaredCopyConstructor())
       DeclareImplicitCopyConstructor(BaseClassDecl);
     
-    HasConstCopyConstructor
-      = BaseClassDecl->hasConstCopyConstructor(Context);
+    HasConstCopyConstructor= BaseClassDecl->hasConstCopyConstructor();
   }
   
   //     -- for all the nonstatic data members of X that are of a
@@ -7101,8 +7099,7 @@
       if (!FieldClassDecl->hasDeclaredCopyConstructor())
         DeclareImplicitCopyConstructor(FieldClassDecl);
 
-      HasConstCopyConstructor
-        = FieldClassDecl->hasConstCopyConstructor(Context);
+      HasConstCopyConstructor = FieldClassDecl->hasConstCopyConstructor();
     }
   }
   //   Otherwise, the implicitly declared copy constructor will have
@@ -7129,7 +7126,7 @@
       DeclareImplicitCopyConstructor(BaseClassDecl);
 
     if (CXXConstructorDecl *CopyConstructor
-                          = BaseClassDecl->getCopyConstructor(Context, Quals))
+                          = BaseClassDecl->getCopyConstructor(Quals))
       ExceptSpec.CalledDecl(CopyConstructor);
   }
   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
@@ -7142,7 +7139,7 @@
       DeclareImplicitCopyConstructor(BaseClassDecl);
 
     if (CXXConstructorDecl *CopyConstructor
-                          = BaseClassDecl->getCopyConstructor(Context, Quals))
+                          = BaseClassDecl->getCopyConstructor(Quals))
       ExceptSpec.CalledDecl(CopyConstructor);
   }
   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
@@ -7157,7 +7154,7 @@
         DeclareImplicitCopyConstructor(FieldClassDecl);
 
       if (CXXConstructorDecl *CopyConstructor
-                          = FieldClassDecl->getCopyConstructor(Context, Quals))
+                          = FieldClassDecl->getCopyConstructor(Quals))
         ExceptSpec.CalledDecl(CopyConstructor);
     }
   }