efriedma created this revision. efriedma added reviewers: rsmith, erik.pilkington, aaron.ballman. efriedma requested review of this revision. Herald added a project: clang.
Similar to variables with an initializer, this is never valid in standard C, so we can safely constant-fold as an extension. I ran into this construct in a couple proprietary codebases. While I'm here, drive-by fix for 090dd647 <https://reviews.llvm.org/rG090dd647d98dc50a56a42fbba0f3f11b10a3a187>: we should only fold variables with VLA types, not arbitrary variably modified types. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D98363 Files: clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaExpr.cpp clang/test/Sema/vla.c
Index: clang/test/Sema/vla.c =================================================================== --- clang/test/Sema/vla.c +++ clang/test/Sema/vla.c @@ -129,4 +129,9 @@ // expected-warning@+1{{variable length array folded to constant array as an extension}} char a8[2][ksize] = {{1,2,3,4},{4,3,2,1}}; + + // expected-warning@+1{{variable length array folded to constant array as an extension}} + char (*a9)[] = (char[2][ksize]) {{1,2,3,4},{4,3,2,1}}; + + char (*a10)[ksize] = 0; } Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -6833,9 +6833,12 @@ diag::err_array_incomplete_or_sizeless_type, SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd()))) return ExprError(); - if (literalType->isVariableArrayType()) - return ExprError(Diag(LParenLoc, diag::err_variable_object_no_init) - << SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd())); + if (literalType->isVariableArrayType()) { + if (!tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc, + diag::err_variable_object_no_init)) { + return ExprError(); + } + } } else if (!literalType->isDependentType() && RequireCompleteType(LParenLoc, literalType, diag::err_typecheck_decl_incomplete_type, Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -6038,26 +6038,26 @@ /// Attempt to fold a variable-sized type to a constant-sized type, returning /// true if we were successful. -static bool tryToFixVariablyModifiedVarType(Sema &S, TypeSourceInfo *&TInfo, - QualType &T, SourceLocation Loc, - unsigned FailedFoldDiagID) { +bool Sema::tryToFixVariablyModifiedVarType(TypeSourceInfo *&TInfo, + QualType &T, SourceLocation Loc, + unsigned FailedFoldDiagID) { bool SizeIsNegative; llvm::APSInt Oversized; TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo( - TInfo, S.Context, SizeIsNegative, Oversized); + TInfo, Context, SizeIsNegative, Oversized); if (FixedTInfo) { - S.Diag(Loc, diag::ext_vla_folded_to_constant); + Diag(Loc, diag::ext_vla_folded_to_constant); TInfo = FixedTInfo; T = FixedTInfo->getType(); return true; } if (SizeIsNegative) - S.Diag(Loc, diag::err_typecheck_negative_array_size); + Diag(Loc, diag::err_typecheck_negative_array_size); else if (Oversized.getBoolValue()) - S.Diag(Loc, diag::err_array_too_large) << Oversized.toString(10); + Diag(Loc, diag::err_array_too_large) << Oversized.toString(10); else if (FailedFoldDiagID) - S.Diag(Loc, FailedFoldDiagID); + Diag(Loc, FailedFoldDiagID); return false; } @@ -6894,10 +6894,10 @@ } } - // If this variable has a variable-modified type and an initializer, try to + // If this variable has a VLA type and an initializer, try to // fold to a constant-sized type. This is otherwise invalid. - if (D.hasInitializer() && R->isVariablyModifiedType()) - tryToFixVariablyModifiedVarType(*this, TInfo, R, D.getIdentifierLoc(), + if (D.hasInitializer() && R->isVariableArrayType()) + tryToFixVariablyModifiedVarType(TInfo, R, D.getIdentifierLoc(), /*DiagID=*/0); bool IsMemberSpecialization = false; @@ -16734,7 +16734,7 @@ // than a variably modified type. if (!InvalidDecl && T->isVariablyModifiedType()) { if (!tryToFixVariablyModifiedVarType( - *this, TInfo, T, Loc, diag::err_typecheck_field_variable_size)) + TInfo, T, Loc, diag::err_typecheck_field_variable_size)) InvalidDecl = true; } @@ -16962,7 +16962,7 @@ // than a variably modified type. else if (T->isVariablyModifiedType()) { if (!tryToFixVariablyModifiedVarType( - *this, TInfo, T, Loc, diag::err_typecheck_ivar_variable_size)) + TInfo, T, Loc, diag::err_typecheck_ivar_variable_size)) D.setInvalidType(); } Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -2579,6 +2579,9 @@ NamedDecl *HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists); + bool tryToFixVariablyModifiedVarType(TypeSourceInfo *&TInfo, + QualType &T, SourceLocation Loc, + unsigned FailedFoldDiagID); void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S); bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info); bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits