Delay parsing of default arguments of member functions until the class
is completely defined (C++ [class.mem]p2).

Reverse the order in which we process the definitions of member
functions specified inline. This way, we'll get diagnostics in the
order in which the member functions were declared in the class.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61103 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 6ce3ec5..3e42280 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -276,6 +276,7 @@
   virtual void ActOnParamDefaultArgument(DeclTy *param, 
                                          SourceLocation EqualLoc,
                                          ExprTy *defarg);
+  virtual void ActOnParamDefaultArgumentError(DeclTy *param);
   void AddInitializerToDecl(DeclTy *dcl, ExprArg init);
   void ActOnUninitializedDecl(DeclTy *dcl);
   virtual DeclTy *FinalizeDeclaratorGroup(Scope *S, DeclTy *Group);
@@ -960,9 +961,13 @@
 
   virtual void ActOnFinishCXXClassDef(DeclTy *TagDecl);
   
-  
+  virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclTy *Method);
+  virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclTy *Param);
+  virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclTy *Method);
+
   bool CheckConstructorDeclarator(Declarator &D, QualType &R,
                                   FunctionDecl::StorageClass& SC);
+  bool CheckConstructor(CXXConstructorDecl *Constructor);
   bool CheckDestructorDeclarator(Declarator &D, QualType &R,
                                  FunctionDecl::StorageClass& SC);
   bool CheckConversionDeclarator(Declarator &D, QualType &R,
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index fe9ae07..f023fbf 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -134,7 +134,8 @@
   assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");

   assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?");

   PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity());

-  S->setEntity(static_cast<DeclContext*>(SS.getScopeRep()));

+  CurContext = static_cast<DeclContext*>(SS.getScopeRep());

+  S->setEntity(CurContext);

 }

 

 /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously

@@ -147,4 +148,9 @@
   assert(S->getEntity() == SS.getScopeRep() && "Context imbalance!");

   S->setEntity(PreDeclaratorDC);

   PreDeclaratorDC = 0;

+

+  // Reset CurContext to the nearest enclosing context.

+  while (!S->getEntity() && S->getParent())

+    S = S->getParent();

+  CurContext = static_cast<DeclContext*>(S->getEntity());

 }

diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 0d48c62..81a4abe 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1230,30 +1230,8 @@
       }
     }
 
-    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
-      CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(DC);
-
-      // C++ [class.copy]p3:
-      //   A declaration of a constructor for a class X is ill-formed if
-      //   its first parameter is of type (optionally cv-qualified) X and
-      //   either there are no other parameters or else all other
-      //   parameters have default arguments.
-      if ((Constructor->getNumParams() == 1) || 
-          (Constructor->getNumParams() > 1 && 
-           Constructor->getParamDecl(1)->getDefaultArg() != 0)) {
-        QualType ParamType = Constructor->getParamDecl(0)->getType();
-        QualType ClassTy = Context.getTagDeclType(ClassDecl);
-        if (Context.getCanonicalType(ParamType).getUnqualifiedType() 
-              == ClassTy) {
-          Diag(Constructor->getLocation(), diag::err_constructor_byvalue_arg)
-            << SourceRange(Constructor->getParamDecl(0)->getLocation());
-          Constructor->setInvalidDecl();
-        }
-      }
-
-      // Notify the class that we've added a constructor.
-      ClassDecl->addedConstructor(Context, Constructor);
-    }
+    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD))
+      InvalidDecl = InvalidDecl || CheckConstructor(Constructor);
     else if (isa<CXXDestructorDecl>(NewFD))
       cast<CXXRecordDecl>(NewFD->getParent())->setUserDeclaredDestructor(true);
     else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
@@ -2865,6 +2843,9 @@
                               DeclSpec::SCS_mutable,
                             /*PrevDecl=*/0);
 
+  if (getLangOptions().CPlusPlus)
+    CheckExtraCXXDefaultArguments(D);
+
   ProcessDeclAttributes(NewFD, D);
 
   if (D.getInvalidType() || InvalidDecl)
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 6f1683e..184ba15 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -114,6 +114,7 @@
   if (!getLangOptions().CPlusPlus) {
     Diag(EqualLoc, diag::err_param_default_argument)
       << DefaultArg->getSourceRange();
+    Param->setInvalidDecl();
     return;
   }
 
@@ -136,13 +137,21 @@
 
   // Check that the default argument is well-formed
   CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg.get(), this);
-  if (DefaultArgChecker.Visit(DefaultArg.get()))
+  if (DefaultArgChecker.Visit(DefaultArg.get())) {
+    Param->setInvalidDecl();
     return;
+  }
 
   // Okay: add the default argument to the parameter
   Param->setDefaultArg(DefaultArg.take());
 }
 
+/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
+/// the default argument for the parameter param failed.
+void Sema::ActOnParamDefaultArgumentError(DeclTy *param) {
+  ((ParmVarDecl*)param)->setInvalidDecl();
+}
+
 /// CheckExtraCXXDefaultArguments - Check for any extra default
 /// arguments in the declarator, which is not a function declaration
 /// or definition and therefore is not permitted to have default
@@ -165,6 +174,12 @@
           Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
             << Param->getDefaultArg()->getSourceRange();
           Param->setDefaultArg(0);
+        } else if (CachedTokens *Toks 
+                     = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens) {
+          Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
+            << SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation());
+          delete Toks;
+          chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0;
         }
       }
     }
@@ -231,7 +246,9 @@
   for(; p < NumParams; ++p) {
     ParmVarDecl *Param = FD->getParamDecl(p);
     if (!Param->getDefaultArg()) {
-      if (Param->getIdentifier())
+      if (Param->isInvalidDecl())
+        /* We already complained about this parameter. */;
+      else if (Param->getIdentifier())
         Diag(Param->getLocation(), 
              diag::err_param_default_argument_missing_name)
           << Param->getIdentifier();
@@ -401,6 +418,7 @@
 /// any. 'LastInGroup' is non-null for cases where one declspec has multiple
 /// declarators on it.
 ///
+/// FIXME: The note below is out-of-date.
 /// NOTE: Because of CXXFieldDecl's inability to be chained like ScopedDecls, if
 /// an instance field is declared, a new CXXFieldDecl is created but the method
 /// does *not* return it; it returns LastInGroup instead. The other C++ members
@@ -875,8 +893,60 @@
   Consumer.HandleTagDeclDefinition(Rec);
 }
 
+/// ActOnStartDelayedCXXMethodDeclaration - We have completed
+/// parsing a top-level (non-nested) C++ class, and we are now
+/// parsing those parts of the given Method declaration that could
+/// not be parsed earlier (C++ [class.mem]p2), such as default
+/// arguments. This action should enter the scope of the given
+/// Method declaration as if we had just parsed the qualified method
+/// name. However, it should not bring the parameters into scope;
+/// that will be performed by ActOnDelayedCXXMethodParameter.
+void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclTy *Method) {
+  CXXScopeSpec SS;
+  SS.setScopeRep(((FunctionDecl*)Method)->getDeclContext());
+  ActOnCXXEnterDeclaratorScope(S, SS);
+}
+
+/// ActOnDelayedCXXMethodParameter - We've already started a delayed
+/// C++ method declaration. We're (re-)introducing the given
+/// function parameter into scope for use in parsing later parts of
+/// the method declaration. For example, we could see an
+/// ActOnParamDefaultArgument event for this parameter.
+void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclTy *ParamD) {
+  ParmVarDecl *Param = (ParmVarDecl*)ParamD;
+  S->AddDecl(Param);
+  if (Param->getDeclName())
+    IdResolver.AddDecl(Param);
+}
+
+/// ActOnFinishDelayedCXXMethodDeclaration - We have finished
+/// processing the delayed method declaration for Method. The method
+/// declaration is now considered finished. There may be a separate
+/// ActOnStartOfFunctionDef action later (not necessarily
+/// immediately!) for this method, if it was also defined inside the
+/// class body.
+void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclTy *MethodD) {
+  FunctionDecl *Method = (FunctionDecl*)MethodD;
+  CXXScopeSpec SS;
+  SS.setScopeRep(Method->getDeclContext());
+  ActOnCXXExitDeclaratorScope(S, SS);
+
+  // Now that we have our default arguments, check the constructor
+  // again. It could produce additional diagnostics or affect whether
+  // the class has implicitly-declared destructors, among other
+  // things.
+  if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {
+    if (CheckConstructor(Constructor))
+      Constructor->setInvalidDecl();
+  }
+
+  // Check the default arguments, which we may have added.
+  if (!Method->isInvalidDecl())
+    CheckCXXDefaultArguments(Method);
+}
+
 /// CheckConstructorDeclarator - Called by ActOnDeclarator to check
-/// the well-formednes of the constructor declarator @p D with type @p
+/// the well-formedness of the constructor declarator @p D with type @p
 /// R. If there are any errors in the declarator, this routine will
 /// emit diagnostics and return true. Otherwise, it will return
 /// false. Either way, the type @p R will be updated to reflect a
@@ -944,6 +1014,39 @@
   return isInvalid;
 }
 
+/// CheckConstructor - Checks a fully-formed constructor for
+/// well-formedness, issuing any diagnostics required. Returns true if
+/// the constructor declarator is invalid.
+bool Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
+  if (Constructor->isInvalidDecl())
+    return true;
+
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext());
+  bool Invalid = false;
+
+  // C++ [class.copy]p3:
+  //   A declaration of a constructor for a class X is ill-formed if
+  //   its first parameter is of type (optionally cv-qualified) X and
+  //   either there are no other parameters or else all other
+  //   parameters have default arguments.
+  if ((Constructor->getNumParams() == 1) || 
+      (Constructor->getNumParams() > 1 && 
+       Constructor->getParamDecl(1)->getDefaultArg() != 0)) {
+    QualType ParamType = Constructor->getParamDecl(0)->getType();
+    QualType ClassTy = Context.getTagDeclType(ClassDecl);
+    if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
+      Diag(Constructor->getLocation(), diag::err_constructor_byvalue_arg)
+        << SourceRange(Constructor->getParamDecl(0)->getLocation());
+      Invalid = true;
+    }
+  }
+  
+  // Notify the class that we've added a constructor.
+  ClassDecl->addedConstructor(Context, Constructor);
+
+  return Invalid;
+}
+
 /// CheckDestructorDeclarator - Called by ActOnDeclarator to check
 /// the well-formednes of the destructor declarator @p D with type @p
 /// R. If there are any errors in the declarator, this routine will