diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-12-15 19:20:59 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-12-15 19:20:59 +0000 |
commit | 018887209f51de943c17718a6f3bce904d612813 (patch) | |
tree | bcd3b50d521bbb9d89fbf3ca94971767df130a5c /lib/Sema/SemaDecl.cpp | |
parent | d4b66b9403d8898cfc82dd588edf9d8b2fa46588 (diff) |
Refactor and simplify AddInitializerToDecl.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146673 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 174 |
1 files changed, 73 insertions, 101 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 238dbd4679..a42b4a54a8 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5946,7 +5946,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, return; } - // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. + // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { TypeSourceInfo *DeducedType = 0; if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType)) @@ -5969,7 +5969,14 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, if (VarDecl *Old = VDecl->getPreviousDeclaration()) MergeVarDeclTypes(VDecl, Old); } - + + if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) { + // C99 6.7.8p5. C++ has no such restriction, but that is a defect. + Diag(VDecl->getLocation(), diag::err_block_extern_cant_init); + VDecl->setInvalidDecl(); + return; + } + // A definition must end up with a complete type, which means it must be // complete with the restriction that an array type might be completed by the @@ -6036,44 +6043,58 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, return; } - // Capture the variable that is being initialized and the style of - // initialization. - InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); - - // FIXME: Poor source location information. - InitializationKind Kind - = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(), - Init->getLocStart(), - Init->getLocEnd()) - : InitializationKind::CreateCopy(VDecl->getLocation(), - Init->getLocStart()); - // Get the decls type and save a reference for later, since // CheckInitializerTypes may change it. QualType DclT = VDecl->getType(), SavT = DclT; - if (VDecl->isLocalVarDecl()) { - if (VDecl->hasExternalStorage()) { // C99 6.7.8p5 - Diag(VDecl->getLocation(), diag::err_block_extern_cant_init); + + // Perform the initialization. + if (!VDecl->isInvalidDecl()) { + InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); + InitializationKind Kind + = DirectInit ? InitializationKind::CreateDirect(VDecl->getLocation(), + Init->getLocStart(), + Init->getLocEnd()) + : InitializationKind::CreateCopy(VDecl->getLocation(), + Init->getLocStart()); + + InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &Init, 1), + &DclT); + if (Result.isInvalid()) { VDecl->setInvalidDecl(); - } else 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; - } + return; + } - Init = Result.takeAs<Expr>(); + Init = Result.takeAs<Expr>(); + } - // C++ 3.6.2p2, allow dynamic initialization of static initializers. - // Don't check invalid declarations to avoid emitting useless diagnostics. - if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) { - if (VDecl->getStorageClass() == SC_Static) // C99 6.7.8p4. - CheckForConstantInitializer(Init, DclT); - } - } + // If the type changed, it means we had an incomplete type that was + // completed by the initializer. For example: + // int ary[] = { 1, 3, 5 }; + // "ary" transitions from a VariableArrayType to a ConstantArrayType. + if (!VDecl->isInvalidDecl() && (DclT != SavT)) { + VDecl->setType(DclT); + Init->setType(DclT.getNonReferenceType()); + } + + // Check any implicit conversions within the expression. + CheckImplicitConversions(Init, VDecl->getLocation()); + + if (!VDecl->isInvalidDecl()) + checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init); + + Init = MaybeCreateExprWithCleanups(Init); + // Attach the initializer to the decl. + VDecl->setInit(Init); + + if (VDecl->isLocalVarDecl()) { + // C99 6.7.8p4: All the expressions in an initializer for an object that has + // static storage duration shall be constant expressions or string literals. + // C++ does not have this restriction. + if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl() && + VDecl->getStorageClass() == SC_Static) + CheckForConstantInitializer(Init, DclT); } else if (VDecl->isStaticDataMember() && VDecl->getLexicalDeclContext()->isRecord()) { // This is an in-class initialization for a static data member, e.g., @@ -6082,26 +6103,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // static const int value = 17; // }; - // 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. // - // C++0x [class.static.data]p3: + // C++11 [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 @@ -6110,10 +6117,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // 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()) { + if (DclT->isDependentType()) { // Allow any 'static constexpr' members, whether or not they are of literal // type. We separately check that the initializer is a constant expression, @@ -6121,17 +6127,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } else if (VDecl->isConstexpr()) { // Require constness. - } else if (!T.isConstQualified()) { + } else if (!DclT.isConstQualified()) { Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const) << Init->getSourceRange(); VDecl->setInvalidDecl(); // We allow integer constant expressions in all cases. - } else if (T->isIntegralOrEnumerationType()) { + } else if (DclT->isIntegralOrEnumerationType()) { // Check whether the expression is a constant expression. SourceLocation Loc; - if (getLangOptions().CPlusPlus0x && T.isVolatileQualified()) - // In C++0x, a non-constexpr const static data member with an + if (getLangOptions().CPlusPlus0x && DclT.isVolatileQualified()) + // In C++11, a non-constexpr const static data member with an // in-class initializer cannot be volatile. Diag(VDecl->getLocation(), diag::err_in_class_initializer_volatile); else if (Init->isValueDependent()) @@ -6151,77 +6157,43 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, VDecl->setInvalidDecl(); } - // We allow floating-point constants as an extension. - } else if (T->isFloatingType()) { // also permits complex, which is ok + // We allow foldable floating-point constants as an extension. + } else if (DclT->isFloatingType()) { // also permits complex, which is ok Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type) - << T << Init->getSourceRange(); + << DclT << Init->getSourceRange(); if (getLangOptions().CPlusPlus0x) Diag(VDecl->getLocation(), diag::note_in_class_initializer_float_type_constexpr) << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); - if (!Init->isValueDependent() && - !Init->isConstantInitializer(Context, false)) { + if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) { Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant) << Init->getSourceRange(); VDecl->setInvalidDecl(); } - // Suggest adding 'constexpr' in C++0x for literal types. - } else if (getLangOptions().CPlusPlus0x && T->isLiteralType()) { + // Suggest adding 'constexpr' in C++11 for literal types. + } else if (getLangOptions().CPlusPlus0x && DclT->isLiteralType()) { Diag(VDecl->getLocation(), diag::err_in_class_initializer_literal_type) - << T << Init->getSourceRange() + << DclT << Init->getSourceRange() << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); VDecl->setConstexpr(true); } else { Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type) - << T << Init->getSourceRange(); + << DclT << Init->getSourceRange(); VDecl->setInvalidDecl(); } } else if (VDecl->isFileVarDecl()) { - if (VDecl->getStorageClassAsWritten() == SC_Extern && - (!getLangOptions().CPlusPlus || + if (VDecl->getStorageClassAsWritten() == SC_Extern && + (!getLangOptions().CPlusPlus || !Context.getBaseElementType(VDecl->getType()).isConstQualified())) Diag(VDecl->getLocation(), diag::warn_extern_init); - 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++ 3.6.2p2, allow dynamic initialization of static initializers. - // Don't check invalid declarations to avoid emitting useless diagnostics. - if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) { - // C99 6.7.8p4. All file scoped initializers need to be constant. + // C99 6.7.8p4. All file scoped initializers need to be constant. + if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) CheckForConstantInitializer(Init, DclT); - } } - // If the type changed, it means we had an incomplete type that was - // completed by the initializer. For example: - // int ary[] = { 1, 3, 5 }; - // "ary" transitions from a VariableArrayType to a ConstantArrayType. - if (!VDecl->isInvalidDecl() && (DclT != SavT)) { - VDecl->setType(DclT); - Init->setType(DclT.getNonReferenceType()); - } - - // Check any implicit conversions within the expression. - CheckImplicitConversions(Init, VDecl->getLocation()); - - if (!VDecl->isInvalidDecl()) - checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init); - - Init = MaybeCreateExprWithCleanups(Init); - // Attach the initializer to the decl. - VDecl->setInit(Init); CheckCompleteVariableDeclaration(VDecl); } |