diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h index 6d21bc406f90..f919eb2946f7 100644 --- a/clang/include/clang/Sema/Initialization.h +++ b/clang/include/clang/Sema/Initialization.h @@ -651,6 +651,8 @@ public: FK_DefaultInitOfConst, /// \brief Initialization of an incomplete type. FK_Incomplete, + /// \brief Variable-length array must not have an initializer. + FK_VariableLengthArrayHasInitializer, /// \brief List initialization failed at some point. FK_ListInitializationFailed, /// \brief Initializer has a placeholder type which cannot be diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 479f80f1dd4d..468baae2052b 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1422,6 +1422,10 @@ bool VarDecl::evaluateValue( } bool VarDecl::checkInitIsICE() const { + // Initializers of weak variables are never ICEs. + if (isWeak()) + return false; + EvaluatedStmt *Eval = ensureEvaluatedStmt(); if (Eval->CheckedICE) // We have already checked whether this subexpression is an diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 43c9af58bc98..f82026f89f98 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6045,7 +6045,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // 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. + // "ary" transitions from an IncompleteArrayType to a ConstantArrayType. if (!VDecl->isInvalidDecl() && (DclT != SavT)) { VDecl->setType(DclT); Init->setType(DclT.getNonReferenceType()); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 7a28a448239c..bcb624be899c 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2427,6 +2427,7 @@ bool InitializationSequence::isAmbiguous() const { case FK_ArrayTypeMismatch: case FK_NonConstantArrayInit: case FK_ListInitializationFailed: + case FK_VariableLengthArrayHasInitializer: case FK_PlaceholderType: return false; @@ -4060,6 +4061,11 @@ InitializationSequence::InitializationSequence(Sema &S, // - Otherwise, if the destination type is an array, the program is // ill-formed. if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) { + if (Initializer && isa(DestAT)) { + SetFailed(FK_VariableLengthArrayHasInitializer); + return; + } + if (Initializer && IsStringInit(Initializer, DestAT, Context)) { TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this); return; @@ -5277,6 +5283,11 @@ bool InitializationSequence::Diagnose(Sema &S, << Args[0]->getSourceRange(); break; + case FK_VariableLengthArrayHasInitializer: + S.Diag(Kind.getLocation(), diag::err_variable_object_no_init) + << Args[0]->getSourceRange(); + break; + case FK_AddressOfOverloadFailed: { DeclAccessPair Found; S.ResolveAddressOfOverloadedFunction(Args[0], @@ -5659,6 +5670,10 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "list initialization checker failure"; break; + case FK_VariableLengthArrayHasInitializer: + OS << "variable length array has an initializer"; + break; + case FK_PlaceholderType: OS << "initializer expression isn't contextually valid"; break; diff --git a/clang/test/Sema/array-init.c b/clang/test/Sema/array-init.c index a8ee3ca8df1d..bd1dfd2c06fd 100644 --- a/clang/test/Sema/array-init.c +++ b/clang/test/Sema/array-init.c @@ -167,7 +167,7 @@ void charArrays() { void variableArrayInit() { int a = 4; - char strlit[a] = "foo"; //expected-error{{array initializer must be an initializer list or string literal}} + char strlit[a] = "foo"; //expected-error{{variable-sized object may not be initialized}} int b[a] = { 1, 2, 4 }; //expected-error{{variable-sized object may not be initialized}} } @@ -278,3 +278,10 @@ int a6[5] = (int[]){1, 2, 3}; // expected-error{{cannot initialize array of type int nonconst_value(); int a7[5] = (int[5]){ 1, 2, 3, 4, nonconst_value() }; // expected-error{{initializer element is not a compile-time constant}} + +// +__attribute__((weak)) const unsigned int test10_bound = 10; +char test10_global[test10_bound]; // expected-error {{variable length array declaration not allowed at file scope}} +void test10() { + char test10_local[test10_bound] = "help"; // expected-error {{variable-sized object may not be initialized}} +}