diff options
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 32 | ||||
-rw-r--r-- | test/SemaCXX/decl-expr-ambiguity.cpp | 17 |
2 files changed, 41 insertions, 8 deletions
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 9bd35dd110..bd2d106923 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -282,16 +282,24 @@ bool Parser::isCXXConditionDeclaration() { return TPR == TPResult::True(); } -/// isCXXTypeIdInParens - Assumes that a '(' was parsed and now we want to
-/// know whether the parens contain an expression or a type-id.
-/// Returns true for a type-id and false for an expression.
-/// If during the disambiguation process a parsing error is encountered,
-/// the function returns true to let the declaration parsing code handle it.
-///
-/// type-id:
+/// isCXXTypeIdInParens - Assumes that a '(' was parsed and now we want to +/// know whether the parens contain an expression or a type-id. +/// Returns true for a type-id and false for an expression. +/// If during the disambiguation process a parsing error is encountered, +/// the function returns true to let the declaration parsing code handle it. +/// +/// type-id: /// type-specifier-seq abstract-declarator[opt] /// bool Parser::isCXXTypeIdInParens() { + + // C++ 8.2p2: + // The ambiguity arising from the similarity between a function-style cast and + // a type-id can occur in different contexts. The ambiguity appears as a + // choice between a function-style cast expression and a declaration of a + // type. The resolution is that any construct that could possibly be a type-id + // in its syntactic context shall be considered a type-id. + TPResult TPR = isCXXDeclarationSpecifier(); if (TPR != TPResult::Ambiguous()) return TPR != TPResult::False(); // Returns true for TPResult::True() or @@ -706,6 +714,16 @@ Parser::TPResult Parser::TryParseDeclarationSpecifier() { /// exception-specification[opt] /// bool Parser::isCXXFunctionDeclarator() { + + // C++ 8.2p1: + // The ambiguity arising from the similarity between a function-style cast and + // a declaration mentioned in 6.8 can also occur in the context of a + // declaration. In that context, the choice is between a function declaration + // with a redundant set of parentheses around a parameter name and an object + // declaration with a function-style cast as the initializer. Just as for the + // ambiguities mentioned in 6.8, the resolution is to consider any construct + // that could possibly be a declaration a declaration. + TentativeParsingAction PA(*this); ConsumeParen(); diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp index 35805abac5..3459d771ab 100644 --- a/test/SemaCXX/decl-expr-ambiguity.cpp +++ b/test/SemaCXX/decl-expr-ambiguity.cpp @@ -1,4 +1,4 @@ -// RUN: clang -fsyntax-only -verify %s +// RUN: clang -fsyntax-only -verify -pedantic-errors %s void f() { int a; @@ -14,7 +14,12 @@ void f() { if (int(a)+1) {} for (int(a)+1;;) {} a = sizeof(int()+1); + a = sizeof(int(1)); typeof(int()+1) a2; + (int(1)); // expected-warning {{expression result unused}} + + // type-id + (int())1; // expected-error {{used type 'int ()' where arithmetic or pointer type is required}} // Declarations. T(*d)(int(p)); // expected-warning {{statement was disambiguated as declaration}} expected-error {{previous definition is here}} @@ -25,3 +30,13 @@ void f() { if (int(a)=1) {} int(d3(int())); // expected-warning {{statement was disambiguated as declaration}} } + +class C { }; +void fn(int(C)) { } // void fn(int(*fp)(C c)) { } + // not: void fn(int C); +int g(C); + +void foo() { + fn(1); // expected-error {{incompatible integer to pointer conversion passing 'int', expected 'int (*)(class C)'}} + fn(g); // OK +} |