Implement C++ 'typeid' parsing and sema.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59042 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index 8375720..82f95bf 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -243,7 +243,7 @@
 /// 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 c661145..e76bec6 100644
--- a/lib/Sema/IdentifierResolver.h
+++ b/lib/Sema/IdentifierResolver.h
@@ -31,7 +31,7 @@
   /// 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 @@
     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 @@
   /// 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 532be59..9c8d0c8 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -113,6 +113,10 @@
   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 3b187f2..7f72928 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -199,10 +199,18 @@
   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 @@
 
   /// 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 @@
 
   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 @@
                                        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 879a79b..b595ad7 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -193,7 +193,8 @@
 /// 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 @@
   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 a6a62a9..e420ce5 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) {