Implement support for C++11 in-class initialization of non-static data members.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132878 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 17b7c9d..9094aba 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -3536,7 +3536,8 @@
                                            SourceLocation(), 0,
                                            FieldTypes[i], /*TInfo=*/0,
                                            /*BitWidth=*/0,
-                                           /*Mutable=*/false);
+                                           /*Mutable=*/false,
+                                           /*HasInit=*/false);
       Field->setAccess(AS_public);
       CFConstantStringTypeDecl->addDecl(Field);
     }
@@ -3577,7 +3578,8 @@
                                            SourceLocation(), 0,
                                            FieldTypes[i], /*TInfo=*/0,
                                            /*BitWidth=*/0,
-                                           /*Mutable=*/false);
+                                           /*Mutable=*/false,
+                                           /*HasInit=*/false);
       Field->setAccess(AS_public);
       NSConstantStringTypeDecl->addDecl(Field);
     }
@@ -3616,7 +3618,8 @@
                                            SourceLocation(), 0,
                                            FieldTypes[i], /*TInfo=*/0,
                                            /*BitWidth=*/0,
-                                           /*Mutable=*/false);
+                                           /*Mutable=*/false,
+                                           /*HasInit=*/false);
       Field->setAccess(AS_public);
       ObjCFastEnumerationStateTypeDecl->addDecl(Field);
     }
@@ -3653,7 +3656,8 @@
                                          &Idents.get(FieldNames[i]),
                                          FieldTypes[i], /*TInfo=*/0,
                                          /*BitWidth=*/0,
-                                         /*Mutable=*/false);
+                                         /*Mutable=*/false,
+                                         /*HasInit=*/false);
     Field->setAccess(AS_public);
     T->addDecl(Field);
   }
@@ -3701,7 +3705,8 @@
                                          &Idents.get(FieldNames[i]),
                                          FieldTypes[i], /*TInfo=*/0,
                                          /*BitWidth=*/0,
-                                         /*Mutable=*/false);
+                                         /*Mutable=*/false,
+                                         /*HasInit=*/false);
     Field->setAccess(AS_public);
     T->addDecl(Field);
   }
@@ -3786,7 +3791,8 @@
                                          SourceLocation(),
                                          &Idents.get(FieldNames[i]),
                                          FieldTypes[i], /*TInfo=*/0,
-                                         /*BitWidth=*/0, /*Mutable=*/false);
+                                         /*BitWidth=*/0, /*Mutable=*/false,
+                                         /*HasInit=*/false);
     Field->setAccess(AS_public);
     T->addDecl(Field);
   }
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index fcca95c..100e604 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -2512,9 +2512,12 @@
   FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC,
                                          Importer.Import(D->getInnerLocStart()),
                                          Loc, Name.getAsIdentifierInfo(),
-                                         T, TInfo, BitWidth, D->isMutable());
+                                         T, TInfo, BitWidth, D->isMutable(),
+                                         D->hasInClassInitializer());
   ToField->setAccess(D->getAccess());
   ToField->setLexicalDeclContext(LexicalDC);
+  if (ToField->hasInClassInitializer())
+    ToField->setInClassInitializer(D->getInClassInitializer());
   Importer.Imported(D, ToField);
   LexicalDC->addDecl(ToField);
   return ToField;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 1cad64e..12357c0 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2077,9 +2077,10 @@
 FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC,
                              SourceLocation StartLoc, SourceLocation IdLoc,
                              IdentifierInfo *Id, QualType T,
-                             TypeSourceInfo *TInfo, Expr *BW, bool Mutable) {
+                             TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
+                             bool HasInit) {
   return new (C) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo,
-                           BW, Mutable);
+                           BW, Mutable, HasInit);
 }
 
 bool FieldDecl::isAnonymousStructOrUnion() const {
@@ -2124,10 +2125,17 @@
 
 SourceRange FieldDecl::getSourceRange() const {
   if (isBitField())
-    return SourceRange(getInnerLocStart(), BitWidth->getLocEnd());
+    return SourceRange(getInnerLocStart(), getBitWidth()->getLocEnd());
   return DeclaratorDecl::getSourceRange();
 }
 
+void FieldDecl::setInClassInitializer(Expr *Init) {
+  assert(!InitializerOrBitWidth.getPointer() &&
+         "bit width or initializer already set");
+  InitializerOrBitWidth.setPointer(Init);
+  InitializerOrBitWidth.setInt(0);
+}
+
 //===----------------------------------------------------------------------===//
 // TagDecl Implementation
 //===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 9e82a1a..08ac2a5 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -715,6 +715,22 @@
     if (!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType())
       data().HasNonLiteralTypeFieldsOrBases = true;
 
+    if (Field->hasInClassInitializer()) {
+      // C++0x [class]p5:
+      //   A default constructor is trivial if [...] no non-static data member
+      //   of its class has a brace-or-equal-initializer.
+      data().HasTrivialDefaultConstructor = false;
+
+      // C++0x [dcl.init.aggr]p1:
+      //   An aggregate is a [...] class with [...] no
+      //   brace-or-equal-initializers for non-static data members.
+      data().Aggregate = false;
+
+      // C++0x [class]p10:
+      //   A POD struct is [...] a trivial class.
+      data().PlainOldData = false;
+    }
+
     if (const RecordType *RecordTy = T->getAs<RecordType>()) {
       CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
       if (FieldRec->getDefinition()) {
@@ -1345,11 +1361,21 @@
 SourceLocation CXXCtorInitializer::getSourceLocation() const {
   if (isAnyMemberInitializer() || isDelegatingInitializer())
     return getMemberLocation();
+
+  if (isInClassMemberInitializer())
+    return getAnyMember()->getLocation();
   
   return getBaseClassLoc().getLocalSourceRange().getBegin();
 }
 
 SourceRange CXXCtorInitializer::getSourceRange() const {
+  if (isInClassMemberInitializer()) {
+    FieldDecl *D = getAnyMember();
+    if (Expr *I = D->getInClassInitializer())
+      return I->getSourceRange();
+    return SourceRange();
+  }
+
   return SourceRange(getSourceLocation(), getRParenLoc());
 }
 
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 49f2723..de1b610 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -450,62 +450,67 @@
     if (D->hasAttr<NoReturnAttr>())
       Proto += " __attribute((noreturn))";
     if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) {
-      if (CDecl->getNumCtorInitializers() > 0) {
-        Proto += " : ";
-        Out << Proto;
-        Proto.clear();
-        for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
-             E = CDecl->init_end();
-             B != E; ++B) {
-          CXXCtorInitializer * BMInitializer = (*B);
-          if (B != CDecl->init_begin())
-            Out << ", ";
-          if (BMInitializer->isAnyMemberInitializer()) {
-            FieldDecl *FD = BMInitializer->getAnyMember();
-            Out << FD;
-          } else {
-            Out << QualType(BMInitializer->getBaseClass(),
-                            0).getAsString(Policy);
-          }
+      bool HasInitializerList = false;
+      for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
+           E = CDecl->init_end();
+           B != E; ++B) {
+        CXXCtorInitializer * BMInitializer = (*B);
+        if (BMInitializer->isInClassMemberInitializer())
+          continue;
+
+        if (!HasInitializerList) {
+          Proto += " : ";
+          Out << Proto;
+          Proto.clear();
+          HasInitializerList = true;
+        } else
+          Out << ", ";
+
+        if (BMInitializer->isAnyMemberInitializer()) {
+          FieldDecl *FD = BMInitializer->getAnyMember();
+          Out << FD;
+        } else {
+          Out << QualType(BMInitializer->getBaseClass(),
+                          0).getAsString(Policy);
+        }
+        
+        Out << "(";
+        if (!BMInitializer->getInit()) {
+          // Nothing to print
+        } else {
+          Expr *Init = BMInitializer->getInit();
+          if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
+            Init = Tmp->getSubExpr();
           
-          Out << "(";
-          if (!BMInitializer->getInit()) {
-            // Nothing to print
-          } else {
-            Expr *Init = BMInitializer->getInit();
-            if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
-              Init = Tmp->getSubExpr();
-            
-            Init = Init->IgnoreParens();
-            
-            Expr *SimpleInit = 0;
-            Expr **Args = 0;
-            unsigned NumArgs = 0;
-            if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
-              Args = ParenList->getExprs();
-              NumArgs = ParenList->getNumExprs();
-            } else if (CXXConstructExpr *Construct
-                                          = dyn_cast<CXXConstructExpr>(Init)) {
-              Args = Construct->getArgs();
-              NumArgs = Construct->getNumArgs();
-            } else
-              SimpleInit = Init;
-            
-            if (SimpleInit)
-              SimpleInit->printPretty(Out, Context, 0, Policy, Indentation);
-            else {
-              for (unsigned I = 0; I != NumArgs; ++I) {
-                if (isa<CXXDefaultArgExpr>(Args[I]))
-                  break;
-                
-                if (I)
-                  Out << ", ";
-                Args[I]->printPretty(Out, Context, 0, Policy, Indentation);
-              }
+          Init = Init->IgnoreParens();
+          
+          Expr *SimpleInit = 0;
+          Expr **Args = 0;
+          unsigned NumArgs = 0;
+          if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+            Args = ParenList->getExprs();
+            NumArgs = ParenList->getNumExprs();
+          } else if (CXXConstructExpr *Construct
+                                        = dyn_cast<CXXConstructExpr>(Init)) {
+            Args = Construct->getArgs();
+            NumArgs = Construct->getNumArgs();
+          } else
+            SimpleInit = Init;
+          
+          if (SimpleInit)
+            SimpleInit->printPretty(Out, Context, 0, Policy, Indentation);
+          else {
+            for (unsigned I = 0; I != NumArgs; ++I) {
+              if (isa<CXXDefaultArgExpr>(Args[I]))
+                break;
+              
+              if (I)
+                Out << ", ";
+              Args[I]->printPretty(Out, Context, 0, Policy, Indentation);
             }
           }
-          Out << ")";
         }
+        Out << ")";
       }
     }
     else
@@ -553,6 +558,12 @@
     Out << " : ";
     D->getBitWidth()->printPretty(Out, Context, 0, Policy, Indentation);
   }
+
+  Expr *Init = D->getInClassInitializer();
+  if (!Policy.SuppressInitializers && Init) {
+    Out << " = ";
+    Init->printPretty(Out, Context, 0, Policy, Indentation);
+  }
 }
 
 void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 012701d..9872139 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Lex/LiteralSupport.h"
 #include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaDiagnostic.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
@@ -1653,7 +1654,8 @@
   return R;
 }
 
-static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Decl *D,
+static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Expr *E,
+                                           const Decl *D,
                                            bool NullThrows = true) {
   if (!D)
     return NullThrows ? Expr::CT_Can : Expr::CT_Cannot;
@@ -1683,6 +1685,15 @@
   if (!FT)
     return Expr::CT_Can;
 
+  if (FT->getExceptionSpecType() == EST_Delayed) {
+    assert(isa<CXXConstructorDecl>(D) &&
+           "only constructor exception specs can be unknown");
+    Ctx.getDiagnostics().Report(E->getLocStart(),
+                                diag::err_exception_spec_unknown)
+      << E->getSourceRange();
+    return Expr::CT_Can;
+  }
+
   return FT->isNothrow(Ctx) ? Expr::CT_Cannot : Expr::CT_Can;
 }
 
@@ -1757,7 +1768,7 @@
     else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
       CT = CT_Cannot;
     else
-      CT = CanCalleeThrow(C, CE->getCalleeDecl());
+      CT = CanCalleeThrow(C, this, CE->getCalleeDecl());
     if (CT == CT_Can)
       return CT;
     return MergeCanThrow(CT, CanSubExprsThrow(C, this));
@@ -1765,7 +1776,7 @@
 
   case CXXConstructExprClass:
   case CXXTemporaryObjectExprClass: {
-    CanThrowResult CT = CanCalleeThrow(C,
+    CanThrowResult CT = CanCalleeThrow(C, this,
         cast<CXXConstructExpr>(this)->getConstructor());
     if (CT == CT_Can)
       return CT;
@@ -1778,8 +1789,8 @@
       CT = CT_Dependent;
     else
       CT = MergeCanThrow(
-        CanCalleeThrow(C, cast<CXXNewExpr>(this)->getOperatorNew()),
-        CanCalleeThrow(C, cast<CXXNewExpr>(this)->getConstructor(),
+        CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew()),
+        CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getConstructor(),
                        /*NullThrows*/false));
     if (CT == CT_Can)
       return CT;
@@ -1792,10 +1803,11 @@
     if (DTy.isNull() || DTy->isDependentType()) {
       CT = CT_Dependent;
     } else {
-      CT = CanCalleeThrow(C, cast<CXXDeleteExpr>(this)->getOperatorDelete());
+      CT = CanCalleeThrow(C, this,
+                          cast<CXXDeleteExpr>(this)->getOperatorDelete());
       if (const RecordType *RT = DTy->getAs<RecordType>()) {
         const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-        CT = MergeCanThrow(CT, CanCalleeThrow(C, RD->getDestructor()));
+        CT = MergeCanThrow(CT, CanCalleeThrow(C, this, RD->getDestructor()));
       }
       if (CT == CT_Can)
         return CT;
@@ -1805,7 +1817,7 @@
 
   case CXXBindTemporaryExprClass: {
     // The bound temporary has to be destroyed again, which might throw.
-    CanThrowResult CT = CanCalleeThrow(C,
+    CanThrowResult CT = CanCalleeThrow(C, this,
       cast<CXXBindTemporaryExpr>(this)->getTemporary()->getDestructor());
     if (CT == CT_Can)
       return CT;
diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp
index 3a0b909..c3f3b11 100644
--- a/lib/AST/Mangle.cpp
+++ b/lib/AST/Mangle.cpp
@@ -48,6 +48,11 @@
   const DeclContext *ExpectedDC = BD->getDeclContext();
   while (isa<BlockDecl>(ExpectedDC) || isa<EnumDecl>(ExpectedDC))
     ExpectedDC = ExpectedDC->getParent();
+  // In-class initializers for non-static data members are lexically defined
+  // within the class, but are mangled as if they were specified as constructor
+  // member initializers.
+  if (isa<CXXRecordDecl>(ExpectedDC) && DC != ExpectedDC)
+    DC = DC->getParent();
   assert(DC == ExpectedDC && "Given decl context did not match expected!");
 #endif
 }