aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseExprCXX.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2011-02-20 13:06:31 +0000
committerDimitry Andric <dim@FreeBSD.org>2011-02-20 13:06:31 +0000
commitbca07a4524feb4edec581062d631a13116320a24 (patch)
treea9243275843fbeaa590afc07ee888e006b8d54ea /lib/Parse/ParseExprCXX.cpp
parent998bc5802ecdd65ce3b270f6c69a8ae8557f0a10 (diff)
downloadsrc-bca07a4524feb4edec581062d631a13116320a24.tar.gz
src-bca07a4524feb4edec581062d631a13116320a24.zip
Notes
Diffstat (limited to 'lib/Parse/ParseExprCXX.cpp')
-rw-r--r--lib/Parse/ParseExprCXX.cpp160
1 files changed, 136 insertions, 24 deletions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 5041a212924a..e73578f23e36 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -13,6 +13,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
+#include "RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "llvm/Support/ErrorHandling.h"
@@ -500,9 +501,9 @@ ExprResult Parser::ParseCXXTypeid() {
TypeResult Ty = ParseTypeName();
// Match the ')'.
- MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
- if (Ty.isInvalid())
+ if (Ty.isInvalid() || RParenLoc.isInvalid())
return ExprError();
Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
@@ -524,8 +525,10 @@ ExprResult Parser::ParseCXXTypeid() {
if (Result.isInvalid())
SkipUntil(tok::r_paren);
else {
- MatchRHSPunctuation(tok::r_paren, LParenLoc);
-
+ RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ if (RParenLoc.isInvalid())
+ return ExprError();
+
Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
Result.release(), RParenLoc);
}
@@ -534,6 +537,54 @@ ExprResult Parser::ParseCXXTypeid() {
return move(Result);
}
+/// ParseCXXUuidof - This handles the Microsoft C++ __uuidof expression.
+///
+/// '__uuidof' '(' expression ')'
+/// '__uuidof' '(' type-id ')'
+///
+ExprResult Parser::ParseCXXUuidof() {
+ assert(Tok.is(tok::kw___uuidof) && "Not '__uuidof'!");
+
+ SourceLocation OpLoc = ConsumeToken();
+ SourceLocation LParenLoc = Tok.getLocation();
+ SourceLocation RParenLoc;
+
+ // __uuidof expressions are always parenthesized.
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+ "__uuidof"))
+ return ExprError();
+
+ ExprResult Result;
+
+ if (isTypeIdInParens()) {
+ TypeResult Ty = ParseTypeName();
+
+ // Match the ')'.
+ RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ if (Ty.isInvalid())
+ return ExprError();
+
+ Result = Actions.ActOnCXXUuidof(OpLoc, LParenLoc, /*isType=*/true,
+ Ty.get().getAsOpaquePtr(), RParenLoc);
+ } else {
+ EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
+ Result = ParseExpression();
+
+ // Match the ')'.
+ if (Result.isInvalid())
+ SkipUntil(tok::r_paren);
+ else {
+ RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ Result = Actions.ActOnCXXUuidof(OpLoc, LParenLoc, /*isType=*/false,
+ Result.release(), RParenLoc);
+ }
+ }
+
+ return move(Result);
+}
+
/// \brief Parse a C++ pseudo-destructor expression after the base,
/// . or -> operator, and nested-name-specifier have already been
/// parsed.
@@ -670,6 +721,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
assert(Tok.is(tok::l_paren) && "Expected '('!");
+ GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
+
SourceLocation LParenLoc = ConsumeParen();
ExprVector Exprs(Actions);
@@ -691,9 +744,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
"Unexpected number of commas!");
- return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
- LParenLoc, move_arg(Exprs),
- CommaLocs.data(), RParenLoc);
+ return Actions.ActOnCXXTypeConstructExpr(TypeRep, LParenLoc, move_arg(Exprs),
+ RParenLoc);
}
/// ParseCXXCondition - if/switch/while condition expression.
@@ -761,24 +813,22 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut,
}
// If attributes are present, parse them.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- DeclaratorInfo.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(DeclaratorInfo);
// Type-check the declaration itself.
DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(getCurScope(),
- DeclaratorInfo);
+ DeclaratorInfo);
DeclOut = Dcl.get();
ExprOut = ExprError();
-
+
// '=' assignment-expression
- if (Tok.is(tok::equal)) {
- SourceLocation EqualLoc = ConsumeToken();
+ if (isTokenEqualOrMistypedEqualEqual(
+ diag::err_invalid_equalequal_after_declarator)) {
+ ConsumeToken();
ExprResult AssignExpr(ParseAssignmentExpression());
if (!AssignExpr.isInvalid())
- Actions.AddInitializerToDecl(DeclOut, AssignExpr.take());
+ Actions.AddInitializerToDecl(DeclOut, AssignExpr.take(), false,
+ DS.getTypeSpecType() == DeclSpec::TST_auto);
} else {
// FIXME: C++0x allows a braced-init-list
Diag(Tok, diag::err_expected_equal_after_declarator);
@@ -862,9 +912,24 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
// type-name
case tok::annot_typename: {
- DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
- getTypeAnnotation(Tok));
- break;
+ if (getTypeAnnotation(Tok))
+ DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
+ getTypeAnnotation(Tok));
+ else
+ DS.SetTypeSpecError();
+
+ DS.SetRangeEnd(Tok.getAnnotationEndLoc());
+ ConsumeToken();
+
+ // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
+ // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
+ // Objective-C interface. If we don't have Objective-C or a '<', this is
+ // just a normal reference to a typedef name.
+ if (Tok.is(tok::less) && getLang().ObjC1)
+ ParseObjCProtocolQualifiers(DS);
+
+ DS.Finish(Diags, PP);
+ return;
}
// builtin types
@@ -943,7 +1008,7 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
// Parse one or more of the type specifiers.
if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
ParsedTemplateInfo(), /*SuppressDeclarations*/true)) {
- Diag(Tok, diag::err_operator_missing_type_specifier);
+ Diag(Tok, diag::err_expected_type);
return true;
}
@@ -1667,7 +1732,8 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) {
first = false;
SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
- D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, ParsedAttributes(),
+ /*static=*/false, /*star=*/false,
Size.release(), LLoc, RLoc),
RLoc);
@@ -1738,7 +1804,7 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
switch(kind) {
- default: assert(false && "Not a known unary type trait.");
+ default: llvm_unreachable("Not a known unary type trait");
case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
@@ -1758,6 +1824,15 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
}
}
+static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) {
+ switch(kind) {
+ default: llvm_unreachable("Not a known binary type trait");
+ case tok::kw___is_base_of: return BTT_IsBaseOf;
+ case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible;
+ case tok::kw___is_convertible_to: return BTT_IsConvertibleTo;
+ }
+}
+
/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
/// pseudo-functions that allow implementation of the TR1/C++0x type traits
/// templates.
@@ -1783,7 +1858,44 @@ ExprResult Parser::ParseUnaryTypeTrait() {
if (Ty.isInvalid())
return ExprError();
- return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
+ return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), RParen);
+}
+
+/// ParseBinaryTypeTrait - Parse the built-in binary type-trait
+/// pseudo-functions that allow implementation of the TR1/C++0x type traits
+/// templates.
+///
+/// primary-expression:
+/// [GNU] binary-type-trait '(' type-id ',' type-id ')'
+///
+ExprResult Parser::ParseBinaryTypeTrait() {
+ BinaryTypeTrait BTT = BinaryTypeTraitFromTokKind(Tok.getKind());
+ SourceLocation Loc = ConsumeToken();
+
+ SourceLocation LParen = Tok.getLocation();
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
+ return ExprError();
+
+ TypeResult LhsTy = ParseTypeName();
+ if (LhsTy.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return ExprError();
+ }
+
+ if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) {
+ SkipUntil(tok::r_paren);
+ return ExprError();
+ }
+
+ TypeResult RhsTy = ParseTypeName();
+ if (RhsTy.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return ExprError();
+ }
+
+ SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
+
+ return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(), RParen);
}
/// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a