Hi Richard,
Could you please review this fix?
Thank you.
--Serge
Recognize additional cases, when '::' is mistyped as ':' and provide
descriptive diagnostics for them.
This is a fix to RP18587 - colons have too much protection in
member-declarations
http://reviews.llvm.org/D3653
Files:
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
test/SemaCXX/nested-name-spec.cpp
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -2706,7 +2706,7 @@
case tok::identifier: {
// In C++, check to see if this is a scope specifier like foo::bar::, if
// so handle it as such. This is important for ctor parsing.
- if (getLangOpts().CPlusPlus) {
+ if (getLangOpts().CPlusPlus && !DS.hasTypeSpecifier()) {
if (TryAnnotateCXXScopeToken(EnteringContext)) {
if (!DS.hasTypeSpecifier())
DS.SetTypeSpecError();
@@ -4508,8 +4508,10 @@
// Member pointers get special handling, since there's no place for the
// scope spec in the generic path below.
if (getLangOpts().CPlusPlus &&
- (Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
- Tok.is(tok::annot_cxxscope))) {
+ (Tok.is(tok::coloncolon) ||
+ (Tok.is(tok::identifier) && (NextToken().is(tok::coloncolon) ||
+ NextToken().is(tok::less))) ||
+ Tok.is(tok::annot_cxxscope))) {
bool EnteringContext = D.getContext() == Declarator::FileContext ||
D.getContext() == Declarator::MemberContext;
CXXScopeSpec SS;
@@ -4701,6 +4703,11 @@
DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) {
+ // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
+ // is a bitfield.
+ ColonProtectionRAIIObject X(*this,
+ D.getContext() == Declarator::MemberContext);
+
// ParseDeclaratorInternal might already have parsed the scope.
if (D.getCXXScopeSpec().isEmpty()) {
bool EnteringContext = D.getContext() == Declarator::FileContext ||
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -1228,7 +1228,8 @@
// Parse the (optional) nested-name-specifier.
CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLangOpts().CPlusPlus) {
- // "FOO : BAR" is not a potential typo for "FOO::BAR".
+ // "FOO : BAR" is not a potential typo for "FOO::BAR". In this context it
+ // is base-specifier-list.
ColonProtectionRAIIObject X(*this);
if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
@@ -1913,14 +1914,8 @@
// declarator pure-specifier[opt]
// declarator brace-or-equal-initializer[opt]
// identifier[opt] ':' constant-expression
- if (Tok.isNot(tok::colon)) {
- // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
- // is a bitfield.
- // FIXME: This should only apply when parsing the id-expression (see
- // PR18587).
- ColonProtectionRAIIObject X(*this);
+ if (Tok.isNot(tok::colon))
ParseDeclarator(DeclaratorInfo);
- }
if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) {
BitfieldSize = ParseConstantExpression();
@@ -2115,13 +2110,8 @@
if (MalformedTypeSpec)
DS.SetTypeSpecError();
- {
- // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
- // is a bitfield.
- ColonProtectionRAIIObject X(*this);
- ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
- &CommonLateParsedAttrs);
- }
+ ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
+ &CommonLateParsedAttrs);
// If we had a free-standing type definition with a missing semicolon, we
// may get this far before the problem becomes obvious.
Index: test/SemaCXX/nested-name-spec.cpp
===================================================================
--- test/SemaCXX/nested-name-spec.cpp
+++ test/SemaCXX/nested-name-spec.cpp
@@ -311,3 +311,116 @@
namespace TypedefNamespace { typedef int F; };
TypedefNamespace::F::NonexistentName BadNNSWithCXXScopeSpec; // expected-error {{'F' (aka 'int') is not a class, namespace, or scoped enumeration}}
+
+namespace PR18587 {
+
+struct C1 {
+ int a, b, c;
+ typedef int C2;
+ struct B1 {
+ struct B2 {
+ int a, b, c;
+ };
+ };
+};
+struct C2 { static const unsigned N1 = 1; };
+struct B1 {
+ enum { B2 = 2 };
+ static const int B3 = 3;
+};
+const int N1 = 2;
+
+// Function declarators
+struct S1a { int f(C1::C2); };
+struct S1b { int f(C1:C2); }; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+
+struct S2a {
+ C1::C2 f(C1::C2);
+};
+struct S2b {
+ C1:C2 f(C1::C2); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+};
+struct S2c {
+ C1::C2 f(C1:C2); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+};
+
+struct S3a {
+ int f(C1::C2), C2 : N1;
+ int g : B1::B2;
+};
+struct S3b {
+ int g : B1:B2; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+};
+
+// Inside square brackets
+struct S4a {
+ int f[C2::N1];
+};
+struct S4b {
+ int f[C2:N1]; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+};
+
+struct S5a {
+ int f(int xx[B1::B3 ? C2::N1 : B1::B2]);
+};
+struct S5b {
+ int f(int xx[B1::B3 ? C2::N1 : B1:B2]); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+};
+struct S5c {
+ int f(int xx[B1:B3 ? C2::N1 : B1::B2]); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+};
+
+// Bit fields
+struct S6a {
+ C1::C2 m1 : B1::B2;
+};
+struct S6b {
+ C1:C2 m1 : B1::B2; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+};
+struct S6c {
+ C1::C2 m1 : B1:B2; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+};
+struct S6d {
+ int C2:N1;
+};
+
+// Template parameters
+template <int N> struct T1 {
+ int a,b,c;
+ static const unsigned N1 = N;
+ typedef unsigned C1;
+};
+T1<C2::N1> var_1a;
+T1<C2:N1> var_1b; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+template<int N> int F() {}
+int (*X1)() = (B1::B2 ? F<1> : F<2>);
+int (*X2)() = (B1:B2 ? F<1> : F<2>); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+
+// Bit fields + templates
+struct S7a {
+ T1<B1::B2>::C1 m1 : T1<B1::B2>::N1;
+};
+struct S7b {
+ T1<B1:B2>::C1 m1 : T1<B1::B2>::N1; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+};
+struct S7c {
+ T1<B1::B2>::C1 m1 : T1<B1:B2>::N1; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+};
+
+// Member pointers
+struct S8a {
+ C1::C2 C1::*m1;
+};
+struct S8b {
+ C1:C2 C1::*m1; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+};
+
+// nested types
+struct S9a {
+ typedef C1::C2 t1;
+};
+struct S9b {
+ typedef C1:C2 t1; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
+};
+
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits