aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Sema/DeclSpec.h3
-rw-r--r--lib/Parse/ParseDecl.cpp12
-rw-r--r--lib/Sema/DeclSpec.cpp8
-rw-r--r--test/Parser/cxx0x-decl.cpp3
4 files changed, 16 insertions, 10 deletions
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 0f323bd929..7999748b0f 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -598,7 +598,8 @@ public:
}
bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID, const LangOptions &Lang);
+ unsigned &DiagID, const LangOptions &Lang,
+ bool IsTypeSpec);
bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index c6a7d05c8f..b2a6b4bb41 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2666,15 +2666,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// cv-qualifier:
case tok::kw_const:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID,
- getLangOpts());
+ getLangOpts(), /*IsTypeSpec*/true);
break;
case tok::kw_volatile:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
- getLangOpts());
+ getLangOpts(), /*IsTypeSpec*/true);
break;
case tok::kw_restrict:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
- getLangOpts());
+ getLangOpts(), /*IsTypeSpec*/true);
break;
// C++ typename-specifier:
@@ -3869,15 +3869,15 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
case tok::kw_const:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID,
- getLangOpts());
+ getLangOpts(), /*IsTypeSpec*/false);
break;
case tok::kw_volatile:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
- getLangOpts());
+ getLangOpts(), /*IsTypeSpec*/false);
break;
case tok::kw_restrict:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
- getLangOpts());
+ getLangOpts(), /*IsTypeSpec*/false);
break;
// OpenCL qualifiers:
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 3cce8cb444..f3ec5656ea 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -668,9 +668,11 @@ bool DeclSpec::SetTypeSpecError() {
}
bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID, const LangOptions &Lang) {
- // Duplicates turn into warnings pre-C99.
- if ((TypeQualifiers & T) && !Lang.C99)
+ 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);
TypeQualifiers |= T;
diff --git a/test/Parser/cxx0x-decl.cpp b/test/Parser/cxx0x-decl.cpp
index 9a220caa5a..a6fc49cb9e 100644
--- a/test/Parser/cxx0x-decl.cpp
+++ b/test/Parser/cxx0x-decl.cpp
@@ -25,3 +25,6 @@ class ExtraSemiAfterMemFn {
void h() = delete;; // ok
void i() = delete;;; // expected-warning {{extra ';' after member function definition}}
};
+
+int *const const p = 0; // ok
+const const int *q = 0; // expected-warning {{duplicate 'const' declaration specifier}}