[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