diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 9e8823fb4d17..d224a77d8424 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4675,6 +4675,10 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide) { return false; } + // There may be attributes here, appertaining to the constructor name or type + // we just stepped past. + SkipCXX11Attributes(); + // Current class name must be followed by a left parenthesis. if (Tok.isNot(tok::l_paren)) { TPA.Revert(); @@ -4742,18 +4746,24 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide) { case tok::r_paren: // C(X ) + + // Skip past the right-paren and any following attributes to get to + // the function body or trailing-return-type. + ConsumeParen(); + SkipCXX11Attributes(); + if (DeductionGuide) { // C(X) -> ... is a deduction guide. - IsConstructor = NextToken().is(tok::arrow); + IsConstructor = Tok.is(tok::arrow); break; } - if (NextToken().is(tok::colon) || NextToken().is(tok::kw_try)) { + if (Tok.is(tok::colon) || Tok.is(tok::kw_try)) { // Assume these were meant to be constructors: // C(X) : (the name of a bit-field cannot be parenthesized). // C(X) try (this is otherwise ill-formed). IsConstructor = true; } - if (NextToken().is(tok::semi) || NextToken().is(tok::l_brace)) { + if (Tok.is(tok::semi) || Tok.is(tok::l_brace)) { // If we have a constructor name within the class definition, // assume these were meant to be constructors: // C(X) { diff --git a/clang/test/CXX/temp/temp.deduct.guide/p1.cpp b/clang/test/CXX/temp/temp.deduct.guide/p1.cpp index 5c27cfe96cbc..fb0a26a5c735 100644 --- a/clang/test/CXX/temp/temp.deduct.guide/p1.cpp +++ b/clang/test/CXX/temp/temp.deduct.guide/p1.cpp @@ -31,7 +31,7 @@ A(int(&)[5])[3] -> A; // (Pending DR) attributes and parens around the declarator-id are OK. [[deprecated]] A(int(&)[6]) [[]] -> A [[]]; -A [[]] (int(&)[7]) -> A; // FIXME: expected-error 2{{expected}} expected-note {{to match}} +A [[]] (int(&)[7]) -> A; (A)(int(&)[8]) -> A; // ... but the trailing-return-type is part of the function-declarator as normal diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp index 906d72b087cb..647762f165cb 100644 --- a/clang/test/Parser/cxx0x-attributes.cpp +++ b/clang/test/Parser/cxx0x-attributes.cpp @@ -99,11 +99,13 @@ void fn_with_structs() { } [[]]; struct ctordtor { - [[]] ctordtor(); - [[]] ~ctordtor(); + [[]] ctordtor [[]] () [[]]; + ctordtor (C) [[]]; + [[]] ~ctordtor [[]] () [[]]; }; -[[]] ctordtor::ctordtor() {} -[[]] ctordtor::~ctordtor() {} +[[]] ctordtor::ctordtor [[]] () [[]] {} +[[]] ctordtor::ctordtor (C) [[]] try {} catch (...) {} +[[]] ctordtor::~ctordtor [[]] () [[]] {} extern "C++" [[]] int extern_attr; template [[]] void template_attr (); [[]] [[]] int [[]] [[]] multi_attr [[]] [[]];