diff options
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 21 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 13 | ||||
-rw-r--r-- | clang/test/SemaCXX/constructor.cpp | 13 |
4 files changed, 36 insertions, 23 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 59e9ed6acbe..8b81c312d2e 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2381c62575a..37f4985ebe8 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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<CXXRecordDecl>(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<CXXRecordDecl>(DC), D.getIdentifierLoc(), Name, R, diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e9b7fb04ceb..6e00488c509 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/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/clang/test/SemaCXX/constructor.cpp b/clang/test/SemaCXX/constructor.cpp index 1429cc64527..8f289a2b1e9 100644 --- a/clang/test/SemaCXX/constructor.cpp +++ b/clang/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); +} +} |