[cfe-commits] r172376 - in /cfe/trunk: lib/Sema/SemaDecl.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaType.cpp test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp

Alexey Samsonov samsonov at google.com
Sun Jan 13 22:50:39 PST 2013


Hi Richard!

Looks like this breaks compilation of libcxx with Clang:

linux-cmake/build/llvm/projects/libcxx/include/bitset:674:47: error:
functions that differ only in their return type cannot be overloaded
    _LIBCPP_INLINE_VISIBILITY       reference operator[](size_t __p)
    {return base::__make_ref(__p);}
                                              ^
linux-cmake/build/llvm/projects/libcxx/include/bitset:673:47: note:
previous declaration is here
                              const_reference operator[](size_t __p)
const {return base::__make_ref(__p);}
                                              ^



On Mon, Jan 14, 2013 at 9:37 AM, Richard Smith
<richard-llvm at metafoo.co.uk>wrote:

> Author: rsmith
> Date: Sun Jan 13 23:37:29 2013
> New Revision: 172376
>
> URL: http://llvm.org/viewvc/llvm-project?rev=172376&view=rev
> Log:
> PR12008: defer adding the implicit 'const' to a constexpr member function
> until
> we know whether it is static.
>
> Modified:
>     cfe/trunk/lib/Sema/SemaDecl.cpp
>     cfe/trunk/lib/Sema/SemaOverload.cpp
>     cfe/trunk/lib/Sema/SemaTemplate.cpp
>     cfe/trunk/lib/Sema/SemaType.cpp
>     cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp
>     cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=172376&r1=172375&r2=172376&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Jan 13 23:37:29 2013
> @@ -5598,11 +5598,11 @@
>      }
>
>      if (isConstexpr) {
> -      // C++0x [dcl.constexpr]p2: constexpr functions and constexpr
> constructors
> +      // C++11 [dcl.constexpr]p2: constexpr functions and constexpr
> constructors
>        // are implicitly inline.
>        NewFD->setImplicitlyInline();
>
> -      // C++0x [dcl.constexpr]p3: functions declared constexpr are
> required to
> +      // C++11 [dcl.constexpr]p3: functions declared constexpr are
> required to
>        // be either constructors or to return a literal type. Therefore,
>        // destructors cannot be declared constexpr.
>        if (isa<CXXDestructorDecl>(NewFD))
> @@ -6162,6 +6162,7 @@
>    filterNonConflictingPreviousDecls(Context, NewFD, Previous);
>
>    bool Redeclaration = false;
> +  NamedDecl *OldDecl = 0;
>
>    // Merge or overload the declaration with an existing declaration of
>    // the same name, if appropriate.
> @@ -6170,8 +6171,6 @@
>      // a declaration that requires merging. If it's an overload,
>      // there's no more work to do here; we'll just add the new
>      // function to the scope.
> -
> -    NamedDecl *OldDecl = 0;
>      if (!AllowOverloadingOfFunction(Previous, Context)) {
>        Redeclaration = true;
>        OldDecl = Previous.getFoundDecl();
> @@ -6208,43 +6207,68 @@
>                                                          Context));
>        }
>      }
> +  }
>
> -    if (Redeclaration) {
> -      // NewFD and OldDecl represent declarations that need to be
> -      // merged.
> -      if (MergeFunctionDecl(NewFD, OldDecl, S)) {
> -        NewFD->setInvalidDecl();
> -        return Redeclaration;
> -      }
> +  // C++11 [dcl.constexpr]p8:
> +  //   A constexpr specifier for a non-static member function that is not
> +  //   a constructor declares that member function to be const.
> +  //
> +  // This needs to be delayed until we know whether this is an out-of-line
> +  // definition of a static member function.
> +  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
> +  if (MD && MD->isConstexpr() && !MD->isStatic() &&
> +      !isa<CXXConstructorDecl>(MD) &&
> +      (MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
> +    CXXMethodDecl *OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl);
> +    if (FunctionTemplateDecl *OldTD =
> +          dyn_cast_or_null<FunctionTemplateDecl>(OldDecl))
> +      OldMD = dyn_cast<CXXMethodDecl>(OldTD->getTemplatedDecl());
> +    if (!OldMD || !OldMD->isStatic()) {
> +      const FunctionProtoType *FPT =
> +        MD->getType()->castAs<FunctionProtoType>();
> +      FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
> +      EPI.TypeQuals |= Qualifiers::Const;
> +      MD->setType(Context.getFunctionType(FPT->getResultType(),
> +                                          FPT->arg_type_begin(),
> +                                          FPT->getNumArgs(), EPI));
> +    }
> +  }
>
> -      Previous.clear();
> -      Previous.addDecl(OldDecl);
> +  if (Redeclaration) {
> +    // NewFD and OldDecl represent declarations that need to be
> +    // merged.
> +    if (MergeFunctionDecl(NewFD, OldDecl, S)) {
> +      NewFD->setInvalidDecl();
> +      return Redeclaration;
> +    }
>
> -      if (FunctionTemplateDecl *OldTemplateDecl
> -                                    =
> dyn_cast<FunctionTemplateDecl>(OldDecl)) {
> -
>  NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
> -        FunctionTemplateDecl *NewTemplateDecl
> -          = NewFD->getDescribedFunctionTemplate();
> -        assert(NewTemplateDecl && "Template/non-template mismatch");
> -        if (CXXMethodDecl *Method
> -              =
> dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
> -          Method->setAccess(OldTemplateDecl->getAccess());
> -          NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
> -        }
> -
> -        // If this is an explicit specialization of a member that is a
> function
> -        // template, mark it as a member specialization.
> -        if (IsExplicitSpecialization &&
> -            NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
> -          NewTemplateDecl->setMemberSpecialization();
> -          assert(OldTemplateDecl->isMemberSpecialization());
> -        }
> -
> -      } else {
> -        if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line
> definitions
> -          NewFD->setAccess(OldDecl->getAccess());
> -        NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
> +    Previous.clear();
> +    Previous.addDecl(OldDecl);
> +
> +    if (FunctionTemplateDecl *OldTemplateDecl
> +                                  =
> dyn_cast<FunctionTemplateDecl>(OldDecl)) {
> +      NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
> +      FunctionTemplateDecl *NewTemplateDecl
> +        = NewFD->getDescribedFunctionTemplate();
> +      assert(NewTemplateDecl && "Template/non-template mismatch");
> +      if (CXXMethodDecl *Method
> +            =
> dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
> +        Method->setAccess(OldTemplateDecl->getAccess());
> +        NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
> +      }
> +
> +      // If this is an explicit specialization of a member that is a
> function
> +      // template, mark it as a member specialization.
> +      if (IsExplicitSpecialization &&
> +          NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
> +        NewTemplateDecl->setMemberSpecialization();
> +        assert(OldTemplateDecl->isMemberSpecialization());
>        }
> +
> +    } else {
> +      if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line
> definitions
> +        NewFD->setAccess(OldDecl->getAccess());
> +      NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
>      }
>    }
>
>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=172376&r1=172375&r2=172376&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Sun Jan 13 23:37:29 2013
> @@ -1012,28 +1012,37 @@
>    // 13.1p2). While not part of the definition of the signature,
>    // this check is important to determine whether these functions
>    // can be overloaded.
> -  CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
> -  CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
> +  CXXMethodDecl *OldMethod = dyn_cast<CXXMethodDecl>(Old);
> +  CXXMethodDecl *NewMethod = dyn_cast<CXXMethodDecl>(New);
>    if (OldMethod && NewMethod &&
> -      !OldMethod->isStatic() && !NewMethod->isStatic() &&
> -      (OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers() ||
> -       OldMethod->getRefQualifier() != NewMethod->getRefQualifier())) {
> -    if (!UseUsingDeclRules &&
> -        OldMethod->getRefQualifier() != NewMethod->getRefQualifier() &&
> -        (OldMethod->getRefQualifier() == RQ_None ||
> -         NewMethod->getRefQualifier() == RQ_None)) {
> -      // C++0x [over.load]p2:
> -      //   - Member function declarations with the same name and the same
> -      //     parameter-type-list as well as member function template
> -      //     declarations with the same name, the same
> parameter-type-list, and
> -      //     the same template parameter lists cannot be overloaded if
> any of
> -      //     them, but not all, have a ref-qualifier (8.3.5).
> -      Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
> -        << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
> -      Diag(OldMethod->getLocation(), diag::note_previous_declaration);
> +      !OldMethod->isStatic() && !NewMethod->isStatic()) {
> +    if (OldMethod->getRefQualifier() != NewMethod->getRefQualifier()) {
> +      if (!UseUsingDeclRules &&
> +          (OldMethod->getRefQualifier() == RQ_None ||
> +           NewMethod->getRefQualifier() == RQ_None)) {
> +        // C++0x [over.load]p2:
> +        //   - Member function declarations with the same name and the
> same
> +        //     parameter-type-list as well as member function template
> +        //     declarations with the same name, the same
> parameter-type-list, and
> +        //     the same template parameter lists cannot be overloaded if
> any of
> +        //     them, but not all, have a ref-qualifier (8.3.5).
> +        Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
> +          << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
> +        Diag(OldMethod->getLocation(), diag::note_previous_declaration);
> +      }
> +      return true;
>      }
>
> -    return true;
> +    // We may not have applied the implicit const for a constexpr member
> +    // function yet (because we haven't yet resolved whether this is a
> static
> +    // or non-static member function). Add it now, on the assumption that
> this
> +    // is a redeclaration of OldMethod.
> +    unsigned NewQuals = NewMethod->getTypeQualifiers();
> +    if ((OldMethod->isConstexpr() || NewMethod->isConstexpr()) &&
> +        !isa<CXXConstructorDecl>(NewMethod))
> +      NewQuals |= Qualifiers::Const;
> +    if (OldMethod->getTypeQualifiers() != NewQuals)
> +      return true;
>    }
>
>    // The signatures match; this is not an overload.
>
> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=172376&r1=172375&r2=172376&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sun Jan 13 23:37:29 2013
> @@ -5918,6 +5918,25 @@
>
>  Ovl->getDeclContext()->getRedeclContext()))
>          continue;
>
> +      // When matching a constexpr member function template specialization
> +      // against the primary template, we don't yet know whether the
> +      // specialization has an implicit 'const' (because we don't know
> whether
> +      // it will be a static member function until we know which template
> it
> +      // specializes), so adjust it now assuming it specializes this
> template.
> +      QualType FT = FD->getType();
> +      if (FD->isConstexpr()) {
> +        CXXMethodDecl *OldMD =
> +          dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
> +        if (OldMD && OldMD->isConst()) {
> +          const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
> +          FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
> +          EPI.TypeQuals |= Qualifiers::Const;
> +          FT = Context.getFunctionType(FPT->getResultType(),
> +                                       FPT->arg_type_begin(),
> +                                       FPT->getNumArgs(), EPI);
> +        }
> +      }
> +
>        // C++ [temp.expl.spec]p11:
>        //   A trailing template-argument can be left unspecified in the
>        //   template-id naming an explicit function template specialization
> @@ -5928,10 +5947,8 @@
>        TemplateDeductionInfo Info(FD->getLocation());
>        FunctionDecl *Specialization = 0;
>        if (TemplateDeductionResult TDK
> -            = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs,
> -                                      FD->getType(),
> -                                      Specialization,
> -                                      Info)) {
> +            = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, FT,
> +                                      Specialization, Info)) {
>          // FIXME: Template argument deduction failed; record why it
> failed, so
>          // that we can provide nifty diagnostics.
>          (void)TDK;
>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=172376&r1=172375&r2=172376&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Sun Jan 13 23:37:29 2013
> @@ -2690,30 +2690,6 @@
>        FreeFunction = (DC && !DC->isRecord());
>      }
>
> -    // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static
> member
> -    // function that is not a constructor declares that function to be
> const.
> -    // FIXME: This should be deferred until we know whether this is a
> static
> -    //        member function (for an out-of-class definition, we don't
> know
> -    //        this until we perform redeclaration lookup).
> -    if (D.getDeclSpec().isConstexprSpecified() && !FreeFunction &&
> -        D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static &&
> -        D.getName().getKind() != UnqualifiedId::IK_ConstructorName &&
> -        D.getName().getKind() != UnqualifiedId::IK_ConstructorTemplateId
> &&
> -        !(FnTy->getTypeQuals() & DeclSpec::TQ_const)) {
> -      // Rebuild function type adding a 'const' qualifier.
> -      FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
> -      EPI.TypeQuals |= DeclSpec::TQ_const;
> -      T = Context.getFunctionType(FnTy->getResultType(),
> -                                  FnTy->arg_type_begin(),
> -                                  FnTy->getNumArgs(), EPI);
> -      // Rebuild any parens around the identifier in the function type.
> -      for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
> -        if (D.getTypeObject(i).Kind != DeclaratorChunk::Paren)
> -          break;
> -        T = S.BuildParenType(T);
> -      }
> -    }
> -
>      // C++11 [dcl.fct]p6 (w/DR1417):
>      // An attempt to specify a function type with a cv-qualifier-seq or a
>      // ref-qualifier (including by typedef-name) is ill-formed unless it
> is:
>
> Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp?rev=172376&r1=172375&r2=172376&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp (original)
> +++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp Sun Jan 13
> 23:37:29 2013
> @@ -1,19 +1,35 @@
>  // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
>
> +using size_t = decltype(sizeof(int));
> +
>  struct S {
>    constexpr int f();
>    constexpr int g() const;
>    static constexpr int Sf();
> +  /*static*/ constexpr void *operator new(size_t) noexcept;
> +  template<typename T> constexpr T tm();
> +  template<typename T> static constexpr T ts();
>  };
>
>  void f(const S &s) {
>    s.f();
>    s.g();
>
> -  int (*f)() = &S::Sf;
> +  int (*Sf)() = &S::Sf;
> +  int (S::*f)() const = &S::f;
>    int (S::*g)() const = &S::g;
> +  void *(*opNew)(size_t) = &S::operator new;
> +  int (S::*tm)() const = &S::tm;
> +  int (*ts)() = &S::ts;
>  }
>
> +constexpr int S::f() const { return 0; }
> +constexpr int S::g() { return 1; }
> +constexpr int S::Sf() { return 2; }
> +constexpr void *S::operator new(size_t) noexcept { return 0; }
> +template<typename T> constexpr T S::tm() { return T(); }
> +template<typename T> constexpr T S::ts() { return T(); }
> +
>  namespace std_example {
>
>    class debug_flag { // expected-note {{not an aggregate and has no
> constexpr constructors}}
>
> Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp?rev=172376&r1=172375&r2=172376&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp (original)
> +++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp Sun Jan 13
> 23:37:29 2013
> @@ -12,7 +12,7 @@
>    constexpr int f() { return 0; }
>  };
>
> -template constexpr int Y<int>::f(); // expected-error{{explicit
> instantiation cannot be 'constexpr'}}
> +template constexpr int Y<int>::f() const; // expected-error{{explicit
> instantiation cannot be 'constexpr'}}
>
>  template<typename T>
>  struct Z {
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>



-- 
Alexey Samsonov, MSK
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130114/71fa2910/attachment.html>


More information about the cfe-commits mailing list