diff options
| author | John McCall <rjmccall@apple.com> | 2010-09-10 23:21:22 +0000 | 
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2010-09-10 23:21:22 +0000 | 
| commit | db76892e72e458030804b9d6d9e2eea16d52f229 (patch) | |
| tree | 2db0059dbf234b610cf64617ed4daee2299eb444 /clang/lib | |
| parent | 72497e5d90807a40eb4d8d311e9e0c0e011c6e4c (diff) | |
| download | bcm5719-llvm-db76892e72e458030804b9d6d9e2eea16d52f229.tar.gz bcm5719-llvm-db76892e72e458030804b9d6d9e2eea16d52f229.zip | |
Support in-class initialization of static const floating-point data members.
llvm-svn: 113663
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 78 | 
1 files changed, 53 insertions, 25 deletions
| diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index dbc758f1f2a..e4dca2ba980 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4115,8 +4115,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {      if (getLangOptions().CPlusPlus &&          RealDecl->getLexicalDeclContext()->isRecord() &&          isa<NamedDecl>(RealDecl)) -      Diag(RealDecl->getLocation(), diag::err_member_initialization) -        << cast<NamedDecl>(RealDecl)->getDeclName(); +      Diag(RealDecl->getLocation(), diag::err_member_initialization);      else        Diag(RealDecl->getLocation(), diag::err_illegal_initializer);      RealDecl->setInvalidDecl(); @@ -4220,34 +4219,38 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {      //   static const int value = 17;      // }; -    // Attach the initializer -    VDecl->setInit(Init); +    // Try to perform the initialization regardless. +    if (!VDecl->isInvalidDecl()) { +      InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); +      ExprResult Result = InitSeq.Perform(*this, Entity, Kind, +                                          MultiExprArg(*this, &Init, 1), +                                          &DclT); +      if (Result.isInvalid()) { +        VDecl->setInvalidDecl(); +        return; +      } + +      Init = Result.takeAs<Expr>(); +    }      // C++ [class.mem]p4:      //   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.      QualType T = VDecl->getType(); -    if (!T->isDependentType() && -        (!Context.getCanonicalType(T).isConstQualified() || -         !T->isIntegralOrEnumerationType())) { -      Diag(VDecl->getLocation(), diag::err_member_initialization) -        << VDecl->getDeclName() << Init->getSourceRange(); + +    // Do nothing on dependent types. +    if (T->isDependentType()) { + +    // Require constness. +    } else if (!T.isConstQualified()) { +      Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const) +        << Init->getSourceRange();        VDecl->setInvalidDecl(); -    } else { -      // C++ [class.static.data]p4: -      //   If a static data member is of const integral or const -      //   enumeration type, its declaration in the class definition -      //   can specify a constant-initializer which shall be an -      //   integral constant expression (5.19). -      if (!Init->isTypeDependent() && -          !Init->getType()->isIntegralOrEnumerationType()) { -        // We have a non-dependent, non-integral or enumeration type. -        Diag(Init->getSourceRange().getBegin(), -             diag::err_in_class_initializer_non_integral_type) -          << Init->getType() << Init->getSourceRange(); -        VDecl->setInvalidDecl(); -      } else if (!Init->isTypeDependent() && !Init->isValueDependent()) { + +    // We allow integer constant expressions in all cases. +    } else if (T->isIntegralOrEnumerationType()) { +      if (!Init->isValueDependent()) {          // Check whether the expression is a constant expression.          llvm::APSInt Value;          SourceLocation Loc; @@ -4255,8 +4258,33 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {            Diag(Loc, diag::err_in_class_initializer_non_constant)              << Init->getSourceRange();            VDecl->setInvalidDecl(); -        } else if (!VDecl->getType()->isDependentType()) -          ImpCastExprToType(Init, VDecl->getType(), CK_IntegralCast); +        } +      } + +    // 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; +      } + +      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)) { +        Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant) +          << Init->getSourceRange(); +        VDecl->setInvalidDecl();        }      }    } else if (VDecl->isFileVarDecl()) { | 

