diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-01-13 17:31:36 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-01-13 17:31:36 +0000 |
commit | 9de54ea41bdcf97f238ba9c4a1fa1d091d5813d9 (patch) | |
tree | cba2865d8d63cf45bf9270ea576c1e68bd757a88 /clang/lib/Parse/ParseExprCXX.cpp | |
parent | b89b99f1f267237d68712b728b4aa5c90907cb48 (diff) | |
download | bcm5719-llvm-9de54ea41bdcf97f238ba9c4a1fa1d091d5813d9.tar.gz bcm5719-llvm-9de54ea41bdcf97f238ba9c4a1fa1d091d5813d9.zip |
Reimplement constructor declarator parsing to cope with template-ids
that name constructors, the endless joys of out-of-line constructor
definitions, and various other corner cases that the previous hack
never imagined. Fixes PR5688 and tightens up semantic analysis for
constructor names.
Additionally, fixed a problem where we wouldn't properly enter the
declarator scope of a parenthesized declarator. We were entering the
scope, then leaving it when we saw the ")"; now, we re-enter the
declarator scope before parsing the parameter list.
Note that we are forced to perform some tentative parsing within a
class (call it C) to tell the difference between
C(int); // constructor
and
C (f)(int); // member function
which is rather unfortunate. And, although it isn't necessary for
correctness, we use the same tentative-parsing mechanism for
out-of-line constructors to improve diagnostics in icky cases like:
C::C C::f(int); // error: C::C refers to the constructor name, but
// we complain nicely and recover by treating it as
// a type.
llvm-svn: 93322
Diffstat (limited to 'clang/lib/Parse/ParseExprCXX.cpp')
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index dc6f7cf4586..ca50ef40009 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1182,12 +1182,41 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, // unqualified-id: // template-id (already parsed and annotated) if (Tok.is(tok::annot_template_id)) { - // FIXME: Could this be a constructor name??? - + TemplateIdAnnotation *TemplateId + = static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue()); + + // If the template-name names the current class, then this is a constructor + if (AllowConstructorName && TemplateId->Name && + Actions.isCurrentClassName(*TemplateId->Name, CurScope, &SS)) { + if (SS.isSet()) { + // C++ [class.qual]p2 specifies that a qualified template-name + // is taken as the constructor name where a constructor can be + // declared. Thus, the template arguments are extraneous, so + // complain about them and remove them entirely. + Diag(TemplateId->TemplateNameLoc, + diag::err_out_of_line_constructor_template_id) + << TemplateId->Name + << CodeModificationHint::CreateRemoval( + SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)); + Result.setConstructorName(Actions.getTypeName(*TemplateId->Name, + TemplateId->TemplateNameLoc, + CurScope, + &SS, false), + TemplateId->TemplateNameLoc, + TemplateId->RAngleLoc); + TemplateId->Destroy(); + ConsumeToken(); + return false; + } + + Result.setConstructorTemplateId(TemplateId); + ConsumeToken(); + return false; + } + // We have already parsed a template-id; consume the annotation token as // our unqualified-id. - Result.setTemplateId( - static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue())); + Result.setTemplateId(TemplateId); ConsumeToken(); return false; } |