From 6b13022faef260c8f49d04310f4a2c0a57f9103b Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 18 Oct 2011 21:39:00 +0000 Subject: [PATCH] -Wc++98-compat and -Wc++98-compat-pedantic warnings for Sema, part 2. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142426 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 12 ++++ lib/Sema/SemaCXXScopeSpec.cpp | 2 +- lib/Sema/SemaDeclCXX.cpp | 67 ++++++++++++---------- lib/Sema/SemaInit.cpp | 13 +++-- test/SemaCXX/cxx98-compat.cpp | 14 ++++- 5 files changed, 69 insertions(+), 39 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 3993046b2a..8d8a888e7e 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -622,8 +622,14 @@ def err_unexpected_friend : Error< "friends can only be classes or functions">; def ext_enum_friend : ExtWarn< "enumeration type %0 cannot be a friend">; +def warn_cxx98_compat_enum_friend : Warning< + "befriending enumeration type %0 is incompatible with C++98">, + InGroup, DefaultIgnore; def ext_nonclass_type_friend : ExtWarn< "non-class friend type %0 is a C++11 extension">, InGroup; +def warn_cxx98_compat_nonclass_type_friend : Warning< + "non-class friend type %0 is incompatible with C++98">, + InGroup, DefaultIgnore; def err_friend_is_member : Error< "friends cannot be members of the declaring class">; def warn_cxx98_compat_friend_is_member : Warning< @@ -632,6 +638,9 @@ def warn_cxx98_compat_friend_is_member : Warning< def ext_unelaborated_friend_type : ExtWarn< "specify '%select{struct|union|class|enum}0' to befriend %1; accepted " "as a C++11 extension">, InGroup; +def warn_cxx98_compat_unelaborated_friend_type : Warning< + "befriending %1 without '%select{struct|union|class|enum}0' keyword is " + "incompatible with C++98">, InGroup, DefaultIgnore; def err_qualified_friend_not_found : Error< "no function named %0 with type %1 was found in the specified scope">; def err_introducing_special_friend : Error< @@ -2800,6 +2809,9 @@ def ext_complex_component_init : Extension< "complex initialization specifying real and imaginary components " "is an extension">, InGroup>; def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">; +def warn_cxx98_compat_empty_scalar_initializer : Warning< + "scalar initialized from empty initializer list is incompatible with C++98">, + InGroup, DefaultIgnore; def err_illegal_initializer : Error< "illegal initializer (only variables can be initialized)">; def err_illegal_initializer_type : Error<"illegal initializer type %0">; diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 360a0404b8..a9b6536e7d 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -268,7 +268,7 @@ bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) { if (!isa(SD)) return false; - // Determine whether we have a class (or, in C++0x, an enum) or + // Determine whether we have a class (or, in C++11, an enum) or // a typedef thereof. If so, build the nested-name-specifier. QualType T = Context.getTypeDeclType(cast(SD)); if (T->isDependentType()) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 528c4ddbc3..951ea9ccfd 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -9652,39 +9652,46 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation FriendLoc, QualType T = TSInfo->getType(); SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange(); - if (!getLangOptions().CPlusPlus0x) { - // C++03 [class.friend]p2: - // An elaborated-type-specifier shall be used in a friend declaration - // for a class.* - // - // * The class-key of the elaborated-type-specifier is required. - if (!ActiveTemplateInstantiations.empty()) { - // Do not complain about the form of friend template types during - // template instantiation; we will already have complained when the - // template was declared. - } else if (!T->isElaboratedTypeSpecifier()) { - // If we evaluated the type to a record type, suggest putting - // a tag in front. - if (const RecordType *RT = T->getAs()) { - RecordDecl *RD = RT->getDecl(); - - std::string InsertionText = std::string(" ") + RD->getKindName(); - - Diag(TypeRange.getBegin(), diag::ext_unelaborated_friend_type) - << (unsigned) RD->getTagKind() - << T - << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), - InsertionText); - } else { - Diag(FriendLoc, diag::ext_nonclass_type_friend) - << T - << SourceRange(FriendLoc, TypeRange.getEnd()); - } - } else if (T->getAs()) { - Diag(FriendLoc, diag::ext_enum_friend) + // C++03 [class.friend]p2: + // An elaborated-type-specifier shall be used in a friend declaration + // for a class.* + // + // * The class-key of the elaborated-type-specifier is required. + if (!ActiveTemplateInstantiations.empty()) { + // Do not complain about the form of friend template types during + // template instantiation; we will already have complained when the + // template was declared. + } else if (!T->isElaboratedTypeSpecifier()) { + // If we evaluated the type to a record type, suggest putting + // a tag in front. + if (const RecordType *RT = T->getAs()) { + RecordDecl *RD = RT->getDecl(); + + std::string InsertionText = std::string(" ") + RD->getKindName(); + + Diag(TypeRange.getBegin(), + getLangOptions().CPlusPlus0x ? + diag::warn_cxx98_compat_unelaborated_friend_type : + diag::ext_unelaborated_friend_type) + << (unsigned) RD->getTagKind() + << T + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), + InsertionText); + } else { + Diag(FriendLoc, + getLangOptions().CPlusPlus0x ? + diag::warn_cxx98_compat_nonclass_type_friend : + diag::ext_nonclass_type_friend) << T << SourceRange(FriendLoc, TypeRange.getEnd()); } + } else if (T->getAs()) { + Diag(FriendLoc, + getLangOptions().CPlusPlus0x ? + diag::warn_cxx98_compat_enum_friend : + diag::ext_enum_friend) + << T + << SourceRange(FriendLoc, TypeRange.getEnd()); } // C++0x [class.friend]p3: diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index f449c7d70d..b96d168a97 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -902,12 +902,13 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity, InitListExpr *StructuredList, unsigned &StructuredIndex) { if (Index >= IList->getNumInits()) { - if (!SemaRef.getLangOptions().CPlusPlus0x) { - if (!VerifyOnly) - SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer) - << IList->getSourceRange(); - hadError = true; - } + if (!VerifyOnly) + SemaRef.Diag(IList->getLocStart(), + SemaRef.getLangOptions().CPlusPlus0x ? + diag::warn_cxx98_compat_empty_scalar_initializer : + diag::err_empty_scalar_initializer) + << IList->getSourceRange(); + hadError = !SemaRef.getLangOptions().CPlusPlus0x; ++Index; ++StructuredIndex; return; diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp index 123dd4f637..84dc87ac3d 100644 --- a/test/SemaCXX/cxx98-compat.cpp +++ b/test/SemaCXX/cxx98-compat.cpp @@ -40,8 +40,8 @@ void Lambda() { int InitList() { (void)new int {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} (void)int{}; // expected-warning {{generalized initializer lists are incompatible with C++98}} - int x {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} - return {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} + int x { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}} + return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}} } int operator""_hello(const char *); // expected-warning {{literal operators are incompatible with C++98}} @@ -160,3 +160,13 @@ void TrivialButNonPODThroughEllipsis() { struct HasExplicitConversion { explicit operator bool(); // expected-warning {{explicit conversion functions are incompatible with C++98}} }; + +struct Struct {}; +enum Enum { enum_val = 0 }; +struct BadFriends { + friend enum ::Enum; // expected-warning {{befriending enumeration type 'enum ::Enum' is incompatible with C++98}} + friend int; // expected-warning {{non-class friend type 'int' is incompatible with C++98}} + friend Struct; // expected-warning {{befriending 'Struct' without 'struct' keyword is incompatible with C++98}} +}; + +int n = {}; // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} -- 2.40.0