Add support for C++ default arguments, and rework Parse-Sema 
interaction for function parameters, fixing PR2046.

Patch by Doug Gregor!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49369 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index e27015b..8228ece 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -224,9 +224,9 @@
 ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *CD,
                                  SourceLocation L, IdentifierInfo *Id,
                                  QualType T, StorageClass S,
-                                 ScopedDecl *PrevDecl) {
+                                 Expr *DefArg, ScopedDecl *PrevDecl) {
   void *Mem = C.getAllocator().Allocate<ParmVarDecl>();
-  return new (Mem) ParmVarDecl(CD, L, Id, T, S, PrevDecl);
+  return new (Mem) ParmVarDecl(CD, L, Id, T, S, DefArg, PrevDecl);
 }
 
 FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *CD,
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index bc5310c..14666d6 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -226,15 +226,16 @@
 void ParmVarDecl::EmitImpl(llvm::Serializer& S) const {
   VarDecl::EmitImpl(S);
   S.EmitInt(getObjCDeclQualifier());        // From ParmVarDecl.
+  S.EmitOwnedPtr(getDefaultArg());          // From ParmVarDecl.
 }
 
 ParmVarDecl* ParmVarDecl::CreateImpl(Deserializer& D, ASTContext& C) {
   ParmVarDecl* decl =
-    new ParmVarDecl(0, SourceLocation(),NULL,QualType(),None,NULL);
+    new ParmVarDecl(0, SourceLocation(), NULL, QualType(), None, NULL, NULL);
   
   decl->VarDecl::ReadImpl(D, C);
   decl->objcDeclQualifier = static_cast<ObjCDeclQualifier>(D.ReadInt());
-
+  decl->DefaultArg = D.ReadOwnedPtr<Expr>(C);
   return decl;
 }
 
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 5205702..0287aa0 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -337,6 +337,9 @@
     if (getType()->isVoidType())
       return cast<CastExpr>(this)->getSubExpr()->hasLocalSideEffect();
     return false;
+
+  case CXXDefaultArgExprClass:
+    return cast<CXXDefaultArgExpr>(this)->getExpr()->hasLocalSideEffect();
   }     
 }
 
@@ -401,6 +404,8 @@
     return LV_Valid;
   case PreDefinedExprClass:
     return LV_Valid;
+  case CXXDefaultArgExprClass:
+    return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue();
   default:
     break;
   }
@@ -465,6 +470,8 @@
     return cast<ArraySubscriptExpr>(this)->getBase()->hasGlobalStorage();
   case PreDefinedExprClass:
     return true;
+  case CXXDefaultArgExprClass:
+    return cast<CXXDefaultArgExpr>(this)->getExpr()->hasGlobalStorage();
   }
 }
 
@@ -636,6 +643,8 @@
     }
     return true;
   }
+  case CXXDefaultArgExprClass:
+    return cast<CXXDefaultArgExpr>(this)->getExpr()->isConstantExpr(Ctx, Loc);
   }
 }
 
@@ -981,6 +990,9 @@
       return false;
     break;
   }
+  case CXXDefaultArgExprClass:
+    return cast<CXXDefaultArgExpr>(this)
+             ->isIntegerConstantExpr(Result, Ctx, Loc, isEvaluated);
   }
 
   // Cases that are valid constant exprs fall through to here.
@@ -1009,6 +1021,9 @@
     // Accept ((void*)0) as a null pointer constant, as many other
     // implementations do.
     return PE->getSubExpr()->isNullPointerConstant(Ctx);
+  } else if (const CXXDefaultArgExpr *DefaultArg = dyn_cast<CXXDefaultArgExpr>(this)) {
+    // See through default argument expressions
+    return DefaultArg->getExpr()->isNullPointerConstant(Ctx);
   }
   
   // This expression must be an integer type.
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 3bc32e7..03faf8b 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -45,3 +45,11 @@
     return reinterpret_cast<Stmt**>(&Op)+0;
   return reinterpret_cast<Stmt**>(&Op)+1;
 }
+
+// CXXDefaultArgExpr
+Stmt::child_iterator CXXDefaultArgExpr::child_begin() {
+  return reinterpret_cast<Stmt**>(Param->getDefaultArg());
+}
+Stmt::child_iterator CXXDefaultArgExpr::child_end() {
+  return reinterpret_cast<Stmt**>(Param->getDefaultArg())+1;
+}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index ba82b7f..a76fd1f 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -658,6 +658,11 @@
   PrintExpr(Call->getCallee());
   OS << "(";
   for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) {
+    if (isa<CXXDefaultArgExpr>(Call->getArg(i))) {
+      // Don't print any defaulted arguments
+      break;
+    }
+
     if (i) OS << ", ";
     PrintExpr(Call->getArg(i));
   }
@@ -789,6 +794,10 @@
   }
 }
 
+void StmtPrinter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Node) {
+  // Nothing to print: we picked up the default argument
+}
+
 // Obj-C 
 
 void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp
index 41569df..7058c0c 100644
--- a/lib/AST/StmtSerialization.cpp
+++ b/lib/AST/StmtSerialization.cpp
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "llvm/Bitcode/Serialize.h"
 #include "llvm/Bitcode/Deserialize.h"
 
@@ -185,6 +186,13 @@
       
     case ObjCStringLiteralClass:
       return ObjCStringLiteral::CreateImpl(D, C);
+      
+    //==--------------------------------------==//
+    //    C++
+    //==--------------------------------------==//
+    case CXXDefaultArgExprClass:
+      return CXXDefaultArgExpr::CreateImpl(D, C);
+      
   }
 }
 
@@ -1002,3 +1010,16 @@
   StringLiteral* String = cast<StringLiteral>(D.ReadOwnedPtr<Stmt>(C));
   return new ObjCStringLiteral(String,T,L);
 }
+
+//===----------------------------------------------------------------------===//
+//   C++ Serialization
+//===----------------------------------------------------------------------===//
+void CXXDefaultArgExpr::EmitImpl(Serializer& S) const {
+  S.EmitPtr(Param);
+}
+
+CXXDefaultArgExpr *CXXDefaultArgExpr::CreateImpl(Deserializer& D, ASTContext& C) {
+  ParmVarDecl* Param = 0;
+  D.ReadPtr(Param, false);
+  return new CXXDefaultArgExpr(Param);
+}