From: Anders Carlsson Date: Thu, 30 Apr 2009 22:41:11 +0000 (+0000) Subject: Rework the way we handle constructor decls to be less hacky and fix PR3948 completely. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4649cac75c3cb80d543c6d90269388277228508d;p=clang Rework the way we handle constructor decls to be less hacky and fix PR3948 completely. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70516 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 59e9ed6acb..8b81c312d2 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1982,7 +1982,17 @@ void Parser::ParseDirectDeclarator(Declarator &D) { if (Tok.is(tok::identifier)) { assert(Tok.getIdentifierInfo() && "Not an identifier?"); - D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); + + // If this identifier is the name of the current class, it's a + // constructor name. + if (!D.getDeclSpec().hasTypeSpecifier() && + Actions.isCurrentClassName(*Tok.getIdentifierInfo(),CurScope)) { + D.setConstructor(Actions.getTypeName(*Tok.getIdentifierInfo(), + Tok.getLocation(), CurScope), + Tok.getLocation()); + // This is a normal identifier. + } else + D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); goto PastIdentifier; } else if (Tok.is(tok::annot_template_id)) { @@ -2092,15 +2102,6 @@ void Parser::ParseDirectDeclarator(Declarator &D) { break; } ParseFunctionDeclarator(ConsumeParen(), D); - - // If this identifier is the name of the current class, it's a - // constructor name. - if (IdentifierInfo *II = D.getIdentifier()) { - if (Actions.isCurrentClassName(*II, CurScope)) - D.setConstructor(Actions.getTypeName(*II, D.getIdentifierLoc(), - CurScope), - D.getIdentifierLoc()); - } } else if (Tok.is(tok::l_square)) { ParseBracketDeclarator(D); } else { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 2381c62575..37f4985ebe 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2035,6 +2035,18 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isVirtualOkay = true; } else if (DC->isRecord()) { + // If the of the function is the same as the name of the record, then this + // must be an invalid constructor that has a return type. + // (The parser checks for a return type and makes the declarator a + // constructor if it has no return type). + // must have an invalid constructor that has a return type + if (Name.getAsIdentifierInfo() == cast(DC)->getIdentifier()){ + Diag(D.getIdentifierLoc(), diag::err_constructor_return_type) + << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) + << SourceRange(D.getIdentifierLoc()); + return 0; + } + // This is a C++ method declaration. NewFD = CXXMethodDecl::Create(Context, cast(DC), D.getIdentifierLoc(), Name, R, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index e9b7fb04ce..6e00488c50 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1294,19 +1294,6 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, D.setInvalidType(); SC = FunctionDecl::None; } - if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) { - // Constructors don't have return types, but the parser will - // happily parse something like: - // - // class X { - // float X(float); - // }; - // - // The return type will be eliminated later. - Diag(D.getIdentifierLoc(), diag::err_constructor_return_type) - << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) - << SourceRange(D.getIdentifierLoc()); - } DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; if (FTI.TypeQuals != 0) { diff --git a/test/SemaCXX/constructor.cpp b/test/SemaCXX/constructor.cpp index 1429cc6452..8f289a2b1e 100644 --- a/test/SemaCXX/constructor.cpp +++ b/test/SemaCXX/constructor.cpp @@ -45,3 +45,16 @@ struct Length { struct mmst_reg{ char mmst_reg[10]; }; + +// PR3948 +namespace PR3948 { +// PR3948 +class a { + public: + int b(int a()); +}; +int x(); +void y() { + a z; z.b(x); +} +}