From 539470e7d38f71b7a0700e1f1b371e76480cf0a6 Mon Sep 17 00:00:00 2001 From: Larisse Voufo Date: Sat, 15 Jun 2013 20:17:46 +0000 Subject: [PATCH] Updated the support for contextual conversion tweaks (n3323) with a previously overlooked part: implicitly converting array sizes to size_t, rather than contextually converting them to some unique type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184048 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 6 +- include/clang/Sema/Sema.h | 7 +- lib/Sema/SemaExprCXX.cpp | 141 +++++++++++++-------- test/SemaCXX/cxx98-compat-pedantic.cpp | 13 +- 4 files changed, 101 insertions(+), 66 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7891f12323..eddf1e2e95 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -36,15 +36,15 @@ def err_typecheck_converted_constant_expression : Error< def err_typecheck_converted_constant_expression_disallowed : Error< "conversion from %0 to %1 is not allowed in a converted constant expression">; def err_expr_not_cce : Error< - "%select{case value|enumerator value|non-type template argument}0 " + "%select{case value|enumerator value|non-type template argument|array size}0 " "is not a constant expression">; def err_cce_narrowing : ExtWarn< - "%select{case value|enumerator value|non-type template argument}0 " + "%select{case value|enumerator value|non-type template argument|array size}0 " "%select{cannot be narrowed from type %2 to %3|" "evaluates to %2, which cannot be narrowed to type %3}1">, InGroup, DefaultError; def err_cce_narrowing_sfinae : Error< - "%select{case value|enumerator value|non-type template argument}0 " + "%select{case value|enumerator value|non-type template argument|array size}0 " "%select{cannot be narrowed from type %2 to %3|" "evaluates to %2, which cannot be narrowed to type %3}1">; def err_ice_not_integral : Error< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 9a91bc46d7..0cd639d0fe 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1938,9 +1938,10 @@ public: /// Contexts in which a converted constant expression is required. enum CCEKind { - CCEK_CaseValue, ///< Expression in a case label. - CCEK_Enumerator, ///< Enumerator value with fixed underlying type. - CCEK_TemplateArg ///< Value of a non-type template parameter. + CCEK_CaseValue, ///< Expression in a case label. + CCEK_Enumerator, ///< Enumerator value with fixed underlying type. + CCEK_TemplateArg, ///< Value of a non-type template parameter. + CCEK_NewExpr ///< Constant expression in a noptr-new-declarator. }; ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, llvm::APSInt &Value, CCEKind CCE); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 087fea206d..40af2075c3 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1017,10 +1017,23 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr; if (Expr *NumElts = (Expr *)Array.NumElts) { if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) { - Array.NumElts - = VerifyIntegerConstantExpression(NumElts, 0, - diag::err_new_array_nonconst) - .take(); + if (getLangOpts().CPlusPlus1y) { + // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator + // shall be a converted constant expression (5.19) of type std::size_t + // and shall evaluate to a strictly positive value. + unsigned IntWidth = Context.getTargetInfo().getIntWidth(); + assert(IntWidth && "Builtin type of size 0?"); + llvm::APSInt Value(IntWidth); + Array.NumElts + = CheckConvertedConstantExpression(NumElts, Context.getSizeType(), Value, + CCEK_NewExpr) + .take(); + } else { + Array.NumElts + = VerifyIntegerConstantExpression(NumElts, 0, + diag::err_new_array_nonconst) + .take(); + } if (!Array.NumElts) return ExprError(); } @@ -1183,65 +1196,81 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // C++1y [expr.new]p6: The expression [...] is implicitly converted to // std::size_t. (FIXME) if (ArraySize && !ArraySize->isTypeDependent()) { - class SizeConvertDiagnoser : public ICEConvertDiagnoser { - Expr *ArraySize; - - public: - SizeConvertDiagnoser(Expr *ArraySize) - : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false, false, false), - ArraySize(ArraySize) {} - - virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, - QualType T) { - return S.Diag(Loc, diag::err_array_size_not_integral) - << S.getLangOpts().CPlusPlus11 << T; - } - - virtual SemaDiagnosticBuilder diagnoseIncomplete( - Sema &S, SourceLocation Loc, QualType T) { - return S.Diag(Loc, diag::err_array_size_incomplete_type) - << T << ArraySize->getSourceRange(); - } - - virtual SemaDiagnosticBuilder diagnoseExplicitConv( - Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) { - return S.Diag(Loc, diag::err_array_size_explicit_conversion) << T << ConvTy; - } - - virtual SemaDiagnosticBuilder noteExplicitConv( - Sema &S, CXXConversionDecl *Conv, QualType ConvTy) { - return S.Diag(Conv->getLocation(), diag::note_array_size_conversion) - << ConvTy->isEnumeralType() << ConvTy; - } - - virtual SemaDiagnosticBuilder diagnoseAmbiguous( - Sema &S, SourceLocation Loc, QualType T) { - return S.Diag(Loc, diag::err_array_size_ambiguous_conversion) << T; - } - - virtual SemaDiagnosticBuilder noteAmbiguous( - Sema &S, CXXConversionDecl *Conv, QualType ConvTy) { - return S.Diag(Conv->getLocation(), diag::note_array_size_conversion) - << ConvTy->isEnumeralType() << ConvTy; - } + ExprResult ConvertedSize; + if (getLangOpts().CPlusPlus1y) { + unsigned IntWidth = Context.getTargetInfo().getIntWidth(); + assert(IntWidth && "Builtin type of size 0?"); + llvm::APSInt Value(IntWidth); + ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(), + AA_Converting); + + if (!isSFINAEContext()) + // Diagnose the compatibility of this conversion. + Diag(StartLoc, diag::warn_cxx98_compat_array_size_conversion) + << ArraySize->getType() << 0 << Context.getSizeType(); + } else { + class SizeConvertDiagnoser : public ICEConvertDiagnoser { + protected: + Expr *ArraySize; + + public: + SizeConvertDiagnoser(Expr *ArraySize) + : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false, false, false), + ArraySize(ArraySize) {} + + virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_array_size_not_integral) + << S.getLangOpts().CPlusPlus11 << T; + } + + virtual SemaDiagnosticBuilder diagnoseIncomplete( + Sema &S, SourceLocation Loc, QualType T) { + return S.Diag(Loc, diag::err_array_size_incomplete_type) + << T << ArraySize->getSourceRange(); + } + + virtual SemaDiagnosticBuilder diagnoseExplicitConv( + Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) { + return S.Diag(Loc, diag::err_array_size_explicit_conversion) << T << ConvTy; + } + + virtual SemaDiagnosticBuilder noteExplicitConv( + Sema &S, CXXConversionDecl *Conv, QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_array_size_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual SemaDiagnosticBuilder diagnoseAmbiguous( + Sema &S, SourceLocation Loc, QualType T) { + return S.Diag(Loc, diag::err_array_size_ambiguous_conversion) << T; + } + + virtual SemaDiagnosticBuilder noteAmbiguous( + Sema &S, CXXConversionDecl *Conv, QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_array_size_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } - virtual SemaDiagnosticBuilder diagnoseConversion( - Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) { - return S.Diag(Loc, - S.getLangOpts().CPlusPlus11 - ? diag::warn_cxx98_compat_array_size_conversion - : diag::ext_array_size_conversion) - << T << ConvTy->isEnumeralType() << ConvTy; - } - } SizeDiagnoser(ArraySize); + virtual SemaDiagnosticBuilder diagnoseConversion( + Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) { + return S.Diag(Loc, + S.getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_array_size_conversion + : diag::ext_array_size_conversion) + << T << ConvTy->isEnumeralType() << ConvTy; + } + } SizeDiagnoser(ArraySize); - ExprResult ConvertedSize - = PerformContextualImplicitConversion(StartLoc, ArraySize, SizeDiagnoser); + ConvertedSize = PerformContextualImplicitConversion(StartLoc, ArraySize, + SizeDiagnoser); + } if (ConvertedSize.isInvalid()) return ExprError(); ArraySize = ConvertedSize.take(); QualType SizeType = ArraySize->getType(); + if (!SizeType->isIntegralOrUnscopedEnumerationType()) return ExprError(); diff --git a/test/SemaCXX/cxx98-compat-pedantic.cpp b/test/SemaCXX/cxx98-compat-pedantic.cpp index 0b18ae4f22..d1bb437df5 100644 --- a/test/SemaCXX/cxx98-compat-pedantic.cpp +++ b/test/SemaCXX/cxx98-compat-pedantic.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat-pedantic -verify %s -// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat -Werror %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat-pedantic -verify %s -DCXX1Y2 +// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat -Werror %s -DCXX1Y2 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat-pedantic -verify %s // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -Werror %s // RUN: %clang_cc1 -fsyntax-only -std=c++98 -Werror %s -// RUN: %clang_cc1 -fsyntax-only -std=c++1y -Wc++98-compat-pedantic -verify %s -Wno-c++98-c++11-compat-pedantic +// RUN: %clang_cc1 -fsyntax-only -std=c++1y -Wc++98-compat-pedantic -verify %s -Wno-c++98-c++11-compat-pedantic -DCXX1Y2 // -Wc++98-compat-pedantic warns on C++11 features which we accept without a // warning in C++98 mode. @@ -32,7 +32,12 @@ void *FnVoidPtr = (void*)&dlsym; // expected-warning {{cast between pointer-to-f struct ConvertToInt { operator int(); }; -int *ArraySizeConversion = new int[ConvertToInt()]; // expected-warning {{implicit conversion from array size expression of type 'ConvertToInt' to integral type 'int' is incompatible with C++98}} +int *ArraySizeConversion = new int[ConvertToInt()]; +#ifdef CXX1Y2 +// expected-warning@-2 {{implicit conversion from array size expression of type 'ConvertToInt' to integral type 'unsigned long' is incompatible with C++98}} +#else +// expected-warning@-4 {{implicit conversion from array size expression of type 'ConvertToInt' to integral type 'int' is incompatible with C++98}} +#endif template class ExternTemplate {}; extern template class ExternTemplate; // expected-warning {{extern templates are incompatible with C++98}} -- 2.40.0