Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -36,6 +36,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" +#include using namespace clang; @@ -1679,8 +1680,16 @@ // C90 6.5.3 constraints: "The same type qualifier shall not appear more // than once in the same specifier-list or qualifier-list, either directly // or via one or more typedefs." - if (!S.getLangOpts().C99 && !S.getLangOpts().CPlusPlus - && TypeQuals & Result.getCVRQualifiers()) { + // + // C90 and GNU89 do not warn if the TST is from a typedef unless -pedantic + // was set. GNU89 additionally does not warn if the TST is from a typeof + // expression and -pedantic was not set. + if (!S.getLangOpts().C99 && !S.getLangOpts().CPlusPlus && + TypeQuals & Result.getCVRQualifiers() && + (S.Diags.getDiagnosticOptions().Pedantic || + !(DS.getTypeSpecType() == DeclSpec::TST_typename || + (S.getLangOpts().GNUMode && + DS.getTypeSpecType() == DeclSpec::TST_typeofExpr)))) { if (TypeQuals & DeclSpec::TQ_const && Result.isConstQualified()) { S.Diag(DS.getConstSpecLoc(), diag::ext_duplicate_declspec) << "const"; Index: test/Sema/gnu89-const.c =================================================================== --- /dev/null +++ test/Sema/gnu89-const.c @@ -0,0 +1,87 @@ +/* +RUN: not %clang_cc1 %s -std=c89 -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-C89 %s +RUN: not %clang_cc1 %s -std=c89 -pedantic -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-C89-PEDANTIC %s +RUN: not %clang_cc1 %s -std=c99 -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-C99 %s +RUN: not %clang_cc1 %s -std=c99 -pedantic -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-C99-PEDANTIC %s +RUN: not %clang_cc1 %s -std=c11 -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-C11 %s +RUN: not %clang_cc1 %s -std=c11 -pedantic -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-C11-PEDANTIC %s +RUN: not %clang_cc1 %s -std=c17 -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-C17 %s +RUN: not %clang_cc1 %s -std=c17 -pedantic -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-C17-PEDANTIC %s + +RUN: %clang_cc1 %s -std=gnu89 -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-GNU89 %s +RUN: %clang_cc1 %s -std=gnu89 -pedantic -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-GNU89-PEDANTIC %s +RUN: %clang_cc1 %s -std=gnu99 -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-GNU99 %s +RUN: %clang_cc1 %s -std=gnu99 -pedantic -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-GNU99-PEDANTIC %s +RUN: %clang_cc1 %s -std=gnu11 -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-GNU11 %s +RUN: %clang_cc1 %s -std=gnu11 -pedantic -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-GNU11-PEDANTIC %s +RUN: %clang_cc1 %s -std=gnu17 -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-GNU17 %s +RUN: %clang_cc1 %s -std=gnu17 -pedantic -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-GNU17-PEDANTIC %s +*/ + +const const int c_i; +/* +CHECK-C89: 21:7: warning: duplicate 'const' declaration specifier +CHECK-C89-PEDANTIC: 21:7: warning: duplicate 'const' declaration specifier +CHECK-C99: 21:7: warning: duplicate 'const' declaration specifier +CHECK-C99-PEDANTIC: 21:7: warning: duplicate 'const' declaration specifier +CHECK-C11: 21:7: warning: duplicate 'const' declaration specifier +CHECK-C11-PEDANTIC: 21:7: warning: duplicate 'const' declaration specifier +CHECK-C17: 21:7: warning: duplicate 'const' declaration specifier +CHECK-C17-PEDANTIC: 21:7: warning: duplicate 'const' declaration specifier + +CHECK-GNU89: 21:7: warning: duplicate 'const' declaration specifier +CHECK-GNU89-PEDANTIC: 21:7: warning: duplicate 'const' declaration specifier +CHECK-GNU99: 21:7: warning: duplicate 'const' declaration specifier +CHECK-GNU99-PEDANTIC: 21:7: warning: duplicate 'const' declaration specifier +CHECK-GNU11: 21:7: warning: duplicate 'const' declaration specifier +CHECK-GNU11-PEDANTIC: 21:7: warning: duplicate 'const' declaration specifier +CHECK-GNU17: 21:7: warning: duplicate 'const' declaration specifier +CHECK-GNU17-PEDANTIC: 21:7: warning: duplicate 'const' declaration specifier +*/ + +typedef const int t; +const t c_i2; +/* +CHECK-C89-NOT: 43:1: warning: duplicate 'const' declaration specifier +CHECK-C89-PEDANTIC: 43:1: warning: duplicate 'const' declaration specifier + ^ NOTE: special case +CHECK-C99-NOT: 43:1: warning: duplicate 'const' declaration specifier +CHECK-C99-PEDANTIC-NOT: 43:1: warning: duplicate 'const' declaration specifier +CHECK-C11-NOT: 43:1: warning: duplicate 'const' declaration specifier +CHECK-C11-PEDANTIC-NOT: 43:1: warning: duplicate 'const' declaration specifier +CHECK-C17-NOT: 43:1: warning: duplicate 'const' declaration specifier +CHECK-C17-PEDANTIC-NOT: 43:1: warning: duplicate 'const' declaration specifier + +CHECK-GNU89-NOT: 43:1: warning: duplicate 'const' declaration specifier +CHECK-CNU89-PEDANTIC: 43:1: warning: duplicate 'const' declaration specifier +CHECK-CNU99-NOT: 43:1: warning: duplicate 'const' declaration specifier +CHECK-CNU99-PEDANTIC-NOT: 43:1: warning: duplicate 'const' declaration specifier +CHECK-CNU11-NOT: 43:1: warning: duplicate 'const' declaration specifier +CHECK-CNU11-PEDANTIC-NOT: 43:1: warning: duplicate 'const' declaration specifier +CHECK-CNU17-NOT: 43:1: warning: duplicate 'const' declaration specifier +CHECK-CNU17-PEDANTIC-NOT: 43:1: warning: duplicate 'const' declaration specifier +*/ + +const int c_i3; +const typeof(c_i) c_i4; +/* +CHECK-C89: 66:19: error: expected function body after function declarator +CHECK-C89-PEDANTIC: 66:19: error: expected function body after function declarator +CHECK-C99: 66:19: error: expected function body after function declarator +CHECK-C99-PEDANTIC: 66:19: error: expected function body after function declarator +CHECK-C11: 66:19: error: expected function body after function declarator +CHECK-C11-PEDANTIC: 66:19: error: expected function body after function declarator +CHECK-C17: 66:19: error: expected function body after function declarator +CHECK-C17-PEDANTIC: 66:19: error: expected function body after function declarator + +CHECK-GNU89-NOT: 66:1: warning: duplicate 'const' declaration specifier + ^ NOTE: special case +CHECK-GNU89-PEDANTIC: 66:1: warning: duplicate 'const' declaration specifier + ^ NOTE: special case +CHECK-GNU99-NOT: 66:1: warning: duplicate 'const' declaration specifier +CHECK-GNU99-PEDANTIC-NOT: 66:1: warning: duplicate 'const' declaration specifier +CHECK-GNU11-NOT: 66:1: warning: duplicate 'const' declaration specifier +CHECK-GNU11-PEDANTIC-NOT: 66:1: warning: duplicate 'const' declaration specifier +CHECK-GNU17-NOT: 66:1: warning: duplicate 'const' declaration specifier +CHECK-GNU17-PEDANTIC-NOT: 66:1: warning: duplicate 'const' declaration specifier +*/