summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseExprCXX.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-01-13 17:31:36 +0000
committerDouglas Gregor <dgregor@apple.com>2010-01-13 17:31:36 +0000
commit9de54ea41bdcf97f238ba9c4a1fa1d091d5813d9 (patch)
treecba2865d8d63cf45bf9270ea576c1e68bd757a88 /clang/lib/Parse/ParseExprCXX.cpp
parentb89b99f1f267237d68712b728b4aa5c90907cb48 (diff)
downloadbcm5719-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.cpp37
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;
}
OpenPOWER on IntegriCloud