diff options
author | Larisse Voufo <lvoufo@google.com> | 2013-06-15 20:17:46 +0000 |
---|---|---|
committer | Larisse Voufo <lvoufo@google.com> | 2013-06-15 20:17:46 +0000 |
commit | 0f1394c86eb68f0390fee4bef987e9ea4451a757 (patch) | |
tree | 0415b7d9e4db92250a883e5434b4de44fa5d0118 /clang | |
parent | c5f290f6c6159d1a90974455af5738c8109e2159 (diff) | |
download | bcm5719-llvm-0f1394c86eb68f0390fee4bef987e9ea4451a757.tar.gz bcm5719-llvm-0f1394c86eb68f0390fee4bef987e9ea4451a757.zip |
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.
llvm-svn: 184048
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 141 | ||||
-rw-r--r-- | clang/test/SemaCXX/cxx98-compat-pedantic.cpp | 13 |
4 files changed, 101 insertions, 66 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 7891f12323e..eddf1e2e950 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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<CXX11Narrowing>, 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/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 9a91bc46d7b..0cd639d0fe3 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 087fea206d7..40af2075c3f 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/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/clang/test/SemaCXX/cxx98-compat-pedantic.cpp b/clang/test/SemaCXX/cxx98-compat-pedantic.cpp index 0b18ae4f221..d1bb437df59 100644 --- a/clang/test/SemaCXX/cxx98-compat-pedantic.cpp +++ b/clang/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<typename T> class ExternTemplate {}; extern template class ExternTemplate<int>; // expected-warning {{extern templates are incompatible with C++98}} |