diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Expr.cpp | 3 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 7 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 10 | ||||
-rw-r--r-- | lib/AST/StmtSerialization.cpp | 28 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 8 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 48 | ||||
-rw-r--r-- | lib/Sema/IdentifierResolver.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/IdentifierResolver.h | 6 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 17 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 28 |
12 files changed, 169 insertions, 7 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index ce0856033d..86a2f2902e 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -437,6 +437,9 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { if (cast<ExplicitCastExpr>(this)->getTypeAsWritten()->isReferenceType()) return LV_Valid; break; + case CXXTypeidExprClass: + // C++ 5.2.8p1: The result of a typeid expression is an lvalue of ... + return LV_Valid; case CXXThisExprClass: return LV_InvalidExpression; default: diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 0eead3ca55..ff97e688b8 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -24,6 +24,13 @@ void CXXConditionDeclExpr::Destroy(ASTContext& C) { // Child Iterators for iterating over subexpressions/substatements //===----------------------------------------------------------------------===// +// CXXTypeidExpr - has child iterators if the operand is an expression +Stmt::child_iterator CXXTypeidExpr::child_begin() { + return isTypeOperand() ? child_iterator() : (Stmt**)&Operand; +} +Stmt::child_iterator CXXTypeidExpr::child_end() { + return isTypeOperand() ? child_iterator() : (Stmt**)&Operand+1; +} // CXXBoolLiteralExpr Stmt::child_iterator CXXBoolLiteralExpr::child_begin() { diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 420bdbdee9..cc861cc6b4 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -832,6 +832,16 @@ void StmtPrinter::VisitCXXConstCastExpr(CXXConstCastExpr *Node) { VisitCXXNamedCastExpr(Node); } +void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) { + OS << "typeid("; + if (Node->isTypeOperand()) { + OS << Node->getTypeOperand().getAsString(); + } else { + PrintExpr(Node->getExprOperand()); + } + OS << ")"; +} + void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) { OS << (Node->getValue() ? "true" : "false"); } diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp index 09aaceffda..3982881576 100644 --- a/lib/AST/StmtSerialization.cpp +++ b/lib/AST/StmtSerialization.cpp @@ -216,6 +216,9 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) { case CXXConstCastExprClass: return CXXConstCastExpr::CreateImpl(D, C, SC); + case CXXTypeidExprClass: + return CXXTypeidExpr::CreateImpl(D, C); + case CXXThisExprClass: return CXXThisExpr::CreateImpl(D, C); @@ -1346,6 +1349,31 @@ CXXNamedCastExpr::CreateImpl(Deserializer& D, ASTContext& C, StmtClass SC) { } } +void CXXTypeidExpr::EmitImpl(llvm::Serializer& S) const { + S.Emit(getType()); + S.Emit(isTypeOperand()); + if (isTypeOperand()) { + S.Emit(getTypeOperand()); + } else { + S.EmitOwnedPtr(getExprOperand()); + } + S.Emit(Range); +} + +CXXTypeidExpr* +CXXTypeidExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) { + QualType Ty = QualType::ReadVal(D); + bool isTypeOp = D.ReadBool(); + void *Operand; + if (isTypeOp) { + Operand = QualType::ReadVal(D).getAsOpaquePtr(); + } else { + Operand = D.ReadOwnedPtr<Expr>(C); + } + SourceRange Range = SourceRange::ReadVal(D); + return new CXXTypeidExpr(isTypeOp, Operand, Ty, Range); +} + void CXXThisExpr::EmitImpl(llvm::Serializer& S) const { S.Emit(getType()); S.Emit(Loc); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index e8758e15f1..df55bf79fc 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -357,7 +357,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) { /// /// primary-expression: [C99 6.5.1] /// [C99] identifier -// [C++] id-expression +/// [C++] id-expression /// constant /// string-literal /// [C++] boolean-literal [C++ 2.13.5] @@ -382,6 +382,8 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) { /// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'static_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] +/// [C++] 'typeid' '(' expression ')' [C++ 5.2p1] +/// [C++] 'typeid' '(' type-id ')' [C++ 5.2p1] /// [C++] 'this' [C++ 9.3.2] /// [clang] '^' block-literal /// @@ -567,6 +569,10 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) { Res = ParseCXXCasts(); // These can be followed by postfix-expr pieces. return ParsePostfixExpressionSuffix(Res); + case tok::kw_typeid: + Res = ParseCXXTypeid(); + // This can be followed by postfix-expr pieces. + return ParsePostfixExpressionSuffix(Res); case tok::kw_this: Res = ParseCXXThis(); // This can be followed by postfix-expr pieces. diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index a1fd565822..692e35df93 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -216,6 +216,54 @@ Parser::ExprResult Parser::ParseCXXCasts() { return Result; } +/// ParseCXXTypeid - This handles the C++ typeid expression. +/// +/// postfix-expression: [C++ 5.2p1] +/// 'typeid' '(' expression ')' +/// 'typeid' '(' type-id ')' +/// +Parser::ExprResult Parser::ParseCXXTypeid() { + assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!"); + + SourceLocation OpLoc = ConsumeToken(); + SourceLocation LParenLoc = Tok.getLocation(); + SourceLocation RParenLoc; + + // typeid expressions are always parenthesized. + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, + "typeid")) + return ExprResult(true); + + Parser::ExprResult Result; + + if (isTypeIdInParens()) { + TypeTy *Ty = ParseTypeName(); + + // Match the ')'. + MatchRHSPunctuation(tok::r_paren, LParenLoc); + + if (!Ty) + return ExprResult(true); + + Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true, + Ty, RParenLoc); + } else { + Result = ParseExpression(); + + // Match the ')'. + if (Result.isInvalid) + SkipUntil(tok::r_paren); + else { + MatchRHSPunctuation(tok::r_paren, LParenLoc); + + Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false, + Result.Val, RParenLoc); + } + } + + return Result; +} + /// ParseCXXBoolLiteral - This handles the C++ Boolean literals. /// /// boolean-literal: [C++ 2.13.5] diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index 8375720e55..82f95bf108 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -243,7 +243,7 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) { /// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the /// decls of parent declaration contexts too. IdentifierResolver::iterator -IdentifierResolver::begin(const IdentifierInfo *II, DeclContext *Ctx, +IdentifierResolver::begin(const IdentifierInfo *II, const DeclContext *Ctx, bool LookInParentCtx) { assert(Ctx && "null param passed"); diff --git a/lib/Sema/IdentifierResolver.h b/lib/Sema/IdentifierResolver.h index c661145d89..e76bec6ee2 100644 --- a/lib/Sema/IdentifierResolver.h +++ b/lib/Sema/IdentifierResolver.h @@ -31,7 +31,7 @@ class IdentifierResolver { /// ScopedDecls, LookupContext can be used with all decls (assumes /// translation unit context for non ScopedDecls). class LookupContext { - DeclContext *Ctx; + const DeclContext *Ctx; /// TUCtx - Provides a common value for translation unit context for all /// decls. @@ -49,7 +49,7 @@ class IdentifierResolver { LookupContext(Decl *D) { Ctx = getContext(D); } - LookupContext(DeclContext *DC) { + LookupContext(const DeclContext *DC) { if (!DC || isa<TranslationUnitDecl>(DC)) Ctx = TUCtx(); else @@ -196,7 +196,7 @@ public: /// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the /// decls of parent declaration contexts too. /// Default for 'LookInParentCtx is true. - static iterator begin(const IdentifierInfo *II, DeclContext *Ctx, + static iterator begin(const IdentifierInfo *II, const DeclContext *Ctx, bool LookInParentCtx = true); /// end - Returns an iterator that has 'finished'. diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 532be59cd4..9c8d0c8bcb 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -113,6 +113,10 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer) Ident_SEL = &IT.get("SEL"); Ident_Protocol = &IT.get("Protocol"); + Ident_StdNs = &IT.get("std"); + Ident_TypeInfo = 0; + StdNamespace = 0; + TUScope = 0; if (getLangOptions().CPlusPlus) FieldCollector.reset(new CXXFieldCollector()); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 3b187f2099..7f72928064 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -199,10 +199,18 @@ public: IdentifierInfo *Ident_id, *Ident_Class; // "id", "Class" IdentifierInfo *Ident_SEL, *Ident_Protocol; // "SEL", "Protocol" + /// Identifiers used by the C++ language + IdentifierInfo *Ident_StdNs; // "std" + IdentifierInfo *Ident_TypeInfo; // "type_info" - lazily created + /// Translation Unit Scope - useful to Objective-C actions that need /// to lookup file scope declarations in the "ordinary" C decl namespace. /// For example, user-defined classes, built-in "id" type, etc. Scope *TUScope; + + /// The C++ "std" namespace, where the standard library resides. Cached here + /// by GetStdNamespace + NamespaceDecl *StdNamespace; /// ObjCMethodList - a linked list of methods with different signatures. struct ObjCMethodList { @@ -450,7 +458,7 @@ public: /// More parsing and symbol table subroutines... Decl *LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S, - DeclContext *LookupCtx = 0, + const DeclContext *LookupCtx = 0, bool enableLazyBuiltinCreation = true); ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id); ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, @@ -463,6 +471,8 @@ public: void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, bool &IncompleteImpl); + + NamespaceDecl *GetStdNamespace(); /// CheckProtocolMethodDefs - This routine checks unimpletented /// methods declared in protocol, and those referenced by it. @@ -751,6 +761,11 @@ public: SourceLocation LParenLoc, ExprTy *E, SourceLocation RParenLoc); + /// ActOnCXXTypeidOfType - Parse typeid( type-id ). + virtual ExprResult ActOnCXXTypeid(SourceLocation OpLoc, + SourceLocation LParenLoc, bool isType, + void *TyOrExpr, SourceLocation RParenLoc); + //// ActOnCXXThis - Parse 'this' pointer. virtual ExprResult ActOnCXXThis(SourceLocation ThisLoc); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 879a79b633..b595ad7f31 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -193,7 +193,8 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) { /// LookupDecl - Look up the inner-most declaration in the specified /// namespace. Decl *Sema::LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S, - DeclContext *LookupCtx, bool enableLazyBuiltinCreation) { + const DeclContext *LookupCtx, + bool enableLazyBuiltinCreation) { if (II == 0) return 0; unsigned NS = NSI; if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary)) @@ -278,6 +279,18 @@ ScopedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, return New; } +/// GetStdNamespace - This method gets the C++ "std" namespace. This is where +/// everything from the standard library is defined. +NamespaceDecl *Sema::GetStdNamespace() { + if (!StdNamespace) { + DeclContext *Global = Context.getTranslationUnitDecl(); + Decl *Std = LookupDecl(Ident_StdNs, Decl::IDNS_Tag | Decl::IDNS_Ordinary, + 0, Global, /*enableLazyBuiltinCreation=*/false); + StdNamespace = dyn_cast_or_null<NamespaceDecl>(Std); + } + return StdNamespace; +} + /// MergeTypeDefDecl - We just parsed a typedef 'New' which has the same name /// and scope as a previous declaration 'Old'. Figure out how to resolve this /// situation, merging decls or emitting diagnostics as appropriate. diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index a6a62a9e37..e420ce5991 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -19,6 +19,34 @@ #include "clang/Basic/Diagnostic.h" using namespace clang; + +/// ActOnCXXTypeidOfType - Parse typeid( type-id ). +Action::ExprResult +Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, + bool isType, void *TyOrExpr, SourceLocation RParenLoc) { + const NamespaceDecl *StdNs = GetStdNamespace(); + if (!StdNs) { + Diag(OpLoc, diag::err_need_header_before_typeid); + return ExprResult(true); + } + if (!Ident_TypeInfo) { + Ident_TypeInfo = &PP.getIdentifierTable().get("type_info"); + } + Decl *TypeInfoDecl = LookupDecl(Ident_TypeInfo, + Decl::IDNS_Tag | Decl::IDNS_Ordinary, + 0, StdNs, /*createBuiltins=*/false); + RecordDecl *TypeInfoRecordDecl = dyn_cast_or_null<RecordDecl>(TypeInfoDecl); + if (!TypeInfoRecordDecl) { + Diag(OpLoc, diag::err_need_header_before_typeid); + return ExprResult(true); + } + + QualType TypeInfoType = Context.getTypeDeclType(TypeInfoRecordDecl); + + return new CXXTypeidExpr(isType, TyOrExpr, TypeInfoType.withConst(), + SourceRange(OpLoc, RParenLoc)); +} + /// ActOnCXXBoolLiteral - Parse {true,false} literals. Action::ExprResult Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { |