summaryrefslogtreecommitdiffstats
path: root/lib/Parse
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/DeclSpec.cpp12
-rw-r--r--lib/Parse/ExtensionRAIIObject.h40
-rw-r--r--lib/Parse/MinimalAction.cpp1
-rw-r--r--lib/Parse/ParseDecl.cpp36
-rw-r--r--lib/Parse/ParseDeclCXX.cpp76
-rw-r--r--lib/Parse/ParseExpr.cpp18
-rw-r--r--lib/Parse/ParseExprCXX.cpp21
-rw-r--r--lib/Parse/ParseObjc.cpp155
-rw-r--r--lib/Parse/ParseStmt.cpp24
-rw-r--r--lib/Parse/ParseTemplate.cpp3
-rw-r--r--lib/Parse/Parser.cpp37
-rw-r--r--lib/Parse/RAIIObjectsForParser.h85
12 files changed, 351 insertions, 157 deletions
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index f00f33f..4cd8fe8 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -137,7 +137,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) {
case DeclSpec::SCS_private_extern: return "__private_extern__";
case DeclSpec::SCS_mutable: return "mutable";
}
- llvm::llvm_unreachable("Unknown typespec!");
+ llvm_unreachable("Unknown typespec!");
}
const char *DeclSpec::getSpecifierName(TSW W) {
@@ -147,7 +147,7 @@ const char *DeclSpec::getSpecifierName(TSW W) {
case TSW_long: return "long";
case TSW_longlong: return "long long";
}
- llvm::llvm_unreachable("Unknown typespec!");
+ llvm_unreachable("Unknown typespec!");
}
const char *DeclSpec::getSpecifierName(TSC C) {
@@ -156,7 +156,7 @@ const char *DeclSpec::getSpecifierName(TSC C) {
case TSC_imaginary: return "imaginary";
case TSC_complex: return "complex";
}
- llvm::llvm_unreachable("Unknown typespec!");
+ llvm_unreachable("Unknown typespec!");
}
@@ -166,7 +166,7 @@ const char *DeclSpec::getSpecifierName(TSS S) {
case TSS_signed: return "signed";
case TSS_unsigned: return "unsigned";
}
- llvm::llvm_unreachable("Unknown typespec!");
+ llvm_unreachable("Unknown typespec!");
}
const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
@@ -195,7 +195,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
case DeclSpec::TST_decltype: return "(decltype)";
case DeclSpec::TST_error: return "(error)";
}
- llvm::llvm_unreachable("Unknown typespec!");
+ llvm_unreachable("Unknown typespec!");
}
const char *DeclSpec::getSpecifierName(TQ T) {
@@ -205,7 +205,7 @@ const char *DeclSpec::getSpecifierName(TQ T) {
case DeclSpec::TQ_restrict: return "restrict";
case DeclSpec::TQ_volatile: return "volatile";
}
- llvm::llvm_unreachable("Unknown typespec!");
+ llvm_unreachable("Unknown typespec!");
}
bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
diff --git a/lib/Parse/ExtensionRAIIObject.h b/lib/Parse/ExtensionRAIIObject.h
deleted file mode 100644
index cc7c8e2..0000000
--- a/lib/Parse/ExtensionRAIIObject.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===--- ExtensionRAIIObject.h - Use RAII for __extension__ -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines and implements the ExtensionRAIIObject class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_PARSE_EXTENSION_RAII_OBJECT_H
-#define LLVM_CLANG_PARSE_EXTENSION_RAII_OBJECT_H
-
-#include "clang/Parse/ParseDiagnostic.h"
-
-namespace clang {
-
- /// ExtensionRAIIObject - This saves the state of extension warnings when
- /// constructed and disables them. When destructed, it restores them back to
- /// the way they used to be. This is used to handle __extension__ in the
- /// parser.
- class ExtensionRAIIObject {
- void operator=(const ExtensionRAIIObject &); // DO NOT IMPLEMENT
- ExtensionRAIIObject(const ExtensionRAIIObject&); // DO NOT IMPLEMENT
- Diagnostic &Diags;
- public:
- ExtensionRAIIObject(Diagnostic &diags) : Diags(diags) {
- Diags.IncrementAllExtensionsSilenced();
- }
-
- ~ExtensionRAIIObject() {
- Diags.DecrementAllExtensionsSilenced();
- }
- };
-}
-
-#endif
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index aa0b89b..8b207fa 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -45,6 +45,7 @@ Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope,
// Defined out-of-line here because of dependency on AttributeList
Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
AccessSpecifier AS,
+ bool HasUsingKeyword,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
UnqualifiedId &Name,
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index b13dc73..5dd78f7 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1,4 +1,3 @@
-
//===--- ParseDecl.cpp - Declaration Parsing ------------------------------===//
//
// The LLVM Compiler Infrastructure
@@ -16,7 +15,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Scope.h"
#include "clang/Parse/Template.h"
-#include "ExtensionRAIIObject.h"
+#include "RAIIObjectsForParser.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
@@ -825,14 +824,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (DS.hasTypeSpecifier())
goto DoneWithDeclSpec;
+ CXXScopeSpec SS;
+ SS.setScopeRep(Tok.getAnnotationValue());
+ SS.setRange(Tok.getAnnotationRange());
+
// We are looking for a qualified typename.
Token Next = NextToken();
if (Next.is(tok::annot_template_id) &&
static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue())
->Kind == TNK_Type_template) {
// We have a qualified template-id, e.g., N::A<int>
- CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
+ DS.getTypeSpecScope() = SS;
+ ConsumeToken(); // The C++ scope.
assert(Tok.is(tok::annot_template_id) &&
"ParseOptionalCXXScopeSpecifier not working");
AnnotateTemplateIdTokenAsType(&SS);
@@ -840,8 +843,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
}
if (Next.is(tok::annot_typename)) {
- // FIXME: is this scope-specifier getting dropped?
- ConsumeToken(); // the scope-specifier
+ DS.getTypeSpecScope() = SS;
+ ConsumeToken(); // The C++ scope.
if (Tok.getAnnotationValue())
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc,
PrevSpec, DiagID,
@@ -855,10 +858,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (Next.isNot(tok::identifier))
goto DoneWithDeclSpec;
- CXXScopeSpec SS;
- SS.setScopeRep(Tok.getAnnotationValue());
- SS.setRange(Tok.getAnnotationRange());
-
// 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.
@@ -880,6 +879,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
goto DoneWithDeclSpec;
}
+ DS.getTypeSpecScope() = SS;
ConsumeToken(); // The C++ scope.
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
@@ -1545,8 +1545,11 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
/// struct-declarator: declarator
/// struct-declarator: declarator[opt] ':' constant-expression
- if (Tok.isNot(tok::colon))
+ if (Tok.isNot(tok::colon)) {
+ // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
+ ColonProtectionRAIIObject X(*this);
ParseDeclarator(DeclaratorInfo.D);
+ }
if (Tok.is(tok::colon)) {
ConsumeToken();
@@ -1616,7 +1619,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
// Check for extraneous top-level semicolon.
if (Tok.is(tok::semi)) {
Diag(Tok, diag::ext_extra_struct_semi)
- << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
+ << CodeModificationHint::CreateRemoval(Tok.getLocation());
ConsumeToken();
continue;
}
@@ -1841,7 +1844,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) {
!(getLang().C99 || getLang().CPlusPlus0x))
Diag(CommaLoc, diag::ext_enumerator_list_comma)
<< getLang().CPlusPlus
- << CodeModificationHint::CreateRemoval((SourceRange(CommaLoc)));
+ << CodeModificationHint::CreateRemoval(CommaLoc);
}
// Eat the }.
@@ -2333,9 +2336,10 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
true);
if (afterCXXScope) {
- // Change the declaration context for name lookup, until this function
- // is exited (and the declarator has been parsed).
- DeclScopeObj.EnterDeclaratorScope();
+ 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();
}
if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 505a4d8..d4d19a0 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -17,7 +17,7 @@
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
#include "clang/Parse/Template.h"
-#include "ExtensionRAIIObject.h"
+#include "RAIIObjectsForParser.h"
using namespace clang;
/// ParseNamespace - We know that the current token is a namespace keyword. This
@@ -161,7 +161,8 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
/// 'extern' string-literal '{' declaration-seq[opt] '}'
/// 'extern' string-literal declaration
///
-Parser::DeclPtrTy Parser::ParseLinkage(unsigned Context) {
+Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
+ unsigned Context) {
assert(Tok.is(tok::string_literal) && "Not a string literal!");
llvm::SmallVector<char, 8> LangBuffer;
// LangBuffer is guaranteed to be big enough.
@@ -185,7 +186,7 @@ Parser::DeclPtrTy Parser::ParseLinkage(unsigned Context) {
}
if (Tok.isNot(tok::l_brace)) {
- ParseDeclarationOrFunctionDefinition(Attr.AttrList);
+ ParseDeclarationOrFunctionDefinition(DS, Attr.AttrList);
return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec,
SourceLocation());
}
@@ -356,7 +357,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
AttrList ? "attributes list" : "using declaration",
tok::semi);
- return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, Name,
+ return Actions.ActOnUsingDeclaration(CurScope, AS, true, UsingLoc, SS, Name,
AttrList, IsTypeName, TypenameLoc);
}
@@ -599,11 +600,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
}
// Parse the (optional) nested-name-specifier.
- CXXScopeSpec SS;
- if (getLang().CPlusPlus &&
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true))
- if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
- Diag(Tok, diag::err_expected_ident);
+ CXXScopeSpec &SS = DS.getTypeSpecScope();
+ if (getLang().CPlusPlus) {
+ // "FOO : BAR" is not a potential typo for "FOO::BAR".
+ ColonProtectionRAIIObject X(*this);
+
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true))
+ if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
+ Diag(Tok, diag::err_expected_ident);
+ }
TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
@@ -954,7 +959,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
if (IsVirtual) {
// Complain about duplicate 'virtual'
Diag(VirtualLoc, diag::err_dup_virtual)
- << CodeModificationHint::CreateRemoval(SourceRange(VirtualLoc));
+ << CodeModificationHint::CreateRemoval(VirtualLoc);
}
IsVirtual = true;
@@ -1060,6 +1065,46 @@ void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
///
void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
const ParsedTemplateInfo &TemplateInfo) {
+ // Access declarations.
+ if (!TemplateInfo.Kind &&
+ (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
+ TryAnnotateCXXScopeToken() &&
+ Tok.is(tok::annot_cxxscope)) {
+ bool isAccessDecl = false;
+ if (NextToken().is(tok::identifier))
+ isAccessDecl = GetLookAheadToken(2).is(tok::semi);
+ else
+ isAccessDecl = NextToken().is(tok::kw_operator);
+
+ if (isAccessDecl) {
+ // Collect the scope specifier token we annotated earlier.
+ CXXScopeSpec SS;
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType*/ 0, false);
+
+ // Try to parse an unqualified-id.
+ UnqualifiedId Name;
+ if (ParseUnqualifiedId(SS, false, true, true, /*ObjectType*/ 0, Name)) {
+ SkipUntil(tok::semi);
+ return;
+ }
+
+ // TODO: recover from mistakenly-qualified operator declarations.
+ if (ExpectAndConsume(tok::semi,
+ diag::err_expected_semi_after,
+ "access declaration",
+ tok::semi))
+ return;
+
+ Actions.ActOnUsingDeclaration(CurScope, AS,
+ false, SourceLocation(),
+ SS, Name,
+ /* AttrList */ 0,
+ /* IsTypeName */ false,
+ SourceLocation());
+ return;
+ }
+ }
+
// static_assert-declaration
if (Tok.is(tok::kw_static_assert)) {
// FIXME: Check for templates
@@ -1085,11 +1130,13 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
return ParseCXXClassMemberDeclaration(AS, TemplateInfo);
}
+ // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
+ ColonProtectionRAIIObject X(*this);
+
CXX0XAttributeList AttrList;
// Optional C++0x attribute-specifier
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
AttrList = ParseCXX0XAttributes();
- }
if (Tok.is(tok::kw_using)) {
// FIXME: Check for template aliases
@@ -1133,6 +1180,9 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
if (Tok.isNot(tok::colon)) {
+ // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
+ ColonProtectionRAIIObject X(*this);
+
// Parse the first declarator.
ParseDeclarator(DeclaratorInfo);
// Error parsing the declarator?
@@ -1349,7 +1399,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
// Check for extraneous top-level semicolon.
if (Tok.is(tok::semi)) {
Diag(Tok, diag::ext_extra_struct_semi)
- << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
+ << CodeModificationHint::CreateRemoval(Tok.getLocation());
ConsumeToken();
continue;
}
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index f780cf1..bdbc67f 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -23,7 +23,7 @@
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
#include "clang/Basic/PrettyStackTrace.h"
-#include "ExtensionRAIIObject.h"
+#include "RAIIObjectsForParser.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;
@@ -317,6 +317,9 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
OwningExprResult TernaryMiddle(Actions, true);
if (NextTokPrec == prec::Conditional) {
if (Tok.isNot(tok::colon)) {
+ // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
+ ColonProtectionRAIIObject X(*this);
+
// Handle this production specially:
// logical-OR-expression '?' expression ':' conditional-expression
// In particular, the RHS of the '?' is 'expression', not
@@ -562,9 +565,15 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
TypeTy *CastTy;
SourceLocation LParenLoc = Tok.getLocation();
SourceLocation RParenLoc;
- Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
- TypeOfCast, CastTy, RParenLoc);
- if (Res.isInvalid()) return move(Res);
+
+ {
+ // The inside of the parens don't need to be a colon protected scope.
+ ColonProtectionRAIIObject X(*this, false);
+
+ Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
+ TypeOfCast, CastTy, RParenLoc);
+ if (Res.isInvalid()) return move(Res);
+ }
switch (ParenExprType) {
case SimpleExpr: break; // Nothing else to do.
@@ -826,6 +835,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___is_empty:
case tok::kw___is_polymorphic:
case tok::kw___is_abstract:
+ case tok::kw___is_literal:
case tok::kw___has_trivial_constructor:
case tok::kw___has_trivial_copy:
case tok::kw___has_trivial_assign:
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 52003e6..abd26d7 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -214,11 +214,29 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// namespace-name '::'
// nested-name-specifier identifier '::'
Token Next = NextToken();
+
+ // If we get foo:bar, this is almost certainly a typo for foo::bar. Recover
+ // and emit a fixit hint for it.
+ if (Next.is(tok::colon) && !ColonIsSacred &&
+ Actions.IsInvalidUnlessNestedName(CurScope, SS, II, ObjectType,
+ EnteringContext) &&
+ // If the token after the colon isn't an identifier, it's still an
+ // error, but they probably meant something else strange so don't
+ // recover like this.
+ PP.LookAhead(1).is(tok::identifier)) {
+ Diag(Next, diag::err_unexected_colon_in_nested_name_spec)
+ << CodeModificationHint::CreateReplacement(Next.getLocation(), "::");
+
+ // Recover as if the user wrote '::'.
+ Next.setKind(tok::coloncolon);
+ }
+
if (Next.is(tok::coloncolon)) {
// We have an identifier followed by a '::'. Lookup this name
// as the name in a nested-name-specifier.
SourceLocation IdLoc = ConsumeToken();
- assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
+ assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) &&
+ "NextToken() not working properly!");
SourceLocation CCLoc = ConsumeToken();
if (!HasScopeSpecifier) {
@@ -1459,6 +1477,7 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
case tok::kw___is_pod: return UTT_IsPOD;
case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
case tok::kw___is_union: return UTT_IsUnion;
+ case tok::kw___is_literal: return UTT_IsLiteral;
}
}
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 295625a..2c53847 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -30,6 +30,11 @@ using namespace clang;
Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
SourceLocation AtLoc = ConsumeToken(); // the "@"
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, false);
+ ConsumeToken();
+ }
+
switch (Tok.getObjCKeywordID()) {
case tok::objc_class:
return ParseObjCAtClassDeclaration(AtLoc);
@@ -228,6 +233,63 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
return ClsType;
}
+/// The Objective-C property callback. This should be defined where
+/// it's used, but instead it's been lifted to here to support VS2005.
+struct Parser::ObjCPropertyCallback : FieldCallback {
+ Parser &P;
+ DeclPtrTy IDecl;
+ llvm::SmallVectorImpl<DeclPtrTy> &Props;
+ ObjCDeclSpec &OCDS;
+ SourceLocation AtLoc;
+ tok::ObjCKeywordKind MethodImplKind;
+
+ ObjCPropertyCallback(Parser &P, DeclPtrTy IDecl,
+ llvm::SmallVectorImpl<DeclPtrTy> &Props,
+ ObjCDeclSpec &OCDS, SourceLocation AtLoc,
+ tok::ObjCKeywordKind MethodImplKind) :
+ P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc),
+ MethodImplKind(MethodImplKind) {
+ }
+
+ DeclPtrTy invoke(FieldDeclarator &FD) {
+ if (FD.D.getIdentifier() == 0) {
+ P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
+ << FD.D.getSourceRange();
+ return DeclPtrTy();
+ }
+ if (FD.BitfieldSize) {
+ P.Diag(AtLoc, diag::err_objc_property_bitfield)
+ << FD.D.getSourceRange();
+ return DeclPtrTy();
+ }
+
+ // Install the property declarator into interfaceDecl.
+ IdentifierInfo *SelName =
+ OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
+
+ Selector GetterSel =
+ P.PP.getSelectorTable().getNullarySelector(SelName);
+ IdentifierInfo *SetterName = OCDS.getSetterName();
+ Selector SetterSel;
+ if (SetterName)
+ SetterSel = P.PP.getSelectorTable().getSelector(1, &SetterName);
+ else
+ SetterSel = SelectorTable::constructSetterName(P.PP.getIdentifierTable(),
+ P.PP.getSelectorTable(),
+ FD.D.getIdentifier());
+ bool isOverridingProperty = false;
+ DeclPtrTy Property =
+ P.Actions.ActOnProperty(P.CurScope, AtLoc, FD, OCDS,
+ GetterSel, SetterSel, IDecl,
+ &isOverridingProperty,
+ MethodImplKind);
+ if (!isOverridingProperty)
+ Props.push_back(Property);
+
+ return Property;
+ }
+};
+
/// objc-interface-decl-list:
/// empty
/// objc-interface-decl-list objc-property-decl [OBJC2]
@@ -288,6 +350,12 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
// Otherwise, we have an @ directive, eat the @.
SourceLocation AtLoc = ConsumeToken(); // the "@"
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
+ ConsumeToken();
+ break;
+ }
+
tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
if (DirectiveKind == tok::objc_end) { // @end -> terminate list
@@ -329,61 +397,8 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
ParseObjCPropertyAttribute(OCDS, interfaceDecl,
allMethods.data(), allMethods.size());
- struct ObjCPropertyCallback : FieldCallback {
- Parser &P;
- DeclPtrTy IDecl;
- llvm::SmallVectorImpl<DeclPtrTy> &Props;
- ObjCDeclSpec &OCDS;
- SourceLocation AtLoc;
- tok::ObjCKeywordKind MethodImplKind;
-
- ObjCPropertyCallback(Parser &P, DeclPtrTy IDecl,
- llvm::SmallVectorImpl<DeclPtrTy> &Props,
- ObjCDeclSpec &OCDS, SourceLocation AtLoc,
- tok::ObjCKeywordKind MethodImplKind) :
- P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc),
- MethodImplKind(MethodImplKind) {
- }
-
- DeclPtrTy invoke(FieldDeclarator &FD) {
- if (FD.D.getIdentifier() == 0) {
- P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
- << FD.D.getSourceRange();
- return DeclPtrTy();
- }
- if (FD.BitfieldSize) {
- P.Diag(AtLoc, diag::err_objc_property_bitfield)
- << FD.D.getSourceRange();
- return DeclPtrTy();
- }
-
- // Install the property declarator into interfaceDecl.
- IdentifierInfo *SelName =
- OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
-
- Selector GetterSel =
- P.PP.getSelectorTable().getNullarySelector(SelName);
- IdentifierInfo *SetterName = OCDS.getSetterName();
- Selector SetterSel;
- if (SetterName)
- SetterSel = P.PP.getSelectorTable().getSelector(1, &SetterName);
- else
- SetterSel = SelectorTable::constructSetterName(P.PP.getIdentifierTable(),
- P.PP.getSelectorTable(),
- FD.D.getIdentifier());
- bool isOverridingProperty = false;
- DeclPtrTy Property =
- P.Actions.ActOnProperty(P.CurScope, AtLoc, FD, OCDS,
- GetterSel, SetterSel, IDecl,
- &isOverridingProperty,
- MethodImplKind);
- if (!isOverridingProperty)
- Props.push_back(Property);
-
- return Property;
- }
- } Callback(*this, interfaceDecl, allProperties,
- OCDS, AtLoc, MethodImplKind);
+ ObjCPropertyCallback Callback(*this, interfaceDecl, allProperties,
+ OCDS, AtLoc, MethodImplKind);
// Parse all the comma separated declarators.
DeclSpec DS;
@@ -397,7 +412,10 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
// We break out of the big loop in two cases: when we see @end or when we see
// EOF. In the former case, eat the @end. In the later case, emit an error.
- if (Tok.isObjCAtKeyword(tok::objc_end))
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
+ ConsumeToken();
+ } else if (Tok.isObjCAtKeyword(tok::objc_end))
ConsumeToken(); // the "end" identifier
else
Diag(Tok, diag::err_objc_missing_end);
@@ -938,7 +956,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
// Check for extraneous top-level semicolon.
if (Tok.is(tok::semi)) {
Diag(Tok, diag::ext_extra_struct_semi)
- << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
+ << CodeModificationHint::CreateRemoval(Tok.getLocation());
ConsumeToken();
continue;
}
@@ -1503,7 +1521,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
if (Tok.is(tok::semi)) {
if (ObjCImpDecl) {
Diag(Tok, diag::warn_semicolon_before_method_body)
- << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
+ << CodeModificationHint::CreateRemoval(Tok.getLocation());
}
ConsumeToken();
}
@@ -1545,12 +1563,21 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
}
Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
- if (Tok.isObjCAtKeyword(tok::objc_try)) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCAtStatement(CurScope);
+ ConsumeToken();
+ return StmtError();
+ }
+
+ if (Tok.isObjCAtKeyword(tok::objc_try))
return ParseObjCTryStmt(AtLoc);
- } else if (Tok.isObjCAtKeyword(tok::objc_throw))
+
+ if (Tok.isObjCAtKeyword(tok::objc_throw))
return ParseObjCThrowStmt(AtLoc);
- else if (Tok.isObjCAtKeyword(tok::objc_synchronized))
+
+ if (Tok.isObjCAtKeyword(tok::objc_synchronized))
return ParseObjCSynchronizedStmt(AtLoc);
+
OwningExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
if (Res.isInvalid()) {
// If the expression is invalid, skip ahead to the next semicolon. Not
@@ -1559,6 +1586,7 @@ Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
SkipUntil(tok::semi);
return StmtError();
}
+
// Otherwise, eat the semicolon.
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
return Actions.ActOnExprStmt(Actions.FullExpr(Res));
@@ -1566,6 +1594,11 @@ Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
switch (Tok.getKind()) {
+ case tok::code_completion:
+ Actions.CodeCompleteObjCAtExpression(CurScope);
+ ConsumeToken();
+ return ExprError();
+
case tok::string_literal: // primary-expression: string-literal
case tok::wide_string_literal:
return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index c87010e..a2ac646 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -13,7 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Parser.h"
-#include "ExtensionRAIIObject.h"
+#include "RAIIObjectsForParser.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
#include "clang/Basic/Diagnostic.h"
@@ -279,6 +279,11 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
ConsumeToken();
}
+ /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
+ /// Disable this form of error recovery while we're parsing the case
+ /// expression.
+ ColonProtectionRAIIObject ColonProtection(*this);
+
OwningExprResult LHS(ParseConstantExpression());
if (LHS.isInvalid()) {
SkipUntil(tok::colon);
@@ -298,6 +303,8 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
return StmtError();
}
}
+
+ ColonProtection.restore();
if (Tok.isNot(tok::colon)) {
Diag(Tok, diag::err_expected_colon_after) << "'case'";
@@ -1162,7 +1169,20 @@ Parser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) &&
Tok.isNot(tok::eof));
}
- return Actions.ActOnNullStmt(Tok.getLocation());
+ llvm::SmallVector<std::string, 4> Names;
+ Token t;
+ t.setKind(tok::string_literal);
+ t.setLiteralData("\"FIXME: not done\"");
+ t.clearFlag(Token::NeedsCleaning);
+ t.setLength(17);
+ OwningExprResult AsmString(Actions.ActOnStringLiteral(&t, 1));
+ ExprVector Constraints(Actions);
+ ExprVector Exprs(Actions);
+ ExprVector Clobbers(Actions);
+ return Actions.ActOnAsmStmt(Tok.getLocation(), true, true, 0, 0, Names.data(),
+ move_arg(Constraints), move_arg(Exprs),
+ move(AsmString), move_arg(Clobbers),
+ Tok.getLocation());
}
/// ParseAsmStatement - Parse a GNU extended asm statement.
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 0dbf37c..cc28541 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -16,6 +16,7 @@
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
#include "clang/Parse/Template.h"
+#include "RAIIObjectsForParser.h"
using namespace clang;
/// \brief Parse a template declaration, explicit instantiation, or
@@ -522,7 +523,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
if (Default.isInvalid()) {
Diag(Tok.getLocation(),
diag::err_default_template_template_parameter_not_template);
- static tok::TokenKind EndToks[] = {
+ static const tok::TokenKind EndToks[] = {
tok::comma, tok::greater, tok::greatergreater
};
SkipUntil(EndToks, 3, true, true);
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index e321564..a864e7c 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -17,7 +17,7 @@
#include "clang/Parse/Scope.h"
#include "clang/Parse/Template.h"
#include "llvm/Support/raw_ostream.h"
-#include "ExtensionRAIIObject.h"
+#include "RAIIObjectsForParser.h"
#include "ParsePragma.h"
using namespace clang;
@@ -36,7 +36,8 @@ public:
Parser::Parser(Preprocessor &pp, Action &actions)
: CrashInfo(*this), PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
- GreaterThanIsOperator(true), TemplateParameterDepth(0) {
+ GreaterThanIsOperator(true), ColonIsSacred(false),
+ TemplateParameterDepth(0) {
Tok.setKind(tok::eof);
CurScope = 0;
NumCachedScopes = 0;
@@ -405,7 +406,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr)
case tok::semi:
if (!getLang().CPlusPlus0x)
Diag(Tok, diag::ext_top_level_semi)
- << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
+ << CodeModificationHint::CreateRemoval(Tok.getLocation());
ConsumeToken();
// TODO: Invoke action for top-level semicolon.
@@ -507,12 +508,13 @@ bool Parser::isDeclarationAfterDeclarator() {
/// \brief Determine whether the current token, if it occurs after a
/// declarator, indicates the start of a function definition.
bool Parser::isStartOfFunctionDefinition() {
- return Tok.is(tok::l_brace) || // int X() {}
- (!getLang().CPlusPlus &&
- isDeclarationSpecifier()) || // int X(f) int f; {}
- (getLang().CPlusPlus &&
- (Tok.is(tok::colon) || // X() : Base() {} (used for ctors)
- Tok.is(tok::kw_try))); // X() try { ... }
+ if (Tok.is(tok::l_brace)) // int X() {}
+ return true;
+
+ if (!getLang().CPlusPlus)
+ return isDeclarationSpecifier(); // int X(f) int f; {}
+ return Tok.is(tok::colon) || // X() : Base() {} (used for ctors)
+ Tok.is(tok::kw_try); // X() try { ... }
}
/// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or
@@ -532,10 +534,10 @@ bool Parser::isStartOfFunctionDefinition() {
/// [OMP] threadprivate-directive [TODO]
///
Parser::DeclGroupPtrTy
-Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
+Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
+ AttributeList *Attr,
AccessSpecifier AS) {
// Parse the common declaration-specifiers piece.
- ParsingDeclSpec DS(*this);
if (Attr)
DS.AddAttributes(Attr);
@@ -584,13 +586,20 @@ Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
DS.abort();
- DeclPtrTy TheDecl = ParseLinkage(Declarator::FileContext);
+ DeclPtrTy TheDecl = ParseLinkage(DS, Declarator::FileContext);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
return ParseDeclGroup(DS, Declarator::FileContext, true);
}
+Parser::DeclGroupPtrTy
+Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
+ AccessSpecifier AS) {
+ ParsingDeclSpec DS(*this);
+ return ParseDeclarationOrFunctionDefinition(DS, Attr, AS);
+}
+
/// ParseFunctionDefinition - We parsed and verified that the specified
/// Declarator is well formed. If this is a K&R-style function, read the
/// parameters declaration-list, then start the compound-statement.
@@ -1029,7 +1038,9 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
CXXScopeSpec SS;
if (!ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext))
- return Tok.is(tok::annot_template_id);
+ // If the token left behind is not an identifier, we either had an error or
+ // successfully turned it into an annotation token.
+ return Tok.isNot(tok::identifier);
// Push the current token back into the token stream (or revert it if it is
// cached) and use an annotation scope token for current token.
diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h
new file mode 100644
index 0000000..06bbbc2
--- /dev/null
+++ b/lib/Parse/RAIIObjectsForParser.h
@@ -0,0 +1,85 @@
+//===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines and implements the some simple RAII objects that are used
+// by the parser to manage bits in recursion.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H
+#define LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H
+
+#include "clang/Parse/ParseDiagnostic.h"
+
+namespace clang {
+ // TODO: move ParsingDeclRAIIObject here.
+ // TODO: move ParsingClassDefinition here.
+ // TODO: move TentativeParsingAction here.
+
+
+ /// ExtensionRAIIObject - This saves the state of extension warnings when
+ /// constructed and disables them. When destructed, it restores them back to
+ /// the way they used to be. This is used to handle __extension__ in the
+ /// parser.
+ class ExtensionRAIIObject {
+ void operator=(const ExtensionRAIIObject &); // DO NOT IMPLEMENT
+ ExtensionRAIIObject(const ExtensionRAIIObject&); // DO NOT IMPLEMENT
+ Diagnostic &Diags;
+ public:
+ ExtensionRAIIObject(Diagnostic &diags) : Diags(diags) {
+ Diags.IncrementAllExtensionsSilenced();
+ }
+
+ ~ExtensionRAIIObject() {
+ Diags.DecrementAllExtensionsSilenced();
+ }
+ };
+
+ /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
+ /// restores it when destroyed. This says that "foo:" should not be
+ /// considered a possible typo for "foo::" for error recovery purposes.
+ class ColonProtectionRAIIObject {
+ Parser &P;
+ bool OldVal;
+ public:
+ ColonProtectionRAIIObject(Parser &p, bool Value = true)
+ : P(p), OldVal(P.ColonIsSacred) {
+ P.ColonIsSacred = Value;
+ }
+
+ /// restore - This can be used to restore the state early, before the dtor
+ /// is run.
+ void restore() {
+ P.ColonIsSacred = OldVal;
+ }
+
+ ~ColonProtectionRAIIObject() {
+ restore();
+ }
+ };
+
+ /// \brief RAII object that makes '>' behave either as an operator
+ /// or as the closing angle bracket for a template argument list.
+ class GreaterThanIsOperatorScope {
+ bool &GreaterThanIsOperator;
+ bool OldGreaterThanIsOperator;
+ public:
+ GreaterThanIsOperatorScope(bool &GTIO, bool Val)
+ : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
+ GreaterThanIsOperator = Val;
+ }
+
+ ~GreaterThanIsOperatorScope() {
+ GreaterThanIsOperator = OldGreaterThanIsOperator;
+ }
+ };
+
+} // end namespace clang
+
+#endif
OpenPOWER on IntegriCloud