[cfe-commits] r130974 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticCommonKinds.td include/clang/Basic/DiagnosticParseKinds.td include/clang/Sema/Sema.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp

Sean Hunt scshunt at csclub.uwaterloo.ca
Thu May 5 18:42:00 PDT 2011


Author: coppro
Date: Thu May  5 20:42:00 2011
New Revision: 130974

URL: http://llvm.org/viewvc/llvm-project?rev=130974&view=rev
Log:
Do defaulted constructors properly.

Explictly defaultedness is correctly reflected on the AST, but there are
no changes to how that affects the definition of functions or much else
really.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu May  5 20:42:00 2011
@@ -1365,6 +1365,8 @@
   bool HasWrittenPrototype : 1;
   bool IsDeleted : 1;
   bool IsTrivial : 1; // sunk from CXXMethodDecl
+  bool IsDefaulted : 1; // sunk from CXXMethoDecl
+  bool IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
   bool HasImplicitReturnZero : 1;
   bool IsLateTemplateParsed : 1;
 
@@ -1566,6 +1568,16 @@
   bool isTrivial() const { return IsTrivial; }
   void setTrivial(bool IT) { IsTrivial = IT; }
 
+  /// Whether this function is defaulted per C++0x. Only valid for
+  /// special member functions. 
+  bool isDefaulted() const { return IsDefaulted; }
+  void setDefaulted(bool D = true) { IsDefaulted = D; }
+
+  /// Whether this function is explicitly defaulted per C++0x. Only valid
+  /// for special member functions.
+  bool isExplicitlyDefaulted() const { return IsExplicitlyDefaulted; }
+  void setExplicitlyDefaulted(bool ED = true) { IsExplicitlyDefaulted = ED; }
+
   /// Whether falling off this function implicitly returns null/zero.
   /// If a more specific implicit return value is required, front-ends
   /// should synthesize the appropriate return statements.

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu May  5 20:42:00 2011
@@ -1189,6 +1189,12 @@
   CXXMethodDecl *getCanonicalDecl() {
     return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
   }
+
+  /// isUserProvided - True if it is either an implicit constructor or
+  /// if it was defaulted or deleted on first declaration.
+  bool isUserProvided() const {
+    return getCanonicalDecl()->isDeleted() || getCanonicalDecl()->isDefaulted();
+  }
   
   ///
   void addOverriddenMethod(const CXXMethodDecl *MD);

Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Thu May  5 20:42:00 2011
@@ -52,6 +52,10 @@
 def err_expected_namespace_name : Error<"expected namespace name">;
 def ext_variadic_templates : ExtWarn<
   "variadic templates are a C++0x extension">, InGroup<CXX0x>;
+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">;
 
 // Sema && Lex
 def ext_longlong : Extension<

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu May  5 20:42:00 2011
@@ -434,6 +434,9 @@
 
 def warn_deleted_function_accepted_as_extension: ExtWarn<
   "deleted function definition accepted as a C++0x extension">, InGroup<CXX0x>;
+def warn_defaulted_function_accepted_as_extension: ExtWarn<
+  "defaulted function definition accepted as a C++0x extension">,
+  InGroup<CXX0x>;
 
 // C++0x alias-declaration
 def ext_alias_declaration : ExtWarn<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu May  5 20:42:00 2011
@@ -935,7 +935,8 @@
 
   Decl *HandleDeclarator(Scope *S, Declarator &D,
                          MultiTemplateParamsArg TemplateParameterLists,
-                         bool IsFunctionDefinition);
+                         bool IsFunctionDefinition,
+                         SourceLocation DefLoc = SourceLocation());
   void RegisterLocallyScopedExternCDecl(NamedDecl *ND,
                                         const LookupResult &Previous,
                                         Scope *S);
@@ -963,7 +964,8 @@
                                      LookupResult &Previous,
                                      MultiTemplateParamsArg TemplateParamLists,
                                      bool IsFunctionDefinition,
-                                     bool &Redeclaration);
+                                     bool &Redeclaration,
+                                     SourceLocation DefLoc = SourceLocation());
   bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
   void DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
   void CheckFunctionDeclaration(Scope *S,
@@ -3063,7 +3065,8 @@
                                  MultiTemplateParamsArg TemplateParameterLists,
                                  Expr *BitfieldWidth, const VirtSpecifiers &VS,
                                  Expr *Init, bool IsDefinition,
-                                 bool Deleted = false);
+                                 bool Deleted = false,
+                                 SourceLocation DefLoc = SourceLocation());
 
   MemInitResult ActOnMemInitializer(Decl *ConstructorD,
                                     Scope *S,

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu May  5 20:42:00 2011
@@ -966,6 +966,10 @@
         Diag(DelLoc, diag::warn_deleted_function_accepted_as_extension);
 
       Actions.SetDeclDeleted(ThisDecl, DelLoc);
+    } else if (Tok.is(tok::kw_default)) {
+      SourceLocation DefLoc = ConsumeToken();
+
+      Diag(DefLoc, diag::err_default_special_members);
     } else {
       if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
         EnterScope(0);

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu May  5 20:42:00 2011
@@ -1648,6 +1648,7 @@
   ExprResult BitfieldSize;
   ExprResult Init;
   bool Deleted = false;
+  SourceLocation DefLoc;
 
   while (1) {
     // member-declarator:
@@ -1679,6 +1680,10 @@
           Diag(Tok, diag::warn_deleted_function_accepted_as_extension);
         ConsumeToken();
         Deleted = true;
+      } else if (Tok.is(tok::kw_default)) {
+        if (!getLang().CPlusPlus0x)
+          Diag(Tok, diag::warn_defaulted_function_accepted_as_extension);
+        DefLoc = ConsumeToken();
       } else {
         Init = ParseInitializer();
         if (Init.isInvalid())
@@ -1706,6 +1711,9 @@
 
     Decl *ThisDecl = 0;
     if (DS.isFriendSpecified()) {
+      if (DefLoc.isValid())
+        Diag(DefLoc, diag::err_default_special_members);
+
       // TODO: handle initializers, bitfields, 'delete'
       ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,
                                                  /*IsDefinition*/ false,
@@ -1717,7 +1725,7 @@
                                                   BitfieldSize.release(),
                                                   VS, Init.release(),
                                                   /*IsDefinition*/Deleted,
-                                                  Deleted);
+                                                  Deleted, DefLoc);
     }
     if (ThisDecl)
       DeclsInGroup.push_back(ThisDecl);
@@ -1744,6 +1752,7 @@
     BitfieldSize = 0;
     Init = 0;
     Deleted = false;
+    DefLoc = SourceLocation();
 
     // Attributes are only allowed on the second declarator.
     MaybeParseGNUAttributes(DeclaratorInfo);

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu May  5 20:42:00 2011
@@ -2919,7 +2919,8 @@
   
 Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
                              MultiTemplateParamsArg TemplateParamLists,
-                             bool IsFunctionDefinition) {
+                             bool IsFunctionDefinition,
+                             SourceLocation DefLoc) {
   // TODO: consider using NameInfo for diagnostic.
   DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
   DeclarationName Name = NameInfo.getName();
@@ -2962,7 +2963,6 @@
         << D.getCXXScopeSpec().getRange();
       return 0;
     }
-
     bool IsDependentContext = DC->isDependentContext();
 
     if (!IsDependentContext && 
@@ -3121,6 +3121,9 @@
 
   bool Redeclaration = false;
   if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
+    if (DefLoc.isValid())
+      Diag(DefLoc, diag::err_default_special_members);
+
     if (TemplateParamLists.size()) {
       Diag(D.getIdentifierLoc(), diag::err_template_typedef);
       return 0;
@@ -3130,8 +3133,9 @@
   } else if (R->isFunctionType()) {
     New = ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous,
                                   move(TemplateParamLists),
-                                  IsFunctionDefinition, Redeclaration);
+                                  IsFunctionDefinition, Redeclaration, DefLoc);
   } else {
+    assert(!DefLoc.isValid() && "We should have caught this in a caller");
     New = ActOnVariableDeclarator(S, D, DC, R, TInfo, Previous,
                                   move(TemplateParamLists),
                                   Redeclaration);
@@ -4003,7 +4007,8 @@
                               QualType R, TypeSourceInfo *TInfo,
                               LookupResult &Previous,
                               MultiTemplateParamsArg TemplateParamLists,
-                              bool IsFunctionDefinition, bool &Redeclaration) {
+                              bool IsFunctionDefinition, bool &Redeclaration,
+                              SourceLocation DefLoc) {
   assert(R.getTypePtr()->isFunctionType());
 
   // TODO: consider using NameInfo for diagnostic.
@@ -4060,6 +4065,8 @@
   bool isFunctionTemplateSpecialization = false;
 
   if (!getLangOptions().CPlusPlus) {
+    assert(!DefLoc.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
@@ -4104,12 +4111,25 @@
       R = CheckConstructorDeclarator(D, R, SC);
 
       // Create the new declaration
-      NewFD = CXXConstructorDecl::Create(Context,
+      CXXConstructorDecl *NewCD = CXXConstructorDecl::Create(
+                                         Context,
                                          cast<CXXRecordDecl>(DC),
                                          D.getSourceRange().getBegin(),
                                          NameInfo, R, TInfo,
                                          isExplicit, isInline,
                                          /*isImplicitlyDeclared=*/false);
+
+      NewFD = NewCD;
+
+      if (DefLoc.isValid()) {
+        if (NewCD->isDefaultConstructor() ||
+            NewCD->isCopyOrMoveConstructor()) {
+          NewFD->setDefaulted();
+          NewFD->setExplicitlyDefaulted();
+        } else {
+          Diag(DefLoc, diag::err_default_special_members);
+        }
+      }
     } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
       // This is a C++ destructor declaration.
       if (DC->isRecord()) {
@@ -4122,6 +4142,11 @@
                                           isInline,
                                           /*isImplicitlyDeclared=*/false);
         isVirtualOkay = true;
+
+        if (DefLoc.isValid()) {
+          NewFD->setDefaulted();
+          NewFD->setExplicitlyDefaulted();
+        }
       } else {
         Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
 
@@ -4140,6 +4165,9 @@
         return 0;
       }
 
+      if (DefLoc.isValid())
+        Diag(DefLoc, diag::err_default_special_members);
+
       CheckConversionDeclarator(D, R, SC);
       NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
                                         D.getSourceRange().getBegin(),
@@ -4178,14 +4206,29 @@
         isStatic = true;
 
       // This is a C++ method declaration.
-      NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
-                                    D.getSourceRange().getBegin(),
-                                    NameInfo, R, TInfo,
-                                    isStatic, SCAsWritten, isInline,
-                                    SourceLocation());
+      CXXMethodDecl *NewMD = CXXMethodDecl::Create(
+                                               Context, cast<CXXRecordDecl>(DC),
+                                               D.getSourceRange().getBegin(),
+                                               NameInfo, R, TInfo,
+                                               isStatic, SCAsWritten, isInline,
+                                               SourceLocation());
+      NewFD = NewMD;
 
       isVirtualOkay = !isStatic;
+
+      if (DefLoc.isValid()) {
+        if (NewMD->isCopyAssignmentOperator() /* ||
+            NewMD->isMoveAssignmentOperator() */) {
+          NewFD->setDefaulted();
+          NewFD->setExplicitlyDefaulted();
+        } else {
+          Diag(DefLoc, diag::err_default_special_members);
+        }
+      }
     } else {
+      if (DefLoc.isValid())
+        Diag(DefLoc, diag::err_default_special_members);
+
       // Determine whether the function was written with a
       // prototype. This true when:
       //   - we're in C++ (where every function has a prototype),

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu May  5 20:42:00 2011
@@ -963,7 +963,7 @@
                                MultiTemplateParamsArg TemplateParameterLists,
                                ExprTy *BW, const VirtSpecifiers &VS,
                                ExprTy *InitExpr, bool IsDefinition,
-                               bool Deleted) {
+                               bool Deleted, SourceLocation DefLoc) {
   const DeclSpec &DS = D.getDeclSpec();
   DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
   DeclarationName Name = NameInfo.getName();
@@ -1028,6 +1028,8 @@
   if (isInstField) {
     CXXScopeSpec &SS = D.getCXXScopeSpec();
     
+    if (DefLoc.isValid())
+      Diag(DefLoc, diag::err_default_special_members);
     
     if (SS.isSet() && !SS.isInvalid()) {
       // The user provided a superfluous scope specifier inside a class
@@ -1053,7 +1055,8 @@
                          AS);
     assert(Member && "HandleField never returns null");
   } else {
-    Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition);
+    Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition,
+                              DefLoc);
     if (!Member) {
       return 0;
     }





More information about the cfe-commits mailing list