[cfe-commits] r140801 - in /cfe/trunk: include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/CXX/class/class.static/class.static.data/p3.cpp test/CXX/dcl.dcl/dcl.spe

Chandler Carruth chandlerc at google.com
Thu Sep 29 16:25:12 PDT 2011


On Thu, Sep 29, 2011 at 4:22 PM, Richard Smith <richard at metafoo.co.uk>wrote:

> On Thu, September 29, 2011 21:35, Chandler Carruth wrote:
> > On Thu, Sep 29, 2011 at 12:11 PM, Richard Smith
> > <richard-llvm at metafoo.co.uk>wrote:
> >> Author: rsmith
> >> Date: Thu Sep 29 14:11:37 2011
> >> New Revision: 140801
> >>
> >>
> >> URL: http://llvm.org/viewvc/llvm-project?rev=140801&view=rev
> >> Log:
> >> constexpr: semantic checking for constexpr variables.
> >>
> >>
> >> We had an extension which allowed const static class members of
> >> floating-point type to have in-class initializers, 'as a C++0x
> extension'.
> >> However, C++0x does not allow this. The extension has been kept, and
> >> extended to all literal types in C++0x mode (with a fixit to add the
> >> 'constexpr' specifier).
> >>
> >>
> >> Added:
> >> cfe/trunk/test/CXX/class/class.static/class.static.data/p3.cpp
> >> cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp Modified:
> >> cfe/trunk/include/clang/Basic/DiagnosticGroups.td
> >> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> >> cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> >> cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp
> >> cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
> >> cfe/trunk/test/FixIt/fixit-cxx0x.cpp cfe/trunk/test/SemaCXX/class.cpp
> >> cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp
> >>
> >> Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
> >> URL:
> >>
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic
> >> Groups.td?rev=140801&r1=140800&r2=140801&view=diff
> >>
> >>
> >>
> ===========================================================================
> >> ===
> >> --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
> >> +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Thu Sep 29
> 14:11:37
> >> 2011
> >> @@ -303,9 +303,7 @@
> >>
> >>
> >> // A warning group for warnings about using C++0x features as extensions
> >> in // earlier C++ versions.
> >> -def CXX0xStaticNonIntegralInitializer :
> >> -  DiagGroup<"c++0x-static-nonintegral-init">;
> >> -def CXX0x : DiagGroup<"c++0x-extensions",
> >> [CXX0xStaticNonIntegralInitializer]>;
> >> +def CXX0x : DiagGroup<"c++0x-extensions">;
> >
> > This could really use a better name than 'CXX0x'...
>
> CXX0xExt? And similarly for C1X, GNU and Microsoft?
>

I would probably be verbose and say CXX0xExtensions...


> >> @@ -5796,11 +5824,26 @@
> >> //   A member-declarator can contain a constant-initializer only
> >> //   if it declares a static member (9.4) of const integral or
> >> //   const enumeration type, see 9.4.2.
> >> +    //
> >> +    // C++0x [class.static.data]p3:
> >> +    //   If a non-volatile const static data member is of integral or
> >> +    //   enumeration type, its declaration in the class definition can
> >> +    //   specify a brace-or-equal-initializer in which every
> >> initalizer-clause +    //   that is an assignment-expression is a
> constant
> >> expression. A static +    //   data member of literal type can be
> declared in
> >> the class definition +    //   with the constexpr specifier; if so, its
> >> declaration shall specify a +    //   brace-or-equal-initializer in
> which
> >> every initializer-clause that is +    //   an assignment-expression is a
> >> constant expression. QualType T = VDecl->getType();
> >>
> >>
> >> // Do nothing on dependent types.
> >> if (T->isDependentType()) {
> >>
> >> +    // Allow any 'static constexpr' members, whether or not they are of
> >> literal +    // type. We separately check that the initializer is a
> constant
> >> expression, +    // which implicitly requires the member to be of
> literal
> >> type. +    } else if (VDecl->isConstexpr()) {
> >> +
> >> // Require constness.
> >> } else if (!T.isConstQualified()) {
> >> Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const)
> >> @@ -5809,6 +5852,9 @@
> >>
> >>
> >> // We allow integer constant expressions in all cases.
> >> } else if (T->isIntegralOrEnumerationType()) {
> >> +      // FIXME: In C++0x, a non-constexpr const static data member with
> an
> >> +      // in-class initializer cannot be volatile.
> >> +
> >> // Check whether the expression is a constant expression.
> >> SourceLocation Loc;
> >> if (Init->isValueDependent()) @@ -5828,31 +5874,28 @@
> >> VDecl->setInvalidDecl();
> >> }
> >>
> >>
> >> -    // We allow floating-point constants as an extension in C++03, and
> >> -    // C++0x has far more complicated rules that we don't really
> >> -    // implement fully.
> >> -    } else {
> >> -      bool Allowed = false;
> >> -      if (getLangOptions().CPlusPlus0x) {
> >> -        Allowed = T->isLiteralType();
> >> -      } else if (T->isFloatingType()) { // also permits complex, which
> is
> >> ok -        Diag(VDecl->getLocation(),
> >> diag::ext_in_class_initializer_float_type)
> >> -          << T << Init->getSourceRange();
> >> -        Allowed = true;
> >> -      }
> >> +    // Suggest adding 'constexpr' in C++0x for literal types.
> >> +    } else if (getLangOptions().CPlusPlus0x && T->isLiteralType()) {
> >> +      Diag(VDecl->getLocation(),
> >> diag::ext_in_class_initializer_literal_type)
> >> +        << T << Init->getSourceRange()
> >> +        << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr
> ");
> >>
> >>
> >
> > This FixItHint needs to be on a note, rather than the ext-warn; we don't
> > recover here by parsing this *as* a constexpr (nor would that be entirely
> > appropriate I suspect)...
>
> I've moved this from an ExtWarn to an Error (with the same fixit and error
> recovery) in r140820. The GNU extension allowing in-class initializers for
> static const members of floating point types is kept as-is -- such values
> aren't implicitly marked constexpr and thus can't be used in constant
> expressions.
>
> >> +      VDecl->setConstexpr(true);
> >> +
> >> +    // We allow floating-point constants as an extension.
> >> +    } else if (T->isFloatingType()) { // also permits complex, which is
> ok
> >> +      Diag(VDecl->getLocation(),
> >> diag::ext_in_class_initializer_float_type)
> >> +        << T << Init->getSourceRange();
> >>
> >>
> >> -      if (!Allowed) {
> >> -        Diag(VDecl->getLocation(),
> >> diag::err_in_class_initializer_bad_type)
> >> -          << T << Init->getSourceRange();
> >> -        VDecl->setInvalidDecl();
> >> -
> >> -      // TODO: there are probably expressions that pass here that
> >> shouldn't. -      } else if (!Init->isValueDependent() &&
> >> -                 !Init->isConstantInitializer(Context, false)) {
> >> +      if (!Init->isValueDependent() &&
> >> +          !Init->isConstantInitializer(Context, false)) {
> >> Diag(Init->getExprLoc(),
> >> diag::err_in_class_initializer_non_constant)
> >> << Init->getSourceRange();
> >> VDecl->setInvalidDecl();
> >> }
> >> +    } else {
> >> +      Diag(VDecl->getLocation(),
> diag::err_in_class_initializer_bad_type)
> >> +        << T << Init->getSourceRange();
> >> +      VDecl->setInvalidDecl();
> >> }
> >> } else if (VDecl->isFileVarDecl()) {
> >> if (VDecl->getStorageClassAsWritten() == SC_Extern && @@ -5893,6
> +5936,17 @@
> >>
> >>
> >> if (!VDecl->isInvalidDecl()) checkUnsafeAssigns(VDecl->getLocation(),
> >> VDecl->getType(), Init);
> >> +
> >> +  if (VDecl->isConstexpr() && !VDecl->isInvalidDecl() &&
> >> +      !VDecl->getType()->isDependentType() &&
> >> +      !Init->isTypeDependent() && !Init->isValueDependent() &&
> >> +      !Init->isConstantInitializer(Context,
> >> +
> VDecl->getType()->isReferenceType())) {
> >> +    // FIXME: Improve this diagnostic to explain why the initializer is
> >> not +    // a constant expression.
> >> +    Diag(VDecl->getLocation(),
> >> diag::err_constexpr_var_requires_const_init)
> >> +      << VDecl << Init->getSourceRange();
> >> +  }
> >>
> >>
> >> Init = MaybeCreateExprWithCleanups(Init);
> >> // Attach the initializer to the decl.
> >> @@ -5958,6 +6012,24 @@
> >> return; }
> >>
> >>
> >> +    // C++0x [dcl.constexpr]p9: An object or reference declared
> constexpr
> >> must +    // have an initializer.
> >> +    // C++0x [class.static.data]p3: A static data member can be
> declared
> >> with +    // the constexpr specifier; if so, its declaration shall
> specify
> >> +    // a brace-or-equal-initializer.
> >> +    if (Var->isConstexpr()) {
> >> +      // FIXME: Provide fix-its to convert the constexpr to const.
> >> +      if (Var->isStaticDataMember() && Var->getAnyInitializer()) {
> >> +        Diag(Var->getLocation(),
> >> diag::err_constexpr_initialized_static_member)
> >> +          << Var->getDeclName();
> >> +      } else {
> >> +        Diag(Var->getLocation(), diag::err_constexpr_var_requires_init)
> >> +          << Var->getDeclName();
> >> +      }
> >> +      Var->setInvalidDecl();
> >> +      return;
> >> +    }
> >> +
> >> switch (Var->isThisDeclarationADefinition()) { case VarDecl::Definition:
> if
> >> (!Var->isStaticDataMember() || !Var->getAnyInitializer())
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20110929/053d134f/attachment.html>


More information about the cfe-commits mailing list