summaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/MinimalAction.cpp16
-rw-r--r--lib/Parse/ParseDecl.cpp15
-rw-r--r--lib/Parse/ParseDeclCXX.cpp91
-rw-r--r--lib/Parse/ParseExpr.cpp22
-rw-r--r--lib/Parse/ParseExprCXX.cpp11
5 files changed, 142 insertions, 13 deletions
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index b018e36519f3c..9ded366b29f91 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -42,6 +42,22 @@ Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope,
return DeclPtrTy();
}
+// Defined out-of-line here because of dependecy on AttributeList
+Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
+ SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *TargetName,
+ AttributeList *AttrList,
+ bool IsTypeName) {
+
+ // FIXME: Parser seems to assume that Action::ActOn* takes ownership over
+ // passed AttributeList, however other actions don't free it, is it
+ // temporary state or bug?
+ delete AttrList;
+ return DeclPtrTy();
+}
+
void PrettyStackTraceActionsDecl::print(llvm::raw_ostream &OS) const {
if (Loc.isValid()) {
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 9073c6dbd1930..69152523a112e 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -402,7 +402,14 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D) {
SourceLocation DelLoc = ConsumeToken();
Actions.SetDeclDeleted(ThisDecl, DelLoc);
} else {
+ if (getLang().CPlusPlus)
+ Actions.ActOnCXXEnterDeclInitializer(CurScope, ThisDecl);
+
OwningExprResult Init(ParseInitializer());
+
+ if (getLang().CPlusPlus)
+ Actions.ActOnCXXExitDeclInitializer(CurScope, ThisDecl);
+
if (Init.isInvalid()) {
SkipUntil(tok::semi, true, true);
return DeclPtrTy();
@@ -2692,8 +2699,12 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// things like '=' and '*='. Sema rejects these in C89 mode because they
// are not i-c-e's, so we don't need to distinguish between the two here.
- // Parse the assignment-expression now.
- NumElements = ParseAssignmentExpression();
+ // Parse the constant-expression or assignment-expression now (depending
+ // on dialect).
+ if (getLang().CPlusPlus)
+ NumElements = ParseConstantExpression();
+ else
+ NumElements = ParseAssignmentExpression();
}
// If there was an error parsing the assignment-expression, recover.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 498eaf19cd66c..44f231a667862 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -48,6 +48,8 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
SourceLocation IdentLoc;
IdentifierInfo *Ident = 0;
+
+ Token attrTok;
if (Tok.is(tok::identifier)) {
Ident = Tok.getIdentifierInfo();
@@ -56,13 +58,19 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
// Read label attributes, if present.
Action::AttrTy *AttrList = 0;
- if (Tok.is(tok::kw___attribute))
+ if (Tok.is(tok::kw___attribute)) {
+ attrTok = Tok;
+
// FIXME: save these somewhere.
AttrList = ParseAttributes();
+ }
- if (Tok.is(tok::equal))
- // FIXME: Verify no attributes were present.
+ if (Tok.is(tok::equal)) {
+ if (AttrList)
+ Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
+
return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
+ }
if (Tok.isNot(tok::l_brace)) {
Diag(Tok, Ident ? diag::err_expected_lbrace :
@@ -245,15 +253,62 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
///
/// using-declaration: [C++ 7.3.p3: namespace.udecl]
/// 'using' 'typename'[opt] ::[opt] nested-name-specifier
-/// unqualified-id [TODO]
-/// 'using' :: unqualified-id [TODO]
+/// unqualified-id
+/// 'using' :: unqualified-id
///
Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
SourceLocation UsingLoc,
SourceLocation &DeclEnd) {
- assert(false && "Not implemented");
- // FIXME: Implement parsing.
- return DeclPtrTy();
+ CXXScopeSpec SS;
+ bool IsTypeName;
+
+ // Ignore optional 'typename'.
+ if (Tok.is(tok::kw_typename)) {
+ ConsumeToken();
+ IsTypeName = true;
+ }
+ else
+ IsTypeName = false;
+
+ // Parse nested-name-specifier.
+ ParseOptionalCXXScopeSpecifier(SS);
+
+ AttributeList *AttrList = 0;
+ IdentifierInfo *TargetName = 0;
+ SourceLocation IdentLoc = SourceLocation();
+
+ // Check nested-name specifier.
+ if (SS.isInvalid()) {
+ SkipUntil(tok::semi);
+ return DeclPtrTy();
+ }
+ if (Tok.is(tok::annot_template_id)) {
+ Diag(Tok, diag::err_unexpected_template_spec_in_using);
+ SkipUntil(tok::semi);
+ return DeclPtrTy();
+ }
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident_in_using);
+ // If there was invalid identifier, skip to end of decl, and eat ';'.
+ SkipUntil(tok::semi);
+ return DeclPtrTy();
+ }
+
+ // Parse identifier.
+ TargetName = Tok.getIdentifierInfo();
+ IdentLoc = ConsumeToken();
+
+ // Parse (optional) attributes (most likely GNU strong-using extension).
+ if (Tok.is(tok::kw___attribute))
+ AttrList = ParseAttributes();
+
+ // Eat ';'.
+ DeclEnd = Tok.getLocation();
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+ AttrList ? "attributes list" : "namespace name", tok::semi);
+
+ return Actions.ActOnUsingDeclaration(CurScope, UsingLoc, SS,
+ IdentLoc, TargetName, AttrList, IsTypeName);
}
/// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.
@@ -271,7 +326,7 @@ Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
}
SourceLocation LParenLoc = ConsumeParen();
-
+
OwningExprResult AssertExpr(ParseConstantExpression());
if (AssertExpr.isInvalid()) {
SkipUntil(tok::semi);
@@ -782,7 +837,23 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
ConsumeToken();
return ParseCXXClassMemberDeclaration(AS);
}
-
+
+ if (Tok.is(tok::kw_using)) {
+ // Eat 'using'.
+ SourceLocation UsingLoc = ConsumeToken();
+
+ if (Tok.is(tok::kw_namespace)) {
+ Diag(UsingLoc, diag::err_using_namespace_in_class);
+ SkipUntil(tok::semi, true, true);
+ }
+ else {
+ SourceLocation DeclEnd;
+ // Otherwise, it must be using-declaration.
+ ParseUsingDeclaration(Declarator::MemberContext, UsingLoc, DeclEnd);
+ }
+ return;
+ }
+
SourceLocation DSStart = Tok.getLocation();
// decl-specifier-seq:
// Parse the common declaration-specifiers piece.
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 3fee78bb719f6..4a07d05650bd1 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -276,6 +276,11 @@ Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
Parser::OwningExprResult Parser::ParseConstantExpression() {
+ // C++ [basic.def.odr]p2:
+ // An expression is potentially evaluated unless it appears where an
+ // integral constant expression is required (see 5.19) [...].
+ EnterUnevaluatedOperand Unevaluated(Actions);
+
OwningExprResult LHS(ParseCastExpression(false));
if (LHS.isInvalid()) return move(LHS);
@@ -971,8 +976,15 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
return ExprError();
}
+
+ // C++0x [expr.sizeof]p1:
+ // [...] The operand is either an expression, which is an unevaluated
+ // operand (Clause 5) [...]
+ //
+ // The GNU typeof and alignof extensions also behave as unevaluated
+ // operands.
+ EnterUnevaluatedOperand Unevaluated(Actions);
Operand = ParseCastExpression(true/*isUnaryExpression*/);
-
} else {
// If it starts with a '(', we know that it is either a parenthesized
// type-name, or it is a unary-expression that starts with a compound
@@ -980,6 +992,14 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
// expression.
ParenParseOption ExprType = CastExpr;
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
+
+ // C++0x [expr.sizeof]p1:
+ // [...] The operand is either an expression, which is an unevaluated
+ // operand (Clause 5) [...]
+ //
+ // The GNU typeof and alignof extensions also behave as unevaluated
+ // operands.
+ EnterUnevaluatedOperand Unevaluated(Actions);
Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
CastTy, RParenLoc);
CastRange = SourceRange(LParenLoc, RParenLoc);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 681c6adb2ea96..87aa5dc671167 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -377,6 +377,17 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
Ty.get(), RParenLoc);
} else {
+ // C++0x [expr.typeid]p3:
+ // When typeid is applied to an expression other than an lvalue of a
+ // polymorphic class type [...] The expression is an unevaluated
+ // operand (Clause 5).
+ //
+ // Note that we can't tell whether the expression is an lvalue of a
+ // polymorphic class type until after we've parsed the expression, so
+ // we treat the expression as an unevaluated operand and let semantic
+ // analysis cope with case where the expression is not an unevaluated
+ // operand.
+ EnterUnevaluatedOperand Unevaluated(Actions);
Result = ParseExpression();
// Match the ')'.