[cfe-commits] r142056 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td lib/Parse/ParseCXXInlineMethods.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseExpr.cpp lib/Parse/ParseExprCXX.cpp lib/Parse/ParseStmt.cpp lib/Parse/ParseTemplate.cpp lib/Parse/Parser.cpp test/SemaCXX/cxx98-compat-pedantic.cpp test/SemaCXX/cxx98-compat.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Fri Oct 14 22:09:34 PDT 2011
Author: rsmith
Date: Sat Oct 15 00:09:34 2011
New Revision: 142056
URL: http://llvm.org/viewvc/llvm-project?rev=142056&view=rev
Log:
Implement -Wc++98-compat warnings for the parser.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/test/SemaCXX/cxx98-compat-pedantic.cpp
cfe/trunk/test/SemaCXX/cxx98-compat.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=142056&r1=142055&r2=142056&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Sat Oct 15 00:09:34 2011
@@ -23,6 +23,9 @@
def ext_empty_source_file : Extension<"ISO C forbids an empty source file">;
def ext_top_level_semi : Extension<
"extra ';' outside of a function">;
+def warn_cxx98_compat_top_level_semi : Warning<
+ "extra ';' outside of a function is incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
def ext_extra_struct_semi : Extension<
"extra ';' inside a %0">;
def ext_extra_ivar_semi : Extension<
@@ -55,6 +58,9 @@
def ext_enumerator_list_comma : Extension<
"commas at the end of enumerator lists are a %select{C99|C++11}0-specific "
"feature">;
+def warn_cxx98_compat_enumerator_list_comma : Warning<
+ "commas at the end of enumerator lists are incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
def err_enumerator_list_missing_comma : Error<
"missing ',' between enumerators">;
def err_enumerator_unnamed_no_def : Error<
@@ -62,6 +68,9 @@
def ext_ms_enum_fixed_underlying_type : Extension<
"enumeration types with a fixed underlying type are a Microsoft extension">,
InGroup<Microsoft>;
+def warn_cxx98_compat_enum_fixed_underlying_type : Warning<
+ "enumeration types with a fixed underlying type are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def ext_c1x_generic_selection : Extension<
"generic selections are a C1X-specific feature">, InGroup<C1X>;
@@ -188,15 +197,30 @@
"%0 declared as a reference to a reference">;
def ext_rvalue_reference : ExtWarn<
"rvalue references are a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_rvalue_reference : Warning<
+ "rvalue references are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def ext_ref_qualifier : ExtWarn<
"reference qualifiers on functions are a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_ref_qualifier : Warning<
+ "reference qualifiers on functions are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def ext_inline_namespace : ExtWarn<
"inline namespaces are a C++11 feature">, InGroup<CXX11>;
+def warn_cxx98_compat_inline_namespace : Warning<
+ "inline namespaces are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def err_generalized_initializer_lists : Error<
"generalized initializer lists are a C++11 extension unsupported in Clang">;
def ext_generalized_initializer_lists : ExtWarn<
"generalized initializer lists are a C++11 extension unsupported in Clang">,
InGroup<CXX11>;
+def warn_cxx98_compat_generalized_initializer_lists : Warning<
+ "generalized initializer lists are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_trailing_return_type : Warning<
+ "trailing return types are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def ext_auto_type_specifier : ExtWarn<
"'auto' type specifier is a C++11 extension">, InGroup<CXX11>;
def warn_auto_storage_class : Warning<
@@ -207,6 +231,9 @@
"be supported in future releases">;
def ext_for_range : ExtWarn<
"range-based for loop is a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_for_range : Warning<
+ "range-based for loop is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def err_argument_required_after_attribute : Error<
"argument required after attribute">;
def err_missing_param : Error<"expected parameter declarator">;
@@ -363,6 +390,9 @@
// C++ operator overloading
def err_operator_string_not_empty : Error<
"string literal after 'operator' must be '\"\"'">;
+def warn_cxx98_compat_literal_operator : Warning<
+ "literal operators are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
// Classes.
def err_anon_type_definition : Error<
@@ -405,6 +435,9 @@
def warn_cxx0x_right_shift_in_template_arg : Warning<
"use of right-shift operator ('>>') in template argument will require "
"parentheses in C++11">;
+def warn_cxx98_compat_two_right_angle_brackets : Warning<
+ "consecutive right angle brackets are incompatible with C++98 (use '> >')">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def err_multiple_template_declarators : Error<
"%select{|a template declaration|an explicit template specialization|"
"an explicit template instantiation}0 can "
@@ -466,14 +499,23 @@
def warn_deleted_function_accepted_as_extension: ExtWarn<
"deleted function definition accepted as a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_deleted_function : Warning<
+ "deleted function definitions are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def warn_defaulted_function_accepted_as_extension: ExtWarn<
"defaulted function definition accepted as a C++11 extension">,
InGroup<CXX11>;
+def warn_cxx98_compat_defaulted_function : Warning<
+ "defaulted function definitions are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
// C++11 in-class member initialization
def ext_nonstatic_member_init : ExtWarn<
"in-class initialization of non-static data member accepted as a C++11 extension">,
InGroup<CXX11>;
+def warn_cxx98_compat_nonstatic_member_init : Warning<
+ "in-class initialization of non-static data members is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def err_bitfield_member_init: Error<
"bitfield member cannot have an in-class initializer">;
def err_incomplete_array_member_init: Error<
@@ -482,6 +524,9 @@
// C++11 alias-declaration
def ext_alias_declaration : ExtWarn<
"alias declarations accepted as a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_alias_declaration : Warning<
+ "alias declarations are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def err_alias_declaration_not_identifier : Error<
"name defined in alias declaration must be an identifier">;
def err_alias_declaration_specialization : Error<
@@ -490,6 +535,9 @@
// C++11 override control
def ext_override_control_keyword : ExtWarn<
"'%0' keyword accepted as a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_override_control_keyword : Warning<
+ "'%0' keyword is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def err_duplicate_virt_specifier : Error<
"class member already marked '%0'">;
@@ -498,6 +546,9 @@
def err_scoped_enum_missing_identifier : Error<
"scoped enumeration requires a name">;
+def warn_cxx98_compat_scoped_enum : Warning<
+ "scoped enumerations are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
def err_expected_parameter_pack : Error<
"expected the name of a parameter pack">;
@@ -514,6 +565,9 @@
def err_expected_capture : Error<
"expected variable name or 'this' in lambda capture list">;
def err_expected_lambda_body : Error<"expected body of lambda expression">;
+def warn_cxx98_compat_lambda : Warning<
+ "lambda expressions are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
// Availability attribute
def err_expected_version : Error<
Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=142056&r1=142055&r2=142056&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Sat Oct 15 00:09:34 2011
@@ -67,15 +67,17 @@
bool Delete = false;
SourceLocation KWLoc;
if (Tok.is(tok::kw_delete)) {
- if (!getLang().CPlusPlus0x)
- Diag(Tok, diag::warn_deleted_function_accepted_as_extension);
+ Diag(Tok, getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_deleted_function :
+ diag::warn_deleted_function_accepted_as_extension);
KWLoc = ConsumeToken();
Actions.SetDeclDeleted(FnD, KWLoc);
Delete = true;
} else if (Tok.is(tok::kw_default)) {
- if (!getLang().CPlusPlus0x)
- Diag(Tok, diag::warn_defaulted_function_accepted_as_extension);
+ Diag(Tok, getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_defaulted_function :
+ diag::warn_defaulted_function_accepted_as_extension);
KWLoc = ConsumeToken();
Actions.SetDeclDefaulted(FnD, KWLoc);
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=142056&r1=142055&r2=142056&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Oct 15 00:09:34 2011
@@ -1276,6 +1276,8 @@
}
} else if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) {
// Parse C++0x braced-init-list.
+ Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
+
if (D.getCXXScopeSpec().isSet()) {
EnterScope(0);
Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
@@ -2778,6 +2780,7 @@
if (getLang().CPlusPlus0x &&
(Tok.is(tok::kw_class) || Tok.is(tok::kw_struct))) {
+ Diag(Tok, diag::warn_cxx98_compat_scoped_enum);
IsScopedEnum = true;
IsScopedUsingClassTag = Tok.is(tok::kw_class);
ConsumeToken();
@@ -2894,6 +2897,8 @@
if (!getLang().CPlusPlus0x && !getLang().ObjC2)
Diag(StartLoc, diag::ext_ms_enum_fixed_underlying_type)
<< Range;
+ if (getLang().CPlusPlus0x)
+ Diag(StartLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type);
}
}
@@ -3054,11 +3059,15 @@
break;
SourceLocation CommaLoc = ConsumeToken();
- if (Tok.isNot(tok::identifier) &&
- !(getLang().C99 || getLang().CPlusPlus0x))
- Diag(CommaLoc, diag::ext_enumerator_list_comma)
- << getLang().CPlusPlus
- << FixItHint::CreateRemoval(CommaLoc);
+ if (Tok.isNot(tok::identifier)) {
+ if (!getLang().C99 && !getLang().CPlusPlus0x)
+ Diag(CommaLoc, diag::ext_enumerator_list_comma)
+ << getLang().CPlusPlus
+ << FixItHint::CreateRemoval(CommaLoc);
+ else if (getLang().CPlusPlus0x)
+ Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma)
+ << FixItHint::CreateRemoval(CommaLoc);
+ }
}
// Eat the }.
@@ -3682,8 +3691,10 @@
// Complain about rvalue references in C++03, but then go on and build
// the declarator.
- if (Kind == tok::ampamp && !getLang().CPlusPlus0x)
- Diag(Loc, diag::ext_rvalue_reference);
+ if (Kind == tok::ampamp)
+ Diag(Loc, getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_rvalue_reference :
+ diag::ext_rvalue_reference);
// C++ 8.3.2p1: cv-qualified references are ill-formed except when the
// cv-qualifiers are introduced through the use of a typedef or of a
@@ -4080,8 +4091,9 @@
// Parse ref-qualifier[opt].
if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) {
- if (!getLang().CPlusPlus0x)
- Diag(Tok, diag::ext_ref_qualifier);
+ Diag(Tok, getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_ref_qualifier :
+ diag::ext_ref_qualifier);
RefQualifierIsLValueRef = Tok.is(tok::amp);
RefQualifierLoc = ConsumeToken();
@@ -4098,6 +4110,7 @@
// Parse trailing-return-type[opt].
if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) {
+ Diag(Tok, diag::warn_cxx98_compat_trailing_return_type);
SourceRange Range;
TrailingReturnType = ParseTrailingReturnType(Range).get();
if (Range.getEnd().isValid())
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=142056&r1=142055&r2=142056&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sat Oct 15 00:09:34 2011
@@ -148,8 +148,9 @@
}
// If we're still good, complain about inline namespaces in non-C++0x now.
- if (!getLang().CPlusPlus0x && InlineLoc.isValid())
- Diag(InlineLoc, diag::ext_inline_namespace);
+ if (InlineLoc.isValid())
+ Diag(InlineLoc, getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_inline_namespace : diag::ext_inline_namespace);
// Enter a scope for the namespace.
ParseScope NamespaceScope(this, Scope::DeclScope);
@@ -481,8 +482,9 @@
// Where can GNU attributes appear?
ConsumeToken();
- if (!getLang().CPlusPlus0x)
- Diag(Tok.getLocation(), diag::ext_alias_declaration);
+ Diag(Tok.getLocation(), getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_alias_declaration :
+ diag::ext_alias_declaration);
// Type alias templates cannot be specialized.
int SpecKind = -1;
@@ -1516,9 +1518,10 @@
<< PrevSpec
<< FixItHint::CreateRemoval(Tok.getLocation());
- if (!getLang().CPlusPlus0x)
- Diag(Tok.getLocation(), diag::ext_override_control_keyword)
- << VirtSpecifiers::getSpecifierName(Specifier);
+ Diag(Tok.getLocation(), getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_override_control_keyword :
+ diag::ext_override_control_keyword)
+ << VirtSpecifiers::getSpecifierName(Specifier);
ConsumeToken();
}
}
@@ -1884,9 +1887,10 @@
// Handle the initializer.
if (HasDeferredInitializer) {
// The initializer was deferred; parse it and cache the tokens.
- if (!getLang().CPlusPlus0x)
- Diag(Tok, diag::ext_nonstatic_member_init);
-
+ Diag(Tok, getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_nonstatic_member_init :
+ diag::ext_nonstatic_member_init);
+
if (DeclaratorInfo.isArrayOfUnknownBound()) {
// C++0x [dcl.array]p3: An array bound may also be omitted when the
// declarator is followed by an initializer.
@@ -2075,8 +2079,9 @@
assert(isCXX0XFinalKeyword() && "not a class definition");
FinalLoc = ConsumeToken();
- if (!getLang().CPlusPlus0x)
- Diag(FinalLoc, diag::ext_override_control_keyword) << "final";
+ Diag(FinalLoc, getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_override_control_keyword :
+ diag::ext_override_control_keyword) << "final";
}
if (Tok.is(tok::colon)) {
@@ -2318,6 +2323,8 @@
// Parse the '('.
if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) {
+ Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
+
ExprResult InitList = ParseBraceInitializer();
if (InitList.isInvalid())
return true;
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=142056&r1=142055&r2=142056&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Sat Oct 15 00:09:34 2011
@@ -949,6 +949,9 @@
return ExprError(Diag(Tok, diag::err_expected_lparen_after_type)
<< DS.getSourceRange());
+ if (Tok.is(tok::l_brace))
+ Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
+
Res = ParseCXXTypeConstructExpression(DS);
break;
}
@@ -1207,9 +1210,10 @@
T.consumeOpen();
Loc = T.getOpenLocation();
ExprResult Idx;
- if (getLang().CPlusPlus0x && Tok.is(tok::l_brace))
+ if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) {
+ Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
Idx = ParseBraceInitializer();
- else
+ } else
Idx = ParseExpression();
SourceLocation RLoc = Tok.getLocation();
@@ -2157,9 +2161,10 @@
}
ExprResult Expr;
- if (getLang().CPlusPlus0x && Tok.is(tok::l_brace))
+ if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) {
+ Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
Expr = ParseBraceInitializer();
- else
+ } else
Expr = ParseAssignmentExpression();
if (Tok.is(tok::ellipsis))
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=142056&r1=142055&r2=142056&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Sat Oct 15 00:09:34 2011
@@ -679,6 +679,8 @@
/// expression.
ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
LambdaIntroducer &Intro) {
+ Diag(Intro.Range.getBegin(), diag::warn_cxx98_compat_lambda);
+
// Parse lambda-declarator[opt].
DeclSpec DS(AttrFactory);
Declarator D(DS, Declarator::PrototypeContext);
@@ -1743,6 +1745,7 @@
// operator "" identifier
if (getLang().CPlusPlus0x && Tok.is(tok::string_literal)) {
+ Diag(Tok.getLocation(), diag::warn_cxx98_compat_literal_operator);
if (Tok.getLength() != 2)
Diag(Tok.getLocation(), diag::err_operator_string_not_empty);
ConsumeStringToken();
@@ -2104,6 +2107,8 @@
return ExprError();
}
} else if (Tok.is(tok::l_brace) && getLang().CPlusPlus0x) {
+ Diag(Tok.getLocation(),
+ diag::warn_cxx98_compat_generalized_initializer_lists);
// FIXME: Have to communicate the init-list to ActOnCXXNew.
ParseBraceInitializer();
}
Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=142056&r1=142055&r2=142056&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Sat Oct 15 00:09:34 2011
@@ -1326,8 +1326,8 @@
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
if (ForRangeInit.ParsedForRangeDecl()) {
- if (!getLang().CPlusPlus0x)
- Diag(ForRangeInit.ColonLoc, diag::ext_for_range);
+ Diag(ForRangeInit.ColonLoc, getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_for_range : diag::ext_for_range);
ForRange = true;
} else if (Tok.is(tok::semi)) { // for (int x = 4;
@@ -1569,8 +1569,10 @@
// parse libstdc++ 4.5's headers.
if (Tok.is(tok::l_brace) && getLang().CPlusPlus) {
R = ParseInitializer();
- if (R.isUsable() && !getLang().CPlusPlus0x)
- Diag(R.get()->getLocStart(), diag::ext_generalized_initializer_lists)
+ if (R.isUsable())
+ Diag(R.get()->getLocStart(), getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_generalized_initializer_lists :
+ diag::ext_generalized_initializer_lists)
<< R.get()->getSourceRange();
} else
R = ParseExpression();
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=142056&r1=142055&r2=142056&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Sat Oct 15 00:09:34 2011
@@ -709,15 +709,15 @@
RAngleLoc = Tok.getLocation();
if (Tok.is(tok::greatergreater)) {
- if (!getLang().CPlusPlus0x) {
- const char *ReplaceStr = "> >";
- if (NextToken().is(tok::greater) || NextToken().is(tok::greatergreater))
- ReplaceStr = "> > ";
-
- Diag(Tok.getLocation(), diag::err_two_right_angle_brackets_need_space)
- << FixItHint::CreateReplacement(
- SourceRange(Tok.getLocation()), ReplaceStr);
- }
+ const char *ReplaceStr = "> >";
+ if (NextToken().is(tok::greater) || NextToken().is(tok::greatergreater))
+ ReplaceStr = "> > ";
+
+ Diag(Tok.getLocation(), getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_two_right_angle_brackets :
+ diag::err_two_right_angle_brackets_need_space)
+ << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()),
+ ReplaceStr);
Tok.setKind(tok::greater);
if (!ConsumeLastToken) {
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=142056&r1=142055&r2=142056&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Sat Oct 15 00:09:34 2011
@@ -535,9 +535,9 @@
Decl *SingleDecl = 0;
switch (Tok.getKind()) {
case tok::semi:
- if (!getLang().CPlusPlus0x)
- Diag(Tok, diag::ext_top_level_semi)
- << FixItHint::CreateRemoval(Tok.getLocation());
+ Diag(Tok, getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_top_level_semi : diag::ext_top_level_semi)
+ << FixItHint::CreateRemoval(Tok.getLocation());
ConsumeToken();
// TODO: Invoke action for top-level semicolon.
@@ -918,15 +918,17 @@
bool Delete = false;
SourceLocation KWLoc;
if (Tok.is(tok::kw_delete)) {
- if (!getLang().CPlusPlus0x)
- Diag(Tok, diag::warn_deleted_function_accepted_as_extension);
+ Diag(Tok, getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_deleted_function :
+ diag::warn_deleted_function_accepted_as_extension);
KWLoc = ConsumeToken();
Actions.SetDeclDeleted(Res, KWLoc);
Delete = true;
} else if (Tok.is(tok::kw_default)) {
- if (!getLang().CPlusPlus0x)
- Diag(Tok, diag::warn_defaulted_function_accepted_as_extension);
+ Diag(Tok, getLang().CPlusPlus0x ?
+ diag::warn_cxx98_compat_defaulted_function :
+ diag::warn_defaulted_function_accepted_as_extension);
KWLoc = ConsumeToken();
Actions.SetDeclDefaulted(Res, KWLoc);
Modified: cfe/trunk/test/SemaCXX/cxx98-compat-pedantic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat-pedantic.cpp?rev=142056&r1=142055&r2=142056&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx98-compat-pedantic.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx98-compat-pedantic.cpp Sat Oct 15 00:09:34 2011
@@ -1,4 +1,5 @@
// 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
// -Wc++98-compat-pedantic warns on C++11 features which we accept without a
@@ -9,3 +10,9 @@
#define VA_MACRO(x, ...) x // expected-warning {{variadic macros are incompatible with C++98}}
VA_MACRO(,x) // expected-warning {{empty macro argument list is incompatible with C++98}}
+
+; // expected-warning {{extra ';' outside of a function is incompatible with C++98}}
+
+enum Enum {
+ Enum_value, // expected-warning {{commas at the end of enumerator lists are incompatible with C++98}}
+};
Modified: cfe/trunk/test/SemaCXX/cxx98-compat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat.cpp?rev=142056&r1=142055&r2=142056&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx98-compat.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx98-compat.cpp Sat Oct 15 00:09:34 2011
@@ -27,4 +27,63 @@
}
template<typename T> struct S {};
-S<::S<void> > s; // expected-warning {{'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98}}
+namespace TemplateParsing {
+ S<::S<void> > s; // expected-warning {{'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98}}
+ S< ::S<void>> t; // expected-warning {{consecutive right angle brackets are incompatible with C++98 (use '> >')}}
+}
+
+void Lambda() {
+ []{}; // expected-warning {{lambda expressions are incompatible with C++98}}
+}
+
+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 operator""_hello(const char *); // expected-warning {{literal operators are incompatible with C++98}}
+
+enum EnumFixed : int { // expected-warning {{enumeration types with a fixed underlying type are incompatible with C++98}}
+};
+
+enum class EnumScoped { // expected-warning {{scoped enumerations are incompatible with C++98}}
+};
+
+void Deleted() = delete; // expected-warning {{deleted function definitions are incompatible with C++98}}
+struct Defaulted {
+ Defaulted() = default; // expected-warning {{defaulted function definitions are incompatible with C++98}}
+};
+
+int &&RvalueReference = 0; // expected-warning {{rvalue references are incompatible with C++98}}
+struct RefQualifier {
+ void f() &; // expected-warning {{reference qualifiers on functions are incompatible with C++98}}
+};
+
+auto f() -> int; // expected-warning {{trailing return types are incompatible with C++98}}
+
+void RangeFor() {
+ int xs[] = {1, 2, 3};
+ for (int &a : xs) { // expected-warning {{range-based for loop is incompatible with C++98}}
+ }
+}
+
+struct InClassInit {
+ int n = 0; // expected-warning {{in-class initialization of non-static data members is incompatible with C++98}}
+};
+
+struct OverrideControlBase {
+ virtual void f();
+ virtual void g();
+};
+struct OverrideControl final : OverrideControlBase { // expected-warning {{'final' keyword is incompatible with C++98}}
+ virtual void f() override; // expected-warning {{'override' keyword is incompatible with C++98}}
+ virtual void g() final; // expected-warning {{'final' keyword is incompatible with C++98}}
+};
+
+using AliasDecl = int; // expected-warning {{alias declarations are incompatible with C++98}}
+template<typename T> using AliasTemplate = T; // expected-warning {{alias declarations are incompatible with C++98}}
+
+inline namespace N { // expected-warning {{inline namespaces are incompatible with C++98}}
+}
More information about the cfe-commits
mailing list