[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
Richard Smith
richard at metafoo.co.uk
Fri May 6 07:16:09 PDT 2011
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
More information about the cfe-commits
mailing list