[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
Richard Smith
richard at metafoo.co.uk
Mon Jan 14 00:01:05 PST 2013
Thanks, fixed in r172384.
On Sun, Jan 13, 2013 at 10:50 PM, Alexey Samsonov <samsonov at google.com>wrote:
> 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/8d665f1c/attachment.html>
More information about the cfe-commits
mailing list