]> granicus.if.org Git - clang/commitdiff
Properly parse the 'default' and 'delete' keywords.
authorSean Hunt <scshunt@csclub.uwaterloo.ca>
Thu, 12 May 2011 06:15:49 +0000 (06:15 +0000)
committerSean Hunt <scshunt@csclub.uwaterloo.ca>
Thu, 12 May 2011 06:15:49 +0000 (06:15 +0000)
They are actually grammatically considered definitions and parsed
accordingly.

This fixes the outstanding bugs regarding defaulting functions after
their declarations.

We now really nicely diagnose the following construct (try it!)

int foo() = delete, bar;

Still todo: Defaulted functions other than default constructors
            Test cases (including for the above construct)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131228 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticCommonKinds.td
include/clang/Basic/DiagnosticParseKinds.td
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Parse/Parser.h
include/clang/Sema/Sema.h
lib/Parse/ParseCXXInlineMethods.cpp
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/Parser.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp

index 4383555c11e78db52a9368715b9d3857b9d51f3a..50110fb537292b4b361f47888be14e845f522c85 100644 (file)
@@ -56,6 +56,8 @@ def err_default_special_members : Error<
   "only special member functions may be defaulted">;
 def err_friends_define_only_namespace_scope : Error<
   "cannot define a function with non-namespace scope in a friend declaration">;
+def err_deleted_non_function : Error<
+  "only functions can have deleted definitions">;
 
 // Sema && Lex
 def ext_longlong : Extension<
index 3a8a708afa0bc3b5ac993f8488351abc9a088c0c..45275ea3676d13e7e3b33dc0c58730cf947aed99 100644 (file)
@@ -343,6 +343,9 @@ def err_operator_string_not_empty : Error<
 // Classes.
 def err_anon_type_definition : Error<
   "declaration of anonymous %0 must be a definition">;
+def err_default_delete_in_multiple_declaration : Error<
+  "'= %select{default|delete}0' is a function definition and must occur in a "
+  "standalone declaration">;
 
 def err_cxx0x_attribute_forbids_arguments : Error<
   "C++0x attribute '%0' cannot have an argument list">;
index 2ab02d60e19d534fb6263694ccda27796822d0a5..8d5951f3f3514f635955d0b1f4cbec9282905587 100644 (file)
@@ -553,8 +553,6 @@ def err_type_defined_in_alias_template : Error<
 def note_pure_virtual_function : Note<
   "unimplemented pure virtual method %0 in %1">;
 
-def err_deleted_non_function : Error<
-  "only functions can have deleted definitions">;
 def err_deleted_decl_not_first : Error<
   "deleted definition must be first declaration">;
 
index 613acb1cbc46672eb0dd85d97ce09cba9a1d88bd..e54b00c821d2457a1ed10c5df33105b1e1e3e4f0 100644 (file)
@@ -1000,7 +1000,7 @@ private:
 
   DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
                                           ParsingDeclSpec *DS = 0);
-  bool isDeclarationAfterDeclarator() const;
+  bool isDeclarationAfterDeclarator();
   bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
   DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
                                                   AccessSpecifier AS = AS_none);
index 3abc970de2ef85ce49c6bb2a9a40fee21b726dce..27833f562a5e89e2ac2c607ea7e624cdb180bf0c 100644 (file)
@@ -931,12 +931,12 @@ public:
                                   SourceLocation NameLoc,
                                   const Token &NextToken);
   
-  Decl *ActOnDeclarator(Scope *S, Declarator &D);
+  Decl *ActOnDeclarator(Scope *S, Declarator &D,
+                        bool IsFunctionDefintion = false);
 
   Decl *HandleDeclarator(Scope *S, Declarator &D,
                          MultiTemplateParamsArg TemplateParameterLists,
-                         bool IsFunctionDefinition,
-                         SourceLocation DefaultLoc = SourceLocation());
+                         bool IsFunctionDefinition);
   void RegisterLocallyScopedExternCDecl(NamedDecl *ND,
                                         const LookupResult &Previous,
                                         Scope *S);
@@ -964,8 +964,7 @@ public:
                                      LookupResult &Previous,
                                      MultiTemplateParamsArg TemplateParamLists,
                                      bool IsFunctionDefinition,
-                                     bool &Redeclaration,
-                                   SourceLocation DefaultLoc = SourceLocation());
+                                     bool &Redeclaration);
   bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
   void DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
   void CheckFunctionDeclaration(Scope *S,
@@ -997,6 +996,7 @@ public:
   void ActOnInitializerError(Decl *Dcl);
   void ActOnCXXForRangeDecl(Decl *D);
   void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
+  void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
   void FinalizeDeclaration(Decl *D);
   DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
                                          Decl **Group,
@@ -3126,9 +3126,7 @@ public:
                                  Declarator &D,
                                  MultiTemplateParamsArg TemplateParameterLists,
                                  Expr *BitfieldWidth, const VirtSpecifiers &VS,
-                                 Expr *Init, bool IsDefinition,
-                                 bool Deleted = false,
-                                 SourceLocation DefaultLoc = SourceLocation());
+                                 Expr *Init, bool IsDefinition);
 
   MemInitResult ActOnMemInitializer(Decl *ConstructorD,
                                     Scope *S,
index 1e1a0e2b0700cde55f808f3c46d317b623d9bd39..dee00275e7efd0eb6dbf96dc03489ba1ccaba600 100644 (file)
@@ -25,8 +25,9 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
                                 const ParsedTemplateInfo &TemplateInfo,
                                 const VirtSpecifiers& VS, ExprResult& Init) {
   assert(D.isFunctionDeclarator() && "This isn't a function declarator!");
-  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&
-         "Current token not a '{', ':' or 'try'!");
+  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try) ||
+          Tok.is(tok::equal)) &&
+         "Current token not a '{', ':', '=', or 'try'!");
 
   MultiTemplateParamsArg TemplateParams(Actions,
           TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0,
@@ -48,6 +49,40 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
 
   D.complete(FnD);
 
+  if (Tok.is(tok::equal)) {
+    ConsumeToken();
+
+    bool Delete = false;
+    SourceLocation KWLoc;
+    if (Tok.is(tok::kw_delete)) {
+      if (!getLang().CPlusPlus0x)
+        Diag(Tok, diag::warn_deleted_function_accepted_as_extension);
+
+      KWLoc = ConsumeToken();
+      Actions.SetDeclDeleted(FnD, KWLoc);
+      Delete = true;
+    } else if (Tok.is(tok::kw_default)) {
+      if (!getLang().CPlusPlus0x)
+        Diag(Tok, diag::warn_defaulted_function_accepted_as_extension);
+
+      KWLoc = ConsumeToken();
+      Actions.SetDeclDefaulted(FnD, KWLoc);
+    } else {
+      llvm_unreachable("function definition after = not 'delete' or 'default'");
+    }
+
+    if (Tok.is(tok::comma)) {
+      Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)
+        << Delete;
+      SkipUntil(tok::semi);
+    } else {
+      ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+                       Delete ? "delete" : "default", tok::semi);
+    }
+
+    return FnD;
+  }
+
   // In delayed template parsing mode, if we are within a class template
   // or if we are about to parse function member template then consume
   // the tokens and store them for parsing at the end of the translation unit.
index c54a0ed70798c09f60d8f62463f9022f816c4cce..d7b90f129c4494310c45f1aec007d5ee54b1b2cc 100644 (file)
@@ -968,14 +968,17 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
                                diag::err_invalid_equalequal_after_declarator)) {
     ConsumeToken();
     if (Tok.is(tok::kw_delete)) {
-      SourceLocation DelLoc = ConsumeToken();
-      
-      if (!getLang().CPlusPlus0x)
-        Diag(DelLoc, diag::warn_deleted_function_accepted_as_extension);
-
-      Actions.SetDeclDeleted(ThisDecl, DelLoc);
+      if (D.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)) {
-      Diag(ConsumeToken(), diag::err_default_special_members);
+      if (D.isFunctionDeclarator())
+        Diag(Tok, diag::err_default_delete_in_multiple_declaration)
+          << 1 /* delete */;
+      else
+        Diag(ConsumeToken(), diag::err_default_special_members);
     } else {
       if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
         EnterScope(0);
index ecf66a79dba50a073ab6abd1cf4ae6bf788b0cdb..91b55d5b58729a8310251c5b9146ce6c061d2360 100644 (file)
@@ -1614,10 +1614,21 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
         SkipUntil(tok::comma, true, true);
     }
 
+    bool IsDefinition = false;
     // function-definition:
-    if (Tok.is(tok::l_brace)
-        || (DeclaratorInfo.isFunctionDeclarator() &&
-            (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) {
+    if (Tok.is(tok::l_brace)) {
+      IsDefinition = true;
+    } else if (DeclaratorInfo.isFunctionDeclarator()) {
+      if (Tok.is(tok::colon) || Tok.is(tok::kw_try)) {
+        IsDefinition = true;
+      } else if (Tok.is(tok::equal)) {
+        const Token &KW = NextToken();
+        if (KW.is(tok::kw_default) || KW.is(tok::kw_delete))
+          IsDefinition = true;
+      }
+    }
+
+    if (IsDefinition) {
       if (!DeclaratorInfo.isFunctionDeclarator()) {
         Diag(Tok, diag::err_func_def_no_params);
         ConsumeBrace();
@@ -1644,9 +1655,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
       }
 
       ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS, Init);
-      // Consume the optional ';'
-      if (Tok.is(tok::semi))
+
+      // Consume the ';' - it's optional unless we have a delete or default
+      if (Tok.is(tok::semi)) {
         ConsumeToken();
+      }
 
       return;
     }
@@ -1658,8 +1671,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
 
   llvm::SmallVector<Decl *, 8> DeclsInGroup;
   ExprResult BitfieldSize;
-  bool Deleted = false;
-  SourceLocation DefaultLoc;
 
   while (1) {
     // member-declarator:
@@ -1687,14 +1698,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
     if (Tok.is(tok::equal)) {
       ConsumeToken();
       if (Tok.is(tok::kw_delete)) {
-        if (!getLang().CPlusPlus0x)
-          Diag(Tok, diag::warn_deleted_function_accepted_as_extension);
-        ConsumeToken();
-        Deleted = true;
+        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 (!getLang().CPlusPlus0x)
-          Diag(Tok, diag::warn_defaulted_function_accepted_as_extension);
-        DefaultLoc = ConsumeToken();
+        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())
@@ -1722,9 +1736,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
 
     Decl *ThisDecl = 0;
     if (DS.isFriendSpecified()) {
-      if (DefaultLoc.isValid())
-        Diag(DefaultLoc, diag::err_default_special_members);
-
       // TODO: handle initializers, bitfields, 'delete'
       ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,
                                                  /*IsDefinition*/ false,
@@ -1734,9 +1745,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
                                                   DeclaratorInfo,
                                                   move(TemplateParams),
                                                   BitfieldSize.release(),
-                                                  VS, Init.release(),
-                                                  /*IsDefinition*/Deleted,
-                                                  Deleted, DefaultLoc);
+                                                  VS, Init.release(), false);
     }
     if (ThisDecl)
       DeclsInGroup.push_back(ThisDecl);
@@ -1762,8 +1771,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
     VS.clear();
     BitfieldSize = 0;
     Init = 0;
-    Deleted = false;
-    DefaultLoc = SourceLocation();
 
     // Attributes are only allowed on the second declarator.
     MaybeParseGNUAttributes(DeclaratorInfo);
index 263a4916b631958bb07256de1114f7e0ad7059fe..4e4819e9fca1b6bd2d79ffc8fb5835ee6089ffbb 100644 (file)
@@ -677,7 +677,14 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
 
 /// \brief Determine whether the current token, if it occurs after a
 /// declarator, continues a declaration or declaration list.
-bool Parser::isDeclarationAfterDeclarator() const {
+bool Parser::isDeclarationAfterDeclarator() {
+  // Check for '= delete' or '= default'
+  if (getLang().CPlusPlus && Tok.is(tok::equal)) {
+    const Token &KW = NextToken();
+    if (KW.is(tok::kw_default) || KW.is(tok::kw_delete))
+      return false;
+  }
+
   return Tok.is(tok::equal) ||      // int X()=  -> not a function def
     Tok.is(tok::comma) ||           // int X(),  -> not a function def
     Tok.is(tok::semi)  ||           // int X();  -> not a function def
@@ -698,6 +705,11 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) {
   if (!getLang().CPlusPlus &&
       Declarator.getFunctionTypeInfo().isKNRPrototype()) 
     return isDeclarationSpecifier();
+
+  if (getLang().CPlusPlus && Tok.is(tok::equal)) {
+    const Token &KW = NextToken();
+    return KW.is(tok::kw_default) || KW.is(tok::kw_delete);
+  }
   
   return Tok.is(tok::colon) ||         // X() : Base() {} (used for ctors)
          Tok.is(tok::kw_try);          // X() try { ... }
@@ -820,6 +832,73 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
   if (FTI.isKNRPrototype())
     ParseKNRParamDeclarations(D);
 
+  if (Tok.is(tok::equal)) {
+    assert(getLang().CPlusPlus && "Only C++ function definitions have '='");
+    ConsumeToken();
+
+    Decl *Decl = 0;
+    // Here we complete the declaration as if it were normal
+    switch (TemplateInfo.Kind) {
+    case ParsedTemplateInfo::NonTemplate:
+      Decl = Actions.ActOnDeclarator(getCurScope(), D, true);
+      break;
+
+    case ParsedTemplateInfo::Template:
+    case ParsedTemplateInfo::ExplicitSpecialization:
+      Decl = Actions.ActOnTemplateDeclarator(getCurScope(),
+                                   MultiTemplateParamsArg(Actions,
+                                          TemplateInfo.TemplateParams->data(),
+                                          TemplateInfo.TemplateParams->size()),
+                                             D);
+      break;
+
+    case ParsedTemplateInfo::ExplicitInstantiation: {
+      DeclResult Result
+        = Actions.ActOnExplicitInstantiation(getCurScope(),
+                                             TemplateInfo.ExternLoc,
+                                             TemplateInfo.TemplateLoc,
+                                             D);
+      if (Result.isInvalid()) {
+        SkipUntil(tok::semi);
+        return 0;
+      }
+
+      Decl = Result.get();
+      break;
+    }
+    }
+      
+    bool Delete = false;
+    SourceLocation KWLoc;
+    if (Tok.is(tok::kw_delete)) {
+      if (!getLang().CPlusPlus0x)
+        Diag(Tok, diag::warn_deleted_function_accepted_as_extension);
+
+      KWLoc = ConsumeToken();
+      Actions.SetDeclDeleted(Decl, KWLoc);
+      Delete = true;
+    } else if (Tok.is(tok::kw_default)) {
+      if (!getLang().CPlusPlus0x)
+        Diag(Tok, diag::warn_defaulted_function_accepted_as_extension);
+
+      KWLoc = ConsumeToken();
+      Actions.SetDeclDefaulted(Decl, KWLoc);
+    } else {
+      llvm_unreachable("function definition after = not 'delete' or 'default'");
+    }
+
+    if (Tok.is(tok::comma)) {
+      Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)
+        << Delete;
+      SkipUntil(tok::semi);
+    } else {
+      ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+                       Delete ? "delete" : "default", tok::semi);
+    }
+
+    return Decl;
+  }
+
   // We should have either an opening brace or, in a C++ constructor,
   // we may have a colon.
   if (Tok.isNot(tok::l_brace) && 
index 972d080fc967490a048b4dd01376973d5d8114da..58b807fb2aed635771fdad0e23a8192acb7a0164 100644 (file)
@@ -2913,8 +2913,10 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
   return false;
 }
 
-Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
-  return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false);
+Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D,
+                            bool IsFunctionDefinition) {
+  return HandleDeclarator(S, D, MultiTemplateParamsArg(*this),
+                          IsFunctionDefinition);
 }
 
 /// DiagnoseClassNameShadow - Implement C++ [class.mem]p13:
@@ -2939,8 +2941,7 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
   
 Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
                              MultiTemplateParamsArg TemplateParamLists,
-                             bool IsFunctionDefinition,
-                             SourceLocation DefaultLoc) {
+                             bool IsFunctionDefinition) {
   // TODO: consider using NameInfo for diagnostic.
   DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
   DeclarationName Name = NameInfo.getName();
@@ -3141,9 +3142,6 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
 
   bool Redeclaration = false;
   if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
-    if (DefaultLoc.isValid())
-      Diag(DefaultLoc, diag::err_default_special_members);
-
     if (TemplateParamLists.size()) {
       Diag(D.getIdentifierLoc(), diag::err_template_typedef);
       return 0;
@@ -3153,10 +3151,8 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
   } else if (R->isFunctionType()) {
     New = ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous,
                                   move(TemplateParamLists),
-                                  IsFunctionDefinition, Redeclaration,
-                                  DefaultLoc);
+                                  IsFunctionDefinition, Redeclaration);
   } else {
-    assert(!DefaultLoc.isValid() && "We should have caught this in a caller");
     New = ActOnVariableDeclarator(S, D, DC, R, TInfo, Previous,
                                   move(TemplateParamLists),
                                   Redeclaration);
@@ -4028,8 +4024,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                               QualType R, TypeSourceInfo *TInfo,
                               LookupResult &Previous,
                               MultiTemplateParamsArg TemplateParamLists,
-                              bool IsFunctionDefinition, bool &Redeclaration,
-                              SourceLocation DefaultLoc) {
+                              bool IsFunctionDefinition, bool &Redeclaration) {
   assert(R.getTypePtr()->isFunctionType());
 
   // TODO: consider using NameInfo for diagnostic.
@@ -4086,8 +4081,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   bool isFunctionTemplateSpecialization = false;
 
   if (!getLangOptions().CPlusPlus) {
-    assert(!DefaultLoc.isValid() && "Defaulted functions are a C++ feature");
-
     // Determine whether the function was written with a
     // prototype. This true when:
     //   - there is a prototype in the declarator, or
@@ -4689,7 +4682,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
 
     } else if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() &&
                !isFriend && !isFunctionTemplateSpecialization &&
-               !isExplicitSpecialization && !DefaultLoc.isValid()) {
+               !isExplicitSpecialization) {
       // An out-of-line member function declaration must also be a
       // definition (C++ [dcl.meaning]p1).
       // Note that this is not the case for explicit specializations of
@@ -4700,8 +4693,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
         << D.getCXXScopeSpec().getRange();
     }
   }
-  
-  
   // Handle attributes. We need to have merged decls when handling attributes
   // (for example to check for conflicts, etc).
   // FIXME: This needs to happen before we merge declarations. Then,
@@ -4774,16 +4767,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
         }
       }
 
-  if (DefaultLoc.isValid()) {
-    CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
-    if (MD && getSpecialMember(MD) != CXXInvalid) {
-      MD->setExplicitlyDefaulted();
-      MD->setDefaulted();
-    } else {
-      Diag(DefaultLoc, diag::err_default_special_members);
-    }
-  }
-
   return NewFD;
 }
 
index 13e2819f7bdd58c4a6f6fa580b2152e079199326..b98777bad7952c2e0cccca75defb901991f3ffea 100644 (file)
@@ -1025,8 +1025,7 @@ Decl *
 Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
                                MultiTemplateParamsArg TemplateParameterLists,
                                ExprTy *BW, const VirtSpecifiers &VS,
-                               ExprTy *InitExpr, bool IsDefinition,
-                               bool Deleted, SourceLocation DefaultLoc) {
+                               ExprTy *InitExpr, bool IsDefinition) {
   const DeclSpec &DS = D.getDeclSpec();
   DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
   DeclarationName Name = NameInfo.getName();
@@ -1091,9 +1090,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
   if (isInstField) {
     CXXScopeSpec &SS = D.getCXXScopeSpec();
     
-    if (DefaultLoc.isValid())
-      Diag(DefaultLoc, diag::err_default_special_members);
-    
     if (SS.isSet() && !SS.isInvalid()) {
       // The user provided a superfluous scope specifier inside a class
       // definition:
@@ -1118,8 +1114,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
                          AS);
     assert(Member && "HandleField never returns null");
   } else {
-    Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition,
-                              DefaultLoc);
+    Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition);
     if (!Member) {
       return 0;
     }
@@ -1189,8 +1184,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
   if (Init)
     AddInitializerToDecl(Member, Init, false,
                          DS.getTypeSpecType() == DeclSpec::TST_auto);
-  if (Deleted) // FIXME: Source location is not very good.
-    SetDeclDeleted(Member, D.getSourceRange().getBegin());
 
   FinalizeDeclaration(Member);
 
@@ -7865,6 +7858,39 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
   Fn->setDeletedAsWritten();
 }
 
+void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
+  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl);
+
+  if (MD) {
+    CXXSpecialMember Member = getSpecialMember(MD);
+    if (Member == CXXInvalid) {
+      Diag(DefaultLoc, diag::err_default_special_members);
+      return;
+    }
+
+    MD->setDefaulted();
+    MD->setExplicitlyDefaulted();
+
+    // We'll check it when the record is done
+    if (MD == MD->getCanonicalDecl())
+      return;
+
+    switch (Member) {
+    case CXXDefaultConstructor: {
+      CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
+      CheckExplicitlyDefaultedDefaultConstructor(CD);
+      DefineImplicitDefaultConstructor(DefaultLoc, CD);
+      break;
+    }
+    default:
+      // FIXME: Do the rest once we have functions
+      break;
+    }
+  } else {
+    Diag(DefaultLoc, diag::err_default_special_members);
+  }
+}
+
 static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
   for (Stmt::child_range CI = S->children(); CI; ++CI) {
     Stmt *SubStmt = *CI;