mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-14 15:46:32 +00:00
Reapply "[Clang] [NFC] Introduce a helper for emitting compatibility diagnostics (#132348)" (#134043)
This reapplies #132348 with a fix to the python bindings tests, reverting
076397ff32
.
This commit is contained in:
parent
41d718b1cf
commit
10c6ebc427
@ -79,7 +79,7 @@ class TestDiagnostics(unittest.TestCase):
|
||||
self.assertEqual(d.location.line, 1)
|
||||
self.assertEqual(d.location.column, 11)
|
||||
|
||||
self.assertEqual(d.category_number, 2)
|
||||
self.assertEqual(d.category_number, 3)
|
||||
self.assertEqual(d.category_name, "Semantic Issue")
|
||||
|
||||
def test_diagnostic_option(self):
|
||||
@ -123,7 +123,7 @@ class TestDiagnostics(unittest.TestCase):
|
||||
self.assertEqual(str(d), "t.c:1:26: error: expected ';' after struct")
|
||||
self.assertEqual(
|
||||
d.format(0b111111),
|
||||
"t.c:1:26: error: expected ';' after struct [3, Parse Issue]",
|
||||
"t.c:1:26: error: expected ';' after struct [2, Parse Issue]",
|
||||
)
|
||||
with self.assertRaises(ValueError):
|
||||
d.format(0b1000000)
|
||||
|
@ -8,6 +8,11 @@ macro(clang_diag_gen component)
|
||||
-gen-clang-diags-enums -clang-component=${component}
|
||||
SOURCE Diagnostic.td
|
||||
TARGET ClangDiagnostic${component}Enums)
|
||||
|
||||
clang_tablegen(Diagnostic${component}CompatIDs.inc
|
||||
-gen-clang-diags-compat-ids -clang-component=${component}
|
||||
SOURCE Diagnostic.td
|
||||
TARGET ClangDiagnostic${component}CompatIDs)
|
||||
endmacro(clang_diag_gen)
|
||||
|
||||
clang_diag_gen(Analysis)
|
||||
@ -31,6 +36,11 @@ clang_tablegen(DiagnosticIndexName.inc -gen-clang-diags-index-name
|
||||
SOURCE Diagnostic.td
|
||||
TARGET ClangDiagnosticIndexName)
|
||||
|
||||
clang_tablegen(DiagnosticAllCompatIDs.inc
|
||||
-gen-clang-diags-compat-ids
|
||||
SOURCE Diagnostic.td
|
||||
TARGET ClangDiagnosticAllCompatIDs)
|
||||
|
||||
clang_tablegen(AttrList.inc -gen-clang-attr-list
|
||||
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
|
||||
SOURCE Attr.td
|
||||
|
@ -155,6 +155,19 @@ class DefaultWarnNoWerror {
|
||||
}
|
||||
class DefaultRemark { Severity DefaultSeverity = SEV_Remark; }
|
||||
|
||||
class CompatWarningId<string name, int std, string diag, string diag_pre> {
|
||||
string Component = ?;
|
||||
string Name = name;
|
||||
string Diag = diag;
|
||||
string DiagPre = diag_pre;
|
||||
int Std = std;
|
||||
|
||||
// This is unused, but Tablegen will complain if it's missing because we define
|
||||
// the compatibility ids in the same place as the other diagnostics (which means
|
||||
// that we'll be inside a 'let CategoryName = "" in { ... }' block).
|
||||
string CategoryName = ?;
|
||||
}
|
||||
|
||||
// C++ compatibility warnings.
|
||||
multiclass CXXCompat<
|
||||
string message,
|
||||
@ -178,6 +191,11 @@ multiclass CXXCompat<
|
||||
"CXX98Compat",
|
||||
"CXXPre"#std_ver#"Compat"))>,
|
||||
DefaultIgnore;
|
||||
|
||||
def : CompatWarningId<
|
||||
NAME, std_ver,
|
||||
"compat_cxx"#std_ver#"_"#NAME,
|
||||
"compat_pre_cxx"#std_ver#"_"#NAME>;
|
||||
}
|
||||
|
||||
// These generate pairs of C++ compatibility warnings of the form:
|
||||
|
@ -36,6 +36,18 @@ enum {
|
||||
#undef DIAG_ENUM_ITEM
|
||||
#undef DIAG_ENUM
|
||||
} // end namespace diag
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticASTCompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_DIAGNOSTICAST_H
|
||||
|
@ -35,6 +35,18 @@ enum {
|
||||
#undef DIAG_ENUM_ITEM
|
||||
#undef DIAG_ENUM
|
||||
} // end namespace diag
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticAnalysisCompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_DIAGNOSTICANALYSIS_H
|
||||
|
@ -36,6 +36,18 @@ enum {
|
||||
#undef DIAG_ENUM_ITEM
|
||||
#undef DIAG_ENUM
|
||||
} // end namespace diag
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticCommentCompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_DIAGNOSTICCOMMENT_H
|
||||
|
@ -36,6 +36,18 @@ enum {
|
||||
#undef DIAG_ENUM_ITEM
|
||||
#undef DIAG_ENUM
|
||||
} // end namespace diag
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticCrossTUCompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_DIAGNOSTICCROSSTU_H
|
||||
|
@ -36,6 +36,18 @@ enum {
|
||||
#undef DIAG_ENUM_ITEM
|
||||
#undef DIAG_ENUM
|
||||
} // end namespace diag
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticDriverCompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_DIAGNOSTICDRIVER_H
|
||||
|
@ -36,6 +36,18 @@ enum {
|
||||
#undef DIAG_ENUM_ITEM
|
||||
#undef DIAG_ENUM
|
||||
} // end namespace diag
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticFrontendCompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_DIAGNOSTICFRONTEND_H
|
||||
|
@ -25,6 +25,7 @@
|
||||
namespace clang {
|
||||
class DiagnosticsEngine;
|
||||
class DiagnosticBuilder;
|
||||
class LangOptions;
|
||||
class SourceLocation;
|
||||
|
||||
// Import the diagnostic enums themselves.
|
||||
@ -104,6 +105,18 @@ namespace clang {
|
||||
};
|
||||
}
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticCommonCompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
|
||||
class DiagnosticMapping {
|
||||
LLVM_PREFERRED_TYPE(diag::Severity)
|
||||
unsigned Severity : 3;
|
||||
@ -464,6 +477,11 @@ public:
|
||||
/// given group name.
|
||||
static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group);
|
||||
|
||||
/// Get the appropriate diagnostic Id to use for issuing a compatibility
|
||||
/// diagnostic. For use by the various DiagCompat() helpers.
|
||||
static unsigned getCXXCompatDiagId(const LangOptions &LangOpts,
|
||||
unsigned CompatDiagId);
|
||||
|
||||
private:
|
||||
/// Classify the specified diagnostic ID into a Level, consumable by
|
||||
/// the DiagnosticClient.
|
||||
|
@ -35,5 +35,17 @@ enum {
|
||||
#undef DIAG_ENUM_ITEM
|
||||
#undef DIAG_ENUM
|
||||
} // namespace diag
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticInstallAPICompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
} // namespace clang
|
||||
#endif // LLVM_CLANG_BASIC_DIAGNOSTICINSTALLAPI_H
|
||||
|
@ -35,6 +35,18 @@ enum {
|
||||
#undef DIAG_ENUM_ITEM
|
||||
#undef DIAG_ENUM
|
||||
} // end namespace diag
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticLexCompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_DIAGNOSTICLEX_H
|
||||
|
@ -36,6 +36,18 @@ enum {
|
||||
#undef DIAG_ENUM_ITEM
|
||||
#undef DIAG_ENUM
|
||||
} // end namespace diag
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticParseCompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_DIAGNOSTICPARSE_H
|
||||
|
@ -11,6 +11,12 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let Component = "Parse" in {
|
||||
let CategoryName = "Parse Issue" in {
|
||||
// C++11 compatibility with C++98.
|
||||
defm enum_fixed_underlying_type : CXX11Compat<
|
||||
"enumeration types with a fixed underlying type are",
|
||||
/*ext_warn=*/false>;
|
||||
}
|
||||
|
||||
def err_asm_qualifier_ignored : Error<
|
||||
"expected 'volatile', 'inline', 'goto', or '('">, CatInlineAsm;
|
||||
@ -107,9 +113,6 @@ def err_enumerator_list_missing_comma : Error<
|
||||
"missing ',' between enumerators">;
|
||||
def err_enumerator_unnamed_no_def : Error<
|
||||
"unnamed enumeration must be a definition">;
|
||||
def ext_cxx11_enum_fixed_underlying_type : Extension<
|
||||
"enumeration types with a fixed underlying type are a C++11 extension">,
|
||||
InGroup<CXX11>;
|
||||
def ext_ms_c_enum_fixed_underlying_type : Extension<
|
||||
"enumeration types with a fixed underlying type are a Microsoft extension">,
|
||||
InGroup<MicrosoftFixedEnum>;
|
||||
@ -119,9 +122,6 @@ def ext_c23_enum_fixed_underlying_type : Extension<
|
||||
def warn_c17_compat_enum_fixed_underlying_type : Warning<
|
||||
"enumeration types with a fixed underlying type are incompatible with C standards before C23">,
|
||||
DefaultIgnore, InGroup<CPre23Compat>;
|
||||
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_enum_base_in_type_specifier : ExtWarn<
|
||||
"non-defining declaration of enumeration with a fixed underlying type is "
|
||||
"only permitted as a standalone declaration"
|
||||
|
@ -36,6 +36,18 @@ enum {
|
||||
#undef DIAG_ENUM_ITEM
|
||||
#undef DIAG_ENUM
|
||||
} // end namespace diag
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticRefactoringCompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_DIAGNOSTICREFACTORING_H
|
||||
|
@ -35,7 +35,20 @@ enum {
|
||||
#undef DIAG_ENUM_END
|
||||
#undef DIAG_ENUM_ITEM
|
||||
#undef DIAG_ENUM
|
||||
|
||||
} // end namespace diag
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticSemaCompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_DIAGNOSTICSEMA_H
|
||||
|
@ -61,7 +61,7 @@ defm decomp_decl_cond : CXX26Compat<"structured binding declaration in a conditi
|
||||
|
||||
// Compatibility warnings duplicated across multiple language versions.
|
||||
foreach std = [14, 20, 23] in {
|
||||
defm constexpr_body_invalid_stmt : CXXCompat<
|
||||
defm cxx#std#_constexpr_body_invalid_stmt : CXXCompat<
|
||||
"use of this statement in a constexpr %select{function|constructor}0 is", std>;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,18 @@ enum {
|
||||
#undef DIAG_ENUM_ITEM
|
||||
#undef DIAG_ENUM
|
||||
} // end namespace diag
|
||||
|
||||
namespace diag_compat {
|
||||
#define DIAG_COMPAT_IDS_BEGIN() enum {
|
||||
#define DIAG_COMPAT_IDS_END() \
|
||||
} \
|
||||
;
|
||||
#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX,
|
||||
#include "clang/Basic/DiagnosticSerializationCompatIDs.inc"
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
} // end namespace diag_compat
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_DIAGNOSTICSERIALIZATION_H
|
||||
|
@ -1263,6 +1263,12 @@ public:
|
||||
return Diag(Tok, DiagID);
|
||||
}
|
||||
|
||||
DiagnosticBuilder DiagCompat(SourceLocation Loc, unsigned CompatDiagId);
|
||||
DiagnosticBuilder DiagCompat(const Token &Tok, unsigned CompatDiagId);
|
||||
DiagnosticBuilder DiagCompat(unsigned CompatDiagId) {
|
||||
return DiagCompat(Tok, CompatDiagId);
|
||||
}
|
||||
|
||||
private:
|
||||
void SuggestParentheses(SourceLocation Loc, unsigned DK,
|
||||
SourceRange ParenRange);
|
||||
|
@ -219,6 +219,10 @@ public:
|
||||
SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD,
|
||||
bool DeferHint = false);
|
||||
|
||||
/// Emit a compatibility diagnostic.
|
||||
SemaDiagnosticBuilder DiagCompat(SourceLocation Loc, unsigned CompatDiagId,
|
||||
bool DeferHint = false);
|
||||
|
||||
/// Build a partial diagnostic.
|
||||
PartialDiagnostic PDiag(unsigned DiagID = 0);
|
||||
};
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "clang/Basic/DiagnosticIDs.h"
|
||||
#include "clang/Basic/AllDiagnostics.h"
|
||||
#include "clang/Basic/DiagnosticCategories.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
@ -769,6 +770,51 @@ StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
|
||||
return Best;
|
||||
}
|
||||
|
||||
unsigned DiagnosticIDs::getCXXCompatDiagId(const LangOptions &LangOpts,
|
||||
unsigned CompatDiagId) {
|
||||
struct CompatDiag {
|
||||
unsigned StdVer;
|
||||
unsigned DiagId;
|
||||
unsigned PreDiagId;
|
||||
};
|
||||
|
||||
// We encode the standard version such that C++98 < C++11 < C++14 etc. The
|
||||
// actual numbers don't really matter for this, but the definitions of the
|
||||
// compat diags in the Tablegen file use the standard version number (i.e.
|
||||
// 98, 11, 14, etc.), so we base the encoding here on that.
|
||||
#define DIAG_COMPAT_IDS_BEGIN()
|
||||
#define DIAG_COMPAT_IDS_END()
|
||||
#define DIAG_COMPAT_ID(Value, Name, Std, Diag, DiagPre) \
|
||||
{Std == 98 ? 1998 : 2000 + Std, diag::Diag, diag::DiagPre},
|
||||
static constexpr CompatDiag Diags[]{
|
||||
#include "clang/Basic/DiagnosticAllCompatIDs.inc"
|
||||
};
|
||||
#undef DIAG_COMPAT_ID
|
||||
#undef DIAG_COMPAT_IDS_BEGIN
|
||||
#undef DIAG_COMPAT_IDS_END
|
||||
|
||||
assert(CompatDiagId < std::size(Diags) && "Invalid compat diag id");
|
||||
|
||||
unsigned StdVer = [&] {
|
||||
if (LangOpts.CPlusPlus26)
|
||||
return 2026;
|
||||
if (LangOpts.CPlusPlus23)
|
||||
return 2023;
|
||||
if (LangOpts.CPlusPlus20)
|
||||
return 2020;
|
||||
if (LangOpts.CPlusPlus17)
|
||||
return 2017;
|
||||
if (LangOpts.CPlusPlus14)
|
||||
return 2014;
|
||||
if (LangOpts.CPlusPlus11)
|
||||
return 2011;
|
||||
return 1998;
|
||||
}();
|
||||
|
||||
const CompatDiag &D = Diags[CompatDiagId];
|
||||
return StdVer >= D.StdVer ? D.DiagId : D.PreDiagId;
|
||||
}
|
||||
|
||||
/// ProcessDiag - This is the method used to report a diagnostic that is
|
||||
/// finally fully formed.
|
||||
bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag,
|
||||
|
@ -5452,11 +5452,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
|
||||
BaseRange = SourceRange(ColonLoc, DeclaratorInfo.getSourceRange().getEnd());
|
||||
|
||||
if (!getLangOpts().ObjC) {
|
||||
if (getLangOpts().CPlusPlus11)
|
||||
Diag(ColonLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type)
|
||||
<< BaseRange;
|
||||
else if (getLangOpts().CPlusPlus)
|
||||
Diag(ColonLoc, diag::ext_cxx11_enum_fixed_underlying_type)
|
||||
if (getLangOpts().CPlusPlus)
|
||||
DiagCompat(ColonLoc, diag_compat::enum_fixed_underlying_type)
|
||||
<< BaseRange;
|
||||
else if (getLangOpts().MicrosoftExt && !getLangOpts().C23)
|
||||
Diag(ColonLoc, diag::ext_ms_c_enum_fixed_underlying_type)
|
||||
|
@ -89,6 +89,16 @@ DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) {
|
||||
return Diag(Tok.getLocation(), DiagID);
|
||||
}
|
||||
|
||||
DiagnosticBuilder Parser::DiagCompat(SourceLocation Loc,
|
||||
unsigned CompatDiagId) {
|
||||
return Diag(Loc,
|
||||
DiagnosticIDs::getCXXCompatDiagId(getLangOpts(), CompatDiagId));
|
||||
}
|
||||
|
||||
DiagnosticBuilder Parser::DiagCompat(const Token &Tok, unsigned CompatDiagId) {
|
||||
return DiagCompat(Tok.getLocation(), CompatDiagId);
|
||||
}
|
||||
|
||||
/// Emits a diagnostic suggesting parentheses surrounding a
|
||||
/// given range.
|
||||
///
|
||||
|
@ -88,4 +88,11 @@ Sema::SemaDiagnosticBuilder SemaBase::Diag(SourceLocation Loc,
|
||||
return Diag(Loc, PD.getDiagID(), DeferHint) << PD;
|
||||
}
|
||||
|
||||
SemaBase::SemaDiagnosticBuilder SemaBase::DiagCompat(SourceLocation Loc,
|
||||
unsigned CompatDiagId,
|
||||
bool DeferHint) {
|
||||
return Diag(Loc,
|
||||
DiagnosticIDs::getCXXCompatDiagId(getLangOpts(), CompatDiagId),
|
||||
DeferHint);
|
||||
}
|
||||
} // namespace clang
|
||||
|
@ -7649,10 +7649,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
||||
IsVariableTemplate = true;
|
||||
|
||||
// Only C++1y supports variable templates (N3651).
|
||||
Diag(D.getIdentifierLoc(),
|
||||
getLangOpts().CPlusPlus14
|
||||
? diag::compat_cxx14_variable_template
|
||||
: diag::compat_pre_cxx14_variable_template);
|
||||
DiagCompat(D.getIdentifierLoc(), diag_compat::variable_template);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -7718,10 +7715,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
||||
} else if (RD->isUnion()) {
|
||||
// C++98 [class.union]p1: If a union contains a static data member,
|
||||
// the program is ill-formed. C++11 drops this restriction.
|
||||
Diag(D.getIdentifierLoc(),
|
||||
getLangOpts().CPlusPlus11
|
||||
? diag::compat_cxx11_static_data_member_in_union
|
||||
: diag::compat_pre_cxx11_static_data_member_in_union)
|
||||
DiagCompat(D.getIdentifierLoc(),
|
||||
diag_compat::static_data_member_in_union)
|
||||
<< Name;
|
||||
}
|
||||
}
|
||||
|
@ -807,10 +807,8 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
|
||||
for (auto Loc : BadSpecifierLocs)
|
||||
Err << SourceRange(Loc, Loc);
|
||||
} else if (!CPlusPlus20Specifiers.empty()) {
|
||||
auto &&Warn = Diag(CPlusPlus20SpecifierLocs.front(),
|
||||
getLangOpts().CPlusPlus20
|
||||
? diag::compat_cxx20_decomp_decl_spec
|
||||
: diag::compat_pre_cxx20_decomp_decl_spec);
|
||||
auto &&Warn = DiagCompat(CPlusPlus20SpecifierLocs.front(),
|
||||
diag_compat::decomp_decl_spec);
|
||||
Warn << (int)CPlusPlus20Specifiers.size()
|
||||
<< llvm::join(CPlusPlus20Specifiers.begin(),
|
||||
CPlusPlus20Specifiers.end(), " ");
|
||||
@ -2040,10 +2038,8 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
|
||||
// C++1y allows types to be defined, not just declared.
|
||||
if (cast<TagDecl>(DclIt)->isThisDeclarationADefinition()) {
|
||||
if (Kind == Sema::CheckConstexprKind::Diagnose) {
|
||||
SemaRef.Diag(DS->getBeginLoc(),
|
||||
SemaRef.getLangOpts().CPlusPlus14
|
||||
? diag::compat_cxx14_constexpr_type_definition
|
||||
: diag::compat_pre_cxx14_constexpr_type_definition)
|
||||
SemaRef.DiagCompat(DS->getBeginLoc(),
|
||||
diag_compat::constexpr_type_definition)
|
||||
<< isa<CXXConstructorDecl>(Dcl);
|
||||
} else if (!SemaRef.getLangOpts().CPlusPlus14) {
|
||||
return false;
|
||||
@ -2068,10 +2064,8 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
|
||||
if (VD->isThisDeclarationADefinition()) {
|
||||
if (VD->isStaticLocal()) {
|
||||
if (Kind == Sema::CheckConstexprKind::Diagnose) {
|
||||
SemaRef.Diag(VD->getLocation(),
|
||||
SemaRef.getLangOpts().CPlusPlus23
|
||||
? diag::compat_cxx23_constexpr_static_var
|
||||
: diag::compat_pre_cxx23_constexpr_static_var)
|
||||
SemaRef.DiagCompat(VD->getLocation(),
|
||||
diag_compat::constexpr_static_var)
|
||||
<< isa<CXXConstructorDecl>(Dcl)
|
||||
<< (VD->getTLSKind() == VarDecl::TLS_Dynamic);
|
||||
} else if (!SemaRef.getLangOpts().CPlusPlus23) {
|
||||
@ -2091,11 +2085,8 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
|
||||
if (!VD->getType()->isDependentType() &&
|
||||
!VD->hasInit() && !VD->isCXXForRangeDecl()) {
|
||||
if (Kind == Sema::CheckConstexprKind::Diagnose) {
|
||||
SemaRef.Diag(
|
||||
VD->getLocation(),
|
||||
SemaRef.getLangOpts().CPlusPlus20
|
||||
? diag::compat_cxx20_constexpr_local_var_no_init
|
||||
: diag::compat_pre_cxx20_constexpr_local_var_no_init)
|
||||
SemaRef.DiagCompat(VD->getLocation(),
|
||||
diag_compat::constexpr_local_var_no_init)
|
||||
<< isa<CXXConstructorDecl>(Dcl);
|
||||
} else if (!SemaRef.getLangOpts().CPlusPlus20) {
|
||||
return false;
|
||||
@ -2104,10 +2095,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
|
||||
}
|
||||
}
|
||||
if (Kind == Sema::CheckConstexprKind::Diagnose) {
|
||||
SemaRef.Diag(VD->getLocation(),
|
||||
SemaRef.getLangOpts().CPlusPlus14
|
||||
? diag::compat_cxx14_constexpr_local_var
|
||||
: diag::compat_pre_cxx14_constexpr_local_var)
|
||||
SemaRef.DiagCompat(VD->getLocation(), diag_compat::constexpr_local_var)
|
||||
<< isa<CXXConstructorDecl>(Dcl);
|
||||
} else if (!SemaRef.getLangOpts().CPlusPlus14) {
|
||||
return false;
|
||||
@ -2177,10 +2165,8 @@ static bool CheckConstexprCtorInitializer(Sema &SemaRef,
|
||||
if (!Inits.count(Field)) {
|
||||
if (Kind == Sema::CheckConstexprKind::Diagnose) {
|
||||
if (!Diagnosed) {
|
||||
SemaRef.Diag(Dcl->getLocation(),
|
||||
SemaRef.getLangOpts().CPlusPlus20
|
||||
? diag::compat_cxx20_constexpr_ctor_missing_init
|
||||
: diag::compat_pre_cxx20_constexpr_ctor_missing_init);
|
||||
SemaRef.DiagCompat(Dcl->getLocation(),
|
||||
diag_compat::constexpr_ctor_missing_init);
|
||||
Diagnosed = true;
|
||||
}
|
||||
SemaRef.Diag(Field->getLocation(),
|
||||
@ -2391,10 +2377,8 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
|
||||
break;
|
||||
|
||||
case Sema::CheckConstexprKind::Diagnose:
|
||||
SemaRef.Diag(Body->getBeginLoc(),
|
||||
SemaRef.getLangOpts().CPlusPlus20
|
||||
? diag::compat_cxx20_constexpr_function_try_block
|
||||
: diag::compat_pre_cxx20_constexpr_function_try_block)
|
||||
SemaRef.DiagCompat(Body->getBeginLoc(),
|
||||
diag_compat::constexpr_function_try_block)
|
||||
<< isa<CXXConstructorDecl>(Dcl);
|
||||
break;
|
||||
}
|
||||
@ -2421,22 +2405,13 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
|
||||
(Cxx1yLoc.isValid() && !SemaRef.getLangOpts().CPlusPlus17))
|
||||
return false;
|
||||
} else if (Cxx2bLoc.isValid()) {
|
||||
SemaRef.Diag(Cxx2bLoc,
|
||||
SemaRef.getLangOpts().CPlusPlus23
|
||||
? diag::compat_cxx23_constexpr_body_invalid_stmt
|
||||
: diag::compat_pre_cxx23_constexpr_body_invalid_stmt)
|
||||
SemaRef.DiagCompat(Cxx2bLoc, diag_compat::cxx23_constexpr_body_invalid_stmt)
|
||||
<< isa<CXXConstructorDecl>(Dcl);
|
||||
} else if (Cxx2aLoc.isValid()) {
|
||||
SemaRef.Diag(Cxx2aLoc,
|
||||
SemaRef.getLangOpts().CPlusPlus20
|
||||
? diag::compat_cxx20_constexpr_body_invalid_stmt
|
||||
: diag::compat_pre_cxx20_constexpr_body_invalid_stmt)
|
||||
SemaRef.DiagCompat(Cxx2aLoc, diag_compat::cxx20_constexpr_body_invalid_stmt)
|
||||
<< isa<CXXConstructorDecl>(Dcl);
|
||||
} else if (Cxx1yLoc.isValid()) {
|
||||
SemaRef.Diag(Cxx1yLoc,
|
||||
SemaRef.getLangOpts().CPlusPlus14
|
||||
? diag::compat_cxx14_constexpr_body_invalid_stmt
|
||||
: diag::compat_pre_cxx14_constexpr_body_invalid_stmt)
|
||||
SemaRef.DiagCompat(Cxx1yLoc, diag_compat::cxx14_constexpr_body_invalid_stmt)
|
||||
<< isa<CXXConstructorDecl>(Dcl);
|
||||
}
|
||||
|
||||
@ -2453,11 +2428,8 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
|
||||
if (Constructor->getNumCtorInitializers() == 0 &&
|
||||
RD->hasVariantMembers()) {
|
||||
if (Kind == Sema::CheckConstexprKind::Diagnose) {
|
||||
SemaRef.Diag(
|
||||
Dcl->getLocation(),
|
||||
SemaRef.getLangOpts().CPlusPlus20
|
||||
? diag::compat_cxx20_constexpr_union_ctor_no_init
|
||||
: diag::compat_pre_cxx20_constexpr_union_ctor_no_init);
|
||||
SemaRef.DiagCompat(Dcl->getLocation(),
|
||||
diag_compat::constexpr_union_ctor_no_init);
|
||||
} else if (!SemaRef.getLangOpts().CPlusPlus20) {
|
||||
return false;
|
||||
}
|
||||
@ -2520,11 +2492,8 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
|
||||
} else if (ReturnStmts.size() > 1) {
|
||||
switch (Kind) {
|
||||
case Sema::CheckConstexprKind::Diagnose:
|
||||
SemaRef.Diag(
|
||||
ReturnStmts.back(),
|
||||
SemaRef.getLangOpts().CPlusPlus14
|
||||
? diag::compat_cxx14_constexpr_body_multiple_return
|
||||
: diag::compat_pre_cxx14_constexpr_body_multiple_return);
|
||||
SemaRef.DiagCompat(ReturnStmts.back(),
|
||||
diag_compat::constexpr_body_multiple_return);
|
||||
for (unsigned I = 0; I < ReturnStmts.size() - 1; ++I)
|
||||
SemaRef.Diag(ReturnStmts[I],
|
||||
diag::note_constexpr_body_previous_return);
|
||||
@ -17836,9 +17805,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
|
||||
<< FixItHint::CreateInsertion(getLocForEndOfToken(FriendLoc),
|
||||
InsertionText);
|
||||
} else {
|
||||
Diag(FriendLoc, getLangOpts().CPlusPlus11
|
||||
? diag::compat_cxx11_nonclass_type_friend
|
||||
: diag::compat_pre_cxx11_nonclass_type_friend)
|
||||
DiagCompat(FriendLoc, diag_compat::nonclass_type_friend)
|
||||
<< T << DS.getSourceRange();
|
||||
}
|
||||
}
|
||||
|
@ -6508,9 +6508,7 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
|
||||
if (const auto *ULE = dyn_cast<UnresolvedLookupExpr>(Fn);
|
||||
ULE && ULE->hasExplicitTemplateArgs() &&
|
||||
ULE->decls_begin() == ULE->decls_end()) {
|
||||
Diag(Fn->getExprLoc(), getLangOpts().CPlusPlus20
|
||||
? diag::compat_cxx20_adl_only_template_id
|
||||
: diag::compat_pre_cxx20_adl_only_template_id)
|
||||
DiagCompat(Fn->getExprLoc(), diag_compat::adl_only_template_id)
|
||||
<< ULE->getName();
|
||||
}
|
||||
|
||||
|
@ -2234,10 +2234,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S,
|
||||
// template-argument, that declaration shall be a definition and shall be
|
||||
// the only declaration of the function template in the translation unit.
|
||||
// (C++98/03 doesn't have this wording; see DR226).
|
||||
S.Diag(ParamLoc,
|
||||
S.getLangOpts().CPlusPlus11
|
||||
? diag::compat_cxx11_templ_default_in_function_templ
|
||||
: diag::compat_pre_cxx11_templ_default_in_function_templ)
|
||||
S.DiagCompat(ParamLoc, diag_compat::templ_default_in_function_templ)
|
||||
<< DefArgRange;
|
||||
return false;
|
||||
|
||||
@ -6432,10 +6429,7 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction(
|
||||
bool ExtraParens = false;
|
||||
while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
|
||||
if (!Invalid && !ExtraParens) {
|
||||
S.Diag(Arg->getBeginLoc(),
|
||||
S.getLangOpts().CPlusPlus11
|
||||
? diag::compat_cxx11_template_arg_extra_parens
|
||||
: diag::compat_pre_cxx11_template_arg_extra_parens)
|
||||
S.DiagCompat(Arg->getBeginLoc(), diag_compat::template_arg_extra_parens)
|
||||
<< Arg->getSourceRange();
|
||||
ExtraParens = true;
|
||||
}
|
||||
@ -6655,10 +6649,7 @@ CheckTemplateArgumentPointerToMember(Sema &S, NonTypeTemplateParmDecl *Param,
|
||||
bool ExtraParens = false;
|
||||
while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
|
||||
if (!Invalid && !ExtraParens) {
|
||||
S.Diag(Arg->getBeginLoc(),
|
||||
S.getLangOpts().CPlusPlus11
|
||||
? diag::compat_cxx11_template_arg_extra_parens
|
||||
: diag::compat_pre_cxx11_template_arg_extra_parens)
|
||||
S.DiagCompat(Arg->getBeginLoc(), diag_compat::template_arg_extra_parens)
|
||||
<< Arg->getSourceRange();
|
||||
ExtraParens = true;
|
||||
}
|
||||
@ -10639,9 +10630,7 @@ TypeResult Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
|
||||
return true;
|
||||
|
||||
if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
|
||||
Diag(TypenameLoc, getLangOpts().CPlusPlus11
|
||||
? diag::compat_cxx11_typename_outside_of_template
|
||||
: diag::compat_pre_cxx11_typename_outside_of_template)
|
||||
DiagCompat(TypenameLoc, diag_compat::typename_outside_of_template)
|
||||
<< FixItHint::CreateRemoval(TypenameLoc);
|
||||
|
||||
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
|
||||
|
@ -18,7 +18,7 @@ void test(int x, int y) {
|
||||
// BASE: {{.*}}: warning: {{[a-z ]+$}}
|
||||
// OPTION: {{.*}}: warning: {{[a-z ]+}} [-Wparentheses]
|
||||
// OPTION_ERROR: {{.*}}: error: {{[a-z ]+}} [-Werror,-Wparentheses]
|
||||
// CATEGORY_ID: {{.*}}: warning: {{[a-z ]+}} [2]
|
||||
// CATEGORY_ID: {{.*}}: warning: {{[a-z ]+}} [{{[0-9]+}}]
|
||||
// CATEGORY_NAME: {{.*}}: warning: {{[a-z ]+}} [Semantic Issue]
|
||||
// OPTION_ERROR_CATEGORY: {{.*}}: error: {{[a-z ]+}} [-Werror,-Wparentheses,Semantic Issue]
|
||||
|
||||
|
@ -1518,6 +1518,50 @@ static void verifyDiagnosticWording(const Record &Diag) {
|
||||
// runs into odd situations like [[clang::warn_unused_result]],
|
||||
// #pragma clang, or --unwindlib=libgcc.
|
||||
}
|
||||
|
||||
/// ClangDiagsCompatIDsEmitter - Emit a set of 'compatibility diagnostic ids'
|
||||
/// that map to a set of 2 regular diagnostic ids each and which are used to
|
||||
/// simplify emitting compatibility warnings.
|
||||
void clang::EmitClangDiagsCompatIDs(const llvm::RecordKeeper &Records,
|
||||
llvm::raw_ostream &OS,
|
||||
const std::string &Component) {
|
||||
ArrayRef<const Record *> Ids =
|
||||
Records.getAllDerivedDefinitions("CompatWarningId");
|
||||
|
||||
StringRef PrevComponent = "";
|
||||
for (auto [I, R] : enumerate(make_pointee_range(Ids))) {
|
||||
StringRef DiagComponent = R.getValueAsString("Component");
|
||||
if (!Component.empty() && Component != DiagComponent)
|
||||
continue;
|
||||
|
||||
StringRef CompatDiagName = R.getValueAsString("Name");
|
||||
StringRef Diag = R.getValueAsString("Diag");
|
||||
StringRef DiagPre = R.getValueAsString("DiagPre");
|
||||
int64_t CXXStdVer = R.getValueAsInt("Std");
|
||||
|
||||
// We don't want to create empty enums since some compilers (including
|
||||
// Clang) warn about that, so these macros are used to avoid having to
|
||||
// unconditionally write 'enum {' and '};' in the headers.
|
||||
if (PrevComponent != DiagComponent) {
|
||||
if (!PrevComponent.empty())
|
||||
OS << "DIAG_COMPAT_IDS_END()\n";
|
||||
OS << "DIAG_COMPAT_IDS_BEGIN()\n";
|
||||
PrevComponent = DiagComponent;
|
||||
}
|
||||
|
||||
// FIXME: We sometimes define multiple compat diagnostics with the same
|
||||
// name, e.g. 'constexpr_body_invalid_stmt' exists for C++14/20/23. It would
|
||||
// be nice if we could combine all of them into a single compatibility diag
|
||||
// id.
|
||||
OS << "DIAG_COMPAT_ID(" << I << ",";
|
||||
OS << CompatDiagName << "," << CXXStdVer << "," << Diag << "," << DiagPre;
|
||||
OS << ")\n";
|
||||
}
|
||||
|
||||
if (!PrevComponent.empty())
|
||||
OS << "DIAG_COMPAT_IDS_END()\n";
|
||||
}
|
||||
|
||||
/// ClangDiagsEnumsEmitter - The top-level class emits .def files containing
|
||||
/// declarations of Clang diagnostic enums for selects.
|
||||
void clang::EmitClangDiagsEnums(const RecordKeeper &Records, raw_ostream &OS,
|
||||
|
@ -48,6 +48,7 @@ enum ActionType {
|
||||
GenClangBasicWriter,
|
||||
GenClangBuiltins,
|
||||
GenClangBuiltinTemplates,
|
||||
GenClangDiagsCompatIDs,
|
||||
GenClangDiagsDefs,
|
||||
GenClangDiagsEnums,
|
||||
GenClangDiagGroups,
|
||||
@ -176,6 +177,8 @@ cl::opt<ActionType> Action(
|
||||
"Generate clang builtins list"),
|
||||
clEnumValN(GenClangBuiltinTemplates, "gen-clang-builtin-templates",
|
||||
"Generate clang builtins list"),
|
||||
clEnumValN(GenClangDiagsCompatIDs, "gen-clang-diags-compat-ids",
|
||||
"Generate Clang diagnostic compatibility ids"),
|
||||
clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
|
||||
"Generate Clang diagnostics definitions"),
|
||||
clEnumValN(GenClangDiagsEnums, "gen-clang-diags-enums",
|
||||
@ -399,6 +402,9 @@ bool ClangTableGenMain(raw_ostream &OS, const RecordKeeper &Records) {
|
||||
case GenClangBuiltinTemplates:
|
||||
EmitClangBuiltinTemplates(Records, OS);
|
||||
break;
|
||||
case GenClangDiagsCompatIDs:
|
||||
EmitClangDiagsCompatIDs(Records, OS, ClangComponent);
|
||||
break;
|
||||
case GenClangDiagsDefs:
|
||||
EmitClangDiagsDefs(Records, OS, ClangComponent);
|
||||
break;
|
||||
|
@ -91,6 +91,9 @@ void EmitClangBuiltins(const llvm::RecordKeeper &Records,
|
||||
void EmitClangBuiltinTemplates(const llvm::RecordKeeper &Records,
|
||||
llvm::raw_ostream &OS);
|
||||
|
||||
void EmitClangDiagsCompatIDs(const llvm::RecordKeeper &Records,
|
||||
llvm::raw_ostream &OS,
|
||||
const std::string &Component);
|
||||
void EmitClangDiagsDefs(const llvm::RecordKeeper &Records,
|
||||
llvm::raw_ostream &OS, const std::string &Component);
|
||||
void EmitClangDiagsEnums(const llvm::RecordKeeper &Records,
|
||||
|
Loading…
x
Reference in New Issue
Block a user