Hi Sean, > 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(); > + }
This looks almost exactly backwards from how the standard specifies "user-provided". > /// > 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">; Diagnostics should start with a lowercase letter. > // 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()); 'Def' is ambiguous here: is it 'default' or 'definition'? 'DefaultLoc' would be clearer. > 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; > } Cheers! Richard _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
