[cfe-commits] r132878 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ include/clang/Sema/ lib/AST/ lib/CodeGen/ lib/Parse/ lib/Rewrite/ lib/Sema/ lib/Serialization/ test/CXX/class/class.mem/ test/CXX/dcl.dcl/dcl.spec/dcl.type/ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/ test/CXX/dcl.decl/dcl.init/ test/CXX/dcl.decl/dcl.init/dcl.init.aggr/ test/CXX/except/except.spec/ test/CXX/expr/expr.prim/ test/CXX/special/class.ctor/ test/CXX/special/class.init/class.base.init/ test/CodeGenCXX/ t...

Richard Smith richard-llvm at metafoo.co.uk
Sat Jun 11 10:19:42 PDT 2011


Author: rsmith
Date: Sat Jun 11 12:19:42 2011
New Revision: 132878

URL: http://llvm.org/viewvc/llvm-project?rev=132878&view=rev
Log:
Implement support for C++11 in-class initialization of non-static data members.


Added:
    cfe/trunk/test/CXX/class/class.mem/p5-0x.cpp
    cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp
    cfe/trunk/test/CXX/dcl.decl/dcl.init/p14-0x.cpp
    cfe/trunk/test/CXX/expr/expr.prim/p12-0x.cpp
    cfe/trunk/test/CXX/expr/expr.prim/p4-0x.cpp
    cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp
    cfe/trunk/test/CXX/special/class.init/class.base.init/p8-0x.cpp
    cfe/trunk/test/CXX/special/class.init/class.base.init/p9-0x.cpp
    cfe/trunk/test/CodeGenCXX/member-init-ctor.cpp
    cfe/trunk/test/PCH/cxx-member-init.cpp
    cfe/trunk/test/Parser/cxx0x-member-initializers.cpp
    cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp
    cfe/trunk/test/SemaCXX/member-init.cpp
Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/include/clang/Sema/Scope.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/DeclPrinter.cpp
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/Mangle.cpp
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGClass.cpp
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Rewrite/RewriteObjC.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
    cfe/trunk/test/CXX/except/except.spec/p14.cpp
    cfe/trunk/test/CodeGenObjCXX/blocks.mm
    cfe/trunk/test/SemaCXX/PR9572.cpp
    cfe/trunk/test/SemaCXX/class.cpp
    cfe/trunk/test/SemaCXX/type-traits.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sat Jun 11 12:19:42 2011
@@ -1953,20 +1953,33 @@
   bool Mutable : 1;
   mutable unsigned CachedFieldIndex : 31;
 
-  Expr *BitWidth;
+  /// \brief A pointer to either the in-class initializer for this field (if
+  /// the boolean value is false), or the bit width expression for this bit
+  /// field (if the boolean value is true).
+  ///
+  /// We can safely combine these two because in-class initializers are not
+  /// permitted for bit-fields.
+  ///
+  /// If the boolean is false and the initializer is null, then this field has
+  /// an in-class initializer which has not yet been parsed and attached.
+  llvm::PointerIntPair<Expr *, 1, bool> InitializerOrBitWidth;
 protected:
   FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
             SourceLocation IdLoc, IdentifierInfo *Id,
-            QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable)
+            QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
+            bool HasInit)
     : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
-      Mutable(Mutable), CachedFieldIndex(0), BitWidth(BW) {
+      Mutable(Mutable), CachedFieldIndex(0),
+      InitializerOrBitWidth(BW, !HasInit) {
+    assert(!(BW && HasInit) && "got initializer for bitfield");
   }
 
 public:
   static 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);
 
   /// getFieldIndex - Returns the index of this field within its record,
   /// as appropriate for passing to ASTRecordLayout::getFieldOffset.
@@ -1979,10 +1992,12 @@
   void setMutable(bool M) { Mutable = M; }
 
   /// isBitfield - Determines whether this field is a bitfield.
-  bool isBitField() const { return BitWidth != NULL; }
+  bool isBitField() const {
+    return InitializerOrBitWidth.getInt() && InitializerOrBitWidth.getPointer();
+  }
 
   /// @brief Determines whether this is an unnamed bitfield.
-  bool isUnnamedBitfield() const { return BitWidth != NULL && !getDeclName(); }
+  bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); }
 
   /// isAnonymousStructOrUnion - Determines whether this field is a
   /// representative for an anonymous struct or union. Such fields are
@@ -1990,8 +2005,37 @@
   /// store the data for the anonymous union or struct.
   bool isAnonymousStructOrUnion() const;
 
-  Expr *getBitWidth() const { return BitWidth; }
-  void setBitWidth(Expr *BW) { BitWidth = BW; }
+  Expr *getBitWidth() const {
+    return isBitField() ? InitializerOrBitWidth.getPointer() : 0;
+  }
+  void setBitWidth(Expr *BW) {
+    assert(!InitializerOrBitWidth.getPointer() &&
+           "bit width or initializer already set");
+    InitializerOrBitWidth.setPointer(BW);
+    InitializerOrBitWidth.setInt(1);
+  }
+
+  /// hasInClassInitializer - Determine whether this member has a C++0x in-class
+  /// initializer.
+  bool hasInClassInitializer() const {
+    return !InitializerOrBitWidth.getInt();
+  }
+  /// getInClassInitializer - Get the C++0x in-class initializer for this
+  /// member, or null if one has not been set. If a valid declaration has an
+  /// in-class initializer, but this returns null, then we have not parsed and
+  /// attached it yet.
+  Expr *getInClassInitializer() const {
+    return hasInClassInitializer() ? InitializerOrBitWidth.getPointer() : 0;
+  }
+  /// setInClassInitializer - Set the C++0x in-class initializer for this member.
+  void setInClassInitializer(Expr *Init);
+  /// removeInClassInitializer - Remove the C++0x in-class initializer from this
+  /// member.
+  void removeInClassInitializer() {
+    assert(!InitializerOrBitWidth.getInt() && "no initializer to remove");
+    InitializerOrBitWidth.setPointer(0);
+    InitializerOrBitWidth.setInt(1);
+  }
 
   /// getParent - Returns the parent of this field declaration, which
   /// is the struct in which this method is defined.

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Sat Jun 11 12:19:42 2011
@@ -1378,6 +1378,8 @@
   
   /// \brief The argument used to initialize the base or member, which may
   /// end up constructing an object (when multiple arguments are involved).
+  /// If 0, this is a field initializer, and the in-class member initializer 
+  /// will be used.
   Stmt *Init;
   
   /// LParenLoc - Location of the left paren of the ctor-initializer.
@@ -1452,6 +1454,13 @@
     return Initializee.is<IndirectFieldDecl*>();
   }
 
+  /// isInClassMemberInitializer - Returns true when this initializer is an
+  /// implicit ctor initializer generated for a field with an initializer
+  /// defined on the member declaration.
+  bool isInClassMemberInitializer() const {
+    return !Init;
+  }
+
   /// isDelegatingInitializer - Returns true when this initializer is creating
   /// a delegating constructor.
   bool isDelegatingInitializer() const {
@@ -1580,7 +1589,14 @@
     reinterpret_cast<VarDecl **>(this + 1)[I] = Index;
   }
   
-  Expr *getInit() const { return static_cast<Expr *>(Init); }
+  /// \brief Get the initializer. This is 0 if this is an in-class initializer
+  /// for a non-static data member which has not yet been parsed.
+  Expr *getInit() const {
+    if (!Init)
+      return getAnyMember()->getInClassInitializer();
+
+    return static_cast<Expr*>(Init);
+  }
 };
 
 /// CXXConstructorDecl - Represents a C++ constructor within a

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Sat Jun 11 12:19:42 2011
@@ -724,7 +724,7 @@
                QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
                bool synthesized)
     : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
-                /*Mutable=*/false),
+                /*Mutable=*/false, /*HasInit=*/false),
       NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {}
 
 public:
@@ -779,7 +779,7 @@
                       QualType T, Expr *BW)
     : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T,
                 /*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ?
-                BW, /*Mutable=*/false) {}
+                BW, /*Mutable=*/false, /*HasInit=*/false) {}
 
 public:
   static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Sat Jun 11 12:19:42 2011
@@ -2604,6 +2604,7 @@
   }
   bool isNothrow(ASTContext &Ctx) const {
     ExceptionSpecificationType EST = getExceptionSpecType();
+    assert(EST != EST_Delayed);
     if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
       return true;
     if (EST != EST_ComputedNoexcept)

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Sat Jun 11 12:19:42 2011
@@ -193,6 +193,8 @@
   "reference qualifiers on functions are a C++0x extension">, InGroup<CXX0x>;
 def ext_inline_namespace : ExtWarn<
   "inline namespaces are a C++0x feature">, InGroup<CXX0x>;
+def err_generalized_initializer_lists : Error<
+  "generalized initializer lists are a C++0x extension unsupported in Clang">;
 def ext_generalized_initializer_lists : ExtWarn<
   "generalized initializer lists are a C++0x extension unsupported in Clang">,
   InGroup<CXX0x>;
@@ -444,6 +446,15 @@
   "defaulted function definition accepted as a C++0x extension">,
   InGroup<CXX0x>;
 
+// C++0x in-class member initialization
+def warn_nonstatic_member_init_accepted_as_extension: ExtWarn<
+  "in-class initialization of non-static data member accepted as a C++0x extension">,
+  InGroup<CXX0x>;
+def err_bitfield_member_init: Error<
+  "bitfield member cannot have an in-class initializer">;
+def err_incomplete_array_member_init: Error<
+  "array bound cannot be deduced from an in-class initializer">;
+
 // C++0x alias-declaration
 def ext_alias_declaration : ExtWarn<
   "alias declarations accepted as a C++0x extension">, InGroup<CXX0x>;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Jun 11 12:19:42 2011
@@ -589,6 +589,8 @@
   "%0 is missing exception specification '%1'">;
 def err_noexcept_needs_constant_expression : Error<
   "argument to noexcept specifier must be a constant expression">;
+def err_exception_spec_unknown : Error<
+  "exception specification is not available until end of class definition">;
 
 // C++ access checking
 def err_class_redeclared_with_different_access : Error<
@@ -973,8 +975,8 @@
 def err_new_array_of_auto : Error<
   "cannot allocate array of 'auto'">;
 def err_auto_not_allowed : Error<
-  "'auto' not allowed %select{in function prototype|in struct member"
-  "|in union member|in class member|in exception declaration"
+  "'auto' not allowed %select{in function prototype|in non-static struct member"
+  "|in non-static union member|in non-static class member|in exception declaration"
   "|in template parameter|in block literal|in template argument"
   "|in typedef|in type alias|in function return type|here}0">;
 def err_auto_var_requires_init : Error<

Modified: cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h (original)
+++ cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h Sat Jun 11 12:19:42 2011
@@ -18,12 +18,13 @@
 
 /// \brief The various types of exception specifications that exist in C++0x.
 enum ExceptionSpecificationType {
-  EST_None,            ///< no exception specification
-  EST_DynamicNone,     ///< throw()
-  EST_Dynamic,         ///< throw(T1, T2)
-  EST_MSAny,           ///< Microsoft throw(...) extension
-  EST_BasicNoexcept,   ///< noexcept
-  EST_ComputedNoexcept ///< noexcept(expression)
+  EST_None,             ///< no exception specification
+  EST_DynamicNone,      ///< throw()
+  EST_Dynamic,          ///< throw(T1, T2)
+  EST_MSAny,            ///< Microsoft throw(...) extension
+  EST_BasicNoexcept,    ///< noexcept
+  EST_ComputedNoexcept, ///< noexcept(expression)
+  EST_Delayed           ///< not known yet
 };
 
 inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType) {

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sat Jun 11 12:19:42 2011
@@ -580,6 +580,18 @@
   /// ExitScope - Pop a scope off the scope stack.
   void ExitScope();
 
+  /// \brief RAII object used to modify the scope flags for the current scope.
+  class ParseScopeFlags {
+    Scope *CurScope;
+    unsigned OldFlags;
+    ParseScopeFlags(const ParseScopeFlags &); // do not implement
+    void operator=(const ParseScopeFlags &); // do not implement
+
+  public:
+    ParseScopeFlags(Parser *Self, unsigned ScopeFlags, bool ManageFlags = true);
+    ~ParseScopeFlags();
+  };
+
   //===--------------------------------------------------------------------===//
   // Diagnostic Emission and Error recovery.
 
@@ -621,8 +633,8 @@
   /// - function bodies
   /// - default arguments
   /// - exception-specifications (TODO: C++0x)
-  /// - and brace-or-equal-initializers (TODO: C++0x)
-  /// for non-static data members (including such things in nested classes)."
+  /// - and brace-or-equal-initializers for non-static data members
+  /// (including such things in nested classes)."
   /// LateParsedDeclarations build the tree of those elements so they can
   /// be parsed after parsing the top-level class.
   class LateParsedDeclaration {
@@ -630,6 +642,7 @@
     virtual ~LateParsedDeclaration();
 
     virtual void ParseLexedMethodDeclarations();
+    virtual void ParseLexedMemberInitializers();
     virtual void ParseLexedMethodDefs();
   };
 
@@ -641,6 +654,7 @@
     virtual ~LateParsedClass();
 
     virtual void ParseLexedMethodDeclarations();
+    virtual void ParseLexedMemberInitializers();
     virtual void ParseLexedMethodDefs();
 
   private:
@@ -714,6 +728,25 @@
     llvm::SmallVector<LateParsedDefaultArgument, 8> DefaultArgs;
   };
 
+  /// LateParsedMemberInitializer - An initializer for a non-static class data
+  /// member whose parsing must to be delayed until the class is completely
+  /// defined (C++11 [class.mem]p2).
+  struct LateParsedMemberInitializer : public LateParsedDeclaration {
+    LateParsedMemberInitializer(Parser *P, Decl *FD)
+      : Self(P), Field(FD) { }
+
+    virtual void ParseLexedMemberInitializers();
+
+    Parser *Self;
+
+    /// Field - The field declaration.
+    Decl *Field;
+
+    /// CachedTokens - The sequence of tokens that comprises the initializer,
+    /// including any leading '='.
+    CachedTokens Toks;
+  };
+
   /// LateParsedDeclarationsContainer - During parsing of a top (non-nested)
   /// C++ class, its method declarations that contain parts that won't be
   /// parsed until after the definition is completed (C++ [class.mem]p2),
@@ -974,10 +1007,13 @@
   Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
                                 const ParsedTemplateInfo &TemplateInfo,
                                 const VirtSpecifiers& VS, ExprResult& Init);
+  void ParseCXXNonStaticMemberInitializer(Decl *VarD);
   void ParseLexedMethodDeclarations(ParsingClass &Class);
   void ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM);
   void ParseLexedMethodDefs(ParsingClass &Class);
   void ParseLexedMethodDef(LexedMethod &LM);
+  void ParseLexedMemberInitializers(ParsingClass &Class);
+  void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI);
   bool ConsumeAndStoreUntil(tok::TokenKind T1,
                             CachedTokens &Toks,
                             bool StopAtSemi = true,
@@ -1755,6 +1791,8 @@
                            bool SuppressDeclarations = false);
   void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
                                    Decl *TagDecl);
+  ExprResult ParseCXXMemberInitializer(bool IsFunction,
+                                       SourceLocation &EqualLoc);
   void ParseCXXClassMemberDeclaration(AccessSpecifier AS,
                 const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
                                  ParsingDeclRAIIObject *DiagsFromTParams = 0);

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Sat Jun 11 12:19:42 2011
@@ -1078,8 +1078,8 @@
     /// If this is an invalid location, there is no ref-qualifier.
     unsigned RefQualifierLoc;
 
-    /// \brief When ExceptionSpecType isn't EST_None, the location of the
-    /// keyword introducing the spec.
+    /// \brief When ExceptionSpecType isn't EST_None or EST_Delayed, the
+    /// location of the keyword introducing the spec.
     unsigned ExceptionSpecLoc;
 
     /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that
@@ -1616,6 +1616,29 @@
     DeclTypeInfo.erase(DeclTypeInfo.begin());
   }
 
+  /// isArrayOfUnknownBound - This method returns true if the declarator
+  /// is a declarator for an array of unknown bound (looking through
+  /// parentheses).
+  bool isArrayOfUnknownBound() const {
+    for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
+      switch (DeclTypeInfo[i].Kind) {
+      case DeclaratorChunk::Paren:
+        continue;
+      case DeclaratorChunk::Function:
+      case DeclaratorChunk::Pointer:
+      case DeclaratorChunk::Reference:
+      case DeclaratorChunk::BlockPointer:
+      case DeclaratorChunk::MemberPointer:
+        return false;
+      case DeclaratorChunk::Array:
+        return !DeclTypeInfo[i].Arr.NumElts;
+      }
+      llvm_unreachable("Invalid type chunk");
+      return false;
+    }
+    return false;
+  }
+
   /// isFunctionDeclarator - This method returns true if the declarator
   /// is a function declarator (looking through parentheses).
   /// If true is returned, then the reference type parameter idx is

Modified: cfe/trunk/include/clang/Sema/Scope.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Scope.h?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Scope.h (original)
+++ cfe/trunk/include/clang/Sema/Scope.h Sat Jun 11 12:19:42 2011
@@ -79,7 +79,12 @@
     ObjCMethodScope = 0x400,
 
     /// SwitchScope - This is a scope that corresponds to a switch statement.
-    SwitchScope = 0x800
+    SwitchScope = 0x800,
+
+    /// ThisScope - This is the scope of a struct/union/class definition,
+    /// outside of any member function definition, where 'this' is nonetheless
+    /// usable.
+    ThisScope = 0x1000
   };
 private:
   /// The parent scope for this scope.  This is null for the translation-unit

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sat Jun 11 12:19:42 2011
@@ -1144,13 +1144,13 @@
                    Declarator &D, Expr *BitfieldWidth);
 
   FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
-                         Declarator &D, Expr *BitfieldWidth,
+                         Declarator &D, Expr *BitfieldWidth, bool HasInit,
                          AccessSpecifier AS);
 
   FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
                             TypeSourceInfo *TInfo,
                             RecordDecl *Record, SourceLocation Loc,
-                            bool Mutable, Expr *BitfieldWidth,
+                            bool Mutable, Expr *BitfieldWidth, bool HasInit,
                             SourceLocation TSSL,
                             AccessSpecifier AS, NamedDecl *PrevDecl,
                             Declarator *D = 0);
@@ -2612,6 +2612,13 @@
     // Then a throw(collected exceptions)
     // Finally no specification.
     // throw(...) is used instead if any called function uses it.
+    //
+    // If this exception specification cannot be known yet (for instance,
+    // because this is the exception specification for a defaulted default
+    // constructor and we haven't finished parsing the deferred parts of the
+    // class yet), the C++0x standard does not specify how to behave. We
+    // record this as an 'unknown' exception specification, which overrules
+    // any other specification (even 'none', to keep this rule simple).
     ExceptionSpecificationType ComputedEST;
     llvm::SmallPtrSet<CanQualType, 4> ExceptionsSeen;
     llvm::SmallVector<QualType, 4> Exceptions;
@@ -2644,6 +2651,15 @@
     /// \brief Integrate another called method into the collected data.
     void CalledDecl(CXXMethodDecl *Method);
 
+    /// \brief Integrate an invoked expression into the collected data.
+    void CalledExpr(Expr *E);
+
+    /// \brief Specify that the exception specification can't be detemined yet.
+    void SetDelayed() {
+      ClearExceptions();
+      ComputedEST = EST_Delayed;
+    }
+
     FunctionProtoType::ExtProtoInfo getEPI() const {
       FunctionProtoType::ExtProtoInfo EPI;
       EPI.ExceptionSpecType = getExceptionSpecType();
@@ -2836,10 +2852,9 @@
   //// ActOnCXXThis -  Parse 'this' pointer.
   ExprResult ActOnCXXThis(SourceLocation loc);
 
-  /// tryCaptureCXXThis - Try to capture a 'this' pointer.  Returns a
-  /// pointer to an instance method whose 'this' pointer is
-  /// capturable, or null if this is not possible.
-  CXXMethodDecl *tryCaptureCXXThis();
+  /// getAndCaptureCurrentThisType - Try to capture a 'this' pointer.  Returns
+  /// the type of the 'this' pointer, or a null type if this is not possible.
+  QualType getAndCaptureCurrentThisType();
 
   /// ActOnCXXBoolLiteral - Parse {true,false} literals.
   ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
@@ -3238,7 +3253,10 @@
                                  Declarator &D,
                                  MultiTemplateParamsArg TemplateParameterLists,
                                  Expr *BitfieldWidth, const VirtSpecifiers &VS,
-                                 Expr *Init, bool IsDefinition);
+                                 Expr *Init, bool HasDeferredInit,
+                                 bool IsDefinition);
+  void ActOnCXXInClassMemberInitializer(Decl *VarDecl, SourceLocation EqualLoc,
+                                        Expr *Init);
 
   MemInitResult ActOnMemInitializer(Decl *ConstructorD,
                                     Scope *S,
@@ -3342,8 +3360,9 @@
   void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record);
   void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
   void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param);
-  void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
   void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record);
+  void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
+  void ActOnFinishDelayedMemberInitializers(Decl *Record);
   void MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag = true);
   bool IsInsideALocalClassWithinATemplateFunction();
 

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sat Jun 11 12:19:42 2011
@@ -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);
   }

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Sat Jun 11 12:19:42 2011
@@ -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;

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Sat Jun 11 12:19:42 2011
@@ -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
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Sat Jun 11 12:19:42 2011
@@ -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());
 }
 

Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Sat Jun 11 12:19:42 2011
@@ -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();
+          
+          Init = Init->IgnoreParens();
           
-          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);
-              }
+          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) {

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Sat Jun 11 12:19:42 2011
@@ -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;

Modified: cfe/trunk/lib/AST/Mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Mangle.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Mangle.cpp (original)
+++ cfe/trunk/lib/AST/Mangle.cpp Sat Jun 11 12:19:42 2011
@@ -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
 }

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Sat Jun 11 12:19:42 2011
@@ -304,7 +304,11 @@
     const DeclContext *DC = block->getDeclContext();
     for (; isa<BlockDecl>(DC); DC = cast<BlockDecl>(DC)->getDeclContext())
       ;
-    QualType thisType = cast<CXXMethodDecl>(DC)->getThisType(C);
+    QualType thisType;
+    if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
+      thisType = C.getPointerType(C.getRecordType(RD));
+    else
+      thisType = cast<CXXMethodDecl>(DC)->getThisType(C);
 
     const llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType);
     std::pair<CharUnits,CharUnits> tinfo

Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Sat Jun 11 12:19:42 2011
@@ -520,6 +520,7 @@
                                   FunctionArgList &Args) {
   assert(MemberInit->isAnyMemberInitializer() &&
          "Must have member initializer!");
+  assert(MemberInit->getInit() && "Must have initializer!");
   
   // non-static data member initializers.
   FieldDecl *Field = MemberInit->getAnyMember();

Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Sat Jun 11 12:19:42 2011
@@ -4098,9 +4098,9 @@
                                       SourceLocation(), SourceLocation(),
                                       &Ctx.Idents.get("_objc_super"));
   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
-                                Ctx.getObjCIdType(), 0, 0, false));
+                                Ctx.getObjCIdType(), 0, 0, false, false));
   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
-                                Ctx.getObjCClassType(), 0, 0, false));
+                                Ctx.getObjCClassType(), 0, 0, false, false));
   RD->completeDefinition();
 
   SuperCTy = Ctx.getTagDeclType(RD);
@@ -4559,9 +4559,9 @@
                                       SourceLocation(), SourceLocation(),
                                       &Ctx.Idents.get("_message_ref_t"));
   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
-                                Ctx.VoidPtrTy, 0, 0, false));
+                                Ctx.VoidPtrTy, 0, 0, false, false));
   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
-                                Ctx.getObjCSelType(), 0, 0, false));
+                                Ctx.getObjCSelType(), 0, 0, false, false));
   RD->completeDefinition();
 
   MessageRefCTy = Ctx.getTagDeclType(RD);

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Sat Jun 11 12:19:42 2011
@@ -42,6 +42,7 @@
     FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D,
                                            move(TemplateParams), 0, 
                                            VS, Init.release(),
+                                           /*HasInit=*/false,
                                            /*IsDefinition*/true);
   }
 
@@ -166,8 +167,50 @@
   return FnD;
 }
 
+/// ParseCXXNonStaticMemberInitializer - We parsed and verified that the
+/// specified Declarator is a well formed C++ non-static data member
+/// declaration. Now lex its initializer and store its tokens for parsing
+/// after the class is complete.
+void Parser::ParseCXXNonStaticMemberInitializer(Decl *VarD) {
+  assert((Tok.is(tok::l_brace) || Tok.is(tok::equal)) &&
+         "Current token not a '{' or '='!");
+
+  LateParsedMemberInitializer *MI =
+    new LateParsedMemberInitializer(this, VarD);
+  getCurrentClass().LateParsedDeclarations.push_back(MI);
+  CachedTokens &Toks = MI->Toks;
+
+  tok::TokenKind kind = Tok.getKind();
+  if (kind == tok::equal) {
+    Toks.push_back(Tok);
+    ConsumeAnyToken();
+  }
+
+  if (kind == tok::l_brace) {
+    // Begin by storing the '{' token.
+    Toks.push_back(Tok);
+    ConsumeBrace();
+
+    // Consume everything up to (and including) the matching right brace.
+    ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/true);
+  } else {
+    // Consume everything up to (but excluding) the comma or semicolon.
+    ConsumeAndStoreUntil(tok::comma, Toks, /*StopAtSemi=*/true,
+                         /*ConsumeFinalToken=*/false);
+  }
+
+  // Store an artificial EOF token to ensure that we don't run off the end of
+  // the initializer when we come to parse it.
+  Token Eof;
+  Eof.startToken();
+  Eof.setKind(tok::eof);
+  Eof.setLocation(Tok.getLocation());
+  Toks.push_back(Eof);
+}
+
 Parser::LateParsedDeclaration::~LateParsedDeclaration() {}
 void Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {}
+void Parser::LateParsedDeclaration::ParseLexedMemberInitializers() {}
 void Parser::LateParsedDeclaration::ParseLexedMethodDefs() {}
 
 Parser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C)
@@ -181,6 +224,10 @@
   Self->ParseLexedMethodDeclarations(*Class);
 }
 
+void Parser::LateParsedClass::ParseLexedMemberInitializers() {
+  Self->ParseLexedMemberInitializers(*Class);
+}
+
 void Parser::LateParsedClass::ParseLexedMethodDefs() {
   Self->ParseLexedMethodDefs(*Class);
 }
@@ -193,6 +240,10 @@
   Self->ParseLexedMethodDef(*this);
 }
 
+void Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() {
+  Self->ParseLexedMemberInitializer(*this);
+}
+
 /// ParseLexedMethodDeclarations - We finished parsing the member
 /// specification of a top (non-nested) C++ class. Now go over the
 /// stack of method declarations with some parts for which parsing was
@@ -364,8 +415,70 @@
                                                         origLoc))
       while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
         ConsumeAnyToken();
+  }
+}
+
+/// ParseLexedMemberInitializers - We finished parsing the member specification
+/// of a top (non-nested) C++ class. Now go over the stack of lexed data member
+/// initializers that were collected during its parsing and parse them all.
+void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
+  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
+  ParseScope ClassTemplateScope(this, Scope::TemplateParamScope,
+                                HasTemplateScope);
+  if (HasTemplateScope)
+    Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
+
+  // Set or update the scope flags to include Scope::ThisScope.
+  bool AlreadyHasClassScope = Class.TopLevelClass;
+  unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope|Scope::ThisScope;
+  ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope);
+  ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope);
+
+  if (!AlreadyHasClassScope)
+    Actions.ActOnStartDelayedMemberDeclarations(getCurScope(),
+                                                Class.TagOrTemplate);
+
+  for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
+    Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers();
+  }
+
+  if (!AlreadyHasClassScope)
+    Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(),
+                                                 Class.TagOrTemplate);
+
+  Actions.ActOnFinishDelayedMemberInitializers(Class.TagOrTemplate);
+}
+
+void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
+  if (MI.Field->isInvalidDecl())
+    return;
 
+  // Append the current token at the end of the new token stream so that it
+  // doesn't get lost.
+  MI.Toks.push_back(Tok);
+  PP.EnterTokenStream(MI.Toks.data(), MI.Toks.size(), true, false);
+
+  // Consume the previously pushed token.
+  ConsumeAnyToken();
+
+  SourceLocation EqualLoc;
+  ExprResult Init = ParseCXXMemberInitializer(/*IsFunction=*/false, EqualLoc);
+
+  Actions.ActOnCXXInClassMemberInitializer(MI.Field, EqualLoc, Init.release());
+
+  // The next token should be our artificial terminating EOF token.
+  if (Tok.isNot(tok::eof)) {
+    SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
+    if (!EndLoc.isValid())
+      EndLoc = Tok.getLocation();
+    // No fixit; we can't recover as if there were a semicolon here.
+    Diag(EndLoc, diag::err_expected_semi_decl_list);
+
+    // Consume tokens until we hit the artificial EOF.
+    while (Tok.isNot(tok::eof))
+      ConsumeAnyToken();
   }
+  ConsumeAnyToken();
 }
 
 /// ConsumeAndStoreUntil - Consume and store the token at the passed token

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sat Jun 11 12:19:42 2011
@@ -1553,6 +1553,7 @@
 ///       member-declarator:
 ///         declarator virt-specifier-seq[opt] pure-specifier[opt]
 ///         declarator constant-initializer[opt]
+/// [C++11] declarator brace-or-equal-initializer[opt]
 ///         identifier[opt] ':' constant-expression
 ///
 ///       virt-specifier-seq:
@@ -1731,10 +1732,14 @@
 
     bool IsDefinition = false;
     // function-definition:
-    if (Tok.is(tok::l_brace)) {
+    //
+    // In C++11, a non-function declarator followed by an open brace is a
+    // braced-init-list for an in-class member initialization, not an
+    // erroneous function definition.
+    if (Tok.is(tok::l_brace) && !getLang().CPlusPlus0x) {
       IsDefinition = true;
     } else if (DeclaratorInfo.isFunctionDeclarator()) {
-      if (Tok.is(tok::colon) || Tok.is(tok::kw_try)) {
+      if (Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) {
         IsDefinition = true;
       } else if (Tok.is(tok::equal)) {
         const Token &KW = NextToken();
@@ -1790,7 +1795,7 @@
   while (1) {
     // member-declarator:
     //   declarator pure-specifier[opt]
-    //   declarator constant-initializer[opt]
+    //   declarator brace-or-equal-initializer[opt]
     //   identifier[opt] ':' constant-expression
     if (Tok.is(tok::colon)) {
       ConsumeToken();
@@ -1799,38 +1804,6 @@
         SkipUntil(tok::comma, true, true);
     }
 
-    ParseOptionalCXX0XVirtSpecifierSeq(VS);
-
-    // pure-specifier:
-    //   '= 0'
-    //
-    // constant-initializer:
-    //   '=' constant-expression
-    //
-    // defaulted/deleted function-definition:
-    //   '=' 'default'                          [TODO]
-    //   '=' 'delete'
-    if (Tok.is(tok::equal)) {
-      ConsumeToken();
-      if (Tok.is(tok::kw_delete)) {
-        if (DeclaratorInfo.isFunctionDeclarator())
-          Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
-            << 1 /* delete */;
-        else
-          Diag(ConsumeToken(), diag::err_deleted_non_function);
-      } else if (Tok.is(tok::kw_default)) {
-        if (DeclaratorInfo.isFunctionDeclarator())
-          Diag(Tok, diag::err_default_delete_in_multiple_declaration)
-            << 1 /* delete */;
-        else
-          Diag(ConsumeToken(), diag::err_default_special_members);
-      } else {
-        Init = ParseInitializer();
-        if (Init.isInvalid())
-          SkipUntil(tok::comma, true, true);
-      }
-    }
-
     // If a simple-asm-expr is present, parse it.
     if (Tok.is(tok::kw_asm)) {
       SourceLocation Loc;
@@ -1845,6 +1818,30 @@
     // If attributes exist after the declarator, parse them.
     MaybeParseGNUAttributes(DeclaratorInfo);
 
+    // FIXME: When g++ adds support for this, we'll need to check whether it
+    // goes before or after the GNU attributes and __asm__.
+    ParseOptionalCXX0XVirtSpecifierSeq(VS);
+
+    bool HasDeferredInitializer = false;
+    if (Tok.is(tok::equal) || Tok.is(tok::l_brace)) {
+      if (BitfieldSize.get()) {
+        Diag(Tok, diag::err_bitfield_member_init);
+        SkipUntil(tok::comma, true, true);
+      } else {
+        HasDeferredInitializer = !DeclaratorInfo.isFunctionDeclarator() &&
+          DeclaratorInfo.getDeclSpec().getStorageClassSpec()
+            != DeclSpec::SCS_static;
+
+        if (!HasDeferredInitializer) {
+          SourceLocation EqualLoc;
+          Init = ParseCXXMemberInitializer(
+            DeclaratorInfo.isFunctionDeclarator(), EqualLoc);
+          if (Init.isInvalid())
+            SkipUntil(tok::comma, true, true);
+        }
+      }
+    }
+
     // NOTE: If Sema is the Action module and declarator is an instance field,
     // this call will *not* return the created decl; It will return null.
     // See Sema::ActOnCXXMemberDeclarator for details.
@@ -1860,7 +1857,9 @@
                                                   DeclaratorInfo,
                                                   move(TemplateParams),
                                                   BitfieldSize.release(),
-                                                  VS, Init.release(), false);
+                                                  VS, Init.release(),
+                                                  HasDeferredInitializer,
+                                                  /*IsDefinition*/ false);
     }
     if (ThisDecl)
       DeclsInGroup.push_back(ThisDecl);
@@ -1873,6 +1872,24 @@
 
     DeclaratorInfo.complete(ThisDecl);
 
+    if (HasDeferredInitializer) {
+      if (!getLang().CPlusPlus0x)
+        Diag(Tok, diag::warn_nonstatic_member_init_accepted_as_extension);
+
+      if (DeclaratorInfo.isArrayOfUnknownBound()) {
+        // C++0x [dcl.array]p3: An array bound may also be omitted when the
+        // declarator is followed by an initializer. 
+        //
+        // A brace-or-equal-initializer for a member-declarator is not an
+        // initializer in the gramamr, so this is ill-formed.
+        Diag(Tok, diag::err_incomplete_array_member_init);
+        SkipUntil(tok::comma, true, true);
+        // Avoid later warnings about a class member of incomplete type.
+        ThisDecl->setInvalidDecl();
+      } else
+        ParseCXXNonStaticMemberInitializer(ThisDecl);
+    }
+
     // If we don't have a comma, it is either the end of the list (a ';')
     // or an error, bail out.
     if (Tok.isNot(tok::comma))
@@ -1906,6 +1923,66 @@
                                   DeclsInGroup.size());
 }
 
+/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer or
+/// pure-specifier. Also detect and reject any attempted defaulted/deleted
+/// function definition. The location of the '=', if any, will be placed in
+/// EqualLoc.
+///
+///   pure-specifier:
+///     '= 0'
+///  
+///   brace-or-equal-initializer:
+///     '=' initializer-expression
+///     braced-init-list                       [TODO]
+///  
+///   initializer-clause:
+///     assignment-expression
+///     braced-init-list                       [TODO]
+///  
+///   defaulted/deleted function-definition:                                                                                                                                                                                               
+///     '=' 'default'
+///     '=' 'delete'
+///
+/// Prior to C++0x, the assignment-expression in an initializer-clause must
+/// be a constant-expression.
+ExprResult Parser::ParseCXXMemberInitializer(bool IsFunction,
+                                             SourceLocation &EqualLoc) {
+  assert((Tok.is(tok::equal) || Tok.is(tok::l_brace))
+         && "Data member initializer not starting with '=' or '{'");
+
+  if (Tok.is(tok::equal)) {
+    EqualLoc = ConsumeToken();
+    if (Tok.is(tok::kw_delete)) {
+      // In principle, an initializer of '= delete p;' is legal, but it will
+      // never type-check. It's better to diagnose it as an ill-formed expression
+      // than as an ill-formed deleted non-function member.
+      // An initializer of '= delete p, foo' will never be parsed, because
+      // a top-level comma always ends the initializer expression.
+      const Token &Next = NextToken();
+      if (IsFunction || Next.is(tok::semi) || Next.is(tok::comma) ||
+           Next.is(tok::eof)) {
+        if (IsFunction)
+          Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
+            << 1 /* delete */;
+        else
+          Diag(ConsumeToken(), diag::err_deleted_non_function);
+        return ExprResult();
+      }
+    } else if (Tok.is(tok::kw_default)) {
+      Diag(ConsumeToken(), diag::err_default_special_members);
+      if (IsFunction)
+        Diag(Tok, diag::err_default_delete_in_multiple_declaration)
+          << 0 /* default */;
+      else
+        Diag(ConsumeToken(), diag::err_default_special_members);
+      return ExprResult();
+    }
+
+    return ParseInitializer();
+  } else
+    return ExprError(Diag(Tok, diag::err_generalized_initializer_lists));
+}
+
 /// ParseCXXMemberSpecification - Parse the class definition.
 ///
 ///       member-specification:
@@ -2057,19 +2134,20 @@
                                               LBraceLoc, RBraceLoc,
                                               attrs.getList());
 
-  // C++ 9.2p2: Within the class member-specification, the class is regarded as
-  // complete within function bodies, default arguments,
-  // exception-specifications, and constructor ctor-initializers (including
-  // such things in nested classes).
+  // C++0x [class.mem]p2: Within the class member-specification, the class is
+  // regarded as complete within function bodies, default arguments, exception-
+  // specifications, and brace-or-equal-initializers for non-static data
+  // members (including such things in nested classes).
   //
-  // FIXME: Only function bodies and constructor ctor-initializers are
-  // parsed correctly, fix the rest.
+  // FIXME: Only function bodies and brace-or-equal-initializers are currently
+  // handled. Fix the others!
   if (TagDecl && NonNestedClass) {
     // We are not inside a nested class. This class and its nested classes
     // are complete and we can parse the delayed portions of method
     // declarations and the lexed inline method definitions.
     SourceLocation SavedPrevTokLocation = PrevTokLocation;
     ParseLexedMethodDeclarations(getCurrentClass());
+    ParseLexedMemberInitializers(getCurrentClass());
     ParseLexedMethodDefs(getCurrentClass());
     PrevTokLocation = SavedPrevTokLocation;
   }

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Sat Jun 11 12:19:42 2011
@@ -351,7 +351,23 @@
     ScopeCache[NumCachedScopes++] = OldScope;
 }
 
+/// Set the flags for the current scope to ScopeFlags. If ManageFlags is false,
+/// this object does nothing.
+Parser::ParseScopeFlags::ParseScopeFlags(Parser *Self, unsigned ScopeFlags,
+                                 bool ManageFlags)
+  : CurScope(ManageFlags ? Self->getCurScope() : 0) {
+  if (CurScope) {
+    OldFlags = CurScope->getFlags();
+    CurScope->setFlags(ScopeFlags);
+  }
+}
 
+/// Restore the flags for the current scope to what they were before this
+/// object overrode them.
+Parser::ParseScopeFlags::~ParseScopeFlags() {
+  if (CurScope)
+    CurScope->setFlags(OldFlags);
+}
 
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Rewrite/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteObjC.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Rewrite/RewriteObjC.cpp Sat Jun 11 12:19:42 2011
@@ -2695,7 +2695,8 @@
                                                  SourceLocation(), 0,
                                                  FieldTypes[i], 0,
                                                  /*BitWidth=*/0,
-                                                 /*Mutable=*/false));
+                                                 /*Mutable=*/false,
+                                                 /*HasInit=*/false));
     }
 
     SuperStructDecl->completeDefinition();
@@ -2727,7 +2728,8 @@
                                                     SourceLocation(), 0,
                                                     FieldTypes[i], 0,
                                                     /*BitWidth=*/0,
-                                                    /*Mutable=*/true));
+                                                    /*Mutable=*/true,
+                                                    /*HasInit=*/false));
     }
 
     ConstantStringDecl->completeDefinition();
@@ -4709,7 +4711,8 @@
                                     SourceLocation(),
                                     &Context->Idents.get("FuncPtr"),
                                     Context->VoidPtrTy, 0,
-                                    /*BitWidth=*/0, /*Mutable=*/true);
+                                    /*BitWidth=*/0, /*Mutable=*/true,
+                                    /*HasInit=*/false);
   MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
                                             FD->getType(), VK_LValue,
                                             OK_Ordinary);
@@ -4763,7 +4766,8 @@
                                     SourceLocation(),
                                     &Context->Idents.get("__forwarding"), 
                                     Context->VoidPtrTy, 0,
-                                    /*BitWidth=*/0, /*Mutable=*/true);
+                                    /*BitWidth=*/0, /*Mutable=*/true,
+                                    /*HasInit=*/false);
   MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
                                             FD, SourceLocation(),
                                             FD->getType(), VK_LValue,
@@ -4773,7 +4777,8 @@
   FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(),
                          &Context->Idents.get(Name), 
                          Context->VoidPtrTy, 0,
-                         /*BitWidth=*/0, /*Mutable=*/true);
+                         /*BitWidth=*/0, /*Mutable=*/true,
+                         /*HasInit=*/false);
   ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
                                 DeclRefExp->getType(), VK_LValue, OK_Ordinary);
   

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Jun 11 12:19:42 2011
@@ -2610,7 +2610,8 @@
                              /*IdentifierInfo=*/0,
                              Context.getTypeDeclType(Record),
                              TInfo,
-                             /*BitWidth=*/0, /*Mutable=*/false);
+                             /*BitWidth=*/0, /*Mutable=*/false,
+                             /*HasInit=*/false);
     Anon->setAccess(AS);
     if (getLangOptions().CPlusPlus)
       FieldCollector->Add(cast<FieldDecl>(Anon));
@@ -2700,7 +2701,8 @@
                              /*IdentifierInfo=*/0,
                              Context.getTypeDeclType(Record),
                              TInfo,
-                             /*BitWidth=*/0, /*Mutable=*/false);
+                             /*BitWidth=*/0, /*Mutable=*/false,
+                             /*HasInit=*/false);
   Anon->setImplicit();
 
   // Add the anonymous struct object to the current context.
@@ -7512,14 +7514,13 @@
   return false;
 }
 
-/// ActOnField - Each field of a struct/union/class is passed into this in order
+/// ActOnField - Each field of a C struct/union is passed into this in order
 /// to create a FieldDecl object for it.
-Decl *Sema::ActOnField(Scope *S, Decl *TagD,
-                                 SourceLocation DeclStart,
-                                 Declarator &D, ExprTy *BitfieldWidth) {
+Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart,
+                       Declarator &D, ExprTy *BitfieldWidth) {
   FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD),
                                DeclStart, D, static_cast<Expr*>(BitfieldWidth),
-                               AS_public);
+                               /*HasInit=*/false, AS_public);
   return Res;
 }
 
@@ -7527,7 +7528,7 @@
 ///
 FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
                              SourceLocation DeclStart,
-                             Declarator &D, Expr *BitWidth,
+                             Declarator &D, Expr *BitWidth, bool HasInit,
                              AccessSpecifier AS) {
   IdentifierInfo *II = D.getIdentifier();
   SourceLocation Loc = DeclStart;
@@ -7576,8 +7577,8 @@
     = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable);
   SourceLocation TSSL = D.getSourceRange().getBegin();
   FieldDecl *NewFD
-    = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, TSSL,
-                     AS, PrevDecl, &D);
+    = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, HasInit,
+                     TSSL, AS, PrevDecl, &D);
 
   if (NewFD->isInvalidDecl())
     Record->setInvalidDecl();
@@ -7606,7 +7607,7 @@
 FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
                                 TypeSourceInfo *TInfo,
                                 RecordDecl *Record, SourceLocation Loc,
-                                bool Mutable, Expr *BitWidth,
+                                bool Mutable, Expr *BitWidth, bool HasInit,
                                 SourceLocation TSSL,
                                 AccessSpecifier AS, NamedDecl *PrevDecl,
                                 Declarator *D) {
@@ -7686,7 +7687,7 @@
   }
 
   FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo,
-                                       BitWidth, Mutable);
+                                       BitWidth, Mutable, HasInit);
   if (InvalidDecl)
     NewFD->setInvalidDecl();
 
@@ -8289,16 +8290,17 @@
 
     // Now that the record is complete, do any delayed exception spec checks
     // we were missing.
-    if (!DelayedDestructorExceptionSpecChecks.empty()) {
+    while (!DelayedDestructorExceptionSpecChecks.empty()) {
       const CXXDestructorDecl *Dtor =
               DelayedDestructorExceptionSpecChecks.back().first;
-      if (Dtor->getParent() == Record) {
-        assert(!Dtor->getParent()->isDependentType() &&
-            "Should not ever add destructors of templates into the list.");
-        CheckOverridingFunctionExceptionSpec(Dtor,
-            DelayedDestructorExceptionSpecChecks.back().second);
-        DelayedDestructorExceptionSpecChecks.pop_back();
-      }
+      if (Dtor->getParent() != Record)
+        break;
+
+      assert(!Dtor->getParent()->isDependentType() &&
+          "Should not ever add destructors of templates into the list.");
+      CheckOverridingFunctionExceptionSpec(Dtor,
+          DelayedDestructorExceptionSpecChecks.back().second);
+      DelayedDestructorExceptionSpecChecks.pop_back();
     }
 
   } else {

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Jun 11 12:19:42 2011
@@ -113,8 +113,8 @@
 
 void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) {
   assert(Context && "ImplicitExceptionSpecification without an ASTContext");
-  // If we have an MSAny spec already, don't bother.
-  if (!Method || ComputedEST == EST_MSAny)
+  // If we have an MSAny or unknown spec already, don't bother.
+  if (!Method || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed)
     return;
 
   const FunctionProtoType *Proto
@@ -123,12 +123,15 @@
   ExceptionSpecificationType EST = Proto->getExceptionSpecType();
 
   // If this function can throw any exceptions, make a note of that.
-  if (EST == EST_MSAny || EST == EST_None) {
+  if (EST == EST_Delayed || EST == EST_MSAny || EST == EST_None) {
     ClearExceptions();
     ComputedEST = EST;
     return;
   }
 
+  // FIXME: If the call to this decl is using any of its default arguments, we
+  // need to search them for potentially-throwing calls.
+
   // If this function has a basic noexcept, it doesn't affect the outcome.
   if (EST == EST_BasicNoexcept)
     return;
@@ -175,6 +178,35 @@
       Exceptions.push_back(*E);
 }
 
+void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) {
+  if (!E || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed)
+    return;
+
+  // FIXME:
+  //
+  // C++0x [except.spec]p14:
+  //   [An] implicit exception-specification specifies the type-id T if and
+  // only if T is allowed by the exception-specification of a function directly
+  // invoked by f’s implicit definition; f shall allow all exceptions if any
+  // function it directly invokes allows all exceptions, and f shall allow no
+  // exceptions if every function it directly invokes allows no exceptions.
+  //
+  // Note in particular that if an implicit exception-specification is generated
+  // for a function containing a throw-expression, that specification can still
+  // be noexcept(true).
+  //
+  // Note also that 'directly invoked' is not defined in the standard, and there
+  // is no indication that we should only consider potentially-evaluated calls.
+  //
+  // Ultimately we should implement the intent of the standard: the exception
+  // specification should be the set of exceptions which can be thrown by the
+  // implicit definition. For now, we assume that any non-nothrow expression can
+  // throw any exception.
+
+  if (E->CanThrow(*Context))
+    ComputedEST = EST_None;
+}
+
 bool
 Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
                               SourceLocation EqualLoc) {
@@ -1029,13 +1061,15 @@
 
 /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
 /// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
-/// bitfield width if there is one and 'InitExpr' specifies the initializer if
-/// any.
+/// bitfield width if there is one, 'InitExpr' specifies the initializer if
+/// one has been parsed, and 'HasDeferredInit' is true if an initializer is
+/// present but parsing it has been deferred.
 Decl *
 Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
                                MultiTemplateParamsArg TemplateParameterLists,
                                ExprTy *BW, const VirtSpecifiers &VS,
-                               ExprTy *InitExpr, bool IsDefinition) {
+                               ExprTy *InitExpr, bool HasDeferredInit,
+                               bool IsDefinition) {
   const DeclSpec &DS = D.getDeclSpec();
   DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
   DeclarationName Name = NameInfo.getName();
@@ -1050,6 +1084,7 @@
 
   assert(isa<CXXRecordDecl>(CurContext));
   assert(!DS.isFriendSpecified());
+  assert(!Init || !HasDeferredInit);
 
   bool isFunc = false;
   if (D.isFunctionDeclarator())
@@ -1121,9 +1156,11 @@
     // FIXME: Check for template parameters!
     // FIXME: Check that the name is an identifier!
     Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
-                         AS);
+                         HasDeferredInit, AS);
     assert(Member && "HandleField never returns null");
   } else {
+    assert(!HasDeferredInit);
+
     Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition);
     if (!Member) {
       return 0;
@@ -1194,6 +1231,14 @@
   if (Init)
     AddInitializerToDecl(Member, Init, false,
                          DS.getTypeSpecType() == DeclSpec::TST_auto);
+  else if (DS.getTypeSpecType() == DeclSpec::TST_auto &&
+           DS.getStorageClassSpec() == DeclSpec::SCS_static) {
+    // C++0x [dcl.spec.auto]p4: 'auto' can only be used in the type of a static
+    // data member if a brace-or-equal-initializer is provided.
+    Diag(Loc, diag::err_auto_var_requires_init)
+      << Name << cast<ValueDecl>(Member)->getType();
+    Member->setInvalidDecl();
+  }
 
   FinalizeDeclaration(Member);
 
@@ -1202,6 +1247,47 @@
   return Member;
 }
 
+/// ActOnCXXInClassMemberInitializer - This is invoked after parsing an
+/// in-class initializer for a non-static C++ class member. Such parsing
+/// is deferred until the class is complete.
+void
+Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation EqualLoc,
+                                       Expr *InitExpr) {
+  FieldDecl *FD = cast<FieldDecl>(D);
+
+  if (!InitExpr) {
+    FD->setInvalidDecl();
+    FD->removeInClassInitializer();
+    return;
+  }
+
+  ExprResult Init = InitExpr;
+  if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
+    // FIXME: if there is no EqualLoc, this is list-initialization.
+    Init = PerformCopyInitialization(
+      InitializedEntity::InitializeMember(FD), EqualLoc, InitExpr);
+    if (Init.isInvalid()) {
+      FD->setInvalidDecl();
+      return;
+    }
+
+    CheckImplicitConversions(Init.get(), EqualLoc);
+  }
+
+  // C++0x [class.base.init]p7:
+  //   The initialization of each base and member constitutes a
+  //   full-expression.
+  Init = MaybeCreateExprWithCleanups(Init);
+  if (Init.isInvalid()) {
+    FD->setInvalidDecl();
+    return;
+  }
+
+  InitExpr = Init.release();
+
+  FD->setInClassInitializer(InitExpr);
+}
+
 /// \brief Find the direct and/or virtual base specifiers that
 /// correspond to the given base type, for use in base initialization
 /// within a constructor.
@@ -2073,7 +2159,7 @@
 };
 }
 
-static bool CollectFieldInitializer(BaseAndFieldInfo &Info,
+static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
                                     FieldDecl *Top, FieldDecl *Field) {
 
   // Overwhelmingly common case: we have a direct initializer for this field.
@@ -2082,6 +2168,18 @@
     return false;
   }
 
+  // C++0x [class.base.init]p8: if the entity is a non-static data member that
+  // has a brace-or-equal-initializer, the entity is initialized as specified
+  // in [dcl.init].
+  if (Field->hasInClassInitializer()) {
+    Info.AllToInit.push_back(
+      new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field,
+                                               SourceLocation(),
+                                               SourceLocation(), 0,
+                                               SourceLocation()));
+    return false;
+  }
+
   if (Info.IIK == IIK_Default && Field->isAnonymousStructOrUnion()) {
     const RecordType *FieldClassType = Field->getType()->getAs<RecordType>();
     assert(FieldClassType && "anonymous struct/union without record type");
@@ -2104,7 +2202,7 @@
           // field in the class is also initialized, so exit immediately.
           return false;
         } else if ((*FA)->isAnonymousStructOrUnion()) {
-          if (CollectFieldInitializer(Info, Top, *FA))
+          if (CollectFieldInitializer(SemaRef, Info, Top, *FA))
             return true;
         }
       }
@@ -2119,7 +2217,7 @@
       // necessary.
       for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
            EA = FieldClassDecl->field_end(); FA != EA; FA++) {
-        if (CollectFieldInitializer(Info, Top, *FA))
+        if (CollectFieldInitializer(SemaRef, Info, Top, *FA))
           return true;
       }
     }
@@ -2128,7 +2226,7 @@
   // Don't try to build an implicit initializer if there were semantic
   // errors in any of the initializers (and therefore we might be
   // missing some that the user actually wrote).
-  if (Info.AnyErrorsInInits)
+  if (Info.AnyErrorsInInits || Field->isInvalidDecl())
     return false;
 
   CXXCtorInitializer *Init = 0;
@@ -2260,7 +2358,7 @@
              "Incomplete array type is not valid");
       continue;
     }
-    if (CollectFieldInitializer(Info, *Field, *Field))
+    if (CollectFieldInitializer(*this, Info, *Field, *Field))
       HadError = true;
   }
 
@@ -2939,6 +3037,9 @@
     for (RecordDecl::field_iterator F = Record->field_begin(), 
                                  FEnd = Record->field_end();
          F != FEnd; ++F) {
+      if (F->hasInClassInitializer())
+        continue;
+
       if (F->getType()->isReferenceType() ||
           (F->getType().isConstQualified() && F->getType()->isScalarType())) {
         if (!Complained) {
@@ -3066,6 +3167,11 @@
   ImplicitExceptionSpecification Spec
     = ComputeDefaultedDefaultCtorExceptionSpec(CD->getParent());
   FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+  if (EPI.ExceptionSpecType == EST_Delayed) {
+    // Exception specification depends on some deferred part of the class. We'll
+    // try again when the class's definition has been fully processed.
+    return;
+  }
   const FunctionProtoType *CtorType = CD->getType()->getAs<FunctionProtoType>(),
                           *ExceptionType = Context.getFunctionType(
                          Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>();
@@ -3383,12 +3489,15 @@
   for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
                                      FE = RD->field_end();
        FI != FE; ++FI) {
+    if (FI->isInvalidDecl())
+      continue;
+    
     QualType FieldType = Context.getBaseElementType(FI->getType());
     CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl();
-    
+
     // -- any non-static data member with no brace-or-equal-initializer is of
     //    reference type
-    if (FieldType->isReferenceType())
+    if (FieldType->isReferenceType() && !FI->hasInClassInitializer())
       return true;
 
     // -- X is a union and all its variant members are of const-qualified type
@@ -3413,6 +3522,7 @@
       //    array thereof) with no brace-or-equal-initializer does not have a
       //    user-provided default constructor
       if (FieldType.isConstQualified() &&
+          !FI->hasInClassInitializer() &&
           !FieldRecord->hasUserProvidedDefaultConstructor())
         return true;
  
@@ -3445,18 +3555,21 @@
         continue;
       }
 
-      // -- any non-static data member ... has class type M (or array thereof)
-      //    and either M has no default constructor or overload resolution as
-      //    applied to M's default constructor results in an ambiguity or in a
-      //    function that is deleted or inaccessible from the defaulted default
-      //    constructor.
-      CXXConstructorDecl *FieldDefault = LookupDefaultConstructor(FieldRecord);
-      if (!FieldDefault || FieldDefault->isDeleted())
-        return true;
-      if (CheckConstructorAccess(Loc, FieldDefault, FieldDefault->getAccess(),
-                                 PDiag()) != AR_accessible)
-        return true;
-    } else if (!Union && FieldType.isConstQualified()) {
+      // -- any non-static data member with no brace-or-equal-initializer has
+      //    class type M (or array thereof) and either M has no default
+      //    constructor or overload resolution as applied to M's default
+      //    constructor results in an ambiguity or in a function that is deleted
+      //    or inaccessible from the defaulted default constructor.
+      if (!FI->hasInClassInitializer()) {
+        CXXConstructorDecl *FieldDefault = LookupDefaultConstructor(FieldRecord);
+        if (!FieldDefault || FieldDefault->isDeleted())
+          return true;
+        if (CheckConstructorAccess(Loc, FieldDefault, FieldDefault->getAccess(),
+                                   PDiag()) != AR_accessible)
+          return true;
+      }
+    } else if (!Union && FieldType.isConstQualified() &&
+               !FI->hasInClassInitializer()) {
       // -- any non-variant non-static data member of const-qualified type (or
       //    array thereof) with no brace-or-equal-initializer does not have a
       //    user-provided default constructor
@@ -5905,7 +6018,12 @@
   for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
                                FEnd = ClassDecl->field_end();
        F != FEnd; ++F) {
-    if (const RecordType *RecordTy
+    if (F->hasInClassInitializer()) {
+      if (Expr *E = F->getInClassInitializer())
+        ExceptSpec.CalledExpr(E);
+      else if (!F->isInvalidDecl())
+        ExceptSpec.SetDelayed();
+    } else if (const RecordType *RecordTy
               = Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
       CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
       CXXConstructorDecl *Constructor = LookupDefaultConstructor(FieldRecDecl);
@@ -6001,6 +6119,59 @@
   }
 }
 
+/// Get any existing defaulted default constructor for the given class. Do not
+/// implicitly define one if it does not exist.
+static CXXConstructorDecl *getDefaultedDefaultConstructorUnsafe(Sema &Self,
+                                                             CXXRecordDecl *D) {
+  ASTContext &Context = Self.Context;
+  QualType ClassType = Context.getTypeDeclType(D);
+  DeclarationName ConstructorName
+    = Context.DeclarationNames.getCXXConstructorName(
+                      Context.getCanonicalType(ClassType.getUnqualifiedType()));
+
+  DeclContext::lookup_const_iterator Con, ConEnd;
+  for (llvm::tie(Con, ConEnd) = D->lookup(ConstructorName);
+       Con != ConEnd; ++Con) {
+    // A function template cannot be defaulted.
+    if (isa<FunctionTemplateDecl>(*Con))
+      continue;
+
+    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+    if (Constructor->isDefaultConstructor())
+      return Constructor->isDefaulted() ? Constructor : 0;
+  }
+  return 0;
+}
+
+void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) {
+  if (!D) return;
+  AdjustDeclIfTemplate(D);
+
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D);
+  CXXConstructorDecl *CtorDecl
+    = getDefaultedDefaultConstructorUnsafe(*this, ClassDecl);
+
+  if (!CtorDecl) return;
+
+  // Compute the exception specification for the default constructor.
+  const FunctionProtoType *CtorTy =
+    CtorDecl->getType()->castAs<FunctionProtoType>();
+  if (CtorTy->getExceptionSpecType() == EST_Delayed) {
+    ImplicitExceptionSpecification Spec = 
+      ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl);
+    FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+    assert(EPI.ExceptionSpecType != EST_Delayed);
+
+    CtorDecl->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI));
+  }
+
+  // If the default constructor is explicitly defaulted, checking the exception
+  // specification is deferred until now.
+  if (!CtorDecl->isInvalidDecl() && CtorDecl->isExplicitlyDefaulted() &&
+      !ClassDecl->isDependentType())
+    CheckExplicitlyDefaultedDefaultConstructor(CtorDecl);
+}
+
 void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
   // We start with an initial pass over the base classes to collect those that
   // inherit constructors from. If there are none, we can forgo all further
@@ -6094,7 +6265,9 @@
         // Build up a function type for this particular constructor.
         // FIXME: The working paper does not consider that the exception spec
         // for the inheriting constructor might be larger than that of the
-        // source. This code doesn't yet, either.
+        // source. This code doesn't yet, either. When it does, this code will
+        // need to be delayed until after exception specifications and in-class
+        // member initializers are attached.
         const Type *NewCtorType;
         if (params == maxParams)
           NewCtorType = BaseCtorType;

Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Sat Jun 11 12:19:42 2011
@@ -298,8 +298,6 @@
   //   - both are non-throwing, regardless of their form,
   //   - both have the form noexcept(constant-expression) and the constant-
   //     expressions are equivalent,
-  //   - one exception-specification is a noexcept-specification allowing all
-  //     exceptions and the other is of the form throw(type-id-list), or
   //   - both are dynamic-exception-specifications that have the same set of
   //     adjusted types.
   //
@@ -307,8 +305,6 @@
   //   of the form throw(), noexcept, or noexcept(constant-expression) where the
   //   constant-expression yields true.
   //
-  // CWG 1073 Proposed resolution: Strike the third bullet above.
-  //
   // C++0x [except.spec]p4: If any declaration of a function has an exception-
   //   specifier that is not a noexcept-specification allowing all exceptions,
   //   all declarations [...] of that function shall have a compatible
@@ -320,6 +316,9 @@
   ExceptionSpecificationType OldEST = Old->getExceptionSpecType();
   ExceptionSpecificationType NewEST = New->getExceptionSpecType();
 
+  assert(OldEST != EST_Delayed && NewEST != EST_Delayed &&
+         "Shouldn't see unknown exception specifications here");
+
   // Shortcut the case where both have no spec.
   if (OldEST == EST_None && NewEST == EST_None)
     return false;
@@ -506,6 +505,9 @@
 
   ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
 
+  assert(SuperEST != EST_Delayed && SubEST != EST_Delayed &&
+         "Shouldn't see unknown exception specifications here");
+
   // It does not. If the subset contains everything, we've failed.
   if (SubEST == EST_None || SubEST == EST_MSAny) {
     Diag(SubLoc, DiagID);

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sat Jun 11 12:19:42 2011
@@ -1333,8 +1333,8 @@
     // We've found a member of an anonymous struct/union that is
     // inside a non-anonymous struct/union, so in a well-formed
     // program our base object expression is "this".
-    CXXMethodDecl *method = tryCaptureCXXThis();
-    if (!method) {
+    QualType ThisTy = getAndCaptureCurrentThisType();
+    if (ThisTy.isNull()) {
       Diag(loc, diag::err_invalid_member_use_in_static_method)
         << indirectField->getDeclName();
       return ExprError();
@@ -1342,10 +1342,9 @@
 
     // Our base object expression is "this".
     baseObjectExpr =
-      new (Context) CXXThisExpr(loc, method->getThisType(Context),
-                                /*isImplicit=*/ true);
+      new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true);
     baseObjectIsPointer = true;
-    baseQuals = Qualifiers::fromCVRMask(method->getTypeQualifiers());
+    baseQuals = ThisTy->castAs<PointerType>()->getPointeeType().getQualifiers();
   }
 
   // Build the implicit member references to the field of the
@@ -1492,14 +1491,23 @@
 /// conservatively answer "yes", in which case some errors will simply
 /// not be caught until template-instantiation.
 static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
+                                            Scope *CurScope,
                                             const LookupResult &R) {
   assert(!R.empty() && (*R.begin())->isCXXClassMember());
 
   DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
+
   bool isStaticContext =
     (!isa<CXXMethodDecl>(DC) ||
      cast<CXXMethodDecl>(DC)->isStatic());
 
+  // C++0x [expr.prim]p4:
+  //   Otherwise, if a member-declarator declares a non-static data member
+  // of a class X, the expression this is a prvalue of type "pointer to X"
+  // within the optional brace-or-equal-initializer.
+  if (CurScope->getFlags() & Scope::ThisScope)
+    isStaticContext = false;
+
   if (R.isUnresolvableResult())
     return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved;
 
@@ -1547,8 +1555,11 @@
     return IMA_Error_StaticContext;
   }
 
-  CXXRecordDecl *
-        contextClass = cast<CXXMethodDecl>(DC)->getParent()->getCanonicalDecl();
+  CXXRecordDecl *contextClass;
+  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC))
+    contextClass = MD->getParent()->getCanonicalDecl();
+  else
+    contextClass = cast<CXXRecordDecl>(DC);
 
   // [class.mfct.non-static]p3: 
   // ...is used in the body of a non-static member function of class X,
@@ -2026,7 +2037,7 @@
 Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
                                       LookupResult &R,
                                 const TemplateArgumentListInfo *TemplateArgs) {
-  switch (ClassifyImplicitMemberAccess(*this, R)) {
+  switch (ClassifyImplicitMemberAccess(*this, CurScope, R)) {
   case IMA_Instance:
     return BuildImplicitMemberExpr(SS, R, TemplateArgs, true);
 
@@ -2469,19 +2480,18 @@
   // If this is known to be an instance access, go ahead and build an
   // implicit 'this' expression now.
   // 'this' expression now.
-  CXXMethodDecl *method = tryCaptureCXXThis();
-  assert(method && "didn't correctly pre-flight capture of 'this'");
+  QualType ThisTy = getAndCaptureCurrentThisType();
+  assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");
 
-  QualType thisType = method->getThisType(Context);
   Expr *baseExpr = 0; // null signifies implicit access
   if (IsKnownInstance) {
     SourceLocation Loc = R.getNameLoc();
     if (SS.getRange().isValid())
       Loc = SS.getRange().getBegin();
-    baseExpr = new (Context) CXXThisExpr(loc, thisType, /*isImplicit=*/true);
+    baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true);
   }
 
-  return BuildMemberReferenceExpr(baseExpr, thisType,
+  return BuildMemberReferenceExpr(baseExpr, ThisTy,
                                   /*OpLoc*/ SourceLocation(),
                                   /*IsArrow*/ true,
                                   SS,

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sat Jun 11 12:19:42 2011
@@ -17,6 +17,7 @@
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Scope.h"
 #include "clang/Sema/TemplateDeduction.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CXXInheritance.h"
@@ -575,42 +576,54 @@
   return Owned(E);
 }
 
-CXXMethodDecl *Sema::tryCaptureCXXThis() {
+QualType Sema::getAndCaptureCurrentThisType() {
   // Ignore block scopes: we can capture through them.
   // Ignore nested enum scopes: we'll diagnose non-constant expressions
   // where they're invalid, and other uses are legitimate.
   // Don't ignore nested class scopes: you can't use 'this' in a local class.
   DeclContext *DC = CurContext;
+  unsigned NumBlocks = 0;
   while (true) {
-    if (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext();
-    else if (isa<EnumDecl>(DC)) DC = cast<EnumDecl>(DC)->getDeclContext();
+    if (isa<BlockDecl>(DC)) {
+      DC = cast<BlockDecl>(DC)->getDeclContext();
+      ++NumBlocks;
+    } else if (isa<EnumDecl>(DC))
+      DC = cast<EnumDecl>(DC)->getDeclContext();
     else break;
   }
 
-  // If we're not in an instance method, error out.
-  CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC);
-  if (!method || !method->isInstance())
-    return 0;
-
-  // Mark that we're closing on 'this' in all the block scopes, if applicable.
-  for (unsigned idx = FunctionScopes.size() - 1;
-       isa<BlockScopeInfo>(FunctionScopes[idx]);
-       --idx)
-    cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true;
+  QualType ThisTy;
+  if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) {
+    if (method && method->isInstance())
+      ThisTy = method->getThisType(Context);
+  } else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
+    // C++0x [expr.prim]p4:
+    //   Otherwise, if a member-declarator declares a non-static data member
+    // of a class X, the expression this is a prvalue of type "pointer to X"
+    // within the optional brace-or-equal-initializer.
+    Scope *S = getScopeForContext(DC);
+    if (!S || S->getFlags() & Scope::ThisScope)
+      ThisTy = Context.getPointerType(Context.getRecordType(RD));
+  }
+
+  // Mark that we're closing on 'this' in all the block scopes we ignored.
+  if (!ThisTy.isNull())
+    for (unsigned idx = FunctionScopes.size() - 1;
+         NumBlocks; --idx, --NumBlocks)
+      cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true;
 
-  return method;
+  return ThisTy;
 }
 
-ExprResult Sema::ActOnCXXThis(SourceLocation loc) {
+ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
   /// C++ 9.3.2: In the body of a non-static member function, the keyword this
   /// is a non-lvalue expression whose value is the address of the object for
   /// which the function is called.
 
-  CXXMethodDecl *method = tryCaptureCXXThis();
-  if (!method) return Diag(loc, diag::err_invalid_this_use);
+  QualType ThisTy = getAndCaptureCurrentThisType();
+  if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use);
 
-  return Owned(new (Context) CXXThisExpr(loc, method->getThisType(Context),
-                                         /*isImplicit=*/false));
+  return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false));
 }
 
 ExprResult
@@ -2663,7 +2676,6 @@
         return true;
 
       bool FoundAssign = false;
-      bool AllNoThrow = true;
       DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);
       LookupResult Res(Self, DeclarationNameInfo(Name, KeyLoc),
                        Sema::LookupOrdinaryName);
@@ -2675,15 +2687,15 @@
             FoundAssign = true;
             const FunctionProtoType *CPT
                 = Operator->getType()->getAs<FunctionProtoType>();
-            if (!CPT->isNothrow(Self.Context)) {
-              AllNoThrow = false;
-              break;
-            }
+            if (CPT->getExceptionSpecType() == EST_Delayed)
+              return false;
+            if (!CPT->isNothrow(Self.Context))
+              return false;
           }
         }
       }
 
-      return FoundAssign && AllNoThrow;
+      return FoundAssign;
     }
     return false;
   case UTT_HasNothrowCopy:
@@ -2700,7 +2712,6 @@
         return true;
 
       bool FoundConstructor = false;
-      bool AllNoThrow = true;
       unsigned FoundTQs;
       DeclContext::lookup_const_iterator Con, ConEnd;
       for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
@@ -2715,16 +2726,16 @@
           FoundConstructor = true;
           const FunctionProtoType *CPT
               = Constructor->getType()->getAs<FunctionProtoType>();
+          if (CPT->getExceptionSpecType() == EST_Delayed)
+            return false;
           // FIXME: check whether evaluating default arguments can throw.
           // For now, we'll be conservative and assume that they can throw.
-          if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1) {
-            AllNoThrow = false;
-            break;
-          }
+          if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1)
+            return false;
         }
       }
 
-      return FoundConstructor && AllNoThrow;
+      return FoundConstructor;
     }
     return false;
   case UTT_HasNothrowConstructor:
@@ -2750,6 +2761,8 @@
         if (Constructor->isDefaultConstructor()) {
           const FunctionProtoType *CPT
               = Constructor->getType()->getAs<FunctionProtoType>();
+          if (CPT->getExceptionSpecType() == EST_Delayed)
+            return false;
           // TODO: check whether evaluating default arguments can throw.
           // For now, we'll be conservative and assume that they can throw.
           return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0;

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Sat Jun 11 12:19:42 2011
@@ -13,6 +13,7 @@
 #include "clang/Sema/SemaInternal.h"
 #include "TreeTransform.h"
 #include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Template.h"
 #include "clang/Sema/TemplateDeduction.h"
@@ -1744,6 +1745,8 @@
 
   TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
   llvm::SmallVector<Decl*, 4> Fields;
+  llvm::SmallVector<std::pair<FieldDecl*, FieldDecl*>, 4>
+    FieldsWithMemberInitializers;
   for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
          MemberEnd = Pattern->decls_end();
        Member != MemberEnd; ++Member) {
@@ -1766,9 +1769,13 @@
 
     Decl *NewMember = Instantiator.Visit(*Member);
     if (NewMember) {
-      if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
+      if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) {
         Fields.push_back(Field);
-      else if (NewMember->isInvalidDecl())
+        FieldDecl *OldField = cast<FieldDecl>(*Member);
+        if (OldField->getInClassInitializer())
+          FieldsWithMemberInitializers.push_back(std::make_pair(OldField,
+                                                                Field));
+      } else if (NewMember->isInvalidDecl())
         Invalid = true;
     } else {
       // FIXME: Eventually, a NULL return will mean that one of the
@@ -1782,6 +1789,43 @@
               Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
               0);
   CheckCompletedCXXClass(Instantiation);
+
+  // Attach any in-class member initializers now the class is complete.
+  for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) {
+    FieldDecl *OldField = FieldsWithMemberInitializers[I].first;
+    FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
+    Expr *OldInit = OldField->getInClassInitializer();
+    ExprResult NewInit = SubstExpr(OldInit, TemplateArgs);
+
+    // If the initialization is no longer dependent, check it now.
+    if ((OldField->getType()->isDependentType() || OldInit->isTypeDependent())
+        && !NewField->getType()->isDependentType()
+        && !NewInit.get()->isTypeDependent()) {
+      // FIXME: handle list-initialization
+      SourceLocation EqualLoc = NewField->getLocation();
+      NewInit = PerformCopyInitialization(
+        InitializedEntity::InitializeMember(NewField), EqualLoc,
+        NewInit.release());
+
+      if (!NewInit.isInvalid()) {
+        CheckImplicitConversions(NewInit.get(), EqualLoc);
+
+        // C++0x [class.base.init]p7:
+        //   The initialization of each base and member constitutes a
+        //   full-expression.
+        NewInit = MaybeCreateExprWithCleanups(NewInit);
+      }
+    }
+
+    if (NewInit.isInvalid())
+      NewField->setInvalidDecl();
+    else
+      NewField->setInClassInitializer(NewInit.release());
+  }
+
+  if (!FieldsWithMemberInitializers.empty())
+    ActOnFinishDelayedMemberInitializers(Instantiation);
+
   if (Instantiation->isInvalidDecl())
     Invalid = true;
   else {

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Jun 11 12:19:42 2011
@@ -477,6 +477,7 @@
                                             D->getLocation(),
                                             D->isMutable(),
                                             BitWidth,
+                                            D->hasInClassInitializer(),
                                             D->getTypeSpecStartLoc(),
                                             D->getAccess(),
                                             0);

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Sat Jun 11 12:19:42 2011
@@ -1593,6 +1593,8 @@
       Error = 0; // Function prototype
       break;
     case Declarator::MemberContext:
+      if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
+        break;
       switch (cast<TagDecl>(CurContext)->getTagKind()) {
       case TTK_Enum: assert(0 && "unhandled tag kind"); break;
       case TTK_Struct: Error = 1; /* Struct member */ break;

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Sat Jun 11 12:19:42 2011
@@ -6697,8 +6697,12 @@
 ExprResult
 TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
   DeclContext *DC = getSema().getFunctionLevelDeclContext();
-  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC);
-  QualType T = MD->getThisType(getSema().Context);
+  QualType T;
+  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC))
+    T = MD->getThisType(getSema().Context);
+  else
+    T = getSema().Context.getPointerType(
+      getSema().Context.getRecordType(cast<CXXRecordDecl>(DC)));
 
   if (!getDerived().AlwaysRebuild() && T == E->getType())
     return SemaRef.Owned(E);

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Sat Jun 11 12:19:42 2011
@@ -677,8 +677,11 @@
 void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
   VisitDeclaratorDecl(FD);
   FD->setMutable(Record[Idx++]);
-  if (Record[Idx++])
+  int BitWidthOrInitializer = Record[Idx++];
+  if (BitWidthOrInitializer == 1)
     FD->setBitWidth(Reader.ReadExpr(F));
+  else if (BitWidthOrInitializer == 2)
+    FD->setInClassInitializer(Reader.ReadExpr(F));
   if (!FD->getDeclName()) {
     FieldDecl *Tmpl = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++]));
     if (Tmpl)
@@ -1649,7 +1652,7 @@
     break;
   case DECL_FIELD:
     D = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 0,
-                          QualType(), 0, 0, false);
+                          QualType(), 0, 0, false, false);
     break;
   case DECL_INDIRECTFIELD:
     D = IndirectFieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(),

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Sat Jun 11 12:19:42 2011
@@ -599,9 +599,11 @@
 void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
   VisitDeclaratorDecl(D);
   Record.push_back(D->isMutable());
-  Record.push_back(D->getBitWidth()? 1 : 0);
+  Record.push_back(D->getBitWidth()? 1 : D->hasInClassInitializer() ? 2 : 0);
   if (D->getBitWidth())
     Writer.AddStmt(D->getBitWidth());
+  else if (D->hasInClassInitializer())
+    Writer.AddStmt(D->getInClassInitializer());
   if (!D->getDeclName())
     Writer.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D), Record);
 
@@ -612,6 +614,7 @@
       !D->isReferenced() &&
       D->getPCHLevel() == 0 &&
       !D->getBitWidth() &&
+      !D->hasInClassInitializer() &&
       !D->hasExtInfo() &&
       !ObjCIvarDecl::classofKind(D->getKind()) &&
       !ObjCAtDefsFieldDecl::classofKind(D->getKind()) &&

Added: cfe/trunk/test/CXX/class/class.mem/p5-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.mem/p5-0x.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/CXX/class/class.mem/p5-0x.cpp (added)
+++ cfe/trunk/test/CXX/class/class.mem/p5-0x.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s 
+
+int f();
+
+struct S 
+{
+  int a = f(); // ok
+  int b = g(); // expected-error {{use of undeclared identifier 'g'}}
+};

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp Sat Jun 11 12:19:42 2011
@@ -22,14 +22,21 @@
   new const auto (0);
   new (auto) (0.0);
 
-#if 0
-  // When clang supports for-range:
-  for (auto i : {1,2,3}) {
+  int arr[] = {1, 2, 3};
+  for (auto i : arr) {
   }
-
-  // When clang supports inline initialization of members.
-  class X {
-    static const auto &n = 'x';
-  };
-#endif
 }
+
+class X {
+  static const auto n = 'x';
+
+  auto m = 0; // expected-error {{'auto' not allowed in non-static class member}}
+};
+
+struct S {
+  static const auto a; // expected-error {{declaration of variable 'a' with type 'auto const' requires an initializer}}
+  static const auto b = 0;
+  static const int c;
+};
+const int S::b;
+const auto S::c = 0;

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp Sat Jun 11 12:19:42 2011
@@ -3,13 +3,13 @@
 struct S {
   virtual ~S();
 
-  auto a; // expected-error{{'auto' not allowed in struct member}}
-  auto *b; // expected-error{{'auto' not allowed in struct member}}
-  const auto c; // expected-error{{'auto' not allowed in struct member}}
+  auto a; // expected-error{{'auto' not allowed in non-static struct member}}
+  auto *b; // expected-error{{'auto' not allowed in non-static struct member}}
+  const auto c; // expected-error{{'auto' not allowed in non-static struct member}}
 
   void f() throw (auto); // expected-error{{'auto' not allowed here}}
 
-  friend auto; // expected-error{{'auto' not allowed in struct member}}
+  friend auto; // expected-error{{'auto' not allowed in non-static struct member}}
 
   operator auto(); // expected-error{{'auto' not allowed here}}
 };

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp Sat Jun 11 12:19:42 2011
@@ -7,8 +7,8 @@
 
 class K {
   virtual ~K();
-  // FIXME: the diagnostic here isn't very good
-  operator struct S {} (); // expected-error 2{{}}
+  // FIXME: the diagnostic here is really bad
+  operator struct S {} (); // expected-error 2{{}} expected-note {{}}
 };
 
 void f() {

Added: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+// An aggregate is an array or a class...
+struct Aggr {
+private:
+  static const int n;
+  void f();
+protected:
+  struct Inner { int m; };
+public:
+  bool &br;
+};
+bool b;
+Aggr ag = { b };
+
+// with no user-provided constructors, ...
+struct NonAggr1a {
+  NonAggr1a(int, int);
+  int k;
+};
+// In C++03, this is {{non-aggregate type 'NonAggr1a'}}.
+// In C++0x, 'user-provided' is only defined for special member functions, so
+// this type is considered to be an aggregate. This is probably a langauge
+// defect.
+NonAggr1a na1a = { 42 };
+
+struct NonAggr1b {
+  NonAggr1b(const NonAggr1b &);
+  int k;
+};
+NonAggr1b na1b = { 42 }; // expected-error {{non-aggregate type 'NonAggr1b'}}
+
+// no brace-or-equal-initializers for non-static data members, ...
+struct NonAggr2 {
+  int m = { 123 };
+};
+NonAggr2 na2 = { 42 }; // expected-error {{non-aggregate type 'NonAggr2'}}
+
+// no private...
+struct NonAggr3 {
+private:
+  int n;
+};
+NonAggr3 na3 = { 42 }; // expected-error {{non-aggregate type 'NonAggr3'}}
+
+// or protected non-static data members, ...
+struct NonAggr4 {
+protected:
+  int n;
+};
+NonAggr4 na4 = { 42 }; // expected-error {{non-aggregate type 'NonAggr4'}}
+
+// no base classes, ...
+struct NonAggr5 : Aggr {
+};
+NonAggr5 na5 = { b }; // expected-error {{non-aggregate type 'NonAggr5'}}
+
+// and no virtual functions.
+struct NonAggr6 {
+  virtual void f();
+  int n;
+};
+NonAggr6 na6 = { 42 }; // expected-error {{non-aggregate type 'NonAggr6'}}

Added: cfe/trunk/test/CXX/dcl.decl/dcl.init/p14-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/p14-0x.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/p14-0x.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/p14-0x.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+struct NoDefault {
+  NoDefault() = delete; // expected-note {{here}}
+  NoDefault(int);
+};
+struct Explicit { // expected-note {{candidate}} expected-note {{here}}
+  explicit Explicit(int);
+};
+struct NoCopy {
+  NoCopy();
+  NoCopy(const NoCopy &) = delete; // expected-note {{here}}
+};
+struct NoMove {
+  NoMove();
+  NoMove(NoMove &&) = delete; // expected-note {{here}}
+};
+class Private {
+  Private(int); // expected-note {{here}}
+public:
+  Private();
+};
+class Friend {
+  friend class S;
+  Friend(int);
+};
+
+
+class S {
+  NoDefault nd1;
+  NoDefault nd2 = 42;
+  Explicit e1; // expected-note {{here}}
+  Explicit e2 = 42; // expected-error {{no viable conversion}}
+  NoCopy nc = NoCopy(); // expected-error {{call to deleted}}
+  NoMove nm = NoMove(); // expected-error {{call to deleted}}
+  Private p = 42; // expected-error {{private constructor}}
+  Friend f = 42;
+
+  S() {} // expected-error {{call to deleted constructor of 'NoDefault'}} \
+            expected-error {{must explicitly initialize the member 'e1' which does not have a default constructor}}
+  S(int) : nd1(42), e1(42) {}
+};
+
+// FIXME: test the other forms which use copy-initialization

Modified: cfe/trunk/test/CXX/except/except.spec/p14.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p14.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/test/CXX/except/except.spec/p14.cpp (original)
+++ cfe/trunk/test/CXX/except/except.spec/p14.cpp Sat Jun 11 12:19:42 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -verify %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -verify -std=c++0x %s
 struct A { };
 struct B { };
 struct C { };
@@ -27,3 +27,15 @@
   CA2 &(CA2::*captr3)(const CA2&) throw(A) = &CA2::operator=; // expected-error{{target exception specification is not superset of source}}
   CA2 &(CA2::*captr4)(const CA2&) throw(B) = &CA2::operator=; // expected-error{{target exception specification is not superset of source}}
 }
+
+// In-class member initializers.
+struct IC0 {
+  int inClassInit = 0;
+};
+struct IC1 {
+  int inClassInit = (throw B(), 0);
+};
+// FIXME: the exception specification on the default constructor is wrong:
+// we cannot currently compute the set of thrown types.
+static_assert(noexcept(IC0()), "IC0() does not throw");
+static_assert(!noexcept(IC1()), "IC1() throws");

Added: cfe/trunk/test/CXX/expr/expr.prim/p12-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/p12-0x.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/p12-0x.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.prim/p12-0x.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+struct S {
+  int *j = &nonexistent; // expected-error {{use of undeclared identifier 'nonexistent'}}
+  int *m = &n; // ok
+
+  int n = f(); // ok
+  int f();
+};
+
+int i = sizeof(S::m); // ok
+int j = sizeof(S::m + 42); // ok

Added: cfe/trunk/test/CXX/expr/expr.prim/p4-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/p4-0x.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/p4-0x.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.prim/p4-0x.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+struct S {
+  S *p = this; // ok
+  decltype(this) q; // expected-error {{invalid use of 'this' outside of a nonstatic member function}} \
+                       expected-error {{C++ requires a type specifier for all declarations}}
+
+  int arr[sizeof(this)]; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
+  int sz = sizeof(this); // ok
+};

Added: cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp (added)
+++ cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,173 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+
+struct DefaultedDefCtor1 {};
+struct DefaultedDefCtor2 { DefaultedDefCtor2() = default; };
+struct DeletedDefCtor { DeletedDefCtor() = delete; DeletedDefCtor(int); };
+class PrivateDefCtor { PrivateDefCtor() = default; public: PrivateDefCtor(int); };
+struct DeletedDtor { ~DeletedDtor() = delete; };
+class PrivateDtor { ~PrivateDtor() = default; };
+class Friend {
+  Friend() = default; ~Friend() = default;
+  friend struct NotDeleted6c;
+  friend struct NotDeleted7i;
+  friend struct NotDeleted7j;
+  friend struct NotDeleted7k;
+};
+struct UserProvidedDefCtor { UserProvidedDefCtor() {} };
+int n;
+
+
+// A defaulted default constructor for a class X is defined as deleted if:
+
+// - X is a union-like class that has a variant member with a non-trivial
+// default constructor,
+union Deleted1a { UserProvidedDefCtor u; }; // expected-note {{deleted here}}
+Deleted1a d1a; // expected-error {{deleted constructor}}
+// FIXME: treating this as having a deleted default constructor is probably a
+// bug in the standard.
+union Deleted1b { UserProvidedDefCtor u = UserProvidedDefCtor(); }; // expected-note {{deleted here}}
+Deleted1b d1b; // expected-error {{deleted constructor}}
+union NotDeleted1a { DefaultedDefCtor1 nu; };
+NotDeleted1a nd1a;
+// FIXME: clang implements the pre-FDIS rule, under which DefaultedDefCtor2's
+// default constructor is non-trivial.
+union NotDeleted1b { DefaultedDefCtor2 nu; }; // unexpected-note {{deleted here}}
+NotDeleted1b nd1b; // unexpected-error {{deleted constructor}}
+
+// - any non-static data member with no brace-or-equal-initializer is of
+// reference type,
+class Deleted2a { Deleted2a() = default; int &a; }; // expected-note {{deleted here}}
+Deleted2a d2a; // expected-error {{deleted constructor}}
+class NotDeleted2a { int &a = n; };
+NotDeleted2a nd2a;
+class NotDeleted2b { int &a = error; }; // expected-error {{undeclared identifier}}
+NotDeleted2b nd2b;
+
+// - any non-variant non-static data member of const qualified type (or array
+// thereof) with no brace-or-equal-initializer does not have a user-provided
+// default constructor,
+class Deleted3a { const int a; }; // expected-note {{here}} \
+                                     expected-warning {{does not declare any constructor}} \
+                                     expected-note {{will never be initialized}}
+Deleted3a d3a; // expected-error {{deleted constructor}}
+class Deleted3b { const DefaultedDefCtor1 a[42]; }; // expected-note {{here}}
+Deleted3b d3b; // expected-error {{deleted constructor}}
+// FIXME: clang implements the pre-FDIS rule, under which DefaultedDefCtor2's
+// default constructor is user-provided.
+class Deleted3c { const DefaultedDefCtor2 a; }; // desired-note {{here}}
+Deleted3c d3c; // desired-error {{deleted constructor}}
+class NotDeleted3a { const int a = 0; };
+NotDeleted3a nd3a;
+class NotDeleted3b { const DefaultedDefCtor1 a[42] = {}; };
+NotDeleted3b nd3b;
+class NotDeleted3c { const DefaultedDefCtor2 a = DefaultedDefCtor2(); };
+NotDeleted3c nd3c;
+union NotDeleted3d { const int a; int b; };
+NotDeleted3d nd3d;
+// FIXME: this class should not have a deleted default constructor.
+union NotDeleted3e { const DefaultedDefCtor1 a[42]; int b; }; // unexpected-note {{here}}
+NotDeleted3e nd3e; // unexpected-error {{deleted constructor}}
+// FIXME: clang implements the pre-FDIS rule, under which DefaultedDefCtor2 is
+// non-trivial.
+union NotDeleted3f { const DefaultedDefCtor2 a; int b; }; // unexpected-note {{here}}
+NotDeleted3f nd3f; // unexpected-error {{deleted constructor}}
+
+// - X is a union and all of its variant members are of const-qualified type (or
+// array thereof),
+union Deleted4a { const int a; const int b; const UserProvidedDefCtor c; }; // expected-note {{here}}
+Deleted4a d4a; // expected-error {{deleted constructor}}
+union Deleted4b { const int a; int b; };
+Deleted4b d4b;
+
+// - X is a non-union class and all members of any anonymous union member are of
+// const-qualified type (or array thereof),
+struct Deleted5a { union { const int a; }; union { int b; }; }; // expected-note {{here}}
+Deleted5a d5a; // expected-error {{deleted constructor}}
+struct Deleted5b { union { const int a; int b; }; union { const int c; int d; }; };
+Deleted5b d5b;
+
+// - any direct or virtual base class, or non-static data member with no
+// brace-or-equal-initializer, has class type M (or array thereof) and either
+// M has no default constructor or overload resolution as applied to M's default
+// constructor results in an ambiguity or in a function that is deleted or
+// inaccessible from the defaulted default constructor, or
+struct Deleted6a : Deleted2a {}; // expected-note {{here}}
+Deleted6a d6a; // expected-error {{deleted constructor}}
+struct Deleted6b : virtual Deleted2a {}; // expected-note {{here}}
+Deleted6b d6b; // expected-error {{deleted constructor}}
+struct Deleted6c { Deleted2a a; }; // expected-note {{here}}
+Deleted6c d6c; // expected-error {{deleted constructor}}
+struct Deleted6d { DeletedDefCtor a; }; // expected-note {{here}}
+Deleted6d d6d; // expected-error {{deleted constructor}}
+struct NotDeleted6a { DeletedDefCtor a = 0; };
+NotDeleted6a nd6a;
+struct Deleted6e { PrivateDefCtor a; }; // expected-note {{here}}
+Deleted6e d6e; // expected-error {{deleted constructor}}
+struct NotDeleted6b { PrivateDefCtor a = 0; };
+NotDeleted6b nd6b;
+struct NotDeleted6c { Friend a; };
+NotDeleted6c nd6c;
+
+// - any direct or virtual base class or non-static data member has a type with
+// a destructor that is deleted or inaccessible from the defaulted default
+// constructor.
+struct Deleted7a : DeletedDtor {}; // expected-note {{here}}
+Deleted7a d7a; // expected-error {{deleted constructor}}
+struct Deleted7b : virtual DeletedDtor {}; // expected-note {{here}}
+Deleted7b d7b; // expected-error {{deleted constructor}}
+struct Deleted7c { DeletedDtor a; }; // expected-note {{here}}
+Deleted7c d7c; // expected-error {{deleted constructor}}
+struct Deleted7d { DeletedDtor a = {}; }; // expected-note {{here}}
+Deleted7d d7d; // expected-error {{deleted constructor}}
+struct Deleted7e : PrivateDtor {}; // expected-note {{here}}
+Deleted7e d7e; // expected-error {{deleted constructor}}
+struct Deleted7f : virtual PrivateDtor {}; // expected-note {{here}}
+Deleted7f d7f; // expected-error {{deleted constructor}}
+struct Deleted7g { PrivateDtor a; }; // expected-note {{here}}
+Deleted7g d7g; // expected-error {{deleted constructor}}
+struct Deleted7h { PrivateDtor a = {}; }; // expected-note {{here}}
+Deleted7h d7h; // expected-error {{deleted constructor}}
+struct NotDeleted7i : Friend {};
+NotDeleted7i d7i;
+struct NotDeleted7j : virtual Friend {};
+NotDeleted7j d7j;
+struct NotDeleted7k { Friend a; };
+NotDeleted7k d7k;
+
+
+class Trivial { static const int n = 42; };
+static_assert(__has_trivial_constructor(Trivial), "Trivial is nontrivial");
+
+// A default constructor is trivial if it is not user-provided and if:
+class NonTrivialDefCtor1 { NonTrivialDefCtor1(); };
+static_assert(!__has_trivial_constructor(NonTrivialDefCtor1), "NonTrivialDefCtor1 is trivial");
+
+// - its class has no virtual functions (10.3) and no virtual base classes (10.1), and
+class NonTrivialDefCtor2 { virtual void f(); };
+static_assert(!__has_trivial_constructor(NonTrivialDefCtor2), "NonTrivialDefCtor2 is trivial");
+class NonTrivialDefCtor3 : virtual Trivial {};
+static_assert(!__has_trivial_constructor(NonTrivialDefCtor3), "NonTrivialDefCtor3 is trivial");
+
+// - no non-static data member of its class has a brace-or-equal-initializer, and
+class NonTrivialDefCtor4 { int m = 52; };
+static_assert(!__has_trivial_constructor(NonTrivialDefCtor4), "NonTrivialDefCtor4 is trivial");
+
+// - all the direct base classes of its class have trivial default constructors, and
+class NonTrivialDefCtor5 : NonTrivialDefCtor1 {};
+static_assert(!__has_trivial_constructor(NonTrivialDefCtor5), "NonTrivialDefCtor5 is trivial");
+
+// - for all the non-static data members of its class that are of class type (or array thereof), each such class
+// has a trivial default constructor.
+class NonTrivialDefCtor6 { NonTrivialDefCtor1 t; };
+static_assert(!__has_trivial_constructor(NonTrivialDefCtor6), "NonTrivialDefCtor5 is trivial");
+
+// Otherwise, the default constructor is non-trivial.
+class Trivial2 { Trivial2() = delete; };
+//static_assert(__has_trivial_constructor(Trivial2), "NonTrivialDefCtor2 is trivial");
+// FIXME: clang implements the pre-FDIS rule, under which this class is non-trivial.
+static_assert(!__has_trivial_constructor(Trivial2), "NonTrivialDefCtor2 is trivial");
+
+class Trivial3 { Trivial3() = default; };
+//static_assert(__has_trivial_constructor(Trivial3), "NonTrivialDefCtor3 is trivial");
+// FIXME: clang implements the pre-FDIS rule, under which this class is non-trivial.
+static_assert(!__has_trivial_constructor(Trivial3), "NonTrivialDefCtor3 is trivial");

Added: cfe/trunk/test/CXX/special/class.init/class.base.init/p8-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.init/class.base.init/p8-0x.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/CXX/special/class.init/class.base.init/p8-0x.cpp (added)
+++ cfe/trunk/test/CXX/special/class.init/class.base.init/p8-0x.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+int n;
+struct S {
+  int &a; // expected-note 2{{here}}
+  int &b = n;
+
+  S() {} // expected-error {{constructor for 'S' must explicitly initialize the reference member 'a'}}
+  S(int) : a(n) {} // ok
+  S(char) : b(n) {} // expected-error {{constructor for 'S' must explicitly initialize the reference member 'a'}}
+  S(double) : a(n), b(n) {} // ok
+};
+
+union U {
+  int a = 0;
+  char b = 'x';
+
+  // FIXME: these should all be rejected
+  U() {} // desired-error {{at most one member of a union may be initialized}}
+  U(int) : a(1) {} // desired-error {{at most one member of a union may be initialized}}
+  U(char) : b('y') {} // desired-error {{at most one member of a union may be initialized}}
+  U(double) : a(1), b('y') {} // desired-error {{at most one member of a union may be initialized}}
+};

Added: cfe/trunk/test/CXX/special/class.init/class.base.init/p9-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.init/class.base.init/p9-0x.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/CXX/special/class.init/class.base.init/p9-0x.cpp (added)
+++ cfe/trunk/test/CXX/special/class.init/class.base.init/p9-0x.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -std=c++0x %s -O1 -emit-llvm -o - | FileCheck %s
+
+struct S {
+  int n = 10;
+  int m = 2 * n;
+
+  S() {}
+  S(int a) : n(a) {}
+  S(int a, int b) : n(a), m(b) {}
+
+  struct T {
+    T *that = this;
+  };
+};
+
+template<typename T>
+struct U {
+  T *r = &q;
+  T q = 42;
+  U *p = this;
+};
+
+S a;
+// CHECK: @a = {{.*}} { i32 10, i32 20 }
+
+S b(5);
+// CHECK: @b = {{.*}} { i32 5, i32 10 }
+
+S c(3, 9);
+// CHECK: @c = {{.*}} { i32 3, i32 9 }
+
+S::T d;
+// CHECK: @d = {{.*}} { {{.*}} @d }
+
+U<S> e;
+// CHECK: @e = {{.*}} { {{.*}} { i32 42, i32 84 }, {{.*}} @e }

Added: cfe/trunk/test/CodeGenCXX/member-init-ctor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/member-init-ctor.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/member-init-ctor.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/member-init-ctor.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 %s -std=c++0x -emit-llvm -o - | FileCheck %s
+
+bool b();
+struct S {
+  int n = b() ? S().n + 1 : 0;
+};
+
+S s;
+
+// CHECK: define{{.*}} void @_ZN1SC2Ev(
+// CHECK-NOT }
+// CHECK: call {{.*}} @_Z1bv()
+// CHECK-NOT }
+// CHECK: call {{.*}} @_ZN1SC1Ev(

Modified: cfe/trunk/test/CodeGenObjCXX/blocks.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/blocks.mm?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/blocks.mm (original)
+++ cfe/trunk/test/CodeGenObjCXX/blocks.mm Sat Jun 11 12:19:42 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -x objective-c++ -fblocks -triple x86_64-apple-darwin %s
+// RUN: %clang_cc1 -x objective-c++ -fblocks -triple x86_64-apple-darwin %s -verify -emit-llvm -o %t
 // rdar://8979379
 
 @interface A
@@ -28,3 +28,19 @@
     return bar(objectCreationBlock);
 }
 
+// Test4
+struct S {
+  S *(^a)() = ^{ // expected-warning {{C++0x}}
+    return this;
+  };
+};
+S s;
+
+// Test5
+struct X {
+  void f() {
+    ^ {
+      struct Nested { Nested *ptr = this; }; // expected-warning {{C++0x}}
+    } ();
+  };
+};

Added: cfe/trunk/test/PCH/cxx-member-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-member-init.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/PCH/cxx-member-init.cpp (added)
+++ cfe/trunk/test/PCH/cxx-member-init.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,22 @@
+// Test this without pch.
+// RUN: %clang_cc1 -x c++ -std=c++0x -DHEADER -DSOURCE -fsyntax-only -emit-llvm -o - %s
+
+// Test with pch.
+// RUN: %clang_cc1 -x c++ -std=c++0x -DHEADER -emit-pch -o %t %s
+// RUN: %clang_cc1 -x c++ -std=c++0x -DHEADER -include-pch %t -fsyntax-only -emit-llvm -o - %s 
+
+#ifdef HEADER
+int n;
+struct S {
+  int *p = &m;
+  int &m = n;
+  S *that = this;
+};
+#endif
+
+#ifdef SOURCE
+S s;
+#elif HEADER
+#undef HEADER
+#define SOURCE
+#endif

Added: cfe/trunk/test/Parser/cxx0x-member-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-member-initializers.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-member-initializers.cpp (added)
+++ cfe/trunk/test/Parser/cxx0x-member-initializers.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+// Make sure we don't run off the end of the stream when parsing a deferred
+// initializer.
+int a; // expected-note {{previous}}
+struct S {
+  int n = 4 + ; // expected-error {{expected expression}}
+} a; // expected-error {{redefinition}}
+
+// Make sure we use all of the tokens.
+struct T {
+  int a = 1 // expected-error {{expected ';' at end of declaration list}}
+  int b = 2;
+  int c = b; // expected-error {{undeclared identifier}}
+};

Modified: cfe/trunk/test/SemaCXX/PR9572.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR9572.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/PR9572.cpp (original)
+++ cfe/trunk/test/SemaCXX/PR9572.cpp Sat Jun 11 12:19:42 2011
@@ -1,13 +1,13 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 class Base {
-  virtual ~Base();
+  virtual ~Base(); // expected-note {{implicitly declared private here}}
 };
-struct Foo : public Base {
-  const int kBlah = 3; // expected-error{{fields can only be initialized in constructors}}
+struct Foo : public Base { // expected-error {{base class 'Base' has private destructor}}
+  const int kBlah = 3; // expected-warning {{accepted as a C++0x extension}}
   Foo();
 };
 struct Bar : public Foo {
-  Bar() { }
+  Bar() { } // expected-note {{implicit default destructor for 'Foo' first required here}}
 };
 struct Baz {
   Foo f;

Modified: cfe/trunk/test/SemaCXX/class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/class.cpp (original)
+++ cfe/trunk/test/SemaCXX/class.cpp Sat Jun 11 12:19:42 2011
@@ -34,7 +34,7 @@
 
   enum E1 { en1, en2 };
 
-  int i = 0; // expected-error {{fields can only be initialized in constructors}}
+  int i = 0; // expected-warning {{in-class initialization of non-static data member accepted as a C++0x extension}}
   static int si = 0; // expected-error {{non-const static data member must be initialized out of line}}
   static const NestedC ci = 0; // expected-error {{static data member of type 'const C::NestedC' must be initialized out of line}}
   static const int nci = vs; // expected-error {{in-class initializer is not a constant expression}}

Added: cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp (added)
+++ cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++0x -Wall %s
+
+template<bool b> struct ExceptionIf { static int f(); };
+template<> struct ExceptionIf<false> { typedef int f; };
+
+// The exception specification of a defaulted default constructor depends on
+// the contents of in-class member initializers. However, the in-class member
+// initializers can depend on the exception specification of the constructor,
+// since the class is considered complete within them. We reject any such cases.
+namespace InClassInitializers {
+  // Noexcept::Noexcept() is implicitly declared as noexcept(false), because it
+  // directly invokes ThrowSomething(). However...
+  //
+  // If noexcept(Noexcept()) is false, then Noexcept() is a constant expression,
+  // so noexcept(Noexcept()) is true. But if noexcept(Noexcept()) is true, then
+  // Noexcept::Noexcept is not declared constexpr, therefore noexcept(Noexcept())
+  // is false.
+  bool ThrowSomething() noexcept(false);
+  struct ConstExpr {
+    bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{exception specification is not available until end of class definition}}
+  };
+  // We can use it now.
+  bool w = noexcept(ConstExpr());
+
+  // Much more obviously broken: we can't parse the initializer without already
+  // knowing whether it produces a noexcept expression.
+  struct TemplateArg {
+    int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{exception specification is not available until end of class definition}}
+  };
+  bool x = noexcept(TemplateArg());
+
+  // And within a nested class.
+  struct Nested {
+    struct Inner {
+      int n = ExceptionIf<noexcept(Nested())>::f(); // expected-error {{exception specification is not available until end of class definition}}
+    } inner;
+  };
+  bool y = noexcept(Nested());
+  bool z = noexcept(Nested::Inner());
+}
+
+// FIXME:
+// The same problem arises in delayed parsing of exception specifications,
+// which clang does not yet support.
+namespace ExceptionSpecification {
+  struct Nested { // expected-note {{not complete}}
+    struct T {
+      T() noexcept(!noexcept(Nested())); // expected-error {{incomplete type}}
+    } t;
+  };
+}
+
+// FIXME:
+// The same problem arises in delayed parsing of default arguments,
+// which clang does not yet support.
+namespace DefaultArgument {
+  // FIXME: this diagnostic is completely wrong.
+  struct Default { // expected-note {{explicitly marked deleted here}}
+    struct T {
+      T(int = ExceptionIf<noexcept(Default())::f()); // expected-error {{call to deleted constructor}}
+    } t;
+  };
+}

Added: cfe/trunk/test/SemaCXX/member-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-init.cpp?rev=132878&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/member-init.cpp (added)
+++ cfe/trunk/test/SemaCXX/member-init.cpp Sat Jun 11 12:19:42 2011
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++0x -Wall %s
+
+struct Bitfield {
+  int n : 3 = 7; // expected-error {{bitfield member cannot have an in-class initializer}}
+};
+
+int a;
+class NoWarning {
+  int &n = a;
+public:
+  int &GetN() { return n; }
+};
+
+bool b();
+int k;
+struct Recurse {
+  int &n = b() ? Recurse().n : k; // ok
+};
+
+struct UnknownBound {
+  int as[] = { 1, 2, 3 }; // expected-error {{array bound cannot be deduced from an in-class initializer}}
+  int bs[4] = { 4, 5, 6, 7 };
+  int cs[] = { 8, 9, 10 }; // expected-error {{array bound cannot be deduced from an in-class initializer}}
+};
+
+template<int n> struct T { static const int B; };
+template<> struct T<2> { template<int C, int D> using B = int; };
+const int C = 0, D = 0;
+struct S {
+  int as[] = { decltype(x)::B<C, D>(0) }; // expected-error {{array bound cannot be deduced from an in-class initializer}}
+  T<sizeof(as) / sizeof(int)> x; // expected-error {{requires a type specifier}}
+};
+
+struct ThrowCtor { ThrowCtor(int) noexcept(false); };
+struct NoThrowCtor { NoThrowCtor(int) noexcept(true); };
+
+struct Throw { ThrowCtor tc = 42; };
+struct NoThrow { NoThrowCtor tc = 42; };
+
+static_assert(!noexcept(Throw()), "incorrect exception specification");
+static_assert(noexcept(NoThrow()), "incorrect exception specification");
+
+struct CheckExcSpec {
+  CheckExcSpec() noexcept(true) = default;
+  int n = 0;
+};
+struct CheckExcSpecFail {
+  CheckExcSpecFail() noexcept(true) = default; // expected-error {{exception specification of explicitly defaulted default constructor does not match the calculated one}}
+  ThrowCtor tc = 123;
+};

Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=132878&r1=132877&r2=132878&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Sat Jun 11 12:19:42 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify %s 
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++0x %s 
 #define T(b) (b) ? 1 : -1
 #define F(b) (b) ? -1 : 1
 
@@ -38,8 +38,7 @@
 struct DerivesEmpty : Empty {};
 struct HasCons { HasCons(int); };
 struct HasCopyAssign { HasCopyAssign operator =(const HasCopyAssign&); };
-struct HasMoveAssign { HasMoveAssign operator =(const HasMoveAssign&&); }; // \
-    // expected-warning {{rvalue references}}
+struct HasMoveAssign { HasMoveAssign operator =(const HasMoveAssign&&); };
 struct HasDest { ~HasDest(); };
 class  HasPriv { int priv; };
 class  HasProt { protected: int prot; };
@@ -1069,7 +1068,7 @@
 };
 
 struct HasMove {
-  HasMove(HasMove&& cp); // expected-warning {{rvalue references}}
+  HasMove(HasMove&& cp);
 };
 
 struct HasTemplateCons {
@@ -1253,6 +1252,9 @@
   { int arr[F(__has_nothrow_copy(cvoid))]; }
 }
 
+template<bool b> struct assert_expr;
+template<> struct assert_expr<true> {};
+
 void has_nothrow_constructor() {
   { int arr[T(__has_nothrow_constructor(Int))]; }
   { int arr[T(__has_nothrow_constructor(IntAr))]; }
@@ -1280,6 +1282,11 @@
   { int arr[F(__has_nothrow_constructor(void))]; }
   { int arr[F(__has_nothrow_constructor(cvoid))]; }
   { int arr[F(__has_nothrow_constructor(HasTemplateCons))]; }
+
+  // While parsing an in-class initializer, the constructor is not known to be
+  // non-throwing yet.
+  struct HasInClassInit { int n = (assert_expr<!__has_nothrow_constructor(HasInClassInit)>(), 0); };
+  { int arr[T(__has_nothrow_constructor(HasInClassInit))]; }
 }
 
 void has_virtual_destructor() {





More information about the cfe-commits mailing list