diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2008-08-22 15:38:55 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2008-08-22 15:38:55 +0000 |
commit | 987a14bf5883ef6e5d07f1c83eb6d41a8212a78c (patch) | |
tree | d5691abce8108c4987271f3bcf4a2fb4c147640a /lib/Parse | |
parent | dfb99a968b3cebe4ca5dd7941f228678f2cb3566 (diff) |
Add support for C++'s "type-specifier ( expression-list )" expression:
-The Parser calls a new "ActOnCXXTypeConstructExpr" action.
-Sema, depending on the type and expressions number:
-If the type is a class, it will treat it as a class constructor. [TODO]
-If there's only one expression (i.e. "int(0.5)" ), creates a new "CXXFunctionalCastExpr" Expr node
-If there are no expressions (i.e "int()" ), creates a new "CXXZeroInitValueExpr" Expr node.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55177 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 46 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 128 |
2 files changed, 172 insertions, 2 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 9eccd06da1..d4b46982ac 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -20,6 +20,7 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" +#include "clang/Parse/DeclSpec.h" #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallString.h" @@ -372,6 +373,8 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) { /// [OBJC] '@protocol' '(' identifier ')' /// [OBJC] '@encode' '(' type-name ')' /// [OBJC] objc-string-literal +/// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] +/// [C++] typename-specifier '(' expression-list[opt] ')' [TODO] /// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] @@ -446,8 +449,17 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) { case tok::kw_false: return ParseCXXBoolLiteral(); - case tok::identifier: { // primary-expression: identifier - // constant: enumeration-constant + case tok::identifier: { + if (getLang().CPlusPlus && + Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope)) { + // Handle C++ function-style cast, e.g. "T(4.5)" where T is a typedef for + // double. + goto HandleType; + } + + // primary-expression: identifier + // constant: enumeration-constant + // Consume the identifier so that we can see if it is followed by a '('. // Function designators are allowed to be undeclared (C99 6.5.1p2), so we // need to know whether or not this identifier is a function designator or @@ -545,6 +557,35 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) { Res = ParseCXXThis(); // This can be followed by postfix-expr pieces. return ParsePostfixExpressionSuffix(Res); + + case tok::kw_char: + case tok::kw_wchar_t: + case tok::kw_bool: + case tok::kw_short: + case tok::kw_int: + case tok::kw_long: + case tok::kw_signed: + case tok::kw_unsigned: + case tok::kw_float: + case tok::kw_double: + case tok::kw_void: + case tok::kw_typeof: { + if (!getLang().CPlusPlus) + goto UnhandledToken; + HandleType: + // postfix-expression: simple-type-specifier '(' expression-list[opt] ')' + // + DeclSpec DS; + ParseCXXSimpleTypeSpecifier(DS); + if (Tok.isNot(tok::l_paren)) + return Diag(Tok.getLocation(), diag::err_expected_lparen_after_type, + DS.getSourceRange()); + + Res = ParseCXXTypeConstructExpression(DS); + // This can be followed by postfix-expr pieces. + return ParsePostfixExpressionSuffix(Res); + } + case tok::at: { SourceLocation AtLoc = ConsumeToken(); return ParseObjCAtExpression(AtLoc); @@ -555,6 +596,7 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) { return ParsePostfixExpressionSuffix(ParseObjCMessageExpression()); // FALL THROUGH. default: + UnhandledToken: Diag(Tok, diag::err_expected_expression); return ExprResult(true); } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 45f482792d..bd8e7d510e 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Parse/Parser.h" +#include "clang/Parse/DeclSpec.h" using namespace clang; /// ParseCXXCasts - This handles the various ways to cast expressions to another @@ -114,3 +115,130 @@ Parser::ExprResult Parser::ParseCXXThis() { SourceLocation ThisLoc = ConsumeToken(); return Actions.ActOnCXXThis(ThisLoc); } + +/// ParseCXXTypeConstructExpression - Parse construction of a specified type. +/// Can be interpreted either as function-style casting ("int(x)") +/// or class type construction ("ClassType(x,y,z)") +/// or creation of a value-initialized type ("int()"). +/// +/// postfix-expression: [C++ 5.2p1] +/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] +/// typename-specifier '(' expression-list[opt] ')' [TODO] +/// +Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { + Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val; + + assert(Tok.is(tok::l_paren) && "Expected '('!"); + SourceLocation LParenLoc = ConsumeParen(); + + ExprListTy Exprs; + CommaLocsTy CommaLocs; + + if (Tok.isNot(tok::r_paren)) { + if (ParseExpressionList(Exprs, CommaLocs)) { + SkipUntil(tok::r_paren); + return ExprResult(true); + } + } + + // Match the ')'. + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + + assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& + "Unexpected number of commas!"); + return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep, + LParenLoc, + &Exprs[0], Exprs.size(), + &CommaLocs[0], RParenLoc); +} + +/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. +/// This should only be called when the current token is known to be part of +/// simple-type-specifier. +/// +/// simple-type-specifier: +/// '::'[opt] nested-name-specifier[opt] type-name [TODO] +/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO] +/// char +/// wchar_t +/// bool +/// short +/// int +/// long +/// signed +/// unsigned +/// float +/// double +/// void +/// [GNU] typeof-specifier +/// [C++0x] auto [TODO] +/// +/// type-name: +/// class-name +/// enum-name +/// typedef-name +/// +void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { + DS.SetRangeStart(Tok.getLocation()); + const char *PrevSpec; + SourceLocation Loc = Tok.getLocation(); + + switch (Tok.getKind()) { + default: + assert(0 && "Not a simple-type-specifier token!"); + abort(); + + // type-name + case tok::identifier: { + TypeTy *TypeRep = Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope); + assert(TypeRep && "Identifier wasn't a type-name!"); + DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec, TypeRep); + break; + } + + // builtin types + case tok::kw_short: + DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec); + break; + case tok::kw_long: + DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec); + break; + case tok::kw_signed: + DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec); + break; + case tok::kw_unsigned: + DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec); + break; + case tok::kw_void: + DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec); + break; + case tok::kw_char: + DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec); + break; + case tok::kw_int: + DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec); + break; + case tok::kw_float: + DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec); + break; + case tok::kw_double: + DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec); + break; + case tok::kw_wchar_t: + DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec); + break; + case tok::kw_bool: + DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec); + break; + + // GNU typeof support. + case tok::kw_typeof: + ParseTypeofSpecifier(DS); + DS.Finish(Diags, PP.getSourceManager(), getLang()); + return; + } + DS.SetRangeEnd(Tok.getLocation()); + ConsumeToken(); + DS.Finish(Diags, PP.getSourceManager(), getLang()); +} |