Add support for parsing and representing C++ constructor declarations.
Notes:
- Constructors are never found by name lookup, so they'll never get
pushed into any scope. Instead, they are stored as an
OverloadedFunctionDecl in CXXRecordDecl for easy overloading.
- There's a new action isCurrentClassName that determines whether an
identifier is the name of the innermost class currently being defined;
we use this to identify the declarator-id grammar rule that refers to
a type-name.
- MinimalAction does *not* support parsing constructors.
- We now handle virtual and explicit function specifiers.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58499 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 1d42fed..d61d6c5 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -30,7 +30,7 @@
if (hasTypeSpecifier())
Res |= PQ_TypeSpecifier;
- if (FS_inline_specified)
+ if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified)
Res |= PQ_FunctionSpecifier;
return Res;
}
@@ -206,6 +206,20 @@
return false;
}
+bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec){
+ // 'virtual virtual' is ok.
+ FS_virtual_specified = true;
+ FS_virtualLoc = Loc;
+ return false;
+}
+
+bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec){
+ // 'explicit explicit' is ok.
+ FS_explicit_specified = true;
+ FS_explicitLoc = Loc;
+ return false;
+}
+
/// Finish - This does final analysis of the declspec, rejecting things like
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index c98830c..2fec359 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -63,6 +63,12 @@
return 0;
}
+/// isCurrentClassName - Always returns false, because MinimalAction
+/// does not support C++ classes with constructors.
+bool MinimalAction::isCurrentClassName(const IdentifierInfo &, Scope *) {
+ return false;
+}
+
/// ActOnDeclarator - If this is a typedef declarator, we modify the
/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
/// popped.
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 243a15f..7a84171 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -383,7 +383,12 @@
// Issue diagnostic and remove function specfier if present.
if (Specs & DeclSpec::PQ_FunctionSpecifier) {
- Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
+ if (DS.isInlineSpecified())
+ Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
+ if (DS.isVirtualSpecified())
+ Diag(DS.getVirtualSpecLoc(), diag::err_typename_invalid_functionspec);
+ if (DS.isExplicitSpecified())
+ Diag(DS.getExplicitSpecLoc(), diag::err_typename_invalid_functionspec);
DS.ClearFunctionSpecs();
}
}
@@ -433,6 +438,8 @@
/// [C99] 'restrict'
/// function-specifier: [C99 6.7.4]
/// [C99] 'inline'
+/// [C++] 'virtual'
+/// [C++] 'explicit'
///
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
DS.SetRangeStart(Tok.getLocation());
@@ -462,6 +469,16 @@
if (TypeRep == 0)
goto DoneWithDeclSpec;
+ // C++: If the identifier is actually the name of the class type
+ // being defined and the next token is a '(', then this is a
+ // constructor declaration. We're done with the decl-specifiers
+ // and will treat this token as an identifier.
+ if (getLang().CPlusPlus &&
+ CurScope->isCXXClassScope() &&
+ Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope) &&
+ NextToken().getKind() == tok::l_paren)
+ goto DoneWithDeclSpec;
+
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
TypeRep);
if (isInvalid)
@@ -607,6 +624,14 @@
case tok::kw_inline:
isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec);
break;
+
+ case tok::kw_virtual:
+ isInvalid = DS.SetFunctionSpecVirtual(Loc, PrevSpec);
+ break;
+
+ case tok::kw_explicit:
+ isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec);
+ break;
case tok::less:
// GCC ObjC supports types like "<SomeProtocol>" as a synonym for
@@ -1056,6 +1081,8 @@
// function-specifier
case tok::kw_inline:
+ case tok::kw_virtual:
+ case tok::kw_explicit:
// GNU typeof support.
case tok::kw_typeof:
@@ -1217,7 +1244,11 @@
/// parameter-type-list[opt] ')'
/// [C++] direct-declarator '(' parameter-declaration-clause ')'
/// cv-qualifier-seq[opt] exception-specification[opt]
-///
+/// [C++] declarator-id
+//
+// declarator-id: [C++ 8]
+// id-expression
+// '::'[opt] nested-name-specifier[opt] type-name
void Parser::ParseDirectDeclarator(Declarator &D) {
// Parse the first direct-declarator seen.
if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {