aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2010-01-15 15:39:40 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2010-01-15 15:39:40 +0000
commitee791dde723a2089c681d2ab6a9d4f96379d5f49 (patch)
treea6082d4d1d1e9ddaea09a6a04bb4a47da95d642d /lib/Parse
parentabe15e553e58165e7692c0d0842865c488ed7b45 (diff)
Notes
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/DeclSpec.cpp8
-rw-r--r--lib/Parse/ParseDecl.cpp178
-rw-r--r--lib/Parse/ParseDeclCXX.cpp58
-rw-r--r--lib/Parse/ParseExpr.cpp24
-rw-r--r--lib/Parse/ParseExprCXX.cpp52
-rw-r--r--lib/Parse/ParseObjc.cpp39
-rw-r--r--lib/Parse/ParseStmt.cpp8
-rw-r--r--lib/Parse/ParseTemplate.cpp3
-rw-r--r--lib/Parse/Parser.cpp6
9 files changed, 321 insertions, 55 deletions
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 4cd8fe887bb1..f52d8b98567a 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -36,6 +36,14 @@ void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
EndLocation = TemplateId->RAngleLoc;
}
+void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
+ assert(TemplateId && "NULL template-id annotation?");
+ Kind = IK_ConstructorTemplateId;
+ this->TemplateId = TemplateId;
+ StartLocation = TemplateId->TemplateNameLoc;
+ EndLocation = TemplateId->RAngleLoc;
+}
+
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index f429ac991d83..b5ba8acafc8d 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -356,7 +356,8 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
ParsingDeclSpec DS(*this);
if (Attr)
DS.AddAttributes(Attr);
- ParseDeclarationSpecifiers(DS);
+ ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
+ getDeclSpecContextFromDeclaratorContext(Context));
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
// declaration-specifiers init-declarator-list[opt] ';'
@@ -786,6 +787,20 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
return false;
}
+/// \brief Determine the declaration specifier context from the declarator
+/// context.
+///
+/// \param Context the declarator context, which is one of the
+/// Declarator::TheContext enumerator values.
+Parser::DeclSpecContext
+Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
+ if (Context == Declarator::MemberContext)
+ return DSC_class;
+ if (Context == Declarator::FileContext)
+ return DSC_top_level;
+ return DSC_normal;
+}
+
/// ParseDeclarationSpecifiers
/// declaration-specifiers: [C99 6.7]
/// storage-class-specifier declaration-specifiers[opt]
@@ -814,7 +829,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
AccessSpecifier AS,
DeclSpecContext DSContext) {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(CurScope);
+ Action::CodeCompletionContext CCC = Action::CCC_Namespace;
+ if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
+ CCC = DSContext == DSC_class? Action::CCC_MemberTemplate
+ : Action::CCC_Template;
+ else if (DSContext == DSC_class)
+ CCC = Action::CCC_Class;
+ else if (ObjCImpDecl)
+ CCC = Action::CCC_ObjCImplementation;
+
+ Actions.CodeCompleteOrdinaryName(CurScope, CCC);
ConsumeToken();
}
@@ -854,6 +878,47 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue())
->Kind == TNK_Type_template) {
// We have a qualified template-id, e.g., N::A<int>
+
+ // C++ [class.qual]p2:
+ // In a lookup in which the constructor is an acceptable lookup
+ // result and the nested-name-specifier nominates a class C:
+ //
+ // - if the name specified after the
+ // nested-name-specifier, when looked up in C, is the
+ // injected-class-name of C (Clause 9), or
+ //
+ // - if the name specified after the nested-name-specifier
+ // is the same as the identifier or the
+ // simple-template-id's template-name in the last
+ // component of the nested-name-specifier,
+ //
+ // the name is instead considered to name the constructor of
+ // class C.
+ //
+ // Thus, if the template-name is actually the constructor
+ // name, then the code is ill-formed; this interpretation is
+ // reinforced by the NAD status of core issue 635.
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue());
+ if (DSContext == DSC_top_level && TemplateId->Name &&
+ Actions.isCurrentClassName(*TemplateId->Name, CurScope, &SS)) {
+ if (isConstructorDeclarator()) {
+ // The user meant this to be an out-of-line constructor
+ // definition, but template arguments are not allowed
+ // there. Just allow this as a constructor; we'll
+ // complain about it later.
+ goto DoneWithDeclSpec;
+ }
+
+ // The user meant this to name a type, but it actually names
+ // a constructor with some extraneous template
+ // arguments. Complain, then parse it as a type as the user
+ // intended.
+ Diag(TemplateId->TemplateNameLoc,
+ diag::err_out_of_line_template_id_names_constructor)
+ << TemplateId->Name;
+ }
+
DS.getTypeSpecScope() = SS;
ConsumeToken(); // The C++ scope.
assert(Tok.is(tok::annot_template_id) &&
@@ -878,13 +943,23 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (Next.isNot(tok::identifier))
goto DoneWithDeclSpec;
- // If the next token is the name of the class type that the C++ scope
- // denotes, followed by a '(', then this is a constructor declaration.
- // We're done with the decl-specifiers.
- if (Actions.isCurrentClassName(*Next.getIdentifierInfo(),
- CurScope, &SS) &&
- GetLookAheadToken(2).is(tok::l_paren))
- goto DoneWithDeclSpec;
+ // If we're in a context where the identifier could be a class name,
+ // check whether this is a constructor declaration.
+ if (DSContext == DSC_top_level &&
+ Actions.isCurrentClassName(*Next.getIdentifierInfo(), CurScope,
+ &SS)) {
+ if (isConstructorDeclarator())
+ goto DoneWithDeclSpec;
+
+ // As noted in C++ [class.qual]p2 (cited above), when the name
+ // of the class is qualified in a context where it could name
+ // a constructor, its a constructor name. However, we've
+ // looked at the declarator, and the user probably meant this
+ // to be a type. Complain that it isn't supposed to be treated
+ // as a type, then proceed to parse it as a type.
+ Diag(Next.getLocation(), diag::err_out_of_line_type_names_constructor)
+ << Next.getIdentifierInfo();
+ }
TypeTy *TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(),
Next.getLocation(), CurScope, &SS);
@@ -965,16 +1040,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
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->isClassScope() ||
- (CurScope->isTemplateParamScope() &&
- CurScope->getParent()->isClassScope())) &&
+ // If we're in a context where the identifier could be a class name,
+ // check whether this is a constructor declaration.
+ if (getLang().CPlusPlus && DSContext == DSC_class &&
Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope) &&
- NextToken().getKind() == tok::l_paren)
+ isConstructorDeclarator())
goto DoneWithDeclSpec;
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
@@ -1017,6 +1087,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
goto DoneWithDeclSpec;
}
+ // If we're in a context where the template-id could be a
+ // constructor name or specialization, check whether this is a
+ // constructor declaration.
+ if (getLang().CPlusPlus && DSContext == DSC_class &&
+ Actions.isCurrentClassName(*TemplateId->Name, CurScope) &&
+ isConstructorDeclarator())
+ goto DoneWithDeclSpec;
+
// Turn the template-id annotation token into a type annotation
// token, then try again to parse it as a type-specifier.
AnnotateTemplateIdTokenAsType();
@@ -2082,6 +2160,48 @@ bool Parser::isDeclarationSpecifier() {
}
}
+bool Parser::isConstructorDeclarator() {
+ TentativeParsingAction TPA(*this);
+
+ // Parse the C++ scope specifier.
+ CXXScopeSpec SS;
+ ParseOptionalCXXScopeSpecifier(SS, 0, true);
+
+ // Parse the constructor name.
+ if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
+ // We already know that we have a constructor name; just consume
+ // the token.
+ ConsumeToken();
+ } else {
+ TPA.Revert();
+ return false;
+ }
+
+ // Current class name must be followed by a left parentheses.
+ if (Tok.isNot(tok::l_paren)) {
+ TPA.Revert();
+ return false;
+ }
+ ConsumeParen();
+
+ // A right parentheses or ellipsis signals that we have a constructor.
+ if (Tok.is(tok::r_paren) || Tok.is(tok::ellipsis)) {
+ TPA.Revert();
+ return true;
+ }
+
+ // If we need to, enter the specified scope.
+ DeclaratorScopeObj DeclScopeObj(*this, SS);
+ if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(CurScope, SS))
+ DeclScopeObj.EnterDeclaratorScope();
+
+ // Check whether the next token(s) are part of a declaration
+ // specifier, in which case we have the start of a parameter and,
+ // therefore, we know that this is a constructor.
+ bool IsConstructor = isDeclarationSpecifier();
+ TPA.Revert();
+ return IsConstructor;
+}
/// ParseTypeQualifierListOpt
/// type-qualifier-list: [C99 6.7.5]
@@ -2366,10 +2486,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) {
// We found something that indicates the start of an unqualified-id.
// Parse that unqualified-id.
+ bool AllowConstructorName
+ = ((D.getCXXScopeSpec().isSet() &&
+ D.getContext() == Declarator::FileContext) ||
+ (!D.getCXXScopeSpec().isSet() &&
+ D.getContext() == Declarator::MemberContext)) &&
+ !D.getDeclSpec().hasTypeSpecifier();
if (ParseUnqualifiedId(D.getCXXScopeSpec(),
/*EnteringContext=*/true,
/*AllowDestructorName=*/true,
- /*AllowConstructorName=*/!D.getDeclSpec().hasTypeSpecifier(),
+ AllowConstructorName,
/*ObjectType=*/0,
D.getName())) {
D.SetIdentifier(0, Tok.getLocation());
@@ -2396,6 +2522,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// direct-declarator: '(' attributes declarator ')'
// Example: 'char (*X)' or 'int (*XX)(void)'
ParseParenDeclarator(D);
+
+ // If the declarator was parenthesized, we entered the declarator
+ // scope when parsing the parenthesized declarator, then exited
+ // the scope already. Re-enter the scope, if we need to.
+ if (D.getCXXScopeSpec().isSet()) {
+ if (Actions.ShouldEnterDeclaratorScope(CurScope, D.getCXXScopeSpec()))
+ // Change the declaration context for name lookup, until this function
+ // is exited (and the declarator has been parsed).
+ DeclScopeObj.EnterDeclaratorScope();
+ }
} else if (D.mayOmitIdentifier()) {
// This could be something simple like "int" (in which case the declarator
// portion is empty), if an abstract-declarator is allowed.
@@ -3020,6 +3156,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
Token OpTok = Tok;
SourceLocation StartLoc = ConsumeToken();
+ const bool hasParens = Tok.is(tok::l_paren);
+
bool isCastExpr;
TypeTy *CastTy;
SourceRange CastRange;
@@ -3027,6 +3165,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
isCastExpr,
CastTy,
CastRange);
+ if (hasParens)
+ DS.setTypeofParensRange(CastRange);
if (CastRange.getEnd().isInvalid())
// FIXME: Not accurate, the range gets one token more than it should.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 265d0f3e849f..90040c54bfb1 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -468,7 +468,8 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
- if (TemplateId->Kind == TNK_Type_template) {
+ if (TemplateId->Kind == TNK_Type_template ||
+ TemplateId->Kind == TNK_Dependent_template_name) {
AnnotateTemplateIdTokenAsType(SS);
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
@@ -489,18 +490,57 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
return true;
}
+ IdentifierInfo *Id = Tok.getIdentifierInfo();
+ SourceLocation IdLoc = ConsumeToken();
+
+ if (Tok.is(tok::less)) {
+ // It looks the user intended to write a template-id here, but the
+ // template-name was wrong. Try to fix that.
+ TemplateNameKind TNK = TNK_Type_template;
+ TemplateTy Template;
+ if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, CurScope,
+ SS, Template, TNK)) {
+ Diag(IdLoc, diag::err_unknown_template_name)
+ << Id;
+ }
+
+ if (!Template)
+ return true;
+
+ // Form the template name
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(Id, IdLoc);
+
+ // Parse the full template-id, then turn it into a type.
+ if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName,
+ SourceLocation(), true))
+ return true;
+ if (TNK == TNK_Dependent_template_name)
+ AnnotateTemplateIdTokenAsType(SS);
+
+ // If we didn't end up with a typename token, there's nothing more we
+ // can do.
+ if (Tok.isNot(tok::annot_typename))
+ return true;
+
+ // Retrieve the type from the annotation token, consume that token, and
+ // return.
+ EndLocation = Tok.getAnnotationEndLoc();
+ TypeTy *Type = Tok.getAnnotationValue();
+ ConsumeToken();
+ return Type;
+ }
+
// We have an identifier; check whether it is actually a type.
- TypeTy *Type = Actions.getTypeName(*Tok.getIdentifierInfo(),
- Tok.getLocation(), CurScope, SS,
- true);
- if (!Type) {
- Diag(Tok, DestrExpected ? diag::err_destructor_class_name
+ TypeTy *Type = Actions.getTypeName(*Id, IdLoc, CurScope, SS, true);
+ if (!Type) {
+ Diag(IdLoc, DestrExpected ? diag::err_destructor_class_name
: diag::err_expected_class_name);
return true;
}
// Consume the identifier.
- EndLocation = ConsumeToken();
+ EndLocation = IdLoc;
return Type;
}
@@ -1527,12 +1567,12 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
- if (TemplateId->Kind == TNK_Type_template) {
+ if (TemplateId->Kind == TNK_Type_template ||
+ TemplateId->Kind == TNK_Dependent_template_name) {
AnnotateTemplateIdTokenAsType(&SS);
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
TemplateTypeTy = Tok.getAnnotationValue();
}
- // FIXME. May need to check for TNK_Dependent_template as well.
}
if (!TemplateTypeTy && Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_member_or_base_name);
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index bdbc67f782dc..669575c4f030 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -200,11 +200,6 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
/// expression ',' assignment-expression
///
Parser::OwningExprResult Parser::ParseExpression() {
- if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(CurScope);
- ConsumeToken();
- }
-
OwningExprResult LHS(ParseAssignmentExpression());
if (LHS.isInvalid()) return move(LHS);
@@ -248,6 +243,11 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
/// ParseAssignmentExpression - Parse an expr that doesn't include commas.
///
Parser::OwningExprResult Parser::ParseAssignmentExpression() {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression);
+ ConsumeToken();
+ }
+
if (Tok.is(tok::kw_throw))
return ParseThrowExpression();
@@ -616,9 +616,17 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// Turn a potentially qualified name into a annot_typename or
// annot_cxxscope if it would be valid. This handles things like x::y, etc.
if (getLang().CPlusPlus) {
- // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
- if (TryAnnotateTypeOrScopeToken())
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
+ // Avoid the unnecessary parse-time lookup in the common case
+ // where the syntax forbids a type.
+ const Token &Next = NextToken();
+ if (Next.is(tok::coloncolon) ||
+ (!ColonIsSacred && Next.is(tok::colon)) ||
+ Next.is(tok::less) ||
+ Next.is(tok::l_paren)) {
+ // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
+ if (TryAnnotateTypeOrScopeToken())
+ return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
+ }
}
// Consume the identifier so that we can see if it is followed by a '(' or
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index abd26d7d4905..ca50ef400092 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -585,6 +585,11 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
/// \returns true if there was a parsing, false otherwise.
bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
DeclPtrTy &DeclResult) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Condition);
+ ConsumeToken();
+ }
+
if (!isCXXConditionDeclaration()) {
ExprResult = ParseExpression(); // expression
DeclResult = DeclPtrTy();
@@ -1148,6 +1153,13 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
IdentifierInfo *Id = Tok.getIdentifierInfo();
SourceLocation IdLoc = ConsumeToken();
+ if (!getLang().CPlusPlus) {
+ // If we're not in C++, only identifiers matter. Record the
+ // identifier and return.
+ Result.setIdentifier(Id, IdLoc);
+ return false;
+ }
+
if (AllowConstructorName &&
Actions.isCurrentClassName(*Id, CurScope, &SS)) {
// We have parsed a constructor name.
@@ -1170,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;
}
@@ -1202,7 +1243,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
return false;
}
- if ((AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) {
+ if (getLang().CPlusPlus &&
+ (AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) {
// C++ [expr.unary.op]p10:
// There is an ambiguity in the unary-expression ~X(), where X is a
// class-name. The ambiguity is resolved in favor of treating ~ as a
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 9904a2ca85dc..5e2363535320 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -309,7 +309,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
llvm::SmallVector<DeclGroupPtrTy, 8> allTUVariables;
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
- SourceLocation AtEndLoc;
+ SourceRange AtEnd;
while (1) {
// If this is a method prototype, parse it.
@@ -334,6 +334,14 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
if (Tok.is(tok::eof))
break;
+ // Code completion within an Objective-C interface.
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(CurScope,
+ ObjCImpDecl? Action::CCC_ObjCImplementation
+ : Action::CCC_ObjCInterface);
+ ConsumeToken();
+ }
+
// If we don't have an @ directive, parse it as a function definition.
if (Tok.isNot(tok::at)) {
// The code below does not consume '}'s because it is afraid of eating the
@@ -359,7 +367,8 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
if (DirectiveKind == tok::objc_end) { // @end -> terminate list
- AtEndLoc = AtLoc;
+ AtEnd.setBegin(AtLoc);
+ AtEnd.setEnd(Tok.getLocation());
break;
}
@@ -422,7 +431,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
// Insert collected methods declarations into the @interface object.
// This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
- Actions.ActOnAtEnd(AtEndLoc, interfaceDecl,
+ Actions.ActOnAtEnd(AtEnd, interfaceDecl,
allMethods.data(), allMethods.size(),
allProperties.data(), allProperties.size(),
allTUVariables.data(), allTUVariables.size());
@@ -964,6 +973,12 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
// Set the default visibility to private.
if (Tok.is(tok::at)) { // parse objc-visibility-spec
ConsumeToken(); // eat the @ sign
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCAtVisibility(CurScope);
+ ConsumeToken();
+ }
+
switch (Tok.getObjCKeywordID()) {
case tok::objc_private:
case tok::objc_public:
@@ -978,6 +993,12 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
}
}
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(CurScope,
+ Action::CCC_ObjCInstanceVariableList);
+ ConsumeToken();
+ }
+
struct ObjCIvarCallback : FieldCallback {
Parser &P;
DeclPtrTy IDecl;
@@ -1197,18 +1218,20 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
return DeclPtrTy();
}
-Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
+Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
assert(Tok.isObjCAtKeyword(tok::objc_end) &&
"ParseObjCAtEndDeclaration(): Expected @end");
DeclPtrTy Result = ObjCImpDecl;
ConsumeToken(); // the "end" identifier
if (ObjCImpDecl) {
- Actions.ActOnAtEnd(atLoc, ObjCImpDecl);
+ Actions.ActOnAtEnd(atEnd, ObjCImpDecl);
ObjCImpDecl = DeclPtrTy();
PendingObjCImpDecl.pop_back();
}
- else
- Diag(atLoc, diag::warn_expected_implementation); // missing @implementation
+ else {
+ // missing @implementation
+ Diag(atEnd.getBegin(), diag::warn_expected_implementation);
+ }
return Result;
}
@@ -1216,7 +1239,7 @@ Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() {
if (PendingObjCImpDecl.empty())
return Actions.ConvertDeclToDeclGroup(DeclPtrTy());
DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val();
- Actions.ActOnAtEnd(SourceLocation(), ImpDecl);
+ Actions.ActOnAtEnd(SourceRange(), ImpDecl);
return Actions.ConvertDeclToDeclGroup(ImpDecl);
}
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 9085b8713dfd..21e960aa8173 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -95,7 +95,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
}
case tok::code_completion:
- Actions.CodeCompleteOrdinaryName(CurScope);
+ Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Statement);
ConsumeToken();
return ParseStatementOrDeclaration(OnlyStatement);
@@ -955,7 +955,9 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
DeclPtrTy SecondVar;
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(CurScope);
+ Actions.CodeCompleteOrdinaryName(CurScope,
+ C99orCXXorObjC? Action::CCC_ForInit
+ : Action::CCC_Expression);
ConsumeToken();
}
@@ -1182,7 +1184,7 @@ Parser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
return Actions.ActOnAsmStmt(Tok.getLocation(), true, true, 0, 0, Names.data(),
move_arg(Constraints), move_arg(Exprs),
move(AsmString), move_arg(Clobbers),
- Tok.getLocation());
+ Tok.getLocation(), true);
}
/// ParseAsmStatement - Parse a GNU extended asm statement.
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 8b8af99ec6d7..797c1dfe3e6a 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -196,7 +196,8 @@ Parser::ParseSingleDeclarationAfterTemplate(
if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
DS.AddAttributes(ParseCXX0XAttributes().AttrList);
- ParseDeclarationSpecifiers(DS, TemplateInfo, AS);
+ ParseDeclarationSpecifiers(DS, TemplateInfo, AS,
+ getDeclSpecContextFromDeclaratorContext(Context));
if (Tok.is(tok::semi)) {
DeclEnd = ConsumeToken();
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 52c0153bfad8..0aecac975741 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -455,7 +455,9 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr)
SingleDecl = ParseObjCMethodDefinition();
break;
case tok::code_completion:
- Actions.CodeCompleteOrdinaryName(CurScope);
+ Actions.CodeCompleteOrdinaryName(CurScope,
+ ObjCImpDecl? Action::CCC_ObjCImplementation
+ : Action::CCC_Namespace);
ConsumeToken();
return ParseExternalDeclaration(Attr);
case tok::kw_using:
@@ -541,7 +543,7 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
if (Attr)
DS.AddAttributes(Attr);
- ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS);
+ ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level);
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
// declaration-specifiers init-declarator-list[opt] ';'