Splitting the duplicated decl spec extension warning into two: one is an ExtWarn and the other a vanilla warning. This addresses PR13705, where const char const * wouldn't warn unless -pedantic was specified under the right conditions.

llvm-svn: 162793
This commit is contained in:
Aaron Ballman 2012-08-28 20:55:40 +00:00
parent 8d48938bf3
commit 3731b33009
6 changed files with 27 additions and 9 deletions

View File

@ -197,6 +197,7 @@ def StringPlusInt : DiagGroup<"string-plus-int">;
def StrncatSize : DiagGroup<"strncat-size">;
def TautologicalCompare : DiagGroup<"tautological-compare">;
def HeaderHygiene : DiagGroup<"header-hygiene">;
def DuplicateDeclSpecifiers : DiagGroup<"duplicate-decl-specifiers">;
// Preprocessor warnings.
def : DiagGroup<"builtin-macro-redefined">;

View File

@ -43,7 +43,10 @@ def warn_extra_semi_after_mem_fn_def : Warning<
"extra ';' after member function definition">,
InGroup<ExtraSemi>, DefaultIgnore;
def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">;
def ext_duplicate_declspec : ExtWarn<"duplicate '%0' declaration specifier">,
InGroup<DuplicateDeclSpecifiers>;
def warn_duplicate_declspec : Warning<"duplicate '%0' declaration specifier">,
InGroup<DuplicateDeclSpecifiers>;
def ext_plain_complex : ExtWarn<
"plain '_Complex' requires a type specifier; assuming '_Complex double'">;
def ext_integer_complex : Extension<

View File

@ -325,10 +325,14 @@ unsigned DeclSpec::getParsedSpecifiers() const {
template <class T> static bool BadSpecifier(T TNew, T TPrev,
const char *&PrevSpec,
unsigned &DiagID) {
unsigned &DiagID,
bool IsExtension = true) {
PrevSpec = DeclSpec::getSpecifierName(TPrev);
DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec
: diag::err_invalid_decl_spec_combination);
if (TNew != TPrev)
DiagID = diag::err_invalid_decl_spec_combination;
else
DiagID = IsExtension ? diag::ext_duplicate_declspec :
diag::warn_duplicate_declspec;
return true;
}
@ -673,9 +677,15 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID, const LangOptions &Lang,
bool IsTypeSpec) {
// Duplicates are permitted in C99, and are permitted in C++11 unless the
// cv-qualifier appears as a type-specifier.
if ((TypeQualifiers & T) && !Lang.C99 && (!Lang.CPlusPlus0x || IsTypeSpec))
return BadSpecifier(T, T, PrevSpec, DiagID);
// cv-qualifier appears as a type-specifier. However, since this is likely
// not what the user intended, we will always warn. We do not need to set the
// qualifier's location since we already have it.
if (TypeQualifiers & T) {
bool IsExtension = false;
if (Lang.C99 || (Lang.CPlusPlus0x && !IsTypeSpec))
IsExtension = true;
return BadSpecifier(T, T, PrevSpec, DiagID, IsExtension);
}
TypeQualifiers |= T;
switch (T) {

View File

@ -181,4 +181,4 @@ CHECK-NEXT: warn_weak_import
The list of warnings in -Wpedantic should NEVER grow.
CHECK: Number in -Wpedantic (not covered by other -W flags): 39
CHECK: Number in -Wpedantic (not covered by other -W flags): 38

View File

@ -1,5 +1,7 @@
// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -pedantic %s
const char const *x10; // expected-warning {{duplicate 'const' declaration specifier}}
int x(*g); // expected-error {{use of undeclared identifier 'g'}}
struct Type {

View File

@ -26,5 +26,7 @@ class ExtraSemiAfterMemFn {
void i() = delete;;; // expected-warning {{extra ';' after member function definition}}
};
int *const const p = 0; // ok
// This is technically okay, but not likely what the user expects, so we will
// pedantically warn on it
int *const const p = 0; // expected-warning {{duplicate 'const' declaration specifier}}
const const int *q = 0; // expected-warning {{duplicate 'const' declaration specifier}}