-Wc++98-compat and -Wc++98-compat-pedantic warnings for Sema, part 2.

llvm-svn: 142426
This commit is contained in:
Richard Smith 2011-10-18 21:39:00 +00:00
parent c1939d3967
commit c82397332d
5 changed files with 69 additions and 39 deletions

View File

@ -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<CXX98Compat>, DefaultIgnore;
def ext_nonclass_type_friend : ExtWarn<
"non-class friend type %0 is a C++11 extension">, InGroup<CXX11>;
def warn_cxx98_compat_nonclass_type_friend : Warning<
"non-class friend type %0 is incompatible with C++98">,
InGroup<CXX98Compat>, 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<CXX11>;
def warn_cxx98_compat_unelaborated_friend_type : Warning<
"befriending %1 without '%select{struct|union|class|enum}0' keyword is "
"incompatible with C++98">, InGroup<CXX98Compat>, 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<DiagGroup<"complex-component-init">>;
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<CXX98Compat>, DefaultIgnore;
def err_illegal_initializer : Error<
"illegal initializer (only variables can be initialized)">;
def err_illegal_initializer_type : Error<"illegal initializer type %0">;

View File

@ -268,7 +268,7 @@ bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) {
if (!isa<TypeDecl>(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<TypeDecl>(SD));
if (T->isDependentType())

View File

@ -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<RecordType>()) {
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<EnumType>()) {
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<RecordType>()) {
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<EnumType>()) {
Diag(FriendLoc,
getLangOptions().CPlusPlus0x ?
diag::warn_cxx98_compat_enum_friend :
diag::ext_enum_friend)
<< T
<< SourceRange(FriendLoc, TypeRange.getEnd());
}
// C++0x [class.friend]p3:

View File

@ -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;

View File

@ -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}}