[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