forked from OSchip/llvm-project
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. llvm-svn: 55177
This commit is contained in:
parent
5a87265775
commit
857fcc2f8e
|
@ -169,6 +169,71 @@ public:
|
|||
static CXXDefaultArgExpr* CreateImpl(llvm::Deserializer& D,
|
||||
ASTContext& C);
|
||||
};
|
||||
|
||||
/// CXXFunctionalCastExpr - [C++ 5.2.3p1] Explicit type conversion
|
||||
/// (functional notation).
|
||||
/// Example: "x = int(0.5);"
|
||||
///
|
||||
class CXXFunctionalCastExpr : public CastExpr {
|
||||
SourceLocation TyBeginLoc;
|
||||
SourceLocation RParenLoc;
|
||||
public:
|
||||
CXXFunctionalCastExpr(QualType ty, SourceLocation tyBeginLoc, Expr *castExpr,
|
||||
SourceLocation rParenLoc) :
|
||||
CastExpr(CXXFunctionalCastExprClass, ty, castExpr),
|
||||
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
|
||||
|
||||
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
|
||||
SourceLocation getRParenLoc() const { return RParenLoc; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(TyBeginLoc, RParenLoc);
|
||||
}
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CXXFunctionalCastExprClass;
|
||||
}
|
||||
static bool classof(const CXXFunctionalCastExpr *) { return true; }
|
||||
|
||||
virtual void EmitImpl(llvm::Serializer& S) const;
|
||||
static CXXFunctionalCastExpr *
|
||||
CreateImpl(llvm::Deserializer& D, ASTContext& C);
|
||||
};
|
||||
|
||||
/// CXXZeroInitValueExpr - [C++ 5.2.3p2]
|
||||
/// Expression "T()" which creates a value-initialized Rvalue of non-class
|
||||
/// type T.
|
||||
///
|
||||
class CXXZeroInitValueExpr : public Expr {
|
||||
SourceLocation TyBeginLoc;
|
||||
SourceLocation RParenLoc;
|
||||
|
||||
public:
|
||||
CXXZeroInitValueExpr(QualType ty, SourceLocation tyBeginLoc,
|
||||
SourceLocation rParenLoc ) :
|
||||
Expr(CXXZeroInitValueExprClass, ty),
|
||||
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
|
||||
|
||||
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
|
||||
SourceLocation getRParenLoc() const { return RParenLoc; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(TyBeginLoc, RParenLoc);
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CXXZeroInitValueExprClass;
|
||||
}
|
||||
static bool classof(const CXXZeroInitValueExpr *) { return true; }
|
||||
|
||||
// Iterators
|
||||
virtual child_iterator child_begin();
|
||||
virtual child_iterator child_end();
|
||||
|
||||
virtual void EmitImpl(llvm::Serializer& S) const;
|
||||
static CXXZeroInitValueExpr *
|
||||
CreateImpl(llvm::Deserializer& D, ASTContext& C);
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
@ -93,6 +93,8 @@ STMT(60, CXXCastExpr , Expr)
|
|||
STMT(61, CXXBoolLiteralExpr , Expr)
|
||||
STMT(62, CXXThrowExpr , Expr)
|
||||
STMT(63, CXXDefaultArgExpr , Expr)
|
||||
STMT(64, CXXFunctionalCastExpr, CastExpr)
|
||||
STMT(65, CXXZeroInitValueExpr , Expr)
|
||||
|
||||
// Obj-C Expressions.
|
||||
STMT(70, ObjCStringLiteral , Expr)
|
||||
|
|
|
@ -529,6 +529,8 @@ DIAG(err_no_declarators, ERROR,
|
|||
"declaration does not declare anything")
|
||||
DIAG(err_func_def_no_params, ERROR,
|
||||
"function definition does not declare parameters")
|
||||
DIAG(err_expected_lparen_after_type, ERROR,
|
||||
"expected '(' for function-style cast or type construction")
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Semantic Analysis
|
||||
|
@ -949,6 +951,16 @@ DIAG(err_invalid_member_use_in_static_method, ERROR,
|
|||
"invalid use of member '%0' in static member function")
|
||||
DIAG(err_invalid_non_static_member_use, ERROR,
|
||||
"invalid use of nonstatic data member '%0'")
|
||||
DIAG(err_invalid_incomplete_type_use, ERROR,
|
||||
"invalid use of incomplete type '%0'")
|
||||
DIAG(err_builtin_func_cast_more_than_one_arg, ERROR,
|
||||
"function-style cast to a builtin type can only take one argument")
|
||||
DIAG(err_value_init_for_array_type, ERROR,
|
||||
"array types cannot be value-initialized")
|
||||
// Temporary
|
||||
DIAG(err_unsupported_class_constructor, ERROR,
|
||||
"class constructors are not supported yet")
|
||||
|
||||
|
||||
// assignment related diagnostics (also for argument passing, returning, etc).
|
||||
DIAG(err_typecheck_convert_incompatible, ERROR,
|
||||
|
|
|
@ -578,6 +578,20 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/// ActOnCXXTypeConstructExpr - 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()").
|
||||
virtual ExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange,
|
||||
TypeTy *TypeRep,
|
||||
SourceLocation LParenLoc,
|
||||
ExprTy **Exprs,
|
||||
unsigned NumExprs,
|
||||
SourceLocation *CommaLocs,
|
||||
SourceLocation RParenLoc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===---------------------------- C++ Classes ---------------------------===//
|
||||
/// ActOnBaseSpecifier - Parsed a base specifier
|
||||
virtual void ActOnBaseSpecifier(DeclTy *classdecl, SourceRange SpecifierRange,
|
||||
|
|
|
@ -430,6 +430,15 @@ private:
|
|||
// C++ 2.13.5: C++ Boolean Literals
|
||||
ExprResult ParseCXXBoolLiteral();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ 5.2.3: Explicit type conversion (functional notation)
|
||||
ExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS);
|
||||
|
||||
/// 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.
|
||||
void ParseCXXSimpleTypeSpecifier(DeclSpec &DS);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C99 6.7.8: Initialization.
|
||||
ExprResult ParseInitializer();
|
||||
|
|
|
@ -360,6 +360,7 @@ bool Expr::hasLocalSideEffect() const {
|
|||
return false;
|
||||
}
|
||||
case ExplicitCastExprClass:
|
||||
case CXXFunctionalCastExprClass:
|
||||
// If this is a cast to void, check the operand. Otherwise, the result of
|
||||
// the cast is unused.
|
||||
if (getType()->isVoidType())
|
||||
|
@ -643,7 +644,8 @@ bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
|
|||
return true;
|
||||
}
|
||||
case ImplicitCastExprClass:
|
||||
case ExplicitCastExprClass: {
|
||||
case ExplicitCastExprClass:
|
||||
case CXXFunctionalCastExprClass: {
|
||||
const Expr *SubExpr = cast<CastExpr>(this)->getSubExpr();
|
||||
SourceLocation CastLoc = getLocStart();
|
||||
if (!SubExpr->isConstantExpr(Ctx, Loc)) {
|
||||
|
@ -931,7 +933,8 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
|
|||
break;
|
||||
}
|
||||
case ImplicitCastExprClass:
|
||||
case ExplicitCastExprClass: {
|
||||
case ExplicitCastExprClass:
|
||||
case CXXFunctionalCastExprClass: {
|
||||
const Expr *SubExpr = cast<CastExpr>(this)->getSubExpr();
|
||||
SourceLocation CastLoc = getLocStart();
|
||||
|
||||
|
|
|
@ -45,3 +45,11 @@ Stmt::child_iterator CXXDefaultArgExpr::child_begin() {
|
|||
Stmt::child_iterator CXXDefaultArgExpr::child_end() {
|
||||
return child_iterator();
|
||||
}
|
||||
|
||||
// CXXZeroInitValueExpr
|
||||
Stmt::child_iterator CXXZeroInitValueExpr::child_begin() {
|
||||
return child_iterator();
|
||||
}
|
||||
Stmt::child_iterator CXXZeroInitValueExpr::child_end() {
|
||||
return child_iterator();
|
||||
}
|
||||
|
|
|
@ -818,6 +818,17 @@ void StmtPrinter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Node) {
|
|||
// Nothing to print: we picked up the default argument
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
|
||||
OS << Node->getType().getAsString();
|
||||
OS << "(";
|
||||
PrintExpr(Node->getSubExpr());
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *Node) {
|
||||
OS << Node->getType().getAsString() << "()";
|
||||
}
|
||||
|
||||
// Obj-C
|
||||
|
||||
void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
|
||||
|
|
|
@ -197,6 +197,12 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) {
|
|||
|
||||
case CXXDefaultArgExprClass:
|
||||
return CXXDefaultArgExpr::CreateImpl(D, C);
|
||||
|
||||
case CXXFunctionalCastExprClass:
|
||||
return CXXFunctionalCastExpr::CreateImpl(D, C);
|
||||
|
||||
case CXXZeroInitValueExprClass:
|
||||
return CXXZeroInitValueExpr::CreateImpl(D, C);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1101,3 +1107,33 @@ CXXDefaultArgExpr *CXXDefaultArgExpr::CreateImpl(Deserializer& D, ASTContext& C)
|
|||
D.ReadPtr(Param, false);
|
||||
return new CXXDefaultArgExpr(Param);
|
||||
}
|
||||
|
||||
void CXXFunctionalCastExpr::EmitImpl(Serializer& S) const {
|
||||
S.Emit(getType());
|
||||
S.Emit(TyBeginLoc);
|
||||
S.Emit(RParenLoc);
|
||||
S.EmitOwnedPtr(getSubExpr());
|
||||
}
|
||||
|
||||
CXXFunctionalCastExpr *
|
||||
CXXFunctionalCastExpr::CreateImpl(Deserializer& D, ASTContext& C) {
|
||||
QualType Ty = QualType::ReadVal(D);
|
||||
SourceLocation TyBeginLoc = SourceLocation::ReadVal(D);
|
||||
SourceLocation RParenLoc = SourceLocation::ReadVal(D);
|
||||
Expr* SubExpr = D.ReadOwnedPtr<Expr>(C);
|
||||
return new CXXFunctionalCastExpr(Ty, TyBeginLoc, SubExpr, RParenLoc);
|
||||
}
|
||||
|
||||
void CXXZeroInitValueExpr::EmitImpl(Serializer& S) const {
|
||||
S.Emit(getType());
|
||||
S.Emit(TyBeginLoc);
|
||||
S.Emit(RParenLoc);
|
||||
}
|
||||
|
||||
CXXZeroInitValueExpr *
|
||||
CXXZeroInitValueExpr::CreateImpl(Deserializer& D, ASTContext& C) {
|
||||
QualType Ty = QualType::ReadVal(D);
|
||||
SourceLocation TyBeginLoc = SourceLocation::ReadVal(D);
|
||||
SourceLocation RParenLoc = SourceLocation::ReadVal(D);
|
||||
return new CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -559,6 +559,18 @@ public:
|
|||
virtual ExprResult ActOnCXXThrow(SourceLocation OpLoc,
|
||||
ExprTy *expr);
|
||||
|
||||
/// ActOnCXXTypeConstructExpr - 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()").
|
||||
virtual ExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange,
|
||||
TypeTy *TypeRep,
|
||||
SourceLocation LParenLoc,
|
||||
ExprTy **Exprs,
|
||||
unsigned NumExprs,
|
||||
SourceLocation *CommaLocs,
|
||||
SourceLocation RParenLoc);
|
||||
|
||||
// ParseObjCStringLiteral - Parse Objective-C string literals.
|
||||
virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
|
||||
ExprTy **Strings,
|
||||
|
|
|
@ -68,3 +68,67 @@ Action::ExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) {
|
|||
|
||||
return Diag(ThisLoc, diag::err_invalid_this_use);
|
||||
}
|
||||
|
||||
/// ActOnCXXTypeConstructExpr - 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()").
|
||||
Action::ExprResult
|
||||
Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
|
||||
SourceLocation LParenLoc,
|
||||
ExprTy **ExprTys, unsigned NumExprs,
|
||||
SourceLocation *CommaLocs,
|
||||
SourceLocation RParenLoc) {
|
||||
assert(TypeRep && "Missing type!");
|
||||
QualType Ty = QualType::getFromOpaquePtr(TypeRep);
|
||||
Expr **Exprs = (Expr**)ExprTys;
|
||||
SourceLocation TyBeginLoc = TypeRange.getBegin();
|
||||
SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc);
|
||||
|
||||
if (const RecordType *RT = Ty->getAsRecordType()) {
|
||||
// C++ 5.2.3p1:
|
||||
// If the simple-type-specifier specifies a class type, the class type shall
|
||||
// be complete.
|
||||
//
|
||||
if (!RT->getDecl()->isDefinition())
|
||||
return Diag(TyBeginLoc, diag::err_invalid_incomplete_type_use,
|
||||
Ty.getAsString(), FullRange);
|
||||
|
||||
// "class constructors are not supported yet"
|
||||
return Diag(TyBeginLoc, diag::err_unsupported_class_constructor, FullRange);
|
||||
}
|
||||
|
||||
// C++ 5.2.3p1:
|
||||
// If the expression list is a single expression, the type conversion
|
||||
// expression is equivalent (in definedness, and if defined in meaning) to the
|
||||
// corresponding cast expression.
|
||||
//
|
||||
if (NumExprs == 1) {
|
||||
if (CheckCastTypes(TypeRange, Ty, Exprs[0]))
|
||||
return true;
|
||||
return new CXXFunctionalCastExpr(Ty, TyBeginLoc, Exprs[0], RParenLoc);
|
||||
}
|
||||
|
||||
// C++ 5.2.3p1:
|
||||
// If the expression list specifies more than a single value, the type shall
|
||||
// be a class with a suitably declared constructor.
|
||||
//
|
||||
if (NumExprs > 1)
|
||||
return Diag(CommaLocs[0], diag::err_builtin_func_cast_more_than_one_arg,
|
||||
FullRange);
|
||||
|
||||
assert(NumExprs == 0 && "Expected 0 expressions");
|
||||
|
||||
// C++ 5.2.3p2:
|
||||
// The expression T(), where T is a simple-type-specifier for a non-array
|
||||
// complete object type or the (possibly cv-qualified) void type, creates an
|
||||
// rvalue of the specified type, which is value-initialized.
|
||||
//
|
||||
if (Ty->isArrayType())
|
||||
return Diag(TyBeginLoc, diag::err_value_init_for_array_type, FullRange);
|
||||
if (Ty->isIncompleteType() && !Ty->isVoidType())
|
||||
return Diag(TyBeginLoc, diag::err_invalid_incomplete_type_use,
|
||||
Ty.getAsString(), FullRange);
|
||||
|
||||
return new CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
|
||||
void f() {
|
||||
float v1 = float(1);
|
||||
int v2 = typeof(int)(1,2); // expected-error {{function-style cast to a builtin type can only take one argument}}
|
||||
typedef int arr[];
|
||||
int v3 = arr(); // expected-error {{array types cannot be value-initialized}}
|
||||
int v4 = int();
|
||||
int v5 = int; // expected-error {{expected '(' for function-style cast or type construction}}
|
||||
}
|
Loading…
Reference in New Issue