summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2008-11-11 11:37:55 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2008-11-11 11:37:55 +0000
commitc470476420249d85e6a82275e90d3a8f62312fa1 (patch)
treea8f9b143310c392c35c5883bd8358da872b63403
parent8cb2e28e43b99df65c904d87ada93c99660e4fa4 (diff)
downloadbcm5719-llvm-c470476420249d85e6a82275e90d3a8f62312fa1.tar.gz
bcm5719-llvm-c470476420249d85e6a82275e90d3a8f62312fa1.zip
Implement C++ 'typeid' parsing and sema.
llvm-svn: 59042
-rw-r--r--clang/include/clang/AST/ExprCXX.h41
-rw-r--r--clang/include/clang/AST/StmtNodes.def13
-rw-r--r--clang/include/clang/Basic/DiagnosticKinds.def4
-rw-r--r--clang/include/clang/Parse/Action.h7
-rw-r--r--clang/include/clang/Parse/Parser.h4
-rw-r--r--clang/lib/AST/Expr.cpp3
-rw-r--r--clang/lib/AST/ExprCXX.cpp7
-rw-r--r--clang/lib/AST/StmtPrinter.cpp10
-rw-r--r--clang/lib/AST/StmtSerialization.cpp28
-rw-r--r--clang/lib/Parse/ParseExpr.cpp8
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp48
-rw-r--r--clang/lib/Sema/IdentifierResolver.cpp2
-rw-r--r--clang/lib/Sema/IdentifierResolver.h6
-rw-r--r--clang/lib/Sema/Sema.cpp4
-rw-r--r--clang/lib/Sema/Sema.h17
-rw-r--r--clang/lib/Sema/SemaDecl.cpp15
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp28
-rw-r--r--clang/test/Parser/cxx-typeid.cpp13
-rw-r--r--clang/test/SemaCXX/typeid.cpp16
-rw-r--r--clang/www/cxx_status.html6
20 files changed, 264 insertions, 16 deletions
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 73ef6160a66..37f892ce3da 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -154,6 +154,47 @@ public:
virtual child_iterator child_end();
};
+/// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets
+/// the type_info that corresponds to the supplied type, or the (possibly
+/// dynamic) type of the supplied expression.
+///
+/// This represents code like @c typeid(int) or @c typeid(*objPtr)
+class CXXTypeidExpr : public Expr {
+private:
+ bool isTypeOp : 1;
+ void *Operand;
+ SourceRange Range;
+
+public:
+ CXXTypeidExpr(bool isTypeOp, void *op, QualType Ty, const SourceRange r) :
+ Expr(CXXTypeidExprClass, Ty), isTypeOp(isTypeOp), Operand(op), Range(r) {}
+
+ bool isTypeOperand() const { return isTypeOp; }
+ QualType getTypeOperand() const {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
+ return QualType::getFromOpaquePtr(Operand);
+ }
+ Expr* getExprOperand() const {
+ assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)");
+ return static_cast<Expr*>(Operand);
+ }
+
+ virtual SourceRange getSourceRange() const {
+ return Range;
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXTypeidExprClass;
+ }
+ static bool classof(const CXXTypeidExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+
+ virtual void EmitImpl(llvm::Serializer& S) const;
+ static CXXTypeidExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
+};
+
/// CXXThisExpr - Represents the "this" expression in C++, which is a
/// pointer to the object on which the current member function is
/// executing (C++ [expr.prim]p3). Example:
diff --git a/clang/include/clang/AST/StmtNodes.def b/clang/include/clang/AST/StmtNodes.def
index 7b60fcf6756..2b814a0e4b0 100644
--- a/clang/include/clang/AST/StmtNodes.def
+++ b/clang/include/clang/AST/StmtNodes.def
@@ -96,12 +96,13 @@ STMT(62, CXXDynamicCastExpr , CXXNamedCastExpr)
STMT(63, CXXReinterpretCastExpr , CXXNamedCastExpr)
STMT(64, CXXConstCastExpr , CXXNamedCastExpr)
STMT(65, CXXFunctionalCastExpr , Expr)
-STMT(66, CXXBoolLiteralExpr , Expr)
-STMT(67, CXXThisExpr , Expr)
-STMT(68, CXXThrowExpr , Expr)
-STMT(69, CXXDefaultArgExpr , Expr)
-STMT(70, CXXZeroInitValueExpr , Expr)
-STMT(71, CXXConditionDeclExpr , DeclRefExpr)
+STMT(66, CXXTypeidExpr , Expr)
+STMT(67, CXXBoolLiteralExpr , Expr)
+STMT(68, CXXThisExpr , Expr)
+STMT(69, CXXThrowExpr , Expr)
+STMT(70, CXXDefaultArgExpr , Expr)
+STMT(71, CXXZeroInitValueExpr , Expr)
+STMT(72, CXXConditionDeclExpr , DeclRefExpr)
// Obj-C Expressions.
STMT(80, ObjCStringLiteral , Expr)
diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def
index 59c05fc20d2..8d821e4362b 100644
--- a/clang/include/clang/Basic/DiagnosticKinds.def
+++ b/clang/include/clang/Basic/DiagnosticKinds.def
@@ -1157,6 +1157,10 @@ DIAG(err_ambiguous_base_to_derived_cast, ERROR,
DIAG(err_static_downcast_via_virtual, ERROR,
"cannot cast '%0' to '%1' via virtual base '%2'")
+// Other C++ expressions
+DIAG(err_need_header_before_typeid, ERROR,
+ "you need to include <typeinfo> before using the 'typeid' operator")
+
DIAG(err_invalid_use_of_function_type, ERROR,
"a function type is not allowed here")
DIAG(err_invalid_use_of_array_type, ERROR,
diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h
index 038c8583f81..d1ab26f6937 100644
--- a/clang/include/clang/Parse/Action.h
+++ b/clang/include/clang/Parse/Action.h
@@ -676,6 +676,13 @@ public:
return 0;
}
+ /// ActOnCXXTypeidOfType - Parse typeid( type-id ).
+ virtual ExprResult ActOnCXXTypeid(SourceLocation OpLoc,
+ SourceLocation LParenLoc, bool isType,
+ void *TyOrExpr, SourceLocation RParenLoc) {
+ return 0;
+ }
+
/// ActOnCXXThis - Parse the C++ 'this' pointer.
virtual ExprResult ActOnCXXThis(SourceLocation ThisLoc) {
return 0;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 4071172743a..9eefe55cb96 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -505,6 +505,10 @@ private:
ExprResult ParseCXXCasts();
//===--------------------------------------------------------------------===//
+ // C++ 5.2p1: C++ Type Identification
+ ExprResult ParseCXXTypeid();
+
+ //===--------------------------------------------------------------------===//
// C++ 9.3.2: C++ 'this' pointer
ExprResult ParseCXXThis();
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index ce0856033d6..86a2f2902e9 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/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/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 0eead3ca552..ff97e688b8d 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/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/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 420bdbdee90..cc861cc6b4e 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/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/clang/lib/AST/StmtSerialization.cpp b/clang/lib/AST/StmtSerialization.cpp
index 09aaceffda4..39828815769 100644
--- a/clang/lib/AST/StmtSerialization.cpp
+++ b/clang/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/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index e8758e15f10..df55bf79fca 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/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/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index a1fd565822d..692e35df93d 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/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/clang/lib/Sema/IdentifierResolver.cpp b/clang/lib/Sema/IdentifierResolver.cpp
index 8375720e55c..82f95bf1082 100644
--- a/clang/lib/Sema/IdentifierResolver.cpp
+++ b/clang/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/clang/lib/Sema/IdentifierResolver.h b/clang/lib/Sema/IdentifierResolver.h
index c661145d89f..e76bec6ee25 100644
--- a/clang/lib/Sema/IdentifierResolver.h
+++ b/clang/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/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 532be59cd4d..9c8d0c8bcb4 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/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/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 3b187f2099d..7f72928064a 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 879a79b633a..b595ad7f317 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/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/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index a6a62a9e377..e420ce59916 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/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) {
diff --git a/clang/test/Parser/cxx-typeid.cpp b/clang/test/Parser/cxx-typeid.cpp
new file mode 100644
index 00000000000..1a6ffdbcd0a
--- /dev/null
+++ b/clang/test/Parser/cxx-typeid.cpp
@@ -0,0 +1,13 @@
+// RUN: clang -fsyntax-only -verify %s
+
+// FIXME: This should really include <typeinfo>, but we don't have that yet.
+namespace std {
+ class type_info;
+}
+
+void f()
+{
+ (void)typeid(int);
+ (void)typeid(0);
+ (void)typeid 1; // expected-error {{error: expected '(' after 'typeid'}}
+}
diff --git a/clang/test/SemaCXX/typeid.cpp b/clang/test/SemaCXX/typeid.cpp
new file mode 100644
index 00000000000..80a70a7b562
--- /dev/null
+++ b/clang/test/SemaCXX/typeid.cpp
@@ -0,0 +1,16 @@
+// RUN: clang -fsyntax-only -verify %s
+
+void f()
+{
+ (void)typeid(int); // expected-error {{error: you need to include <typeinfo> before using the 'typeid' operator}}
+}
+
+// FIXME: This should really include <typeinfo>, but we don't have that yet.
+namespace std {
+ class type_info;
+}
+
+void g()
+{
+ (void)typeid(int);
+}
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index 586cb2652b9..f4e3402584d 100644
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -466,9 +466,9 @@ welcome!</p>
</tr>
<tr>
<td>&nbsp;&nbsp;&nbsp;&nbsp;5.2.8 [expr.typeid]</td>
- <td></td>
- <td></td>
- <td></td>
+ <td class="complete" align="center">&#x2713;</td>
+ <td class="complete" align="center">&#x2713;</td>
+ <td class="complete" align="center">&#x2713;</td>
<td></td>
<td></td>
</tr>
OpenPOWER on IntegriCloud