[cfe-commits] r170428 [2/3] - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Sema/ include/clang/Serialization/ lib/AST/ lib/CodeGen/ lib/Parse/ lib/Sema/ lib/Serialization/ test/CodeGenOpenCL/ test/PCH/ test/Parser/ tools/libclang/

Guy Benyei guy.benyei at intel.com
Tue Dec 18 04:30:04 PST 2012


Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=170428&r1=170427&r2=170428&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Tue Dec 18 06:30:03 2012
@@ -1,1574 +1,1580 @@
-//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file implements the tentative parsing portions of the Parser
-//  interfaces, for ambiguity resolution.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Parse/Parser.h"
-#include "clang/Parse/ParseDiagnostic.h"
-#include "clang/Sema/ParsedTemplate.h"
-using namespace clang;
-
-/// isCXXDeclarationStatement - C++-specialized function that disambiguates
-/// between a declaration or an expression statement, when parsing function
-/// bodies. Returns true for declaration, false for expression.
-///
-///         declaration-statement:
-///           block-declaration
-///
-///         block-declaration:
-///           simple-declaration
-///           asm-definition
-///           namespace-alias-definition
-///           using-declaration
-///           using-directive
-/// [C++0x]   static_assert-declaration
-///
-///         asm-definition:
-///           'asm' '(' string-literal ')' ';'
-///
-///         namespace-alias-definition:
-///           'namespace' identifier = qualified-namespace-specifier ';'
-///
-///         using-declaration:
-///           'using' typename[opt] '::'[opt] nested-name-specifier
-///                 unqualified-id ';'
-///           'using' '::' unqualified-id ;
-///
-///         using-directive:
-///           'using' 'namespace' '::'[opt] nested-name-specifier[opt]
-///                 namespace-name ';'
-///
-bool Parser::isCXXDeclarationStatement() {
-  switch (Tok.getKind()) {
-    // asm-definition
-  case tok::kw_asm:
-    // namespace-alias-definition
-  case tok::kw_namespace:
-    // using-declaration
-    // using-directive
-  case tok::kw_using:
-    // static_assert-declaration
-  case tok::kw_static_assert:
-  case tok::kw__Static_assert:
-    return true;
-    // simple-declaration
-  default:
-    return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);
-  }
-}
-
-/// isCXXSimpleDeclaration - C++-specialized function that disambiguates
-/// between a simple-declaration or an expression-statement.
-/// If during the disambiguation process a parsing error is encountered,
-/// the function returns true to let the declaration parsing code handle it.
-/// Returns false if the statement is disambiguated as expression.
-///
-/// simple-declaration:
-///   decl-specifier-seq init-declarator-list[opt] ';'
-///
-/// (if AllowForRangeDecl specified)
-/// for ( for-range-declaration : for-range-initializer ) statement
-/// for-range-declaration: 
-///    attribute-specifier-seqopt type-specifier-seq declarator
-bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
-  // C++ 6.8p1:
-  // There is an ambiguity in the grammar involving expression-statements and
-  // declarations: An expression-statement with a function-style explicit type
-  // conversion (5.2.3) as its leftmost subexpression can be indistinguishable
-  // from a declaration where the first declarator starts with a '('. In those
-  // cases the statement is a declaration. [Note: To disambiguate, the whole
-  // statement might have to be examined to determine if it is an
-  // expression-statement or a declaration].
-
-  // C++ 6.8p3:
-  // The disambiguation is purely syntactic; that is, the meaning of the names
-  // occurring in such a statement, beyond whether they are type-names or not,
-  // is not generally used in or changed by the disambiguation. Class
-  // templates are instantiated as necessary to determine if a qualified name
-  // is a type-name. Disambiguation precedes parsing, and a statement
-  // disambiguated as a declaration may be an ill-formed declaration.
-
-  // We don't have to parse all of the decl-specifier-seq part. There's only
-  // an ambiguity if the first decl-specifier is
-  // simple-type-specifier/typename-specifier followed by a '(', which may
-  // indicate a function-style cast expression.
-  // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such
-  // a case.
-
-  bool InvalidAsDeclaration = false;
-  TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),
-                                           &InvalidAsDeclaration);
-  if (TPR != TPResult::Ambiguous())
-    return TPR != TPResult::False(); // Returns true for TPResult::True() or
-                                     // TPResult::Error().
-
-  // FIXME: TryParseSimpleDeclaration doesn't look past the first initializer,
-  // and so gets some cases wrong. We can't carry on if we've already seen
-  // something which makes this statement invalid as a declaration in this case,
-  // since it can cause us to misparse valid code. Revisit this once
-  // TryParseInitDeclaratorList is fixed.
-  if (InvalidAsDeclaration)
-    return false;
-
-  // FIXME: Add statistics about the number of ambiguous statements encountered
-  // and how they were resolved (number of declarations+number of expressions).
-
-  // Ok, we have a simple-type-specifier/typename-specifier followed by a '(',
-  // or an identifier which doesn't resolve as anything. We need tentative
-  // parsing...
-
-  TentativeParsingAction PA(*this);
-  TPR = TryParseSimpleDeclaration(AllowForRangeDecl);
-  PA.Revert();
-
-  // In case of an error, let the declaration parsing code handle it.
-  if (TPR == TPResult::Error())
-    return true;
-
-  // Declarations take precedence over expressions.
-  if (TPR == TPResult::Ambiguous())
-    TPR = TPResult::True();
-
-  assert(TPR == TPResult::True() || TPR == TPResult::False());
-  return TPR == TPResult::True();
-}
-
-/// simple-declaration:
-///   decl-specifier-seq init-declarator-list[opt] ';'
-///
-/// (if AllowForRangeDecl specified)
-/// for ( for-range-declaration : for-range-initializer ) statement
-/// for-range-declaration: 
-///    attribute-specifier-seqopt type-specifier-seq declarator
-///
-Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
-  if (Tok.is(tok::kw_typeof))
-    TryParseTypeofSpecifier();
-  else {
-    if (Tok.is(tok::annot_cxxscope))
-      ConsumeToken();
-    ConsumeToken();
-
-    if (getLangOpts().ObjC1 && Tok.is(tok::less))
-      TryParseProtocolQualifiers();
-  }
-
-  // Two decl-specifiers in a row conclusively disambiguate this as being a
-  // simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the
-  // overwhelmingly common case that the next token is a '('.
-  if (Tok.isNot(tok::l_paren)) {
-    TPResult TPR = isCXXDeclarationSpecifier();
-    if (TPR == TPResult::Ambiguous())
-      return TPResult::True();
-    if (TPR == TPResult::True() || TPR == TPResult::Error())
-      return TPR;
-    assert(TPR == TPResult::False());
-  }
-
-  TPResult TPR = TryParseInitDeclaratorList();
-  if (TPR != TPResult::Ambiguous())
-    return TPR;
-
-  if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon)))
-    return TPResult::False();
-
-  return TPResult::Ambiguous();
-}
-
-///       init-declarator-list:
-///         init-declarator
-///         init-declarator-list ',' init-declarator
-///
-///       init-declarator:
-///         declarator initializer[opt]
-/// [GNU]   declarator simple-asm-expr[opt] attributes[opt] initializer[opt]
-///
-/// initializer:
-///   '=' initializer-clause
-///   '(' expression-list ')'
-///
-/// initializer-clause:
-///   assignment-expression
-///   '{' initializer-list ','[opt] '}'
-///   '{' '}'
-///
-Parser::TPResult Parser::TryParseInitDeclaratorList() {
-  while (1) {
-    // declarator
-    TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
-    if (TPR != TPResult::Ambiguous())
-      return TPR;
-
-    // [GNU] simple-asm-expr[opt] attributes[opt]
-    if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
-      return TPResult::True();
-
-    // initializer[opt]
-    if (Tok.is(tok::l_paren)) {
-      // Parse through the parens.
-      ConsumeParen();
-      if (!SkipUntil(tok::r_paren))
-        return TPResult::Error();
-    } else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
-      // MSVC and g++ won't examine the rest of declarators if '=' is 
-      // encountered; they just conclude that we have a declaration.
-      // EDG parses the initializer completely, which is the proper behavior
-      // for this case.
-      //
-      // At present, Clang follows MSVC and g++, since the parser does not have
-      // the ability to parse an expression fully without recording the
-      // results of that parse.
-      // Also allow 'in' after on objective-c declaration as in: 
-      // for (int (^b)(void) in array). Ideally this should be done in the 
-      // context of parsing for-init-statement of a foreach statement only. But,
-      // in any other context 'in' is invalid after a declaration and parser
-      // issues the error regardless of outcome of this decision.
-      // FIXME. Change if above assumption does not hold.
-      return TPResult::True();
-    }
-
-    if (Tok.isNot(tok::comma))
-      break;
-    ConsumeToken(); // the comma.
-  }
-
-  return TPResult::Ambiguous();
-}
-
-/// isCXXConditionDeclaration - Disambiguates between a declaration or an
-/// expression for a condition of a if/switch/while/for statement.
-/// If during the disambiguation process a parsing error is encountered,
-/// the function returns true to let the declaration parsing code handle it.
-///
-///       condition:
-///         expression
-///         type-specifier-seq declarator '=' assignment-expression
-/// [C++11] type-specifier-seq declarator '=' initializer-clause
-/// [C++11] type-specifier-seq declarator braced-init-list
-/// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
-///             '=' assignment-expression
-///
-bool Parser::isCXXConditionDeclaration() {
-  TPResult TPR = isCXXDeclarationSpecifier();
-  if (TPR != TPResult::Ambiguous())
-    return TPR != TPResult::False(); // Returns true for TPResult::True() or
-                                     // TPResult::Error().
-
-  // FIXME: Add statistics about the number of ambiguous statements encountered
-  // and how they were resolved (number of declarations+number of expressions).
-
-  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
-  // We need tentative parsing...
-
-  TentativeParsingAction PA(*this);
-
-  // type-specifier-seq
-  if (Tok.is(tok::kw_typeof))
-    TryParseTypeofSpecifier();
-  else {
-    ConsumeToken();
-    
-    if (getLangOpts().ObjC1 && Tok.is(tok::less))
-      TryParseProtocolQualifiers();
-  }
-  assert(Tok.is(tok::l_paren) && "Expected '('");
-
-  // declarator
-  TPR = TryParseDeclarator(false/*mayBeAbstract*/);
-
-  // In case of an error, let the declaration parsing code handle it.
-  if (TPR == TPResult::Error())
-    TPR = TPResult::True();
-
-  if (TPR == TPResult::Ambiguous()) {
-    // '='
-    // [GNU] simple-asm-expr[opt] attributes[opt]
-    if (Tok.is(tok::equal)  ||
-        Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
-      TPR = TPResult::True();
-    else if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace))
-      TPR = TPResult::True();
-    else
-      TPR = TPResult::False();
-  }
-
-  PA.Revert();
-
-  assert(TPR == TPResult::True() || TPR == TPResult::False());
-  return TPR == TPResult::True();
-}
-
-  /// \brief Determine whether the next set of tokens contains a type-id.
-  ///
-  /// The context parameter states what context we're parsing right
-  /// now, which affects how this routine copes with the token
-  /// following the type-id. If the context is TypeIdInParens, we have
-  /// already parsed the '(' and we will cease lookahead when we hit
-  /// the corresponding ')'. If the context is
-  /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
-  /// before this template argument, and will cease lookahead when we
-  /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id
-  /// and false for an expression.  If during the disambiguation
-  /// process a parsing error is encountered, the function returns
-  /// true to let the declaration parsing code handle it.
-  ///
-  /// type-id:
-  ///   type-specifier-seq abstract-declarator[opt]
-  ///
-bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
-
-  isAmbiguous = false;
-
-  // C++ 8.2p2:
-  // The ambiguity arising from the similarity between a function-style cast and
-  // a type-id can occur in different contexts. The ambiguity appears as a
-  // choice between a function-style cast expression and a declaration of a
-  // type. The resolution is that any construct that could possibly be a type-id
-  // in its syntactic context shall be considered a type-id.
-
-  TPResult TPR = isCXXDeclarationSpecifier();
-  if (TPR != TPResult::Ambiguous())
-    return TPR != TPResult::False(); // Returns true for TPResult::True() or
-                                     // TPResult::Error().
-
-  // FIXME: Add statistics about the number of ambiguous statements encountered
-  // and how they were resolved (number of declarations+number of expressions).
-
-  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
-  // We need tentative parsing...
-
-  TentativeParsingAction PA(*this);
-
-  // type-specifier-seq
-  if (Tok.is(tok::kw_typeof))
-    TryParseTypeofSpecifier();
-  else {
-    ConsumeToken();
-    
-    if (getLangOpts().ObjC1 && Tok.is(tok::less))
-      TryParseProtocolQualifiers();
-  }
-  
-  assert(Tok.is(tok::l_paren) && "Expected '('");
-
-  // declarator
-  TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
-
-  // In case of an error, let the declaration parsing code handle it.
-  if (TPR == TPResult::Error())
-    TPR = TPResult::True();
-
-  if (TPR == TPResult::Ambiguous()) {
-    // We are supposed to be inside parens, so if after the abstract declarator
-    // we encounter a ')' this is a type-id, otherwise it's an expression.
-    if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
-      TPR = TPResult::True();
-      isAmbiguous = true;
-
-    // We are supposed to be inside a template argument, so if after
-    // the abstract declarator we encounter a '>', '>>' (in C++0x), or
-    // ',', this is a type-id. Otherwise, it's an expression.
-    } else if (Context == TypeIdAsTemplateArgument &&
-               (Tok.is(tok::greater) || Tok.is(tok::comma) ||
-                (getLangOpts().CPlusPlus0x && Tok.is(tok::greatergreater)))) {
-      TPR = TPResult::True();
-      isAmbiguous = true;
-
-    } else
-      TPR = TPResult::False();
-  }
-
-  PA.Revert();
-
-  assert(TPR == TPResult::True() || TPR == TPResult::False());
-  return TPR == TPResult::True();
-}
-
-/// \brief Returns true if this is a C++11 attribute-specifier. Per
-/// C++11 [dcl.attr.grammar]p6, two consecutive left square bracket tokens
-/// always introduce an attribute. In Objective-C++11, this rule does not
-/// apply if either '[' begins a message-send.
-///
-/// If Disambiguate is true, we try harder to determine whether a '[[' starts
-/// an attribute-specifier, and return CAK_InvalidAttributeSpecifier if not.
-///
-/// If OuterMightBeMessageSend is true, we assume the outer '[' is either an
-/// Obj-C message send or the start of an attribute. Otherwise, we assume it
-/// is not an Obj-C message send.
-///
-/// C++11 [dcl.attr.grammar]:
-///
-///     attribute-specifier:
-///         '[' '[' attribute-list ']' ']'
-///         alignment-specifier
-///
-///     attribute-list:
-///         attribute[opt]
-///         attribute-list ',' attribute[opt]
-///         attribute '...'
-///         attribute-list ',' attribute '...'
-///
-///     attribute:
-///         attribute-token attribute-argument-clause[opt]
-///
-///     attribute-token:
-///         identifier
-///         identifier '::' identifier
-///
-///     attribute-argument-clause:
-///         '(' balanced-token-seq ')'
-Parser::CXX11AttributeKind
-Parser::isCXX11AttributeSpecifier(bool Disambiguate,
-                                  bool OuterMightBeMessageSend) {
-  if (Tok.is(tok::kw_alignas))
-    return CAK_AttributeSpecifier;
-
-  if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
-    return CAK_NotAttributeSpecifier;
-
-  // No tentative parsing if we don't need to look for ']]' or a lambda.
-  if (!Disambiguate && !getLangOpts().ObjC1)
-    return CAK_AttributeSpecifier;
-
-  TentativeParsingAction PA(*this);
-
-  // Opening brackets were checked for above.
-  ConsumeBracket();
-
-  // Outside Obj-C++11, treat anything with a matching ']]' as an attribute.
-  if (!getLangOpts().ObjC1) {
-    ConsumeBracket();
-
-    bool IsAttribute = SkipUntil(tok::r_square, false);
-    IsAttribute &= Tok.is(tok::r_square);
-
-    PA.Revert();
-
-    return IsAttribute ? CAK_AttributeSpecifier : CAK_InvalidAttributeSpecifier;
-  }
-
-  // In Obj-C++11, we need to distinguish four situations:
-  //  1a) int x[[attr]];                     C++11 attribute.
-  //  1b) [[attr]];                          C++11 statement attribute.
-  //   2) int x[[obj](){ return 1; }()];     Lambda in array size/index.
-  //  3a) int x[[obj get]];                  Message send in array size/index.
-  //  3b) [[Class alloc] init];              Message send in message send.
-  //   4) [[obj]{ return self; }() doStuff]; Lambda in message send.
-  // (1) is an attribute, (2) is ill-formed, and (3) and (4) are accepted.
-
-  // If we have a lambda-introducer, then this is definitely not a message send.
-  // FIXME: If this disambiguation is too slow, fold the tentative lambda parse
-  // into the tentative attribute parse below.
-  LambdaIntroducer Intro;
-  if (!TryParseLambdaIntroducer(Intro)) {
-    // A lambda cannot end with ']]', and an attribute must.
-    bool IsAttribute = Tok.is(tok::r_square);
-
-    PA.Revert();
-
-    if (IsAttribute)
-      // Case 1: C++11 attribute.
-      return CAK_AttributeSpecifier;
-
-    if (OuterMightBeMessageSend)
-      // Case 4: Lambda in message send.
-      return CAK_NotAttributeSpecifier;
-
-    // Case 2: Lambda in array size / index.
-    return CAK_InvalidAttributeSpecifier;
-  }
-
-  ConsumeBracket();
-
-  // If we don't have a lambda-introducer, then we have an attribute or a
-  // message-send.
-  bool IsAttribute = true;
-  while (Tok.isNot(tok::r_square)) {
-    if (Tok.is(tok::comma)) {
-      // Case 1: Stray commas can only occur in attributes.
-      PA.Revert();
-      return CAK_AttributeSpecifier;
-    }
-
-    // Parse the attribute-token, if present.
-    // C++11 [dcl.attr.grammar]:
-    //   If a keyword or an alternative token that satisfies the syntactic
-    //   requirements of an identifier is contained in an attribute-token,
-    //   it is considered an identifier.
-    SourceLocation Loc;
-    if (!TryParseCXX11AttributeIdentifier(Loc)) {
-      IsAttribute = false;
-      break;
-    }
-    if (Tok.is(tok::coloncolon)) {
-      ConsumeToken();
-      if (!TryParseCXX11AttributeIdentifier(Loc)) {
-        IsAttribute = false;
-        break;
-      }
-    }
-
-    // Parse the attribute-argument-clause, if present.
-    if (Tok.is(tok::l_paren)) {
-      ConsumeParen();
-      if (!SkipUntil(tok::r_paren, false)) {
-        IsAttribute = false;
-        break;
-      }
-    }
-
-    if (Tok.is(tok::ellipsis))
-      ConsumeToken();
-
-    if (Tok.isNot(tok::comma))
-      break;
-
-    ConsumeToken();
-  }
-
-  // An attribute must end ']]'.
-  if (IsAttribute) {
-    if (Tok.is(tok::r_square)) {
-      ConsumeBracket();
-      IsAttribute = Tok.is(tok::r_square);
-    } else {
-      IsAttribute = false;
-    }
-  }
-
-  PA.Revert();
-
-  if (IsAttribute)
-    // Case 1: C++11 statement attribute.
-    return CAK_AttributeSpecifier;
-
-  // Case 3: Message send.
-  return CAK_NotAttributeSpecifier;
-}
-
-///         declarator:
-///           direct-declarator
-///           ptr-operator declarator
-///
-///         direct-declarator:
-///           declarator-id
-///           direct-declarator '(' parameter-declaration-clause ')'
-///                 cv-qualifier-seq[opt] exception-specification[opt]
-///           direct-declarator '[' constant-expression[opt] ']'
-///           '(' declarator ')'
-/// [GNU]     '(' attributes declarator ')'
-///
-///         abstract-declarator:
-///           ptr-operator abstract-declarator[opt]
-///           direct-abstract-declarator
-///           ...
-///
-///         direct-abstract-declarator:
-///           direct-abstract-declarator[opt]
-///           '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
-///                 exception-specification[opt]
-///           direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
-///           '(' abstract-declarator ')'
-///
-///         ptr-operator:
-///           '*' cv-qualifier-seq[opt]
-///           '&'
-/// [C++0x]   '&&'                                                        [TODO]
-///           '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
-///
-///         cv-qualifier-seq:
-///           cv-qualifier cv-qualifier-seq[opt]
-///
-///         cv-qualifier:
-///           'const'
-///           'volatile'
-///
-///         declarator-id:
-///           '...'[opt] id-expression
-///
-///         id-expression:
-///           unqualified-id
-///           qualified-id                                                [TODO]
-///
-///         unqualified-id:
-///           identifier
-///           operator-function-id                                        [TODO]
-///           conversion-function-id                                      [TODO]
-///           '~' class-name                                              [TODO]
-///           template-id                                                 [TODO]
-///
-Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
-                                            bool mayHaveIdentifier) {
-  // declarator:
-  //   direct-declarator
-  //   ptr-operator declarator
-
-  while (1) {
-    if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
-      if (TryAnnotateCXXScopeToken(true))
-        return TPResult::Error();
-
-    if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
-        Tok.is(tok::ampamp) ||
-        (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
-      // ptr-operator
-      ConsumeToken();
-      while (Tok.is(tok::kw_const)    ||
-             Tok.is(tok::kw_volatile) ||
-             Tok.is(tok::kw_restrict))
-        ConsumeToken();
-    } else {
-      break;
-    }
-  }
-
-  // direct-declarator:
-  // direct-abstract-declarator:
-  if (Tok.is(tok::ellipsis))
-    ConsumeToken();
-  
-  if ((Tok.is(tok::identifier) ||
-       (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) &&
-      mayHaveIdentifier) {
-    // declarator-id
-    if (Tok.is(tok::annot_cxxscope))
-      ConsumeToken();
-    else
-      TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo());
-    ConsumeToken();
-  } else if (Tok.is(tok::l_paren)) {
-    ConsumeParen();
-    if (mayBeAbstract &&
-        (Tok.is(tok::r_paren) ||       // 'int()' is a function.
-         // 'int(...)' is a function.
-         (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren)) ||
-         isDeclarationSpecifier())) {   // 'int(int)' is a function.
-      // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
-      //        exception-specification[opt]
-      TPResult TPR = TryParseFunctionDeclarator();
-      if (TPR != TPResult::Ambiguous())
-        return TPR;
-    } else {
-      // '(' declarator ')'
-      // '(' attributes declarator ')'
-      // '(' abstract-declarator ')'
-      if (Tok.is(tok::kw___attribute) ||
-          Tok.is(tok::kw___declspec) ||
-          Tok.is(tok::kw___cdecl) ||
-          Tok.is(tok::kw___stdcall) ||
-          Tok.is(tok::kw___fastcall) ||
-          Tok.is(tok::kw___thiscall) ||
-          Tok.is(tok::kw___unaligned))
-        return TPResult::True(); // attributes indicate declaration
-      TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
-      if (TPR != TPResult::Ambiguous())
-        return TPR;
-      if (Tok.isNot(tok::r_paren))
-        return TPResult::False();
-      ConsumeParen();
-    }
-  } else if (!mayBeAbstract) {
-    return TPResult::False();
-  }
-
-  while (1) {
-    TPResult TPR(TPResult::Ambiguous());
-
-    // abstract-declarator: ...
-    if (Tok.is(tok::ellipsis))
-      ConsumeToken();
-
-    if (Tok.is(tok::l_paren)) {
-      // Check whether we have a function declarator or a possible ctor-style
-      // initializer that follows the declarator. Note that ctor-style
-      // initializers are not possible in contexts where abstract declarators
-      // are allowed.
-      if (!mayBeAbstract && !isCXXFunctionDeclarator())
-        break;
-
-      // direct-declarator '(' parameter-declaration-clause ')'
-      //        cv-qualifier-seq[opt] exception-specification[opt]
-      ConsumeParen();
-      TPR = TryParseFunctionDeclarator();
-    } else if (Tok.is(tok::l_square)) {
-      // direct-declarator '[' constant-expression[opt] ']'
-      // direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
-      TPR = TryParseBracketDeclarator();
-    } else {
-      break;
-    }
-
-    if (TPR != TPResult::Ambiguous())
-      return TPR;
-  }
-
-  return TPResult::Ambiguous();
-}
-
-Parser::TPResult 
-Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
-  switch (Kind) {
-  // Obviously starts an expression.
-  case tok::numeric_constant:
-  case tok::char_constant:
-  case tok::wide_char_constant:
-  case tok::utf16_char_constant:
-  case tok::utf32_char_constant:
-  case tok::string_literal:
-  case tok::wide_string_literal:
-  case tok::utf8_string_literal:
-  case tok::utf16_string_literal:
-  case tok::utf32_string_literal:
-  case tok::l_square:
-  case tok::l_paren:
-  case tok::amp:
-  case tok::ampamp:
-  case tok::star:
-  case tok::plus:
-  case tok::plusplus:
-  case tok::minus:
-  case tok::minusminus:
-  case tok::tilde:
-  case tok::exclaim:
-  case tok::kw_sizeof:
-  case tok::kw___func__:
-  case tok::kw_const_cast:
-  case tok::kw_delete:
-  case tok::kw_dynamic_cast:
-  case tok::kw_false:
-  case tok::kw_new:
-  case tok::kw_operator:
-  case tok::kw_reinterpret_cast:
-  case tok::kw_static_cast:
-  case tok::kw_this:
-  case tok::kw_throw:
-  case tok::kw_true:
-  case tok::kw_typeid:
-  case tok::kw_alignof:
-  case tok::kw_noexcept:
-  case tok::kw_nullptr:
-  case tok::kw__Alignof:
-  case tok::kw___null:
-  case tok::kw___alignof:
-  case tok::kw___builtin_choose_expr:
-  case tok::kw___builtin_offsetof:
-  case tok::kw___builtin_types_compatible_p:
-  case tok::kw___builtin_va_arg:
-  case tok::kw___imag:
-  case tok::kw___real:
-  case tok::kw___FUNCTION__:
-  case tok::kw_L__FUNCTION__:
-  case tok::kw___PRETTY_FUNCTION__:
-  case tok::kw___has_nothrow_assign:
-  case tok::kw___has_nothrow_copy:
-  case tok::kw___has_nothrow_constructor:
-  case tok::kw___has_trivial_assign:
-  case tok::kw___has_trivial_copy:
-  case tok::kw___has_trivial_constructor:
-  case tok::kw___has_trivial_destructor:
-  case tok::kw___has_virtual_destructor:
-  case tok::kw___is_abstract:
-  case tok::kw___is_base_of:
-  case tok::kw___is_class:
-  case tok::kw___is_convertible_to:
-  case tok::kw___is_empty:
-  case tok::kw___is_enum:
-  case tok::kw___is_interface_class:
-  case tok::kw___is_final:
-  case tok::kw___is_literal:
-  case tok::kw___is_literal_type:
-  case tok::kw___is_pod:
-  case tok::kw___is_polymorphic:
-  case tok::kw___is_trivial:
-  case tok::kw___is_trivially_assignable:
-  case tok::kw___is_trivially_constructible:
-  case tok::kw___is_trivially_copyable:
-  case tok::kw___is_union:
-  case tok::kw___uuidof:
-    return TPResult::True();
-      
-  // Obviously starts a type-specifier-seq:
-  case tok::kw_char:
-  case tok::kw_const:
-  case tok::kw_double:
-  case tok::kw_enum:
-  case tok::kw_half:
-  case tok::kw_float:
-  case tok::kw_int:
-  case tok::kw_long:
-  case tok::kw___int64:
-  case tok::kw___int128:
-  case tok::kw_restrict:
-  case tok::kw_short:
-  case tok::kw_signed:
-  case tok::kw_struct:
-  case tok::kw_union:
-  case tok::kw_unsigned:
-  case tok::kw_void:
-  case tok::kw_volatile:
-  case tok::kw__Bool:
-  case tok::kw__Complex:
-  case tok::kw_class:
-  case tok::kw_typename:
-  case tok::kw_wchar_t:
-  case tok::kw_char16_t:
-  case tok::kw_char32_t:
-  case tok::kw___underlying_type:
-  case tok::kw_thread_local:
-  case tok::kw__Decimal32:
-  case tok::kw__Decimal64:
-  case tok::kw__Decimal128:
-  case tok::kw___thread:
-  case tok::kw_typeof:
-  case tok::kw___cdecl:
-  case tok::kw___stdcall:
-  case tok::kw___fastcall:
-  case tok::kw___thiscall:
-  case tok::kw___unaligned:
-  case tok::kw___vector:
-  case tok::kw___pixel:
-  case tok::kw__Atomic:
-  case tok::kw___unknown_anytype:
-    return TPResult::False();
-
-  default:
-    break;
-  }
-  
-  return TPResult::Ambiguous();
-}
-
-bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
-  return std::find(TentativelyDeclaredIdentifiers.begin(),
-                   TentativelyDeclaredIdentifiers.end(), II)
-      != TentativelyDeclaredIdentifiers.end();
-}
-
-/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration
-/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could
-/// be either a decl-specifier or a function-style cast, and TPResult::Error()
-/// if a parsing error was found and reported.
-///
-/// If HasMissingTypename is provided, a name with a dependent scope specifier
-/// will be treated as ambiguous if the 'typename' keyword is missing. If this
-/// happens, *HasMissingTypename will be set to 'true'. This will also be used
-/// as an indicator that undeclared identifiers (which will trigger a later
-/// parse error) should be treated as types. Returns TPResult::Ambiguous() in
-/// such cases.
-///
-///         decl-specifier:
-///           storage-class-specifier
-///           type-specifier
-///           function-specifier
-///           'friend'
-///           'typedef'
-/// [C++0x]   'constexpr'
-/// [GNU]     attributes declaration-specifiers[opt]
-///
-///         storage-class-specifier:
-///           'register'
-///           'static'
-///           'extern'
-///           'mutable'
-///           'auto'
-/// [GNU]     '__thread'
-///
-///         function-specifier:
-///           'inline'
-///           'virtual'
-///           'explicit'
-///
-///         typedef-name:
-///           identifier
-///
-///         type-specifier:
-///           simple-type-specifier
-///           class-specifier
-///           enum-specifier
-///           elaborated-type-specifier
-///           typename-specifier
-///           cv-qualifier
-///
-///         simple-type-specifier:
-///           '::'[opt] nested-name-specifier[opt] type-name
-///           '::'[opt] nested-name-specifier 'template'
-///                 simple-template-id                              [TODO]
-///           'char'
-///           'wchar_t'
-///           'bool'
-///           'short'
-///           'int'
-///           'long'
-///           'signed'
-///           'unsigned'
-///           'float'
-///           'double'
-///           'void'
-/// [GNU]     typeof-specifier
-/// [GNU]     '_Complex'
-/// [C++0x]   'auto'                                                [TODO]
-/// [C++0x]   'decltype' ( expression )
-///
-///         type-name:
-///           class-name
-///           enum-name
-///           typedef-name
-///
-///         elaborated-type-specifier:
-///           class-key '::'[opt] nested-name-specifier[opt] identifier
-///           class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]
-///               simple-template-id
-///           'enum' '::'[opt] nested-name-specifier[opt] identifier
-///
-///         enum-name:
-///           identifier
-///
-///         enum-specifier:
-///           'enum' identifier[opt] '{' enumerator-list[opt] '}'
-///           'enum' identifier[opt] '{' enumerator-list ',' '}'
-///
-///         class-specifier:
-///           class-head '{' member-specification[opt] '}'
-///
-///         class-head:
-///           class-key identifier[opt] base-clause[opt]
-///           class-key nested-name-specifier identifier base-clause[opt]
-///           class-key nested-name-specifier[opt] simple-template-id
-///               base-clause[opt]
-///
-///         class-key:
-///           'class'
-///           'struct'
-///           'union'
-///
-///         cv-qualifier:
-///           'const'
-///           'volatile'
-/// [GNU]     restrict
-///
-Parser::TPResult
-Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
-                                  bool *HasMissingTypename) {
-  switch (Tok.getKind()) {
-  case tok::identifier: {
-    // Check for need to substitute AltiVec __vector keyword
-    // for "vector" identifier.
-    if (TryAltiVecVectorToken())
-      return TPResult::True();
-
-    const Token &Next = NextToken();
-    // In 'foo bar', 'foo' is always a type name outside of Objective-C.
-    if (!getLangOpts().ObjC1 && Next.is(tok::identifier))
-      return TPResult::True();
-
-    if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) {
-      // Determine whether this is a valid expression. If not, we will hit
-      // a parse error one way or another. In that case, tell the caller that
-      // this is ambiguous. Typo-correct to type and expression keywords and
-      // to types and identifiers, in order to try to recover from errors.
-      CorrectionCandidateCallback TypoCorrection;
-      TypoCorrection.WantRemainingKeywords = false;
-      switch (TryAnnotateName(false /* no nested name specifier */,
-                              &TypoCorrection)) {
-      case ANK_Error:
-        return TPResult::Error();
-      case ANK_TentativeDecl:
-        return TPResult::False();
-      case ANK_TemplateName:
-        // A bare type template-name which can't be a template template
-        // argument is an error, and was probably intended to be a type.
-        return GreaterThanIsOperator ? TPResult::True() : TPResult::False();
-      case ANK_Unresolved:
-        return HasMissingTypename ? TPResult::Ambiguous() : TPResult::False();
-      case ANK_Success:
-        break;
-      }
-      assert(Tok.isNot(tok::identifier) &&
-             "TryAnnotateName succeeded without producing an annotation");
-    } else {
-      // This might possibly be a type with a dependent scope specifier and
-      // a missing 'typename' keyword. Don't use TryAnnotateName in this case,
-      // since it will annotate as a primary expression, and we want to use the
-      // "missing 'typename'" logic.
-      if (TryAnnotateTypeOrScopeToken())
-        return TPResult::Error();
-      // If annotation failed, assume it's a non-type.
-      // FIXME: If this happens due to an undeclared identifier, treat it as
-      // ambiguous.
-      if (Tok.is(tok::identifier))
-        return TPResult::False();
-    }
-
-    // We annotated this token as something. Recurse to handle whatever we got.
-    return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
-  }
-
-  case tok::kw_typename:  // typename T::type
-    // Annotate typenames and C++ scope specifiers.  If we get one, just
-    // recurse to handle whatever we get.
-    if (TryAnnotateTypeOrScopeToken())
-      return TPResult::Error();
-    return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
-
-  case tok::coloncolon: {    // ::foo::bar
-    const Token &Next = NextToken();
-    if (Next.is(tok::kw_new) ||    // ::new
-        Next.is(tok::kw_delete))   // ::delete
-      return TPResult::False();
-  }
-    // Fall through.
-  case tok::kw_decltype:
-    // Annotate typenames and C++ scope specifiers.  If we get one, just
-    // recurse to handle whatever we get.
-    if (TryAnnotateTypeOrScopeToken())
-      return TPResult::Error();
-    return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
-
-    // decl-specifier:
-    //   storage-class-specifier
-    //   type-specifier
-    //   function-specifier
-    //   'friend'
-    //   'typedef'
-    //   'constexpr'
-  case tok::kw_friend:
-  case tok::kw_typedef:
-  case tok::kw_constexpr:
-    // storage-class-specifier
-  case tok::kw_register:
-  case tok::kw_static:
-  case tok::kw_extern:
-  case tok::kw_mutable:
-  case tok::kw_auto:
-  case tok::kw___thread:
-    // function-specifier
-  case tok::kw_inline:
-  case tok::kw_virtual:
-  case tok::kw_explicit:
-
-    // Modules
-  case tok::kw___module_private__:
-
-    // Debugger support
-  case tok::kw___unknown_anytype:
-      
-    // type-specifier:
-    //   simple-type-specifier
-    //   class-specifier
-    //   enum-specifier
-    //   elaborated-type-specifier
-    //   typename-specifier
-    //   cv-qualifier
-
-    // class-specifier
-    // elaborated-type-specifier
-  case tok::kw_class:
-  case tok::kw_struct:
-  case tok::kw_union:
-    // enum-specifier
-  case tok::kw_enum:
-    // cv-qualifier
-  case tok::kw_const:
-  case tok::kw_volatile:
-
-    // GNU
-  case tok::kw_restrict:
-  case tok::kw__Complex:
-  case tok::kw___attribute:
-    return TPResult::True();
-
-    // Microsoft
-  case tok::kw___declspec:
-  case tok::kw___cdecl:
-  case tok::kw___stdcall:
-  case tok::kw___fastcall:
-  case tok::kw___thiscall:
-  case tok::kw___w64:
-  case tok::kw___ptr64:
-  case tok::kw___ptr32:
-  case tok::kw___forceinline:
-  case tok::kw___unaligned:
-    return TPResult::True();
-
-    // Borland
-  case tok::kw___pascal:
-    return TPResult::True();
-  
-    // AltiVec
-  case tok::kw___vector:
-    return TPResult::True();
-
-  case tok::annot_template_id: {
-    TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
-    if (TemplateId->Kind != TNK_Type_template)
-      return TPResult::False();
-    CXXScopeSpec SS;
-    AnnotateTemplateIdTokenAsType();
-    assert(Tok.is(tok::annot_typename));
-    goto case_typename;
-  }
-
-  case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
-    // We've already annotated a scope; try to annotate a type.
-    if (TryAnnotateTypeOrScopeToken())
-      return TPResult::Error();
-    if (!Tok.is(tok::annot_typename)) {
-      // If the next token is an identifier or a type qualifier, then this
-      // can't possibly be a valid expression either.
-      if (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier)) {
-        CXXScopeSpec SS;
-        Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
-                                                     Tok.getAnnotationRange(),
-                                                     SS);
-        if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) {
-          TentativeParsingAction PA(*this);
-          ConsumeToken();
-          ConsumeToken();
-          bool isIdentifier = Tok.is(tok::identifier);
-          TPResult TPR = TPResult::False();
-          if (!isIdentifier)
-            TPR = isCXXDeclarationSpecifier(BracedCastResult,
-                                            HasMissingTypename);
-          PA.Revert();
-
-          if (isIdentifier ||
-              TPR == TPResult::True() || TPR == TPResult::Error())
-            return TPResult::Error();
-
-          if (HasMissingTypename) {
-            // We can't tell whether this is a missing 'typename' or a valid
-            // expression.
-            *HasMissingTypename = true;
-            return TPResult::Ambiguous();
-          }
-        } else {
-          // Try to resolve the name. If it doesn't exist, assume it was
-          // intended to name a type and keep disambiguating.
-          switch (TryAnnotateName(false /* SS is not dependent */)) {
-          case ANK_Error:
-            return TPResult::Error();
-          case ANK_TentativeDecl:
-            return TPResult::False();
-          case ANK_TemplateName:
-            // A bare type template-name which can't be a template template
-            // argument is an error, and was probably intended to be a type.
-            return GreaterThanIsOperator ? TPResult::True() : TPResult::False();
-          case ANK_Unresolved:
-            return HasMissingTypename ? TPResult::Ambiguous()
-                                      : TPResult::False();
-          case ANK_Success:
-            // Annotated it, check again.
-            assert(Tok.isNot(tok::annot_cxxscope) ||
-                   NextToken().isNot(tok::identifier));
-            return isCXXDeclarationSpecifier(BracedCastResult,
-                                             HasMissingTypename);
-          }
-        }
-      }
-      return TPResult::False();
-    }
-    // If that succeeded, fallthrough into the generic simple-type-id case.
-
-    // The ambiguity resides in a simple-type-specifier/typename-specifier
-    // followed by a '('. The '(' could either be the start of:
-    //
-    //   direct-declarator:
-    //     '(' declarator ')'
-    //
-    //   direct-abstract-declarator:
-    //     '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
-    //              exception-specification[opt]
-    //     '(' abstract-declarator ')'
-    //
-    // or part of a function-style cast expression:
-    //
-    //     simple-type-specifier '(' expression-list[opt] ')'
-    //
-
-    // simple-type-specifier:
-
-  case tok::annot_typename:
-  case_typename:
-    // In Objective-C, we might have a protocol-qualified type.
-    if (getLangOpts().ObjC1 && NextToken().is(tok::less)) {
-      // Tentatively parse the 
-      TentativeParsingAction PA(*this);
-      ConsumeToken(); // The type token
-      
-      TPResult TPR = TryParseProtocolQualifiers();
-      bool isFollowedByParen = Tok.is(tok::l_paren);
-      bool isFollowedByBrace = Tok.is(tok::l_brace);
-      
-      PA.Revert();
-      
-      if (TPR == TPResult::Error())
-        return TPResult::Error();
-      
-      if (isFollowedByParen)
-        return TPResult::Ambiguous();
-
-      if (getLangOpts().CPlusPlus0x && isFollowedByBrace)
-        return BracedCastResult;
-      
-      return TPResult::True();
-    }
-      
-  case tok::kw_char:
-  case tok::kw_wchar_t:
-  case tok::kw_char16_t:
-  case tok::kw_char32_t:
-  case tok::kw_bool:
-  case tok::kw_short:
-  case tok::kw_int:
-  case tok::kw_long:
-  case tok::kw___int64:
-  case tok::kw___int128:
-  case tok::kw_signed:
-  case tok::kw_unsigned:
-  case tok::kw_half:
-  case tok::kw_float:
-  case tok::kw_double:
-  case tok::kw_void:
-  case tok::annot_decltype:
-    if (NextToken().is(tok::l_paren))
-      return TPResult::Ambiguous();
-
-    // This is a function-style cast in all cases we disambiguate other than
-    // one:
-    //   struct S {
-    //     enum E : int { a = 4 }; // enum
-    //     enum E : int { 4 };     // bit-field
-    //   };
-    if (getLangOpts().CPlusPlus0x && NextToken().is(tok::l_brace))
-      return BracedCastResult;
-
-    if (isStartOfObjCClassMessageMissingOpenBracket())
-      return TPResult::False();
-      
-    return TPResult::True();
-
-  // GNU typeof support.
-  case tok::kw_typeof: {
-    if (NextToken().isNot(tok::l_paren))
-      return TPResult::True();
-
-    TentativeParsingAction PA(*this);
-
-    TPResult TPR = TryParseTypeofSpecifier();
-    bool isFollowedByParen = Tok.is(tok::l_paren);
-    bool isFollowedByBrace = Tok.is(tok::l_brace);
-
-    PA.Revert();
-
-    if (TPR == TPResult::Error())
-      return TPResult::Error();
-
-    if (isFollowedByParen)
-      return TPResult::Ambiguous();
-
-    if (getLangOpts().CPlusPlus0x && isFollowedByBrace)
-      return BracedCastResult;
-
-    return TPResult::True();
-  }
-
-  // C++0x type traits support
-  case tok::kw___underlying_type:
-    return TPResult::True();
-
-  // C11 _Atomic
-  case tok::kw__Atomic:
-    return TPResult::True();
-
-  default:
-    return TPResult::False();
-  }
-}
-
-/// [GNU] typeof-specifier:
-///         'typeof' '(' expressions ')'
-///         'typeof' '(' type-name ')'
-///
-Parser::TPResult Parser::TryParseTypeofSpecifier() {
-  assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!");
-  ConsumeToken();
-
-  assert(Tok.is(tok::l_paren) && "Expected '('");
-  // Parse through the parens after 'typeof'.
-  ConsumeParen();
-  if (!SkipUntil(tok::r_paren))
-    return TPResult::Error();
-
-  return TPResult::Ambiguous();
-}
-
-/// [ObjC] protocol-qualifiers:
-////         '<' identifier-list '>'
-Parser::TPResult Parser::TryParseProtocolQualifiers() {
-  assert(Tok.is(tok::less) && "Expected '<' for qualifier list");
-  ConsumeToken();
-  do {
-    if (Tok.isNot(tok::identifier))
-      return TPResult::Error();
-    ConsumeToken();
-    
-    if (Tok.is(tok::comma)) {
-      ConsumeToken();
-      continue;
-    }
-    
-    if (Tok.is(tok::greater)) {
-      ConsumeToken();
-      return TPResult::Ambiguous();
-    }
-  } while (false);
-  
-  return TPResult::Error();
-}
-
-Parser::TPResult
-Parser::TryParseDeclarationSpecifier(bool *HasMissingTypename) {
-  TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),
-                                           HasMissingTypename);
-  if (TPR != TPResult::Ambiguous())
-    return TPR;
-
-  if (Tok.is(tok::kw_typeof))
-    TryParseTypeofSpecifier();
-  else {
-    if (Tok.is(tok::annot_cxxscope))
-      ConsumeToken();
-    ConsumeToken();
-    
-    if (getLangOpts().ObjC1 && Tok.is(tok::less))
-      TryParseProtocolQualifiers();
-  }
-
-  return TPResult::Ambiguous();
-}
-
-/// isCXXFunctionDeclarator - Disambiguates between a function declarator or
-/// a constructor-style initializer, when parsing declaration statements.
-/// Returns true for function declarator and false for constructor-style
-/// initializer.
-/// If during the disambiguation process a parsing error is encountered,
-/// the function returns true to let the declaration parsing code handle it.
-///
-/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
-///         exception-specification[opt]
-///
-bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) {
-
-  // C++ 8.2p1:
-  // The ambiguity arising from the similarity between a function-style cast and
-  // a declaration mentioned in 6.8 can also occur in the context of a
-  // declaration. In that context, the choice is between a function declaration
-  // with a redundant set of parentheses around a parameter name and an object
-  // declaration with a function-style cast as the initializer. Just as for the
-  // ambiguities mentioned in 6.8, the resolution is to consider any construct
-  // that could possibly be a declaration a declaration.
-
-  TentativeParsingAction PA(*this);
-
-  ConsumeParen();
-  bool InvalidAsDeclaration = false;
-  TPResult TPR = TryParseParameterDeclarationClause(&InvalidAsDeclaration);
-  if (TPR == TPResult::Ambiguous()) {
-    if (Tok.isNot(tok::r_paren))
-      TPR = TPResult::False();
-    else {
-      const Token &Next = NextToken();
-      if (Next.is(tok::amp) || Next.is(tok::ampamp) ||
-          Next.is(tok::kw_const) || Next.is(tok::kw_volatile) ||
-          Next.is(tok::kw_throw) || Next.is(tok::kw_noexcept) ||
-          Next.is(tok::l_square) || isCXX0XVirtSpecifier(Next) ||
-          Next.is(tok::l_brace) || Next.is(tok::kw_try) ||
-          Next.is(tok::equal) || Next.is(tok::arrow))
-        // The next token cannot appear after a constructor-style initializer,
-        // and can appear next in a function definition. This must be a function
-        // declarator.
-        TPR = TPResult::True();
-      else if (InvalidAsDeclaration)
-        // Use the absence of 'typename' as a tie-breaker.
-        TPR = TPResult::False();
-    }
-  }
-
-  PA.Revert();
-
-  if (IsAmbiguous && TPR == TPResult::Ambiguous())
-    *IsAmbiguous = true;
-
-  // In case of an error, let the declaration parsing code handle it.
-  return TPR != TPResult::False();
-}
-
-/// parameter-declaration-clause:
-///   parameter-declaration-list[opt] '...'[opt]
-///   parameter-declaration-list ',' '...'
-///
-/// parameter-declaration-list:
-///   parameter-declaration
-///   parameter-declaration-list ',' parameter-declaration
-///
-/// parameter-declaration:
-///   attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]
-///   attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]
-///     '=' assignment-expression
-///   attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]
-///     attributes[opt]
-///   attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]
-///     attributes[opt] '=' assignment-expression
-///
-Parser::TPResult
-Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration) {
-
-  if (Tok.is(tok::r_paren))
-    return TPResult::Ambiguous();
-
-  //   parameter-declaration-list[opt] '...'[opt]
-  //   parameter-declaration-list ',' '...'
-  //
-  // parameter-declaration-list:
-  //   parameter-declaration
-  //   parameter-declaration-list ',' parameter-declaration
-  //
-  while (1) {
-    // '...'[opt]
-    if (Tok.is(tok::ellipsis)) {
-      ConsumeToken();
-      if (Tok.is(tok::r_paren))
-        return TPResult::True(); // '...)' is a sign of a function declarator.
-      else
-        return TPResult::False();
-    }
-
-    // An attribute-specifier-seq here is a sign of a function declarator.
-    if (isCXX11AttributeSpecifier(/*Disambiguate*/false,
-                                  /*OuterMightBeMessageSend*/true))
-      return TPResult::True();
-
-    ParsedAttributes attrs(AttrFactory);
-    MaybeParseMicrosoftAttributes(attrs);
-
-    // decl-specifier-seq
-    // A parameter-declaration's initializer must be preceded by an '=', so
-    // decl-specifier-seq '{' is not a parameter in C++11.
-    TPResult TPR = TryParseDeclarationSpecifier(InvalidAsDeclaration);
-    if (TPR != TPResult::Ambiguous())
-      return TPR;
-
-    // declarator
-    // abstract-declarator[opt]
-    TPR = TryParseDeclarator(true/*mayBeAbstract*/);
-    if (TPR != TPResult::Ambiguous())
-      return TPR;
-
-    // [GNU] attributes[opt]
-    if (Tok.is(tok::kw___attribute))
-      return TPResult::True();
-
-    if (Tok.is(tok::equal)) {
-      // '=' assignment-expression
-      // Parse through assignment-expression.
-      if (!SkipUntil(tok::comma, tok::r_paren, true/*StopAtSemi*/,
-                     true/*DontConsume*/))
-        return TPResult::Error();
-    }
-
-    if (Tok.is(tok::ellipsis)) {
-      ConsumeToken();
-      if (Tok.is(tok::r_paren))
-        return TPResult::True(); // '...)' is a sign of a function declarator.
-      else
-        return TPResult::False();
-    }
-
-    if (Tok.isNot(tok::comma))
-      break;
-    ConsumeToken(); // the comma.
-  }
-
-  return TPResult::Ambiguous();
-}
-
-/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
-/// parsing as a function declarator.
-/// If TryParseFunctionDeclarator fully parsed the function declarator, it will
-/// return TPResult::Ambiguous(), otherwise it will return either False() or
-/// Error().
-///
-/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
-///         exception-specification[opt]
-///
-/// exception-specification:
-///   'throw' '(' type-id-list[opt] ')'
-///
-Parser::TPResult Parser::TryParseFunctionDeclarator() {
-
-  // The '(' is already parsed.
-
-  TPResult TPR = TryParseParameterDeclarationClause();
-  if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
-    TPR = TPResult::False();
-
-  if (TPR == TPResult::False() || TPR == TPResult::Error())
-    return TPR;
-
-  // Parse through the parens.
-  if (!SkipUntil(tok::r_paren))
-    return TPResult::Error();
-
-  // cv-qualifier-seq
-  while (Tok.is(tok::kw_const)    ||
-         Tok.is(tok::kw_volatile) ||
-         Tok.is(tok::kw_restrict)   )
-    ConsumeToken();
-
-  // ref-qualifier[opt]
-  if (Tok.is(tok::amp) || Tok.is(tok::ampamp))
-    ConsumeToken();
-  
-  // exception-specification
-  if (Tok.is(tok::kw_throw)) {
-    ConsumeToken();
-    if (Tok.isNot(tok::l_paren))
-      return TPResult::Error();
-
-    // Parse through the parens after 'throw'.
-    ConsumeParen();
-    if (!SkipUntil(tok::r_paren))
-      return TPResult::Error();
-  }
-  if (Tok.is(tok::kw_noexcept)) {
-    ConsumeToken();
-    // Possibly an expression as well.
-    if (Tok.is(tok::l_paren)) {
-      // Find the matching rparen.
-      ConsumeParen();
-      if (!SkipUntil(tok::r_paren))
-        return TPResult::Error();
-    }
-  }
-
-  return TPResult::Ambiguous();
-}
-
-/// '[' constant-expression[opt] ']'
-///
-Parser::TPResult Parser::TryParseBracketDeclarator() {
-  ConsumeBracket();
-  if (!SkipUntil(tok::r_square))
-    return TPResult::Error();
-
-  return TPResult::Ambiguous();
-}
+//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the tentative parsing portions of the Parser
+//  interfaces, for ambiguity resolution.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Sema/ParsedTemplate.h"
+using namespace clang;
+
+/// isCXXDeclarationStatement - C++-specialized function that disambiguates
+/// between a declaration or an expression statement, when parsing function
+/// bodies. Returns true for declaration, false for expression.
+///
+///         declaration-statement:
+///           block-declaration
+///
+///         block-declaration:
+///           simple-declaration
+///           asm-definition
+///           namespace-alias-definition
+///           using-declaration
+///           using-directive
+/// [C++0x]   static_assert-declaration
+///
+///         asm-definition:
+///           'asm' '(' string-literal ')' ';'
+///
+///         namespace-alias-definition:
+///           'namespace' identifier = qualified-namespace-specifier ';'
+///
+///         using-declaration:
+///           'using' typename[opt] '::'[opt] nested-name-specifier
+///                 unqualified-id ';'
+///           'using' '::' unqualified-id ;
+///
+///         using-directive:
+///           'using' 'namespace' '::'[opt] nested-name-specifier[opt]
+///                 namespace-name ';'
+///
+bool Parser::isCXXDeclarationStatement() {
+  switch (Tok.getKind()) {
+    // asm-definition
+  case tok::kw_asm:
+    // namespace-alias-definition
+  case tok::kw_namespace:
+    // using-declaration
+    // using-directive
+  case tok::kw_using:
+    // static_assert-declaration
+  case tok::kw_static_assert:
+  case tok::kw__Static_assert:
+    return true;
+    // simple-declaration
+  default:
+    return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);
+  }
+}
+
+/// isCXXSimpleDeclaration - C++-specialized function that disambiguates
+/// between a simple-declaration or an expression-statement.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+/// Returns false if the statement is disambiguated as expression.
+///
+/// simple-declaration:
+///   decl-specifier-seq init-declarator-list[opt] ';'
+///
+/// (if AllowForRangeDecl specified)
+/// for ( for-range-declaration : for-range-initializer ) statement
+/// for-range-declaration: 
+///    attribute-specifier-seqopt type-specifier-seq declarator
+bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
+  // C++ 6.8p1:
+  // There is an ambiguity in the grammar involving expression-statements and
+  // declarations: An expression-statement with a function-style explicit type
+  // conversion (5.2.3) as its leftmost subexpression can be indistinguishable
+  // from a declaration where the first declarator starts with a '('. In those
+  // cases the statement is a declaration. [Note: To disambiguate, the whole
+  // statement might have to be examined to determine if it is an
+  // expression-statement or a declaration].
+
+  // C++ 6.8p3:
+  // The disambiguation is purely syntactic; that is, the meaning of the names
+  // occurring in such a statement, beyond whether they are type-names or not,
+  // is not generally used in or changed by the disambiguation. Class
+  // templates are instantiated as necessary to determine if a qualified name
+  // is a type-name. Disambiguation precedes parsing, and a statement
+  // disambiguated as a declaration may be an ill-formed declaration.
+
+  // We don't have to parse all of the decl-specifier-seq part. There's only
+  // an ambiguity if the first decl-specifier is
+  // simple-type-specifier/typename-specifier followed by a '(', which may
+  // indicate a function-style cast expression.
+  // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such
+  // a case.
+
+  bool InvalidAsDeclaration = false;
+  TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),
+                                           &InvalidAsDeclaration);
+  if (TPR != TPResult::Ambiguous())
+    return TPR != TPResult::False(); // Returns true for TPResult::True() or
+                                     // TPResult::Error().
+
+  // FIXME: TryParseSimpleDeclaration doesn't look past the first initializer,
+  // and so gets some cases wrong. We can't carry on if we've already seen
+  // something which makes this statement invalid as a declaration in this case,
+  // since it can cause us to misparse valid code. Revisit this once
+  // TryParseInitDeclaratorList is fixed.
+  if (InvalidAsDeclaration)
+    return false;
+
+  // FIXME: Add statistics about the number of ambiguous statements encountered
+  // and how they were resolved (number of declarations+number of expressions).
+
+  // Ok, we have a simple-type-specifier/typename-specifier followed by a '(',
+  // or an identifier which doesn't resolve as anything. We need tentative
+  // parsing...
+
+  TentativeParsingAction PA(*this);
+  TPR = TryParseSimpleDeclaration(AllowForRangeDecl);
+  PA.Revert();
+
+  // In case of an error, let the declaration parsing code handle it.
+  if (TPR == TPResult::Error())
+    return true;
+
+  // Declarations take precedence over expressions.
+  if (TPR == TPResult::Ambiguous())
+    TPR = TPResult::True();
+
+  assert(TPR == TPResult::True() || TPR == TPResult::False());
+  return TPR == TPResult::True();
+}
+
+/// simple-declaration:
+///   decl-specifier-seq init-declarator-list[opt] ';'
+///
+/// (if AllowForRangeDecl specified)
+/// for ( for-range-declaration : for-range-initializer ) statement
+/// for-range-declaration: 
+///    attribute-specifier-seqopt type-specifier-seq declarator
+///
+Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
+  if (Tok.is(tok::kw_typeof))
+    TryParseTypeofSpecifier();
+  else {
+    if (Tok.is(tok::annot_cxxscope))
+      ConsumeToken();
+    ConsumeToken();
+
+    if (getLangOpts().ObjC1 && Tok.is(tok::less))
+      TryParseProtocolQualifiers();
+  }
+
+  // Two decl-specifiers in a row conclusively disambiguate this as being a
+  // simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the
+  // overwhelmingly common case that the next token is a '('.
+  if (Tok.isNot(tok::l_paren)) {
+    TPResult TPR = isCXXDeclarationSpecifier();
+    if (TPR == TPResult::Ambiguous())
+      return TPResult::True();
+    if (TPR == TPResult::True() || TPR == TPResult::Error())
+      return TPR;
+    assert(TPR == TPResult::False());
+  }
+
+  TPResult TPR = TryParseInitDeclaratorList();
+  if (TPR != TPResult::Ambiguous())
+    return TPR;
+
+  if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon)))
+    return TPResult::False();
+
+  return TPResult::Ambiguous();
+}
+
+///       init-declarator-list:
+///         init-declarator
+///         init-declarator-list ',' init-declarator
+///
+///       init-declarator:
+///         declarator initializer[opt]
+/// [GNU]   declarator simple-asm-expr[opt] attributes[opt] initializer[opt]
+///
+/// initializer:
+///   '=' initializer-clause
+///   '(' expression-list ')'
+///
+/// initializer-clause:
+///   assignment-expression
+///   '{' initializer-list ','[opt] '}'
+///   '{' '}'
+///
+Parser::TPResult Parser::TryParseInitDeclaratorList() {
+  while (1) {
+    // declarator
+    TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
+    if (TPR != TPResult::Ambiguous())
+      return TPR;
+
+    // [GNU] simple-asm-expr[opt] attributes[opt]
+    if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+      return TPResult::True();
+
+    // initializer[opt]
+    if (Tok.is(tok::l_paren)) {
+      // Parse through the parens.
+      ConsumeParen();
+      if (!SkipUntil(tok::r_paren))
+        return TPResult::Error();
+    } else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
+      // MSVC and g++ won't examine the rest of declarators if '=' is 
+      // encountered; they just conclude that we have a declaration.
+      // EDG parses the initializer completely, which is the proper behavior
+      // for this case.
+      //
+      // At present, Clang follows MSVC and g++, since the parser does not have
+      // the ability to parse an expression fully without recording the
+      // results of that parse.
+      // Also allow 'in' after on objective-c declaration as in: 
+      // for (int (^b)(void) in array). Ideally this should be done in the 
+      // context of parsing for-init-statement of a foreach statement only. But,
+      // in any other context 'in' is invalid after a declaration and parser
+      // issues the error regardless of outcome of this decision.
+      // FIXME. Change if above assumption does not hold.
+      return TPResult::True();
+    }
+
+    if (Tok.isNot(tok::comma))
+      break;
+    ConsumeToken(); // the comma.
+  }
+
+  return TPResult::Ambiguous();
+}
+
+/// isCXXConditionDeclaration - Disambiguates between a declaration or an
+/// expression for a condition of a if/switch/while/for statement.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+///
+///       condition:
+///         expression
+///         type-specifier-seq declarator '=' assignment-expression
+/// [C++11] type-specifier-seq declarator '=' initializer-clause
+/// [C++11] type-specifier-seq declarator braced-init-list
+/// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
+///             '=' assignment-expression
+///
+bool Parser::isCXXConditionDeclaration() {
+  TPResult TPR = isCXXDeclarationSpecifier();
+  if (TPR != TPResult::Ambiguous())
+    return TPR != TPResult::False(); // Returns true for TPResult::True() or
+                                     // TPResult::Error().
+
+  // FIXME: Add statistics about the number of ambiguous statements encountered
+  // and how they were resolved (number of declarations+number of expressions).
+
+  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
+  // We need tentative parsing...
+
+  TentativeParsingAction PA(*this);
+
+  // type-specifier-seq
+  if (Tok.is(tok::kw_typeof))
+    TryParseTypeofSpecifier();
+  else {
+    ConsumeToken();
+    
+    if (getLangOpts().ObjC1 && Tok.is(tok::less))
+      TryParseProtocolQualifiers();
+  }
+  assert(Tok.is(tok::l_paren) && "Expected '('");
+
+  // declarator
+  TPR = TryParseDeclarator(false/*mayBeAbstract*/);
+
+  // In case of an error, let the declaration parsing code handle it.
+  if (TPR == TPResult::Error())
+    TPR = TPResult::True();
+
+  if (TPR == TPResult::Ambiguous()) {
+    // '='
+    // [GNU] simple-asm-expr[opt] attributes[opt]
+    if (Tok.is(tok::equal)  ||
+        Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+      TPR = TPResult::True();
+    else if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace))
+      TPR = TPResult::True();
+    else
+      TPR = TPResult::False();
+  }
+
+  PA.Revert();
+
+  assert(TPR == TPResult::True() || TPR == TPResult::False());
+  return TPR == TPResult::True();
+}
+
+  /// \brief Determine whether the next set of tokens contains a type-id.
+  ///
+  /// The context parameter states what context we're parsing right
+  /// now, which affects how this routine copes with the token
+  /// following the type-id. If the context is TypeIdInParens, we have
+  /// already parsed the '(' and we will cease lookahead when we hit
+  /// the corresponding ')'. If the context is
+  /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
+  /// before this template argument, and will cease lookahead when we
+  /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id
+  /// and false for an expression.  If during the disambiguation
+  /// process a parsing error is encountered, the function returns
+  /// true to let the declaration parsing code handle it.
+  ///
+  /// type-id:
+  ///   type-specifier-seq abstract-declarator[opt]
+  ///
+bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
+
+  isAmbiguous = false;
+
+  // C++ 8.2p2:
+  // The ambiguity arising from the similarity between a function-style cast and
+  // a type-id can occur in different contexts. The ambiguity appears as a
+  // choice between a function-style cast expression and a declaration of a
+  // type. The resolution is that any construct that could possibly be a type-id
+  // in its syntactic context shall be considered a type-id.
+
+  TPResult TPR = isCXXDeclarationSpecifier();
+  if (TPR != TPResult::Ambiguous())
+    return TPR != TPResult::False(); // Returns true for TPResult::True() or
+                                     // TPResult::Error().
+
+  // FIXME: Add statistics about the number of ambiguous statements encountered
+  // and how they were resolved (number of declarations+number of expressions).
+
+  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
+  // We need tentative parsing...
+
+  TentativeParsingAction PA(*this);
+
+  // type-specifier-seq
+  if (Tok.is(tok::kw_typeof))
+    TryParseTypeofSpecifier();
+  else {
+    ConsumeToken();
+    
+    if (getLangOpts().ObjC1 && Tok.is(tok::less))
+      TryParseProtocolQualifiers();
+  }
+  
+  assert(Tok.is(tok::l_paren) && "Expected '('");
+
+  // declarator
+  TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
+
+  // In case of an error, let the declaration parsing code handle it.
+  if (TPR == TPResult::Error())
+    TPR = TPResult::True();
+
+  if (TPR == TPResult::Ambiguous()) {
+    // We are supposed to be inside parens, so if after the abstract declarator
+    // we encounter a ')' this is a type-id, otherwise it's an expression.
+    if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
+      TPR = TPResult::True();
+      isAmbiguous = true;
+
+    // We are supposed to be inside a template argument, so if after
+    // the abstract declarator we encounter a '>', '>>' (in C++0x), or
+    // ',', this is a type-id. Otherwise, it's an expression.
+    } else if (Context == TypeIdAsTemplateArgument &&
+               (Tok.is(tok::greater) || Tok.is(tok::comma) ||
+                (getLangOpts().CPlusPlus0x && Tok.is(tok::greatergreater)))) {
+      TPR = TPResult::True();
+      isAmbiguous = true;
+
+    } else
+      TPR = TPResult::False();
+  }
+
+  PA.Revert();
+
+  assert(TPR == TPResult::True() || TPR == TPResult::False());
+  return TPR == TPResult::True();
+}
+
+/// \brief Returns true if this is a C++11 attribute-specifier. Per
+/// C++11 [dcl.attr.grammar]p6, two consecutive left square bracket tokens
+/// always introduce an attribute. In Objective-C++11, this rule does not
+/// apply if either '[' begins a message-send.
+///
+/// If Disambiguate is true, we try harder to determine whether a '[[' starts
+/// an attribute-specifier, and return CAK_InvalidAttributeSpecifier if not.
+///
+/// If OuterMightBeMessageSend is true, we assume the outer '[' is either an
+/// Obj-C message send or the start of an attribute. Otherwise, we assume it
+/// is not an Obj-C message send.
+///
+/// C++11 [dcl.attr.grammar]:
+///
+///     attribute-specifier:
+///         '[' '[' attribute-list ']' ']'
+///         alignment-specifier
+///
+///     attribute-list:
+///         attribute[opt]
+///         attribute-list ',' attribute[opt]
+///         attribute '...'
+///         attribute-list ',' attribute '...'
+///
+///     attribute:
+///         attribute-token attribute-argument-clause[opt]
+///
+///     attribute-token:
+///         identifier
+///         identifier '::' identifier
+///
+///     attribute-argument-clause:
+///         '(' balanced-token-seq ')'
+Parser::CXX11AttributeKind
+Parser::isCXX11AttributeSpecifier(bool Disambiguate,
+                                  bool OuterMightBeMessageSend) {
+  if (Tok.is(tok::kw_alignas))
+    return CAK_AttributeSpecifier;
+
+  if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
+    return CAK_NotAttributeSpecifier;
+
+  // No tentative parsing if we don't need to look for ']]' or a lambda.
+  if (!Disambiguate && !getLangOpts().ObjC1)
+    return CAK_AttributeSpecifier;
+
+  TentativeParsingAction PA(*this);
+
+  // Opening brackets were checked for above.
+  ConsumeBracket();
+
+  // Outside Obj-C++11, treat anything with a matching ']]' as an attribute.
+  if (!getLangOpts().ObjC1) {
+    ConsumeBracket();
+
+    bool IsAttribute = SkipUntil(tok::r_square, false);
+    IsAttribute &= Tok.is(tok::r_square);
+
+    PA.Revert();
+
+    return IsAttribute ? CAK_AttributeSpecifier : CAK_InvalidAttributeSpecifier;
+  }
+
+  // In Obj-C++11, we need to distinguish four situations:
+  //  1a) int x[[attr]];                     C++11 attribute.
+  //  1b) [[attr]];                          C++11 statement attribute.
+  //   2) int x[[obj](){ return 1; }()];     Lambda in array size/index.
+  //  3a) int x[[obj get]];                  Message send in array size/index.
+  //  3b) [[Class alloc] init];              Message send in message send.
+  //   4) [[obj]{ return self; }() doStuff]; Lambda in message send.
+  // (1) is an attribute, (2) is ill-formed, and (3) and (4) are accepted.
+
+  // If we have a lambda-introducer, then this is definitely not a message send.
+  // FIXME: If this disambiguation is too slow, fold the tentative lambda parse
+  // into the tentative attribute parse below.
+  LambdaIntroducer Intro;
+  if (!TryParseLambdaIntroducer(Intro)) {
+    // A lambda cannot end with ']]', and an attribute must.
+    bool IsAttribute = Tok.is(tok::r_square);
+
+    PA.Revert();
+
+    if (IsAttribute)
+      // Case 1: C++11 attribute.
+      return CAK_AttributeSpecifier;
+
+    if (OuterMightBeMessageSend)
+      // Case 4: Lambda in message send.
+      return CAK_NotAttributeSpecifier;
+
+    // Case 2: Lambda in array size / index.
+    return CAK_InvalidAttributeSpecifier;
+  }
+
+  ConsumeBracket();
+
+  // If we don't have a lambda-introducer, then we have an attribute or a
+  // message-send.
+  bool IsAttribute = true;
+  while (Tok.isNot(tok::r_square)) {
+    if (Tok.is(tok::comma)) {
+      // Case 1: Stray commas can only occur in attributes.
+      PA.Revert();
+      return CAK_AttributeSpecifier;
+    }
+
+    // Parse the attribute-token, if present.
+    // C++11 [dcl.attr.grammar]:
+    //   If a keyword or an alternative token that satisfies the syntactic
+    //   requirements of an identifier is contained in an attribute-token,
+    //   it is considered an identifier.
+    SourceLocation Loc;
+    if (!TryParseCXX11AttributeIdentifier(Loc)) {
+      IsAttribute = false;
+      break;
+    }
+    if (Tok.is(tok::coloncolon)) {
+      ConsumeToken();
+      if (!TryParseCXX11AttributeIdentifier(Loc)) {
+        IsAttribute = false;
+        break;
+      }
+    }
+
+    // Parse the attribute-argument-clause, if present.
+    if (Tok.is(tok::l_paren)) {
+      ConsumeParen();
+      if (!SkipUntil(tok::r_paren, false)) {
+        IsAttribute = false;
+        break;
+      }
+    }
+
+    if (Tok.is(tok::ellipsis))
+      ConsumeToken();
+
+    if (Tok.isNot(tok::comma))
+      break;
+
+    ConsumeToken();
+  }
+
+  // An attribute must end ']]'.
+  if (IsAttribute) {
+    if (Tok.is(tok::r_square)) {
+      ConsumeBracket();
+      IsAttribute = Tok.is(tok::r_square);
+    } else {
+      IsAttribute = false;
+    }
+  }
+
+  PA.Revert();
+
+  if (IsAttribute)
+    // Case 1: C++11 statement attribute.
+    return CAK_AttributeSpecifier;
+
+  // Case 3: Message send.
+  return CAK_NotAttributeSpecifier;
+}
+
+///         declarator:
+///           direct-declarator
+///           ptr-operator declarator
+///
+///         direct-declarator:
+///           declarator-id
+///           direct-declarator '(' parameter-declaration-clause ')'
+///                 cv-qualifier-seq[opt] exception-specification[opt]
+///           direct-declarator '[' constant-expression[opt] ']'
+///           '(' declarator ')'
+/// [GNU]     '(' attributes declarator ')'
+///
+///         abstract-declarator:
+///           ptr-operator abstract-declarator[opt]
+///           direct-abstract-declarator
+///           ...
+///
+///         direct-abstract-declarator:
+///           direct-abstract-declarator[opt]
+///           '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+///                 exception-specification[opt]
+///           direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
+///           '(' abstract-declarator ')'
+///
+///         ptr-operator:
+///           '*' cv-qualifier-seq[opt]
+///           '&'
+/// [C++0x]   '&&'                                                        [TODO]
+///           '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
+///
+///         cv-qualifier-seq:
+///           cv-qualifier cv-qualifier-seq[opt]
+///
+///         cv-qualifier:
+///           'const'
+///           'volatile'
+///
+///         declarator-id:
+///           '...'[opt] id-expression
+///
+///         id-expression:
+///           unqualified-id
+///           qualified-id                                                [TODO]
+///
+///         unqualified-id:
+///           identifier
+///           operator-function-id                                        [TODO]
+///           conversion-function-id                                      [TODO]
+///           '~' class-name                                              [TODO]
+///           template-id                                                 [TODO]
+///
+Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
+                                            bool mayHaveIdentifier) {
+  // declarator:
+  //   direct-declarator
+  //   ptr-operator declarator
+
+  while (1) {
+    if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
+      if (TryAnnotateCXXScopeToken(true))
+        return TPResult::Error();
+
+    if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
+        Tok.is(tok::ampamp) ||
+        (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
+      // ptr-operator
+      ConsumeToken();
+      while (Tok.is(tok::kw_const)    ||
+             Tok.is(tok::kw_volatile) ||
+             Tok.is(tok::kw_restrict))
+        ConsumeToken();
+    } else {
+      break;
+    }
+  }
+
+  // direct-declarator:
+  // direct-abstract-declarator:
+  if (Tok.is(tok::ellipsis))
+    ConsumeToken();
+  
+  if ((Tok.is(tok::identifier) ||
+       (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) &&
+      mayHaveIdentifier) {
+    // declarator-id
+    if (Tok.is(tok::annot_cxxscope))
+      ConsumeToken();
+    else
+      TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo());
+    ConsumeToken();
+  } else if (Tok.is(tok::l_paren)) {
+    ConsumeParen();
+    if (mayBeAbstract &&
+        (Tok.is(tok::r_paren) ||       // 'int()' is a function.
+         // 'int(...)' is a function.
+         (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren)) ||
+         isDeclarationSpecifier())) {   // 'int(int)' is a function.
+      // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+      //        exception-specification[opt]
+      TPResult TPR = TryParseFunctionDeclarator();
+      if (TPR != TPResult::Ambiguous())
+        return TPR;
+    } else {
+      // '(' declarator ')'
+      // '(' attributes declarator ')'
+      // '(' abstract-declarator ')'
+      if (Tok.is(tok::kw___attribute) ||
+          Tok.is(tok::kw___declspec) ||
+          Tok.is(tok::kw___cdecl) ||
+          Tok.is(tok::kw___stdcall) ||
+          Tok.is(tok::kw___fastcall) ||
+          Tok.is(tok::kw___thiscall) ||
+          Tok.is(tok::kw___unaligned))
+        return TPResult::True(); // attributes indicate declaration
+      TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
+      if (TPR != TPResult::Ambiguous())
+        return TPR;
+      if (Tok.isNot(tok::r_paren))
+        return TPResult::False();
+      ConsumeParen();
+    }
+  } else if (!mayBeAbstract) {
+    return TPResult::False();
+  }
+
+  while (1) {
+    TPResult TPR(TPResult::Ambiguous());
+
+    // abstract-declarator: ...
+    if (Tok.is(tok::ellipsis))
+      ConsumeToken();
+
+    if (Tok.is(tok::l_paren)) {
+      // Check whether we have a function declarator or a possible ctor-style
+      // initializer that follows the declarator. Note that ctor-style
+      // initializers are not possible in contexts where abstract declarators
+      // are allowed.
+      if (!mayBeAbstract && !isCXXFunctionDeclarator())
+        break;
+
+      // direct-declarator '(' parameter-declaration-clause ')'
+      //        cv-qualifier-seq[opt] exception-specification[opt]
+      ConsumeParen();
+      TPR = TryParseFunctionDeclarator();
+    } else if (Tok.is(tok::l_square)) {
+      // direct-declarator '[' constant-expression[opt] ']'
+      // direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
+      TPR = TryParseBracketDeclarator();
+    } else {
+      break;
+    }
+
+    if (TPR != TPResult::Ambiguous())
+      return TPR;
+  }
+
+  return TPResult::Ambiguous();
+}
+
+Parser::TPResult 
+Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
+  switch (Kind) {
+  // Obviously starts an expression.
+  case tok::numeric_constant:
+  case tok::char_constant:
+  case tok::wide_char_constant:
+  case tok::utf16_char_constant:
+  case tok::utf32_char_constant:
+  case tok::string_literal:
+  case tok::wide_string_literal:
+  case tok::utf8_string_literal:
+  case tok::utf16_string_literal:
+  case tok::utf32_string_literal:
+  case tok::l_square:
+  case tok::l_paren:
+  case tok::amp:
+  case tok::ampamp:
+  case tok::star:
+  case tok::plus:
+  case tok::plusplus:
+  case tok::minus:
+  case tok::minusminus:
+  case tok::tilde:
+  case tok::exclaim:
+  case tok::kw_sizeof:
+  case tok::kw___func__:
+  case tok::kw_const_cast:
+  case tok::kw_delete:
+  case tok::kw_dynamic_cast:
+  case tok::kw_false:
+  case tok::kw_new:
+  case tok::kw_operator:
+  case tok::kw_reinterpret_cast:
+  case tok::kw_static_cast:
+  case tok::kw_this:
+  case tok::kw_throw:
+  case tok::kw_true:
+  case tok::kw_typeid:
+  case tok::kw_alignof:
+  case tok::kw_noexcept:
+  case tok::kw_nullptr:
+  case tok::kw__Alignof:
+  case tok::kw___null:
+  case tok::kw___alignof:
+  case tok::kw___builtin_choose_expr:
+  case tok::kw___builtin_offsetof:
+  case tok::kw___builtin_types_compatible_p:
+  case tok::kw___builtin_va_arg:
+  case tok::kw___imag:
+  case tok::kw___real:
+  case tok::kw___FUNCTION__:
+  case tok::kw_L__FUNCTION__:
+  case tok::kw___PRETTY_FUNCTION__:
+  case tok::kw___has_nothrow_assign:
+  case tok::kw___has_nothrow_copy:
+  case tok::kw___has_nothrow_constructor:
+  case tok::kw___has_trivial_assign:
+  case tok::kw___has_trivial_copy:
+  case tok::kw___has_trivial_constructor:
+  case tok::kw___has_trivial_destructor:
+  case tok::kw___has_virtual_destructor:
+  case tok::kw___is_abstract:
+  case tok::kw___is_base_of:
+  case tok::kw___is_class:
+  case tok::kw___is_convertible_to:
+  case tok::kw___is_empty:
+  case tok::kw___is_enum:
+  case tok::kw___is_interface_class:
+  case tok::kw___is_final:
+  case tok::kw___is_literal:
+  case tok::kw___is_literal_type:
+  case tok::kw___is_pod:
+  case tok::kw___is_polymorphic:
+  case tok::kw___is_trivial:
+  case tok::kw___is_trivially_assignable:
+  case tok::kw___is_trivially_constructible:
+  case tok::kw___is_trivially_copyable:
+  case tok::kw___is_union:
+  case tok::kw___uuidof:
+    return TPResult::True();
+      
+  // Obviously starts a type-specifier-seq:
+  case tok::kw_char:
+  case tok::kw_const:
+  case tok::kw_double:
+  case tok::kw_enum:
+  case tok::kw_half:
+  case tok::kw_float:
+  case tok::kw_int:
+  case tok::kw_long:
+  case tok::kw___int64:
+  case tok::kw___int128:
+  case tok::kw_restrict:
+  case tok::kw_short:
+  case tok::kw_signed:
+  case tok::kw_struct:
+  case tok::kw_union:
+  case tok::kw_unsigned:
+  case tok::kw_void:
+  case tok::kw_volatile:
+  case tok::kw__Bool:
+  case tok::kw__Complex:
+  case tok::kw_class:
+  case tok::kw_typename:
+  case tok::kw_wchar_t:
+  case tok::kw_char16_t:
+  case tok::kw_char32_t:
+  case tok::kw___underlying_type:
+  case tok::kw_thread_local:
+  case tok::kw__Decimal32:
+  case tok::kw__Decimal64:
+  case tok::kw__Decimal128:
+  case tok::kw___thread:
+  case tok::kw_typeof:
+  case tok::kw___cdecl:
+  case tok::kw___stdcall:
+  case tok::kw___fastcall:
+  case tok::kw___thiscall:
+  case tok::kw___unaligned:
+  case tok::kw___vector:
+  case tok::kw___pixel:
+  case tok::kw__Atomic:
+  case tok::kw_image1d_t:
+  case tok::kw_image1d_array_t:
+  case tok::kw_image1d_buffer_t:
+  case tok::kw_image2d_t:
+  case tok::kw_image2d_array_t:
+  case tok::kw_image3d_t:
+  case tok::kw___unknown_anytype:
+    return TPResult::False();
+
+  default:
+    break;
+  }
+  
+  return TPResult::Ambiguous();
+}
+
+bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
+  return std::find(TentativelyDeclaredIdentifiers.begin(),
+                   TentativelyDeclaredIdentifiers.end(), II)
+      != TentativelyDeclaredIdentifiers.end();
+}
+
+/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration
+/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could
+/// be either a decl-specifier or a function-style cast, and TPResult::Error()
+/// if a parsing error was found and reported.
+///
+/// If HasMissingTypename is provided, a name with a dependent scope specifier
+/// will be treated as ambiguous if the 'typename' keyword is missing. If this
+/// happens, *HasMissingTypename will be set to 'true'. This will also be used
+/// as an indicator that undeclared identifiers (which will trigger a later
+/// parse error) should be treated as types. Returns TPResult::Ambiguous() in
+/// such cases.
+///
+///         decl-specifier:
+///           storage-class-specifier
+///           type-specifier
+///           function-specifier
+///           'friend'
+///           'typedef'
+/// [C++0x]   'constexpr'
+/// [GNU]     attributes declaration-specifiers[opt]
+///
+///         storage-class-specifier:
+///           'register'
+///           'static'
+///           'extern'
+///           'mutable'
+///           'auto'
+/// [GNU]     '__thread'
+///
+///         function-specifier:
+///           'inline'
+///           'virtual'
+///           'explicit'
+///
+///         typedef-name:
+///           identifier
+///
+///         type-specifier:
+///           simple-type-specifier
+///           class-specifier
+///           enum-specifier
+///           elaborated-type-specifier
+///           typename-specifier
+///           cv-qualifier
+///
+///         simple-type-specifier:
+///           '::'[opt] nested-name-specifier[opt] type-name
+///           '::'[opt] nested-name-specifier 'template'
+///                 simple-template-id                              [TODO]
+///           'char'
+///           'wchar_t'
+///           'bool'
+///           'short'
+///           'int'
+///           'long'
+///           'signed'
+///           'unsigned'
+///           'float'
+///           'double'
+///           'void'
+/// [GNU]     typeof-specifier
+/// [GNU]     '_Complex'
+/// [C++0x]   'auto'                                                [TODO]
+/// [C++0x]   'decltype' ( expression )
+///
+///         type-name:
+///           class-name
+///           enum-name
+///           typedef-name
+///
+///         elaborated-type-specifier:
+///           class-key '::'[opt] nested-name-specifier[opt] identifier
+///           class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]
+///               simple-template-id
+///           'enum' '::'[opt] nested-name-specifier[opt] identifier
+///
+///         enum-name:
+///           identifier
+///
+///         enum-specifier:
+///           'enum' identifier[opt] '{' enumerator-list[opt] '}'
+///           'enum' identifier[opt] '{' enumerator-list ',' '}'
+///
+///         class-specifier:
+///           class-head '{' member-specification[opt] '}'
+///
+///         class-head:
+///           class-key identifier[opt] base-clause[opt]
+///           class-key nested-name-specifier identifier base-clause[opt]
+///           class-key nested-name-specifier[opt] simple-template-id
+///               base-clause[opt]
+///
+///         class-key:
+///           'class'
+///           'struct'
+///           'union'
+///
+///         cv-qualifier:
+///           'const'
+///           'volatile'
+/// [GNU]     restrict
+///
+Parser::TPResult
+Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
+                                  bool *HasMissingTypename) {
+  switch (Tok.getKind()) {
+  case tok::identifier: {
+    // Check for need to substitute AltiVec __vector keyword
+    // for "vector" identifier.
+    if (TryAltiVecVectorToken())
+      return TPResult::True();
+
+    const Token &Next = NextToken();
+    // In 'foo bar', 'foo' is always a type name outside of Objective-C.
+    if (!getLangOpts().ObjC1 && Next.is(tok::identifier))
+      return TPResult::True();
+
+    if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) {
+      // Determine whether this is a valid expression. If not, we will hit
+      // a parse error one way or another. In that case, tell the caller that
+      // this is ambiguous. Typo-correct to type and expression keywords and
+      // to types and identifiers, in order to try to recover from errors.
+      CorrectionCandidateCallback TypoCorrection;
+      TypoCorrection.WantRemainingKeywords = false;
+      switch (TryAnnotateName(false /* no nested name specifier */,
+                              &TypoCorrection)) {
+      case ANK_Error:
+        return TPResult::Error();
+      case ANK_TentativeDecl:
+        return TPResult::False();
+      case ANK_TemplateName:
+        // A bare type template-name which can't be a template template
+        // argument is an error, and was probably intended to be a type.
+        return GreaterThanIsOperator ? TPResult::True() : TPResult::False();
+      case ANK_Unresolved:
+        return HasMissingTypename ? TPResult::Ambiguous() : TPResult::False();
+      case ANK_Success:
+        break;
+      }
+      assert(Tok.isNot(tok::identifier) &&
+             "TryAnnotateName succeeded without producing an annotation");
+    } else {
+      // This might possibly be a type with a dependent scope specifier and
+      // a missing 'typename' keyword. Don't use TryAnnotateName in this case,
+      // since it will annotate as a primary expression, and we want to use the
+      // "missing 'typename'" logic.
+      if (TryAnnotateTypeOrScopeToken())
+        return TPResult::Error();
+      // If annotation failed, assume it's a non-type.
+      // FIXME: If this happens due to an undeclared identifier, treat it as
+      // ambiguous.
+      if (Tok.is(tok::identifier))
+        return TPResult::False();
+    }
+
+    // We annotated this token as something. Recurse to handle whatever we got.
+    return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
+  }
+
+  case tok::kw_typename:  // typename T::type
+    // Annotate typenames and C++ scope specifiers.  If we get one, just
+    // recurse to handle whatever we get.
+    if (TryAnnotateTypeOrScopeToken())
+      return TPResult::Error();
+    return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
+
+  case tok::coloncolon: {    // ::foo::bar
+    const Token &Next = NextToken();
+    if (Next.is(tok::kw_new) ||    // ::new
+        Next.is(tok::kw_delete))   // ::delete
+      return TPResult::False();
+  }
+    // Fall through.
+  case tok::kw_decltype:
+    // Annotate typenames and C++ scope specifiers.  If we get one, just
+    // recurse to handle whatever we get.
+    if (TryAnnotateTypeOrScopeToken())
+      return TPResult::Error();
+    return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
+
+    // decl-specifier:
+    //   storage-class-specifier
+    //   type-specifier
+    //   function-specifier
+    //   'friend'
+    //   'typedef'
+    //   'constexpr'
+  case tok::kw_friend:
+  case tok::kw_typedef:
+  case tok::kw_constexpr:
+    // storage-class-specifier
+  case tok::kw_register:
+  case tok::kw_static:
+  case tok::kw_extern:
+  case tok::kw_mutable:
+  case tok::kw_auto:
+  case tok::kw___thread:
+    // function-specifier
+  case tok::kw_inline:
+  case tok::kw_virtual:
+  case tok::kw_explicit:
+
+    // Modules
+  case tok::kw___module_private__:
+
+    // Debugger support
+  case tok::kw___unknown_anytype:
+      
+    // type-specifier:
+    //   simple-type-specifier
+    //   class-specifier
+    //   enum-specifier
+    //   elaborated-type-specifier
+    //   typename-specifier
+    //   cv-qualifier
+
+    // class-specifier
+    // elaborated-type-specifier
+  case tok::kw_class:
+  case tok::kw_struct:
+  case tok::kw_union:
+    // enum-specifier
+  case tok::kw_enum:
+    // cv-qualifier
+  case tok::kw_const:
+  case tok::kw_volatile:
+
+    // GNU
+  case tok::kw_restrict:
+  case tok::kw__Complex:
+  case tok::kw___attribute:
+    return TPResult::True();
+
+    // Microsoft
+  case tok::kw___declspec:
+  case tok::kw___cdecl:
+  case tok::kw___stdcall:
+  case tok::kw___fastcall:
+  case tok::kw___thiscall:
+  case tok::kw___w64:
+  case tok::kw___ptr64:
+  case tok::kw___ptr32:
+  case tok::kw___forceinline:
+  case tok::kw___unaligned:
+    return TPResult::True();
+
+    // Borland
+  case tok::kw___pascal:
+    return TPResult::True();
+  
+    // AltiVec
+  case tok::kw___vector:
+    return TPResult::True();
+
+  case tok::annot_template_id: {
+    TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
+    if (TemplateId->Kind != TNK_Type_template)
+      return TPResult::False();
+    CXXScopeSpec SS;
+    AnnotateTemplateIdTokenAsType();
+    assert(Tok.is(tok::annot_typename));
+    goto case_typename;
+  }
+
+  case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
+    // We've already annotated a scope; try to annotate a type.
+    if (TryAnnotateTypeOrScopeToken())
+      return TPResult::Error();
+    if (!Tok.is(tok::annot_typename)) {
+      // If the next token is an identifier or a type qualifier, then this
+      // can't possibly be a valid expression either.
+      if (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier)) {
+        CXXScopeSpec SS;
+        Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
+                                                     Tok.getAnnotationRange(),
+                                                     SS);
+        if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) {
+          TentativeParsingAction PA(*this);
+          ConsumeToken();
+          ConsumeToken();
+          bool isIdentifier = Tok.is(tok::identifier);
+          TPResult TPR = TPResult::False();
+          if (!isIdentifier)
+            TPR = isCXXDeclarationSpecifier(BracedCastResult,
+                                            HasMissingTypename);
+          PA.Revert();
+
+          if (isIdentifier ||
+              TPR == TPResult::True() || TPR == TPResult::Error())
+            return TPResult::Error();
+
+          if (HasMissingTypename) {
+            // We can't tell whether this is a missing 'typename' or a valid
+            // expression.
+            *HasMissingTypename = true;
+            return TPResult::Ambiguous();
+          }
+        } else {
+          // Try to resolve the name. If it doesn't exist, assume it was
+          // intended to name a type and keep disambiguating.
+          switch (TryAnnotateName(false /* SS is not dependent */)) {
+          case ANK_Error:
+            return TPResult::Error();
+          case ANK_TentativeDecl:
+            return TPResult::False();
+          case ANK_TemplateName:
+            // A bare type template-name which can't be a template template
+            // argument is an error, and was probably intended to be a type.
+            return GreaterThanIsOperator ? TPResult::True() : TPResult::False();
+          case ANK_Unresolved:
+            return HasMissingTypename ? TPResult::Ambiguous()
+                                      : TPResult::False();
+          case ANK_Success:
+            // Annotated it, check again.
+            assert(Tok.isNot(tok::annot_cxxscope) ||
+                   NextToken().isNot(tok::identifier));
+            return isCXXDeclarationSpecifier(BracedCastResult,
+                                             HasMissingTypename);
+          }
+        }
+      }
+      return TPResult::False();
+    }
+    // If that succeeded, fallthrough into the generic simple-type-id case.
+
+    // The ambiguity resides in a simple-type-specifier/typename-specifier
+    // followed by a '('. The '(' could either be the start of:
+    //
+    //   direct-declarator:
+    //     '(' declarator ')'
+    //
+    //   direct-abstract-declarator:
+    //     '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+    //              exception-specification[opt]
+    //     '(' abstract-declarator ')'
+    //
+    // or part of a function-style cast expression:
+    //
+    //     simple-type-specifier '(' expression-list[opt] ')'
+    //
+
+    // simple-type-specifier:
+
+  case tok::annot_typename:
+  case_typename:
+    // In Objective-C, we might have a protocol-qualified type.
+    if (getLangOpts().ObjC1 && NextToken().is(tok::less)) {
+      // Tentatively parse the 
+      TentativeParsingAction PA(*this);
+      ConsumeToken(); // The type token
+      
+      TPResult TPR = TryParseProtocolQualifiers();
+      bool isFollowedByParen = Tok.is(tok::l_paren);
+      bool isFollowedByBrace = Tok.is(tok::l_brace);
+      
+      PA.Revert();
+      
+      if (TPR == TPResult::Error())
+        return TPResult::Error();
+      
+      if (isFollowedByParen)
+        return TPResult::Ambiguous();
+
+      if (getLangOpts().CPlusPlus0x && isFollowedByBrace)
+        return BracedCastResult;
+      
+      return TPResult::True();
+    }
+      
+  case tok::kw_char:
+  case tok::kw_wchar_t:
+  case tok::kw_char16_t:
+  case tok::kw_char32_t:
+  case tok::kw_bool:
+  case tok::kw_short:
+  case tok::kw_int:
+  case tok::kw_long:
+  case tok::kw___int64:
+  case tok::kw___int128:
+  case tok::kw_signed:
+  case tok::kw_unsigned:
+  case tok::kw_half:
+  case tok::kw_float:
+  case tok::kw_double:
+  case tok::kw_void:
+  case tok::annot_decltype:
+    if (NextToken().is(tok::l_paren))
+      return TPResult::Ambiguous();
+
+    // This is a function-style cast in all cases we disambiguate other than
+    // one:
+    //   struct S {
+    //     enum E : int { a = 4 }; // enum
+    //     enum E : int { 4 };     // bit-field
+    //   };
+    if (getLangOpts().CPlusPlus0x && NextToken().is(tok::l_brace))
+      return BracedCastResult;
+
+    if (isStartOfObjCClassMessageMissingOpenBracket())
+      return TPResult::False();
+      
+    return TPResult::True();
+
+  // GNU typeof support.
+  case tok::kw_typeof: {
+    if (NextToken().isNot(tok::l_paren))
+      return TPResult::True();
+
+    TentativeParsingAction PA(*this);
+
+    TPResult TPR = TryParseTypeofSpecifier();
+    bool isFollowedByParen = Tok.is(tok::l_paren);
+    bool isFollowedByBrace = Tok.is(tok::l_brace);
+
+    PA.Revert();
+
+    if (TPR == TPResult::Error())
+      return TPResult::Error();
+
+    if (isFollowedByParen)
+      return TPResult::Ambiguous();
+
+    if (getLangOpts().CPlusPlus0x && isFollowedByBrace)
+      return BracedCastResult;
+
+    return TPResult::True();
+  }
+
+  // C++0x type traits support
+  case tok::kw___underlying_type:
+    return TPResult::True();
+
+  // C11 _Atomic
+  case tok::kw__Atomic:
+    return TPResult::True();
+
+  default:
+    return TPResult::False();
+  }
+}
+
+/// [GNU] typeof-specifier:
+///         'typeof' '(' expressions ')'
+///         'typeof' '(' type-name ')'
+///
+Parser::TPResult Parser::TryParseTypeofSpecifier() {
+  assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!");
+  ConsumeToken();
+
+  assert(Tok.is(tok::l_paren) && "Expected '('");
+  // Parse through the parens after 'typeof'.
+  ConsumeParen();
+  if (!SkipUntil(tok::r_paren))
+    return TPResult::Error();
+
+  return TPResult::Ambiguous();
+}
+
+/// [ObjC] protocol-qualifiers:
+////         '<' identifier-list '>'
+Parser::TPResult Parser::TryParseProtocolQualifiers() {
+  assert(Tok.is(tok::less) && "Expected '<' for qualifier list");
+  ConsumeToken();
+  do {
+    if (Tok.isNot(tok::identifier))
+      return TPResult::Error();
+    ConsumeToken();
+    
+    if (Tok.is(tok::comma)) {
+      ConsumeToken();
+      continue;
+    }
+    
+    if (Tok.is(tok::greater)) {
+      ConsumeToken();
+      return TPResult::Ambiguous();
+    }
+  } while (false);
+  
+  return TPResult::Error();
+}
+
+Parser::TPResult
+Parser::TryParseDeclarationSpecifier(bool *HasMissingTypename) {
+  TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),
+                                           HasMissingTypename);
+  if (TPR != TPResult::Ambiguous())
+    return TPR;
+
+  if (Tok.is(tok::kw_typeof))
+    TryParseTypeofSpecifier();
+  else {
+    if (Tok.is(tok::annot_cxxscope))
+      ConsumeToken();
+    ConsumeToken();
+    
+    if (getLangOpts().ObjC1 && Tok.is(tok::less))
+      TryParseProtocolQualifiers();
+  }
+
+  return TPResult::Ambiguous();
+}
+
+/// isCXXFunctionDeclarator - Disambiguates between a function declarator or
+/// a constructor-style initializer, when parsing declaration statements.
+/// Returns true for function declarator and false for constructor-style
+/// initializer.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+///
+/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+///         exception-specification[opt]
+///
+bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) {
+
+  // C++ 8.2p1:
+  // The ambiguity arising from the similarity between a function-style cast and
+  // a declaration mentioned in 6.8 can also occur in the context of a
+  // declaration. In that context, the choice is between a function declaration
+  // with a redundant set of parentheses around a parameter name and an object
+  // declaration with a function-style cast as the initializer. Just as for the
+  // ambiguities mentioned in 6.8, the resolution is to consider any construct
+  // that could possibly be a declaration a declaration.
+
+  TentativeParsingAction PA(*this);
+
+  ConsumeParen();
+  bool InvalidAsDeclaration = false;
+  TPResult TPR = TryParseParameterDeclarationClause(&InvalidAsDeclaration);
+  if (TPR == TPResult::Ambiguous()) {
+    if (Tok.isNot(tok::r_paren))
+      TPR = TPResult::False();
+    else {
+      const Token &Next = NextToken();
+      if (Next.is(tok::amp) || Next.is(tok::ampamp) ||
+          Next.is(tok::kw_const) || Next.is(tok::kw_volatile) ||
+          Next.is(tok::kw_throw) || Next.is(tok::kw_noexcept) ||
+          Next.is(tok::l_square) || isCXX0XVirtSpecifier(Next) ||
+          Next.is(tok::l_brace) || Next.is(tok::kw_try) ||
+          Next.is(tok::equal) || Next.is(tok::arrow))
+        // The next token cannot appear after a constructor-style initializer,
+        // and can appear next in a function definition. This must be a function
+        // declarator.
+        TPR = TPResult::True();
+      else if (InvalidAsDeclaration)
+        // Use the absence of 'typename' as a tie-breaker.
+        TPR = TPResult::False();
+    }
+  }
+
+  PA.Revert();
+
+  if (IsAmbiguous && TPR == TPResult::Ambiguous())
+    *IsAmbiguous = true;
+
+  // In case of an error, let the declaration parsing code handle it.
+  return TPR != TPResult::False();
+}
+
+/// parameter-declaration-clause:
+///   parameter-declaration-list[opt] '...'[opt]
+///   parameter-declaration-list ',' '...'
+///
+/// parameter-declaration-list:
+///   parameter-declaration
+///   parameter-declaration-list ',' parameter-declaration
+///
+/// parameter-declaration:
+///   attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]
+///   attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]
+///     '=' assignment-expression
+///   attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]
+///     attributes[opt]
+///   attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]
+///     attributes[opt] '=' assignment-expression
+///
+Parser::TPResult
+Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration) {
+
+  if (Tok.is(tok::r_paren))
+    return TPResult::Ambiguous();
+
+  //   parameter-declaration-list[opt] '...'[opt]
+  //   parameter-declaration-list ',' '...'
+  //
+  // parameter-declaration-list:
+  //   parameter-declaration
+  //   parameter-declaration-list ',' parameter-declaration
+  //
+  while (1) {
+    // '...'[opt]
+    if (Tok.is(tok::ellipsis)) {
+      ConsumeToken();
+      if (Tok.is(tok::r_paren))
+        return TPResult::True(); // '...)' is a sign of a function declarator.
+      else
+        return TPResult::False();
+    }
+
+    // An attribute-specifier-seq here is a sign of a function declarator.
+    if (isCXX11AttributeSpecifier(/*Disambiguate*/false,
+                                  /*OuterMightBeMessageSend*/true))
+      return TPResult::True();
+
+    ParsedAttributes attrs(AttrFactory);
+    MaybeParseMicrosoftAttributes(attrs);
+
+    // decl-specifier-seq
+    // A parameter-declaration's initializer must be preceded by an '=', so
+    // decl-specifier-seq '{' is not a parameter in C++11.
+    TPResult TPR = TryParseDeclarationSpecifier(InvalidAsDeclaration);
+    if (TPR != TPResult::Ambiguous())
+      return TPR;
+
+    // declarator
+    // abstract-declarator[opt]
+    TPR = TryParseDeclarator(true/*mayBeAbstract*/);
+    if (TPR != TPResult::Ambiguous())
+      return TPR;
+
+    // [GNU] attributes[opt]
+    if (Tok.is(tok::kw___attribute))
+      return TPResult::True();
+
+    if (Tok.is(tok::equal)) {
+      // '=' assignment-expression
+      // Parse through assignment-expression.
+      if (!SkipUntil(tok::comma, tok::r_paren, true/*StopAtSemi*/,
+                     true/*DontConsume*/))
+        return TPResult::Error();
+    }
+
+    if (Tok.is(tok::ellipsis)) {
+      ConsumeToken();
+      if (Tok.is(tok::r_paren))
+        return TPResult::True(); // '...)' is a sign of a function declarator.
+      else
+        return TPResult::False();
+    }
+
+    if (Tok.isNot(tok::comma))
+      break;
+    ConsumeToken(); // the comma.
+  }
+
+  return TPResult::Ambiguous();
+}
+
+/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
+/// parsing as a function declarator.
+/// If TryParseFunctionDeclarator fully parsed the function declarator, it will
+/// return TPResult::Ambiguous(), otherwise it will return either False() or
+/// Error().
+///
+/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+///         exception-specification[opt]
+///
+/// exception-specification:
+///   'throw' '(' type-id-list[opt] ')'
+///
+Parser::TPResult Parser::TryParseFunctionDeclarator() {
+
+  // The '(' is already parsed.
+
+  TPResult TPR = TryParseParameterDeclarationClause();
+  if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
+    TPR = TPResult::False();
+
+  if (TPR == TPResult::False() || TPR == TPResult::Error())
+    return TPR;
+
+  // Parse through the parens.
+  if (!SkipUntil(tok::r_paren))
+    return TPResult::Error();
+
+  // cv-qualifier-seq
+  while (Tok.is(tok::kw_const)    ||
+         Tok.is(tok::kw_volatile) ||
+         Tok.is(tok::kw_restrict)   )
+    ConsumeToken();
+
+  // ref-qualifier[opt]
+  if (Tok.is(tok::amp) || Tok.is(tok::ampamp))
+    ConsumeToken();
+  
+  // exception-specification
+  if (Tok.is(tok::kw_throw)) {
+    ConsumeToken();
+    if (Tok.isNot(tok::l_paren))
+      return TPResult::Error();
+
+    // Parse through the parens after 'throw'.
+    ConsumeParen();
+    if (!SkipUntil(tok::r_paren))
+      return TPResult::Error();
+  }
+  if (Tok.is(tok::kw_noexcept)) {
+    ConsumeToken();
+    // Possibly an expression as well.
+    if (Tok.is(tok::l_paren)) {
+      // Find the matching rparen.
+      ConsumeParen();
+      if (!SkipUntil(tok::r_paren))
+        return TPResult::Error();
+    }
+  }
+
+  return TPResult::Ambiguous();
+}
+
+/// '[' constant-expression[opt] ']'
+///
+Parser::TPResult Parser::TryParseBracketDeclarator() {
+  ConsumeBracket();
+  if (!SkipUntil(tok::r_square))
+    return TPResult::Error();
+
+  return TPResult::Ambiguous();
+}

Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=170428&r1=170427&r2=170428&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Sema/DeclSpec.cpp Tue Dec 18 06:30:03 2012
@@ -280,6 +280,12 @@
     case TST_unspecified:
     case TST_void:
     case TST_wchar:
+    case TST_image1d_t:
+    case TST_image1d_array_t:
+    case TST_image1d_buffer_t:
+    case TST_image2d_t:
+    case TST_image2d_array_t:
+    case TST_image3d_t:
       return false;
 
     case TST_decltype:
@@ -414,6 +420,12 @@
   case DeclSpec::TST_underlyingType: return "__underlying_type";
   case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
   case DeclSpec::TST_atomic: return "_Atomic";
+  case DeclSpec::TST_image1d_t:   return "image1d_t";
+  case DeclSpec::TST_image1d_array_t: return "image1d_array_t";
+  case DeclSpec::TST_image1d_buffer_t: return "image1d_buffer_t";
+  case DeclSpec::TST_image2d_t:   return "image2d_t";
+  case DeclSpec::TST_image2d_array_t: return "image2d_array_t";
+  case DeclSpec::TST_image3d_t:   return "image3d_t";
   case DeclSpec::TST_error:       return "(error)";
   }
   llvm_unreachable("Unknown typespec!");

Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=170428&r1=170427&r2=170428&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Tue Dec 18 06:30:03 2012
@@ -731,6 +731,12 @@
   case TST_class:
   case TST_auto:
   case TST_unknown_anytype:
+  case TST_image1d_t:
+  case TST_image1d_array_t:
+  case TST_image1d_buffer_t:
+  case TST_image2d_t:
+  case TST_image2d_array_t:
+  case TST_image3d_t:
   case TST_error:
     break;
   }

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=170428&r1=170427&r2=170428&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Tue Dec 18 06:30:03 2012
@@ -903,6 +903,30 @@
     }
     break;
 
+  case DeclSpec::TST_image1d_t:
+    Result = Context.OCLImage1dTy;
+    break;
+
+  case DeclSpec::TST_image1d_array_t:
+    Result = Context.OCLImage1dArrayTy;
+    break;
+
+  case DeclSpec::TST_image1d_buffer_t:
+    Result = Context.OCLImage1dBufferTy;
+    break;
+
+  case DeclSpec::TST_image2d_t:
+    Result = Context.OCLImage2dTy;
+    break;
+
+  case DeclSpec::TST_image2d_array_t:
+    Result = Context.OCLImage2dArrayTy;
+    break;
+
+  case DeclSpec::TST_image3d_t:
+    Result = Context.OCLImage3dTy;
+    break;
+
   case DeclSpec::TST_error:
     Result = Context.IntTy;
     declarator.setInvalidType(true);

Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=170428&r1=170427&r2=170428&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.cpp Tue Dec 18 06:30:03 2012
@@ -1,80 +1,86 @@
-//===--- ASTCommon.cpp - Common stuff for ASTReader/ASTWriter----*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file defines common functions that both ASTReader and ASTWriter use.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ASTCommon.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Serialization/ASTDeserializationListener.h"
-#include "llvm/ADT/StringExtras.h"
-
-using namespace clang;
-
-// Give ASTDeserializationListener's VTable a home.
-ASTDeserializationListener::~ASTDeserializationListener() { }
-
-serialization::TypeIdx
-serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
-  unsigned ID = 0;
-  switch (BT->getKind()) {
-  case BuiltinType::Void:       ID = PREDEF_TYPE_VOID_ID;       break;
-  case BuiltinType::Bool:       ID = PREDEF_TYPE_BOOL_ID;       break;
-  case BuiltinType::Char_U:     ID = PREDEF_TYPE_CHAR_U_ID;     break;
-  case BuiltinType::UChar:      ID = PREDEF_TYPE_UCHAR_ID;      break;
-  case BuiltinType::UShort:     ID = PREDEF_TYPE_USHORT_ID;     break;
-  case BuiltinType::UInt:       ID = PREDEF_TYPE_UINT_ID;       break;
-  case BuiltinType::ULong:      ID = PREDEF_TYPE_ULONG_ID;      break;
-  case BuiltinType::ULongLong:  ID = PREDEF_TYPE_ULONGLONG_ID;  break;
-  case BuiltinType::UInt128:    ID = PREDEF_TYPE_UINT128_ID;    break;
-  case BuiltinType::Char_S:     ID = PREDEF_TYPE_CHAR_S_ID;     break;
-  case BuiltinType::SChar:      ID = PREDEF_TYPE_SCHAR_ID;      break;
-  case BuiltinType::WChar_S:
-  case BuiltinType::WChar_U:    ID = PREDEF_TYPE_WCHAR_ID;      break;
-  case BuiltinType::Short:      ID = PREDEF_TYPE_SHORT_ID;      break;
-  case BuiltinType::Int:        ID = PREDEF_TYPE_INT_ID;        break;
-  case BuiltinType::Long:       ID = PREDEF_TYPE_LONG_ID;       break;
-  case BuiltinType::LongLong:   ID = PREDEF_TYPE_LONGLONG_ID;   break;
-  case BuiltinType::Int128:     ID = PREDEF_TYPE_INT128_ID;     break;
-  case BuiltinType::Half:       ID = PREDEF_TYPE_HALF_ID;       break;
-  case BuiltinType::Float:      ID = PREDEF_TYPE_FLOAT_ID;      break;
-  case BuiltinType::Double:     ID = PREDEF_TYPE_DOUBLE_ID;     break;
-  case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break;
-  case BuiltinType::NullPtr:    ID = PREDEF_TYPE_NULLPTR_ID;    break;
-  case BuiltinType::Char16:     ID = PREDEF_TYPE_CHAR16_ID;     break;
-  case BuiltinType::Char32:     ID = PREDEF_TYPE_CHAR32_ID;     break;
-  case BuiltinType::Overload:   ID = PREDEF_TYPE_OVERLOAD_ID;   break;
-  case BuiltinType::BoundMember:ID = PREDEF_TYPE_BOUND_MEMBER;  break;
-  case BuiltinType::PseudoObject:ID = PREDEF_TYPE_PSEUDO_OBJECT;break;
-  case BuiltinType::Dependent:  ID = PREDEF_TYPE_DEPENDENT_ID;  break;
-  case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY;   break;
-  case BuiltinType::ARCUnbridgedCast:
-                                ID = PREDEF_TYPE_ARC_UNBRIDGED_CAST; break;
-  case BuiltinType::ObjCId:     ID = PREDEF_TYPE_OBJC_ID;       break;
-  case BuiltinType::ObjCClass:  ID = PREDEF_TYPE_OBJC_CLASS;    break;
-  case BuiltinType::ObjCSel:    ID = PREDEF_TYPE_OBJC_SEL;      break;
-  case BuiltinType::BuiltinFn:
-                                ID = PREDEF_TYPE_BUILTIN_FN; break;
-
-  }
-
-  return TypeIdx(ID);
-}
-
-unsigned serialization::ComputeHash(Selector Sel) {
-  unsigned N = Sel.getNumArgs();
-  if (N == 0)
-    ++N;
-  unsigned R = 5381;
-  for (unsigned I = 0; I != N; ++I)
-    if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
-      R = llvm::HashString(II->getName(), R);
-  return R;
-}
+//===--- ASTCommon.cpp - Common stuff for ASTReader/ASTWriter----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines common functions that both ASTReader and ASTWriter use.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTCommon.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace clang;
+
+// Give ASTDeserializationListener's VTable a home.
+ASTDeserializationListener::~ASTDeserializationListener() { }
+
+serialization::TypeIdx
+serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
+  unsigned ID = 0;
+  switch (BT->getKind()) {
+  case BuiltinType::Void:       ID = PREDEF_TYPE_VOID_ID;       break;
+  case BuiltinType::Bool:       ID = PREDEF_TYPE_BOOL_ID;       break;
+  case BuiltinType::Char_U:     ID = PREDEF_TYPE_CHAR_U_ID;     break;
+  case BuiltinType::UChar:      ID = PREDEF_TYPE_UCHAR_ID;      break;
+  case BuiltinType::UShort:     ID = PREDEF_TYPE_USHORT_ID;     break;
+  case BuiltinType::UInt:       ID = PREDEF_TYPE_UINT_ID;       break;
+  case BuiltinType::ULong:      ID = PREDEF_TYPE_ULONG_ID;      break;
+  case BuiltinType::ULongLong:  ID = PREDEF_TYPE_ULONGLONG_ID;  break;
+  case BuiltinType::UInt128:    ID = PREDEF_TYPE_UINT128_ID;    break;
+  case BuiltinType::Char_S:     ID = PREDEF_TYPE_CHAR_S_ID;     break;
+  case BuiltinType::SChar:      ID = PREDEF_TYPE_SCHAR_ID;      break;
+  case BuiltinType::WChar_S:
+  case BuiltinType::WChar_U:    ID = PREDEF_TYPE_WCHAR_ID;      break;
+  case BuiltinType::Short:      ID = PREDEF_TYPE_SHORT_ID;      break;
+  case BuiltinType::Int:        ID = PREDEF_TYPE_INT_ID;        break;
+  case BuiltinType::Long:       ID = PREDEF_TYPE_LONG_ID;       break;
+  case BuiltinType::LongLong:   ID = PREDEF_TYPE_LONGLONG_ID;   break;
+  case BuiltinType::Int128:     ID = PREDEF_TYPE_INT128_ID;     break;
+  case BuiltinType::Half:       ID = PREDEF_TYPE_HALF_ID;       break;
+  case BuiltinType::Float:      ID = PREDEF_TYPE_FLOAT_ID;      break;
+  case BuiltinType::Double:     ID = PREDEF_TYPE_DOUBLE_ID;     break;
+  case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break;
+  case BuiltinType::NullPtr:    ID = PREDEF_TYPE_NULLPTR_ID;    break;
+  case BuiltinType::Char16:     ID = PREDEF_TYPE_CHAR16_ID;     break;
+  case BuiltinType::Char32:     ID = PREDEF_TYPE_CHAR32_ID;     break;
+  case BuiltinType::Overload:   ID = PREDEF_TYPE_OVERLOAD_ID;   break;
+  case BuiltinType::BoundMember:ID = PREDEF_TYPE_BOUND_MEMBER;  break;
+  case BuiltinType::PseudoObject:ID = PREDEF_TYPE_PSEUDO_OBJECT;break;
+  case BuiltinType::Dependent:  ID = PREDEF_TYPE_DEPENDENT_ID;  break;
+  case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY;   break;
+  case BuiltinType::ARCUnbridgedCast:
+                                ID = PREDEF_TYPE_ARC_UNBRIDGED_CAST; break;
+  case BuiltinType::ObjCId:     ID = PREDEF_TYPE_OBJC_ID;       break;
+  case BuiltinType::ObjCClass:  ID = PREDEF_TYPE_OBJC_CLASS;    break;
+  case BuiltinType::ObjCSel:    ID = PREDEF_TYPE_OBJC_SEL;      break;
+  case BuiltinType::OCLImage1d:       ID = PREDEF_TYPE_IMAGE1D_ID;      break;
+  case BuiltinType::OCLImage1dArray:  ID = PREDEF_TYPE_IMAGE1D_ARR_ID;  break;
+  case BuiltinType::OCLImage1dBuffer: ID = PREDEF_TYPE_IMAGE1D_BUFF_ID; break;
+  case BuiltinType::OCLImage2d:       ID = PREDEF_TYPE_IMAGE2D_ID;      break;
+  case BuiltinType::OCLImage2dArray:  ID = PREDEF_TYPE_IMAGE2D_ARR_ID;  break;
+  case BuiltinType::OCLImage3d:       ID = PREDEF_TYPE_IMAGE3D_ID;      break;
+  case BuiltinType::BuiltinFn:
+                                ID = PREDEF_TYPE_BUILTIN_FN; break;
+
+  }
+
+  return TypeIdx(ID);
+}
+
+unsigned serialization::ComputeHash(Selector Sel) {
+  unsigned N = Sel.getNumArgs();
+  if (N == 0)
+    ++N;
+  unsigned R = 5381;
+  for (unsigned I = 0; I != N; ++I)
+    if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
+      R = llvm::HashString(II->getName(), R);
+  return R;
+}

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=170428&r1=170427&r2=170428&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Dec 18 06:30:03 2012
@@ -1,6992 +1,6998 @@
-//===--- ASTReader.cpp - AST File Reader ------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file defines the ASTReader class, which reads AST files.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Serialization/ASTReader.h"
-#include "ASTCommon.h"
-#include "ASTReaderInternals.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/NestedNameSpecifier.h"
-#include "clang/AST/Type.h"
-#include "clang/AST/TypeLocVisitor.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/FileSystemStatCache.h"
-#include "clang/Basic/OnDiskHashTable.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/SourceManagerInternals.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/TargetOptions.h"
-#include "clang/Basic/Version.h"
-#include "clang/Basic/VersionTuple.h"
-#include "clang/Lex/HeaderSearch.h"
-#include "clang/Lex/HeaderSearchOptions.h"
-#include "clang/Lex/MacroInfo.h"
-#include "clang/Lex/PreprocessingRecord.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/PreprocessorOptions.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/Sema.h"
-#include "clang/Serialization/ASTDeserializationListener.h"
-#include "clang/Serialization/ModuleManager.h"
-#include "clang/Serialization/SerializationDiagnostic.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Bitcode/BitstreamReader.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/SaveAndRestore.h"
-#include "llvm/Support/system_error.h"
-#include <algorithm>
-#include <cstdio>
-#include <iterator>
-
-using namespace clang;
-using namespace clang::serialization;
-using namespace clang::serialization::reader;
-
-//===----------------------------------------------------------------------===//
-// PCH validator implementation
-//===----------------------------------------------------------------------===//
-
-ASTReaderListener::~ASTReaderListener() {}
-
-/// \brief Compare the given set of language options against an existing set of
-/// language options.
-///
-/// \param Diags If non-NULL, diagnostics will be emitted via this engine.
-///
-/// \returns true if the languagae options mis-match, false otherwise.
-static bool checkLanguageOptions(const LangOptions &LangOpts,
-                                 const LangOptions &ExistingLangOpts,
-                                 DiagnosticsEngine *Diags) {
-#define LANGOPT(Name, Bits, Default, Description)                 \
-  if (ExistingLangOpts.Name != LangOpts.Name) {                   \
-    if (Diags)                                                    \
-      Diags->Report(diag::err_pch_langopt_mismatch)               \
-        << Description << LangOpts.Name << ExistingLangOpts.Name; \
-    return true;                                                  \
-  }
-
-#define VALUE_LANGOPT(Name, Bits, Default, Description)   \
-  if (ExistingLangOpts.Name != LangOpts.Name) {           \
-    if (Diags)                                            \
-      Diags->Report(diag::err_pch_langopt_value_mismatch) \
-        << Description;                                   \
-    return true;                                          \
-  }
-
-#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)   \
-  if (ExistingLangOpts.get##Name() != LangOpts.get##Name()) {  \
-    if (Diags)                                                 \
-      Diags->Report(diag::err_pch_langopt_value_mismatch)      \
-        << Description;                                        \
-    return true;                                               \
-  }
-
-#define BENIGN_LANGOPT(Name, Bits, Default, Description)
-#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
-#include "clang/Basic/LangOptions.def"
-
-  if (ExistingLangOpts.ObjCRuntime != LangOpts.ObjCRuntime) {
-    if (Diags)
-      Diags->Report(diag::err_pch_langopt_value_mismatch)
-      << "target Objective-C runtime";
-    return true;
-  }
-
-  return false;
-}
-
-/// \brief Compare the given set of target options against an existing set of
-/// target options.
-///
-/// \param Diags If non-NULL, diagnostics will be emitted via this engine.
-///
-/// \returns true if the target options mis-match, false otherwise.
-static bool checkTargetOptions(const TargetOptions &TargetOpts,
-                               const TargetOptions &ExistingTargetOpts,
-                               DiagnosticsEngine *Diags) {
-#define CHECK_TARGET_OPT(Field, Name)                             \
-  if (TargetOpts.Field != ExistingTargetOpts.Field) {             \
-    if (Diags)                                                    \
-      Diags->Report(diag::err_pch_targetopt_mismatch)             \
-        << Name << TargetOpts.Field << ExistingTargetOpts.Field;  \
-    return true;                                                  \
-  }
-
-  CHECK_TARGET_OPT(Triple, "target");
-  CHECK_TARGET_OPT(CPU, "target CPU");
-  CHECK_TARGET_OPT(ABI, "target ABI");
-  CHECK_TARGET_OPT(CXXABI, "target C++ ABI");
-  CHECK_TARGET_OPT(LinkerVersion, "target linker version");
-#undef CHECK_TARGET_OPT
-
-  // Compare feature sets.
-  SmallVector<StringRef, 4> ExistingFeatures(
-                                             ExistingTargetOpts.FeaturesAsWritten.begin(),
-                                             ExistingTargetOpts.FeaturesAsWritten.end());
-  SmallVector<StringRef, 4> ReadFeatures(TargetOpts.FeaturesAsWritten.begin(),
-                                         TargetOpts.FeaturesAsWritten.end());
-  std::sort(ExistingFeatures.begin(), ExistingFeatures.end());
-  std::sort(ReadFeatures.begin(), ReadFeatures.end());
-
-  unsigned ExistingIdx = 0, ExistingN = ExistingFeatures.size();
-  unsigned ReadIdx = 0, ReadN = ReadFeatures.size();
-  while (ExistingIdx < ExistingN && ReadIdx < ReadN) {
-    if (ExistingFeatures[ExistingIdx] == ReadFeatures[ReadIdx]) {
-      ++ExistingIdx;
-      ++ReadIdx;
-      continue;
-    }
-
-    if (ReadFeatures[ReadIdx] < ExistingFeatures[ExistingIdx]) {
-      if (Diags)
-        Diags->Report(diag::err_pch_targetopt_feature_mismatch)
-          << false << ReadFeatures[ReadIdx];
-      return true;
-    }
-
-    if (Diags)
-      Diags->Report(diag::err_pch_targetopt_feature_mismatch)
-        << true << ExistingFeatures[ExistingIdx];
-    return true;
-  }
-
-  if (ExistingIdx < ExistingN) {
-    if (Diags)
-      Diags->Report(diag::err_pch_targetopt_feature_mismatch)
-        << true << ExistingFeatures[ExistingIdx];
-    return true;
-  }
-
-  if (ReadIdx < ReadN) {
-    if (Diags)
-      Diags->Report(diag::err_pch_targetopt_feature_mismatch)
-        << false << ReadFeatures[ReadIdx];
-    return true;
-  }
-
-  return false;
-}
-
-bool
-PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts,
-                                  bool Complain) {
-  const LangOptions &ExistingLangOpts = PP.getLangOpts();
-  return checkLanguageOptions(LangOpts, ExistingLangOpts,
-                              Complain? &Reader.Diags : 0);
-}
-
-bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
-                                     bool Complain) {
-  const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts();
-  return checkTargetOptions(TargetOpts, ExistingTargetOpts,
-                            Complain? &Reader.Diags : 0);
-}
-
-namespace {
-  typedef llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >
-    MacroDefinitionsMap;
-}
-
-/// \brief Collect the macro definitions provided by the given preprocessor
-/// options.
-static void collectMacroDefinitions(const PreprocessorOptions &PPOpts,
-                                    MacroDefinitionsMap &Macros,
-                                    SmallVectorImpl<StringRef> *MacroNames = 0){
-  for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) {
-    StringRef Macro = PPOpts.Macros[I].first;
-    bool IsUndef = PPOpts.Macros[I].second;
-
-    std::pair<StringRef, StringRef> MacroPair = Macro.split('=');
-    StringRef MacroName = MacroPair.first;
-    StringRef MacroBody = MacroPair.second;
-
-    // For an #undef'd macro, we only care about the name.
-    if (IsUndef) {
-      if (MacroNames && !Macros.count(MacroName))
-        MacroNames->push_back(MacroName);
-
-      Macros[MacroName] = std::make_pair("", true);
-      continue;
-    }
-
-    // For a #define'd macro, figure out the actual definition.
-    if (MacroName.size() == Macro.size())
-      MacroBody = "1";
-    else {
-      // Note: GCC drops anything following an end-of-line character.
-      StringRef::size_type End = MacroBody.find_first_of("\n\r");
-      MacroBody = MacroBody.substr(0, End);
-    }
-
-    if (MacroNames && !Macros.count(MacroName))
-      MacroNames->push_back(MacroName);
-    Macros[MacroName] = std::make_pair(MacroBody, false);
-  }
-}
-         
-/// \brief Check the preprocessor options deserialized from the control block
-/// against the preprocessor options in an existing preprocessor.
-///
-/// \param Diags If non-null, produce diagnostics for any mismatches incurred.
-static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
-                                     const PreprocessorOptions &ExistingPPOpts,
-                                     DiagnosticsEngine *Diags,
-                                     FileManager &FileMgr,
-                                     std::string &SuggestedPredefines) {
-  // Check macro definitions.
-  MacroDefinitionsMap ASTFileMacros;
-  collectMacroDefinitions(PPOpts, ASTFileMacros);
-  MacroDefinitionsMap ExistingMacros;
-  SmallVector<StringRef, 4> ExistingMacroNames;
-  collectMacroDefinitions(ExistingPPOpts, ExistingMacros, &ExistingMacroNames);
-
-  for (unsigned I = 0, N = ExistingMacroNames.size(); I != N; ++I) {
-    // Dig out the macro definition in the existing preprocessor options.
-    StringRef MacroName = ExistingMacroNames[I];
-    std::pair<StringRef, bool> Existing = ExistingMacros[MacroName];
-
-    // Check whether we know anything about this macro name or not.
-    llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >::iterator Known
-      = ASTFileMacros.find(MacroName);
-    if (Known == ASTFileMacros.end()) {
-      // FIXME: Check whether this identifier was referenced anywhere in the
-      // AST file. If so, we should reject the AST file. Unfortunately, this
-      // information isn't in the control block. What shall we do about it?
-
-      if (Existing.second) {
-        SuggestedPredefines += "#undef ";
-        SuggestedPredefines += MacroName.str();
-        SuggestedPredefines += '\n';
-      } else {
-        SuggestedPredefines += "#define ";
-        SuggestedPredefines += MacroName.str();
-        SuggestedPredefines += ' ';
-        SuggestedPredefines += Existing.first.str();
-        SuggestedPredefines += '\n';
-      }
-      continue;
-    }
-
-    // If the macro was defined in one but undef'd in the other, we have a
-    // conflict.
-    if (Existing.second != Known->second.second) {
-      if (Diags) {
-        Diags->Report(diag::err_pch_macro_def_undef)
-          << MacroName << Known->second.second;
-      }
-      return true;
-    }
-
-    // If the macro was #undef'd in both, or if the macro bodies are identical,
-    // it's fine.
-    if (Existing.second || Existing.first == Known->second.first)
-      continue;
-
-    // The macro bodies differ; complain.
-    if (Diags) {
-      Diags->Report(diag::err_pch_macro_def_conflict)
-        << MacroName << Known->second.first << Existing.first;
-    }
-    return true;
-  }
-
-  // Check whether we're using predefines.
-  if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines) {
-    if (Diags) {
-      Diags->Report(diag::err_pch_undef) << ExistingPPOpts.UsePredefines;
-    }
-    return true;
-  }
-
-  // Compute the #include and #include_macros lines we need.
-  for (unsigned I = 0, N = ExistingPPOpts.Includes.size(); I != N; ++I) {
-    StringRef File = ExistingPPOpts.Includes[I];
-    if (File == ExistingPPOpts.ImplicitPCHInclude)
-      continue;
-
-    if (std::find(PPOpts.Includes.begin(), PPOpts.Includes.end(), File)
-          != PPOpts.Includes.end())
-      continue;
-
-    SuggestedPredefines += "#include \"";
-    SuggestedPredefines +=
-      HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
-    SuggestedPredefines += "\"\n";
-  }
-
-  for (unsigned I = 0, N = ExistingPPOpts.MacroIncludes.size(); I != N; ++I) {
-    StringRef File = ExistingPPOpts.MacroIncludes[I];
-    if (std::find(PPOpts.MacroIncludes.begin(), PPOpts.MacroIncludes.end(),
-                  File)
-        != PPOpts.MacroIncludes.end())
-      continue;
-
-    SuggestedPredefines += "#__include_macros \"";
-    SuggestedPredefines +=
-      HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
-    SuggestedPredefines += "\"\n##\n";
-  }
-
-  return false;
-}
-
-bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
-                                           bool Complain,
-                                           std::string &SuggestedPredefines) {
-  const PreprocessorOptions &ExistingPPOpts = PP.getPreprocessorOpts();
-
-  return checkPreprocessorOptions(PPOpts, ExistingPPOpts,
-                                  Complain? &Reader.Diags : 0,
-                                  PP.getFileManager(),
-                                  SuggestedPredefines);
-}
-
-void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI,
-                                      unsigned ID) {
-  PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID);
-  ++NumHeaderInfos;
-}
-
-void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) {
-  PP.setCounterValue(Value);
-}
-
-//===----------------------------------------------------------------------===//
-// AST reader implementation
-//===----------------------------------------------------------------------===//
-
-void
-ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) {
-  DeserializationListener = Listener;
-}
-
-
-
-unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) {
-  return serialization::ComputeHash(Sel);
-}
-
-
-std::pair<unsigned, unsigned>
-ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
-  using namespace clang::io;
-  unsigned KeyLen = ReadUnalignedLE16(d);
-  unsigned DataLen = ReadUnalignedLE16(d);
-  return std::make_pair(KeyLen, DataLen);
-}
-
-ASTSelectorLookupTrait::internal_key_type 
-ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {
-  using namespace clang::io;
-  SelectorTable &SelTable = Reader.getContext().Selectors;
-  unsigned N = ReadUnalignedLE16(d);
-  IdentifierInfo *FirstII
-    = Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
-  if (N == 0)
-    return SelTable.getNullarySelector(FirstII);
-  else if (N == 1)
-    return SelTable.getUnarySelector(FirstII);
-
-  SmallVector<IdentifierInfo *, 16> Args;
-  Args.push_back(FirstII);
-  for (unsigned I = 1; I != N; ++I)
-    Args.push_back(Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)));
-
-  return SelTable.getSelector(N, Args.data());
-}
-
-ASTSelectorLookupTrait::data_type 
-ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, 
-                                 unsigned DataLen) {
-  using namespace clang::io;
-
-  data_type Result;
-
-  Result.ID = Reader.getGlobalSelectorID(F, ReadUnalignedLE32(d));
-  unsigned NumInstanceMethods = ReadUnalignedLE16(d);
-  unsigned NumFactoryMethods = ReadUnalignedLE16(d);
-
-  // Load instance methods
-  for (unsigned I = 0; I != NumInstanceMethods; ++I) {
-    if (ObjCMethodDecl *Method
-          = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
-      Result.Instance.push_back(Method);
-  }
-
-  // Load factory methods
-  for (unsigned I = 0; I != NumFactoryMethods; ++I) {
-    if (ObjCMethodDecl *Method
-          = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
-      Result.Factory.push_back(Method);
-  }
-
-  return Result;
-}
-
-unsigned ASTIdentifierLookupTrait::ComputeHash(const internal_key_type& a) {
-  return llvm::HashString(StringRef(a.first, a.second));
-}
-
-std::pair<unsigned, unsigned>
-ASTIdentifierLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
-  using namespace clang::io;
-  unsigned DataLen = ReadUnalignedLE16(d);
-  unsigned KeyLen = ReadUnalignedLE16(d);
-  return std::make_pair(KeyLen, DataLen);
-}
-
-std::pair<const char*, unsigned>
-ASTIdentifierLookupTrait::ReadKey(const unsigned char* d, unsigned n) {
-  assert(n >= 2 && d[n-1] == '\0');
-  return std::make_pair((const char*) d, n-1);
-}
-
-IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
-                                                   const unsigned char* d,
-                                                   unsigned DataLen) {
-  using namespace clang::io;
-  unsigned RawID = ReadUnalignedLE32(d);
-  bool IsInteresting = RawID & 0x01;
-
-  // Wipe out the "is interesting" bit.
-  RawID = RawID >> 1;
-
-  IdentID ID = Reader.getGlobalIdentifierID(F, RawID);
-  if (!IsInteresting) {
-    // For uninteresting identifiers, just build the IdentifierInfo
-    // and associate it with the persistent ID.
-    IdentifierInfo *II = KnownII;
-    if (!II) {
-      II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
-      KnownII = II;
-    }
-    Reader.SetIdentifierInfo(ID, II);
-    II->setIsFromAST();
-    Reader.markIdentifierUpToDate(II);    
-    return II;
-  }
-
-  unsigned ObjCOrBuiltinID = ReadUnalignedLE16(d);
-  unsigned Bits = ReadUnalignedLE16(d);
-  bool CPlusPlusOperatorKeyword = Bits & 0x01;
-  Bits >>= 1;
-  bool HasRevertedTokenIDToIdentifier = Bits & 0x01;
-  Bits >>= 1;
-  bool Poisoned = Bits & 0x01;
-  Bits >>= 1;
-  bool ExtensionToken = Bits & 0x01;
-  Bits >>= 1;
-  bool hadMacroDefinition = Bits & 0x01;
-  Bits >>= 1;
-
-  assert(Bits == 0 && "Extra bits in the identifier?");
-  DataLen -= 8;
-
-  // Build the IdentifierInfo itself and link the identifier ID with
-  // the new IdentifierInfo.
-  IdentifierInfo *II = KnownII;
-  if (!II) {
-    II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
-    KnownII = II;
-  }
-  Reader.markIdentifierUpToDate(II);
-  II->setIsFromAST();
-
-  // Set or check the various bits in the IdentifierInfo structure.
-  // Token IDs are read-only.
-  if (HasRevertedTokenIDToIdentifier)
-    II->RevertTokenIDToIdentifier();
-  II->setObjCOrBuiltinID(ObjCOrBuiltinID);
-  assert(II->isExtensionToken() == ExtensionToken &&
-         "Incorrect extension token flag");
-  (void)ExtensionToken;
-  if (Poisoned)
-    II->setIsPoisoned(true);
-  assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
-         "Incorrect C++ operator keyword flag");
-  (void)CPlusPlusOperatorKeyword;
-
-  // If this identifier is a macro, deserialize the macro
-  // definition.
-  if (hadMacroDefinition) {
-    SmallVector<MacroID, 4> MacroIDs;
-    while (uint32_t LocalID = ReadUnalignedLE32(d)) {
-      MacroIDs.push_back(Reader.getGlobalMacroID(F, LocalID));
-      DataLen -= 4;
-    }
-    DataLen -= 4;
-    Reader.setIdentifierIsMacro(II, MacroIDs);
-  }
-
-  Reader.SetIdentifierInfo(ID, II);
-
-  // Read all of the declarations visible at global scope with this
-  // name.
-  if (DataLen > 0) {
-    SmallVector<uint32_t, 4> DeclIDs;
-    for (; DataLen > 0; DataLen -= 4)
-      DeclIDs.push_back(Reader.getGlobalDeclID(F, ReadUnalignedLE32(d)));
-    Reader.SetGloballyVisibleDecls(II, DeclIDs);
-  }
-
-  return II;
-}
-
-unsigned 
-ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) const {
-  llvm::FoldingSetNodeID ID;
-  ID.AddInteger(Key.Kind);
-
-  switch (Key.Kind) {
-  case DeclarationName::Identifier:
-  case DeclarationName::CXXLiteralOperatorName:
-    ID.AddString(((IdentifierInfo*)Key.Data)->getName());
-    break;
-  case DeclarationName::ObjCZeroArgSelector:
-  case DeclarationName::ObjCOneArgSelector:
-  case DeclarationName::ObjCMultiArgSelector:
-    ID.AddInteger(serialization::ComputeHash(Selector(Key.Data)));
-    break;
-  case DeclarationName::CXXOperatorName:
-    ID.AddInteger((OverloadedOperatorKind)Key.Data);
-    break;
-  case DeclarationName::CXXConstructorName:
-  case DeclarationName::CXXDestructorName:
-  case DeclarationName::CXXConversionFunctionName:
-  case DeclarationName::CXXUsingDirective:
-    break;
-  }
-
-  return ID.ComputeHash();
-}
-
-ASTDeclContextNameLookupTrait::internal_key_type 
-ASTDeclContextNameLookupTrait::GetInternalKey(
-                                          const external_key_type& Name) const {
-  DeclNameKey Key;
-  Key.Kind = Name.getNameKind();
-  switch (Name.getNameKind()) {
-  case DeclarationName::Identifier:
-    Key.Data = (uint64_t)Name.getAsIdentifierInfo();
-    break;
-  case DeclarationName::ObjCZeroArgSelector:
-  case DeclarationName::ObjCOneArgSelector:
-  case DeclarationName::ObjCMultiArgSelector:
-    Key.Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr();
-    break;
-  case DeclarationName::CXXOperatorName:
-    Key.Data = Name.getCXXOverloadedOperator();
-    break;
-  case DeclarationName::CXXLiteralOperatorName:
-    Key.Data = (uint64_t)Name.getCXXLiteralIdentifier();
-    break;
-  case DeclarationName::CXXConstructorName:
-  case DeclarationName::CXXDestructorName:
-  case DeclarationName::CXXConversionFunctionName:
-  case DeclarationName::CXXUsingDirective:
-    Key.Data = 0;
-    break;
-  }
-
-  return Key;
-}
-
-std::pair<unsigned, unsigned>
-ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
-  using namespace clang::io;
-  unsigned KeyLen = ReadUnalignedLE16(d);
-  unsigned DataLen = ReadUnalignedLE16(d);
-  return std::make_pair(KeyLen, DataLen);
-}
-
-ASTDeclContextNameLookupTrait::internal_key_type 
-ASTDeclContextNameLookupTrait::ReadKey(const unsigned char* d, unsigned) {
-  using namespace clang::io;
-
-  DeclNameKey Key;
-  Key.Kind = (DeclarationName::NameKind)*d++;
-  switch (Key.Kind) {
-  case DeclarationName::Identifier:
-    Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
-    break;
-  case DeclarationName::ObjCZeroArgSelector:
-  case DeclarationName::ObjCOneArgSelector:
-  case DeclarationName::ObjCMultiArgSelector:
-    Key.Data =
-       (uint64_t)Reader.getLocalSelector(F, ReadUnalignedLE32(d))
-                   .getAsOpaquePtr();
-    break;
-  case DeclarationName::CXXOperatorName:
-    Key.Data = *d++; // OverloadedOperatorKind
-    break;
-  case DeclarationName::CXXLiteralOperatorName:
-    Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
-    break;
-  case DeclarationName::CXXConstructorName:
-  case DeclarationName::CXXDestructorName:
-  case DeclarationName::CXXConversionFunctionName:
-  case DeclarationName::CXXUsingDirective:
-    Key.Data = 0;
-    break;
-  }
-
-  return Key;
-}
-
-ASTDeclContextNameLookupTrait::data_type 
-ASTDeclContextNameLookupTrait::ReadData(internal_key_type, 
-                                        const unsigned char* d,
-                                        unsigned DataLen) {
-  using namespace clang::io;
-  unsigned NumDecls = ReadUnalignedLE16(d);
-  LE32DeclID *Start = (LE32DeclID *)d;
-  return std::make_pair(Start, Start + NumDecls);
-}
-
-bool ASTReader::ReadDeclContextStorage(ModuleFile &M,
-                                       llvm::BitstreamCursor &Cursor,
-                                   const std::pair<uint64_t, uint64_t> &Offsets,
-                                       DeclContextInfo &Info) {
-  SavedStreamPosition SavedPosition(Cursor);
-  // First the lexical decls.
-  if (Offsets.first != 0) {
-    Cursor.JumpToBit(Offsets.first);
-
-    RecordData Record;
-    const char *Blob;
-    unsigned BlobLen;
-    unsigned Code = Cursor.ReadCode();
-    unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);
-    if (RecCode != DECL_CONTEXT_LEXICAL) {
-      Error("Expected lexical block");
-      return true;
-    }
-
-    Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair*>(Blob);
-    Info.NumLexicalDecls = BlobLen / sizeof(KindDeclIDPair);
-  }
-
-  // Now the lookup table.
-  if (Offsets.second != 0) {
-    Cursor.JumpToBit(Offsets.second);
-
-    RecordData Record;
-    const char *Blob;
-    unsigned BlobLen;
-    unsigned Code = Cursor.ReadCode();
-    unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);
-    if (RecCode != DECL_CONTEXT_VISIBLE) {
-      Error("Expected visible lookup table block");
-      return true;
-    }
-    Info.NameLookupTableData
-      = ASTDeclContextNameLookupTable::Create(
-                    (const unsigned char *)Blob + Record[0],
-                    (const unsigned char *)Blob,
-                    ASTDeclContextNameLookupTrait(*this, M));
-  }
-
-  return false;
-}
-
-void ASTReader::Error(StringRef Msg) {
-  Error(diag::err_fe_pch_malformed, Msg);
-}
-
-void ASTReader::Error(unsigned DiagID,
-                      StringRef Arg1, StringRef Arg2) {
-  if (Diags.isDiagnosticInFlight())
-    Diags.SetDelayedDiagnostic(DiagID, Arg1, Arg2);
-  else
-    Diag(DiagID) << Arg1 << Arg2;
-}
-
-//===----------------------------------------------------------------------===//
-// Source Manager Deserialization
-//===----------------------------------------------------------------------===//
-
-/// \brief Read the line table in the source manager block.
-/// \returns true if there was an error.
-bool ASTReader::ParseLineTable(ModuleFile &F,
-                               SmallVectorImpl<uint64_t> &Record) {
-  unsigned Idx = 0;
-  LineTableInfo &LineTable = SourceMgr.getLineTable();
-
-  // Parse the file names
-  std::map<int, int> FileIDs;
-  for (int I = 0, N = Record[Idx++]; I != N; ++I) {
-    // Extract the file name
-    unsigned FilenameLen = Record[Idx++];
-    std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
-    Idx += FilenameLen;
-    MaybeAddSystemRootToFilename(F, Filename);
-    FileIDs[I] = LineTable.getLineTableFilenameID(Filename);
-  }
-
-  // Parse the line entries
-  std::vector<LineEntry> Entries;
-  while (Idx < Record.size()) {
-    int FID = Record[Idx++];
-    assert(FID >= 0 && "Serialized line entries for non-local file.");
-    // Remap FileID from 1-based old view.
-    FID += F.SLocEntryBaseID - 1;
-
-    // Extract the line entries
-    unsigned NumEntries = Record[Idx++];
-    assert(NumEntries && "Numentries is 00000");
-    Entries.clear();
-    Entries.reserve(NumEntries);
-    for (unsigned I = 0; I != NumEntries; ++I) {
-      unsigned FileOffset = Record[Idx++];
-      unsigned LineNo = Record[Idx++];
-      int FilenameID = FileIDs[Record[Idx++]];
-      SrcMgr::CharacteristicKind FileKind
-        = (SrcMgr::CharacteristicKind)Record[Idx++];
-      unsigned IncludeOffset = Record[Idx++];
-      Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
-                                       FileKind, IncludeOffset));
-    }
-    LineTable.AddEntry(FileID::get(FID), Entries);
-  }
-
-  return false;
-}
-
-/// \brief Read a source manager block
-bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
-  using namespace SrcMgr;
-
-  llvm::BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor;
-
-  // Set the source-location entry cursor to the current position in
-  // the stream. This cursor will be used to read the contents of the
-  // source manager block initially, and then lazily read
-  // source-location entries as needed.
-  SLocEntryCursor = F.Stream;
-
-  // The stream itself is going to skip over the source manager block.
-  if (F.Stream.SkipBlock()) {
-    Error("malformed block record in AST file");
-    return true;
-  }
-
-  // Enter the source manager block.
-  if (SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID)) {
-    Error("malformed source manager block record in AST file");
-    return true;
-  }
-
-  RecordData Record;
-  while (true) {
-    unsigned Code = SLocEntryCursor.ReadCode();
-    if (Code == llvm::bitc::END_BLOCK) {
-      if (SLocEntryCursor.ReadBlockEnd()) {
-        Error("error at end of Source Manager block in AST file");
-        return true;
-      }
-      return false;
-    }
-
-    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-      // No known subblocks, always skip them.
-      SLocEntryCursor.ReadSubBlockID();
-      if (SLocEntryCursor.SkipBlock()) {
-        Error("malformed block record in AST file");
-        return true;
-      }
-      continue;
-    }
-
-    if (Code == llvm::bitc::DEFINE_ABBREV) {
-      SLocEntryCursor.ReadAbbrevRecord();
-      continue;
-    }
-
-    // Read a record.
-    const char *BlobStart;
-    unsigned BlobLen;
-    Record.clear();
-    switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
-    default:  // Default behavior: ignore.
-      break;
-
-    case SM_SLOC_FILE_ENTRY:
-    case SM_SLOC_BUFFER_ENTRY:
-    case SM_SLOC_EXPANSION_ENTRY:
-      // Once we hit one of the source location entries, we're done.
-      return false;
-    }
-  }
-}
-
-/// \brief If a header file is not found at the path that we expect it to be
-/// and the PCH file was moved from its original location, try to resolve the
-/// file by assuming that header+PCH were moved together and the header is in
-/// the same place relative to the PCH.
-static std::string
-resolveFileRelativeToOriginalDir(const std::string &Filename,
-                                 const std::string &OriginalDir,
-                                 const std::string &CurrDir) {
-  assert(OriginalDir != CurrDir &&
-         "No point trying to resolve the file if the PCH dir didn't change");
-  using namespace llvm::sys;
-  SmallString<128> filePath(Filename);
-  fs::make_absolute(filePath);
-  assert(path::is_absolute(OriginalDir));
-  SmallString<128> currPCHPath(CurrDir);
-
-  path::const_iterator fileDirI = path::begin(path::parent_path(filePath)),
-                       fileDirE = path::end(path::parent_path(filePath));
-  path::const_iterator origDirI = path::begin(OriginalDir),
-                       origDirE = path::end(OriginalDir);
-  // Skip the common path components from filePath and OriginalDir.
-  while (fileDirI != fileDirE && origDirI != origDirE &&
-         *fileDirI == *origDirI) {
-    ++fileDirI;
-    ++origDirI;
-  }
-  for (; origDirI != origDirE; ++origDirI)
-    path::append(currPCHPath, "..");
-  path::append(currPCHPath, fileDirI, fileDirE);
-  path::append(currPCHPath, path::filename(Filename));
-  return currPCHPath.str();
-}
-
-bool ASTReader::ReadSLocEntry(int ID) {
-  if (ID == 0)
-    return false;
-
-  if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) {
-    Error("source location entry ID out-of-range for AST file");
-    return true;
-  }
-
-  ModuleFile *F = GlobalSLocEntryMap.find(-ID)->second;
-  F->SLocEntryCursor.JumpToBit(F->SLocEntryOffsets[ID - F->SLocEntryBaseID]);
-  llvm::BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor;
-  unsigned BaseOffset = F->SLocEntryBaseOffset;
-
-  ++NumSLocEntriesRead;
-  unsigned Code = SLocEntryCursor.ReadCode();
-  if (Code == llvm::bitc::END_BLOCK ||
-      Code == llvm::bitc::ENTER_SUBBLOCK ||
-      Code == llvm::bitc::DEFINE_ABBREV) {
-    Error("incorrectly-formatted source location entry in AST file");
-    return true;
-  }
-
-  RecordData Record;
-  const char *BlobStart;
-  unsigned BlobLen;
-  switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
-  default:
-    Error("incorrectly-formatted source location entry in AST file");
-    return true;
-
-  case SM_SLOC_FILE_ENTRY: {
-    // We will detect whether a file changed and return 'Failure' for it, but
-    // we will also try to fail gracefully by setting up the SLocEntry.
-    unsigned InputID = Record[4];
-    InputFile IF = getInputFile(*F, InputID);
-    const FileEntry *File = IF.getPointer();
-    bool OverriddenBuffer = IF.getInt();
-
-    if (!IF.getPointer())
-      return true;
-
-    SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
-    if (IncludeLoc.isInvalid() && F->Kind != MK_MainFile) {
-      // This is the module's main file.
-      IncludeLoc = getImportLocation(F);
-    }
-    SrcMgr::CharacteristicKind
-      FileCharacter = (SrcMgr::CharacteristicKind)Record[2];
-    FileID FID = SourceMgr.createFileID(File, IncludeLoc, FileCharacter,
-                                        ID, BaseOffset + Record[0]);
-    SrcMgr::FileInfo &FileInfo =
-          const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile());
-    FileInfo.NumCreatedFIDs = Record[5];
-    if (Record[3])
-      FileInfo.setHasLineDirectives();
-
-    const DeclID *FirstDecl = F->FileSortedDecls + Record[6];
-    unsigned NumFileDecls = Record[7];
-    if (NumFileDecls) {
-      assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?");
-      FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl,
-                                                             NumFileDecls));
-    }
-    
-    const SrcMgr::ContentCache *ContentCache
-      = SourceMgr.getOrCreateContentCache(File,
-                              /*isSystemFile=*/FileCharacter != SrcMgr::C_User);
-    if (OverriddenBuffer && !ContentCache->BufferOverridden &&
-        ContentCache->ContentsEntry == ContentCache->OrigEntry) {
-      unsigned Code = SLocEntryCursor.ReadCode();
-      Record.clear();
-      unsigned RecCode
-        = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
-      
-      if (RecCode != SM_SLOC_BUFFER_BLOB) {
-        Error("AST record has invalid code");
-        return true;
-      }
-      
-      llvm::MemoryBuffer *Buffer
-        = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),
-                                           File->getName());
-      SourceMgr.overrideFileContents(File, Buffer);
-    }
-
-    break;
-  }
-
-  case SM_SLOC_BUFFER_ENTRY: {
-    const char *Name = BlobStart;
-    unsigned Offset = Record[0];
-    SrcMgr::CharacteristicKind
-      FileCharacter = (SrcMgr::CharacteristicKind)Record[2];
-    SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
-    if (IncludeLoc.isInvalid() && F->Kind == MK_Module) {
-      IncludeLoc = getImportLocation(F);
-    }
-    unsigned Code = SLocEntryCursor.ReadCode();
-    Record.clear();
-    unsigned RecCode
-      = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
-
-    if (RecCode != SM_SLOC_BUFFER_BLOB) {
-      Error("AST record has invalid code");
-      return true;
-    }
-
-    llvm::MemoryBuffer *Buffer
-      = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),
-                                         Name);
-    SourceMgr.createFileIDForMemBuffer(Buffer, FileCharacter, ID,
-                                       BaseOffset + Offset, IncludeLoc);
-    break;
-  }
-
-  case SM_SLOC_EXPANSION_ENTRY: {
-    SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1]);
-    SourceMgr.createExpansionLoc(SpellingLoc,
-                                     ReadSourceLocation(*F, Record[2]),
-                                     ReadSourceLocation(*F, Record[3]),
-                                     Record[4],
-                                     ID,
-                                     BaseOffset + Record[0]);
-    break;
-  }
-  }
-
-  return false;
-}
-
-std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) {
-  if (ID == 0)
-    return std::make_pair(SourceLocation(), "");
-
-  if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) {
-    Error("source location entry ID out-of-range for AST file");
-    return std::make_pair(SourceLocation(), "");
-  }
-
-  // Find which module file this entry lands in.
-  ModuleFile *M = GlobalSLocEntryMap.find(-ID)->second;
-  if (M->Kind != MK_Module)
-    return std::make_pair(SourceLocation(), "");
-
-  // FIXME: Can we map this down to a particular submodule? That would be
-  // ideal.
-  return std::make_pair(M->ImportLoc, llvm::sys::path::stem(M->FileName));
-}
-
-/// \brief Find the location where the module F is imported.
-SourceLocation ASTReader::getImportLocation(ModuleFile *F) {
-  if (F->ImportLoc.isValid())
-    return F->ImportLoc;
-  
-  // Otherwise we have a PCH. It's considered to be "imported" at the first
-  // location of its includer.
-  if (F->ImportedBy.empty() || !F->ImportedBy[0]) {
-    // Main file is the importer. We assume that it is the first entry in the
-    // entry table. We can't ask the manager, because at the time of PCH loading
-    // the main file entry doesn't exist yet.
-    // The very first entry is the invalid instantiation loc, which takes up
-    // offsets 0 and 1.
-    return SourceLocation::getFromRawEncoding(2U);
-  }
-  //return F->Loaders[0]->FirstLoc;
-  return F->ImportedBy[0]->FirstLoc;
-}
-
-/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
-/// specified cursor.  Read the abbreviations that are at the top of the block
-/// and then leave the cursor pointing into the block.
-bool ASTReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
-                                 unsigned BlockID) {
-  if (Cursor.EnterSubBlock(BlockID)) {
-    Error("malformed block record in AST file");
-    return Failure;
-  }
-
-  while (true) {
-    uint64_t Offset = Cursor.GetCurrentBitNo();
-    unsigned Code = Cursor.ReadCode();
-
-    // We expect all abbrevs to be at the start of the block.
-    if (Code != llvm::bitc::DEFINE_ABBREV) {
-      Cursor.JumpToBit(Offset);
-      return false;
-    }
-    Cursor.ReadAbbrevRecord();
-  }
-}
-
-void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,
-                                MacroInfo *Hint) {
-  llvm::BitstreamCursor &Stream = F.MacroCursor;
-
-  // Keep track of where we are in the stream, then jump back there
-  // after reading this macro.
-  SavedStreamPosition SavedPosition(Stream);
-
-  Stream.JumpToBit(Offset);
-  RecordData Record;
-  SmallVector<IdentifierInfo*, 16> MacroArgs;
-  MacroInfo *Macro = 0;
-
-  // RAII object to add the loaded macro information once we're done
-  // adding tokens.
-  struct AddLoadedMacroInfoRAII {
-    Preprocessor &PP;
-    MacroInfo *Hint;
-    MacroInfo *MI;
-    IdentifierInfo *II;
-
-    AddLoadedMacroInfoRAII(Preprocessor &PP, MacroInfo *Hint)
-      : PP(PP), Hint(Hint), MI(), II() { }
-    ~AddLoadedMacroInfoRAII( ) {
-      if (MI) {
-        // Finally, install the macro.
-        PP.addLoadedMacroInfo(II, MI, Hint);
-      }
-    }
-  } AddLoadedMacroInfo(PP, Hint);
-
-  while (true) {
-    unsigned Code = Stream.ReadCode();
-    switch (Code) {
-    case llvm::bitc::END_BLOCK:
-      return;
-
-    case llvm::bitc::ENTER_SUBBLOCK:
-      // No known subblocks, always skip them.
-      Stream.ReadSubBlockID();
-      if (Stream.SkipBlock()) {
-        Error("malformed block record in AST file");
-        return;
-      }
-      continue;
-
-    case llvm::bitc::DEFINE_ABBREV:
-      Stream.ReadAbbrevRecord();
-      continue;
-    default: break;
-    }
-
-    // Read a record.
-    const char *BlobStart = 0;
-    unsigned BlobLen = 0;
-    Record.clear();
-    PreprocessorRecordTypes RecType =
-      (PreprocessorRecordTypes)Stream.ReadRecord(Code, Record, BlobStart,
-                                                 BlobLen);
-    switch (RecType) {
-    case PP_MACRO_OBJECT_LIKE:
-    case PP_MACRO_FUNCTION_LIKE: {
-      // If we already have a macro, that means that we've hit the end
-      // of the definition of the macro we were looking for. We're
-      // done.
-      if (Macro)
-        return;
-
-      IdentifierInfo *II = getLocalIdentifier(F, Record[0]);
-      if (II == 0) {
-        Error("macro must have a name in AST file");
-        return;
-      }
-
-      unsigned GlobalID = getGlobalMacroID(F, Record[1]);
-
-      // If this macro has already been loaded, don't do so again.
-      if (MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS])
-        return;
-
-      SubmoduleID GlobalSubmoduleID = getGlobalSubmoduleID(F, Record[2]);
-      unsigned NextIndex = 3;
-      SourceLocation Loc = ReadSourceLocation(F, Record, NextIndex);
-      MacroInfo *MI = PP.AllocateMacroInfo(Loc);
-
-      // Record this macro.
-      MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS] = MI;
-
-      SourceLocation UndefLoc = ReadSourceLocation(F, Record, NextIndex);
-      if (UndefLoc.isValid())
-        MI->setUndefLoc(UndefLoc);
-
-      MI->setIsUsed(Record[NextIndex++]);
-      MI->setIsFromAST();
-
-      bool IsPublic = Record[NextIndex++];
-      MI->setVisibility(IsPublic, ReadSourceLocation(F, Record, NextIndex));
-
-      if (RecType == PP_MACRO_FUNCTION_LIKE) {
-        // Decode function-like macro info.
-        bool isC99VarArgs = Record[NextIndex++];
-        bool isGNUVarArgs = Record[NextIndex++];
-        bool hasCommaPasting = Record[NextIndex++];
-        MacroArgs.clear();
-        unsigned NumArgs = Record[NextIndex++];
-        for (unsigned i = 0; i != NumArgs; ++i)
-          MacroArgs.push_back(getLocalIdentifier(F, Record[NextIndex++]));
-
-        // Install function-like macro info.
-        MI->setIsFunctionLike();
-        if (isC99VarArgs) MI->setIsC99Varargs();
-        if (isGNUVarArgs) MI->setIsGNUVarargs();
-        if (hasCommaPasting) MI->setHasCommaPasting();
-        MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
-                            PP.getPreprocessorAllocator());
-      }
-
-      if (DeserializationListener)
-        DeserializationListener->MacroRead(GlobalID, MI);
-
-      // If an update record marked this as undefined, do so now.
-      // FIXME: Only if the submodule this update came from is visible?
-      MacroUpdatesMap::iterator Update = MacroUpdates.find(GlobalID);
-      if (Update != MacroUpdates.end()) {
-        if (MI->getUndefLoc().isInvalid()) {
-          for (unsigned I = 0, N = Update->second.size(); I != N; ++I) {
-            bool Hidden = false;
-            if (unsigned SubmoduleID = Update->second[I].first) {
-              if (Module *Owner = getSubmodule(SubmoduleID)) {
-                if (Owner->NameVisibility == Module::Hidden) {
-                  // Note that this #undef is hidden.
-                  Hidden = true;
-
-                  // Record this hiding for later.
-                  HiddenNamesMap[Owner].push_back(
-                    HiddenName(II, MI, Update->second[I].second.UndefLoc));
-                }
-              }
-            }
-
-            if (!Hidden) {
-              MI->setUndefLoc(Update->second[I].second.UndefLoc);
-              if (PPMutationListener *Listener = PP.getPPMutationListener())
-                Listener->UndefinedMacro(MI);
-              break;
-            }
-          }
-        }
-        MacroUpdates.erase(Update);
-      }
-
-      // Determine whether this macro definition is visible.
-      bool Hidden = !MI->isPublic();
-      if (!Hidden && GlobalSubmoduleID) {
-        if (Module *Owner = getSubmodule(GlobalSubmoduleID)) {
-          if (Owner->NameVisibility == Module::Hidden) {
-            // The owning module is not visible, and this macro definition
-            // should not be, either.
-            Hidden = true;
-
-            // Note that this macro definition was hidden because its owning
-            // module is not yet visible.
-            HiddenNamesMap[Owner].push_back(HiddenName(II, MI));
-          }
-        }
-      }
-      MI->setHidden(Hidden);
-
-      // Make sure we install the macro once we're done.
-      AddLoadedMacroInfo.MI = MI;
-      AddLoadedMacroInfo.II = II;
-
-      // Remember that we saw this macro last so that we add the tokens that
-      // form its body to it.
-      Macro = MI;
-
-      if (NextIndex + 1 == Record.size() && PP.getPreprocessingRecord() &&
-          Record[NextIndex]) {
-        // We have a macro definition. Register the association
-        PreprocessedEntityID
-            GlobalID = getGlobalPreprocessedEntityID(F, Record[NextIndex]);
-        PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
-        PPRec.RegisterMacroDefinition(Macro,
-                            PPRec.getPPEntityID(GlobalID-1, /*isLoaded=*/true));
-      }
-
-      ++NumMacrosRead;
-      break;
-    }
-
-    case PP_TOKEN: {
-      // If we see a TOKEN before a PP_MACRO_*, then the file is
-      // erroneous, just pretend we didn't see this.
-      if (Macro == 0) break;
-
-      Token Tok;
-      Tok.startToken();
-      Tok.setLocation(ReadSourceLocation(F, Record[0]));
-      Tok.setLength(Record[1]);
-      if (IdentifierInfo *II = getLocalIdentifier(F, Record[2]))
-        Tok.setIdentifierInfo(II);
-      Tok.setKind((tok::TokenKind)Record[3]);
-      Tok.setFlag((Token::TokenFlags)Record[4]);
-      Macro->AddTokenToBody(Tok);
-      break;
-    }
-    }
-  }
-}
-
-PreprocessedEntityID 
-ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const {
-  ContinuousRangeMap<uint32_t, int, 2>::const_iterator 
-    I = M.PreprocessedEntityRemap.find(LocalID - NUM_PREDEF_PP_ENTITY_IDS);
-  assert(I != M.PreprocessedEntityRemap.end() 
-         && "Invalid index into preprocessed entity index remap");
-  
-  return LocalID + I->second;
-}
-
-unsigned HeaderFileInfoTrait::ComputeHash(const char *path) {
-  return llvm::HashString(llvm::sys::path::filename(path));
-}
-    
-HeaderFileInfoTrait::internal_key_type 
-HeaderFileInfoTrait::GetInternalKey(const char *path) { return path; }
-    
-bool HeaderFileInfoTrait::EqualKey(internal_key_type a, internal_key_type b) {
-  if (strcmp(a, b) == 0)
-    return true;
-  
-  if (llvm::sys::path::filename(a) != llvm::sys::path::filename(b))
-    return false;
-
-  // Determine whether the actual files are equivalent.
-  bool Result = false;
-  if (llvm::sys::fs::equivalent(a, b, Result))
-    return false;
-  
-  return Result;
-}
-    
-std::pair<unsigned, unsigned>
-HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) {
-  unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
-  unsigned DataLen = (unsigned) *d++;
-  return std::make_pair(KeyLen + 1, DataLen);
-}
-    
-HeaderFileInfoTrait::data_type 
-HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d,
-                              unsigned DataLen) {
-  const unsigned char *End = d + DataLen;
-  using namespace clang::io;
-  HeaderFileInfo HFI;
-  unsigned Flags = *d++;
-  HFI.isImport = (Flags >> 5) & 0x01;
-  HFI.isPragmaOnce = (Flags >> 4) & 0x01;
-  HFI.DirInfo = (Flags >> 2) & 0x03;
-  HFI.Resolved = (Flags >> 1) & 0x01;
-  HFI.IndexHeaderMapHeader = Flags & 0x01;
-  HFI.NumIncludes = ReadUnalignedLE16(d);
-  HFI.ControllingMacroID = Reader.getGlobalIdentifierID(M, 
-                                                        ReadUnalignedLE32(d));
-  if (unsigned FrameworkOffset = ReadUnalignedLE32(d)) {
-    // The framework offset is 1 greater than the actual offset, 
-    // since 0 is used as an indicator for "no framework name".
-    StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);
-    HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
-  }
-  
-  assert(End == d && "Wrong data length in HeaderFileInfo deserialization");
-  (void)End;
-        
-  // This HeaderFileInfo was externally loaded.
-  HFI.External = true;
-  return HFI;
-}
-
-void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ArrayRef<MacroID> IDs){
-  II->setHadMacroDefinition(true);
-  assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
-  PendingMacroIDs[II].append(IDs.begin(), IDs.end());
-}
-
-void ASTReader::ReadDefinedMacros() {
-  // Note that we are loading defined macros.
-  Deserializing Macros(this);
-
-  for (ModuleReverseIterator I = ModuleMgr.rbegin(),
-      E = ModuleMgr.rend(); I != E; ++I) {
-    llvm::BitstreamCursor &MacroCursor = (*I)->MacroCursor;
-
-    // If there was no preprocessor block, skip this file.
-    if (!MacroCursor.getBitStreamReader())
-      continue;
-
-    llvm::BitstreamCursor Cursor = MacroCursor;
-    Cursor.JumpToBit((*I)->MacroStartOffset);
-
-    RecordData Record;
-    while (true) {
-      unsigned Code = Cursor.ReadCode();
-      if (Code == llvm::bitc::END_BLOCK)
-        break;
-
-      if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-        // No known subblocks, always skip them.
-        Cursor.ReadSubBlockID();
-        if (Cursor.SkipBlock()) {
-          Error("malformed block record in AST file");
-          return;
-        }
-        continue;
-      }
-
-      if (Code == llvm::bitc::DEFINE_ABBREV) {
-        Cursor.ReadAbbrevRecord();
-        continue;
-      }
-
-      // Read a record.
-      const char *BlobStart;
-      unsigned BlobLen;
-      Record.clear();
-      switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
-      default:  // Default behavior: ignore.
-        break;
-
-      case PP_MACRO_OBJECT_LIKE:
-      case PP_MACRO_FUNCTION_LIKE:
-        getLocalIdentifier(**I, Record[0]);
-        break;
-
-      case PP_TOKEN:
-        // Ignore tokens.
-        break;
-      }
-    }
-  }
-}
-
-namespace {
-  /// \brief Visitor class used to look up identifirs in an AST file.
-  class IdentifierLookupVisitor {
-    StringRef Name;
-    unsigned PriorGeneration;
-    IdentifierInfo *Found;
-  public:
-    IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration) 
-      : Name(Name), PriorGeneration(PriorGeneration), Found() { }
-    
-    static bool visit(ModuleFile &M, void *UserData) {
-      IdentifierLookupVisitor *This
-        = static_cast<IdentifierLookupVisitor *>(UserData);
-      
-      // If we've already searched this module file, skip it now.
-      if (M.Generation <= This->PriorGeneration)
-        return true;
-      
-      ASTIdentifierLookupTable *IdTable
-        = (ASTIdentifierLookupTable *)M.IdentifierLookupTable;
-      if (!IdTable)
-        return false;
-      
-      ASTIdentifierLookupTrait Trait(IdTable->getInfoObj().getReader(),
-                                     M, This->Found);
-                                     
-      std::pair<const char*, unsigned> Key(This->Name.begin(), 
-                                           This->Name.size());
-      ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Trait);
-      if (Pos == IdTable->end())
-        return false;
-      
-      // Dereferencing the iterator has the effect of building the
-      // IdentifierInfo node and populating it with the various
-      // declarations it needs.
-      This->Found = *Pos;
-      return true;
-    }
-    
-    // \brief Retrieve the identifier info found within the module
-    // files.
-    IdentifierInfo *getIdentifierInfo() const { return Found; }
-  };
-}
-
-void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {
-  // Note that we are loading an identifier.
-  Deserializing AnIdentifier(this);
-
-  unsigned PriorGeneration = 0;
-  if (getContext().getLangOpts().Modules)
-    PriorGeneration = IdentifierGeneration[&II];
-  
-  IdentifierLookupVisitor Visitor(II.getName(), PriorGeneration);
-  ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
-  markIdentifierUpToDate(&II);
-}
-
-void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) {
-  if (!II)
-    return;
-  
-  II->setOutOfDate(false);
-
-  // Update the generation for this identifier.
-  if (getContext().getLangOpts().Modules)
-    IdentifierGeneration[II] = CurrentGeneration;
-}
-
-llvm::PointerIntPair<const FileEntry *, 1, bool> 
-ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
-  // If this ID is bogus, just return an empty input file.
-  if (ID == 0 || ID > F.InputFilesLoaded.size())
-    return InputFile();
-
-  // If we've already loaded this input file, return it.
-  if (F.InputFilesLoaded[ID-1].getPointer())
-    return F.InputFilesLoaded[ID-1];
-
-  // Go find this input file.
-  llvm::BitstreamCursor &Cursor = F.InputFilesCursor;
-  SavedStreamPosition SavedPosition(Cursor);
-  Cursor.JumpToBit(F.InputFileOffsets[ID-1]);
-  
-  unsigned Code = Cursor.ReadCode();
-  RecordData Record;
-  const char *BlobStart = 0;
-  unsigned BlobLen = 0;
-  switch ((InputFileRecordTypes)Cursor.ReadRecord(Code, Record,
-                                                  &BlobStart, &BlobLen)) {
-  case INPUT_FILE: {
-    unsigned StoredID = Record[0];
-    assert(ID == StoredID && "Bogus stored ID or offset");
-    (void)StoredID;
-    off_t StoredSize = (off_t)Record[1];
-    time_t StoredTime = (time_t)Record[2];
-    bool Overridden = (bool)Record[3];
-    
-    // Get the file entry for this input file.
-    StringRef OrigFilename(BlobStart, BlobLen);
-    std::string Filename = OrigFilename;
-    MaybeAddSystemRootToFilename(F, Filename);
-    const FileEntry *File 
-      = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime)
-                  : FileMgr.getFile(Filename, /*OpenFile=*/false);
-    
-    // If we didn't find the file, resolve it relative to the
-    // original directory from which this AST file was created.
-    if (File == 0 && !F.OriginalDir.empty() && !CurrentDir.empty() &&
-        F.OriginalDir != CurrentDir) {
-      std::string Resolved = resolveFileRelativeToOriginalDir(Filename,
-                                                              F.OriginalDir,
-                                                              CurrentDir);
-      if (!Resolved.empty())
-        File = FileMgr.getFile(Resolved);
-    }
-    
-    // For an overridden file, create a virtual file with the stored
-    // size/timestamp.
-    if (Overridden && File == 0) {
-      File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime);
-    }
-    
-    if (File == 0) {
-      if (Complain) {
-        std::string ErrorStr = "could not find file '";
-        ErrorStr += Filename;
-        ErrorStr += "' referenced by AST file";
-        Error(ErrorStr.c_str());
-      }
-      return InputFile();
-    }
-    
-    // Note that we've loaded this input file.
-    F.InputFilesLoaded[ID-1] = InputFile(File, Overridden);
-    
-    // Check if there was a request to override the contents of the file
-    // that was part of the precompiled header. Overridding such a file
-    // can lead to problems when lexing using the source locations from the
-    // PCH.
-    SourceManager &SM = getSourceManager();
-    if (!Overridden && SM.isFileOverridden(File)) {
-      Error(diag::err_fe_pch_file_overridden, Filename);
-      // After emitting the diagnostic, recover by disabling the override so
-      // that the original file will be used.
-      SM.disableFileContentsOverride(File);
-      // The FileEntry is a virtual file entry with the size of the contents
-      // that would override the original contents. Set it to the original's
-      // size/time.
-      FileMgr.modifyFileEntry(const_cast<FileEntry*>(File),
-                              StoredSize, StoredTime);
-    }
-
-    // For an overridden file, there is nothing to validate.
-    if (Overridden)
-      return InputFile(File, Overridden);
-
-    if ((StoredSize != File->getSize()
-#if !defined(LLVM_ON_WIN32)
-         // In our regression testing, the Windows file system seems to
-         // have inconsistent modification times that sometimes
-         // erroneously trigger this error-handling path.
-         || StoredTime != File->getModificationTime()
-#endif
-         )) {
-      if (Complain)
-        Error(diag::err_fe_pch_file_modified, Filename);
-      
-      return InputFile();
-    }
-
-    return InputFile(File, Overridden);
-  }
-  }
-
-  return InputFile();
-}
-
-const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) {
-  ModuleFile &M = ModuleMgr.getPrimaryModule();
-  std::string Filename = filenameStrRef;
-  MaybeAddSystemRootToFilename(M, Filename);
-  const FileEntry *File = FileMgr.getFile(Filename);
-  if (File == 0 && !M.OriginalDir.empty() && !CurrentDir.empty() &&
-      M.OriginalDir != CurrentDir) {
-    std::string resolved = resolveFileRelativeToOriginalDir(Filename,
-                                                            M.OriginalDir,
-                                                            CurrentDir);
-    if (!resolved.empty())
-      File = FileMgr.getFile(resolved);
-  }
-
-  return File;
-}
-
-/// \brief If we are loading a relocatable PCH file, and the filename is
-/// not an absolute path, add the system root to the beginning of the file
-/// name.
-void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M,
-                                             std::string &Filename) {
-  // If this is not a relocatable PCH file, there's nothing to do.
-  if (!M.RelocatablePCH)
-    return;
-
-  if (Filename.empty() || llvm::sys::path::is_absolute(Filename))
-    return;
-
-  if (isysroot.empty()) {
-    // If no system root was given, default to '/'
-    Filename.insert(Filename.begin(), '/');
-    return;
-  }
-
-  unsigned Length = isysroot.size();
-  if (isysroot[Length - 1] != '/')
-    Filename.insert(Filename.begin(), '/');
-
-  Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end());
-}
-
-ASTReader::ASTReadResult
-ASTReader::ReadControlBlock(ModuleFile &F,
-                            llvm::SmallVectorImpl<ImportedModule> &Loaded,
-                            unsigned ClientLoadCapabilities) {
-  llvm::BitstreamCursor &Stream = F.Stream;
-
-  if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
-    Error("malformed block record in AST file");
-    return Failure;
-  }
-
-  // Read all of the records and blocks in the control block.
-  RecordData Record;
-  while (!Stream.AtEndOfStream()) {
-    unsigned Code = Stream.ReadCode();
-    if (Code == llvm::bitc::END_BLOCK) {
-      if (Stream.ReadBlockEnd()) {
-        Error("error at end of control block in AST file");
-        return Failure;
-      }
-
-      // Validate all of the input files.
-      if (!DisableValidation) {
-        bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
-        for (unsigned I = 0, N = Record[0]; I < N; ++I)
-          if (!getInputFile(F, I+1, Complain).getPointer())
-            return OutOfDate;
-      }
-
-      return Success;
-    }
-
-    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-      switch (Stream.ReadSubBlockID()) {
-      case INPUT_FILES_BLOCK_ID:
-        F.InputFilesCursor = Stream;
-        if (Stream.SkipBlock() || // Skip with the main cursor
-            // Read the abbreviations
-            ReadBlockAbbrevs(F.InputFilesCursor, INPUT_FILES_BLOCK_ID)) {
-          Error("malformed block record in AST file");
-          return Failure;
-        }
-        continue;
-        
-      default:
-        if (!Stream.SkipBlock())
-          continue;
-        break;
-      }
-
-      Error("malformed block record in AST file");
-      return Failure;
-    }
-
-    if (Code == llvm::bitc::DEFINE_ABBREV) {
-      Stream.ReadAbbrevRecord();
-      continue;
-    }
-
-    // Read and process a record.
-    Record.clear();
-    const char *BlobStart = 0;
-    unsigned BlobLen = 0;
-    switch ((ControlRecordTypes)Stream.ReadRecord(Code, Record,
-                                                  &BlobStart, &BlobLen)) {
-    case METADATA: {
-      if (Record[0] != VERSION_MAJOR && !DisableValidation) {
-        if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
-          Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
-                                        : diag::warn_pch_version_too_new);
-        return VersionMismatch;
-      }
-
-      bool hasErrors = Record[5];
-      if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {
-        Diag(diag::err_pch_with_compiler_errors);
-        return HadErrors;
-      }
-
-      F.RelocatablePCH = Record[4];
-
-      const std::string &CurBranch = getClangFullRepositoryVersion();
-      StringRef ASTBranch(BlobStart, BlobLen);
-      if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {
-        if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
-          Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch;
-        return VersionMismatch;
-      }
-      break;
-    }
-
-    case IMPORTS: {
-      // Load each of the imported PCH files. 
-      unsigned Idx = 0, N = Record.size();
-      while (Idx < N) {
-        // Read information about the AST file.
-        ModuleKind ImportedKind = (ModuleKind)Record[Idx++];
-        // The import location will be the local one for now; we will adjust
-        // all import locations of module imports after the global source
-        // location info are setup.
-        SourceLocation ImportLoc =
-            SourceLocation::getFromRawEncoding(Record[Idx++]);
-        unsigned Length = Record[Idx++];
-        SmallString<128> ImportedFile(Record.begin() + Idx,
-                                      Record.begin() + Idx + Length);
-        Idx += Length;
-
-        // Load the AST file.
-        switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded,
-                           ClientLoadCapabilities)) {
-        case Failure: return Failure;
-          // If we have to ignore the dependency, we'll have to ignore this too.
-        case OutOfDate: return OutOfDate;
-        case VersionMismatch: return VersionMismatch;
-        case ConfigurationMismatch: return ConfigurationMismatch;
-        case HadErrors: return HadErrors;
-        case Success: break;
-        }
-      }
-      break;
-    }
-
-    case LANGUAGE_OPTIONS: {
-      bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
-      if (Listener && &F == *ModuleMgr.begin() &&
-          ParseLanguageOptions(Record, Complain, *Listener) &&
-          !DisableValidation)
-        return ConfigurationMismatch;
-      break;
-    }
-
-    case TARGET_OPTIONS: {
-      bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
-      if (Listener && &F == *ModuleMgr.begin() &&
-          ParseTargetOptions(Record, Complain, *Listener) &&
-          !DisableValidation)
-        return ConfigurationMismatch;
-      break;
-    }
-
-    case DIAGNOSTIC_OPTIONS: {
-      bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
-      if (Listener && &F == *ModuleMgr.begin() &&
-          ParseDiagnosticOptions(Record, Complain, *Listener) &&
-          !DisableValidation)
-        return ConfigurationMismatch;
-      break;
-    }
-
-    case FILE_SYSTEM_OPTIONS: {
-      bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
-      if (Listener && &F == *ModuleMgr.begin() &&
-          ParseFileSystemOptions(Record, Complain, *Listener) &&
-          !DisableValidation)
-        return ConfigurationMismatch;
-      break;
-    }
-
-    case HEADER_SEARCH_OPTIONS: {
-      bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
-      if (Listener && &F == *ModuleMgr.begin() &&
-          ParseHeaderSearchOptions(Record, Complain, *Listener) &&
-          !DisableValidation)
-        return ConfigurationMismatch;
-      break;
-    }
-
-    case PREPROCESSOR_OPTIONS: {
-      bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
-      if (Listener && &F == *ModuleMgr.begin() &&
-          ParsePreprocessorOptions(Record, Complain, *Listener,
-                                   SuggestedPredefines) &&
-          !DisableValidation)
-        return ConfigurationMismatch;
-      break;
-    }
-
-    case ORIGINAL_FILE:
-      F.OriginalSourceFileID = FileID::get(Record[0]);
-      F.ActualOriginalSourceFileName.assign(BlobStart, BlobLen);
-      F.OriginalSourceFileName = F.ActualOriginalSourceFileName;
-      MaybeAddSystemRootToFilename(F, F.OriginalSourceFileName);
-      break;
-
-    case ORIGINAL_FILE_ID:
-      F.OriginalSourceFileID = FileID::get(Record[0]);
-      break;
-
-    case ORIGINAL_PCH_DIR:
-      F.OriginalDir.assign(BlobStart, BlobLen);
-      break;
-
-    case INPUT_FILE_OFFSETS:
-      F.InputFileOffsets = (const uint32_t *)BlobStart;
-      F.InputFilesLoaded.resize(Record[0]);
-      break;
-    }
-  }
-
-  Error("premature end of bitstream in AST file");
-  return Failure;
-}
-
-bool ASTReader::ReadASTBlock(ModuleFile &F) {
-  llvm::BitstreamCursor &Stream = F.Stream;
-
-  if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
-    Error("malformed block record in AST file");
-    return true;
-  }
-
-  // Read all of the records and blocks for the AST file.
-  RecordData Record;
-  while (!Stream.AtEndOfStream()) {
-    unsigned Code = Stream.ReadCode();
-    if (Code == llvm::bitc::END_BLOCK) {
-      if (Stream.ReadBlockEnd()) {
-        Error("error at end of module block in AST file");
-        return true;
-      }
-
-      DeclContext *DC = Context.getTranslationUnitDecl();
-      if (!DC->hasExternalVisibleStorage() && DC->hasExternalLexicalStorage())
-        DC->setMustBuildLookupTable();
-
-      return false;
-    }
-
-    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-      switch (Stream.ReadSubBlockID()) {
-      case DECLTYPES_BLOCK_ID:
-        // We lazily load the decls block, but we want to set up the
-        // DeclsCursor cursor to point into it.  Clone our current bitcode
-        // cursor to it, enter the block and read the abbrevs in that block.
-        // With the main cursor, we just skip over it.
-        F.DeclsCursor = Stream;
-        if (Stream.SkipBlock() ||  // Skip with the main cursor.
-            // Read the abbrevs.
-            ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) {
-          Error("malformed block record in AST file");
-          return true;
-        }
-        break;
-
-      case DECL_UPDATES_BLOCK_ID:
-        if (Stream.SkipBlock()) {
-          Error("malformed block record in AST file");
-          return true;
-        }
-        break;
-
-      case PREPROCESSOR_BLOCK_ID:
-        F.MacroCursor = Stream;
-        if (!PP.getExternalSource())
-          PP.setExternalSource(this);
-
-        if (Stream.SkipBlock() ||
-            ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) {
-          Error("malformed block record in AST file");
-          return true;
-        }
-        F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo();
-        break;
-
-      case PREPROCESSOR_DETAIL_BLOCK_ID:
-        F.PreprocessorDetailCursor = Stream;
-        if (Stream.SkipBlock() ||
-            ReadBlockAbbrevs(F.PreprocessorDetailCursor, 
-                             PREPROCESSOR_DETAIL_BLOCK_ID)) {
-          Error("malformed preprocessor detail record in AST file");
-          return true;
-        }
-        F.PreprocessorDetailStartOffset
-          = F.PreprocessorDetailCursor.GetCurrentBitNo();
-          
-        if (!PP.getPreprocessingRecord())
-          PP.createPreprocessingRecord();
-        if (!PP.getPreprocessingRecord()->getExternalSource())
-          PP.getPreprocessingRecord()->SetExternalSource(*this);
-        break;
-        
-      case SOURCE_MANAGER_BLOCK_ID:
-        if (ReadSourceManagerBlock(F))
-          return true;
-        break;
-
-      case SUBMODULE_BLOCK_ID:
-        if (ReadSubmoduleBlock(F))
-          return true;
-        break;
-
-      case COMMENTS_BLOCK_ID: {
-        llvm::BitstreamCursor C = Stream;
-        if (Stream.SkipBlock() ||
-            ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) {
-          Error("malformed comments block in AST file");
-          return true;
-        }
-        CommentsCursors.push_back(std::make_pair(C, &F));
-        break;
-      }
-
-      default:
-        if (!Stream.SkipBlock())
-          break;
-        Error("malformed block record in AST file");
-        return true;
-      }
-      continue;
-    }
-
-    if (Code == llvm::bitc::DEFINE_ABBREV) {
-      Stream.ReadAbbrevRecord();
-      continue;
-    }
-
-    // Read and process a record.
-    Record.clear();
-    const char *BlobStart = 0;
-    unsigned BlobLen = 0;
-    switch ((ASTRecordTypes)Stream.ReadRecord(Code, Record,
-                                              &BlobStart, &BlobLen)) {
-    default:  // Default behavior: ignore.
-      break;
-
-    case TYPE_OFFSET: {
-      if (F.LocalNumTypes != 0) {
-        Error("duplicate TYPE_OFFSET record in AST file");
-        return true;
-      }
-      F.TypeOffsets = (const uint32_t *)BlobStart;
-      F.LocalNumTypes = Record[0];
-      unsigned LocalBaseTypeIndex = Record[1];
-      F.BaseTypeIndex = getTotalNumTypes();
-        
-      if (F.LocalNumTypes > 0) {
-        // Introduce the global -> local mapping for types within this module.
-        GlobalTypeMap.insert(std::make_pair(getTotalNumTypes(), &F));
-        
-        // Introduce the local -> global mapping for types within this module.
-        F.TypeRemap.insertOrReplace(
-          std::make_pair(LocalBaseTypeIndex, 
-                         F.BaseTypeIndex - LocalBaseTypeIndex));
-        
-        TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes);
-      }
-      break;
-    }
-        
-    case DECL_OFFSET: {
-      if (F.LocalNumDecls != 0) {
-        Error("duplicate DECL_OFFSET record in AST file");
-        return true;
-      }
-      F.DeclOffsets = (const DeclOffset *)BlobStart;
-      F.LocalNumDecls = Record[0];
-      unsigned LocalBaseDeclID = Record[1];
-      F.BaseDeclID = getTotalNumDecls();
-        
-      if (F.LocalNumDecls > 0) {
-        // Introduce the global -> local mapping for declarations within this 
-        // module.
-        GlobalDeclMap.insert(
-          std::make_pair(getTotalNumDecls() + NUM_PREDEF_DECL_IDS, &F));
-        
-        // Introduce the local -> global mapping for declarations within this
-        // module.
-        F.DeclRemap.insertOrReplace(
-          std::make_pair(LocalBaseDeclID, F.BaseDeclID - LocalBaseDeclID));
-        
-        // Introduce the global -> local mapping for declarations within this
-        // module.
-        F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID;
-        
-        DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);
-      }
-      break;
-    }
-        
-    case TU_UPDATE_LEXICAL: {
-      DeclContext *TU = Context.getTranslationUnitDecl();
-      DeclContextInfo &Info = F.DeclContextInfos[TU];
-      Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair *>(BlobStart);
-      Info.NumLexicalDecls 
-        = static_cast<unsigned int>(BlobLen / sizeof(KindDeclIDPair));
-      TU->setHasExternalLexicalStorage(true);
-      break;
-    }
-
-    case UPDATE_VISIBLE: {
-      unsigned Idx = 0;
-      serialization::DeclID ID = ReadDeclID(F, Record, Idx);
-      ASTDeclContextNameLookupTable *Table =
-        ASTDeclContextNameLookupTable::Create(
-                        (const unsigned char *)BlobStart + Record[Idx++],
-                        (const unsigned char *)BlobStart,
-                        ASTDeclContextNameLookupTrait(*this, F));
-      if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID) { // Is it the TU?
-        DeclContext *TU = Context.getTranslationUnitDecl();
-        F.DeclContextInfos[TU].NameLookupTableData = Table;
-        TU->setHasExternalVisibleStorage(true);
-      } else
-        PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F));
-      break;
-    }
-
-    case IDENTIFIER_TABLE:
-      F.IdentifierTableData = BlobStart;
-      if (Record[0]) {
-        F.IdentifierLookupTable
-          = ASTIdentifierLookupTable::Create(
-                       (const unsigned char *)F.IdentifierTableData + Record[0],
-                       (const unsigned char *)F.IdentifierTableData,
-                       ASTIdentifierLookupTrait(*this, F));
-        
-        PP.getIdentifierTable().setExternalIdentifierLookup(this);
-      }
-      break;
-
-    case IDENTIFIER_OFFSET: {
-      if (F.LocalNumIdentifiers != 0) {
-        Error("duplicate IDENTIFIER_OFFSET record in AST file");
-        return true;
-      }
-      F.IdentifierOffsets = (const uint32_t *)BlobStart;
-      F.LocalNumIdentifiers = Record[0];
-      unsigned LocalBaseIdentifierID = Record[1];
-      F.BaseIdentifierID = getTotalNumIdentifiers();
-        
-      if (F.LocalNumIdentifiers > 0) {
-        // Introduce the global -> local mapping for identifiers within this
-        // module.
-        GlobalIdentifierMap.insert(std::make_pair(getTotalNumIdentifiers() + 1, 
-                                                  &F));
-        
-        // Introduce the local -> global mapping for identifiers within this
-        // module.
-        F.IdentifierRemap.insertOrReplace(
-          std::make_pair(LocalBaseIdentifierID,
-                         F.BaseIdentifierID - LocalBaseIdentifierID));
-        
-        IdentifiersLoaded.resize(IdentifiersLoaded.size() 
-                                 + F.LocalNumIdentifiers);
-      }
-      break;
-    }
-
-    case EXTERNAL_DEFINITIONS:
-      for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        ExternalDefinitions.push_back(getGlobalDeclID(F, Record[I]));
-      break;
-
-    case SPECIAL_TYPES:
-      for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        SpecialTypes.push_back(getGlobalTypeID(F, Record[I]));
-      break;
-
-    case STATISTICS:
-      TotalNumStatements += Record[0];
-      TotalNumMacros += Record[1];
-      TotalLexicalDeclContexts += Record[2];
-      TotalVisibleDeclContexts += Record[3];
-      break;
-
-    case UNUSED_FILESCOPED_DECLS:
-      for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        UnusedFileScopedDecls.push_back(getGlobalDeclID(F, Record[I]));
-      break;
-
-    case DELEGATING_CTORS:
-      for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        DelegatingCtorDecls.push_back(getGlobalDeclID(F, Record[I]));
-      break;
-
-    case WEAK_UNDECLARED_IDENTIFIERS:
-      if (Record.size() % 4 != 0) {
-        Error("invalid weak identifiers record");
-        return true;
-      }
-        
-      // FIXME: Ignore weak undeclared identifiers from non-original PCH 
-      // files. This isn't the way to do it :)
-      WeakUndeclaredIdentifiers.clear();
-        
-      // Translate the weak, undeclared identifiers into global IDs.
-      for (unsigned I = 0, N = Record.size(); I < N; /* in loop */) {
-        WeakUndeclaredIdentifiers.push_back(
-          getGlobalIdentifierID(F, Record[I++]));
-        WeakUndeclaredIdentifiers.push_back(
-          getGlobalIdentifierID(F, Record[I++]));
-        WeakUndeclaredIdentifiers.push_back(
-          ReadSourceLocation(F, Record, I).getRawEncoding());
-        WeakUndeclaredIdentifiers.push_back(Record[I++]);
-      }
-      break;
-
-    case LOCALLY_SCOPED_EXTERNAL_DECLS:
-      for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        LocallyScopedExternalDecls.push_back(getGlobalDeclID(F, Record[I]));
-      break;
-
-    case SELECTOR_OFFSETS: {
-      F.SelectorOffsets = (const uint32_t *)BlobStart;
-      F.LocalNumSelectors = Record[0];
-      unsigned LocalBaseSelectorID = Record[1];
-      F.BaseSelectorID = getTotalNumSelectors();
-        
-      if (F.LocalNumSelectors > 0) {
-        // Introduce the global -> local mapping for selectors within this 
-        // module.
-        GlobalSelectorMap.insert(std::make_pair(getTotalNumSelectors()+1, &F));
-        
-        // Introduce the local -> global mapping for selectors within this 
-        // module.
-        F.SelectorRemap.insertOrReplace(
-          std::make_pair(LocalBaseSelectorID,
-                         F.BaseSelectorID - LocalBaseSelectorID));
-
-        SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors);        
-      }
-      break;
-    }
-        
-    case METHOD_POOL:
-      F.SelectorLookupTableData = (const unsigned char *)BlobStart;
-      if (Record[0])
-        F.SelectorLookupTable
-          = ASTSelectorLookupTable::Create(
-                        F.SelectorLookupTableData + Record[0],
-                        F.SelectorLookupTableData,
-                        ASTSelectorLookupTrait(*this, F));
-      TotalNumMethodPoolEntries += Record[1];
-      break;
-
-    case REFERENCED_SELECTOR_POOL:
-      if (!Record.empty()) {
-        for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) {
-          ReferencedSelectorsData.push_back(getGlobalSelectorID(F, 
-                                                                Record[Idx++]));
-          ReferencedSelectorsData.push_back(ReadSourceLocation(F, Record, Idx).
-                                              getRawEncoding());
-        }
-      }
-      break;
-
-    case PP_COUNTER_VALUE:
-      if (!Record.empty() && Listener)
-        Listener->ReadCounter(F, Record[0]);
-      break;
-      
-    case FILE_SORTED_DECLS:
-      F.FileSortedDecls = (const DeclID *)BlobStart;
-      F.NumFileSortedDecls = Record[0];
-      break;
-
-    case SOURCE_LOCATION_OFFSETS: {
-      F.SLocEntryOffsets = (const uint32_t *)BlobStart;
-      F.LocalNumSLocEntries = Record[0];
-      unsigned SLocSpaceSize = Record[1];
-      llvm::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) =
-          SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries,
-                                              SLocSpaceSize);
-      // Make our entry in the range map. BaseID is negative and growing, so
-      // we invert it. Because we invert it, though, we need the other end of
-      // the range.
-      unsigned RangeStart =
-          unsigned(-F.SLocEntryBaseID) - F.LocalNumSLocEntries + 1;
-      GlobalSLocEntryMap.insert(std::make_pair(RangeStart, &F));
-      F.FirstLoc = SourceLocation::getFromRawEncoding(F.SLocEntryBaseOffset);
-
-      // SLocEntryBaseOffset is lower than MaxLoadedOffset and decreasing.
-      assert((F.SLocEntryBaseOffset & (1U << 31U)) == 0);
-      GlobalSLocOffsetMap.insert(
-          std::make_pair(SourceManager::MaxLoadedOffset - F.SLocEntryBaseOffset
-                           - SLocSpaceSize,&F));
-
-      // Initialize the remapping table.
-      // Invalid stays invalid.
-      F.SLocRemap.insert(std::make_pair(0U, 0));
-      // This module. Base was 2 when being compiled.
-      F.SLocRemap.insert(std::make_pair(2U,
-                                  static_cast<int>(F.SLocEntryBaseOffset - 2)));
-      
-      TotalNumSLocEntries += F.LocalNumSLocEntries;
-      break;
-    }
-
-    case MODULE_OFFSET_MAP: {
-      // Additional remapping information.
-      const unsigned char *Data = (const unsigned char*)BlobStart;
-      const unsigned char *DataEnd = Data + BlobLen;
-      
-      // Continuous range maps we may be updating in our module.
-      ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap);
-      ContinuousRangeMap<uint32_t, int, 2>::Builder 
-        IdentifierRemap(F.IdentifierRemap);
-      ContinuousRangeMap<uint32_t, int, 2>::Builder
-        MacroRemap(F.MacroRemap);
-      ContinuousRangeMap<uint32_t, int, 2>::Builder
-        PreprocessedEntityRemap(F.PreprocessedEntityRemap);
-      ContinuousRangeMap<uint32_t, int, 2>::Builder 
-        SubmoduleRemap(F.SubmoduleRemap);
-      ContinuousRangeMap<uint32_t, int, 2>::Builder 
-        SelectorRemap(F.SelectorRemap);
-      ContinuousRangeMap<uint32_t, int, 2>::Builder DeclRemap(F.DeclRemap);
-      ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap);
-
-      while(Data < DataEnd) {
-        uint16_t Len = io::ReadUnalignedLE16(Data);
-        StringRef Name = StringRef((const char*)Data, Len);
-        Data += Len;
-        ModuleFile *OM = ModuleMgr.lookup(Name);
-        if (!OM) {
-          Error("SourceLocation remap refers to unknown module");
-          return true;
-        }
-
-        uint32_t SLocOffset = io::ReadUnalignedLE32(Data);
-        uint32_t IdentifierIDOffset = io::ReadUnalignedLE32(Data);
-        uint32_t MacroIDOffset = io::ReadUnalignedLE32(Data);
-        uint32_t PreprocessedEntityIDOffset = io::ReadUnalignedLE32(Data);
-        uint32_t SubmoduleIDOffset = io::ReadUnalignedLE32(Data);
-        uint32_t SelectorIDOffset = io::ReadUnalignedLE32(Data);
-        uint32_t DeclIDOffset = io::ReadUnalignedLE32(Data);
-        uint32_t TypeIndexOffset = io::ReadUnalignedLE32(Data);
-        
-        // Source location offset is mapped to OM->SLocEntryBaseOffset.
-        SLocRemap.insert(std::make_pair(SLocOffset,
-          static_cast<int>(OM->SLocEntryBaseOffset - SLocOffset)));
-        IdentifierRemap.insert(
-          std::make_pair(IdentifierIDOffset, 
-                         OM->BaseIdentifierID - IdentifierIDOffset));
-        MacroRemap.insert(std::make_pair(MacroIDOffset,
-                                         OM->BaseMacroID - MacroIDOffset));
-        PreprocessedEntityRemap.insert(
-          std::make_pair(PreprocessedEntityIDOffset, 
-            OM->BasePreprocessedEntityID - PreprocessedEntityIDOffset));
-        SubmoduleRemap.insert(std::make_pair(SubmoduleIDOffset, 
-                                      OM->BaseSubmoduleID - SubmoduleIDOffset));
-        SelectorRemap.insert(std::make_pair(SelectorIDOffset, 
-                               OM->BaseSelectorID - SelectorIDOffset));
-        DeclRemap.insert(std::make_pair(DeclIDOffset, 
-                                        OM->BaseDeclID - DeclIDOffset));
-        
-        TypeRemap.insert(std::make_pair(TypeIndexOffset, 
-                                    OM->BaseTypeIndex - TypeIndexOffset));
-
-        // Global -> local mappings.
-        F.GlobalToLocalDeclIDs[OM] = DeclIDOffset;
-      }
-      break;
-    }
-
-    case SOURCE_MANAGER_LINE_TABLE:
-      if (ParseLineTable(F, Record))
-        return true;
-      break;
-
-    case SOURCE_LOCATION_PRELOADS: {
-      // Need to transform from the local view (1-based IDs) to the global view,
-      // which is based off F.SLocEntryBaseID.
-      if (!F.PreloadSLocEntries.empty()) {
-        Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file");
-        return true;
-      }
-      
-      F.PreloadSLocEntries.swap(Record);
-      break;
-    }
-
-    case EXT_VECTOR_DECLS:
-      for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        ExtVectorDecls.push_back(getGlobalDeclID(F, Record[I]));
-      break;
-
-    case VTABLE_USES:
-      if (Record.size() % 3 != 0) {
-        Error("Invalid VTABLE_USES record");
-        return true;
-      }
-        
-      // Later tables overwrite earlier ones.
-      // FIXME: Modules will have some trouble with this. This is clearly not
-      // the right way to do this.
-      VTableUses.clear();
-        
-      for (unsigned Idx = 0, N = Record.size(); Idx != N; /* In loop */) {
-        VTableUses.push_back(getGlobalDeclID(F, Record[Idx++]));
-        VTableUses.push_back(
-          ReadSourceLocation(F, Record, Idx).getRawEncoding());
-        VTableUses.push_back(Record[Idx++]);
-      }
-      break;
-
-    case DYNAMIC_CLASSES:
-      for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        DynamicClasses.push_back(getGlobalDeclID(F, Record[I]));
-      break;
-
-    case PENDING_IMPLICIT_INSTANTIATIONS:
-      if (PendingInstantiations.size() % 2 != 0) {
-        Error("Invalid existing PendingInstantiations");
-        return true;
-      }
-
-      if (Record.size() % 2 != 0) {
-        Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block");
-        return true;
-      }
-
-      for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
-        PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++]));
-        PendingInstantiations.push_back(
-          ReadSourceLocation(F, Record, I).getRawEncoding());
-      }
-      break;
-
-    case SEMA_DECL_REFS:
-      // Later tables overwrite earlier ones.
-      // FIXME: Modules will have some trouble with this.
-      SemaDeclRefs.clear();
-      for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I]));
-      break;
-
-    case PPD_ENTITIES_OFFSETS: {
-      F.PreprocessedEntityOffsets = (const PPEntityOffset *)BlobStart;
-      assert(BlobLen % sizeof(PPEntityOffset) == 0);
-      F.NumPreprocessedEntities = BlobLen / sizeof(PPEntityOffset);
-
-      unsigned LocalBasePreprocessedEntityID = Record[0];
-      
-      unsigned StartingID;
-      if (!PP.getPreprocessingRecord())
-        PP.createPreprocessingRecord();
-      if (!PP.getPreprocessingRecord()->getExternalSource())
-        PP.getPreprocessingRecord()->SetExternalSource(*this);
-      StartingID 
-        = PP.getPreprocessingRecord()
-            ->allocateLoadedEntities(F.NumPreprocessedEntities);
-      F.BasePreprocessedEntityID = StartingID;
-
-      if (F.NumPreprocessedEntities > 0) {
-        // Introduce the global -> local mapping for preprocessed entities in
-        // this module.
-        GlobalPreprocessedEntityMap.insert(std::make_pair(StartingID, &F));
-       
-        // Introduce the local -> global mapping for preprocessed entities in
-        // this module.
-        F.PreprocessedEntityRemap.insertOrReplace(
-          std::make_pair(LocalBasePreprocessedEntityID,
-            F.BasePreprocessedEntityID - LocalBasePreprocessedEntityID));
-      }
-
-      break;
-    }
-        
-    case DECL_UPDATE_OFFSETS: {
-      if (Record.size() % 2 != 0) {
-        Error("invalid DECL_UPDATE_OFFSETS block in AST file");
-        return true;
-      }
-      for (unsigned I = 0, N = Record.size(); I != N; I += 2)
-        DeclUpdateOffsets[getGlobalDeclID(F, Record[I])]
-          .push_back(std::make_pair(&F, Record[I+1]));
-      break;
-    }
-
-    case DECL_REPLACEMENTS: {
-      if (Record.size() % 3 != 0) {
-        Error("invalid DECL_REPLACEMENTS block in AST file");
-        return true;
-      }
-      for (unsigned I = 0, N = Record.size(); I != N; I += 3)
-        ReplacedDecls[getGlobalDeclID(F, Record[I])]
-          = ReplacedDeclInfo(&F, Record[I+1], Record[I+2]);
-      break;
-    }
-
-    case OBJC_CATEGORIES_MAP: {
-      if (F.LocalNumObjCCategoriesInMap != 0) {
-        Error("duplicate OBJC_CATEGORIES_MAP record in AST file");
-        return true;
-      }
-      
-      F.LocalNumObjCCategoriesInMap = Record[0];
-      F.ObjCCategoriesMap = (const ObjCCategoriesInfo *)BlobStart;
-      break;
-    }
-        
-    case OBJC_CATEGORIES:
-      F.ObjCCategories.swap(Record);
-      break;
-        
-    case CXX_BASE_SPECIFIER_OFFSETS: {
-      if (F.LocalNumCXXBaseSpecifiers != 0) {
-        Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file");
-        return true;
-      }
-      
-      F.LocalNumCXXBaseSpecifiers = Record[0];
-      F.CXXBaseSpecifiersOffsets = (const uint32_t *)BlobStart;
-      NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers;
-      break;
-    }
-
-    case DIAG_PRAGMA_MAPPINGS:
-      if (F.PragmaDiagMappings.empty())
-        F.PragmaDiagMappings.swap(Record);
-      else
-        F.PragmaDiagMappings.insert(F.PragmaDiagMappings.end(),
-                                    Record.begin(), Record.end());
-      break;
-        
-    case CUDA_SPECIAL_DECL_REFS:
-      // Later tables overwrite earlier ones.
-      // FIXME: Modules will have trouble with this.
-      CUDASpecialDeclRefs.clear();
-      for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        CUDASpecialDeclRefs.push_back(getGlobalDeclID(F, Record[I]));
-      break;
-
-    case HEADER_SEARCH_TABLE: {
-      F.HeaderFileInfoTableData = BlobStart;
-      F.LocalNumHeaderFileInfos = Record[1];
-      F.HeaderFileFrameworkStrings = BlobStart + Record[2];
-      if (Record[0]) {
-        F.HeaderFileInfoTable
-          = HeaderFileInfoLookupTable::Create(
-                   (const unsigned char *)F.HeaderFileInfoTableData + Record[0],
-                   (const unsigned char *)F.HeaderFileInfoTableData,
-                   HeaderFileInfoTrait(*this, F, 
-                                       &PP.getHeaderSearchInfo(),
-                                       BlobStart + Record[2]));
-        
-        PP.getHeaderSearchInfo().SetExternalSource(this);
-        if (!PP.getHeaderSearchInfo().getExternalLookup())
-          PP.getHeaderSearchInfo().SetExternalLookup(this);
-      }
-      break;
-    }
-        
-    case FP_PRAGMA_OPTIONS:
-      // Later tables overwrite earlier ones.
-      FPPragmaOptions.swap(Record);
-      break;
-
-    case OPENCL_EXTENSIONS:
-      // Later tables overwrite earlier ones.
-      OpenCLExtensions.swap(Record);
-      break;
-
-    case TENTATIVE_DEFINITIONS:
-      for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        TentativeDefinitions.push_back(getGlobalDeclID(F, Record[I]));
-      break;
-        
-    case KNOWN_NAMESPACES:
-      for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        KnownNamespaces.push_back(getGlobalDeclID(F, Record[I]));
-      break;
-        
-    case IMPORTED_MODULES: {
-      if (F.Kind != MK_Module) {
-        // If we aren't loading a module (which has its own exports), make
-        // all of the imported modules visible.
-        // FIXME: Deal with macros-only imports.
-        for (unsigned I = 0, N = Record.size(); I != N; ++I) {
-          if (unsigned GlobalID = getGlobalSubmoduleID(F, Record[I]))
-            ImportedModules.push_back(GlobalID);
-        }
-      }
-      break;
-    }
-
-    case LOCAL_REDECLARATIONS: {
-      F.RedeclarationChains.swap(Record);
-      break;
-    }
-        
-    case LOCAL_REDECLARATIONS_MAP: {
-      if (F.LocalNumRedeclarationsInMap != 0) {
-        Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file");
-        return true;
-      }
-      
-      F.LocalNumRedeclarationsInMap = Record[0];
-      F.RedeclarationsMap = (const LocalRedeclarationsInfo *)BlobStart;
-      break;
-    }
-        
-    case MERGED_DECLARATIONS: {
-      for (unsigned Idx = 0; Idx < Record.size(); /* increment in loop */) {
-        GlobalDeclID CanonID = getGlobalDeclID(F, Record[Idx++]);
-        SmallVectorImpl<GlobalDeclID> &Decls = StoredMergedDecls[CanonID];
-        for (unsigned N = Record[Idx++]; N > 0; --N)
-          Decls.push_back(getGlobalDeclID(F, Record[Idx++]));
-      }
-      break;
-    }
-
-    case MACRO_OFFSET: {
-      if (F.LocalNumMacros != 0) {
-        Error("duplicate MACRO_OFFSET record in AST file");
-        return true;
-      }
-      F.MacroOffsets = (const uint32_t *)BlobStart;
-      F.LocalNumMacros = Record[0];
-      unsigned LocalBaseMacroID = Record[1];
-      F.BaseMacroID = getTotalNumMacros();
-
-      if (F.LocalNumMacros > 0) {
-        // Introduce the global -> local mapping for macros within this module.
-        GlobalMacroMap.insert(std::make_pair(getTotalNumMacros() + 1, &F));
-
-        // Introduce the local -> global mapping for macros within this module.
-        F.MacroRemap.insertOrReplace(
-          std::make_pair(LocalBaseMacroID,
-                         F.BaseMacroID - LocalBaseMacroID));
-
-        MacrosLoaded.resize(MacrosLoaded.size() + F.LocalNumMacros);
-      }
-      break;
-    }
-
-    case MACRO_UPDATES: {
-      for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
-        MacroID ID = getGlobalMacroID(F, Record[I++]);
-        if (I == N)
-          break;
-
-        SourceLocation UndefLoc = ReadSourceLocation(F, Record, I);
-        SubmoduleID SubmoduleID = getGlobalSubmoduleID(F, Record[I++]);;
-        MacroUpdate Update;
-        Update.UndefLoc = UndefLoc;
-        MacroUpdates[ID].push_back(std::make_pair(SubmoduleID, Update));
-      }
-      break;
-    }
-    }
-  }
-  Error("premature end of bitstream in AST file");
-  return true;
-}
-
-void ASTReader::makeNamesVisible(const HiddenNames &Names) {
-  for (unsigned I = 0, N = Names.size(); I != N; ++I) {
-    switch (Names[I].getKind()) {
-    case HiddenName::Declaration:
-      Names[I].getDecl()->Hidden = false;
-      break;
-
-    case HiddenName::MacroVisibility: {
-      std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
-      Macro.second->setHidden(!Macro.second->isPublic());
-      if (Macro.second->isDefined()) {
-        PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
-      }
-      break;
-    }
-
-    case HiddenName::MacroUndef: {
-      std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
-      if (Macro.second->isDefined()) {
-        Macro.second->setUndefLoc(Names[I].getMacroUndefLoc());
-        if (PPMutationListener *Listener = PP.getPPMutationListener())
-          Listener->UndefinedMacro(Macro.second);
-        PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
-      }
-      break;
-    }
-    }
-  }
-}
-
-void ASTReader::makeModuleVisible(Module *Mod, 
-                                  Module::NameVisibilityKind NameVisibility) {
-  llvm::SmallPtrSet<Module *, 4> Visited;
-  llvm::SmallVector<Module *, 4> Stack;
-  Stack.push_back(Mod);  
-  while (!Stack.empty()) {
-    Mod = Stack.back();
-    Stack.pop_back();
-
-    if (NameVisibility <= Mod->NameVisibility) {
-      // This module already has this level of visibility (or greater), so 
-      // there is nothing more to do.
-      continue;
-    }
-    
-    if (!Mod->isAvailable()) {
-      // Modules that aren't available cannot be made visible.
-      continue;
-    }
-
-    // Update the module's name visibility.
-    Mod->NameVisibility = NameVisibility;
-    
-    // If we've already deserialized any names from this module,
-    // mark them as visible.
-    HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod);
-    if (Hidden != HiddenNamesMap.end()) {
-      makeNamesVisible(Hidden->second);
-      HiddenNamesMap.erase(Hidden);
-    }
-    
-    // Push any non-explicit submodules onto the stack to be marked as
-    // visible.
-    for (Module::submodule_iterator Sub = Mod->submodule_begin(),
-                                 SubEnd = Mod->submodule_end();
-         Sub != SubEnd; ++Sub) {
-      if (!(*Sub)->IsExplicit && Visited.insert(*Sub))
-        Stack.push_back(*Sub);
-    }
-    
-    // Push any exported modules onto the stack to be marked as visible.
-    bool AnyWildcard = false;
-    bool UnrestrictedWildcard = false;
-    llvm::SmallVector<Module *, 4> WildcardRestrictions;
-    for (unsigned I = 0, N = Mod->Exports.size(); I != N; ++I) {
-      Module *Exported = Mod->Exports[I].getPointer();
-      if (!Mod->Exports[I].getInt()) {
-        // Export a named module directly; no wildcards involved.
-        if (Visited.insert(Exported))
-          Stack.push_back(Exported);
-        
-        continue;
-      }
-      
-      // Wildcard export: export all of the imported modules that match
-      // the given pattern.
-      AnyWildcard = true;
-      if (UnrestrictedWildcard)
-        continue;
-
-      if (Module *Restriction = Mod->Exports[I].getPointer())
-        WildcardRestrictions.push_back(Restriction);
-      else {
-        WildcardRestrictions.clear();
-        UnrestrictedWildcard = true;
-      }
-    }
-    
-    // If there were any wildcards, push any imported modules that were
-    // re-exported by the wildcard restriction.
-    if (!AnyWildcard)
-      continue;
-    
-    for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) {
-      Module *Imported = Mod->Imports[I];
-      if (!Visited.insert(Imported))
-        continue;
-      
-      bool Acceptable = UnrestrictedWildcard;
-      if (!Acceptable) {
-        // Check whether this module meets one of the restrictions.
-        for (unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) {
-          Module *Restriction = WildcardRestrictions[R];
-          if (Imported == Restriction || Imported->isSubModuleOf(Restriction)) {
-            Acceptable = true;
-            break;
-          }
-        }
-      }
-      
-      if (!Acceptable)
-        continue;
-      
-      Stack.push_back(Imported);
-    }
-  }
-}
-
-ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
-                                            ModuleKind Type,
-                                            SourceLocation ImportLoc,
-                                            unsigned ClientLoadCapabilities) {
-  // Bump the generation number.
-  unsigned PreviousGeneration = CurrentGeneration++;
-
-  unsigned NumModules = ModuleMgr.size();
-  llvm::SmallVector<ImportedModule, 4> Loaded;
-  switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc,
-                                                /*ImportedBy=*/0, Loaded,
-                                                ClientLoadCapabilities)) {
-  case Failure:
-  case OutOfDate:
-  case VersionMismatch:
-  case ConfigurationMismatch:
-  case HadErrors:
-    ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end());
-    return ReadResult;
-
-  case Success:
-    break;
-  }
-
-  // Here comes stuff that we only do once the entire chain is loaded.
-
-  // Load the AST blocks of all of the modules that we loaded.
-  for (llvm::SmallVectorImpl<ImportedModule>::iterator M = Loaded.begin(),
-                                                  MEnd = Loaded.end();
-       M != MEnd; ++M) {
-    ModuleFile &F = *M->Mod;
-
-    // Read the AST block.
-    if (ReadASTBlock(F))
-      return Failure;
-
-    // Once read, set the ModuleFile bit base offset and update the size in 
-    // bits of all files we've seen.
-    F.GlobalBitOffset = TotalModulesSizeInBits;
-    TotalModulesSizeInBits += F.SizeInBits;
-    GlobalBitOffsetsMap.insert(std::make_pair(F.GlobalBitOffset, &F));
-    
-    // Preload SLocEntries.
-    for (unsigned I = 0, N = F.PreloadSLocEntries.size(); I != N; ++I) {
-      int Index = int(F.PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID;
-      // Load it through the SourceManager and don't call ReadSLocEntry()
-      // directly because the entry may have already been loaded in which case
-      // calling ReadSLocEntry() directly would trigger an assertion in
-      // SourceManager.
-      SourceMgr.getLoadedSLocEntryByID(Index);
-    }
-  }
-
-  // Setup the import locations.
-  for (llvm::SmallVectorImpl<ImportedModule>::iterator M = Loaded.begin(),
-                                                    MEnd = Loaded.end();
-       M != MEnd; ++M) {
-    ModuleFile &F = *M->Mod;
-    if (!M->ImportedBy)
-      F.ImportLoc = M->ImportLoc;
-    else
-      F.ImportLoc = ReadSourceLocation(*M->ImportedBy,
-                                       M->ImportLoc.getRawEncoding());
-  }
-
-  // Mark all of the identifiers in the identifier table as being out of date,
-  // so that various accessors know to check the loaded modules when the
-  // identifier is used.
-  for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
-                              IdEnd = PP.getIdentifierTable().end();
-       Id != IdEnd; ++Id)
-    Id->second->setOutOfDate(true);
-  
-  // Resolve any unresolved module exports.
-  for (unsigned I = 0, N = UnresolvedModuleImportExports.size(); I != N; ++I) {
-    UnresolvedModuleImportExport &Unresolved = UnresolvedModuleImportExports[I];
-    SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,Unresolved.ID);
-    Module *ResolvedMod = getSubmodule(GlobalID);
-    
-    if (Unresolved.IsImport) {
-      if (ResolvedMod)
-        Unresolved.Mod->Imports.push_back(ResolvedMod);
-      continue;
-    }
-
-    if (ResolvedMod || Unresolved.IsWildcard)
-      Unresolved.Mod->Exports.push_back(
-        Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard));
-  }
-  UnresolvedModuleImportExports.clear();
-  
-  InitializeContext();
-
-  if (DeserializationListener)
-    DeserializationListener->ReaderInitialized(this);
-
-  ModuleFile &PrimaryModule = ModuleMgr.getPrimaryModule();
-  if (!PrimaryModule.OriginalSourceFileID.isInvalid()) {
-    PrimaryModule.OriginalSourceFileID 
-      = FileID::get(PrimaryModule.SLocEntryBaseID
-                    + PrimaryModule.OriginalSourceFileID.getOpaqueValue() - 1);
-
-    // If this AST file is a precompiled preamble, then set the
-    // preamble file ID of the source manager to the file source file
-    // from which the preamble was built.
-    if (Type == MK_Preamble) {
-      SourceMgr.setPreambleFileID(PrimaryModule.OriginalSourceFileID);
-    } else if (Type == MK_MainFile) {
-      SourceMgr.setMainFileID(PrimaryModule.OriginalSourceFileID);
-    }
-  }
-  
-  // For any Objective-C class definitions we have already loaded, make sure
-  // that we load any additional categories.
-  for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) {
-    loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(), 
-                       ObjCClassesLoaded[I],
-                       PreviousGeneration);
-  }
-  
-  return Success;
-}
-
-ASTReader::ASTReadResult
-ASTReader::ReadASTCore(StringRef FileName,
-                       ModuleKind Type,
-                       SourceLocation ImportLoc,
-                       ModuleFile *ImportedBy,
-                       llvm::SmallVectorImpl<ImportedModule> &Loaded,
-                       unsigned ClientLoadCapabilities) {
-  ModuleFile *M;
-  bool NewModule;
-  std::string ErrorStr;
-  llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportLoc,
-                                                ImportedBy, CurrentGeneration,
-                                                ErrorStr);
-
-  if (!M) {
-    // We couldn't load the module.
-    std::string Msg = "Unable to load module \"" + FileName.str() + "\": "
-      + ErrorStr;
-    Error(Msg);
-    return Failure;
-  }
-
-  if (!NewModule) {
-    // We've already loaded this module.
-    return Success;
-  }
-
-  // FIXME: This seems rather a hack. Should CurrentDir be part of the
-  // module?
-  if (FileName != "-") {
-    CurrentDir = llvm::sys::path::parent_path(FileName);
-    if (CurrentDir.empty()) CurrentDir = ".";
-  }
-
-  ModuleFile &F = *M;
-  llvm::BitstreamCursor &Stream = F.Stream;
-  Stream.init(F.StreamFile);
-  F.SizeInBits = F.Buffer->getBufferSize() * 8;
-  
-  // Sniff for the signature.
-  if (Stream.Read(8) != 'C' ||
-      Stream.Read(8) != 'P' ||
-      Stream.Read(8) != 'C' ||
-      Stream.Read(8) != 'H') {
-    Diag(diag::err_not_a_pch_file) << FileName;
-    return Failure;
-  }
-
-  // This is used for compatibility with older PCH formats.
-  bool HaveReadControlBlock = false;
-
-  while (!Stream.AtEndOfStream()) {
-    unsigned Code = Stream.ReadCode();
-
-    if (Code != llvm::bitc::ENTER_SUBBLOCK) {
-      Error("invalid record at top-level of AST file");
-      return Failure;
-    }
-
-    unsigned BlockID = Stream.ReadSubBlockID();
-
-    // We only know the control subblock ID.
-    switch (BlockID) {
-    case llvm::bitc::BLOCKINFO_BLOCK_ID:
-      if (Stream.ReadBlockInfoBlock()) {
-        Error("malformed BlockInfoBlock in AST file");
-        return Failure;
-      }
-      break;
-    case CONTROL_BLOCK_ID:
-      HaveReadControlBlock = true;
-      switch (ReadControlBlock(F, Loaded, ClientLoadCapabilities)) {
-      case Success:
-        break;
-
-      case Failure: return Failure;
-      case OutOfDate: return OutOfDate;
-      case VersionMismatch: return VersionMismatch;
-      case ConfigurationMismatch: return ConfigurationMismatch;
-      case HadErrors: return HadErrors;
-      }
-      break;
-    case AST_BLOCK_ID:
-      if (!HaveReadControlBlock) {
-        if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
-          Diag(diag::warn_pch_version_too_old);
-        return VersionMismatch;
-      }
-
-      // Record that we've loaded this module.
-      Loaded.push_back(ImportedModule(M, ImportedBy, ImportLoc));
-      return Success;
-
-    default:
-      if (Stream.SkipBlock()) {
-        Error("malformed block record in AST file");
-        return Failure;
-      }
-      break;
-    }
-  }
-  
-  return Success;
-}
-
-void ASTReader::InitializeContext() {  
-  // If there's a listener, notify them that we "read" the translation unit.
-  if (DeserializationListener)
-    DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID, 
-                                      Context.getTranslationUnitDecl());
-
-  // Make sure we load the declaration update records for the translation unit,
-  // if there are any.
-  loadDeclUpdateRecords(PREDEF_DECL_TRANSLATION_UNIT_ID, 
-                        Context.getTranslationUnitDecl());
-  
-  // FIXME: Find a better way to deal with collisions between these
-  // built-in types. Right now, we just ignore the problem.
-  
-  // Load the special types.
-  if (SpecialTypes.size() >= NumSpecialTypeIDs) {
-    if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING]) {
-      if (!Context.CFConstantStringTypeDecl)
-        Context.setCFConstantStringType(GetType(String));
-    }
-    
-    if (unsigned File = SpecialTypes[SPECIAL_TYPE_FILE]) {
-      QualType FileType = GetType(File);
-      if (FileType.isNull()) {
-        Error("FILE type is NULL");
-        return;
-      }
-      
-      if (!Context.FILEDecl) {
-        if (const TypedefType *Typedef = FileType->getAs<TypedefType>())
-          Context.setFILEDecl(Typedef->getDecl());
-        else {
-          const TagType *Tag = FileType->getAs<TagType>();
-          if (!Tag) {
-            Error("Invalid FILE type in AST file");
-            return;
-          }
-          Context.setFILEDecl(Tag->getDecl());
-        }
-      }
-    }
-    
-    if (unsigned Jmp_buf = SpecialTypes[SPECIAL_TYPE_JMP_BUF]) {
-      QualType Jmp_bufType = GetType(Jmp_buf);
-      if (Jmp_bufType.isNull()) {
-        Error("jmp_buf type is NULL");
-        return;
-      }
-      
-      if (!Context.jmp_bufDecl) {
-        if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>())
-          Context.setjmp_bufDecl(Typedef->getDecl());
-        else {
-          const TagType *Tag = Jmp_bufType->getAs<TagType>();
-          if (!Tag) {
-            Error("Invalid jmp_buf type in AST file");
-            return;
-          }
-          Context.setjmp_bufDecl(Tag->getDecl());
-        }
-      }
-    }
-    
-    if (unsigned Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_SIGJMP_BUF]) {
-      QualType Sigjmp_bufType = GetType(Sigjmp_buf);
-      if (Sigjmp_bufType.isNull()) {
-        Error("sigjmp_buf type is NULL");
-        return;
-      }
-      
-      if (!Context.sigjmp_bufDecl) {
-        if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>())
-          Context.setsigjmp_bufDecl(Typedef->getDecl());
-        else {
-          const TagType *Tag = Sigjmp_bufType->getAs<TagType>();
-          assert(Tag && "Invalid sigjmp_buf type in AST file");
-          Context.setsigjmp_bufDecl(Tag->getDecl());
-        }
-      }
-    }
-
-    if (unsigned ObjCIdRedef
-          = SpecialTypes[SPECIAL_TYPE_OBJC_ID_REDEFINITION]) {
-      if (Context.ObjCIdRedefinitionType.isNull())
-        Context.ObjCIdRedefinitionType = GetType(ObjCIdRedef);
-    }
-
-    if (unsigned ObjCClassRedef
-          = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) {
-      if (Context.ObjCClassRedefinitionType.isNull())
-        Context.ObjCClassRedefinitionType = GetType(ObjCClassRedef);
-    }
-
-    if (unsigned ObjCSelRedef
-          = SpecialTypes[SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) {
-      if (Context.ObjCSelRedefinitionType.isNull())
-        Context.ObjCSelRedefinitionType = GetType(ObjCSelRedef);
-    }
-
-    if (unsigned Ucontext_t = SpecialTypes[SPECIAL_TYPE_UCONTEXT_T]) {
-      QualType Ucontext_tType = GetType(Ucontext_t);
-      if (Ucontext_tType.isNull()) {
-        Error("ucontext_t type is NULL");
-        return;
-      }
-
-      if (!Context.ucontext_tDecl) {
-        if (const TypedefType *Typedef = Ucontext_tType->getAs<TypedefType>())
-          Context.setucontext_tDecl(Typedef->getDecl());
-        else {
-          const TagType *Tag = Ucontext_tType->getAs<TagType>();
-          assert(Tag && "Invalid ucontext_t type in AST file");
-          Context.setucontext_tDecl(Tag->getDecl());
-        }
-      }
-    }
-  }
-  
-  ReadPragmaDiagnosticMappings(Context.getDiagnostics());
-
-  // If there were any CUDA special declarations, deserialize them.
-  if (!CUDASpecialDeclRefs.empty()) {
-    assert(CUDASpecialDeclRefs.size() == 1 && "More decl refs than expected!");
-    Context.setcudaConfigureCallDecl(
-                           cast<FunctionDecl>(GetDecl(CUDASpecialDeclRefs[0])));
-  }
-  
-  // Re-export any modules that were imported by a non-module AST file.
-  for (unsigned I = 0, N = ImportedModules.size(); I != N; ++I) {
-    if (Module *Imported = getSubmodule(ImportedModules[I]))
-      makeModuleVisible(Imported, Module::AllVisible);
-  }
-  ImportedModules.clear();
-}
-
-void ASTReader::finalizeForWriting() {
-  for (HiddenNamesMapType::iterator Hidden = HiddenNamesMap.begin(),
-                                 HiddenEnd = HiddenNamesMap.end();
-       Hidden != HiddenEnd; ++Hidden) {
-    makeNamesVisible(Hidden->second);
-  }
-  HiddenNamesMap.clear();
-}
-
-/// \brief Retrieve the name of the original source file name
-/// directly from the AST file, without actually loading the AST
-/// file.
-std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
-                                             FileManager &FileMgr,
-                                             DiagnosticsEngine &Diags) {
-  // Open the AST file.
-  std::string ErrStr;
-  OwningPtr<llvm::MemoryBuffer> Buffer;
-  Buffer.reset(FileMgr.getBufferForFile(ASTFileName, &ErrStr));
-  if (!Buffer) {
-    Diags.Report(diag::err_fe_unable_to_read_pch_file) << ASTFileName << ErrStr;
-    return std::string();
-  }
-
-  // Initialize the stream
-  llvm::BitstreamReader StreamFile;
-  llvm::BitstreamCursor Stream;
-  StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
-                  (const unsigned char *)Buffer->getBufferEnd());
-  Stream.init(StreamFile);
-
-  // Sniff for the signature.
-  if (Stream.Read(8) != 'C' ||
-      Stream.Read(8) != 'P' ||
-      Stream.Read(8) != 'C' ||
-      Stream.Read(8) != 'H') {
-    Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName;
-    return std::string();
-  }
-
-  RecordData Record;
-  while (!Stream.AtEndOfStream()) {
-    unsigned Code = Stream.ReadCode();
-
-    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-      unsigned BlockID = Stream.ReadSubBlockID();
-
-      // We only know the AST subblock ID.
-      switch (BlockID) {
-      case CONTROL_BLOCK_ID:
-        if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
-          Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
-          return std::string();
-        }
-        break;
-
-      default:
-        if (Stream.SkipBlock()) {
-          Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
-          return std::string();
-        }
-        break;
-      }
-      continue;
-    }
-
-    if (Code == llvm::bitc::END_BLOCK) {
-      if (Stream.ReadBlockEnd()) {
-        Diags.Report(diag::err_fe_pch_error_at_end_block) << ASTFileName;
-        return std::string();
-      }
-      continue;
-    }
-
-    if (Code == llvm::bitc::DEFINE_ABBREV) {
-      Stream.ReadAbbrevRecord();
-      continue;
-    }
-
-    Record.clear();
-    const char *BlobStart = 0;
-    unsigned BlobLen = 0;
-    if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen) == ORIGINAL_FILE)
-      return std::string(BlobStart, BlobLen);
-  }
-
-  return std::string();
-}
-
-namespace {
-  class SimplePCHValidator : public ASTReaderListener {
-    const LangOptions &ExistingLangOpts;
-    const TargetOptions &ExistingTargetOpts;
-    const PreprocessorOptions &ExistingPPOpts;
-    FileManager &FileMgr;
-    
-  public:
-    SimplePCHValidator(const LangOptions &ExistingLangOpts,
-                       const TargetOptions &ExistingTargetOpts,
-                       const PreprocessorOptions &ExistingPPOpts,
-                       FileManager &FileMgr)
-      : ExistingLangOpts(ExistingLangOpts),
-        ExistingTargetOpts(ExistingTargetOpts),
-        ExistingPPOpts(ExistingPPOpts),
-        FileMgr(FileMgr)
-    {
-    }
-
-    virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
-                                     bool Complain) {
-      return checkLanguageOptions(ExistingLangOpts, LangOpts, 0);
-    }
-    virtual bool ReadTargetOptions(const TargetOptions &TargetOpts,
-                                   bool Complain) {
-      return checkTargetOptions(ExistingTargetOpts, TargetOpts, 0);
-    }
-    virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
-                                         bool Complain,
-                                         std::string &SuggestedPredefines) {
-      return checkPreprocessorOptions(ExistingPPOpts, PPOpts, 0, FileMgr,
-                                      SuggestedPredefines);
-    }
-  };
-}
-
-bool ASTReader::readASTFileControlBlock(StringRef Filename,
-                                        FileManager &FileMgr,
-                                        ASTReaderListener &Listener) {
-  // Open the AST file.
-  std::string ErrStr;
-  OwningPtr<llvm::MemoryBuffer> Buffer;
-  Buffer.reset(FileMgr.getBufferForFile(Filename, &ErrStr));
-  if (!Buffer) {
-    return true;
-  }
-
-  // Initialize the stream
-  llvm::BitstreamReader StreamFile;
-  llvm::BitstreamCursor Stream;
-  StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
-                  (const unsigned char *)Buffer->getBufferEnd());
-  Stream.init(StreamFile);
-
-  // Sniff for the signature.
-  if (Stream.Read(8) != 'C' ||
-      Stream.Read(8) != 'P' ||
-      Stream.Read(8) != 'C' ||
-      Stream.Read(8) != 'H') {
-    return true;
-  }
-
-  RecordData Record;
-  bool InControlBlock = false;
-  while (!Stream.AtEndOfStream()) {
-    unsigned Code = Stream.ReadCode();
-
-    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-      unsigned BlockID = Stream.ReadSubBlockID();
-
-      // We only know the control subblock ID.
-      switch (BlockID) {
-      case CONTROL_BLOCK_ID:
-        if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
-          return true;
-        } else {
-          InControlBlock = true;
-        }
-        break;
-
-      default:
-        if (Stream.SkipBlock())
-          return true;
-        break;
-      }
-      continue;
-    }
-
-    if (Code == llvm::bitc::END_BLOCK) {
-      if (Stream.ReadBlockEnd()) {
-        return true;
-      }
-
-      InControlBlock = false;
-      continue;
-    }
-
-    if (Code == llvm::bitc::DEFINE_ABBREV) {
-      Stream.ReadAbbrevRecord();
-      continue;
-    }
-
-    Record.clear();
-    const char *BlobStart = 0;
-    unsigned BlobLen = 0;
-    unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);
-    if (InControlBlock) {
-      switch ((ControlRecordTypes)RecCode) {
-      case METADATA: {
-        if (Record[0] != VERSION_MAJOR) {
-          return true;
-        }
-
-        const std::string &CurBranch = getClangFullRepositoryVersion();
-        StringRef ASTBranch(BlobStart, BlobLen);
-        if (StringRef(CurBranch) != ASTBranch)
-          return true;
-
-        break;
-      }
-      case LANGUAGE_OPTIONS:
-        if (ParseLanguageOptions(Record, false, Listener))
-          return true;
-        break;
-
-      case TARGET_OPTIONS:
-        if (ParseTargetOptions(Record, false, Listener))
-          return true;
-        break;
-
-      case DIAGNOSTIC_OPTIONS:
-        if (ParseDiagnosticOptions(Record, false, Listener))
-          return true;
-        break;
-
-      case FILE_SYSTEM_OPTIONS:
-        if (ParseFileSystemOptions(Record, false, Listener))
-          return true;
-        break;
-
-      case HEADER_SEARCH_OPTIONS:
-        if (ParseHeaderSearchOptions(Record, false, Listener))
-          return true;
-        break;
-
-      case PREPROCESSOR_OPTIONS: {
-        std::string IgnoredSuggestedPredefines;
-        if (ParsePreprocessorOptions(Record, false, Listener,
-                                     IgnoredSuggestedPredefines))
-          return true;
-        break;
-      }
-
-      default:
-        // No other validation to perform.
-        break;
-      }
-    }
-  }
-  
-  return false;
-}
-
-
-bool ASTReader::isAcceptableASTFile(StringRef Filename,
-                                    FileManager &FileMgr,
-                                    const LangOptions &LangOpts,
-                                    const TargetOptions &TargetOpts,
-                                    const PreprocessorOptions &PPOpts) {
-  SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, FileMgr);
-  return !readASTFileControlBlock(Filename, FileMgr, validator);
-}
-
-bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
-  // Enter the submodule block.
-  if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) {
-    Error("malformed submodule block record in AST file");
-    return true;
-  }
-
-  ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
-  bool First = true;
-  Module *CurrentModule = 0;
-  RecordData Record;
-  while (true) {
-    unsigned Code = F.Stream.ReadCode();
-    if (Code == llvm::bitc::END_BLOCK) {
-      if (F.Stream.ReadBlockEnd()) {
-        Error("error at end of submodule block in AST file");
-        return true;
-      }
-      return false;
-    }
-    
-    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-      // No known subblocks, always skip them.
-      F.Stream.ReadSubBlockID();
-      if (F.Stream.SkipBlock()) {
-        Error("malformed block record in AST file");
-        return true;
-      }
-      continue;
-    }
-    
-    if (Code == llvm::bitc::DEFINE_ABBREV) {
-      F.Stream.ReadAbbrevRecord();
-      continue;
-    }
-    
-    // Read a record.
-    const char *BlobStart;
-    unsigned BlobLen;
-    Record.clear();
-    switch (F.Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
-    default:  // Default behavior: ignore.
-      break;
-      
-    case SUBMODULE_DEFINITION: {
-      if (First) {
-        Error("missing submodule metadata record at beginning of block");
-        return true;
-      }
-
-      if (Record.size() < 7) {
-        Error("malformed module definition");
-        return true;
-      }
-      
-      StringRef Name(BlobStart, BlobLen);
-      SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[0]);
-      SubmoduleID Parent = getGlobalSubmoduleID(F, Record[1]);
-      bool IsFramework = Record[2];
-      bool IsExplicit = Record[3];
-      bool IsSystem = Record[4];
-      bool InferSubmodules = Record[5];
-      bool InferExplicitSubmodules = Record[6];
-      bool InferExportWildcard = Record[7];
-      
-      Module *ParentModule = 0;
-      if (Parent)
-        ParentModule = getSubmodule(Parent);
-      
-      // Retrieve this (sub)module from the module map, creating it if
-      // necessary.
-      CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, 
-                                                IsFramework, 
-                                                IsExplicit).first;
-      SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS;
-      if (GlobalIndex >= SubmodulesLoaded.size() ||
-          SubmodulesLoaded[GlobalIndex]) {
-        Error("too many submodules");
-        return true;
-      }
-      
-      CurrentModule->setASTFile(F.File);
-      CurrentModule->IsFromModuleFile = true;
-      CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
-      CurrentModule->InferSubmodules = InferSubmodules;
-      CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
-      CurrentModule->InferExportWildcard = InferExportWildcard;
-      if (DeserializationListener)
-        DeserializationListener->ModuleRead(GlobalID, CurrentModule);
-      
-      SubmodulesLoaded[GlobalIndex] = CurrentModule;
-      break;
-    }
-        
-    case SUBMODULE_UMBRELLA_HEADER: {
-      if (First) {
-        Error("missing submodule metadata record at beginning of block");
-        return true;
-      }
-
-      if (!CurrentModule)
-        break;
-      
-      StringRef FileName(BlobStart, BlobLen);
-      if (const FileEntry *Umbrella = PP.getFileManager().getFile(FileName)) {
-        if (!CurrentModule->getUmbrellaHeader())
-          ModMap.setUmbrellaHeader(CurrentModule, Umbrella);
-        else if (CurrentModule->getUmbrellaHeader() != Umbrella) {
-          Error("mismatched umbrella headers in submodule");
-          return true;
-        }
-      }
-      break;
-    }
-        
-    case SUBMODULE_HEADER: {
-      if (First) {
-        Error("missing submodule metadata record at beginning of block");
-        return true;
-      }
-
-      if (!CurrentModule)
-        break;
-      
-      // FIXME: Be more lazy about this!
-      StringRef FileName(BlobStart, BlobLen);
-      if (const FileEntry *File = PP.getFileManager().getFile(FileName)) {
-        if (std::find(CurrentModule->Headers.begin(), 
-                      CurrentModule->Headers.end(), 
-                      File) == CurrentModule->Headers.end())
-          ModMap.addHeader(CurrentModule, File, false);
-      }
-      break;      
-    }
-
-    case SUBMODULE_EXCLUDED_HEADER: {
-      if (First) {
-        Error("missing submodule metadata record at beginning of block");
-        return true;
-      }
-
-      if (!CurrentModule)
-        break;
-      
-      // FIXME: Be more lazy about this!
-      StringRef FileName(BlobStart, BlobLen);
-      if (const FileEntry *File = PP.getFileManager().getFile(FileName)) {
-        if (std::find(CurrentModule->Headers.begin(), 
-                      CurrentModule->Headers.end(), 
-                      File) == CurrentModule->Headers.end())
-          ModMap.addHeader(CurrentModule, File, true);
-      }
-      break;      
-    }
-
-    case SUBMODULE_TOPHEADER: {
-      if (First) {
-        Error("missing submodule metadata record at beginning of block");
-        return true;
-      }
-
-      if (!CurrentModule)
-        break;
-
-      // FIXME: Be more lazy about this!
-      StringRef FileName(BlobStart, BlobLen);
-      if (const FileEntry *File = PP.getFileManager().getFile(FileName))
-        CurrentModule->TopHeaders.insert(File);
-      break;
-    }
-
-    case SUBMODULE_UMBRELLA_DIR: {
-      if (First) {
-        Error("missing submodule metadata record at beginning of block");
-        return true;
-      }
-      
-      if (!CurrentModule)
-        break;
-      
-      StringRef DirName(BlobStart, BlobLen);
-      if (const DirectoryEntry *Umbrella
-                                  = PP.getFileManager().getDirectory(DirName)) {
-        if (!CurrentModule->getUmbrellaDir())
-          ModMap.setUmbrellaDir(CurrentModule, Umbrella);
-        else if (CurrentModule->getUmbrellaDir() != Umbrella) {
-          Error("mismatched umbrella directories in submodule");
-          return true;
-        }
-      }
-      break;
-    }
-        
-    case SUBMODULE_METADATA: {
-      if (!First) {
-        Error("submodule metadata record not at beginning of block");
-        return true;
-      }
-      First = false;
-      
-      F.BaseSubmoduleID = getTotalNumSubmodules();
-      F.LocalNumSubmodules = Record[0];
-      unsigned LocalBaseSubmoduleID = Record[1];
-      if (F.LocalNumSubmodules > 0) {
-        // Introduce the global -> local mapping for submodules within this 
-        // module.
-        GlobalSubmoduleMap.insert(std::make_pair(getTotalNumSubmodules()+1,&F));
-        
-        // Introduce the local -> global mapping for submodules within this 
-        // module.
-        F.SubmoduleRemap.insertOrReplace(
-          std::make_pair(LocalBaseSubmoduleID,
-                         F.BaseSubmoduleID - LocalBaseSubmoduleID));
-        
-        SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules);
-      }      
-      break;
-    }
-        
-    case SUBMODULE_IMPORTS: {
-      if (First) {
-        Error("missing submodule metadata record at beginning of block");
-        return true;
-      }
-      
-      if (!CurrentModule)
-        break;
-      
-      for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {
-        UnresolvedModuleImportExport Unresolved;
-        Unresolved.File = &F;
-        Unresolved.Mod = CurrentModule;
-        Unresolved.ID = Record[Idx];
-        Unresolved.IsImport = true;
-        Unresolved.IsWildcard = false;
-        UnresolvedModuleImportExports.push_back(Unresolved);
-      }
-      break;
-    }
-
-    case SUBMODULE_EXPORTS: {
-      if (First) {
-        Error("missing submodule metadata record at beginning of block");
-        return true;
-      }
-      
-      if (!CurrentModule)
-        break;
-      
-      for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {
-        UnresolvedModuleImportExport Unresolved;
-        Unresolved.File = &F;
-        Unresolved.Mod = CurrentModule;
-        Unresolved.ID = Record[Idx];
-        Unresolved.IsImport = false;
-        Unresolved.IsWildcard = Record[Idx + 1];
-        UnresolvedModuleImportExports.push_back(Unresolved);
-      }
-      
-      // Once we've loaded the set of exports, there's no reason to keep 
-      // the parsed, unresolved exports around.
-      CurrentModule->UnresolvedExports.clear();
-      break;
-    }
-    case SUBMODULE_REQUIRES: {
-      if (First) {
-        Error("missing submodule metadata record at beginning of block");
-        return true;
-      }
-
-      if (!CurrentModule)
-        break;
-
-      CurrentModule->addRequirement(StringRef(BlobStart, BlobLen), 
-                                    Context.getLangOpts(),
-                                    Context.getTargetInfo());
-      break;
-    }
-    }
-  }
-}
-
-/// \brief Parse the record that corresponds to a LangOptions data
-/// structure.
-///
-/// This routine parses the language options from the AST file and then gives
-/// them to the AST listener if one is set.
-///
-/// \returns true if the listener deems the file unacceptable, false otherwise.
-bool ASTReader::ParseLanguageOptions(const RecordData &Record,
-                                     bool Complain,
-                                     ASTReaderListener &Listener) {
-  LangOptions LangOpts;
-  unsigned Idx = 0;
-#define LANGOPT(Name, Bits, Default, Description) \
-  LangOpts.Name = Record[Idx++];
-#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
-  LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++]));
-#include "clang/Basic/LangOptions.def"
-
-  ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++];
-  VersionTuple runtimeVersion = ReadVersionTuple(Record, Idx);
-  LangOpts.ObjCRuntime = ObjCRuntime(runtimeKind, runtimeVersion);
-  
-  unsigned Length = Record[Idx++];
-  LangOpts.CurrentModule.assign(Record.begin() + Idx, 
-                                Record.begin() + Idx + Length);
-  return Listener.ReadLanguageOptions(LangOpts, Complain);
-}
-
-bool ASTReader::ParseTargetOptions(const RecordData &Record,
-                                   bool Complain,
-                                   ASTReaderListener &Listener) {
-  unsigned Idx = 0;
-  TargetOptions TargetOpts;
-  TargetOpts.Triple = ReadString(Record, Idx);
-  TargetOpts.CPU = ReadString(Record, Idx);
-  TargetOpts.ABI = ReadString(Record, Idx);
-  TargetOpts.CXXABI = ReadString(Record, Idx);
-  TargetOpts.LinkerVersion = ReadString(Record, Idx);
-  for (unsigned N = Record[Idx++]; N; --N) {
-    TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx));
-  }
-  for (unsigned N = Record[Idx++]; N; --N) {
-    TargetOpts.Features.push_back(ReadString(Record, Idx));
-  }
-
-  return Listener.ReadTargetOptions(TargetOpts, Complain);
-}
-
-bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain,
-                                       ASTReaderListener &Listener) {
-  DiagnosticOptions DiagOpts;
-  unsigned Idx = 0;
-#define DIAGOPT(Name, Bits, Default) DiagOpts.Name = Record[Idx++];
-#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
-  DiagOpts.set##Name(static_cast<Type>(Record[Idx++]));
-#include "clang/Basic/DiagnosticOptions.def"
-
-  for (unsigned N = Record[Idx++]; N; --N) {
-    DiagOpts.Warnings.push_back(ReadString(Record, Idx));
-  }
-
-  return Listener.ReadDiagnosticOptions(DiagOpts, Complain);
-}
-
-bool ASTReader::ParseFileSystemOptions(const RecordData &Record, bool Complain,
-                                       ASTReaderListener &Listener) {
-  FileSystemOptions FSOpts;
-  unsigned Idx = 0;
-  FSOpts.WorkingDir = ReadString(Record, Idx);
-  return Listener.ReadFileSystemOptions(FSOpts, Complain);
-}
-
-bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
-                                         bool Complain,
-                                         ASTReaderListener &Listener) {
-  HeaderSearchOptions HSOpts;
-  unsigned Idx = 0;
-  HSOpts.Sysroot = ReadString(Record, Idx);
-
-  // Include entries.
-  for (unsigned N = Record[Idx++]; N; --N) {
-    std::string Path = ReadString(Record, Idx);
-    frontend::IncludeDirGroup Group
-      = static_cast<frontend::IncludeDirGroup>(Record[Idx++]);
-    bool IsUserSupplied = Record[Idx++];
-    bool IsFramework = Record[Idx++];
-    bool IgnoreSysRoot = Record[Idx++];
-    bool IsInternal = Record[Idx++];
-    bool ImplicitExternC = Record[Idx++];
-    HSOpts.UserEntries.push_back(
-      HeaderSearchOptions::Entry(Path, Group, IsUserSupplied, IsFramework,
-                                 IgnoreSysRoot, IsInternal, ImplicitExternC));
-  }
-
-  // System header prefixes.
-  for (unsigned N = Record[Idx++]; N; --N) {
-    std::string Prefix = ReadString(Record, Idx);
-    bool IsSystemHeader = Record[Idx++];
-    HSOpts.SystemHeaderPrefixes.push_back(
-      HeaderSearchOptions::SystemHeaderPrefix(Prefix, IsSystemHeader));
-  }
-
-  HSOpts.ResourceDir = ReadString(Record, Idx);
-  HSOpts.ModuleCachePath = ReadString(Record, Idx);
-  HSOpts.DisableModuleHash = Record[Idx++];
-  HSOpts.UseBuiltinIncludes = Record[Idx++];
-  HSOpts.UseStandardSystemIncludes = Record[Idx++];
-  HSOpts.UseStandardCXXIncludes = Record[Idx++];
-  HSOpts.UseLibcxx = Record[Idx++];
-
-  return Listener.ReadHeaderSearchOptions(HSOpts, Complain);
-}
-
-bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
-                                         bool Complain,
-                                         ASTReaderListener &Listener,
-                                         std::string &SuggestedPredefines) {
-  PreprocessorOptions PPOpts;
-  unsigned Idx = 0;
-
-  // Macro definitions/undefs
-  for (unsigned N = Record[Idx++]; N; --N) {
-    std::string Macro = ReadString(Record, Idx);
-    bool IsUndef = Record[Idx++];
-    PPOpts.Macros.push_back(std::make_pair(Macro, IsUndef));
-  }
-
-  // Includes
-  for (unsigned N = Record[Idx++]; N; --N) {
-    PPOpts.Includes.push_back(ReadString(Record, Idx));
-  }
-
-  // Macro Includes
-  for (unsigned N = Record[Idx++]; N; --N) {
-    PPOpts.MacroIncludes.push_back(ReadString(Record, Idx));
-  }
-
-  PPOpts.UsePredefines = Record[Idx++];
-  PPOpts.ImplicitPCHInclude = ReadString(Record, Idx);
-  PPOpts.ImplicitPTHInclude = ReadString(Record, Idx);
-  PPOpts.ObjCXXARCStandardLibrary =
-    static_cast<ObjCXXARCStandardLibraryKind>(Record[Idx++]);
-  SuggestedPredefines.clear();
-  return Listener.ReadPreprocessorOptions(PPOpts, Complain,
-                                          SuggestedPredefines);
-}
-
-std::pair<ModuleFile *, unsigned>
-ASTReader::getModulePreprocessedEntity(unsigned GlobalIndex) {
-  GlobalPreprocessedEntityMapType::iterator
-  I = GlobalPreprocessedEntityMap.find(GlobalIndex);
-  assert(I != GlobalPreprocessedEntityMap.end() && 
-         "Corrupted global preprocessed entity map");
-  ModuleFile *M = I->second;
-  unsigned LocalIndex = GlobalIndex - M->BasePreprocessedEntityID;
-  return std::make_pair(M, LocalIndex);
-}
-
-std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
-ASTReader::getModulePreprocessedEntities(ModuleFile &Mod) const {
-  if (PreprocessingRecord *PPRec = PP.getPreprocessingRecord())
-    return PPRec->getIteratorsForLoadedRange(Mod.BasePreprocessedEntityID,
-                                             Mod.NumPreprocessedEntities);
-
-  return std::make_pair(PreprocessingRecord::iterator(),
-                        PreprocessingRecord::iterator());
-}
-
-std::pair<ASTReader::ModuleDeclIterator, ASTReader::ModuleDeclIterator>
-ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) {
-  return std::make_pair(ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls),
-                        ModuleDeclIterator(this, &Mod,
-                                 Mod.FileSortedDecls + Mod.NumFileSortedDecls));
-}
-
-PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
-  PreprocessedEntityID PPID = Index+1;
-  std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index);
-  ModuleFile &M = *PPInfo.first;
-  unsigned LocalIndex = PPInfo.second;
-  const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex];
-
-  SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor);  
-  M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset);
-
-  unsigned Code = M.PreprocessorDetailCursor.ReadCode();
-  switch (Code) {
-  case llvm::bitc::END_BLOCK:
-    return 0;
-    
-  case llvm::bitc::ENTER_SUBBLOCK:
-    Error("unexpected subblock record in preprocessor detail block");
-    return 0;
-      
-  case llvm::bitc::DEFINE_ABBREV:
-    Error("unexpected abbrevation record in preprocessor detail block");
-    return 0;
-      
-  default:
-    break;
-  }
-
-  if (!PP.getPreprocessingRecord()) {
-    Error("no preprocessing record");
-    return 0;
-  }
-  
-  // Read the record.
-  SourceRange Range(ReadSourceLocation(M, PPOffs.Begin),
-                    ReadSourceLocation(M, PPOffs.End));
-  PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
-  const char *BlobStart = 0;
-  unsigned BlobLen = 0;
-  RecordData Record;
-  PreprocessorDetailRecordTypes RecType =
-    (PreprocessorDetailRecordTypes)M.PreprocessorDetailCursor.ReadRecord(
-                                             Code, Record, BlobStart, BlobLen);
-  switch (RecType) {
-  case PPD_MACRO_EXPANSION: {
-    bool isBuiltin = Record[0];
-    IdentifierInfo *Name = 0;
-    MacroDefinition *Def = 0;
-    if (isBuiltin)
-      Name = getLocalIdentifier(M, Record[1]);
-    else {
-      PreprocessedEntityID
-          GlobalID = getGlobalPreprocessedEntityID(M, Record[1]);
-      Def =cast<MacroDefinition>(PPRec.getLoadedPreprocessedEntity(GlobalID-1));
-    }
-
-    MacroExpansion *ME;
-    if (isBuiltin)
-      ME = new (PPRec) MacroExpansion(Name, Range);
-    else
-      ME = new (PPRec) MacroExpansion(Def, Range);
-
-    return ME;
-  }
-      
-  case PPD_MACRO_DEFINITION: {
-    // Decode the identifier info and then check again; if the macro is
-    // still defined and associated with the identifier,
-    IdentifierInfo *II = getLocalIdentifier(M, Record[0]);
-    MacroDefinition *MD
-      = new (PPRec) MacroDefinition(II, Range);
-
-    if (DeserializationListener)
-      DeserializationListener->MacroDefinitionRead(PPID, MD);
-
-    return MD;
-  }
-      
-  case PPD_INCLUSION_DIRECTIVE: {
-    const char *FullFileNameStart = BlobStart + Record[0];
-    StringRef FullFileName(FullFileNameStart, BlobLen - Record[0]);
-    const FileEntry *File = 0;
-    if (!FullFileName.empty())
-      File = PP.getFileManager().getFile(FullFileName);
-    
-    // FIXME: Stable encoding
-    InclusionDirective::InclusionKind Kind
-      = static_cast<InclusionDirective::InclusionKind>(Record[2]);
-    InclusionDirective *ID
-      = new (PPRec) InclusionDirective(PPRec, Kind,
-                                       StringRef(BlobStart, Record[0]),
-                                       Record[1], Record[3],
-                                       File,
-                                       Range);
-    return ID;
-  }
-  }
-
-  llvm_unreachable("Invalid PreprocessorDetailRecordTypes");
-}
-
-/// \brief \arg SLocMapI points at a chunk of a module that contains no
-/// preprocessed entities or the entities it contains are not the ones we are
-/// looking for. Find the next module that contains entities and return the ID
-/// of the first entry.
-PreprocessedEntityID ASTReader::findNextPreprocessedEntity(
-                       GlobalSLocOffsetMapType::const_iterator SLocMapI) const {
-  ++SLocMapI;
-  for (GlobalSLocOffsetMapType::const_iterator
-         EndI = GlobalSLocOffsetMap.end(); SLocMapI != EndI; ++SLocMapI) {
-    ModuleFile &M = *SLocMapI->second;
-    if (M.NumPreprocessedEntities)
-      return M.BasePreprocessedEntityID;
-  }
-
-  return getTotalNumPreprocessedEntities();
-}
-
-namespace {
-
-template <unsigned PPEntityOffset::*PPLoc>
-struct PPEntityComp {
-  const ASTReader &Reader;
-  ModuleFile &M;
-
-  PPEntityComp(const ASTReader &Reader, ModuleFile &M) : Reader(Reader), M(M) { }
-
-  bool operator()(const PPEntityOffset &L, const PPEntityOffset &R) const {
-    SourceLocation LHS = getLoc(L);
-    SourceLocation RHS = getLoc(R);
-    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
-  }
-
-  bool operator()(const PPEntityOffset &L, SourceLocation RHS) const {
-    SourceLocation LHS = getLoc(L);
-    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
-  }
-
-  bool operator()(SourceLocation LHS, const PPEntityOffset &R) const {
-    SourceLocation RHS = getLoc(R);
-    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
-  }
-
-  SourceLocation getLoc(const PPEntityOffset &PPE) const {
-    return Reader.ReadSourceLocation(M, PPE.*PPLoc);
-  }
-};
-
-}
-
-/// \brief Returns the first preprocessed entity ID that ends after \arg BLoc.
-PreprocessedEntityID
-ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const {
-  if (SourceMgr.isLocalSourceLocation(BLoc))
-    return getTotalNumPreprocessedEntities();
-
-  GlobalSLocOffsetMapType::const_iterator
-    SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -
-                                        BLoc.getOffset());
-  assert(SLocMapI != GlobalSLocOffsetMap.end() &&
-         "Corrupted global sloc offset map");
-
-  if (SLocMapI->second->NumPreprocessedEntities == 0)
-    return findNextPreprocessedEntity(SLocMapI);
-
-  ModuleFile &M = *SLocMapI->second;
-  typedef const PPEntityOffset *pp_iterator;
-  pp_iterator pp_begin = M.PreprocessedEntityOffsets;
-  pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities;
-
-  size_t Count = M.NumPreprocessedEntities;
-  size_t Half;
-  pp_iterator First = pp_begin;
-  pp_iterator PPI;
-
-  // Do a binary search manually instead of using std::lower_bound because
-  // The end locations of entities may be unordered (when a macro expansion
-  // is inside another macro argument), but for this case it is not important
-  // whether we get the first macro expansion or its containing macro.
-  while (Count > 0) {
-    Half = Count/2;
-    PPI = First;
-    std::advance(PPI, Half);
-    if (SourceMgr.isBeforeInTranslationUnit(ReadSourceLocation(M, PPI->End),
-                                            BLoc)){
-      First = PPI;
-      ++First;
-      Count = Count - Half - 1;
-    } else
-      Count = Half;
-  }
-
-  if (PPI == pp_end)
-    return findNextPreprocessedEntity(SLocMapI);
-
-  return M.BasePreprocessedEntityID + (PPI - pp_begin);
-}
-
-/// \brief Returns the first preprocessed entity ID that begins after \arg ELoc.
-PreprocessedEntityID
-ASTReader::findEndPreprocessedEntity(SourceLocation ELoc) const {
-  if (SourceMgr.isLocalSourceLocation(ELoc))
-    return getTotalNumPreprocessedEntities();
-
-  GlobalSLocOffsetMapType::const_iterator
-    SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -
-                                        ELoc.getOffset());
-  assert(SLocMapI != GlobalSLocOffsetMap.end() &&
-         "Corrupted global sloc offset map");
-
-  if (SLocMapI->second->NumPreprocessedEntities == 0)
-    return findNextPreprocessedEntity(SLocMapI);
-
-  ModuleFile &M = *SLocMapI->second;
-  typedef const PPEntityOffset *pp_iterator;
-  pp_iterator pp_begin = M.PreprocessedEntityOffsets;
-  pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities;
-  pp_iterator PPI =
-      std::upper_bound(pp_begin, pp_end, ELoc,
-                       PPEntityComp<&PPEntityOffset::Begin>(*this, M));
-
-  if (PPI == pp_end)
-    return findNextPreprocessedEntity(SLocMapI);
-
-  return M.BasePreprocessedEntityID + (PPI - pp_begin);
-}
-
-/// \brief Returns a pair of [Begin, End) indices of preallocated
-/// preprocessed entities that \arg Range encompasses.
-std::pair<unsigned, unsigned>
-    ASTReader::findPreprocessedEntitiesInRange(SourceRange Range) {
-  if (Range.isInvalid())
-    return std::make_pair(0,0);
-  assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
-
-  PreprocessedEntityID BeginID = findBeginPreprocessedEntity(Range.getBegin());
-  PreprocessedEntityID EndID = findEndPreprocessedEntity(Range.getEnd());
-  return std::make_pair(BeginID, EndID);
-}
-
-/// \brief Optionally returns true or false if the preallocated preprocessed
-/// entity with index \arg Index came from file \arg FID.
-llvm::Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index,
-                                                             FileID FID) {
-  if (FID.isInvalid())
-    return false;
-
-  std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index);
-  ModuleFile &M = *PPInfo.first;
-  unsigned LocalIndex = PPInfo.second;
-  const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex];
-  
-  SourceLocation Loc = ReadSourceLocation(M, PPOffs.Begin);
-  if (Loc.isInvalid())
-    return false;
-  
-  if (SourceMgr.isInFileID(SourceMgr.getFileLoc(Loc), FID))
-    return true;
-  else
-    return false;
-}
-
-namespace {
-  /// \brief Visitor used to search for information about a header file.
-  class HeaderFileInfoVisitor {
-    ASTReader &Reader;
-    const FileEntry *FE;
-    
-    llvm::Optional<HeaderFileInfo> HFI;
-    
-  public:
-    HeaderFileInfoVisitor(ASTReader &Reader, const FileEntry *FE)
-      : Reader(Reader), FE(FE) { }
-    
-    static bool visit(ModuleFile &M, void *UserData) {
-      HeaderFileInfoVisitor *This
-        = static_cast<HeaderFileInfoVisitor *>(UserData);
-      
-      HeaderFileInfoTrait Trait(This->Reader, M, 
-                                &This->Reader.getPreprocessor().getHeaderSearchInfo(),
-                                M.HeaderFileFrameworkStrings,
-                                This->FE->getName());
-      
-      HeaderFileInfoLookupTable *Table
-        = static_cast<HeaderFileInfoLookupTable *>(M.HeaderFileInfoTable);
-      if (!Table)
-        return false;
-
-      // Look in the on-disk hash table for an entry for this file name.
-      HeaderFileInfoLookupTable::iterator Pos = Table->find(This->FE->getName(),
-                                                            &Trait);
-      if (Pos == Table->end())
-        return false;
-
-      This->HFI = *Pos;
-      return true;
-    }
-    
-    llvm::Optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; }
-  };
-}
-
-HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) {
-  HeaderFileInfoVisitor Visitor(*this, FE);
-  ModuleMgr.visit(&HeaderFileInfoVisitor::visit, &Visitor);
-  if (llvm::Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo()) {
-    if (Listener)
-      Listener->ReadHeaderFileInfo(*HFI, FE->getUID());
-    return *HFI;
-  }
-  
-  return HeaderFileInfo();
-}
-
-void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
-  // FIXME: Make it work properly with modules.
-  llvm::SmallVector<DiagnosticsEngine::DiagState *, 32> DiagStates;
-  for (ModuleIterator I = ModuleMgr.begin(), E = ModuleMgr.end(); I != E; ++I) {
-    ModuleFile &F = *(*I);
-    unsigned Idx = 0;
-    DiagStates.clear();
-    assert(!Diag.DiagStates.empty());
-    DiagStates.push_back(&Diag.DiagStates.front()); // the command-line one.
-    while (Idx < F.PragmaDiagMappings.size()) {
-      SourceLocation Loc = ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]);
-      unsigned DiagStateID = F.PragmaDiagMappings[Idx++];
-      if (DiagStateID != 0) {
-        Diag.DiagStatePoints.push_back(
-                    DiagnosticsEngine::DiagStatePoint(DiagStates[DiagStateID-1],
-                    FullSourceLoc(Loc, SourceMgr)));
-        continue;
-      }
-      
-      assert(DiagStateID == 0);
-      // A new DiagState was created here.
-      Diag.DiagStates.push_back(*Diag.GetCurDiagState());
-      DiagnosticsEngine::DiagState *NewState = &Diag.DiagStates.back();
-      DiagStates.push_back(NewState);
-      Diag.DiagStatePoints.push_back(
-          DiagnosticsEngine::DiagStatePoint(NewState,
-                                            FullSourceLoc(Loc, SourceMgr)));
-      while (1) {
-        assert(Idx < F.PragmaDiagMappings.size() &&
-               "Invalid data, didn't find '-1' marking end of diag/map pairs");
-        if (Idx >= F.PragmaDiagMappings.size()) {
-          break; // Something is messed up but at least avoid infinite loop in
-                 // release build.
-        }
-        unsigned DiagID = F.PragmaDiagMappings[Idx++];
-        if (DiagID == (unsigned)-1) {
-          break; // no more diag/map pairs for this location.
-        }
-        diag::Mapping Map = (diag::Mapping)F.PragmaDiagMappings[Idx++];
-        DiagnosticMappingInfo MappingInfo = Diag.makeMappingInfo(Map, Loc);
-        Diag.GetCurDiagState()->setMappingInfo(DiagID, MappingInfo);
-      }
-    }
-  }
-}
-
-/// \brief Get the correct cursor and offset for loading a type.
-ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) {
-  GlobalTypeMapType::iterator I = GlobalTypeMap.find(Index);
-  assert(I != GlobalTypeMap.end() && "Corrupted global type map");
-  ModuleFile *M = I->second;
-  return RecordLocation(M, M->TypeOffsets[Index - M->BaseTypeIndex]);
-}
-
-/// \brief Read and return the type with the given index..
-///
-/// The index is the type ID, shifted and minus the number of predefs. This
-/// routine actually reads the record corresponding to the type at the given
-/// location. It is a helper routine for GetType, which deals with reading type
-/// IDs.
-QualType ASTReader::readTypeRecord(unsigned Index) {
-  RecordLocation Loc = TypeCursorForIndex(Index);
-  llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor;
-
-  // Keep track of where we are in the stream, then jump back there
-  // after reading this type.
-  SavedStreamPosition SavedPosition(DeclsCursor);
-
-  ReadingKindTracker ReadingKind(Read_Type, *this);
-
-  // Note that we are loading a type record.
-  Deserializing AType(this);
-
-  unsigned Idx = 0;
-  DeclsCursor.JumpToBit(Loc.Offset);
-  RecordData Record;
-  unsigned Code = DeclsCursor.ReadCode();
-  switch ((TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
-  case TYPE_EXT_QUAL: {
-    if (Record.size() != 2) {
-      Error("Incorrect encoding of extended qualifier type");
-      return QualType();
-    }
-    QualType Base = readType(*Loc.F, Record, Idx);
-    Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[Idx++]);
-    return Context.getQualifiedType(Base, Quals);
-  }
-
-  case TYPE_COMPLEX: {
-    if (Record.size() != 1) {
-      Error("Incorrect encoding of complex type");
-      return QualType();
-    }
-    QualType ElemType = readType(*Loc.F, Record, Idx);
-    return Context.getComplexType(ElemType);
-  }
-
-  case TYPE_POINTER: {
-    if (Record.size() != 1) {
-      Error("Incorrect encoding of pointer type");
-      return QualType();
-    }
-    QualType PointeeType = readType(*Loc.F, Record, Idx);
-    return Context.getPointerType(PointeeType);
-  }
-
-  case TYPE_BLOCK_POINTER: {
-    if (Record.size() != 1) {
-      Error("Incorrect encoding of block pointer type");
-      return QualType();
-    }
-    QualType PointeeType = readType(*Loc.F, Record, Idx);
-    return Context.getBlockPointerType(PointeeType);
-  }
-
-  case TYPE_LVALUE_REFERENCE: {
-    if (Record.size() != 2) {
-      Error("Incorrect encoding of lvalue reference type");
-      return QualType();
-    }
-    QualType PointeeType = readType(*Loc.F, Record, Idx);
-    return Context.getLValueReferenceType(PointeeType, Record[1]);
-  }
-
-  case TYPE_RVALUE_REFERENCE: {
-    if (Record.size() != 1) {
-      Error("Incorrect encoding of rvalue reference type");
-      return QualType();
-    }
-    QualType PointeeType = readType(*Loc.F, Record, Idx);
-    return Context.getRValueReferenceType(PointeeType);
-  }
-
-  case TYPE_MEMBER_POINTER: {
-    if (Record.size() != 2) {
-      Error("Incorrect encoding of member pointer type");
-      return QualType();
-    }
-    QualType PointeeType = readType(*Loc.F, Record, Idx);
-    QualType ClassType = readType(*Loc.F, Record, Idx);
-    if (PointeeType.isNull() || ClassType.isNull())
-      return QualType();
-    
-    return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
-  }
-
-  case TYPE_CONSTANT_ARRAY: {
-    QualType ElementType = readType(*Loc.F, Record, Idx);
-    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
-    unsigned IndexTypeQuals = Record[2];
-    unsigned Idx = 3;
-    llvm::APInt Size = ReadAPInt(Record, Idx);
-    return Context.getConstantArrayType(ElementType, Size,
-                                         ASM, IndexTypeQuals);
-  }
-
-  case TYPE_INCOMPLETE_ARRAY: {
-    QualType ElementType = readType(*Loc.F, Record, Idx);
-    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
-    unsigned IndexTypeQuals = Record[2];
-    return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
-  }
-
-  case TYPE_VARIABLE_ARRAY: {
-    QualType ElementType = readType(*Loc.F, Record, Idx);
-    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
-    unsigned IndexTypeQuals = Record[2];
-    SourceLocation LBLoc = ReadSourceLocation(*Loc.F, Record[3]);
-    SourceLocation RBLoc = ReadSourceLocation(*Loc.F, Record[4]);
-    return Context.getVariableArrayType(ElementType, ReadExpr(*Loc.F),
-                                         ASM, IndexTypeQuals,
-                                         SourceRange(LBLoc, RBLoc));
-  }
-
-  case TYPE_VECTOR: {
-    if (Record.size() != 3) {
-      Error("incorrect encoding of vector type in AST file");
-      return QualType();
-    }
-
-    QualType ElementType = readType(*Loc.F, Record, Idx);
-    unsigned NumElements = Record[1];
-    unsigned VecKind = Record[2];
-    return Context.getVectorType(ElementType, NumElements,
-                                  (VectorType::VectorKind)VecKind);
-  }
-
-  case TYPE_EXT_VECTOR: {
-    if (Record.size() != 3) {
-      Error("incorrect encoding of extended vector type in AST file");
-      return QualType();
-    }
-
-    QualType ElementType = readType(*Loc.F, Record, Idx);
-    unsigned NumElements = Record[1];
-    return Context.getExtVectorType(ElementType, NumElements);
-  }
-
-  case TYPE_FUNCTION_NO_PROTO: {
-    if (Record.size() != 6) {
-      Error("incorrect encoding of no-proto function type");
-      return QualType();
-    }
-    QualType ResultType = readType(*Loc.F, Record, Idx);
-    FunctionType::ExtInfo Info(Record[1], Record[2], Record[3],
-                               (CallingConv)Record[4], Record[5]);
-    return Context.getFunctionNoProtoType(ResultType, Info);
-  }
-
-  case TYPE_FUNCTION_PROTO: {
-    QualType ResultType = readType(*Loc.F, Record, Idx);
-
-    FunctionProtoType::ExtProtoInfo EPI;
-    EPI.ExtInfo = FunctionType::ExtInfo(/*noreturn*/ Record[1],
-                                        /*hasregparm*/ Record[2],
-                                        /*regparm*/ Record[3],
-                                        static_cast<CallingConv>(Record[4]),
-                                        /*produces*/ Record[5]);
-
-    unsigned Idx = 6;
-    unsigned NumParams = Record[Idx++];
-    SmallVector<QualType, 16> ParamTypes;
-    for (unsigned I = 0; I != NumParams; ++I)
-      ParamTypes.push_back(readType(*Loc.F, Record, Idx));
-
-    EPI.Variadic = Record[Idx++];
-    EPI.HasTrailingReturn = Record[Idx++];
-    EPI.TypeQuals = Record[Idx++];
-    EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]);
-    ExceptionSpecificationType EST =
-        static_cast<ExceptionSpecificationType>(Record[Idx++]);
-    EPI.ExceptionSpecType = EST;
-    SmallVector<QualType, 2> Exceptions;
-    if (EST == EST_Dynamic) {
-      EPI.NumExceptions = Record[Idx++];
-      for (unsigned I = 0; I != EPI.NumExceptions; ++I)
-        Exceptions.push_back(readType(*Loc.F, Record, Idx));
-      EPI.Exceptions = Exceptions.data();
-    } else if (EST == EST_ComputedNoexcept) {
-      EPI.NoexceptExpr = ReadExpr(*Loc.F);
-    } else if (EST == EST_Uninstantiated) {
-      EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
-      EPI.ExceptionSpecTemplate = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
-    } else if (EST == EST_Unevaluated) {
-      EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
-    }
-    return Context.getFunctionType(ResultType, ParamTypes.data(), NumParams,
-                                    EPI);
-  }
-
-  case TYPE_UNRESOLVED_USING: {
-    unsigned Idx = 0;
-    return Context.getTypeDeclType(
-                  ReadDeclAs<UnresolvedUsingTypenameDecl>(*Loc.F, Record, Idx));
-  }
-      
-  case TYPE_TYPEDEF: {
-    if (Record.size() != 2) {
-      Error("incorrect encoding of typedef type");
-      return QualType();
-    }
-    unsigned Idx = 0;
-    TypedefNameDecl *Decl = ReadDeclAs<TypedefNameDecl>(*Loc.F, Record, Idx);
-    QualType Canonical = readType(*Loc.F, Record, Idx);
-    if (!Canonical.isNull())
-      Canonical = Context.getCanonicalType(Canonical);
-    return Context.getTypedefType(Decl, Canonical);
-  }
-
-  case TYPE_TYPEOF_EXPR:
-    return Context.getTypeOfExprType(ReadExpr(*Loc.F));
-
-  case TYPE_TYPEOF: {
-    if (Record.size() != 1) {
-      Error("incorrect encoding of typeof(type) in AST file");
-      return QualType();
-    }
-    QualType UnderlyingType = readType(*Loc.F, Record, Idx);
-    return Context.getTypeOfType(UnderlyingType);
-  }
-
-  case TYPE_DECLTYPE: {
-    QualType UnderlyingType = readType(*Loc.F, Record, Idx);
-    return Context.getDecltypeType(ReadExpr(*Loc.F), UnderlyingType);
-  }
-
-  case TYPE_UNARY_TRANSFORM: {
-    QualType BaseType = readType(*Loc.F, Record, Idx);
-    QualType UnderlyingType = readType(*Loc.F, Record, Idx);
-    UnaryTransformType::UTTKind UKind = (UnaryTransformType::UTTKind)Record[2];
-    return Context.getUnaryTransformType(BaseType, UnderlyingType, UKind);
-  }
-
-  case TYPE_AUTO:
-    return Context.getAutoType(readType(*Loc.F, Record, Idx));
-
-  case TYPE_RECORD: {
-    if (Record.size() != 2) {
-      Error("incorrect encoding of record type");
-      return QualType();
-    }
-    unsigned Idx = 0;
-    bool IsDependent = Record[Idx++];
-    RecordDecl *RD = ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx);
-    RD = cast_or_null<RecordDecl>(RD->getCanonicalDecl());
-    QualType T = Context.getRecordType(RD);
-    const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
-    return T;
-  }
-
-  case TYPE_ENUM: {
-    if (Record.size() != 2) {
-      Error("incorrect encoding of enum type");
-      return QualType();
-    }
-    unsigned Idx = 0;
-    bool IsDependent = Record[Idx++];
-    QualType T
-      = Context.getEnumType(ReadDeclAs<EnumDecl>(*Loc.F, Record, Idx));
-    const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
-    return T;
-  }
-
-  case TYPE_ATTRIBUTED: {
-    if (Record.size() != 3) {
-      Error("incorrect encoding of attributed type");
-      return QualType();
-    }
-    QualType modifiedType = readType(*Loc.F, Record, Idx);
-    QualType equivalentType = readType(*Loc.F, Record, Idx);
-    AttributedType::Kind kind = static_cast<AttributedType::Kind>(Record[2]);
-    return Context.getAttributedType(kind, modifiedType, equivalentType);
-  }
-
-  case TYPE_PAREN: {
-    if (Record.size() != 1) {
-      Error("incorrect encoding of paren type");
-      return QualType();
-    }
-    QualType InnerType = readType(*Loc.F, Record, Idx);
-    return Context.getParenType(InnerType);
-  }
-
-  case TYPE_PACK_EXPANSION: {
-    if (Record.size() != 2) {
-      Error("incorrect encoding of pack expansion type");
-      return QualType();
-    }
-    QualType Pattern = readType(*Loc.F, Record, Idx);
-    if (Pattern.isNull())
-      return QualType();
-    llvm::Optional<unsigned> NumExpansions;
-    if (Record[1])
-      NumExpansions = Record[1] - 1;
-    return Context.getPackExpansionType(Pattern, NumExpansions);
-  }
-
-  case TYPE_ELABORATED: {
-    unsigned Idx = 0;
-    ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
-    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);
-    QualType NamedType = readType(*Loc.F, Record, Idx);
-    return Context.getElaboratedType(Keyword, NNS, NamedType);
-  }
-
-  case TYPE_OBJC_INTERFACE: {
-    unsigned Idx = 0;
-    ObjCInterfaceDecl *ItfD
-      = ReadDeclAs<ObjCInterfaceDecl>(*Loc.F, Record, Idx);
-    return Context.getObjCInterfaceType(ItfD->getCanonicalDecl());
-  }
-
-  case TYPE_OBJC_OBJECT: {
-    unsigned Idx = 0;
-    QualType Base = readType(*Loc.F, Record, Idx);
-    unsigned NumProtos = Record[Idx++];
-    SmallVector<ObjCProtocolDecl*, 4> Protos;
-    for (unsigned I = 0; I != NumProtos; ++I)
-      Protos.push_back(ReadDeclAs<ObjCProtocolDecl>(*Loc.F, Record, Idx));
-    return Context.getObjCObjectType(Base, Protos.data(), NumProtos);
-  }
-
-  case TYPE_OBJC_OBJECT_POINTER: {
-    unsigned Idx = 0;
-    QualType Pointee = readType(*Loc.F, Record, Idx);
-    return Context.getObjCObjectPointerType(Pointee);
-  }
-
-  case TYPE_SUBST_TEMPLATE_TYPE_PARM: {
-    unsigned Idx = 0;
-    QualType Parm = readType(*Loc.F, Record, Idx);
-    QualType Replacement = readType(*Loc.F, Record, Idx);
-    return
-      Context.getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
-                                            Replacement);
-  }
-
-  case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: {
-    unsigned Idx = 0;
-    QualType Parm = readType(*Loc.F, Record, Idx);
-    TemplateArgument ArgPack = ReadTemplateArgument(*Loc.F, Record, Idx);
-    return Context.getSubstTemplateTypeParmPackType(
-                                               cast<TemplateTypeParmType>(Parm),
-                                                     ArgPack);
-  }
-
-  case TYPE_INJECTED_CLASS_NAME: {
-    CXXRecordDecl *D = ReadDeclAs<CXXRecordDecl>(*Loc.F, Record, Idx);
-    QualType TST = readType(*Loc.F, Record, Idx); // probably derivable
-    // FIXME: ASTContext::getInjectedClassNameType is not currently suitable
-    // for AST reading, too much interdependencies.
-    return
-      QualType(new (Context, TypeAlignment) InjectedClassNameType(D, TST), 0);
-  }
-
-  case TYPE_TEMPLATE_TYPE_PARM: {
-    unsigned Idx = 0;
-    unsigned Depth = Record[Idx++];
-    unsigned Index = Record[Idx++];
-    bool Pack = Record[Idx++];
-    TemplateTypeParmDecl *D
-      = ReadDeclAs<TemplateTypeParmDecl>(*Loc.F, Record, Idx);
-    return Context.getTemplateTypeParmType(Depth, Index, Pack, D);
-  }
-
-  case TYPE_DEPENDENT_NAME: {
-    unsigned Idx = 0;
-    ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
-    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);
-    const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx);
-    QualType Canon = readType(*Loc.F, Record, Idx);
-    if (!Canon.isNull())
-      Canon = Context.getCanonicalType(Canon);
-    return Context.getDependentNameType(Keyword, NNS, Name, Canon);
-  }
-
-  case TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: {
-    unsigned Idx = 0;
-    ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
-    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);
-    const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx);
-    unsigned NumArgs = Record[Idx++];
-    SmallVector<TemplateArgument, 8> Args;
-    Args.reserve(NumArgs);
-    while (NumArgs--)
-      Args.push_back(ReadTemplateArgument(*Loc.F, Record, Idx));
-    return Context.getDependentTemplateSpecializationType(Keyword, NNS, Name,
-                                                      Args.size(), Args.data());
-  }
-
-  case TYPE_DEPENDENT_SIZED_ARRAY: {
-    unsigned Idx = 0;
-
-    // ArrayType
-    QualType ElementType = readType(*Loc.F, Record, Idx);
-    ArrayType::ArraySizeModifier ASM
-      = (ArrayType::ArraySizeModifier)Record[Idx++];
-    unsigned IndexTypeQuals = Record[Idx++];
-
-    // DependentSizedArrayType
-    Expr *NumElts = ReadExpr(*Loc.F);
-    SourceRange Brackets = ReadSourceRange(*Loc.F, Record, Idx);
-
-    return Context.getDependentSizedArrayType(ElementType, NumElts, ASM,
-                                               IndexTypeQuals, Brackets);
-  }
-
-  case TYPE_TEMPLATE_SPECIALIZATION: {
-    unsigned Idx = 0;
-    bool IsDependent = Record[Idx++];
-    TemplateName Name = ReadTemplateName(*Loc.F, Record, Idx);
-    SmallVector<TemplateArgument, 8> Args;
-    ReadTemplateArgumentList(Args, *Loc.F, Record, Idx);
-    QualType Underlying = readType(*Loc.F, Record, Idx);
-    QualType T;
-    if (Underlying.isNull())
-      T = Context.getCanonicalTemplateSpecializationType(Name, Args.data(),
-                                                          Args.size());
-    else
-      T = Context.getTemplateSpecializationType(Name, Args.data(),
-                                                 Args.size(), Underlying);
-    const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
-    return T;
-  }
-
-  case TYPE_ATOMIC: {
-    if (Record.size() != 1) {
-      Error("Incorrect encoding of atomic type");
-      return QualType();
-    }
-    QualType ValueType = readType(*Loc.F, Record, Idx);
-    return Context.getAtomicType(ValueType);
-  }
-  }
-  llvm_unreachable("Invalid TypeCode!");
-}
-
-class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> {
-  ASTReader &Reader;
-  ModuleFile &F;
-  const ASTReader::RecordData &Record;
-  unsigned &Idx;
-
-  SourceLocation ReadSourceLocation(const ASTReader::RecordData &R,
-                                    unsigned &I) {
-    return Reader.ReadSourceLocation(F, R, I);
-  }
-
-  template<typename T>
-  T *ReadDeclAs(const ASTReader::RecordData &Record, unsigned &Idx) {
-    return Reader.ReadDeclAs<T>(F, Record, Idx);
-  }
-  
-public:
-  TypeLocReader(ASTReader &Reader, ModuleFile &F,
-                const ASTReader::RecordData &Record, unsigned &Idx)
-    : Reader(Reader), F(F), Record(Record), Idx(Idx)
-  { }
-
-  // We want compile-time assurance that we've enumerated all of
-  // these, so unfortunately we have to declare them first, then
-  // define them out-of-line.
-#define ABSTRACT_TYPELOC(CLASS, PARENT)
-#define TYPELOC(CLASS, PARENT) \
-  void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
-#include "clang/AST/TypeLocNodes.def"
-
-  void VisitFunctionTypeLoc(FunctionTypeLoc);
-  void VisitArrayTypeLoc(ArrayTypeLoc);
-};
-
-void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
-  // nothing to do
-}
-void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
-  TL.setBuiltinLoc(ReadSourceLocation(Record, Idx));
-  if (TL.needsExtraLocalData()) {
-    TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++]));
-    TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++]));
-    TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++]));
-    TL.setModeAttr(Record[Idx++]);
-  }
-}
-void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
-  TL.setStarLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
-  TL.setCaretLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
-  TL.setAmpLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
-  TL.setAmpAmpLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
-  TL.setStarLoc(ReadSourceLocation(Record, Idx));
-  TL.setClassTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
-}
-void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
-  TL.setLBracketLoc(ReadSourceLocation(Record, Idx));
-  TL.setRBracketLoc(ReadSourceLocation(Record, Idx));
-  if (Record[Idx++])
-    TL.setSizeExpr(Reader.ReadExpr(F));
-  else
-    TL.setSizeExpr(0);
-}
-void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
-  VisitArrayTypeLoc(TL);
-}
-void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
-  VisitArrayTypeLoc(TL);
-}
-void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
-  VisitArrayTypeLoc(TL);
-}
-void TypeLocReader::VisitDependentSizedArrayTypeLoc(
-                                            DependentSizedArrayTypeLoc TL) {
-  VisitArrayTypeLoc(TL);
-}
-void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
-                                        DependentSizedExtVectorTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
-  TL.setLocalRangeBegin(ReadSourceLocation(Record, Idx));
-  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
-  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
-  TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx));
-  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
-    TL.setArg(i, ReadDeclAs<ParmVarDecl>(Record, Idx));
-  }
-}
-void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
-  VisitFunctionTypeLoc(TL);
-}
-void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
-  VisitFunctionTypeLoc(TL);
-}
-void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
-  TL.setTypeofLoc(ReadSourceLocation(Record, Idx));
-  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
-  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
-  TL.setTypeofLoc(ReadSourceLocation(Record, Idx));
-  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
-  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
-  TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
-}
-void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
-  TL.setKWLoc(ReadSourceLocation(Record, Idx));
-  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
-  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
-  TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
-}
-void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
-  TL.setAttrNameLoc(ReadSourceLocation(Record, Idx));
-  if (TL.hasAttrOperand()) {
-    SourceRange range;
-    range.setBegin(ReadSourceLocation(Record, Idx));
-    range.setEnd(ReadSourceLocation(Record, Idx));
-    TL.setAttrOperandParensRange(range);
-  }
-  if (TL.hasAttrExprOperand()) {
-    if (Record[Idx++])
-      TL.setAttrExprOperand(Reader.ReadExpr(F));
-    else
-      TL.setAttrExprOperand(0);
-  } else if (TL.hasAttrEnumOperand())
-    TL.setAttrEnumOperandLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
-                                            SubstTemplateTypeParmTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc(
-                                          SubstTemplateTypeParmPackTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitTemplateSpecializationTypeLoc(
-                                           TemplateSpecializationTypeLoc TL) {
-  TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx));
-  TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx));
-  TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
-  TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
-  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
-    TL.setArgLocInfo(i,
-        Reader.GetTemplateArgumentLocInfo(F,
-                                          TL.getTypePtr()->getArg(i).getKind(),
-                                          Record, Idx));
-}
-void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) {
-  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
-  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
-  TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));
-  TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
-}
-void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
-  TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));
-  TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc(
-       DependentTemplateSpecializationTypeLoc TL) {
-  TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));
-  TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
-  TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx));
-  TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx));
-  TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
-  TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
-  for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
-    TL.setArgLocInfo(I,
-        Reader.GetTemplateArgumentLocInfo(F,
-                                          TL.getTypePtr()->getArg(I).getKind(),
-                                          Record, Idx));
-}
-void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
-  TL.setEllipsisLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
-  TL.setNameLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
-  TL.setHasBaseTypeAsWritten(Record[Idx++]);
-  TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
-  TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
-  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
-    TL.setProtocolLoc(i, ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
-  TL.setStarLoc(ReadSourceLocation(Record, Idx));
-}
-void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
-  TL.setKWLoc(ReadSourceLocation(Record, Idx));
-  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
-  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
-}
-
-TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F,
-                                             const RecordData &Record,
-                                             unsigned &Idx) {
-  QualType InfoTy = readType(F, Record, Idx);
-  if (InfoTy.isNull())
-    return 0;
-
-  TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy);
-  TypeLocReader TLR(*this, F, Record, Idx);
-  for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
-    TLR.Visit(TL);
-  return TInfo;
-}
-
-QualType ASTReader::GetType(TypeID ID) {
-  unsigned FastQuals = ID & Qualifiers::FastMask;
-  unsigned Index = ID >> Qualifiers::FastWidth;
-
-  if (Index < NUM_PREDEF_TYPE_IDS) {
-    QualType T;
-    switch ((PredefinedTypeIDs)Index) {
-    case PREDEF_TYPE_NULL_ID: return QualType();
-    case PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;
-    case PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;
-
-    case PREDEF_TYPE_CHAR_U_ID:
-    case PREDEF_TYPE_CHAR_S_ID:
-      // FIXME: Check that the signedness of CharTy is correct!
-      T = Context.CharTy;
-      break;
-
-    case PREDEF_TYPE_UCHAR_ID:      T = Context.UnsignedCharTy;     break;
-    case PREDEF_TYPE_USHORT_ID:     T = Context.UnsignedShortTy;    break;
-    case PREDEF_TYPE_UINT_ID:       T = Context.UnsignedIntTy;      break;
-    case PREDEF_TYPE_ULONG_ID:      T = Context.UnsignedLongTy;     break;
-    case PREDEF_TYPE_ULONGLONG_ID:  T = Context.UnsignedLongLongTy; break;
-    case PREDEF_TYPE_UINT128_ID:    T = Context.UnsignedInt128Ty;   break;
-    case PREDEF_TYPE_SCHAR_ID:      T = Context.SignedCharTy;       break;
-    case PREDEF_TYPE_WCHAR_ID:      T = Context.WCharTy;            break;
-    case PREDEF_TYPE_SHORT_ID:      T = Context.ShortTy;            break;
-    case PREDEF_TYPE_INT_ID:        T = Context.IntTy;              break;
-    case PREDEF_TYPE_LONG_ID:       T = Context.LongTy;             break;
-    case PREDEF_TYPE_LONGLONG_ID:   T = Context.LongLongTy;         break;
-    case PREDEF_TYPE_INT128_ID:     T = Context.Int128Ty;           break;
-    case PREDEF_TYPE_HALF_ID:       T = Context.HalfTy;             break;
-    case PREDEF_TYPE_FLOAT_ID:      T = Context.FloatTy;            break;
-    case PREDEF_TYPE_DOUBLE_ID:     T = Context.DoubleTy;           break;
-    case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy;       break;
-    case PREDEF_TYPE_OVERLOAD_ID:   T = Context.OverloadTy;         break;
-    case PREDEF_TYPE_BOUND_MEMBER:  T = Context.BoundMemberTy;      break;
-    case PREDEF_TYPE_PSEUDO_OBJECT: T = Context.PseudoObjectTy;     break;
-    case PREDEF_TYPE_DEPENDENT_ID:  T = Context.DependentTy;        break;
-    case PREDEF_TYPE_UNKNOWN_ANY:   T = Context.UnknownAnyTy;       break;
-    case PREDEF_TYPE_NULLPTR_ID:    T = Context.NullPtrTy;          break;
-    case PREDEF_TYPE_CHAR16_ID:     T = Context.Char16Ty;           break;
-    case PREDEF_TYPE_CHAR32_ID:     T = Context.Char32Ty;           break;
-    case PREDEF_TYPE_OBJC_ID:       T = Context.ObjCBuiltinIdTy;    break;
-    case PREDEF_TYPE_OBJC_CLASS:    T = Context.ObjCBuiltinClassTy; break;
-    case PREDEF_TYPE_OBJC_SEL:      T = Context.ObjCBuiltinSelTy;   break;
-    case PREDEF_TYPE_AUTO_DEDUCT:   T = Context.getAutoDeductType(); break;
-        
-    case PREDEF_TYPE_AUTO_RREF_DEDUCT: 
-      T = Context.getAutoRRefDeductType(); 
-      break;
-
-    case PREDEF_TYPE_ARC_UNBRIDGED_CAST:
-      T = Context.ARCUnbridgedCastTy;
-      break;
-
-    case PREDEF_TYPE_VA_LIST_TAG:
-      T = Context.getVaListTagType();
-      break;
-
-    case PREDEF_TYPE_BUILTIN_FN:
-      T = Context.BuiltinFnTy;
-      break;
-    }
-
-    assert(!T.isNull() && "Unknown predefined type");
-    return T.withFastQualifiers(FastQuals);
-  }
-
-  Index -= NUM_PREDEF_TYPE_IDS;
-  assert(Index < TypesLoaded.size() && "Type index out-of-range");
-  if (TypesLoaded[Index].isNull()) {
-    TypesLoaded[Index] = readTypeRecord(Index);
-    if (TypesLoaded[Index].isNull())
-      return QualType();
-
-    TypesLoaded[Index]->setFromAST();
-    if (DeserializationListener)
-      DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID),
-                                        TypesLoaded[Index]);
-  }
-
-  return TypesLoaded[Index].withFastQualifiers(FastQuals);
-}
-
-QualType ASTReader::getLocalType(ModuleFile &F, unsigned LocalID) {
-  return GetType(getGlobalTypeID(F, LocalID));
-}
-
-serialization::TypeID 
-ASTReader::getGlobalTypeID(ModuleFile &F, unsigned LocalID) const {
-  unsigned FastQuals = LocalID & Qualifiers::FastMask;
-  unsigned LocalIndex = LocalID >> Qualifiers::FastWidth;
-  
-  if (LocalIndex < NUM_PREDEF_TYPE_IDS)
-    return LocalID;
-
-  ContinuousRangeMap<uint32_t, int, 2>::iterator I
-    = F.TypeRemap.find(LocalIndex - NUM_PREDEF_TYPE_IDS);
-  assert(I != F.TypeRemap.end() && "Invalid index into type index remap");
-  
-  unsigned GlobalIndex = LocalIndex + I->second;
-  return (GlobalIndex << Qualifiers::FastWidth) | FastQuals;
-}
-
-TemplateArgumentLocInfo
-ASTReader::GetTemplateArgumentLocInfo(ModuleFile &F,
-                                      TemplateArgument::ArgKind Kind,
-                                      const RecordData &Record,
-                                      unsigned &Index) {
-  switch (Kind) {
-  case TemplateArgument::Expression:
-    return ReadExpr(F);
-  case TemplateArgument::Type:
-    return GetTypeSourceInfo(F, Record, Index);
-  case TemplateArgument::Template: {
-    NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, 
-                                                                     Index);
-    SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
-    return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc,
-                                   SourceLocation());
-  }
-  case TemplateArgument::TemplateExpansion: {
-    NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, 
-                                                                     Index);
-    SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
-    SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index);
-    return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc, 
-                                   EllipsisLoc);
-  }
-  case TemplateArgument::Null:
-  case TemplateArgument::Integral:
-  case TemplateArgument::Declaration:
-  case TemplateArgument::NullPtr:
-  case TemplateArgument::Pack:
-    // FIXME: Is this right?
-    return TemplateArgumentLocInfo();
-  }
-  llvm_unreachable("unexpected template argument loc");
-}
-
-TemplateArgumentLoc
-ASTReader::ReadTemplateArgumentLoc(ModuleFile &F,
-                                   const RecordData &Record, unsigned &Index) {
-  TemplateArgument Arg = ReadTemplateArgument(F, Record, Index);
-
-  if (Arg.getKind() == TemplateArgument::Expression) {
-    if (Record[Index++]) // bool InfoHasSameExpr.
-      return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr()));
-  }
-  return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(F, Arg.getKind(),
-                                                             Record, Index));
-}
-
-Decl *ASTReader::GetExternalDecl(uint32_t ID) {
-  return GetDecl(ID);
-}
-
-uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record, 
-                                          unsigned &Idx){
-  if (Idx >= Record.size())
-    return 0;
-  
-  unsigned LocalID = Record[Idx++];
-  return getGlobalBitOffset(M, M.CXXBaseSpecifiersOffsets[LocalID - 1]);
-}
-
-CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
-  RecordLocation Loc = getLocalBitOffset(Offset);
-  llvm::BitstreamCursor &Cursor = Loc.F->DeclsCursor;
-  SavedStreamPosition SavedPosition(Cursor);
-  Cursor.JumpToBit(Loc.Offset);
-  ReadingKindTracker ReadingKind(Read_Decl, *this);
-  RecordData Record;
-  unsigned Code = Cursor.ReadCode();
-  unsigned RecCode = Cursor.ReadRecord(Code, Record);
-  if (RecCode != DECL_CXX_BASE_SPECIFIERS) {
-    Error("Malformed AST file: missing C++ base specifiers");
-    return 0;
-  }
-
-  unsigned Idx = 0;
-  unsigned NumBases = Record[Idx++];
-  void *Mem = Context.Allocate(sizeof(CXXBaseSpecifier) * NumBases);
-  CXXBaseSpecifier *Bases = new (Mem) CXXBaseSpecifier [NumBases];
-  for (unsigned I = 0; I != NumBases; ++I)
-    Bases[I] = ReadCXXBaseSpecifier(*Loc.F, Record, Idx);
-  return Bases;
-}
-
-serialization::DeclID 
-ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const {
-  if (LocalID < NUM_PREDEF_DECL_IDS)
-    return LocalID;
-
-  ContinuousRangeMap<uint32_t, int, 2>::iterator I
-    = F.DeclRemap.find(LocalID - NUM_PREDEF_DECL_IDS);
-  assert(I != F.DeclRemap.end() && "Invalid index into decl index remap");
-  
-  return LocalID + I->second;
-}
-
-bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID,
-                                   ModuleFile &M) const {
-  GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(ID);
-  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
-  return &M == I->second;
-}
-
-ModuleFile *ASTReader::getOwningModuleFile(Decl *D) {
-  if (!D->isFromASTFile())
-    return 0;
-  GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID());
-  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
-  return I->second;
-}
-
-SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) {
-  if (ID < NUM_PREDEF_DECL_IDS)
-    return SourceLocation();
-  
-  unsigned Index = ID - NUM_PREDEF_DECL_IDS;
-
-  if (Index > DeclsLoaded.size()) {
-    Error("declaration ID out-of-range for AST file");
-    return SourceLocation();
-  }
-  
-  if (Decl *D = DeclsLoaded[Index])
-    return D->getLocation();
-
-  unsigned RawLocation = 0;
-  RecordLocation Rec = DeclCursorForID(ID, RawLocation);
-  return ReadSourceLocation(*Rec.F, RawLocation);
-}
-
-Decl *ASTReader::GetDecl(DeclID ID) {
-  if (ID < NUM_PREDEF_DECL_IDS) {    
-    switch ((PredefinedDeclIDs)ID) {
-    case PREDEF_DECL_NULL_ID:
-      return 0;
-        
-    case PREDEF_DECL_TRANSLATION_UNIT_ID:
-      return Context.getTranslationUnitDecl();
-        
-    case PREDEF_DECL_OBJC_ID_ID:
-      return Context.getObjCIdDecl();
-
-    case PREDEF_DECL_OBJC_SEL_ID:
-      return Context.getObjCSelDecl();
-
-    case PREDEF_DECL_OBJC_CLASS_ID:
-      return Context.getObjCClassDecl();
-        
-    case PREDEF_DECL_OBJC_PROTOCOL_ID:
-      return Context.getObjCProtocolDecl();
-        
-    case PREDEF_DECL_INT_128_ID:
-      return Context.getInt128Decl();
-
-    case PREDEF_DECL_UNSIGNED_INT_128_ID:
-      return Context.getUInt128Decl();
-        
-    case PREDEF_DECL_OBJC_INSTANCETYPE_ID:
-      return Context.getObjCInstanceTypeDecl();
-
-    case PREDEF_DECL_BUILTIN_VA_LIST_ID:
-      return Context.getBuiltinVaListDecl();
-    }
-  }
-  
-  unsigned Index = ID - NUM_PREDEF_DECL_IDS;
-
-  if (Index >= DeclsLoaded.size()) {
-    assert(0 && "declaration ID out-of-range for AST file");
-    Error("declaration ID out-of-range for AST file");
-    return 0;
-  }
-  
-  if (!DeclsLoaded[Index]) {
-    ReadDeclRecord(ID);
-    if (DeserializationListener)
-      DeserializationListener->DeclRead(ID, DeclsLoaded[Index]);
-  }
-
-  return DeclsLoaded[Index];
-}
-
-DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M, 
-                                                  DeclID GlobalID) {
-  if (GlobalID < NUM_PREDEF_DECL_IDS)
-    return GlobalID;
-  
-  GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID);
-  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
-  ModuleFile *Owner = I->second;
-
-  llvm::DenseMap<ModuleFile *, serialization::DeclID>::iterator Pos
-    = M.GlobalToLocalDeclIDs.find(Owner);
-  if (Pos == M.GlobalToLocalDeclIDs.end())
-    return 0;
-      
-  return GlobalID - Owner->BaseDeclID + Pos->second;
-}
-
-serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F, 
-                                            const RecordData &Record,
-                                            unsigned &Idx) {
-  if (Idx >= Record.size()) {
-    Error("Corrupted AST file");
-    return 0;
-  }
-  
-  return getGlobalDeclID(F, Record[Idx++]);
-}
-
-/// \brief Resolve the offset of a statement into a statement.
-///
-/// This operation will read a new statement from the external
-/// source each time it is called, and is meant to be used via a
-/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
-Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) {
-  // Switch case IDs are per Decl.
-  ClearSwitchCaseIDs();
-
-  // Offset here is a global offset across the entire chain.
-  RecordLocation Loc = getLocalBitOffset(Offset);
-  Loc.F->DeclsCursor.JumpToBit(Loc.Offset);
-  return ReadStmtFromStream(*Loc.F);
-}
-
-namespace {
-  class FindExternalLexicalDeclsVisitor {
-    ASTReader &Reader;
-    const DeclContext *DC;
-    bool (*isKindWeWant)(Decl::Kind);
-    
-    SmallVectorImpl<Decl*> &Decls;
-    bool PredefsVisited[NUM_PREDEF_DECL_IDS];
-
-  public:
-    FindExternalLexicalDeclsVisitor(ASTReader &Reader, const DeclContext *DC,
-                                    bool (*isKindWeWant)(Decl::Kind),
-                                    SmallVectorImpl<Decl*> &Decls)
-      : Reader(Reader), DC(DC), isKindWeWant(isKindWeWant), Decls(Decls) 
-    {
-      for (unsigned I = 0; I != NUM_PREDEF_DECL_IDS; ++I)
-        PredefsVisited[I] = false;
-    }
-
-    static bool visit(ModuleFile &M, bool Preorder, void *UserData) {
-      if (Preorder)
-        return false;
-
-      FindExternalLexicalDeclsVisitor *This
-        = static_cast<FindExternalLexicalDeclsVisitor *>(UserData);
-
-      ModuleFile::DeclContextInfosMap::iterator Info
-        = M.DeclContextInfos.find(This->DC);
-      if (Info == M.DeclContextInfos.end() || !Info->second.LexicalDecls)
-        return false;
-
-      // Load all of the declaration IDs
-      for (const KindDeclIDPair *ID = Info->second.LexicalDecls,
-                               *IDE = ID + Info->second.NumLexicalDecls; 
-           ID != IDE; ++ID) {
-        if (This->isKindWeWant && !This->isKindWeWant((Decl::Kind)ID->first))
-          continue;
-
-        // Don't add predefined declarations to the lexical context more
-        // than once.
-        if (ID->second < NUM_PREDEF_DECL_IDS) {
-          if (This->PredefsVisited[ID->second])
-            continue;
-
-          This->PredefsVisited[ID->second] = true;
-        }
-
-        if (Decl *D = This->Reader.GetLocalDecl(M, ID->second)) {
-          if (!This->DC->isDeclInLexicalTraversal(D))
-            This->Decls.push_back(D);
-        }
-      }
-
-      return false;
-    }
-  };
-}
-
-ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC,
-                                         bool (*isKindWeWant)(Decl::Kind),
-                                         SmallVectorImpl<Decl*> &Decls) {
-  // There might be lexical decls in multiple modules, for the TU at
-  // least. Walk all of the modules in the order they were loaded.
-  FindExternalLexicalDeclsVisitor Visitor(*this, DC, isKindWeWant, Decls);
-  ModuleMgr.visitDepthFirst(&FindExternalLexicalDeclsVisitor::visit, &Visitor);
-  ++NumLexicalDeclContextsRead;
-  return ELR_Success;
-}
-
-namespace {
-
-class DeclIDComp {
-  ASTReader &Reader;
-  ModuleFile &Mod;
-
-public:
-  DeclIDComp(ASTReader &Reader, ModuleFile &M) : Reader(Reader), Mod(M) {}
-
-  bool operator()(LocalDeclID L, LocalDeclID R) const {
-    SourceLocation LHS = getLocation(L);
-    SourceLocation RHS = getLocation(R);
-    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
-  }
-
-  bool operator()(SourceLocation LHS, LocalDeclID R) const {
-    SourceLocation RHS = getLocation(R);
-    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
-  }
-
-  bool operator()(LocalDeclID L, SourceLocation RHS) const {
-    SourceLocation LHS = getLocation(L);
-    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
-  }
-
-  SourceLocation getLocation(LocalDeclID ID) const {
-    return Reader.getSourceManager().getFileLoc(
-            Reader.getSourceLocationForDeclID(Reader.getGlobalDeclID(Mod, ID)));
-  }
-};
-
-}
-
-void ASTReader::FindFileRegionDecls(FileID File,
-                                    unsigned Offset, unsigned Length,
-                                    SmallVectorImpl<Decl *> &Decls) {
-  SourceManager &SM = getSourceManager();
-
-  llvm::DenseMap<FileID, FileDeclsInfo>::iterator I = FileDeclIDs.find(File);
-  if (I == FileDeclIDs.end())
-    return;
-
-  FileDeclsInfo &DInfo = I->second;
-  if (DInfo.Decls.empty())
-    return;
-
-  SourceLocation
-    BeginLoc = SM.getLocForStartOfFile(File).getLocWithOffset(Offset);
-  SourceLocation EndLoc = BeginLoc.getLocWithOffset(Length);
-
-  DeclIDComp DIDComp(*this, *DInfo.Mod);
-  ArrayRef<serialization::LocalDeclID>::iterator
-    BeginIt = std::lower_bound(DInfo.Decls.begin(), DInfo.Decls.end(),
-                               BeginLoc, DIDComp);
-  if (BeginIt != DInfo.Decls.begin())
-    --BeginIt;
-
-  // If we are pointing at a top-level decl inside an objc container, we need
-  // to backtrack until we find it otherwise we will fail to report that the
-  // region overlaps with an objc container.
-  while (BeginIt != DInfo.Decls.begin() &&
-         GetDecl(getGlobalDeclID(*DInfo.Mod, *BeginIt))
-             ->isTopLevelDeclInObjCContainer())
-    --BeginIt;
-
-  ArrayRef<serialization::LocalDeclID>::iterator
-    EndIt = std::upper_bound(DInfo.Decls.begin(), DInfo.Decls.end(),
-                             EndLoc, DIDComp);
-  if (EndIt != DInfo.Decls.end())
-    ++EndIt;
-  
-  for (ArrayRef<serialization::LocalDeclID>::iterator
-         DIt = BeginIt; DIt != EndIt; ++DIt)
-    Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt)));
-}
-
-namespace {
-  /// \brief ModuleFile visitor used to perform name lookup into a
-  /// declaration context.
-  class DeclContextNameLookupVisitor {
-    ASTReader &Reader;
-    llvm::SmallVectorImpl<const DeclContext *> &Contexts;
-    DeclarationName Name;
-    SmallVectorImpl<NamedDecl *> &Decls;
-
-  public:
-    DeclContextNameLookupVisitor(ASTReader &Reader, 
-                                 SmallVectorImpl<const DeclContext *> &Contexts, 
-                                 DeclarationName Name,
-                                 SmallVectorImpl<NamedDecl *> &Decls)
-      : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { }
-
-    static bool visit(ModuleFile &M, void *UserData) {
-      DeclContextNameLookupVisitor *This
-        = static_cast<DeclContextNameLookupVisitor *>(UserData);
-
-      // Check whether we have any visible declaration information for
-      // this context in this module.
-      ModuleFile::DeclContextInfosMap::iterator Info;
-      bool FoundInfo = false;
-      for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {
-        Info = M.DeclContextInfos.find(This->Contexts[I]);
-        if (Info != M.DeclContextInfos.end() && 
-            Info->second.NameLookupTableData) {
-          FoundInfo = true;
-          break;
-        }
-      }
-
-      if (!FoundInfo)
-        return false;
-      
-      // Look for this name within this module.
-      ASTDeclContextNameLookupTable *LookupTable =
-        Info->second.NameLookupTableData;
-      ASTDeclContextNameLookupTable::iterator Pos
-        = LookupTable->find(This->Name);
-      if (Pos == LookupTable->end())
-        return false;
-
-      bool FoundAnything = false;
-      ASTDeclContextNameLookupTrait::data_type Data = *Pos;
-      for (; Data.first != Data.second; ++Data.first) {
-        NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M, *Data.first);
-        if (!ND)
-          continue;
-
-        if (ND->getDeclName() != This->Name) {
-          // A name might be null because the decl's redeclarable part is
-          // currently read before reading its name. The lookup is triggered by
-          // building that decl (likely indirectly), and so it is later in the
-          // sense of "already existing" and can be ignored here.
-          continue;
-        }
-      
-        // Record this declaration.
-        FoundAnything = true;
-        This->Decls.push_back(ND);
-      }
-
-      return FoundAnything;
-    }
-  };
-}
-
-DeclContext::lookup_result
-ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
-                                          DeclarationName Name) {
-  assert(DC->hasExternalVisibleStorage() &&
-         "DeclContext has no visible decls in storage");
-  if (!Name)
-    return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
-                                      DeclContext::lookup_iterator(0));
-
-  SmallVector<NamedDecl *, 64> Decls;
-  
-  // Compute the declaration contexts we need to look into. Multiple such
-  // declaration contexts occur when two declaration contexts from disjoint
-  // modules get merged, e.g., when two namespaces with the same name are 
-  // independently defined in separate modules.
-  SmallVector<const DeclContext *, 2> Contexts;
-  Contexts.push_back(DC);
-  
-  if (DC->isNamespace()) {
-    MergedDeclsMap::iterator Merged
-      = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
-    if (Merged != MergedDecls.end()) {
-      for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
-        Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
-    }
-  }
-  
-  DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
-  ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);
-  ++NumVisibleDeclContextsRead;
-  SetExternalVisibleDeclsForName(DC, Name, Decls);
-  return const_cast<DeclContext*>(DC)->lookup(Name);
-}
-
-namespace {
-  /// \brief ModuleFile visitor used to retrieve all visible names in a
-  /// declaration context.
-  class DeclContextAllNamesVisitor {
-    ASTReader &Reader;
-    llvm::SmallVectorImpl<const DeclContext *> &Contexts;
-    llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> > &Decls;
-
-  public:
-    DeclContextAllNamesVisitor(ASTReader &Reader,
-                               SmallVectorImpl<const DeclContext *> &Contexts,
-                               llvm::DenseMap<DeclarationName,
-                                           SmallVector<NamedDecl *, 8> > &Decls)
-      : Reader(Reader), Contexts(Contexts), Decls(Decls) { }
-
-    static bool visit(ModuleFile &M, void *UserData) {
-      DeclContextAllNamesVisitor *This
-        = static_cast<DeclContextAllNamesVisitor *>(UserData);
-
-      // Check whether we have any visible declaration information for
-      // this context in this module.
-      ModuleFile::DeclContextInfosMap::iterator Info;
-      bool FoundInfo = false;
-      for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {
-        Info = M.DeclContextInfos.find(This->Contexts[I]);
-        if (Info != M.DeclContextInfos.end() &&
-            Info->second.NameLookupTableData) {
-          FoundInfo = true;
-          break;
-        }
-      }
-
-      if (!FoundInfo)
-        return false;
-
-      ASTDeclContextNameLookupTable *LookupTable =
-        Info->second.NameLookupTableData;
-      bool FoundAnything = false;
-      for (ASTDeclContextNameLookupTable::data_iterator
-	     I = LookupTable->data_begin(), E = LookupTable->data_end();
-	   I != E; ++I) {
-        ASTDeclContextNameLookupTrait::data_type Data = *I;
-        for (; Data.first != Data.second; ++Data.first) {
-          NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M,
-                                                                 *Data.first);
-          if (!ND)
-            continue;
-
-          // Record this declaration.
-          FoundAnything = true;
-          This->Decls[ND->getDeclName()].push_back(ND);
-        }
-      }
-
-      return FoundAnything;
-    }
-  };
-}
-
-void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {
-  if (!DC->hasExternalVisibleStorage())
-    return;
-  llvm::DenseMap<DeclarationName, llvm::SmallVector<NamedDecl*, 8> > Decls;
-
-  // Compute the declaration contexts we need to look into. Multiple such
-  // declaration contexts occur when two declaration contexts from disjoint
-  // modules get merged, e.g., when two namespaces with the same name are
-  // independently defined in separate modules.
-  SmallVector<const DeclContext *, 2> Contexts;
-  Contexts.push_back(DC);
-
-  if (DC->isNamespace()) {
-    MergedDeclsMap::iterator Merged
-      = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
-    if (Merged != MergedDecls.end()) {
-      for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
-        Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
-    }
-  }
-
-  DeclContextAllNamesVisitor Visitor(*this, Contexts, Decls);
-  ModuleMgr.visit(&DeclContextAllNamesVisitor::visit, &Visitor);
-  ++NumVisibleDeclContextsRead;
-
-  for (llvm::DenseMap<DeclarationName,
-                      llvm::SmallVector<NamedDecl*, 8> >::iterator
-         I = Decls.begin(), E = Decls.end(); I != E; ++I) {
-    SetExternalVisibleDeclsForName(DC, I->first, I->second);
-  }
-  const_cast<DeclContext *>(DC)->setHasExternalVisibleStorage(false);
-}
-
-/// \brief Under non-PCH compilation the consumer receives the objc methods
-/// before receiving the implementation, and codegen depends on this.
-/// We simulate this by deserializing and passing to consumer the methods of the
-/// implementation before passing the deserialized implementation decl.
-static void PassObjCImplDeclToConsumer(ObjCImplDecl *ImplD,
-                                       ASTConsumer *Consumer) {
-  assert(ImplD && Consumer);
-
-  for (ObjCImplDecl::method_iterator
-         I = ImplD->meth_begin(), E = ImplD->meth_end(); I != E; ++I)
-    Consumer->HandleInterestingDecl(DeclGroupRef(*I));
-
-  Consumer->HandleInterestingDecl(DeclGroupRef(ImplD));
-}
-
-void ASTReader::PassInterestingDeclsToConsumer() {
-  assert(Consumer);
-  while (!InterestingDecls.empty()) {
-    Decl *D = InterestingDecls.front();
-    InterestingDecls.pop_front();
-
-    PassInterestingDeclToConsumer(D);
-  }
-}
-
-void ASTReader::PassInterestingDeclToConsumer(Decl *D) {
-  if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D))
-    PassObjCImplDeclToConsumer(ImplD, Consumer);
-  else
-    Consumer->HandleInterestingDecl(DeclGroupRef(D));
-}
-
-void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
-  this->Consumer = Consumer;
-
-  if (!Consumer)
-    return;
-
-  for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
-    // Force deserialization of this decl, which will cause it to be queued for
-    // passing to the consumer.
-    GetDecl(ExternalDefinitions[I]);
-  }
-  ExternalDefinitions.clear();
-
-  PassInterestingDeclsToConsumer();
-}
-
-void ASTReader::PrintStats() {
-  std::fprintf(stderr, "*** AST File Statistics:\n");
-
-  unsigned NumTypesLoaded
-    = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
-                                      QualType());
-  unsigned NumDeclsLoaded
-    = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
-                                      (Decl *)0);
-  unsigned NumIdentifiersLoaded
-    = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
-                                            IdentifiersLoaded.end(),
-                                            (IdentifierInfo *)0);
-  unsigned NumMacrosLoaded
-    = MacrosLoaded.size() - std::count(MacrosLoaded.begin(),
-                                       MacrosLoaded.end(),
-                                       (MacroInfo *)0);
-  unsigned NumSelectorsLoaded
-    = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
-                                          SelectorsLoaded.end(),
-                                          Selector());
-
-  if (unsigned TotalNumSLocEntries = getTotalNumSLocs())
-    std::fprintf(stderr, "  %u/%u source location entries read (%f%%)\n",
-                 NumSLocEntriesRead, TotalNumSLocEntries,
-                 ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
-  if (!TypesLoaded.empty())
-    std::fprintf(stderr, "  %u/%u types read (%f%%)\n",
-                 NumTypesLoaded, (unsigned)TypesLoaded.size(),
-                 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
-  if (!DeclsLoaded.empty())
-    std::fprintf(stderr, "  %u/%u declarations read (%f%%)\n",
-                 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
-                 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
-  if (!IdentifiersLoaded.empty())
-    std::fprintf(stderr, "  %u/%u identifiers read (%f%%)\n",
-                 NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
-                 ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
-  if (!MacrosLoaded.empty())
-    std::fprintf(stderr, "  %u/%u macros read (%f%%)\n",
-                 NumMacrosLoaded, (unsigned)MacrosLoaded.size(),
-                 ((float)NumMacrosLoaded/MacrosLoaded.size() * 100));
-  if (!SelectorsLoaded.empty())
-    std::fprintf(stderr, "  %u/%u selectors read (%f%%)\n",
-                 NumSelectorsLoaded, (unsigned)SelectorsLoaded.size(),
-                 ((float)NumSelectorsLoaded/SelectorsLoaded.size() * 100));
-  if (TotalNumStatements)
-    std::fprintf(stderr, "  %u/%u statements read (%f%%)\n",
-                 NumStatementsRead, TotalNumStatements,
-                 ((float)NumStatementsRead/TotalNumStatements * 100));
-  if (TotalNumMacros)
-    std::fprintf(stderr, "  %u/%u macros read (%f%%)\n",
-                 NumMacrosRead, TotalNumMacros,
-                 ((float)NumMacrosRead/TotalNumMacros * 100));
-  if (TotalLexicalDeclContexts)
-    std::fprintf(stderr, "  %u/%u lexical declcontexts read (%f%%)\n",
-                 NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
-                 ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
-                  * 100));
-  if (TotalVisibleDeclContexts)
-    std::fprintf(stderr, "  %u/%u visible declcontexts read (%f%%)\n",
-                 NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
-                 ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
-                  * 100));
-  if (TotalNumMethodPoolEntries) {
-    std::fprintf(stderr, "  %u/%u method pool entries read (%f%%)\n",
-                 NumMethodPoolEntriesRead, TotalNumMethodPoolEntries,
-                 ((float)NumMethodPoolEntriesRead/TotalNumMethodPoolEntries
-                  * 100));
-    std::fprintf(stderr, "  %u method pool misses\n", NumMethodPoolMisses);
-  }
-  std::fprintf(stderr, "\n");
-  dump();
-  std::fprintf(stderr, "\n");
-}
-
-template<typename Key, typename ModuleFile, unsigned InitialCapacity>
-static void 
-dumpModuleIDMap(StringRef Name,
-                const ContinuousRangeMap<Key, ModuleFile *, 
-                                         InitialCapacity> &Map) {
-  if (Map.begin() == Map.end())
-    return;
-  
-  typedef ContinuousRangeMap<Key, ModuleFile *, InitialCapacity> MapType;
-  llvm::errs() << Name << ":\n";
-  for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end(); 
-       I != IEnd; ++I) {
-    llvm::errs() << "  " << I->first << " -> " << I->second->FileName
-      << "\n";
-  }
-}
-
-void ASTReader::dump() {
-  llvm::errs() << "*** PCH/ModuleFile Remappings:\n";
-  dumpModuleIDMap("Global bit offset map", GlobalBitOffsetsMap);
-  dumpModuleIDMap("Global source location entry map", GlobalSLocEntryMap);
-  dumpModuleIDMap("Global type map", GlobalTypeMap);
-  dumpModuleIDMap("Global declaration map", GlobalDeclMap);
-  dumpModuleIDMap("Global identifier map", GlobalIdentifierMap);
-  dumpModuleIDMap("Global macro map", GlobalMacroMap);
-  dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap);
-  dumpModuleIDMap("Global selector map", GlobalSelectorMap);
-  dumpModuleIDMap("Global preprocessed entity map", 
-                  GlobalPreprocessedEntityMap);
-  
-  llvm::errs() << "\n*** PCH/Modules Loaded:";
-  for (ModuleManager::ModuleConstIterator M = ModuleMgr.begin(), 
-                                       MEnd = ModuleMgr.end();
-       M != MEnd; ++M)
-    (*M)->dump();
-}
-
-/// Return the amount of memory used by memory buffers, breaking down
-/// by heap-backed versus mmap'ed memory.
-void ASTReader::getMemoryBufferSizes(MemoryBufferSizes &sizes) const {
-  for (ModuleConstIterator I = ModuleMgr.begin(),
-      E = ModuleMgr.end(); I != E; ++I) {
-    if (llvm::MemoryBuffer *buf = (*I)->Buffer.get()) {
-      size_t bytes = buf->getBufferSize();
-      switch (buf->getBufferKind()) {
-        case llvm::MemoryBuffer::MemoryBuffer_Malloc:
-          sizes.malloc_bytes += bytes;
-          break;
-        case llvm::MemoryBuffer::MemoryBuffer_MMap:
-          sizes.mmap_bytes += bytes;
-          break;
-      }
-    }
-  }
-}
-
-void ASTReader::InitializeSema(Sema &S) {
-  SemaObj = &S;
-  S.addExternalSource(this);
-
-  // Makes sure any declarations that were deserialized "too early"
-  // still get added to the identifier's declaration chains.
-  for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
-    SemaObj->pushExternalDeclIntoScope(PreloadedDecls[I], 
-                                       PreloadedDecls[I]->getDeclName());
-  }
-  PreloadedDecls.clear();
-
-  // Load the offsets of the declarations that Sema references.
-  // They will be lazily deserialized when needed.
-  if (!SemaDeclRefs.empty()) {
-    assert(SemaDeclRefs.size() == 2 && "More decl refs than expected!");
-    if (!SemaObj->StdNamespace)
-      SemaObj->StdNamespace = SemaDeclRefs[0];
-    if (!SemaObj->StdBadAlloc)
-      SemaObj->StdBadAlloc = SemaDeclRefs[1];
-  }
-
-  if (!FPPragmaOptions.empty()) {
-    assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS");
-    SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0];
-  }
-
-  if (!OpenCLExtensions.empty()) {
-    unsigned I = 0;
-#define OPENCLEXT(nm)  SemaObj->OpenCLFeatures.nm = OpenCLExtensions[I++];
-#include "clang/Basic/OpenCLExtensions.def"
-
-    assert(OpenCLExtensions.size() == I && "Wrong number of OPENCL_EXTENSIONS");
-  }
-}
-
-IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
-  // Note that we are loading an identifier.
-  Deserializing AnIdentifier(this);
-  
-  IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart),
-                                  /*PriorGeneration=*/0);
-  ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
-  IdentifierInfo *II = Visitor.getIdentifierInfo();
-  markIdentifierUpToDate(II);
-  return II;
-}
-
-namespace clang {
-  /// \brief An identifier-lookup iterator that enumerates all of the
-  /// identifiers stored within a set of AST files.
-  class ASTIdentifierIterator : public IdentifierIterator {
-    /// \brief The AST reader whose identifiers are being enumerated.
-    const ASTReader &Reader;
-
-    /// \brief The current index into the chain of AST files stored in
-    /// the AST reader.
-    unsigned Index;
-
-    /// \brief The current position within the identifier lookup table
-    /// of the current AST file.
-    ASTIdentifierLookupTable::key_iterator Current;
-
-    /// \brief The end position within the identifier lookup table of
-    /// the current AST file.
-    ASTIdentifierLookupTable::key_iterator End;
-
-  public:
-    explicit ASTIdentifierIterator(const ASTReader &Reader);
-
-    virtual StringRef Next();
-  };
-}
-
-ASTIdentifierIterator::ASTIdentifierIterator(const ASTReader &Reader)
-  : Reader(Reader), Index(Reader.ModuleMgr.size() - 1) {
-  ASTIdentifierLookupTable *IdTable
-    = (ASTIdentifierLookupTable *)Reader.ModuleMgr[Index].IdentifierLookupTable;
-  Current = IdTable->key_begin();
-  End = IdTable->key_end();
-}
-
-StringRef ASTIdentifierIterator::Next() {
-  while (Current == End) {
-    // If we have exhausted all of our AST files, we're done.
-    if (Index == 0)
-      return StringRef();
-
-    --Index;
-    ASTIdentifierLookupTable *IdTable
-      = (ASTIdentifierLookupTable *)Reader.ModuleMgr[Index].
-        IdentifierLookupTable;
-    Current = IdTable->key_begin();
-    End = IdTable->key_end();
-  }
-
-  // We have any identifiers remaining in the current AST file; return
-  // the next one.
-  std::pair<const char*, unsigned> Key = *Current;
-  ++Current;
-  return StringRef(Key.first, Key.second);
-}
-
-IdentifierIterator *ASTReader::getIdentifiers() const {
-  return new ASTIdentifierIterator(*this);
-}
-
-namespace clang { namespace serialization {
-  class ReadMethodPoolVisitor {
-    ASTReader &Reader;
-    Selector Sel;
-    unsigned PriorGeneration;
-    llvm::SmallVector<ObjCMethodDecl *, 4> InstanceMethods;
-    llvm::SmallVector<ObjCMethodDecl *, 4> FactoryMethods;
-
-  public:
-    ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel, 
-                          unsigned PriorGeneration)
-      : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration) { }
-    
-    static bool visit(ModuleFile &M, void *UserData) {
-      ReadMethodPoolVisitor *This
-        = static_cast<ReadMethodPoolVisitor *>(UserData);
-      
-      if (!M.SelectorLookupTable)
-        return false;
-      
-      // If we've already searched this module file, skip it now.
-      if (M.Generation <= This->PriorGeneration)
-        return true;
-
-      ASTSelectorLookupTable *PoolTable
-        = (ASTSelectorLookupTable*)M.SelectorLookupTable;
-      ASTSelectorLookupTable::iterator Pos = PoolTable->find(This->Sel);
-      if (Pos == PoolTable->end())
-        return false;
-      
-      ++This->Reader.NumSelectorsRead;
-      // FIXME: Not quite happy with the statistics here. We probably should
-      // disable this tracking when called via LoadSelector.
-      // Also, should entries without methods count as misses?
-      ++This->Reader.NumMethodPoolEntriesRead;
-      ASTSelectorLookupTrait::data_type Data = *Pos;
-      if (This->Reader.DeserializationListener)
-        This->Reader.DeserializationListener->SelectorRead(Data.ID, 
-                                                           This->Sel);
-      
-      This->InstanceMethods.append(Data.Instance.begin(), Data.Instance.end());
-      This->FactoryMethods.append(Data.Factory.begin(), Data.Factory.end());
-      return true;
-    }
-    
-    /// \brief Retrieve the instance methods found by this visitor.
-    ArrayRef<ObjCMethodDecl *> getInstanceMethods() const { 
-      return InstanceMethods; 
-    }
-
-    /// \brief Retrieve the instance methods found by this visitor.
-    ArrayRef<ObjCMethodDecl *> getFactoryMethods() const { 
-      return FactoryMethods;
-    }
-  };
-} } // end namespace clang::serialization
-
-/// \brief Add the given set of methods to the method list.
-static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods,
-                             ObjCMethodList &List) {
-  for (unsigned I = 0, N = Methods.size(); I != N; ++I) {
-    S.addMethodToGlobalList(&List, Methods[I]);
-  }
-}
-                             
-void ASTReader::ReadMethodPool(Selector Sel) {
-  // Get the selector generation and update it to the current generation.
-  unsigned &Generation = SelectorGeneration[Sel];
-  unsigned PriorGeneration = Generation;
-  Generation = CurrentGeneration;
-  
-  // Search for methods defined with this selector.
-  ReadMethodPoolVisitor Visitor(*this, Sel, PriorGeneration);
-  ModuleMgr.visit(&ReadMethodPoolVisitor::visit, &Visitor);
-  
-  if (Visitor.getInstanceMethods().empty() &&
-      Visitor.getFactoryMethods().empty()) {
-    ++NumMethodPoolMisses;
-    return;
-  }
-  
-  if (!getSema())
-    return;
-  
-  Sema &S = *getSema();
-  Sema::GlobalMethodPool::iterator Pos
-    = S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethods())).first;
-  
-  addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first);
-  addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second);
-}
-
-void ASTReader::ReadKnownNamespaces(
-                          SmallVectorImpl<NamespaceDecl *> &Namespaces) {
-  Namespaces.clear();
-  
-  for (unsigned I = 0, N = KnownNamespaces.size(); I != N; ++I) {
-    if (NamespaceDecl *Namespace 
-                = dyn_cast_or_null<NamespaceDecl>(GetDecl(KnownNamespaces[I])))
-      Namespaces.push_back(Namespace);
-  }
-}
-
-void ASTReader::ReadTentativeDefinitions(
-                  SmallVectorImpl<VarDecl *> &TentativeDefs) {
-  for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
-    VarDecl *Var = dyn_cast_or_null<VarDecl>(GetDecl(TentativeDefinitions[I]));
-    if (Var)
-      TentativeDefs.push_back(Var);
-  }
-  TentativeDefinitions.clear();
-}
-
-void ASTReader::ReadUnusedFileScopedDecls(
-                               SmallVectorImpl<const DeclaratorDecl *> &Decls) {
-  for (unsigned I = 0, N = UnusedFileScopedDecls.size(); I != N; ++I) {
-    DeclaratorDecl *D
-      = dyn_cast_or_null<DeclaratorDecl>(GetDecl(UnusedFileScopedDecls[I]));
-    if (D)
-      Decls.push_back(D);
-  }
-  UnusedFileScopedDecls.clear();
-}
-
-void ASTReader::ReadDelegatingConstructors(
-                                 SmallVectorImpl<CXXConstructorDecl *> &Decls) {
-  for (unsigned I = 0, N = DelegatingCtorDecls.size(); I != N; ++I) {
-    CXXConstructorDecl *D
-      = dyn_cast_or_null<CXXConstructorDecl>(GetDecl(DelegatingCtorDecls[I]));
-    if (D)
-      Decls.push_back(D);
-  }
-  DelegatingCtorDecls.clear();
-}
-
-void ASTReader::ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {
-  for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) {
-    TypedefNameDecl *D
-      = dyn_cast_or_null<TypedefNameDecl>(GetDecl(ExtVectorDecls[I]));
-    if (D)
-      Decls.push_back(D);
-  }
-  ExtVectorDecls.clear();
-}
-
-void ASTReader::ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) {
-  for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) {
-    CXXRecordDecl *D
-      = dyn_cast_or_null<CXXRecordDecl>(GetDecl(DynamicClasses[I]));
-    if (D)
-      Decls.push_back(D);
-  }
-  DynamicClasses.clear();
-}
-
-void 
-ASTReader::ReadLocallyScopedExternalDecls(SmallVectorImpl<NamedDecl *> &Decls) {
-  for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
-    NamedDecl *D 
-      = dyn_cast_or_null<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
-    if (D)
-      Decls.push_back(D);
-  }
-  LocallyScopedExternalDecls.clear();
-}
-
-void ASTReader::ReadReferencedSelectors(
-       SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {
-  if (ReferencedSelectorsData.empty())
-    return;
-  
-  // If there are @selector references added them to its pool. This is for
-  // implementation of -Wselector.
-  unsigned int DataSize = ReferencedSelectorsData.size()-1;
-  unsigned I = 0;
-  while (I < DataSize) {
-    Selector Sel = DecodeSelector(ReferencedSelectorsData[I++]);
-    SourceLocation SelLoc
-      = SourceLocation::getFromRawEncoding(ReferencedSelectorsData[I++]);
-    Sels.push_back(std::make_pair(Sel, SelLoc));
-  }
-  ReferencedSelectorsData.clear();
-}
-
-void ASTReader::ReadWeakUndeclaredIdentifiers(
-       SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WeakIDs) {
-  if (WeakUndeclaredIdentifiers.empty())
-    return;
-
-  for (unsigned I = 0, N = WeakUndeclaredIdentifiers.size(); I < N; /*none*/) {
-    IdentifierInfo *WeakId 
-      = DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]);
-    IdentifierInfo *AliasId 
-      = DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]);
-    SourceLocation Loc
-      = SourceLocation::getFromRawEncoding(WeakUndeclaredIdentifiers[I++]);
-    bool Used = WeakUndeclaredIdentifiers[I++];
-    WeakInfo WI(AliasId, Loc);
-    WI.setUsed(Used);
-    WeakIDs.push_back(std::make_pair(WeakId, WI));
-  }
-  WeakUndeclaredIdentifiers.clear();
-}
-
-void ASTReader::ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {
-  for (unsigned Idx = 0, N = VTableUses.size(); Idx < N; /* In loop */) {
-    ExternalVTableUse VT;
-    VT.Record = dyn_cast_or_null<CXXRecordDecl>(GetDecl(VTableUses[Idx++]));
-    VT.Location = SourceLocation::getFromRawEncoding(VTableUses[Idx++]);
-    VT.DefinitionRequired = VTableUses[Idx++];
-    VTables.push_back(VT);
-  }
-  
-  VTableUses.clear();
-}
-
-void ASTReader::ReadPendingInstantiations(
-       SmallVectorImpl<std::pair<ValueDecl *, SourceLocation> > &Pending) {
-  for (unsigned Idx = 0, N = PendingInstantiations.size(); Idx < N;) {
-    ValueDecl *D = cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++]));
-    SourceLocation Loc
-      = SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]);
-
-    Pending.push_back(std::make_pair(D, Loc));
-  }  
-  PendingInstantiations.clear();
-}
-
-void ASTReader::LoadSelector(Selector Sel) {
-  // It would be complicated to avoid reading the methods anyway. So don't.
-  ReadMethodPool(Sel);
-}
-
-void ASTReader::SetIdentifierInfo(IdentifierID ID, IdentifierInfo *II) {
-  assert(ID && "Non-zero identifier ID required");
-  assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
-  IdentifiersLoaded[ID - 1] = II;
-  if (DeserializationListener)
-    DeserializationListener->IdentifierRead(ID, II);
-}
-
-/// \brief Set the globally-visible declarations associated with the given
-/// identifier.
-///
-/// If the AST reader is currently in a state where the given declaration IDs
-/// cannot safely be resolved, they are queued until it is safe to resolve
-/// them.
-///
-/// \param II an IdentifierInfo that refers to one or more globally-visible
-/// declarations.
-///
-/// \param DeclIDs the set of declaration IDs with the name @p II that are
-/// visible at global scope.
-///
-/// \param Nonrecursive should be true to indicate that the caller knows that
-/// this call is non-recursive, and therefore the globally-visible declarations
-/// will not be placed onto the pending queue.
-void
-ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II,
-                              const SmallVectorImpl<uint32_t> &DeclIDs,
-                                   bool Nonrecursive) {
-  if (NumCurrentElementsDeserializing && !Nonrecursive) {
-    PendingIdentifierInfos.push_back(PendingIdentifierInfo());
-    PendingIdentifierInfo &PII = PendingIdentifierInfos.back();
-    PII.II = II;
-    PII.DeclIDs.append(DeclIDs.begin(), DeclIDs.end());
-    return;
-  }
-
-  for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
-    NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
-    if (SemaObj) {
-      // Introduce this declaration into the translation-unit scope
-      // and add it to the declaration chain for this identifier, so
-      // that (unqualified) name lookup will find it.
-      SemaObj->pushExternalDeclIntoScope(D, II);
-    } else {
-      // Queue this declaration so that it will be added to the
-      // translation unit scope and identifier's declaration chain
-      // once a Sema object is known.
-      PreloadedDecls.push_back(D);
-    }
-  }
-}
-
-IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) {
-  if (ID == 0)
-    return 0;
-
-  if (IdentifiersLoaded.empty()) {
-    Error("no identifier table in AST file");
-    return 0;
-  }
-
-  ID -= 1;
-  if (!IdentifiersLoaded[ID]) {
-    GlobalIdentifierMapType::iterator I = GlobalIdentifierMap.find(ID + 1);
-    assert(I != GlobalIdentifierMap.end() && "Corrupted global identifier map");
-    ModuleFile *M = I->second;
-    unsigned Index = ID - M->BaseIdentifierID;
-    const char *Str = M->IdentifierTableData + M->IdentifierOffsets[Index];
-
-    // All of the strings in the AST file are preceded by a 16-bit length.
-    // Extract that 16-bit length to avoid having to execute strlen().
-    // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
-    //  unsigned integers.  This is important to avoid integer overflow when
-    //  we cast them to 'unsigned'.
-    const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
-    unsigned StrLen = (((unsigned) StrLenPtr[0])
-                       | (((unsigned) StrLenPtr[1]) << 8)) - 1;
-    IdentifiersLoaded[ID]
-      = &PP.getIdentifierTable().get(StringRef(Str, StrLen));
-    if (DeserializationListener)
-      DeserializationListener->IdentifierRead(ID + 1, IdentifiersLoaded[ID]);
-  }
-
-  return IdentifiersLoaded[ID];
-}
-
-IdentifierInfo *ASTReader::getLocalIdentifier(ModuleFile &M, unsigned LocalID) {
-  return DecodeIdentifierInfo(getGlobalIdentifierID(M, LocalID));
-}
-
-IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) {
-  if (LocalID < NUM_PREDEF_IDENT_IDS)
-    return LocalID;
-  
-  ContinuousRangeMap<uint32_t, int, 2>::iterator I
-    = M.IdentifierRemap.find(LocalID - NUM_PREDEF_IDENT_IDS);
-  assert(I != M.IdentifierRemap.end() 
-         && "Invalid index into identifier index remap");
-  
-  return LocalID + I->second;
-}
-
-MacroInfo *ASTReader::getMacro(MacroID ID, MacroInfo *Hint) {
-  if (ID == 0)
-    return 0;
-
-  if (MacrosLoaded.empty()) {
-    Error("no macro table in AST file");
-    return 0;
-  }
-
-  ID -= NUM_PREDEF_MACRO_IDS;
-  if (!MacrosLoaded[ID]) {
-    GlobalMacroMapType::iterator I
-      = GlobalMacroMap.find(ID + NUM_PREDEF_MACRO_IDS);
-    assert(I != GlobalMacroMap.end() && "Corrupted global macro map");
-    ModuleFile *M = I->second;
-    unsigned Index = ID - M->BaseMacroID;
-    ReadMacroRecord(*M, M->MacroOffsets[Index], Hint);
-  }
-
-  return MacrosLoaded[ID];
-}
-
-MacroID ASTReader::getGlobalMacroID(ModuleFile &M, unsigned LocalID) {
-  if (LocalID < NUM_PREDEF_MACRO_IDS)
-    return LocalID;
-
-  ContinuousRangeMap<uint32_t, int, 2>::iterator I
-    = M.MacroRemap.find(LocalID - NUM_PREDEF_MACRO_IDS);
-  assert(I != M.MacroRemap.end() && "Invalid index into macro index remap");
-
-  return LocalID + I->second;
-}
-
-serialization::SubmoduleID
-ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) {
-  if (LocalID < NUM_PREDEF_SUBMODULE_IDS)
-    return LocalID;
-  
-  ContinuousRangeMap<uint32_t, int, 2>::iterator I
-    = M.SubmoduleRemap.find(LocalID - NUM_PREDEF_SUBMODULE_IDS);
-  assert(I != M.SubmoduleRemap.end() 
-         && "Invalid index into submodule index remap");
-  
-  return LocalID + I->second;
-}
-
-Module *ASTReader::getSubmodule(SubmoduleID GlobalID) {
-  if (GlobalID < NUM_PREDEF_SUBMODULE_IDS) {
-    assert(GlobalID == 0 && "Unhandled global submodule ID");
-    return 0;
-  }
-  
-  if (GlobalID > SubmodulesLoaded.size()) {
-    Error("submodule ID out of range in AST file");
-    return 0;
-  }
-  
-  return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS];
-}
-                               
-Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) {
-  return DecodeSelector(getGlobalSelectorID(M, LocalID));
-}
-
-Selector ASTReader::DecodeSelector(serialization::SelectorID ID) {
-  if (ID == 0)
-    return Selector();
-
-  if (ID > SelectorsLoaded.size()) {
-    Error("selector ID out of range in AST file");
-    return Selector();
-  }
-
-  if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) {
-    // Load this selector from the selector table.
-    GlobalSelectorMapType::iterator I = GlobalSelectorMap.find(ID);
-    assert(I != GlobalSelectorMap.end() && "Corrupted global selector map");
-    ModuleFile &M = *I->second;
-    ASTSelectorLookupTrait Trait(*this, M);
-    unsigned Idx = ID - M.BaseSelectorID - NUM_PREDEF_SELECTOR_IDS;
-    SelectorsLoaded[ID - 1] =
-      Trait.ReadKey(M.SelectorLookupTableData + M.SelectorOffsets[Idx], 0);
-    if (DeserializationListener)
-      DeserializationListener->SelectorRead(ID, SelectorsLoaded[ID - 1]);
-  }
-
-  return SelectorsLoaded[ID - 1];
-}
-
-Selector ASTReader::GetExternalSelector(serialization::SelectorID ID) {
-  return DecodeSelector(ID);
-}
-
-uint32_t ASTReader::GetNumExternalSelectors() {
-  // ID 0 (the null selector) is considered an external selector.
-  return getTotalNumSelectors() + 1;
-}
-
-serialization::SelectorID
-ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const {
-  if (LocalID < NUM_PREDEF_SELECTOR_IDS)
-    return LocalID;
-  
-  ContinuousRangeMap<uint32_t, int, 2>::iterator I
-    = M.SelectorRemap.find(LocalID - NUM_PREDEF_SELECTOR_IDS);
-  assert(I != M.SelectorRemap.end() 
-         && "Invalid index into selector index remap");
-  
-  return LocalID + I->second;
-}
-
-DeclarationName
-ASTReader::ReadDeclarationName(ModuleFile &F, 
-                               const RecordData &Record, unsigned &Idx) {
-  DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
-  switch (Kind) {
-  case DeclarationName::Identifier:
-    return DeclarationName(GetIdentifierInfo(F, Record, Idx));
-
-  case DeclarationName::ObjCZeroArgSelector:
-  case DeclarationName::ObjCOneArgSelector:
-  case DeclarationName::ObjCMultiArgSelector:
-    return DeclarationName(ReadSelector(F, Record, Idx));
-
-  case DeclarationName::CXXConstructorName:
-    return Context.DeclarationNames.getCXXConstructorName(
-                          Context.getCanonicalType(readType(F, Record, Idx)));
-
-  case DeclarationName::CXXDestructorName:
-    return Context.DeclarationNames.getCXXDestructorName(
-                          Context.getCanonicalType(readType(F, Record, Idx)));
-
-  case DeclarationName::CXXConversionFunctionName:
-    return Context.DeclarationNames.getCXXConversionFunctionName(
-                          Context.getCanonicalType(readType(F, Record, Idx)));
-
-  case DeclarationName::CXXOperatorName:
-    return Context.DeclarationNames.getCXXOperatorName(
-                                       (OverloadedOperatorKind)Record[Idx++]);
-
-  case DeclarationName::CXXLiteralOperatorName:
-    return Context.DeclarationNames.getCXXLiteralOperatorName(
-                                       GetIdentifierInfo(F, Record, Idx));
-
-  case DeclarationName::CXXUsingDirective:
-    return DeclarationName::getUsingDirectiveName();
-  }
-
-  llvm_unreachable("Invalid NameKind!");
-}
-
-void ASTReader::ReadDeclarationNameLoc(ModuleFile &F,
-                                       DeclarationNameLoc &DNLoc,
-                                       DeclarationName Name,
-                                      const RecordData &Record, unsigned &Idx) {
-  switch (Name.getNameKind()) {
-  case DeclarationName::CXXConstructorName:
-  case DeclarationName::CXXDestructorName:
-  case DeclarationName::CXXConversionFunctionName:
-    DNLoc.NamedType.TInfo = GetTypeSourceInfo(F, Record, Idx);
-    break;
-
-  case DeclarationName::CXXOperatorName:
-    DNLoc.CXXOperatorName.BeginOpNameLoc
-        = ReadSourceLocation(F, Record, Idx).getRawEncoding();
-    DNLoc.CXXOperatorName.EndOpNameLoc
-        = ReadSourceLocation(F, Record, Idx).getRawEncoding();
-    break;
-
-  case DeclarationName::CXXLiteralOperatorName:
-    DNLoc.CXXLiteralOperatorName.OpNameLoc
-        = ReadSourceLocation(F, Record, Idx).getRawEncoding();
-    break;
-
-  case DeclarationName::Identifier:
-  case DeclarationName::ObjCZeroArgSelector:
-  case DeclarationName::ObjCOneArgSelector:
-  case DeclarationName::ObjCMultiArgSelector:
-  case DeclarationName::CXXUsingDirective:
-    break;
-  }
-}
-
-void ASTReader::ReadDeclarationNameInfo(ModuleFile &F,
-                                        DeclarationNameInfo &NameInfo,
-                                      const RecordData &Record, unsigned &Idx) {
-  NameInfo.setName(ReadDeclarationName(F, Record, Idx));
-  NameInfo.setLoc(ReadSourceLocation(F, Record, Idx));
-  DeclarationNameLoc DNLoc;
-  ReadDeclarationNameLoc(F, DNLoc, NameInfo.getName(), Record, Idx);
-  NameInfo.setInfo(DNLoc);
-}
-
-void ASTReader::ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info,
-                                  const RecordData &Record, unsigned &Idx) {
-  Info.QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx);
-  unsigned NumTPLists = Record[Idx++];
-  Info.NumTemplParamLists = NumTPLists;
-  if (NumTPLists) {
-    Info.TemplParamLists = new (Context) TemplateParameterList*[NumTPLists];
-    for (unsigned i=0; i != NumTPLists; ++i)
-      Info.TemplParamLists[i] = ReadTemplateParameterList(F, Record, Idx);
-  }
-}
-
-TemplateName
-ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record, 
-                            unsigned &Idx) {
-  TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++];
-  switch (Kind) {
-  case TemplateName::Template:
-      return TemplateName(ReadDeclAs<TemplateDecl>(F, Record, Idx));
-
-  case TemplateName::OverloadedTemplate: {
-    unsigned size = Record[Idx++];
-    UnresolvedSet<8> Decls;
-    while (size--)
-      Decls.addDecl(ReadDeclAs<NamedDecl>(F, Record, Idx));
-
-    return Context.getOverloadedTemplateName(Decls.begin(), Decls.end());
-  }
-
-  case TemplateName::QualifiedTemplate: {
-    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx);
-    bool hasTemplKeyword = Record[Idx++];
-    TemplateDecl *Template = ReadDeclAs<TemplateDecl>(F, Record, Idx);
-    return Context.getQualifiedTemplateName(NNS, hasTemplKeyword, Template);
-  }
-
-  case TemplateName::DependentTemplate: {
-    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx);
-    if (Record[Idx++])  // isIdentifier
-      return Context.getDependentTemplateName(NNS,
-                                               GetIdentifierInfo(F, Record, 
-                                                                 Idx));
-    return Context.getDependentTemplateName(NNS,
-                                         (OverloadedOperatorKind)Record[Idx++]);
-  }
-
-  case TemplateName::SubstTemplateTemplateParm: {
-    TemplateTemplateParmDecl *param
-      = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx);
-    if (!param) return TemplateName();
-    TemplateName replacement = ReadTemplateName(F, Record, Idx);
-    return Context.getSubstTemplateTemplateParm(param, replacement);
-  }
-      
-  case TemplateName::SubstTemplateTemplateParmPack: {
-    TemplateTemplateParmDecl *Param 
-      = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx);
-    if (!Param)
-      return TemplateName();
-    
-    TemplateArgument ArgPack = ReadTemplateArgument(F, Record, Idx);
-    if (ArgPack.getKind() != TemplateArgument::Pack)
-      return TemplateName();
-    
-    return Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
-  }
-  }
-
-  llvm_unreachable("Unhandled template name kind!");
-}
-
-TemplateArgument
-ASTReader::ReadTemplateArgument(ModuleFile &F,
-                                const RecordData &Record, unsigned &Idx) {
-  TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];
-  switch (Kind) {
-  case TemplateArgument::Null:
-    return TemplateArgument();
-  case TemplateArgument::Type:
-    return TemplateArgument(readType(F, Record, Idx));
-  case TemplateArgument::Declaration: {
-    ValueDecl *D = ReadDeclAs<ValueDecl>(F, Record, Idx);
-    bool ForReferenceParam = Record[Idx++];
-    return TemplateArgument(D, ForReferenceParam);
-  }
-  case TemplateArgument::NullPtr:
-    return TemplateArgument(readType(F, Record, Idx), /*isNullPtr*/true);
-  case TemplateArgument::Integral: {
-    llvm::APSInt Value = ReadAPSInt(Record, Idx);
-    QualType T = readType(F, Record, Idx);
-    return TemplateArgument(Context, Value, T);
-  }
-  case TemplateArgument::Template: 
-    return TemplateArgument(ReadTemplateName(F, Record, Idx));
-  case TemplateArgument::TemplateExpansion: {
-    TemplateName Name = ReadTemplateName(F, Record, Idx);
-    llvm::Optional<unsigned> NumTemplateExpansions;
-    if (unsigned NumExpansions = Record[Idx++])
-      NumTemplateExpansions = NumExpansions - 1;
-    return TemplateArgument(Name, NumTemplateExpansions);
-  }
-  case TemplateArgument::Expression:
-    return TemplateArgument(ReadExpr(F));
-  case TemplateArgument::Pack: {
-    unsigned NumArgs = Record[Idx++];
-    TemplateArgument *Args = new (Context) TemplateArgument[NumArgs];
-    for (unsigned I = 0; I != NumArgs; ++I)
-      Args[I] = ReadTemplateArgument(F, Record, Idx);
-    return TemplateArgument(Args, NumArgs);
-  }
-  }
-
-  llvm_unreachable("Unhandled template argument kind!");
-}
-
-TemplateParameterList *
-ASTReader::ReadTemplateParameterList(ModuleFile &F,
-                                     const RecordData &Record, unsigned &Idx) {
-  SourceLocation TemplateLoc = ReadSourceLocation(F, Record, Idx);
-  SourceLocation LAngleLoc = ReadSourceLocation(F, Record, Idx);
-  SourceLocation RAngleLoc = ReadSourceLocation(F, Record, Idx);
-
-  unsigned NumParams = Record[Idx++];
-  SmallVector<NamedDecl *, 16> Params;
-  Params.reserve(NumParams);
-  while (NumParams--)
-    Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx));
-
-  TemplateParameterList* TemplateParams =
-    TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,
-                                  Params.data(), Params.size(), RAngleLoc);
-  return TemplateParams;
-}
-
-void
-ASTReader::
-ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs,
-                         ModuleFile &F, const RecordData &Record,
-                         unsigned &Idx) {
-  unsigned NumTemplateArgs = Record[Idx++];
-  TemplArgs.reserve(NumTemplateArgs);
-  while (NumTemplateArgs--)
-    TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx));
-}
-
-/// \brief Read a UnresolvedSet structure.
-void ASTReader::ReadUnresolvedSet(ModuleFile &F, ASTUnresolvedSet &Set,
-                                  const RecordData &Record, unsigned &Idx) {
-  unsigned NumDecls = Record[Idx++];
-  Set.reserve(Context, NumDecls);
-  while (NumDecls--) {
-    NamedDecl *D = ReadDeclAs<NamedDecl>(F, Record, Idx);
-    AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
-    Set.addDecl(Context, D, AS);
-  }
-}
-
-CXXBaseSpecifier
-ASTReader::ReadCXXBaseSpecifier(ModuleFile &F,
-                                const RecordData &Record, unsigned &Idx) {
-  bool isVirtual = static_cast<bool>(Record[Idx++]);
-  bool isBaseOfClass = static_cast<bool>(Record[Idx++]);
-  AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]);
-  bool inheritConstructors = static_cast<bool>(Record[Idx++]);
-  TypeSourceInfo *TInfo = GetTypeSourceInfo(F, Record, Idx);
-  SourceRange Range = ReadSourceRange(F, Record, Idx);
-  SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Idx);
-  CXXBaseSpecifier Result(Range, isVirtual, isBaseOfClass, AS, TInfo, 
-                          EllipsisLoc);
-  Result.setInheritConstructors(inheritConstructors);
-  return Result;
-}
-
-std::pair<CXXCtorInitializer **, unsigned>
-ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
-                                   unsigned &Idx) {
-  CXXCtorInitializer **CtorInitializers = 0;
-  unsigned NumInitializers = Record[Idx++];
-  if (NumInitializers) {
-    CtorInitializers
-        = new (Context) CXXCtorInitializer*[NumInitializers];
-    for (unsigned i=0; i != NumInitializers; ++i) {
-      TypeSourceInfo *TInfo = 0;
-      bool IsBaseVirtual = false;
-      FieldDecl *Member = 0;
-      IndirectFieldDecl *IndirectMember = 0;
-
-      CtorInitializerType Type = (CtorInitializerType)Record[Idx++];
-      switch (Type) {
-      case CTOR_INITIALIZER_BASE:
-        TInfo = GetTypeSourceInfo(F, Record, Idx);
-        IsBaseVirtual = Record[Idx++];
-        break;
-          
-      case CTOR_INITIALIZER_DELEGATING:
-        TInfo = GetTypeSourceInfo(F, Record, Idx);
-        break;
-
-       case CTOR_INITIALIZER_MEMBER:
-        Member = ReadDeclAs<FieldDecl>(F, Record, Idx);
-        break;
-
-       case CTOR_INITIALIZER_INDIRECT_MEMBER:
-        IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx);
-        break;
-      }
-
-      SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx);
-      Expr *Init = ReadExpr(F);
-      SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);
-      SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);
-      bool IsWritten = Record[Idx++];
-      unsigned SourceOrderOrNumArrayIndices;
-      SmallVector<VarDecl *, 8> Indices;
-      if (IsWritten) {
-        SourceOrderOrNumArrayIndices = Record[Idx++];
-      } else {
-        SourceOrderOrNumArrayIndices = Record[Idx++];
-        Indices.reserve(SourceOrderOrNumArrayIndices);
-        for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
-          Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx));
-      }
-
-      CXXCtorInitializer *BOMInit;
-      if (Type == CTOR_INITIALIZER_BASE) {
-        BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual,
-                                             LParenLoc, Init, RParenLoc,
-                                             MemberOrEllipsisLoc);
-      } else if (Type == CTOR_INITIALIZER_DELEGATING) {
-        BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc,
-                                                   Init, RParenLoc);
-      } else if (IsWritten) {
-        if (Member)
-          BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc,
-                                               LParenLoc, Init, RParenLoc);
-        else 
-          BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember,
-                                               MemberOrEllipsisLoc, LParenLoc,
-                                               Init, RParenLoc);
-      } else {
-        BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc,
-                                             LParenLoc, Init, RParenLoc,
-                                             Indices.data(), Indices.size());
-      }
-
-      if (IsWritten)
-        BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);
-      CtorInitializers[i] = BOMInit;
-    }
-  }
-
-  return std::make_pair(CtorInitializers, NumInitializers);
-}
-
-NestedNameSpecifier *
-ASTReader::ReadNestedNameSpecifier(ModuleFile &F,
-                                   const RecordData &Record, unsigned &Idx) {
-  unsigned N = Record[Idx++];
-  NestedNameSpecifier *NNS = 0, *Prev = 0;
-  for (unsigned I = 0; I != N; ++I) {
-    NestedNameSpecifier::SpecifierKind Kind
-      = (NestedNameSpecifier::SpecifierKind)Record[Idx++];
-    switch (Kind) {
-    case NestedNameSpecifier::Identifier: {
-      IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx);
-      NNS = NestedNameSpecifier::Create(Context, Prev, II);
-      break;
-    }
-
-    case NestedNameSpecifier::Namespace: {
-      NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx);
-      NNS = NestedNameSpecifier::Create(Context, Prev, NS);
-      break;
-    }
-
-    case NestedNameSpecifier::NamespaceAlias: {
-      NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx);
-      NNS = NestedNameSpecifier::Create(Context, Prev, Alias);
-      break;
-    }
-
-    case NestedNameSpecifier::TypeSpec:
-    case NestedNameSpecifier::TypeSpecWithTemplate: {
-      const Type *T = readType(F, Record, Idx).getTypePtrOrNull();
-      if (!T)
-        return 0;
-      
-      bool Template = Record[Idx++];
-      NNS = NestedNameSpecifier::Create(Context, Prev, Template, T);
-      break;
-    }
-
-    case NestedNameSpecifier::Global: {
-      NNS = NestedNameSpecifier::GlobalSpecifier(Context);
-      // No associated value, and there can't be a prefix.
-      break;
-    }
-    }
-    Prev = NNS;
-  }
-  return NNS;
-}
-
-NestedNameSpecifierLoc
-ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record, 
-                                      unsigned &Idx) {
-  unsigned N = Record[Idx++];
-  NestedNameSpecifierLocBuilder Builder;
-  for (unsigned I = 0; I != N; ++I) {
-    NestedNameSpecifier::SpecifierKind Kind
-      = (NestedNameSpecifier::SpecifierKind)Record[Idx++];
-    switch (Kind) {
-    case NestedNameSpecifier::Identifier: {
-      IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx);      
-      SourceRange Range = ReadSourceRange(F, Record, Idx);
-      Builder.Extend(Context, II, Range.getBegin(), Range.getEnd());
-      break;
-    }
-
-    case NestedNameSpecifier::Namespace: {
-      NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx);
-      SourceRange Range = ReadSourceRange(F, Record, Idx);
-      Builder.Extend(Context, NS, Range.getBegin(), Range.getEnd());
-      break;
-    }
-
-    case NestedNameSpecifier::NamespaceAlias: {
-      NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx);
-      SourceRange Range = ReadSourceRange(F, Record, Idx);
-      Builder.Extend(Context, Alias, Range.getBegin(), Range.getEnd());
-      break;
-    }
-
-    case NestedNameSpecifier::TypeSpec:
-    case NestedNameSpecifier::TypeSpecWithTemplate: {
-      bool Template = Record[Idx++];
-      TypeSourceInfo *T = GetTypeSourceInfo(F, Record, Idx);
-      if (!T)
-        return NestedNameSpecifierLoc();
-      SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
-
-      // FIXME: 'template' keyword location not saved anywhere, so we fake it.
-      Builder.Extend(Context, 
-                     Template? T->getTypeLoc().getBeginLoc() : SourceLocation(),
-                     T->getTypeLoc(), ColonColonLoc);
-      break;
-    }
-
-    case NestedNameSpecifier::Global: {
-      SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
-      Builder.MakeGlobal(Context, ColonColonLoc);
-      break;
-    }
-    }
-  }
-  
-  return Builder.getWithLocInContext(Context);
-}
-
-SourceRange
-ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record,
-                           unsigned &Idx) {
-  SourceLocation beg = ReadSourceLocation(F, Record, Idx);
-  SourceLocation end = ReadSourceLocation(F, Record, Idx);
-  return SourceRange(beg, end);
-}
-
-/// \brief Read an integral value
-llvm::APInt ASTReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
-  unsigned BitWidth = Record[Idx++];
-  unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
-  llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
-  Idx += NumWords;
-  return Result;
-}
-
-/// \brief Read a signed integral value
-llvm::APSInt ASTReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
-  bool isUnsigned = Record[Idx++];
-  return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
-}
-
-/// \brief Read a floating-point value
-llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
-  return llvm::APFloat(ReadAPInt(Record, Idx));
-}
-
-// \brief Read a string
-std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) {
-  unsigned Len = Record[Idx++];
-  std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
-  Idx += Len;
-  return Result;
-}
-
-VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record, 
-                                         unsigned &Idx) {
-  unsigned Major = Record[Idx++];
-  unsigned Minor = Record[Idx++];
-  unsigned Subminor = Record[Idx++];
-  if (Minor == 0)
-    return VersionTuple(Major);
-  if (Subminor == 0)
-    return VersionTuple(Major, Minor - 1);
-  return VersionTuple(Major, Minor - 1, Subminor - 1);
-}
-
-CXXTemporary *ASTReader::ReadCXXTemporary(ModuleFile &F, 
-                                          const RecordData &Record,
-                                          unsigned &Idx) {
-  CXXDestructorDecl *Decl = ReadDeclAs<CXXDestructorDecl>(F, Record, Idx);
-  return CXXTemporary::Create(Context, Decl);
-}
-
-DiagnosticBuilder ASTReader::Diag(unsigned DiagID) {
-  return Diag(SourceLocation(), DiagID);
-}
-
-DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) {
-  return Diags.Report(Loc, DiagID);
-}
-
-/// \brief Retrieve the identifier table associated with the
-/// preprocessor.
-IdentifierTable &ASTReader::getIdentifierTable() {
-  return PP.getIdentifierTable();
-}
-
-/// \brief Record that the given ID maps to the given switch-case
-/// statement.
-void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
-  assert((*CurrSwitchCaseStmts)[ID] == 0 &&
-         "Already have a SwitchCase with this ID");
-  (*CurrSwitchCaseStmts)[ID] = SC;
-}
-
-/// \brief Retrieve the switch-case statement with the given ID.
-SwitchCase *ASTReader::getSwitchCaseWithID(unsigned ID) {
-  assert((*CurrSwitchCaseStmts)[ID] != 0 && "No SwitchCase with this ID");
-  return (*CurrSwitchCaseStmts)[ID];
-}
-
-void ASTReader::ClearSwitchCaseIDs() {
-  CurrSwitchCaseStmts->clear();
-}
-
-void ASTReader::ReadComments() {
-  std::vector<RawComment *> Comments;
-  for (SmallVectorImpl<std::pair<llvm::BitstreamCursor,
-                                 serialization::ModuleFile *> >::iterator
-       I = CommentsCursors.begin(),
-       E = CommentsCursors.end();
-       I != E; ++I) {
-    llvm::BitstreamCursor &Cursor = I->first;
-    serialization::ModuleFile &F = *I->second;
-    SavedStreamPosition SavedPosition(Cursor);
-
-    RecordData Record;
-    while (true) {
-      unsigned Code = Cursor.ReadCode();
-      if (Code == llvm::bitc::END_BLOCK)
-        break;
-
-      if (Code == llvm::bitc::ENTER_SUBBLOCK) {
-        // No known subblocks, always skip them.
-        Cursor.ReadSubBlockID();
-        if (Cursor.SkipBlock()) {
-          Error("malformed block record in AST file");
-          return;
-        }
-        continue;
-      }
-
-      if (Code == llvm::bitc::DEFINE_ABBREV) {
-        Cursor.ReadAbbrevRecord();
-        continue;
-      }
-
-      // Read a record.
-      Record.clear();
-      switch ((CommentRecordTypes) Cursor.ReadRecord(Code, Record)) {
-      case COMMENTS_RAW_COMMENT: {
-        unsigned Idx = 0;
-        SourceRange SR = ReadSourceRange(F, Record, Idx);
-        RawComment::CommentKind Kind =
-            (RawComment::CommentKind) Record[Idx++];
-        bool IsTrailingComment = Record[Idx++];
-        bool IsAlmostTrailingComment = Record[Idx++];
-        Comments.push_back(new (Context) RawComment(SR, Kind,
-                                                    IsTrailingComment,
-                                                    IsAlmostTrailingComment));
-        break;
-      }
-      }
-    }
-  }
-  Context.Comments.addCommentsToFront(Comments);
-}
-
-void ASTReader::finishPendingActions() {
-  while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() ||
-         !PendingMacroIDs.empty()) {
-    // If any identifiers with corresponding top-level declarations have
-    // been loaded, load those declarations now.
-    while (!PendingIdentifierInfos.empty()) {
-      SetGloballyVisibleDecls(PendingIdentifierInfos.front().II,
-                              PendingIdentifierInfos.front().DeclIDs, true);
-      PendingIdentifierInfos.pop_front();
-    }
-  
-    // Load pending declaration chains.
-    for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
-      loadPendingDeclChain(PendingDeclChains[I]);
-      PendingDeclChainsKnown.erase(PendingDeclChains[I]);
-    }
-    PendingDeclChains.clear();
-
-    // Load any pending macro definitions.
-    for (unsigned I = 0; I != PendingMacroIDs.size(); ++I) {
-      // FIXME: std::move here
-      SmallVector<MacroID, 2> GlobalIDs = PendingMacroIDs.begin()[I].second;
-      MacroInfo *Hint = 0;
-      for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx !=  NumIDs;
-           ++IDIdx) {
-        Hint = getMacro(GlobalIDs[IDIdx], Hint);
-      }
-    }
-    PendingMacroIDs.clear();
-  }
-  
-  // If we deserialized any C++ or Objective-C class definitions, any
-  // Objective-C protocol definitions, or any redeclarable templates, make sure
-  // that all redeclarations point to the definitions. Note that this can only 
-  // happen now, after the redeclaration chains have been fully wired.
-  for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
-                                           DEnd = PendingDefinitions.end();
-       D != DEnd; ++D) {
-    if (TagDecl *TD = dyn_cast<TagDecl>(*D)) {
-      if (const TagType *TagT = dyn_cast<TagType>(TD->TypeForDecl)) {
-        // Make sure that the TagType points at the definition.
-        const_cast<TagType*>(TagT)->decl = TD;
-      }
-      
-      if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) {
-        for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(),
-                                         REnd = RD->redecls_end();
-             R != REnd; ++R)
-          cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData;
-        
-      }
-
-      continue;
-    }
-    
-    if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) {
-      // Make sure that the ObjCInterfaceType points at the definition.
-      const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl))
-        ->Decl = ID;
-      
-      for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(),
-                                           REnd = ID->redecls_end();
-           R != REnd; ++R)
-        R->Data = ID->Data;
-      
-      continue;
-    }
-    
-    if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) {
-      for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(),
-                                          REnd = PD->redecls_end();
-           R != REnd; ++R)
-        R->Data = PD->Data;
-      
-      continue;
-    }
-    
-    RedeclarableTemplateDecl *RTD
-      = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl();
-    for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(),
-                                                REnd = RTD->redecls_end();
-         R != REnd; ++R)
-      R->Common = RTD->Common;
-  }
-  PendingDefinitions.clear();
-
-  // Load the bodies of any functions or methods we've encountered. We do
-  // this now (delayed) so that we can be sure that the declaration chains
-  // have been fully wired up.
-  for (PendingBodiesMap::iterator PB = PendingBodies.begin(),
-                               PBEnd = PendingBodies.end();
-       PB != PBEnd; ++PB) {
-    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PB->first)) {
-      // FIXME: Check for =delete/=default?
-      // FIXME: Complain about ODR violations here?
-      if (!getContext().getLangOpts().Modules || !FD->hasBody())
-        FD->setLazyBody(PB->second);
-      continue;
-    }
-
-    ObjCMethodDecl *MD = cast<ObjCMethodDecl>(PB->first);
-    if (!getContext().getLangOpts().Modules || !MD->hasBody())
-      MD->setLazyBody(PB->second);
-  }
-  PendingBodies.clear();
-}
-
-void ASTReader::FinishedDeserializing() {
-  assert(NumCurrentElementsDeserializing &&
-         "FinishedDeserializing not paired with StartedDeserializing");
-  if (NumCurrentElementsDeserializing == 1) {
-    // We decrease NumCurrentElementsDeserializing only after pending actions
-    // are finished, to avoid recursively re-calling finishPendingActions().
-    finishPendingActions();
-  }
-  --NumCurrentElementsDeserializing;
-
-  if (NumCurrentElementsDeserializing == 0 &&
-      Consumer && !PassingDeclsToConsumer) {
-    // Guard variable to avoid recursively redoing the process of passing
-    // decls to consumer.
-    SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer,
-                                                     true);
-
-    while (!InterestingDecls.empty()) {
-      // We are not in recursive loading, so it's safe to pass the "interesting"
-      // decls to the consumer.
-      Decl *D = InterestingDecls.front();
-      InterestingDecls.pop_front();
-      PassInterestingDeclToConsumer(D);
-    }
-  }
-}
-
-ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
-                     StringRef isysroot, bool DisableValidation,
-                     bool AllowASTWithCompilerErrors)
-  : Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
-    SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
-    Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context),
-    Consumer(0), ModuleMgr(PP.getFileManager()),
-    isysroot(isysroot), DisableValidation(DisableValidation),
-    AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), 
-    CurrentGeneration(0), CurrSwitchCaseStmts(&SwitchCaseStmts),
-    NumSLocEntriesRead(0), TotalNumSLocEntries(0), 
-    NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), 
-    TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), 
-    NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0), 
-    NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), 
-    NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
-    TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0),
-    PassingDeclsToConsumer(false),
-    NumCXXBaseSpecifiersLoaded(0)
-{
-  SourceMgr.setExternalSLocEntrySource(this);
-}
-
-ASTReader::~ASTReader() {
-  for (DeclContextVisibleUpdatesPending::iterator
-           I = PendingVisibleUpdates.begin(),
-           E = PendingVisibleUpdates.end();
-       I != E; ++I) {
-    for (DeclContextVisibleUpdates::iterator J = I->second.begin(),
-                                             F = I->second.end();
-         J != F; ++J)
-      delete J->first;
-  }
-}
+//===--- ASTReader.cpp - AST File Reader ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the ASTReader class, which reads AST files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Serialization/ASTReader.h"
+#include "ASTCommon.h"
+#include "ASTReaderInternals.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemStatCache.h"
+#include "clang/Basic/OnDiskHashTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceManagerInternals.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/Version.h"
+#include "clang/Basic/VersionTuple.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+#include "clang/Serialization/ModuleManager.h"
+#include "clang/Serialization/SerializationDiagnostic.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/system_error.h"
+#include <algorithm>
+#include <cstdio>
+#include <iterator>
+
+using namespace clang;
+using namespace clang::serialization;
+using namespace clang::serialization::reader;
+
+//===----------------------------------------------------------------------===//
+// PCH validator implementation
+//===----------------------------------------------------------------------===//
+
+ASTReaderListener::~ASTReaderListener() {}
+
+/// \brief Compare the given set of language options against an existing set of
+/// language options.
+///
+/// \param Diags If non-NULL, diagnostics will be emitted via this engine.
+///
+/// \returns true if the languagae options mis-match, false otherwise.
+static bool checkLanguageOptions(const LangOptions &LangOpts,
+                                 const LangOptions &ExistingLangOpts,
+                                 DiagnosticsEngine *Diags) {
+#define LANGOPT(Name, Bits, Default, Description)                 \
+  if (ExistingLangOpts.Name != LangOpts.Name) {                   \
+    if (Diags)                                                    \
+      Diags->Report(diag::err_pch_langopt_mismatch)               \
+        << Description << LangOpts.Name << ExistingLangOpts.Name; \
+    return true;                                                  \
+  }
+
+#define VALUE_LANGOPT(Name, Bits, Default, Description)   \
+  if (ExistingLangOpts.Name != LangOpts.Name) {           \
+    if (Diags)                                            \
+      Diags->Report(diag::err_pch_langopt_value_mismatch) \
+        << Description;                                   \
+    return true;                                          \
+  }
+
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)   \
+  if (ExistingLangOpts.get##Name() != LangOpts.get##Name()) {  \
+    if (Diags)                                                 \
+      Diags->Report(diag::err_pch_langopt_value_mismatch)      \
+        << Description;                                        \
+    return true;                                               \
+  }
+
+#define BENIGN_LANGOPT(Name, Bits, Default, Description)
+#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
+#include "clang/Basic/LangOptions.def"
+
+  if (ExistingLangOpts.ObjCRuntime != LangOpts.ObjCRuntime) {
+    if (Diags)
+      Diags->Report(diag::err_pch_langopt_value_mismatch)
+      << "target Objective-C runtime";
+    return true;
+  }
+
+  return false;
+}
+
+/// \brief Compare the given set of target options against an existing set of
+/// target options.
+///
+/// \param Diags If non-NULL, diagnostics will be emitted via this engine.
+///
+/// \returns true if the target options mis-match, false otherwise.
+static bool checkTargetOptions(const TargetOptions &TargetOpts,
+                               const TargetOptions &ExistingTargetOpts,
+                               DiagnosticsEngine *Diags) {
+#define CHECK_TARGET_OPT(Field, Name)                             \
+  if (TargetOpts.Field != ExistingTargetOpts.Field) {             \
+    if (Diags)                                                    \
+      Diags->Report(diag::err_pch_targetopt_mismatch)             \
+        << Name << TargetOpts.Field << ExistingTargetOpts.Field;  \
+    return true;                                                  \
+  }
+
+  CHECK_TARGET_OPT(Triple, "target");
+  CHECK_TARGET_OPT(CPU, "target CPU");
+  CHECK_TARGET_OPT(ABI, "target ABI");
+  CHECK_TARGET_OPT(CXXABI, "target C++ ABI");
+  CHECK_TARGET_OPT(LinkerVersion, "target linker version");
+#undef CHECK_TARGET_OPT
+
+  // Compare feature sets.
+  SmallVector<StringRef, 4> ExistingFeatures(
+                                             ExistingTargetOpts.FeaturesAsWritten.begin(),
+                                             ExistingTargetOpts.FeaturesAsWritten.end());
+  SmallVector<StringRef, 4> ReadFeatures(TargetOpts.FeaturesAsWritten.begin(),
+                                         TargetOpts.FeaturesAsWritten.end());
+  std::sort(ExistingFeatures.begin(), ExistingFeatures.end());
+  std::sort(ReadFeatures.begin(), ReadFeatures.end());
+
+  unsigned ExistingIdx = 0, ExistingN = ExistingFeatures.size();
+  unsigned ReadIdx = 0, ReadN = ReadFeatures.size();
+  while (ExistingIdx < ExistingN && ReadIdx < ReadN) {
+    if (ExistingFeatures[ExistingIdx] == ReadFeatures[ReadIdx]) {
+      ++ExistingIdx;
+      ++ReadIdx;
+      continue;
+    }
+
+    if (ReadFeatures[ReadIdx] < ExistingFeatures[ExistingIdx]) {
+      if (Diags)
+        Diags->Report(diag::err_pch_targetopt_feature_mismatch)
+          << false << ReadFeatures[ReadIdx];
+      return true;
+    }
+
+    if (Diags)
+      Diags->Report(diag::err_pch_targetopt_feature_mismatch)
+        << true << ExistingFeatures[ExistingIdx];
+    return true;
+  }
+
+  if (ExistingIdx < ExistingN) {
+    if (Diags)
+      Diags->Report(diag::err_pch_targetopt_feature_mismatch)
+        << true << ExistingFeatures[ExistingIdx];
+    return true;
+  }
+
+  if (ReadIdx < ReadN) {
+    if (Diags)
+      Diags->Report(diag::err_pch_targetopt_feature_mismatch)
+        << false << ReadFeatures[ReadIdx];
+    return true;
+  }
+
+  return false;
+}
+
+bool
+PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts,
+                                  bool Complain) {
+  const LangOptions &ExistingLangOpts = PP.getLangOpts();
+  return checkLanguageOptions(LangOpts, ExistingLangOpts,
+                              Complain? &Reader.Diags : 0);
+}
+
+bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
+                                     bool Complain) {
+  const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts();
+  return checkTargetOptions(TargetOpts, ExistingTargetOpts,
+                            Complain? &Reader.Diags : 0);
+}
+
+namespace {
+  typedef llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >
+    MacroDefinitionsMap;
+}
+
+/// \brief Collect the macro definitions provided by the given preprocessor
+/// options.
+static void collectMacroDefinitions(const PreprocessorOptions &PPOpts,
+                                    MacroDefinitionsMap &Macros,
+                                    SmallVectorImpl<StringRef> *MacroNames = 0){
+  for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) {
+    StringRef Macro = PPOpts.Macros[I].first;
+    bool IsUndef = PPOpts.Macros[I].second;
+
+    std::pair<StringRef, StringRef> MacroPair = Macro.split('=');
+    StringRef MacroName = MacroPair.first;
+    StringRef MacroBody = MacroPair.second;
+
+    // For an #undef'd macro, we only care about the name.
+    if (IsUndef) {
+      if (MacroNames && !Macros.count(MacroName))
+        MacroNames->push_back(MacroName);
+
+      Macros[MacroName] = std::make_pair("", true);
+      continue;
+    }
+
+    // For a #define'd macro, figure out the actual definition.
+    if (MacroName.size() == Macro.size())
+      MacroBody = "1";
+    else {
+      // Note: GCC drops anything following an end-of-line character.
+      StringRef::size_type End = MacroBody.find_first_of("\n\r");
+      MacroBody = MacroBody.substr(0, End);
+    }
+
+    if (MacroNames && !Macros.count(MacroName))
+      MacroNames->push_back(MacroName);
+    Macros[MacroName] = std::make_pair(MacroBody, false);
+  }
+}
+         
+/// \brief Check the preprocessor options deserialized from the control block
+/// against the preprocessor options in an existing preprocessor.
+///
+/// \param Diags If non-null, produce diagnostics for any mismatches incurred.
+static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
+                                     const PreprocessorOptions &ExistingPPOpts,
+                                     DiagnosticsEngine *Diags,
+                                     FileManager &FileMgr,
+                                     std::string &SuggestedPredefines) {
+  // Check macro definitions.
+  MacroDefinitionsMap ASTFileMacros;
+  collectMacroDefinitions(PPOpts, ASTFileMacros);
+  MacroDefinitionsMap ExistingMacros;
+  SmallVector<StringRef, 4> ExistingMacroNames;
+  collectMacroDefinitions(ExistingPPOpts, ExistingMacros, &ExistingMacroNames);
+
+  for (unsigned I = 0, N = ExistingMacroNames.size(); I != N; ++I) {
+    // Dig out the macro definition in the existing preprocessor options.
+    StringRef MacroName = ExistingMacroNames[I];
+    std::pair<StringRef, bool> Existing = ExistingMacros[MacroName];
+
+    // Check whether we know anything about this macro name or not.
+    llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >::iterator Known
+      = ASTFileMacros.find(MacroName);
+    if (Known == ASTFileMacros.end()) {
+      // FIXME: Check whether this identifier was referenced anywhere in the
+      // AST file. If so, we should reject the AST file. Unfortunately, this
+      // information isn't in the control block. What shall we do about it?
+
+      if (Existing.second) {
+        SuggestedPredefines += "#undef ";
+        SuggestedPredefines += MacroName.str();
+        SuggestedPredefines += '\n';
+      } else {
+        SuggestedPredefines += "#define ";
+        SuggestedPredefines += MacroName.str();
+        SuggestedPredefines += ' ';
+        SuggestedPredefines += Existing.first.str();
+        SuggestedPredefines += '\n';
+      }
+      continue;
+    }
+
+    // If the macro was defined in one but undef'd in the other, we have a
+    // conflict.
+    if (Existing.second != Known->second.second) {
+      if (Diags) {
+        Diags->Report(diag::err_pch_macro_def_undef)
+          << MacroName << Known->second.second;
+      }
+      return true;
+    }
+
+    // If the macro was #undef'd in both, or if the macro bodies are identical,
+    // it's fine.
+    if (Existing.second || Existing.first == Known->second.first)
+      continue;
+
+    // The macro bodies differ; complain.
+    if (Diags) {
+      Diags->Report(diag::err_pch_macro_def_conflict)
+        << MacroName << Known->second.first << Existing.first;
+    }
+    return true;
+  }
+
+  // Check whether we're using predefines.
+  if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines) {
+    if (Diags) {
+      Diags->Report(diag::err_pch_undef) << ExistingPPOpts.UsePredefines;
+    }
+    return true;
+  }
+
+  // Compute the #include and #include_macros lines we need.
+  for (unsigned I = 0, N = ExistingPPOpts.Includes.size(); I != N; ++I) {
+    StringRef File = ExistingPPOpts.Includes[I];
+    if (File == ExistingPPOpts.ImplicitPCHInclude)
+      continue;
+
+    if (std::find(PPOpts.Includes.begin(), PPOpts.Includes.end(), File)
+          != PPOpts.Includes.end())
+      continue;
+
+    SuggestedPredefines += "#include \"";
+    SuggestedPredefines +=
+      HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+    SuggestedPredefines += "\"\n";
+  }
+
+  for (unsigned I = 0, N = ExistingPPOpts.MacroIncludes.size(); I != N; ++I) {
+    StringRef File = ExistingPPOpts.MacroIncludes[I];
+    if (std::find(PPOpts.MacroIncludes.begin(), PPOpts.MacroIncludes.end(),
+                  File)
+        != PPOpts.MacroIncludes.end())
+      continue;
+
+    SuggestedPredefines += "#__include_macros \"";
+    SuggestedPredefines +=
+      HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+    SuggestedPredefines += "\"\n##\n";
+  }
+
+  return false;
+}
+
+bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
+                                           bool Complain,
+                                           std::string &SuggestedPredefines) {
+  const PreprocessorOptions &ExistingPPOpts = PP.getPreprocessorOpts();
+
+  return checkPreprocessorOptions(PPOpts, ExistingPPOpts,
+                                  Complain? &Reader.Diags : 0,
+                                  PP.getFileManager(),
+                                  SuggestedPredefines);
+}
+
+void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI,
+                                      unsigned ID) {
+  PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID);
+  ++NumHeaderInfos;
+}
+
+void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) {
+  PP.setCounterValue(Value);
+}
+
+//===----------------------------------------------------------------------===//
+// AST reader implementation
+//===----------------------------------------------------------------------===//
+
+void
+ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) {
+  DeserializationListener = Listener;
+}
+
+
+
+unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) {
+  return serialization::ComputeHash(Sel);
+}
+
+
+std::pair<unsigned, unsigned>
+ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
+  using namespace clang::io;
+  unsigned KeyLen = ReadUnalignedLE16(d);
+  unsigned DataLen = ReadUnalignedLE16(d);
+  return std::make_pair(KeyLen, DataLen);
+}
+
+ASTSelectorLookupTrait::internal_key_type 
+ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {
+  using namespace clang::io;
+  SelectorTable &SelTable = Reader.getContext().Selectors;
+  unsigned N = ReadUnalignedLE16(d);
+  IdentifierInfo *FirstII
+    = Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
+  if (N == 0)
+    return SelTable.getNullarySelector(FirstII);
+  else if (N == 1)
+    return SelTable.getUnarySelector(FirstII);
+
+  SmallVector<IdentifierInfo *, 16> Args;
+  Args.push_back(FirstII);
+  for (unsigned I = 1; I != N; ++I)
+    Args.push_back(Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)));
+
+  return SelTable.getSelector(N, Args.data());
+}
+
+ASTSelectorLookupTrait::data_type 
+ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, 
+                                 unsigned DataLen) {
+  using namespace clang::io;
+
+  data_type Result;
+
+  Result.ID = Reader.getGlobalSelectorID(F, ReadUnalignedLE32(d));
+  unsigned NumInstanceMethods = ReadUnalignedLE16(d);
+  unsigned NumFactoryMethods = ReadUnalignedLE16(d);
+
+  // Load instance methods
+  for (unsigned I = 0; I != NumInstanceMethods; ++I) {
+    if (ObjCMethodDecl *Method
+          = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
+      Result.Instance.push_back(Method);
+  }
+
+  // Load factory methods
+  for (unsigned I = 0; I != NumFactoryMethods; ++I) {
+    if (ObjCMethodDecl *Method
+          = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
+      Result.Factory.push_back(Method);
+  }
+
+  return Result;
+}
+
+unsigned ASTIdentifierLookupTrait::ComputeHash(const internal_key_type& a) {
+  return llvm::HashString(StringRef(a.first, a.second));
+}
+
+std::pair<unsigned, unsigned>
+ASTIdentifierLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
+  using namespace clang::io;
+  unsigned DataLen = ReadUnalignedLE16(d);
+  unsigned KeyLen = ReadUnalignedLE16(d);
+  return std::make_pair(KeyLen, DataLen);
+}
+
+std::pair<const char*, unsigned>
+ASTIdentifierLookupTrait::ReadKey(const unsigned char* d, unsigned n) {
+  assert(n >= 2 && d[n-1] == '\0');
+  return std::make_pair((const char*) d, n-1);
+}
+
+IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
+                                                   const unsigned char* d,
+                                                   unsigned DataLen) {
+  using namespace clang::io;
+  unsigned RawID = ReadUnalignedLE32(d);
+  bool IsInteresting = RawID & 0x01;
+
+  // Wipe out the "is interesting" bit.
+  RawID = RawID >> 1;
+
+  IdentID ID = Reader.getGlobalIdentifierID(F, RawID);
+  if (!IsInteresting) {
+    // For uninteresting identifiers, just build the IdentifierInfo
+    // and associate it with the persistent ID.
+    IdentifierInfo *II = KnownII;
+    if (!II) {
+      II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
+      KnownII = II;
+    }
+    Reader.SetIdentifierInfo(ID, II);
+    II->setIsFromAST();
+    Reader.markIdentifierUpToDate(II);    
+    return II;
+  }
+
+  unsigned ObjCOrBuiltinID = ReadUnalignedLE16(d);
+  unsigned Bits = ReadUnalignedLE16(d);
+  bool CPlusPlusOperatorKeyword = Bits & 0x01;
+  Bits >>= 1;
+  bool HasRevertedTokenIDToIdentifier = Bits & 0x01;
+  Bits >>= 1;
+  bool Poisoned = Bits & 0x01;
+  Bits >>= 1;
+  bool ExtensionToken = Bits & 0x01;
+  Bits >>= 1;
+  bool hadMacroDefinition = Bits & 0x01;
+  Bits >>= 1;
+
+  assert(Bits == 0 && "Extra bits in the identifier?");
+  DataLen -= 8;
+
+  // Build the IdentifierInfo itself and link the identifier ID with
+  // the new IdentifierInfo.
+  IdentifierInfo *II = KnownII;
+  if (!II) {
+    II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
+    KnownII = II;
+  }
+  Reader.markIdentifierUpToDate(II);
+  II->setIsFromAST();
+
+  // Set or check the various bits in the IdentifierInfo structure.
+  // Token IDs are read-only.
+  if (HasRevertedTokenIDToIdentifier)
+    II->RevertTokenIDToIdentifier();
+  II->setObjCOrBuiltinID(ObjCOrBuiltinID);
+  assert(II->isExtensionToken() == ExtensionToken &&
+         "Incorrect extension token flag");
+  (void)ExtensionToken;
+  if (Poisoned)
+    II->setIsPoisoned(true);
+  assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
+         "Incorrect C++ operator keyword flag");
+  (void)CPlusPlusOperatorKeyword;
+
+  // If this identifier is a macro, deserialize the macro
+  // definition.
+  if (hadMacroDefinition) {
+    SmallVector<MacroID, 4> MacroIDs;
+    while (uint32_t LocalID = ReadUnalignedLE32(d)) {
+      MacroIDs.push_back(Reader.getGlobalMacroID(F, LocalID));
+      DataLen -= 4;
+    }
+    DataLen -= 4;
+    Reader.setIdentifierIsMacro(II, MacroIDs);
+  }
+
+  Reader.SetIdentifierInfo(ID, II);
+
+  // Read all of the declarations visible at global scope with this
+  // name.
+  if (DataLen > 0) {
+    SmallVector<uint32_t, 4> DeclIDs;
+    for (; DataLen > 0; DataLen -= 4)
+      DeclIDs.push_back(Reader.getGlobalDeclID(F, ReadUnalignedLE32(d)));
+    Reader.SetGloballyVisibleDecls(II, DeclIDs);
+  }
+
+  return II;
+}
+
+unsigned 
+ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) const {
+  llvm::FoldingSetNodeID ID;
+  ID.AddInteger(Key.Kind);
+
+  switch (Key.Kind) {
+  case DeclarationName::Identifier:
+  case DeclarationName::CXXLiteralOperatorName:
+    ID.AddString(((IdentifierInfo*)Key.Data)->getName());
+    break;
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    ID.AddInteger(serialization::ComputeHash(Selector(Key.Data)));
+    break;
+  case DeclarationName::CXXOperatorName:
+    ID.AddInteger((OverloadedOperatorKind)Key.Data);
+    break;
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName:
+  case DeclarationName::CXXUsingDirective:
+    break;
+  }
+
+  return ID.ComputeHash();
+}
+
+ASTDeclContextNameLookupTrait::internal_key_type 
+ASTDeclContextNameLookupTrait::GetInternalKey(
+                                          const external_key_type& Name) const {
+  DeclNameKey Key;
+  Key.Kind = Name.getNameKind();
+  switch (Name.getNameKind()) {
+  case DeclarationName::Identifier:
+    Key.Data = (uint64_t)Name.getAsIdentifierInfo();
+    break;
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    Key.Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr();
+    break;
+  case DeclarationName::CXXOperatorName:
+    Key.Data = Name.getCXXOverloadedOperator();
+    break;
+  case DeclarationName::CXXLiteralOperatorName:
+    Key.Data = (uint64_t)Name.getCXXLiteralIdentifier();
+    break;
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName:
+  case DeclarationName::CXXUsingDirective:
+    Key.Data = 0;
+    break;
+  }
+
+  return Key;
+}
+
+std::pair<unsigned, unsigned>
+ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
+  using namespace clang::io;
+  unsigned KeyLen = ReadUnalignedLE16(d);
+  unsigned DataLen = ReadUnalignedLE16(d);
+  return std::make_pair(KeyLen, DataLen);
+}
+
+ASTDeclContextNameLookupTrait::internal_key_type 
+ASTDeclContextNameLookupTrait::ReadKey(const unsigned char* d, unsigned) {
+  using namespace clang::io;
+
+  DeclNameKey Key;
+  Key.Kind = (DeclarationName::NameKind)*d++;
+  switch (Key.Kind) {
+  case DeclarationName::Identifier:
+    Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
+    break;
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    Key.Data =
+       (uint64_t)Reader.getLocalSelector(F, ReadUnalignedLE32(d))
+                   .getAsOpaquePtr();
+    break;
+  case DeclarationName::CXXOperatorName:
+    Key.Data = *d++; // OverloadedOperatorKind
+    break;
+  case DeclarationName::CXXLiteralOperatorName:
+    Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
+    break;
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName:
+  case DeclarationName::CXXUsingDirective:
+    Key.Data = 0;
+    break;
+  }
+
+  return Key;
+}
+
+ASTDeclContextNameLookupTrait::data_type 
+ASTDeclContextNameLookupTrait::ReadData(internal_key_type, 
+                                        const unsigned char* d,
+                                        unsigned DataLen) {
+  using namespace clang::io;
+  unsigned NumDecls = ReadUnalignedLE16(d);
+  LE32DeclID *Start = (LE32DeclID *)d;
+  return std::make_pair(Start, Start + NumDecls);
+}
+
+bool ASTReader::ReadDeclContextStorage(ModuleFile &M,
+                                       llvm::BitstreamCursor &Cursor,
+                                   const std::pair<uint64_t, uint64_t> &Offsets,
+                                       DeclContextInfo &Info) {
+  SavedStreamPosition SavedPosition(Cursor);
+  // First the lexical decls.
+  if (Offsets.first != 0) {
+    Cursor.JumpToBit(Offsets.first);
+
+    RecordData Record;
+    const char *Blob;
+    unsigned BlobLen;
+    unsigned Code = Cursor.ReadCode();
+    unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);
+    if (RecCode != DECL_CONTEXT_LEXICAL) {
+      Error("Expected lexical block");
+      return true;
+    }
+
+    Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair*>(Blob);
+    Info.NumLexicalDecls = BlobLen / sizeof(KindDeclIDPair);
+  }
+
+  // Now the lookup table.
+  if (Offsets.second != 0) {
+    Cursor.JumpToBit(Offsets.second);
+
+    RecordData Record;
+    const char *Blob;
+    unsigned BlobLen;
+    unsigned Code = Cursor.ReadCode();
+    unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);
+    if (RecCode != DECL_CONTEXT_VISIBLE) {
+      Error("Expected visible lookup table block");
+      return true;
+    }
+    Info.NameLookupTableData
+      = ASTDeclContextNameLookupTable::Create(
+                    (const unsigned char *)Blob + Record[0],
+                    (const unsigned char *)Blob,
+                    ASTDeclContextNameLookupTrait(*this, M));
+  }
+
+  return false;
+}
+
+void ASTReader::Error(StringRef Msg) {
+  Error(diag::err_fe_pch_malformed, Msg);
+}
+
+void ASTReader::Error(unsigned DiagID,
+                      StringRef Arg1, StringRef Arg2) {
+  if (Diags.isDiagnosticInFlight())
+    Diags.SetDelayedDiagnostic(DiagID, Arg1, Arg2);
+  else
+    Diag(DiagID) << Arg1 << Arg2;
+}
+
+//===----------------------------------------------------------------------===//
+// Source Manager Deserialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Read the line table in the source manager block.
+/// \returns true if there was an error.
+bool ASTReader::ParseLineTable(ModuleFile &F,
+                               SmallVectorImpl<uint64_t> &Record) {
+  unsigned Idx = 0;
+  LineTableInfo &LineTable = SourceMgr.getLineTable();
+
+  // Parse the file names
+  std::map<int, int> FileIDs;
+  for (int I = 0, N = Record[Idx++]; I != N; ++I) {
+    // Extract the file name
+    unsigned FilenameLen = Record[Idx++];
+    std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
+    Idx += FilenameLen;
+    MaybeAddSystemRootToFilename(F, Filename);
+    FileIDs[I] = LineTable.getLineTableFilenameID(Filename);
+  }
+
+  // Parse the line entries
+  std::vector<LineEntry> Entries;
+  while (Idx < Record.size()) {
+    int FID = Record[Idx++];
+    assert(FID >= 0 && "Serialized line entries for non-local file.");
+    // Remap FileID from 1-based old view.
+    FID += F.SLocEntryBaseID - 1;
+
+    // Extract the line entries
+    unsigned NumEntries = Record[Idx++];
+    assert(NumEntries && "Numentries is 00000");
+    Entries.clear();
+    Entries.reserve(NumEntries);
+    for (unsigned I = 0; I != NumEntries; ++I) {
+      unsigned FileOffset = Record[Idx++];
+      unsigned LineNo = Record[Idx++];
+      int FilenameID = FileIDs[Record[Idx++]];
+      SrcMgr::CharacteristicKind FileKind
+        = (SrcMgr::CharacteristicKind)Record[Idx++];
+      unsigned IncludeOffset = Record[Idx++];
+      Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
+                                       FileKind, IncludeOffset));
+    }
+    LineTable.AddEntry(FileID::get(FID), Entries);
+  }
+
+  return false;
+}
+
+/// \brief Read a source manager block
+bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
+  using namespace SrcMgr;
+
+  llvm::BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor;
+
+  // Set the source-location entry cursor to the current position in
+  // the stream. This cursor will be used to read the contents of the
+  // source manager block initially, and then lazily read
+  // source-location entries as needed.
+  SLocEntryCursor = F.Stream;
+
+  // The stream itself is going to skip over the source manager block.
+  if (F.Stream.SkipBlock()) {
+    Error("malformed block record in AST file");
+    return true;
+  }
+
+  // Enter the source manager block.
+  if (SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID)) {
+    Error("malformed source manager block record in AST file");
+    return true;
+  }
+
+  RecordData Record;
+  while (true) {
+    unsigned Code = SLocEntryCursor.ReadCode();
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (SLocEntryCursor.ReadBlockEnd()) {
+        Error("error at end of Source Manager block in AST file");
+        return true;
+      }
+      return false;
+    }
+
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      SLocEntryCursor.ReadSubBlockID();
+      if (SLocEntryCursor.SkipBlock()) {
+        Error("malformed block record in AST file");
+        return true;
+      }
+      continue;
+    }
+
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      SLocEntryCursor.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    const char *BlobStart;
+    unsigned BlobLen;
+    Record.clear();
+    switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+    default:  // Default behavior: ignore.
+      break;
+
+    case SM_SLOC_FILE_ENTRY:
+    case SM_SLOC_BUFFER_ENTRY:
+    case SM_SLOC_EXPANSION_ENTRY:
+      // Once we hit one of the source location entries, we're done.
+      return false;
+    }
+  }
+}
+
+/// \brief If a header file is not found at the path that we expect it to be
+/// and the PCH file was moved from its original location, try to resolve the
+/// file by assuming that header+PCH were moved together and the header is in
+/// the same place relative to the PCH.
+static std::string
+resolveFileRelativeToOriginalDir(const std::string &Filename,
+                                 const std::string &OriginalDir,
+                                 const std::string &CurrDir) {
+  assert(OriginalDir != CurrDir &&
+         "No point trying to resolve the file if the PCH dir didn't change");
+  using namespace llvm::sys;
+  SmallString<128> filePath(Filename);
+  fs::make_absolute(filePath);
+  assert(path::is_absolute(OriginalDir));
+  SmallString<128> currPCHPath(CurrDir);
+
+  path::const_iterator fileDirI = path::begin(path::parent_path(filePath)),
+                       fileDirE = path::end(path::parent_path(filePath));
+  path::const_iterator origDirI = path::begin(OriginalDir),
+                       origDirE = path::end(OriginalDir);
+  // Skip the common path components from filePath and OriginalDir.
+  while (fileDirI != fileDirE && origDirI != origDirE &&
+         *fileDirI == *origDirI) {
+    ++fileDirI;
+    ++origDirI;
+  }
+  for (; origDirI != origDirE; ++origDirI)
+    path::append(currPCHPath, "..");
+  path::append(currPCHPath, fileDirI, fileDirE);
+  path::append(currPCHPath, path::filename(Filename));
+  return currPCHPath.str();
+}
+
+bool ASTReader::ReadSLocEntry(int ID) {
+  if (ID == 0)
+    return false;
+
+  if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) {
+    Error("source location entry ID out-of-range for AST file");
+    return true;
+  }
+
+  ModuleFile *F = GlobalSLocEntryMap.find(-ID)->second;
+  F->SLocEntryCursor.JumpToBit(F->SLocEntryOffsets[ID - F->SLocEntryBaseID]);
+  llvm::BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor;
+  unsigned BaseOffset = F->SLocEntryBaseOffset;
+
+  ++NumSLocEntriesRead;
+  unsigned Code = SLocEntryCursor.ReadCode();
+  if (Code == llvm::bitc::END_BLOCK ||
+      Code == llvm::bitc::ENTER_SUBBLOCK ||
+      Code == llvm::bitc::DEFINE_ABBREV) {
+    Error("incorrectly-formatted source location entry in AST file");
+    return true;
+  }
+
+  RecordData Record;
+  const char *BlobStart;
+  unsigned BlobLen;
+  switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+  default:
+    Error("incorrectly-formatted source location entry in AST file");
+    return true;
+
+  case SM_SLOC_FILE_ENTRY: {
+    // We will detect whether a file changed and return 'Failure' for it, but
+    // we will also try to fail gracefully by setting up the SLocEntry.
+    unsigned InputID = Record[4];
+    InputFile IF = getInputFile(*F, InputID);
+    const FileEntry *File = IF.getPointer();
+    bool OverriddenBuffer = IF.getInt();
+
+    if (!IF.getPointer())
+      return true;
+
+    SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
+    if (IncludeLoc.isInvalid() && F->Kind != MK_MainFile) {
+      // This is the module's main file.
+      IncludeLoc = getImportLocation(F);
+    }
+    SrcMgr::CharacteristicKind
+      FileCharacter = (SrcMgr::CharacteristicKind)Record[2];
+    FileID FID = SourceMgr.createFileID(File, IncludeLoc, FileCharacter,
+                                        ID, BaseOffset + Record[0]);
+    SrcMgr::FileInfo &FileInfo =
+          const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile());
+    FileInfo.NumCreatedFIDs = Record[5];
+    if (Record[3])
+      FileInfo.setHasLineDirectives();
+
+    const DeclID *FirstDecl = F->FileSortedDecls + Record[6];
+    unsigned NumFileDecls = Record[7];
+    if (NumFileDecls) {
+      assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?");
+      FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl,
+                                                             NumFileDecls));
+    }
+    
+    const SrcMgr::ContentCache *ContentCache
+      = SourceMgr.getOrCreateContentCache(File,
+                              /*isSystemFile=*/FileCharacter != SrcMgr::C_User);
+    if (OverriddenBuffer && !ContentCache->BufferOverridden &&
+        ContentCache->ContentsEntry == ContentCache->OrigEntry) {
+      unsigned Code = SLocEntryCursor.ReadCode();
+      Record.clear();
+      unsigned RecCode
+        = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+      
+      if (RecCode != SM_SLOC_BUFFER_BLOB) {
+        Error("AST record has invalid code");
+        return true;
+      }
+      
+      llvm::MemoryBuffer *Buffer
+        = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),
+                                           File->getName());
+      SourceMgr.overrideFileContents(File, Buffer);
+    }
+
+    break;
+  }
+
+  case SM_SLOC_BUFFER_ENTRY: {
+    const char *Name = BlobStart;
+    unsigned Offset = Record[0];
+    SrcMgr::CharacteristicKind
+      FileCharacter = (SrcMgr::CharacteristicKind)Record[2];
+    SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
+    if (IncludeLoc.isInvalid() && F->Kind == MK_Module) {
+      IncludeLoc = getImportLocation(F);
+    }
+    unsigned Code = SLocEntryCursor.ReadCode();
+    Record.clear();
+    unsigned RecCode
+      = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+
+    if (RecCode != SM_SLOC_BUFFER_BLOB) {
+      Error("AST record has invalid code");
+      return true;
+    }
+
+    llvm::MemoryBuffer *Buffer
+      = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),
+                                         Name);
+    SourceMgr.createFileIDForMemBuffer(Buffer, FileCharacter, ID,
+                                       BaseOffset + Offset, IncludeLoc);
+    break;
+  }
+
+  case SM_SLOC_EXPANSION_ENTRY: {
+    SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1]);
+    SourceMgr.createExpansionLoc(SpellingLoc,
+                                     ReadSourceLocation(*F, Record[2]),
+                                     ReadSourceLocation(*F, Record[3]),
+                                     Record[4],
+                                     ID,
+                                     BaseOffset + Record[0]);
+    break;
+  }
+  }
+
+  return false;
+}
+
+std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) {
+  if (ID == 0)
+    return std::make_pair(SourceLocation(), "");
+
+  if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) {
+    Error("source location entry ID out-of-range for AST file");
+    return std::make_pair(SourceLocation(), "");
+  }
+
+  // Find which module file this entry lands in.
+  ModuleFile *M = GlobalSLocEntryMap.find(-ID)->second;
+  if (M->Kind != MK_Module)
+    return std::make_pair(SourceLocation(), "");
+
+  // FIXME: Can we map this down to a particular submodule? That would be
+  // ideal.
+  return std::make_pair(M->ImportLoc, llvm::sys::path::stem(M->FileName));
+}
+
+/// \brief Find the location where the module F is imported.
+SourceLocation ASTReader::getImportLocation(ModuleFile *F) {
+  if (F->ImportLoc.isValid())
+    return F->ImportLoc;
+  
+  // Otherwise we have a PCH. It's considered to be "imported" at the first
+  // location of its includer.
+  if (F->ImportedBy.empty() || !F->ImportedBy[0]) {
+    // Main file is the importer. We assume that it is the first entry in the
+    // entry table. We can't ask the manager, because at the time of PCH loading
+    // the main file entry doesn't exist yet.
+    // The very first entry is the invalid instantiation loc, which takes up
+    // offsets 0 and 1.
+    return SourceLocation::getFromRawEncoding(2U);
+  }
+  //return F->Loaders[0]->FirstLoc;
+  return F->ImportedBy[0]->FirstLoc;
+}
+
+/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
+/// specified cursor.  Read the abbreviations that are at the top of the block
+/// and then leave the cursor pointing into the block.
+bool ASTReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
+                                 unsigned BlockID) {
+  if (Cursor.EnterSubBlock(BlockID)) {
+    Error("malformed block record in AST file");
+    return Failure;
+  }
+
+  while (true) {
+    uint64_t Offset = Cursor.GetCurrentBitNo();
+    unsigned Code = Cursor.ReadCode();
+
+    // We expect all abbrevs to be at the start of the block.
+    if (Code != llvm::bitc::DEFINE_ABBREV) {
+      Cursor.JumpToBit(Offset);
+      return false;
+    }
+    Cursor.ReadAbbrevRecord();
+  }
+}
+
+void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,
+                                MacroInfo *Hint) {
+  llvm::BitstreamCursor &Stream = F.MacroCursor;
+
+  // Keep track of where we are in the stream, then jump back there
+  // after reading this macro.
+  SavedStreamPosition SavedPosition(Stream);
+
+  Stream.JumpToBit(Offset);
+  RecordData Record;
+  SmallVector<IdentifierInfo*, 16> MacroArgs;
+  MacroInfo *Macro = 0;
+
+  // RAII object to add the loaded macro information once we're done
+  // adding tokens.
+  struct AddLoadedMacroInfoRAII {
+    Preprocessor &PP;
+    MacroInfo *Hint;
+    MacroInfo *MI;
+    IdentifierInfo *II;
+
+    AddLoadedMacroInfoRAII(Preprocessor &PP, MacroInfo *Hint)
+      : PP(PP), Hint(Hint), MI(), II() { }
+    ~AddLoadedMacroInfoRAII( ) {
+      if (MI) {
+        // Finally, install the macro.
+        PP.addLoadedMacroInfo(II, MI, Hint);
+      }
+    }
+  } AddLoadedMacroInfo(PP, Hint);
+
+  while (true) {
+    unsigned Code = Stream.ReadCode();
+    switch (Code) {
+    case llvm::bitc::END_BLOCK:
+      return;
+
+    case llvm::bitc::ENTER_SUBBLOCK:
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock()) {
+        Error("malformed block record in AST file");
+        return;
+      }
+      continue;
+
+    case llvm::bitc::DEFINE_ABBREV:
+      Stream.ReadAbbrevRecord();
+      continue;
+    default: break;
+    }
+
+    // Read a record.
+    const char *BlobStart = 0;
+    unsigned BlobLen = 0;
+    Record.clear();
+    PreprocessorRecordTypes RecType =
+      (PreprocessorRecordTypes)Stream.ReadRecord(Code, Record, BlobStart,
+                                                 BlobLen);
+    switch (RecType) {
+    case PP_MACRO_OBJECT_LIKE:
+    case PP_MACRO_FUNCTION_LIKE: {
+      // If we already have a macro, that means that we've hit the end
+      // of the definition of the macro we were looking for. We're
+      // done.
+      if (Macro)
+        return;
+
+      IdentifierInfo *II = getLocalIdentifier(F, Record[0]);
+      if (II == 0) {
+        Error("macro must have a name in AST file");
+        return;
+      }
+
+      unsigned GlobalID = getGlobalMacroID(F, Record[1]);
+
+      // If this macro has already been loaded, don't do so again.
+      if (MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS])
+        return;
+
+      SubmoduleID GlobalSubmoduleID = getGlobalSubmoduleID(F, Record[2]);
+      unsigned NextIndex = 3;
+      SourceLocation Loc = ReadSourceLocation(F, Record, NextIndex);
+      MacroInfo *MI = PP.AllocateMacroInfo(Loc);
+
+      // Record this macro.
+      MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS] = MI;
+
+      SourceLocation UndefLoc = ReadSourceLocation(F, Record, NextIndex);
+      if (UndefLoc.isValid())
+        MI->setUndefLoc(UndefLoc);
+
+      MI->setIsUsed(Record[NextIndex++]);
+      MI->setIsFromAST();
+
+      bool IsPublic = Record[NextIndex++];
+      MI->setVisibility(IsPublic, ReadSourceLocation(F, Record, NextIndex));
+
+      if (RecType == PP_MACRO_FUNCTION_LIKE) {
+        // Decode function-like macro info.
+        bool isC99VarArgs = Record[NextIndex++];
+        bool isGNUVarArgs = Record[NextIndex++];
+        bool hasCommaPasting = Record[NextIndex++];
+        MacroArgs.clear();
+        unsigned NumArgs = Record[NextIndex++];
+        for (unsigned i = 0; i != NumArgs; ++i)
+          MacroArgs.push_back(getLocalIdentifier(F, Record[NextIndex++]));
+
+        // Install function-like macro info.
+        MI->setIsFunctionLike();
+        if (isC99VarArgs) MI->setIsC99Varargs();
+        if (isGNUVarArgs) MI->setIsGNUVarargs();
+        if (hasCommaPasting) MI->setHasCommaPasting();
+        MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
+                            PP.getPreprocessorAllocator());
+      }
+
+      if (DeserializationListener)
+        DeserializationListener->MacroRead(GlobalID, MI);
+
+      // If an update record marked this as undefined, do so now.
+      // FIXME: Only if the submodule this update came from is visible?
+      MacroUpdatesMap::iterator Update = MacroUpdates.find(GlobalID);
+      if (Update != MacroUpdates.end()) {
+        if (MI->getUndefLoc().isInvalid()) {
+          for (unsigned I = 0, N = Update->second.size(); I != N; ++I) {
+            bool Hidden = false;
+            if (unsigned SubmoduleID = Update->second[I].first) {
+              if (Module *Owner = getSubmodule(SubmoduleID)) {
+                if (Owner->NameVisibility == Module::Hidden) {
+                  // Note that this #undef is hidden.
+                  Hidden = true;
+
+                  // Record this hiding for later.
+                  HiddenNamesMap[Owner].push_back(
+                    HiddenName(II, MI, Update->second[I].second.UndefLoc));
+                }
+              }
+            }
+
+            if (!Hidden) {
+              MI->setUndefLoc(Update->second[I].second.UndefLoc);
+              if (PPMutationListener *Listener = PP.getPPMutationListener())
+                Listener->UndefinedMacro(MI);
+              break;
+            }
+          }
+        }
+        MacroUpdates.erase(Update);
+      }
+
+      // Determine whether this macro definition is visible.
+      bool Hidden = !MI->isPublic();
+      if (!Hidden && GlobalSubmoduleID) {
+        if (Module *Owner = getSubmodule(GlobalSubmoduleID)) {
+          if (Owner->NameVisibility == Module::Hidden) {
+            // The owning module is not visible, and this macro definition
+            // should not be, either.
+            Hidden = true;
+
+            // Note that this macro definition was hidden because its owning
+            // module is not yet visible.
+            HiddenNamesMap[Owner].push_back(HiddenName(II, MI));
+          }
+        }
+      }
+      MI->setHidden(Hidden);
+
+      // Make sure we install the macro once we're done.
+      AddLoadedMacroInfo.MI = MI;
+      AddLoadedMacroInfo.II = II;
+
+      // Remember that we saw this macro last so that we add the tokens that
+      // form its body to it.
+      Macro = MI;
+
+      if (NextIndex + 1 == Record.size() && PP.getPreprocessingRecord() &&
+          Record[NextIndex]) {
+        // We have a macro definition. Register the association
+        PreprocessedEntityID
+            GlobalID = getGlobalPreprocessedEntityID(F, Record[NextIndex]);
+        PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
+        PPRec.RegisterMacroDefinition(Macro,
+                            PPRec.getPPEntityID(GlobalID-1, /*isLoaded=*/true));
+      }
+
+      ++NumMacrosRead;
+      break;
+    }
+
+    case PP_TOKEN: {
+      // If we see a TOKEN before a PP_MACRO_*, then the file is
+      // erroneous, just pretend we didn't see this.
+      if (Macro == 0) break;
+
+      Token Tok;
+      Tok.startToken();
+      Tok.setLocation(ReadSourceLocation(F, Record[0]));
+      Tok.setLength(Record[1]);
+      if (IdentifierInfo *II = getLocalIdentifier(F, Record[2]))
+        Tok.setIdentifierInfo(II);
+      Tok.setKind((tok::TokenKind)Record[3]);
+      Tok.setFlag((Token::TokenFlags)Record[4]);
+      Macro->AddTokenToBody(Tok);
+      break;
+    }
+    }
+  }
+}
+
+PreprocessedEntityID 
+ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const {
+  ContinuousRangeMap<uint32_t, int, 2>::const_iterator 
+    I = M.PreprocessedEntityRemap.find(LocalID - NUM_PREDEF_PP_ENTITY_IDS);
+  assert(I != M.PreprocessedEntityRemap.end() 
+         && "Invalid index into preprocessed entity index remap");
+  
+  return LocalID + I->second;
+}
+
+unsigned HeaderFileInfoTrait::ComputeHash(const char *path) {
+  return llvm::HashString(llvm::sys::path::filename(path));
+}
+    
+HeaderFileInfoTrait::internal_key_type 
+HeaderFileInfoTrait::GetInternalKey(const char *path) { return path; }
+    
+bool HeaderFileInfoTrait::EqualKey(internal_key_type a, internal_key_type b) {
+  if (strcmp(a, b) == 0)
+    return true;
+  
+  if (llvm::sys::path::filename(a) != llvm::sys::path::filename(b))
+    return false;
+
+  // Determine whether the actual files are equivalent.
+  bool Result = false;
+  if (llvm::sys::fs::equivalent(a, b, Result))
+    return false;
+  
+  return Result;
+}
+    
+std::pair<unsigned, unsigned>
+HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) {
+  unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
+  unsigned DataLen = (unsigned) *d++;
+  return std::make_pair(KeyLen + 1, DataLen);
+}
+    
+HeaderFileInfoTrait::data_type 
+HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d,
+                              unsigned DataLen) {
+  const unsigned char *End = d + DataLen;
+  using namespace clang::io;
+  HeaderFileInfo HFI;
+  unsigned Flags = *d++;
+  HFI.isImport = (Flags >> 5) & 0x01;
+  HFI.isPragmaOnce = (Flags >> 4) & 0x01;
+  HFI.DirInfo = (Flags >> 2) & 0x03;
+  HFI.Resolved = (Flags >> 1) & 0x01;
+  HFI.IndexHeaderMapHeader = Flags & 0x01;
+  HFI.NumIncludes = ReadUnalignedLE16(d);
+  HFI.ControllingMacroID = Reader.getGlobalIdentifierID(M, 
+                                                        ReadUnalignedLE32(d));
+  if (unsigned FrameworkOffset = ReadUnalignedLE32(d)) {
+    // The framework offset is 1 greater than the actual offset, 
+    // since 0 is used as an indicator for "no framework name".
+    StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);
+    HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
+  }
+  
+  assert(End == d && "Wrong data length in HeaderFileInfo deserialization");
+  (void)End;
+        
+  // This HeaderFileInfo was externally loaded.
+  HFI.External = true;
+  return HFI;
+}
+
+void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ArrayRef<MacroID> IDs){
+  II->setHadMacroDefinition(true);
+  assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
+  PendingMacroIDs[II].append(IDs.begin(), IDs.end());
+}
+
+void ASTReader::ReadDefinedMacros() {
+  // Note that we are loading defined macros.
+  Deserializing Macros(this);
+
+  for (ModuleReverseIterator I = ModuleMgr.rbegin(),
+      E = ModuleMgr.rend(); I != E; ++I) {
+    llvm::BitstreamCursor &MacroCursor = (*I)->MacroCursor;
+
+    // If there was no preprocessor block, skip this file.
+    if (!MacroCursor.getBitStreamReader())
+      continue;
+
+    llvm::BitstreamCursor Cursor = MacroCursor;
+    Cursor.JumpToBit((*I)->MacroStartOffset);
+
+    RecordData Record;
+    while (true) {
+      unsigned Code = Cursor.ReadCode();
+      if (Code == llvm::bitc::END_BLOCK)
+        break;
+
+      if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+        // No known subblocks, always skip them.
+        Cursor.ReadSubBlockID();
+        if (Cursor.SkipBlock()) {
+          Error("malformed block record in AST file");
+          return;
+        }
+        continue;
+      }
+
+      if (Code == llvm::bitc::DEFINE_ABBREV) {
+        Cursor.ReadAbbrevRecord();
+        continue;
+      }
+
+      // Read a record.
+      const char *BlobStart;
+      unsigned BlobLen;
+      Record.clear();
+      switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+      default:  // Default behavior: ignore.
+        break;
+
+      case PP_MACRO_OBJECT_LIKE:
+      case PP_MACRO_FUNCTION_LIKE:
+        getLocalIdentifier(**I, Record[0]);
+        break;
+
+      case PP_TOKEN:
+        // Ignore tokens.
+        break;
+      }
+    }
+  }
+}
+
+namespace {
+  /// \brief Visitor class used to look up identifirs in an AST file.
+  class IdentifierLookupVisitor {
+    StringRef Name;
+    unsigned PriorGeneration;
+    IdentifierInfo *Found;
+  public:
+    IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration) 
+      : Name(Name), PriorGeneration(PriorGeneration), Found() { }
+    
+    static bool visit(ModuleFile &M, void *UserData) {
+      IdentifierLookupVisitor *This
+        = static_cast<IdentifierLookupVisitor *>(UserData);
+      
+      // If we've already searched this module file, skip it now.
+      if (M.Generation <= This->PriorGeneration)
+        return true;
+      
+      ASTIdentifierLookupTable *IdTable
+        = (ASTIdentifierLookupTable *)M.IdentifierLookupTable;
+      if (!IdTable)
+        return false;
+      
+      ASTIdentifierLookupTrait Trait(IdTable->getInfoObj().getReader(),
+                                     M, This->Found);
+                                     
+      std::pair<const char*, unsigned> Key(This->Name.begin(), 
+                                           This->Name.size());
+      ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Trait);
+      if (Pos == IdTable->end())
+        return false;
+      
+      // Dereferencing the iterator has the effect of building the
+      // IdentifierInfo node and populating it with the various
+      // declarations it needs.
+      This->Found = *Pos;
+      return true;
+    }
+    
+    // \brief Retrieve the identifier info found within the module
+    // files.
+    IdentifierInfo *getIdentifierInfo() const { return Found; }
+  };
+}
+
+void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {
+  // Note that we are loading an identifier.
+  Deserializing AnIdentifier(this);
+
+  unsigned PriorGeneration = 0;
+  if (getContext().getLangOpts().Modules)
+    PriorGeneration = IdentifierGeneration[&II];
+  
+  IdentifierLookupVisitor Visitor(II.getName(), PriorGeneration);
+  ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
+  markIdentifierUpToDate(&II);
+}
+
+void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) {
+  if (!II)
+    return;
+  
+  II->setOutOfDate(false);
+
+  // Update the generation for this identifier.
+  if (getContext().getLangOpts().Modules)
+    IdentifierGeneration[II] = CurrentGeneration;
+}
+
+llvm::PointerIntPair<const FileEntry *, 1, bool> 
+ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
+  // If this ID is bogus, just return an empty input file.
+  if (ID == 0 || ID > F.InputFilesLoaded.size())
+    return InputFile();
+
+  // If we've already loaded this input file, return it.
+  if (F.InputFilesLoaded[ID-1].getPointer())
+    return F.InputFilesLoaded[ID-1];
+
+  // Go find this input file.
+  llvm::BitstreamCursor &Cursor = F.InputFilesCursor;
+  SavedStreamPosition SavedPosition(Cursor);
+  Cursor.JumpToBit(F.InputFileOffsets[ID-1]);
+  
+  unsigned Code = Cursor.ReadCode();
+  RecordData Record;
+  const char *BlobStart = 0;
+  unsigned BlobLen = 0;
+  switch ((InputFileRecordTypes)Cursor.ReadRecord(Code, Record,
+                                                  &BlobStart, &BlobLen)) {
+  case INPUT_FILE: {
+    unsigned StoredID = Record[0];
+    assert(ID == StoredID && "Bogus stored ID or offset");
+    (void)StoredID;
+    off_t StoredSize = (off_t)Record[1];
+    time_t StoredTime = (time_t)Record[2];
+    bool Overridden = (bool)Record[3];
+    
+    // Get the file entry for this input file.
+    StringRef OrigFilename(BlobStart, BlobLen);
+    std::string Filename = OrigFilename;
+    MaybeAddSystemRootToFilename(F, Filename);
+    const FileEntry *File 
+      = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime)
+                  : FileMgr.getFile(Filename, /*OpenFile=*/false);
+    
+    // If we didn't find the file, resolve it relative to the
+    // original directory from which this AST file was created.
+    if (File == 0 && !F.OriginalDir.empty() && !CurrentDir.empty() &&
+        F.OriginalDir != CurrentDir) {
+      std::string Resolved = resolveFileRelativeToOriginalDir(Filename,
+                                                              F.OriginalDir,
+                                                              CurrentDir);
+      if (!Resolved.empty())
+        File = FileMgr.getFile(Resolved);
+    }
+    
+    // For an overridden file, create a virtual file with the stored
+    // size/timestamp.
+    if (Overridden && File == 0) {
+      File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime);
+    }
+    
+    if (File == 0) {
+      if (Complain) {
+        std::string ErrorStr = "could not find file '";
+        ErrorStr += Filename;
+        ErrorStr += "' referenced by AST file";
+        Error(ErrorStr.c_str());
+      }
+      return InputFile();
+    }
+    
+    // Note that we've loaded this input file.
+    F.InputFilesLoaded[ID-1] = InputFile(File, Overridden);
+    
+    // Check if there was a request to override the contents of the file
+    // that was part of the precompiled header. Overridding such a file
+    // can lead to problems when lexing using the source locations from the
+    // PCH.
+    SourceManager &SM = getSourceManager();
+    if (!Overridden && SM.isFileOverridden(File)) {
+      Error(diag::err_fe_pch_file_overridden, Filename);
+      // After emitting the diagnostic, recover by disabling the override so
+      // that the original file will be used.
+      SM.disableFileContentsOverride(File);
+      // The FileEntry is a virtual file entry with the size of the contents
+      // that would override the original contents. Set it to the original's
+      // size/time.
+      FileMgr.modifyFileEntry(const_cast<FileEntry*>(File),
+                              StoredSize, StoredTime);
+    }
+
+    // For an overridden file, there is nothing to validate.
+    if (Overridden)
+      return InputFile(File, Overridden);
+
+    if ((StoredSize != File->getSize()
+#if !defined(LLVM_ON_WIN32)
+         // In our regression testing, the Windows file system seems to
+         // have inconsistent modification times that sometimes
+         // erroneously trigger this error-handling path.
+         || StoredTime != File->getModificationTime()
+#endif
+         )) {
+      if (Complain)
+        Error(diag::err_fe_pch_file_modified, Filename);
+      
+      return InputFile();
+    }
+
+    return InputFile(File, Overridden);
+  }
+  }
+
+  return InputFile();
+}
+
+const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) {
+  ModuleFile &M = ModuleMgr.getPrimaryModule();
+  std::string Filename = filenameStrRef;
+  MaybeAddSystemRootToFilename(M, Filename);
+  const FileEntry *File = FileMgr.getFile(Filename);
+  if (File == 0 && !M.OriginalDir.empty() && !CurrentDir.empty() &&
+      M.OriginalDir != CurrentDir) {
+    std::string resolved = resolveFileRelativeToOriginalDir(Filename,
+                                                            M.OriginalDir,
+                                                            CurrentDir);
+    if (!resolved.empty())
+      File = FileMgr.getFile(resolved);
+  }
+
+  return File;
+}
+
+/// \brief If we are loading a relocatable PCH file, and the filename is
+/// not an absolute path, add the system root to the beginning of the file
+/// name.
+void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M,
+                                             std::string &Filename) {
+  // If this is not a relocatable PCH file, there's nothing to do.
+  if (!M.RelocatablePCH)
+    return;
+
+  if (Filename.empty() || llvm::sys::path::is_absolute(Filename))
+    return;
+
+  if (isysroot.empty()) {
+    // If no system root was given, default to '/'
+    Filename.insert(Filename.begin(), '/');
+    return;
+  }
+
+  unsigned Length = isysroot.size();
+  if (isysroot[Length - 1] != '/')
+    Filename.insert(Filename.begin(), '/');
+
+  Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end());
+}
+
+ASTReader::ASTReadResult
+ASTReader::ReadControlBlock(ModuleFile &F,
+                            llvm::SmallVectorImpl<ImportedModule> &Loaded,
+                            unsigned ClientLoadCapabilities) {
+  llvm::BitstreamCursor &Stream = F.Stream;
+
+  if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
+    Error("malformed block record in AST file");
+    return Failure;
+  }
+
+  // Read all of the records and blocks in the control block.
+  RecordData Record;
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd()) {
+        Error("error at end of control block in AST file");
+        return Failure;
+      }
+
+      // Validate all of the input files.
+      if (!DisableValidation) {
+        bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
+        for (unsigned I = 0, N = Record[0]; I < N; ++I)
+          if (!getInputFile(F, I+1, Complain).getPointer())
+            return OutOfDate;
+      }
+
+      return Success;
+    }
+
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      switch (Stream.ReadSubBlockID()) {
+      case INPUT_FILES_BLOCK_ID:
+        F.InputFilesCursor = Stream;
+        if (Stream.SkipBlock() || // Skip with the main cursor
+            // Read the abbreviations
+            ReadBlockAbbrevs(F.InputFilesCursor, INPUT_FILES_BLOCK_ID)) {
+          Error("malformed block record in AST file");
+          return Failure;
+        }
+        continue;
+        
+      default:
+        if (!Stream.SkipBlock())
+          continue;
+        break;
+      }
+
+      Error("malformed block record in AST file");
+      return Failure;
+    }
+
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read and process a record.
+    Record.clear();
+    const char *BlobStart = 0;
+    unsigned BlobLen = 0;
+    switch ((ControlRecordTypes)Stream.ReadRecord(Code, Record,
+                                                  &BlobStart, &BlobLen)) {
+    case METADATA: {
+      if (Record[0] != VERSION_MAJOR && !DisableValidation) {
+        if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
+          Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
+                                        : diag::warn_pch_version_too_new);
+        return VersionMismatch;
+      }
+
+      bool hasErrors = Record[5];
+      if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {
+        Diag(diag::err_pch_with_compiler_errors);
+        return HadErrors;
+      }
+
+      F.RelocatablePCH = Record[4];
+
+      const std::string &CurBranch = getClangFullRepositoryVersion();
+      StringRef ASTBranch(BlobStart, BlobLen);
+      if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {
+        if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
+          Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch;
+        return VersionMismatch;
+      }
+      break;
+    }
+
+    case IMPORTS: {
+      // Load each of the imported PCH files. 
+      unsigned Idx = 0, N = Record.size();
+      while (Idx < N) {
+        // Read information about the AST file.
+        ModuleKind ImportedKind = (ModuleKind)Record[Idx++];
+        // The import location will be the local one for now; we will adjust
+        // all import locations of module imports after the global source
+        // location info are setup.
+        SourceLocation ImportLoc =
+            SourceLocation::getFromRawEncoding(Record[Idx++]);
+        unsigned Length = Record[Idx++];
+        SmallString<128> ImportedFile(Record.begin() + Idx,
+                                      Record.begin() + Idx + Length);
+        Idx += Length;
+
+        // Load the AST file.
+        switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded,
+                           ClientLoadCapabilities)) {
+        case Failure: return Failure;
+          // If we have to ignore the dependency, we'll have to ignore this too.
+        case OutOfDate: return OutOfDate;
+        case VersionMismatch: return VersionMismatch;
+        case ConfigurationMismatch: return ConfigurationMismatch;
+        case HadErrors: return HadErrors;
+        case Success: break;
+        }
+      }
+      break;
+    }
+
+    case LANGUAGE_OPTIONS: {
+      bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
+      if (Listener && &F == *ModuleMgr.begin() &&
+          ParseLanguageOptions(Record, Complain, *Listener) &&
+          !DisableValidation)
+        return ConfigurationMismatch;
+      break;
+    }
+
+    case TARGET_OPTIONS: {
+      bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+      if (Listener && &F == *ModuleMgr.begin() &&
+          ParseTargetOptions(Record, Complain, *Listener) &&
+          !DisableValidation)
+        return ConfigurationMismatch;
+      break;
+    }
+
+    case DIAGNOSTIC_OPTIONS: {
+      bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+      if (Listener && &F == *ModuleMgr.begin() &&
+          ParseDiagnosticOptions(Record, Complain, *Listener) &&
+          !DisableValidation)
+        return ConfigurationMismatch;
+      break;
+    }
+
+    case FILE_SYSTEM_OPTIONS: {
+      bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+      if (Listener && &F == *ModuleMgr.begin() &&
+          ParseFileSystemOptions(Record, Complain, *Listener) &&
+          !DisableValidation)
+        return ConfigurationMismatch;
+      break;
+    }
+
+    case HEADER_SEARCH_OPTIONS: {
+      bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+      if (Listener && &F == *ModuleMgr.begin() &&
+          ParseHeaderSearchOptions(Record, Complain, *Listener) &&
+          !DisableValidation)
+        return ConfigurationMismatch;
+      break;
+    }
+
+    case PREPROCESSOR_OPTIONS: {
+      bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+      if (Listener && &F == *ModuleMgr.begin() &&
+          ParsePreprocessorOptions(Record, Complain, *Listener,
+                                   SuggestedPredefines) &&
+          !DisableValidation)
+        return ConfigurationMismatch;
+      break;
+    }
+
+    case ORIGINAL_FILE:
+      F.OriginalSourceFileID = FileID::get(Record[0]);
+      F.ActualOriginalSourceFileName.assign(BlobStart, BlobLen);
+      F.OriginalSourceFileName = F.ActualOriginalSourceFileName;
+      MaybeAddSystemRootToFilename(F, F.OriginalSourceFileName);
+      break;
+
+    case ORIGINAL_FILE_ID:
+      F.OriginalSourceFileID = FileID::get(Record[0]);
+      break;
+
+    case ORIGINAL_PCH_DIR:
+      F.OriginalDir.assign(BlobStart, BlobLen);
+      break;
+
+    case INPUT_FILE_OFFSETS:
+      F.InputFileOffsets = (const uint32_t *)BlobStart;
+      F.InputFilesLoaded.resize(Record[0]);
+      break;
+    }
+  }
+
+  Error("premature end of bitstream in AST file");
+  return Failure;
+}
+
+bool ASTReader::ReadASTBlock(ModuleFile &F) {
+  llvm::BitstreamCursor &Stream = F.Stream;
+
+  if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
+    Error("malformed block record in AST file");
+    return true;
+  }
+
+  // Read all of the records and blocks for the AST file.
+  RecordData Record;
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd()) {
+        Error("error at end of module block in AST file");
+        return true;
+      }
+
+      DeclContext *DC = Context.getTranslationUnitDecl();
+      if (!DC->hasExternalVisibleStorage() && DC->hasExternalLexicalStorage())
+        DC->setMustBuildLookupTable();
+
+      return false;
+    }
+
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      switch (Stream.ReadSubBlockID()) {
+      case DECLTYPES_BLOCK_ID:
+        // We lazily load the decls block, but we want to set up the
+        // DeclsCursor cursor to point into it.  Clone our current bitcode
+        // cursor to it, enter the block and read the abbrevs in that block.
+        // With the main cursor, we just skip over it.
+        F.DeclsCursor = Stream;
+        if (Stream.SkipBlock() ||  // Skip with the main cursor.
+            // Read the abbrevs.
+            ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) {
+          Error("malformed block record in AST file");
+          return true;
+        }
+        break;
+
+      case DECL_UPDATES_BLOCK_ID:
+        if (Stream.SkipBlock()) {
+          Error("malformed block record in AST file");
+          return true;
+        }
+        break;
+
+      case PREPROCESSOR_BLOCK_ID:
+        F.MacroCursor = Stream;
+        if (!PP.getExternalSource())
+          PP.setExternalSource(this);
+
+        if (Stream.SkipBlock() ||
+            ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) {
+          Error("malformed block record in AST file");
+          return true;
+        }
+        F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo();
+        break;
+
+      case PREPROCESSOR_DETAIL_BLOCK_ID:
+        F.PreprocessorDetailCursor = Stream;
+        if (Stream.SkipBlock() ||
+            ReadBlockAbbrevs(F.PreprocessorDetailCursor, 
+                             PREPROCESSOR_DETAIL_BLOCK_ID)) {
+          Error("malformed preprocessor detail record in AST file");
+          return true;
+        }
+        F.PreprocessorDetailStartOffset
+          = F.PreprocessorDetailCursor.GetCurrentBitNo();
+          
+        if (!PP.getPreprocessingRecord())
+          PP.createPreprocessingRecord();
+        if (!PP.getPreprocessingRecord()->getExternalSource())
+          PP.getPreprocessingRecord()->SetExternalSource(*this);
+        break;
+        
+      case SOURCE_MANAGER_BLOCK_ID:
+        if (ReadSourceManagerBlock(F))
+          return true;
+        break;
+
+      case SUBMODULE_BLOCK_ID:
+        if (ReadSubmoduleBlock(F))
+          return true;
+        break;
+
+      case COMMENTS_BLOCK_ID: {
+        llvm::BitstreamCursor C = Stream;
+        if (Stream.SkipBlock() ||
+            ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) {
+          Error("malformed comments block in AST file");
+          return true;
+        }
+        CommentsCursors.push_back(std::make_pair(C, &F));
+        break;
+      }
+
+      default:
+        if (!Stream.SkipBlock())
+          break;
+        Error("malformed block record in AST file");
+        return true;
+      }
+      continue;
+    }
+
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read and process a record.
+    Record.clear();
+    const char *BlobStart = 0;
+    unsigned BlobLen = 0;
+    switch ((ASTRecordTypes)Stream.ReadRecord(Code, Record,
+                                              &BlobStart, &BlobLen)) {
+    default:  // Default behavior: ignore.
+      break;
+
+    case TYPE_OFFSET: {
+      if (F.LocalNumTypes != 0) {
+        Error("duplicate TYPE_OFFSET record in AST file");
+        return true;
+      }
+      F.TypeOffsets = (const uint32_t *)BlobStart;
+      F.LocalNumTypes = Record[0];
+      unsigned LocalBaseTypeIndex = Record[1];
+      F.BaseTypeIndex = getTotalNumTypes();
+        
+      if (F.LocalNumTypes > 0) {
+        // Introduce the global -> local mapping for types within this module.
+        GlobalTypeMap.insert(std::make_pair(getTotalNumTypes(), &F));
+        
+        // Introduce the local -> global mapping for types within this module.
+        F.TypeRemap.insertOrReplace(
+          std::make_pair(LocalBaseTypeIndex, 
+                         F.BaseTypeIndex - LocalBaseTypeIndex));
+        
+        TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes);
+      }
+      break;
+    }
+        
+    case DECL_OFFSET: {
+      if (F.LocalNumDecls != 0) {
+        Error("duplicate DECL_OFFSET record in AST file");
+        return true;
+      }
+      F.DeclOffsets = (const DeclOffset *)BlobStart;
+      F.LocalNumDecls = Record[0];
+      unsigned LocalBaseDeclID = Record[1];
+      F.BaseDeclID = getTotalNumDecls();
+        
+      if (F.LocalNumDecls > 0) {
+        // Introduce the global -> local mapping for declarations within this 
+        // module.
+        GlobalDeclMap.insert(
+          std::make_pair(getTotalNumDecls() + NUM_PREDEF_DECL_IDS, &F));
+        
+        // Introduce the local -> global mapping for declarations within this
+        // module.
+        F.DeclRemap.insertOrReplace(
+          std::make_pair(LocalBaseDeclID, F.BaseDeclID - LocalBaseDeclID));
+        
+        // Introduce the global -> local mapping for declarations within this
+        // module.
+        F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID;
+        
+        DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);
+      }
+      break;
+    }
+        
+    case TU_UPDATE_LEXICAL: {
+      DeclContext *TU = Context.getTranslationUnitDecl();
+      DeclContextInfo &Info = F.DeclContextInfos[TU];
+      Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair *>(BlobStart);
+      Info.NumLexicalDecls 
+        = static_cast<unsigned int>(BlobLen / sizeof(KindDeclIDPair));
+      TU->setHasExternalLexicalStorage(true);
+      break;
+    }
+
+    case UPDATE_VISIBLE: {
+      unsigned Idx = 0;
+      serialization::DeclID ID = ReadDeclID(F, Record, Idx);
+      ASTDeclContextNameLookupTable *Table =
+        ASTDeclContextNameLookupTable::Create(
+                        (const unsigned char *)BlobStart + Record[Idx++],
+                        (const unsigned char *)BlobStart,
+                        ASTDeclContextNameLookupTrait(*this, F));
+      if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID) { // Is it the TU?
+        DeclContext *TU = Context.getTranslationUnitDecl();
+        F.DeclContextInfos[TU].NameLookupTableData = Table;
+        TU->setHasExternalVisibleStorage(true);
+      } else
+        PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F));
+      break;
+    }
+
+    case IDENTIFIER_TABLE:
+      F.IdentifierTableData = BlobStart;
+      if (Record[0]) {
+        F.IdentifierLookupTable
+          = ASTIdentifierLookupTable::Create(
+                       (const unsigned char *)F.IdentifierTableData + Record[0],
+                       (const unsigned char *)F.IdentifierTableData,
+                       ASTIdentifierLookupTrait(*this, F));
+        
+        PP.getIdentifierTable().setExternalIdentifierLookup(this);
+      }
+      break;
+
+    case IDENTIFIER_OFFSET: {
+      if (F.LocalNumIdentifiers != 0) {
+        Error("duplicate IDENTIFIER_OFFSET record in AST file");
+        return true;
+      }
+      F.IdentifierOffsets = (const uint32_t *)BlobStart;
+      F.LocalNumIdentifiers = Record[0];
+      unsigned LocalBaseIdentifierID = Record[1];
+      F.BaseIdentifierID = getTotalNumIdentifiers();
+        
+      if (F.LocalNumIdentifiers > 0) {
+        // Introduce the global -> local mapping for identifiers within this
+        // module.
+        GlobalIdentifierMap.insert(std::make_pair(getTotalNumIdentifiers() + 1, 
+                                                  &F));
+        
+        // Introduce the local -> global mapping for identifiers within this
+        // module.
+        F.IdentifierRemap.insertOrReplace(
+          std::make_pair(LocalBaseIdentifierID,
+                         F.BaseIdentifierID - LocalBaseIdentifierID));
+        
+        IdentifiersLoaded.resize(IdentifiersLoaded.size() 
+                                 + F.LocalNumIdentifiers);
+      }
+      break;
+    }
+
+    case EXTERNAL_DEFINITIONS:
+      for (unsigned I = 0, N = Record.size(); I != N; ++I)
+        ExternalDefinitions.push_back(getGlobalDeclID(F, Record[I]));
+      break;
+
+    case SPECIAL_TYPES:
+      for (unsigned I = 0, N = Record.size(); I != N; ++I)
+        SpecialTypes.push_back(getGlobalTypeID(F, Record[I]));
+      break;
+
+    case STATISTICS:
+      TotalNumStatements += Record[0];
+      TotalNumMacros += Record[1];
+      TotalLexicalDeclContexts += Record[2];
+      TotalVisibleDeclContexts += Record[3];
+      break;
+
+    case UNUSED_FILESCOPED_DECLS:
+      for (unsigned I = 0, N = Record.size(); I != N; ++I)
+        UnusedFileScopedDecls.push_back(getGlobalDeclID(F, Record[I]));
+      break;
+
+    case DELEGATING_CTORS:
+      for (unsigned I = 0, N = Record.size(); I != N; ++I)
+        DelegatingCtorDecls.push_back(getGlobalDeclID(F, Record[I]));
+      break;
+
+    case WEAK_UNDECLARED_IDENTIFIERS:
+      if (Record.size() % 4 != 0) {
+        Error("invalid weak identifiers record");
+        return true;
+      }
+        
+      // FIXME: Ignore weak undeclared identifiers from non-original PCH 
+      // files. This isn't the way to do it :)
+      WeakUndeclaredIdentifiers.clear();
+        
+      // Translate the weak, undeclared identifiers into global IDs.
+      for (unsigned I = 0, N = Record.size(); I < N; /* in loop */) {
+        WeakUndeclaredIdentifiers.push_back(
+          getGlobalIdentifierID(F, Record[I++]));
+        WeakUndeclaredIdentifiers.push_back(
+          getGlobalIdentifierID(F, Record[I++]));
+        WeakUndeclaredIdentifiers.push_back(
+          ReadSourceLocation(F, Record, I).getRawEncoding());
+        WeakUndeclaredIdentifiers.push_back(Record[I++]);
+      }
+      break;
+
+    case LOCALLY_SCOPED_EXTERNAL_DECLS:
+      for (unsigned I = 0, N = Record.size(); I != N; ++I)
+        LocallyScopedExternalDecls.push_back(getGlobalDeclID(F, Record[I]));
+      break;
+
+    case SELECTOR_OFFSETS: {
+      F.SelectorOffsets = (const uint32_t *)BlobStart;
+      F.LocalNumSelectors = Record[0];
+      unsigned LocalBaseSelectorID = Record[1];
+      F.BaseSelectorID = getTotalNumSelectors();
+        
+      if (F.LocalNumSelectors > 0) {
+        // Introduce the global -> local mapping for selectors within this 
+        // module.
+        GlobalSelectorMap.insert(std::make_pair(getTotalNumSelectors()+1, &F));
+        
+        // Introduce the local -> global mapping for selectors within this 
+        // module.
+        F.SelectorRemap.insertOrReplace(
+          std::make_pair(LocalBaseSelectorID,
+                         F.BaseSelectorID - LocalBaseSelectorID));
+
+        SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors);        
+      }
+      break;
+    }
+        
+    case METHOD_POOL:
+      F.SelectorLookupTableData = (const unsigned char *)BlobStart;
+      if (Record[0])
+        F.SelectorLookupTable
+          = ASTSelectorLookupTable::Create(
+                        F.SelectorLookupTableData + Record[0],
+                        F.SelectorLookupTableData,
+                        ASTSelectorLookupTrait(*this, F));
+      TotalNumMethodPoolEntries += Record[1];
+      break;
+
+    case REFERENCED_SELECTOR_POOL:
+      if (!Record.empty()) {
+        for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) {
+          ReferencedSelectorsData.push_back(getGlobalSelectorID(F, 
+                                                                Record[Idx++]));
+          ReferencedSelectorsData.push_back(ReadSourceLocation(F, Record, Idx).
+                                              getRawEncoding());
+        }
+      }
+      break;
+
+    case PP_COUNTER_VALUE:
+      if (!Record.empty() && Listener)
+        Listener->ReadCounter(F, Record[0]);
+      break;
+      
+    case FILE_SORTED_DECLS:
+      F.FileSortedDecls = (const DeclID *)BlobStart;
+      F.NumFileSortedDecls = Record[0];
+      break;
+
+    case SOURCE_LOCATION_OFFSETS: {
+      F.SLocEntryOffsets = (const uint32_t *)BlobStart;
+      F.LocalNumSLocEntries = Record[0];
+      unsigned SLocSpaceSize = Record[1];
+      llvm::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) =
+          SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries,
+                                              SLocSpaceSize);
+      // Make our entry in the range map. BaseID is negative and growing, so
+      // we invert it. Because we invert it, though, we need the other end of
+      // the range.
+      unsigned RangeStart =
+          unsigned(-F.SLocEntryBaseID) - F.LocalNumSLocEntries + 1;
+      GlobalSLocEntryMap.insert(std::make_pair(RangeStart, &F));
+      F.FirstLoc = SourceLocation::getFromRawEncoding(F.SLocEntryBaseOffset);
+
+      // SLocEntryBaseOffset is lower than MaxLoadedOffset and decreasing.
+      assert((F.SLocEntryBaseOffset & (1U << 31U)) == 0);
+      GlobalSLocOffsetMap.insert(
+          std::make_pair(SourceManager::MaxLoadedOffset - F.SLocEntryBaseOffset
+                           - SLocSpaceSize,&F));
+
+      // Initialize the remapping table.
+      // Invalid stays invalid.
+      F.SLocRemap.insert(std::make_pair(0U, 0));
+      // This module. Base was 2 when being compiled.
+      F.SLocRemap.insert(std::make_pair(2U,
+                                  static_cast<int>(F.SLocEntryBaseOffset - 2)));
+      
+      TotalNumSLocEntries += F.LocalNumSLocEntries;
+      break;
+    }
+
+    case MODULE_OFFSET_MAP: {
+      // Additional remapping information.
+      const unsigned char *Data = (const unsigned char*)BlobStart;
+      const unsigned char *DataEnd = Data + BlobLen;
+      
+      // Continuous range maps we may be updating in our module.
+      ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap);
+      ContinuousRangeMap<uint32_t, int, 2>::Builder 
+        IdentifierRemap(F.IdentifierRemap);
+      ContinuousRangeMap<uint32_t, int, 2>::Builder
+        MacroRemap(F.MacroRemap);
+      ContinuousRangeMap<uint32_t, int, 2>::Builder
+        PreprocessedEntityRemap(F.PreprocessedEntityRemap);
+      ContinuousRangeMap<uint32_t, int, 2>::Builder 
+        SubmoduleRemap(F.SubmoduleRemap);
+      ContinuousRangeMap<uint32_t, int, 2>::Builder 
+        SelectorRemap(F.SelectorRemap);
+      ContinuousRangeMap<uint32_t, int, 2>::Builder DeclRemap(F.DeclRemap);
+      ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap);
+
+      while(Data < DataEnd) {
+        uint16_t Len = io::ReadUnalignedLE16(Data);
+        StringRef Name = StringRef((const char*)Data, Len);
+        Data += Len;
+        ModuleFile *OM = ModuleMgr.lookup(Name);
+        if (!OM) {
+          Error("SourceLocation remap refers to unknown module");
+          return true;
+        }
+
+        uint32_t SLocOffset = io::ReadUnalignedLE32(Data);
+        uint32_t IdentifierIDOffset = io::ReadUnalignedLE32(Data);
+        uint32_t MacroIDOffset = io::ReadUnalignedLE32(Data);
+        uint32_t PreprocessedEntityIDOffset = io::ReadUnalignedLE32(Data);
+        uint32_t SubmoduleIDOffset = io::ReadUnalignedLE32(Data);
+        uint32_t SelectorIDOffset = io::ReadUnalignedLE32(Data);
+        uint32_t DeclIDOffset = io::ReadUnalignedLE32(Data);
+        uint32_t TypeIndexOffset = io::ReadUnalignedLE32(Data);
+        
+        // Source location offset is mapped to OM->SLocEntryBaseOffset.
+        SLocRemap.insert(std::make_pair(SLocOffset,
+          static_cast<int>(OM->SLocEntryBaseOffset - SLocOffset)));
+        IdentifierRemap.insert(
+          std::make_pair(IdentifierIDOffset, 
+                         OM->BaseIdentifierID - IdentifierIDOffset));
+        MacroRemap.insert(std::make_pair(MacroIDOffset,
+                                         OM->BaseMacroID - MacroIDOffset));
+        PreprocessedEntityRemap.insert(
+          std::make_pair(PreprocessedEntityIDOffset, 
+            OM->BasePreprocessedEntityID - PreprocessedEntityIDOffset));
+        SubmoduleRemap.insert(std::make_pair(SubmoduleIDOffset, 
+                                      OM->BaseSubmoduleID - SubmoduleIDOffset));
+        SelectorRemap.insert(std::make_pair(SelectorIDOffset, 
+                               OM->BaseSelectorID - SelectorIDOffset));
+        DeclRemap.insert(std::make_pair(DeclIDOffset, 
+                                        OM->BaseDeclID - DeclIDOffset));
+        
+        TypeRemap.insert(std::make_pair(TypeIndexOffset, 
+                                    OM->BaseTypeIndex - TypeIndexOffset));
+
+        // Global -> local mappings.
+        F.GlobalToLocalDeclIDs[OM] = DeclIDOffset;
+      }
+      break;
+    }
+
+    case SOURCE_MANAGER_LINE_TABLE:
+      if (ParseLineTable(F, Record))
+        return true;
+      break;
+
+    case SOURCE_LOCATION_PRELOADS: {
+      // Need to transform from the local view (1-based IDs) to the global view,
+      // which is based off F.SLocEntryBaseID.
+      if (!F.PreloadSLocEntries.empty()) {
+        Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file");
+        return true;
+      }
+      
+      F.PreloadSLocEntries.swap(Record);
+      break;
+    }
+
+    case EXT_VECTOR_DECLS:
+      for (unsigned I = 0, N = Record.size(); I != N; ++I)
+        ExtVectorDecls.push_back(getGlobalDeclID(F, Record[I]));
+      break;
+
+    case VTABLE_USES:
+      if (Record.size() % 3 != 0) {
+        Error("Invalid VTABLE_USES record");
+        return true;
+      }
+        
+      // Later tables overwrite earlier ones.
+      // FIXME: Modules will have some trouble with this. This is clearly not
+      // the right way to do this.
+      VTableUses.clear();
+        
+      for (unsigned Idx = 0, N = Record.size(); Idx != N; /* In loop */) {
+        VTableUses.push_back(getGlobalDeclID(F, Record[Idx++]));
+        VTableUses.push_back(
+          ReadSourceLocation(F, Record, Idx).getRawEncoding());
+        VTableUses.push_back(Record[Idx++]);
+      }
+      break;
+
+    case DYNAMIC_CLASSES:
+      for (unsigned I = 0, N = Record.size(); I != N; ++I)
+        DynamicClasses.push_back(getGlobalDeclID(F, Record[I]));
+      break;
+
+    case PENDING_IMPLICIT_INSTANTIATIONS:
+      if (PendingInstantiations.size() % 2 != 0) {
+        Error("Invalid existing PendingInstantiations");
+        return true;
+      }
+
+      if (Record.size() % 2 != 0) {
+        Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block");
+        return true;
+      }
+
+      for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
+        PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++]));
+        PendingInstantiations.push_back(
+          ReadSourceLocation(F, Record, I).getRawEncoding());
+      }
+      break;
+
+    case SEMA_DECL_REFS:
+      // Later tables overwrite earlier ones.
+      // FIXME: Modules will have some trouble with this.
+      SemaDeclRefs.clear();
+      for (unsigned I = 0, N = Record.size(); I != N; ++I)
+        SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I]));
+      break;
+
+    case PPD_ENTITIES_OFFSETS: {
+      F.PreprocessedEntityOffsets = (const PPEntityOffset *)BlobStart;
+      assert(BlobLen % sizeof(PPEntityOffset) == 0);
+      F.NumPreprocessedEntities = BlobLen / sizeof(PPEntityOffset);
+
+      unsigned LocalBasePreprocessedEntityID = Record[0];
+      
+      unsigned StartingID;
+      if (!PP.getPreprocessingRecord())
+        PP.createPreprocessingRecord();
+      if (!PP.getPreprocessingRecord()->getExternalSource())
+        PP.getPreprocessingRecord()->SetExternalSource(*this);
+      StartingID 
+        = PP.getPreprocessingRecord()
+            ->allocateLoadedEntities(F.NumPreprocessedEntities);
+      F.BasePreprocessedEntityID = StartingID;
+
+      if (F.NumPreprocessedEntities > 0) {
+        // Introduce the global -> local mapping for preprocessed entities in
+        // this module.
+        GlobalPreprocessedEntityMap.insert(std::make_pair(StartingID, &F));
+       
+        // Introduce the local -> global mapping for preprocessed entities in
+        // this module.
+        F.PreprocessedEntityRemap.insertOrReplace(
+          std::make_pair(LocalBasePreprocessedEntityID,
+            F.BasePreprocessedEntityID - LocalBasePreprocessedEntityID));
+      }
+
+      break;
+    }
+        
+    case DECL_UPDATE_OFFSETS: {
+      if (Record.size() % 2 != 0) {
+        Error("invalid DECL_UPDATE_OFFSETS block in AST file");
+        return true;
+      }
+      for (unsigned I = 0, N = Record.size(); I != N; I += 2)
+        DeclUpdateOffsets[getGlobalDeclID(F, Record[I])]
+          .push_back(std::make_pair(&F, Record[I+1]));
+      break;
+    }
+
+    case DECL_REPLACEMENTS: {
+      if (Record.size() % 3 != 0) {
+        Error("invalid DECL_REPLACEMENTS block in AST file");
+        return true;
+      }
+      for (unsigned I = 0, N = Record.size(); I != N; I += 3)
+        ReplacedDecls[getGlobalDeclID(F, Record[I])]
+          = ReplacedDeclInfo(&F, Record[I+1], Record[I+2]);
+      break;
+    }
+
+    case OBJC_CATEGORIES_MAP: {
+      if (F.LocalNumObjCCategoriesInMap != 0) {
+        Error("duplicate OBJC_CATEGORIES_MAP record in AST file");
+        return true;
+      }
+      
+      F.LocalNumObjCCategoriesInMap = Record[0];
+      F.ObjCCategoriesMap = (const ObjCCategoriesInfo *)BlobStart;
+      break;
+    }
+        
+    case OBJC_CATEGORIES:
+      F.ObjCCategories.swap(Record);
+      break;
+        
+    case CXX_BASE_SPECIFIER_OFFSETS: {
+      if (F.LocalNumCXXBaseSpecifiers != 0) {
+        Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file");
+        return true;
+      }
+      
+      F.LocalNumCXXBaseSpecifiers = Record[0];
+      F.CXXBaseSpecifiersOffsets = (const uint32_t *)BlobStart;
+      NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers;
+      break;
+    }
+
+    case DIAG_PRAGMA_MAPPINGS:
+      if (F.PragmaDiagMappings.empty())
+        F.PragmaDiagMappings.swap(Record);
+      else
+        F.PragmaDiagMappings.insert(F.PragmaDiagMappings.end(),
+                                    Record.begin(), Record.end());
+      break;
+        
+    case CUDA_SPECIAL_DECL_REFS:
+      // Later tables overwrite earlier ones.
+      // FIXME: Modules will have trouble with this.
+      CUDASpecialDeclRefs.clear();
+      for (unsigned I = 0, N = Record.size(); I != N; ++I)
+        CUDASpecialDeclRefs.push_back(getGlobalDeclID(F, Record[I]));
+      break;
+
+    case HEADER_SEARCH_TABLE: {
+      F.HeaderFileInfoTableData = BlobStart;
+      F.LocalNumHeaderFileInfos = Record[1];
+      F.HeaderFileFrameworkStrings = BlobStart + Record[2];
+      if (Record[0]) {
+        F.HeaderFileInfoTable
+          = HeaderFileInfoLookupTable::Create(
+                   (const unsigned char *)F.HeaderFileInfoTableData + Record[0],
+                   (const unsigned char *)F.HeaderFileInfoTableData,
+                   HeaderFileInfoTrait(*this, F, 
+                                       &PP.getHeaderSearchInfo(),
+                                       BlobStart + Record[2]));
+        
+        PP.getHeaderSearchInfo().SetExternalSource(this);
+        if (!PP.getHeaderSearchInfo().getExternalLookup())
+          PP.getHeaderSearchInfo().SetExternalLookup(this);
+      }
+      break;
+    }
+        
+    case FP_PRAGMA_OPTIONS:
+      // Later tables overwrite earlier ones.
+      FPPragmaOptions.swap(Record);
+      break;
+
+    case OPENCL_EXTENSIONS:
+      // Later tables overwrite earlier ones.
+      OpenCLExtensions.swap(Record);
+      break;
+
+    case TENTATIVE_DEFINITIONS:
+      for (unsigned I = 0, N = Record.size(); I != N; ++I)
+        TentativeDefinitions.push_back(getGlobalDeclID(F, Record[I]));
+      break;
+        
+    case KNOWN_NAMESPACES:
+      for (unsigned I = 0, N = Record.size(); I != N; ++I)
+        KnownNamespaces.push_back(getGlobalDeclID(F, Record[I]));
+      break;
+        
+    case IMPORTED_MODULES: {
+      if (F.Kind != MK_Module) {
+        // If we aren't loading a module (which has its own exports), make
+        // all of the imported modules visible.
+        // FIXME: Deal with macros-only imports.
+        for (unsigned I = 0, N = Record.size(); I != N; ++I) {
+          if (unsigned GlobalID = getGlobalSubmoduleID(F, Record[I]))
+            ImportedModules.push_back(GlobalID);
+        }
+      }
+      break;
+    }
+
+    case LOCAL_REDECLARATIONS: {
+      F.RedeclarationChains.swap(Record);
+      break;
+    }
+        
+    case LOCAL_REDECLARATIONS_MAP: {
+      if (F.LocalNumRedeclarationsInMap != 0) {
+        Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file");
+        return true;
+      }
+      
+      F.LocalNumRedeclarationsInMap = Record[0];
+      F.RedeclarationsMap = (const LocalRedeclarationsInfo *)BlobStart;
+      break;
+    }
+        
+    case MERGED_DECLARATIONS: {
+      for (unsigned Idx = 0; Idx < Record.size(); /* increment in loop */) {
+        GlobalDeclID CanonID = getGlobalDeclID(F, Record[Idx++]);
+        SmallVectorImpl<GlobalDeclID> &Decls = StoredMergedDecls[CanonID];
+        for (unsigned N = Record[Idx++]; N > 0; --N)
+          Decls.push_back(getGlobalDeclID(F, Record[Idx++]));
+      }
+      break;
+    }
+
+    case MACRO_OFFSET: {
+      if (F.LocalNumMacros != 0) {
+        Error("duplicate MACRO_OFFSET record in AST file");
+        return true;
+      }
+      F.MacroOffsets = (const uint32_t *)BlobStart;
+      F.LocalNumMacros = Record[0];
+      unsigned LocalBaseMacroID = Record[1];
+      F.BaseMacroID = getTotalNumMacros();
+
+      if (F.LocalNumMacros > 0) {
+        // Introduce the global -> local mapping for macros within this module.
+        GlobalMacroMap.insert(std::make_pair(getTotalNumMacros() + 1, &F));
+
+        // Introduce the local -> global mapping for macros within this module.
+        F.MacroRemap.insertOrReplace(
+          std::make_pair(LocalBaseMacroID,
+                         F.BaseMacroID - LocalBaseMacroID));
+
+        MacrosLoaded.resize(MacrosLoaded.size() + F.LocalNumMacros);
+      }
+      break;
+    }
+
+    case MACRO_UPDATES: {
+      for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
+        MacroID ID = getGlobalMacroID(F, Record[I++]);
+        if (I == N)
+          break;
+
+        SourceLocation UndefLoc = ReadSourceLocation(F, Record, I);
+        SubmoduleID SubmoduleID = getGlobalSubmoduleID(F, Record[I++]);;
+        MacroUpdate Update;
+        Update.UndefLoc = UndefLoc;
+        MacroUpdates[ID].push_back(std::make_pair(SubmoduleID, Update));
+      }
+      break;
+    }
+    }
+  }
+  Error("premature end of bitstream in AST file");
+  return true;
+}
+
+void ASTReader::makeNamesVisible(const HiddenNames &Names) {
+  for (unsigned I = 0, N = Names.size(); I != N; ++I) {
+    switch (Names[I].getKind()) {
+    case HiddenName::Declaration:
+      Names[I].getDecl()->Hidden = false;
+      break;
+
+    case HiddenName::MacroVisibility: {
+      std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
+      Macro.second->setHidden(!Macro.second->isPublic());
+      if (Macro.second->isDefined()) {
+        PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
+      }
+      break;
+    }
+
+    case HiddenName::MacroUndef: {
+      std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
+      if (Macro.second->isDefined()) {
+        Macro.second->setUndefLoc(Names[I].getMacroUndefLoc());
+        if (PPMutationListener *Listener = PP.getPPMutationListener())
+          Listener->UndefinedMacro(Macro.second);
+        PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
+      }
+      break;
+    }
+    }
+  }
+}
+
+void ASTReader::makeModuleVisible(Module *Mod, 
+                                  Module::NameVisibilityKind NameVisibility) {
+  llvm::SmallPtrSet<Module *, 4> Visited;
+  llvm::SmallVector<Module *, 4> Stack;
+  Stack.push_back(Mod);  
+  while (!Stack.empty()) {
+    Mod = Stack.back();
+    Stack.pop_back();
+
+    if (NameVisibility <= Mod->NameVisibility) {
+      // This module already has this level of visibility (or greater), so 
+      // there is nothing more to do.
+      continue;
+    }
+    
+    if (!Mod->isAvailable()) {
+      // Modules that aren't available cannot be made visible.
+      continue;
+    }
+
+    // Update the module's name visibility.
+    Mod->NameVisibility = NameVisibility;
+    
+    // If we've already deserialized any names from this module,
+    // mark them as visible.
+    HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod);
+    if (Hidden != HiddenNamesMap.end()) {
+      makeNamesVisible(Hidden->second);
+      HiddenNamesMap.erase(Hidden);
+    }
+    
+    // Push any non-explicit submodules onto the stack to be marked as
+    // visible.
+    for (Module::submodule_iterator Sub = Mod->submodule_begin(),
+                                 SubEnd = Mod->submodule_end();
+         Sub != SubEnd; ++Sub) {
+      if (!(*Sub)->IsExplicit && Visited.insert(*Sub))
+        Stack.push_back(*Sub);
+    }
+    
+    // Push any exported modules onto the stack to be marked as visible.
+    bool AnyWildcard = false;
+    bool UnrestrictedWildcard = false;
+    llvm::SmallVector<Module *, 4> WildcardRestrictions;
+    for (unsigned I = 0, N = Mod->Exports.size(); I != N; ++I) {
+      Module *Exported = Mod->Exports[I].getPointer();
+      if (!Mod->Exports[I].getInt()) {
+        // Export a named module directly; no wildcards involved.
+        if (Visited.insert(Exported))
+          Stack.push_back(Exported);
+        
+        continue;
+      }
+      
+      // Wildcard export: export all of the imported modules that match
+      // the given pattern.
+      AnyWildcard = true;
+      if (UnrestrictedWildcard)
+        continue;
+
+      if (Module *Restriction = Mod->Exports[I].getPointer())
+        WildcardRestrictions.push_back(Restriction);
+      else {
+        WildcardRestrictions.clear();
+        UnrestrictedWildcard = true;
+      }
+    }
+    
+    // If there were any wildcards, push any imported modules that were
+    // re-exported by the wildcard restriction.
+    if (!AnyWildcard)
+      continue;
+    
+    for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) {
+      Module *Imported = Mod->Imports[I];
+      if (!Visited.insert(Imported))
+        continue;
+      
+      bool Acceptable = UnrestrictedWildcard;
+      if (!Acceptable) {
+        // Check whether this module meets one of the restrictions.
+        for (unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) {
+          Module *Restriction = WildcardRestrictions[R];
+          if (Imported == Restriction || Imported->isSubModuleOf(Restriction)) {
+            Acceptable = true;
+            break;
+          }
+        }
+      }
+      
+      if (!Acceptable)
+        continue;
+      
+      Stack.push_back(Imported);
+    }
+  }
+}
+
+ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
+                                            ModuleKind Type,
+                                            SourceLocation ImportLoc,
+                                            unsigned ClientLoadCapabilities) {
+  // Bump the generation number.
+  unsigned PreviousGeneration = CurrentGeneration++;
+
+  unsigned NumModules = ModuleMgr.size();
+  llvm::SmallVector<ImportedModule, 4> Loaded;
+  switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc,
+                                                /*ImportedBy=*/0, Loaded,
+                                                ClientLoadCapabilities)) {
+  case Failure:
+  case OutOfDate:
+  case VersionMismatch:
+  case ConfigurationMismatch:
+  case HadErrors:
+    ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end());
+    return ReadResult;
+
+  case Success:
+    break;
+  }
+
+  // Here comes stuff that we only do once the entire chain is loaded.
+
+  // Load the AST blocks of all of the modules that we loaded.
+  for (llvm::SmallVectorImpl<ImportedModule>::iterator M = Loaded.begin(),
+                                                  MEnd = Loaded.end();
+       M != MEnd; ++M) {
+    ModuleFile &F = *M->Mod;
+
+    // Read the AST block.
+    if (ReadASTBlock(F))
+      return Failure;
+
+    // Once read, set the ModuleFile bit base offset and update the size in 
+    // bits of all files we've seen.
+    F.GlobalBitOffset = TotalModulesSizeInBits;
+    TotalModulesSizeInBits += F.SizeInBits;
+    GlobalBitOffsetsMap.insert(std::make_pair(F.GlobalBitOffset, &F));
+    
+    // Preload SLocEntries.
+    for (unsigned I = 0, N = F.PreloadSLocEntries.size(); I != N; ++I) {
+      int Index = int(F.PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID;
+      // Load it through the SourceManager and don't call ReadSLocEntry()
+      // directly because the entry may have already been loaded in which case
+      // calling ReadSLocEntry() directly would trigger an assertion in
+      // SourceManager.
+      SourceMgr.getLoadedSLocEntryByID(Index);
+    }
+  }
+
+  // Setup the import locations.
+  for (llvm::SmallVectorImpl<ImportedModule>::iterator M = Loaded.begin(),
+                                                    MEnd = Loaded.end();
+       M != MEnd; ++M) {
+    ModuleFile &F = *M->Mod;
+    if (!M->ImportedBy)
+      F.ImportLoc = M->ImportLoc;
+    else
+      F.ImportLoc = ReadSourceLocation(*M->ImportedBy,
+                                       M->ImportLoc.getRawEncoding());
+  }
+
+  // Mark all of the identifiers in the identifier table as being out of date,
+  // so that various accessors know to check the loaded modules when the
+  // identifier is used.
+  for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
+                              IdEnd = PP.getIdentifierTable().end();
+       Id != IdEnd; ++Id)
+    Id->second->setOutOfDate(true);
+  
+  // Resolve any unresolved module exports.
+  for (unsigned I = 0, N = UnresolvedModuleImportExports.size(); I != N; ++I) {
+    UnresolvedModuleImportExport &Unresolved = UnresolvedModuleImportExports[I];
+    SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,Unresolved.ID);
+    Module *ResolvedMod = getSubmodule(GlobalID);
+    
+    if (Unresolved.IsImport) {
+      if (ResolvedMod)
+        Unresolved.Mod->Imports.push_back(ResolvedMod);
+      continue;
+    }
+
+    if (ResolvedMod || Unresolved.IsWildcard)
+      Unresolved.Mod->Exports.push_back(
+        Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard));
+  }
+  UnresolvedModuleImportExports.clear();
+  
+  InitializeContext();
+
+  if (DeserializationListener)
+    DeserializationListener->ReaderInitialized(this);
+
+  ModuleFile &PrimaryModule = ModuleMgr.getPrimaryModule();
+  if (!PrimaryModule.OriginalSourceFileID.isInvalid()) {
+    PrimaryModule.OriginalSourceFileID 
+      = FileID::get(PrimaryModule.SLocEntryBaseID
+                    + PrimaryModule.OriginalSourceFileID.getOpaqueValue() - 1);
+
+    // If this AST file is a precompiled preamble, then set the
+    // preamble file ID of the source manager to the file source file
+    // from which the preamble was built.
+    if (Type == MK_Preamble) {
+      SourceMgr.setPreambleFileID(PrimaryModule.OriginalSourceFileID);
+    } else if (Type == MK_MainFile) {
+      SourceMgr.setMainFileID(PrimaryModule.OriginalSourceFileID);
+    }
+  }
+  
+  // For any Objective-C class definitions we have already loaded, make sure
+  // that we load any additional categories.
+  for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) {
+    loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(), 
+                       ObjCClassesLoaded[I],
+                       PreviousGeneration);
+  }
+  
+  return Success;
+}
+
+ASTReader::ASTReadResult
+ASTReader::ReadASTCore(StringRef FileName,
+                       ModuleKind Type,
+                       SourceLocation ImportLoc,
+                       ModuleFile *ImportedBy,
+                       llvm::SmallVectorImpl<ImportedModule> &Loaded,
+                       unsigned ClientLoadCapabilities) {
+  ModuleFile *M;
+  bool NewModule;
+  std::string ErrorStr;
+  llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportLoc,
+                                                ImportedBy, CurrentGeneration,
+                                                ErrorStr);
+
+  if (!M) {
+    // We couldn't load the module.
+    std::string Msg = "Unable to load module \"" + FileName.str() + "\": "
+      + ErrorStr;
+    Error(Msg);
+    return Failure;
+  }
+
+  if (!NewModule) {
+    // We've already loaded this module.
+    return Success;
+  }
+
+  // FIXME: This seems rather a hack. Should CurrentDir be part of the
+  // module?
+  if (FileName != "-") {
+    CurrentDir = llvm::sys::path::parent_path(FileName);
+    if (CurrentDir.empty()) CurrentDir = ".";
+  }
+
+  ModuleFile &F = *M;
+  llvm::BitstreamCursor &Stream = F.Stream;
+  Stream.init(F.StreamFile);
+  F.SizeInBits = F.Buffer->getBufferSize() * 8;
+  
+  // Sniff for the signature.
+  if (Stream.Read(8) != 'C' ||
+      Stream.Read(8) != 'P' ||
+      Stream.Read(8) != 'C' ||
+      Stream.Read(8) != 'H') {
+    Diag(diag::err_not_a_pch_file) << FileName;
+    return Failure;
+  }
+
+  // This is used for compatibility with older PCH formats.
+  bool HaveReadControlBlock = false;
+
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+
+    if (Code != llvm::bitc::ENTER_SUBBLOCK) {
+      Error("invalid record at top-level of AST file");
+      return Failure;
+    }
+
+    unsigned BlockID = Stream.ReadSubBlockID();
+
+    // We only know the control subblock ID.
+    switch (BlockID) {
+    case llvm::bitc::BLOCKINFO_BLOCK_ID:
+      if (Stream.ReadBlockInfoBlock()) {
+        Error("malformed BlockInfoBlock in AST file");
+        return Failure;
+      }
+      break;
+    case CONTROL_BLOCK_ID:
+      HaveReadControlBlock = true;
+      switch (ReadControlBlock(F, Loaded, ClientLoadCapabilities)) {
+      case Success:
+        break;
+
+      case Failure: return Failure;
+      case OutOfDate: return OutOfDate;
+      case VersionMismatch: return VersionMismatch;
+      case ConfigurationMismatch: return ConfigurationMismatch;
+      case HadErrors: return HadErrors;
+      }
+      break;
+    case AST_BLOCK_ID:
+      if (!HaveReadControlBlock) {
+        if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
+          Diag(diag::warn_pch_version_too_old);
+        return VersionMismatch;
+      }
+
+      // Record that we've loaded this module.
+      Loaded.push_back(ImportedModule(M, ImportedBy, ImportLoc));
+      return Success;
+
+    default:
+      if (Stream.SkipBlock()) {
+        Error("malformed block record in AST file");
+        return Failure;
+      }
+      break;
+    }
+  }
+  
+  return Success;
+}
+
+void ASTReader::InitializeContext() {  
+  // If there's a listener, notify them that we "read" the translation unit.
+  if (DeserializationListener)
+    DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID, 
+                                      Context.getTranslationUnitDecl());
+
+  // Make sure we load the declaration update records for the translation unit,
+  // if there are any.
+  loadDeclUpdateRecords(PREDEF_DECL_TRANSLATION_UNIT_ID, 
+                        Context.getTranslationUnitDecl());
+  
+  // FIXME: Find a better way to deal with collisions between these
+  // built-in types. Right now, we just ignore the problem.
+  
+  // Load the special types.
+  if (SpecialTypes.size() >= NumSpecialTypeIDs) {
+    if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING]) {
+      if (!Context.CFConstantStringTypeDecl)
+        Context.setCFConstantStringType(GetType(String));
+    }
+    
+    if (unsigned File = SpecialTypes[SPECIAL_TYPE_FILE]) {
+      QualType FileType = GetType(File);
+      if (FileType.isNull()) {
+        Error("FILE type is NULL");
+        return;
+      }
+      
+      if (!Context.FILEDecl) {
+        if (const TypedefType *Typedef = FileType->getAs<TypedefType>())
+          Context.setFILEDecl(Typedef->getDecl());
+        else {
+          const TagType *Tag = FileType->getAs<TagType>();
+          if (!Tag) {
+            Error("Invalid FILE type in AST file");
+            return;
+          }
+          Context.setFILEDecl(Tag->getDecl());
+        }
+      }
+    }
+    
+    if (unsigned Jmp_buf = SpecialTypes[SPECIAL_TYPE_JMP_BUF]) {
+      QualType Jmp_bufType = GetType(Jmp_buf);
+      if (Jmp_bufType.isNull()) {
+        Error("jmp_buf type is NULL");
+        return;
+      }
+      
+      if (!Context.jmp_bufDecl) {
+        if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>())
+          Context.setjmp_bufDecl(Typedef->getDecl());
+        else {
+          const TagType *Tag = Jmp_bufType->getAs<TagType>();
+          if (!Tag) {
+            Error("Invalid jmp_buf type in AST file");
+            return;
+          }
+          Context.setjmp_bufDecl(Tag->getDecl());
+        }
+      }
+    }
+    
+    if (unsigned Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_SIGJMP_BUF]) {
+      QualType Sigjmp_bufType = GetType(Sigjmp_buf);
+      if (Sigjmp_bufType.isNull()) {
+        Error("sigjmp_buf type is NULL");
+        return;
+      }
+      
+      if (!Context.sigjmp_bufDecl) {
+        if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>())
+          Context.setsigjmp_bufDecl(Typedef->getDecl());
+        else {
+          const TagType *Tag = Sigjmp_bufType->getAs<TagType>();
+          assert(Tag && "Invalid sigjmp_buf type in AST file");
+          Context.setsigjmp_bufDecl(Tag->getDecl());
+        }
+      }
+    }
+
+    if (unsigned ObjCIdRedef
+          = SpecialTypes[SPECIAL_TYPE_OBJC_ID_REDEFINITION]) {
+      if (Context.ObjCIdRedefinitionType.isNull())
+        Context.ObjCIdRedefinitionType = GetType(ObjCIdRedef);
+    }
+
+    if (unsigned ObjCClassRedef
+          = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) {
+      if (Context.ObjCClassRedefinitionType.isNull())
+        Context.ObjCClassRedefinitionType = GetType(ObjCClassRedef);
+    }
+
+    if (unsigned ObjCSelRedef
+          = SpecialTypes[SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) {
+      if (Context.ObjCSelRedefinitionType.isNull())
+        Context.ObjCSelRedefinitionType = GetType(ObjCSelRedef);
+    }
+
+    if (unsigned Ucontext_t = SpecialTypes[SPECIAL_TYPE_UCONTEXT_T]) {
+      QualType Ucontext_tType = GetType(Ucontext_t);
+      if (Ucontext_tType.isNull()) {
+        Error("ucontext_t type is NULL");
+        return;
+      }
+
+      if (!Context.ucontext_tDecl) {
+        if (const TypedefType *Typedef = Ucontext_tType->getAs<TypedefType>())
+          Context.setucontext_tDecl(Typedef->getDecl());
+        else {
+          const TagType *Tag = Ucontext_tType->getAs<TagType>();
+          assert(Tag && "Invalid ucontext_t type in AST file");
+          Context.setucontext_tDecl(Tag->getDecl());
+        }
+      }
+    }
+  }
+  
+  ReadPragmaDiagnosticMappings(Context.getDiagnostics());
+
+  // If there were any CUDA special declarations, deserialize them.
+  if (!CUDASpecialDeclRefs.empty()) {
+    assert(CUDASpecialDeclRefs.size() == 1 && "More decl refs than expected!");
+    Context.setcudaConfigureCallDecl(
+                           cast<FunctionDecl>(GetDecl(CUDASpecialDeclRefs[0])));
+  }
+  
+  // Re-export any modules that were imported by a non-module AST file.
+  for (unsigned I = 0, N = ImportedModules.size(); I != N; ++I) {
+    if (Module *Imported = getSubmodule(ImportedModules[I]))
+      makeModuleVisible(Imported, Module::AllVisible);
+  }
+  ImportedModules.clear();
+}
+
+void ASTReader::finalizeForWriting() {
+  for (HiddenNamesMapType::iterator Hidden = HiddenNamesMap.begin(),
+                                 HiddenEnd = HiddenNamesMap.end();
+       Hidden != HiddenEnd; ++Hidden) {
+    makeNamesVisible(Hidden->second);
+  }
+  HiddenNamesMap.clear();
+}
+
+/// \brief Retrieve the name of the original source file name
+/// directly from the AST file, without actually loading the AST
+/// file.
+std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
+                                             FileManager &FileMgr,
+                                             DiagnosticsEngine &Diags) {
+  // Open the AST file.
+  std::string ErrStr;
+  OwningPtr<llvm::MemoryBuffer> Buffer;
+  Buffer.reset(FileMgr.getBufferForFile(ASTFileName, &ErrStr));
+  if (!Buffer) {
+    Diags.Report(diag::err_fe_unable_to_read_pch_file) << ASTFileName << ErrStr;
+    return std::string();
+  }
+
+  // Initialize the stream
+  llvm::BitstreamReader StreamFile;
+  llvm::BitstreamCursor Stream;
+  StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
+                  (const unsigned char *)Buffer->getBufferEnd());
+  Stream.init(StreamFile);
+
+  // Sniff for the signature.
+  if (Stream.Read(8) != 'C' ||
+      Stream.Read(8) != 'P' ||
+      Stream.Read(8) != 'C' ||
+      Stream.Read(8) != 'H') {
+    Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName;
+    return std::string();
+  }
+
+  RecordData Record;
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      unsigned BlockID = Stream.ReadSubBlockID();
+
+      // We only know the AST subblock ID.
+      switch (BlockID) {
+      case CONTROL_BLOCK_ID:
+        if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
+          Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
+          return std::string();
+        }
+        break;
+
+      default:
+        if (Stream.SkipBlock()) {
+          Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
+          return std::string();
+        }
+        break;
+      }
+      continue;
+    }
+
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd()) {
+        Diags.Report(diag::err_fe_pch_error_at_end_block) << ASTFileName;
+        return std::string();
+      }
+      continue;
+    }
+
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    Record.clear();
+    const char *BlobStart = 0;
+    unsigned BlobLen = 0;
+    if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen) == ORIGINAL_FILE)
+      return std::string(BlobStart, BlobLen);
+  }
+
+  return std::string();
+}
+
+namespace {
+  class SimplePCHValidator : public ASTReaderListener {
+    const LangOptions &ExistingLangOpts;
+    const TargetOptions &ExistingTargetOpts;
+    const PreprocessorOptions &ExistingPPOpts;
+    FileManager &FileMgr;
+    
+  public:
+    SimplePCHValidator(const LangOptions &ExistingLangOpts,
+                       const TargetOptions &ExistingTargetOpts,
+                       const PreprocessorOptions &ExistingPPOpts,
+                       FileManager &FileMgr)
+      : ExistingLangOpts(ExistingLangOpts),
+        ExistingTargetOpts(ExistingTargetOpts),
+        ExistingPPOpts(ExistingPPOpts),
+        FileMgr(FileMgr)
+    {
+    }
+
+    virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
+                                     bool Complain) {
+      return checkLanguageOptions(ExistingLangOpts, LangOpts, 0);
+    }
+    virtual bool ReadTargetOptions(const TargetOptions &TargetOpts,
+                                   bool Complain) {
+      return checkTargetOptions(ExistingTargetOpts, TargetOpts, 0);
+    }
+    virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
+                                         bool Complain,
+                                         std::string &SuggestedPredefines) {
+      return checkPreprocessorOptions(ExistingPPOpts, PPOpts, 0, FileMgr,
+                                      SuggestedPredefines);
+    }
+  };
+}
+
+bool ASTReader::readASTFileControlBlock(StringRef Filename,
+                                        FileManager &FileMgr,
+                                        ASTReaderListener &Listener) {
+  // Open the AST file.
+  std::string ErrStr;
+  OwningPtr<llvm::MemoryBuffer> Buffer;
+  Buffer.reset(FileMgr.getBufferForFile(Filename, &ErrStr));
+  if (!Buffer) {
+    return true;
+  }
+
+  // Initialize the stream
+  llvm::BitstreamReader StreamFile;
+  llvm::BitstreamCursor Stream;
+  StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
+                  (const unsigned char *)Buffer->getBufferEnd());
+  Stream.init(StreamFile);
+
+  // Sniff for the signature.
+  if (Stream.Read(8) != 'C' ||
+      Stream.Read(8) != 'P' ||
+      Stream.Read(8) != 'C' ||
+      Stream.Read(8) != 'H') {
+    return true;
+  }
+
+  RecordData Record;
+  bool InControlBlock = false;
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      unsigned BlockID = Stream.ReadSubBlockID();
+
+      // We only know the control subblock ID.
+      switch (BlockID) {
+      case CONTROL_BLOCK_ID:
+        if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
+          return true;
+        } else {
+          InControlBlock = true;
+        }
+        break;
+
+      default:
+        if (Stream.SkipBlock())
+          return true;
+        break;
+      }
+      continue;
+    }
+
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd()) {
+        return true;
+      }
+
+      InControlBlock = false;
+      continue;
+    }
+
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    Record.clear();
+    const char *BlobStart = 0;
+    unsigned BlobLen = 0;
+    unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+    if (InControlBlock) {
+      switch ((ControlRecordTypes)RecCode) {
+      case METADATA: {
+        if (Record[0] != VERSION_MAJOR) {
+          return true;
+        }
+
+        const std::string &CurBranch = getClangFullRepositoryVersion();
+        StringRef ASTBranch(BlobStart, BlobLen);
+        if (StringRef(CurBranch) != ASTBranch)
+          return true;
+
+        break;
+      }
+      case LANGUAGE_OPTIONS:
+        if (ParseLanguageOptions(Record, false, Listener))
+          return true;
+        break;
+
+      case TARGET_OPTIONS:
+        if (ParseTargetOptions(Record, false, Listener))
+          return true;
+        break;
+
+      case DIAGNOSTIC_OPTIONS:
+        if (ParseDiagnosticOptions(Record, false, Listener))
+          return true;
+        break;
+
+      case FILE_SYSTEM_OPTIONS:
+        if (ParseFileSystemOptions(Record, false, Listener))
+          return true;
+        break;
+
+      case HEADER_SEARCH_OPTIONS:
+        if (ParseHeaderSearchOptions(Record, false, Listener))
+          return true;
+        break;
+
+      case PREPROCESSOR_OPTIONS: {
+        std::string IgnoredSuggestedPredefines;
+        if (ParsePreprocessorOptions(Record, false, Listener,
+                                     IgnoredSuggestedPredefines))
+          return true;
+        break;
+      }
+
+      default:
+        // No other validation to perform.
+        break;
+      }
+    }
+  }
+  
+  return false;
+}
+
+
+bool ASTReader::isAcceptableASTFile(StringRef Filename,
+                                    FileManager &FileMgr,
+                                    const LangOptions &LangOpts,
+                                    const TargetOptions &TargetOpts,
+                                    const PreprocessorOptions &PPOpts) {
+  SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, FileMgr);
+  return !readASTFileControlBlock(Filename, FileMgr, validator);
+}
+
+bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
+  // Enter the submodule block.
+  if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) {
+    Error("malformed submodule block record in AST file");
+    return true;
+  }
+
+  ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
+  bool First = true;
+  Module *CurrentModule = 0;
+  RecordData Record;
+  while (true) {
+    unsigned Code = F.Stream.ReadCode();
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (F.Stream.ReadBlockEnd()) {
+        Error("error at end of submodule block in AST file");
+        return true;
+      }
+      return false;
+    }
+    
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      F.Stream.ReadSubBlockID();
+      if (F.Stream.SkipBlock()) {
+        Error("malformed block record in AST file");
+        return true;
+      }
+      continue;
+    }
+    
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      F.Stream.ReadAbbrevRecord();
+      continue;
+    }
+    
+    // Read a record.
+    const char *BlobStart;
+    unsigned BlobLen;
+    Record.clear();
+    switch (F.Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+    default:  // Default behavior: ignore.
+      break;
+      
+    case SUBMODULE_DEFINITION: {
+      if (First) {
+        Error("missing submodule metadata record at beginning of block");
+        return true;
+      }
+
+      if (Record.size() < 7) {
+        Error("malformed module definition");
+        return true;
+      }
+      
+      StringRef Name(BlobStart, BlobLen);
+      SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[0]);
+      SubmoduleID Parent = getGlobalSubmoduleID(F, Record[1]);
+      bool IsFramework = Record[2];
+      bool IsExplicit = Record[3];
+      bool IsSystem = Record[4];
+      bool InferSubmodules = Record[5];
+      bool InferExplicitSubmodules = Record[6];
+      bool InferExportWildcard = Record[7];
+      
+      Module *ParentModule = 0;
+      if (Parent)
+        ParentModule = getSubmodule(Parent);
+      
+      // Retrieve this (sub)module from the module map, creating it if
+      // necessary.
+      CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, 
+                                                IsFramework, 
+                                                IsExplicit).first;
+      SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS;
+      if (GlobalIndex >= SubmodulesLoaded.size() ||
+          SubmodulesLoaded[GlobalIndex]) {
+        Error("too many submodules");
+        return true;
+      }
+      
+      CurrentModule->setASTFile(F.File);
+      CurrentModule->IsFromModuleFile = true;
+      CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
+      CurrentModule->InferSubmodules = InferSubmodules;
+      CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
+      CurrentModule->InferExportWildcard = InferExportWildcard;
+      if (DeserializationListener)
+        DeserializationListener->ModuleRead(GlobalID, CurrentModule);
+      
+      SubmodulesLoaded[GlobalIndex] = CurrentModule;
+      break;
+    }
+        
+    case SUBMODULE_UMBRELLA_HEADER: {
+      if (First) {
+        Error("missing submodule metadata record at beginning of block");
+        return true;
+      }
+
+      if (!CurrentModule)
+        break;
+      
+      StringRef FileName(BlobStart, BlobLen);
+      if (const FileEntry *Umbrella = PP.getFileManager().getFile(FileName)) {
+        if (!CurrentModule->getUmbrellaHeader())
+          ModMap.setUmbrellaHeader(CurrentModule, Umbrella);
+        else if (CurrentModule->getUmbrellaHeader() != Umbrella) {
+          Error("mismatched umbrella headers in submodule");
+          return true;
+        }
+      }
+      break;
+    }
+        
+    case SUBMODULE_HEADER: {
+      if (First) {
+        Error("missing submodule metadata record at beginning of block");
+        return true;
+      }
+
+      if (!CurrentModule)
+        break;
+      
+      // FIXME: Be more lazy about this!
+      StringRef FileName(BlobStart, BlobLen);
+      if (const FileEntry *File = PP.getFileManager().getFile(FileName)) {
+        if (std::find(CurrentModule->Headers.begin(), 
+                      CurrentModule->Headers.end(), 
+                      File) == CurrentModule->Headers.end())
+          ModMap.addHeader(CurrentModule, File, false);
+      }
+      break;      
+    }
+
+    case SUBMODULE_EXCLUDED_HEADER: {
+      if (First) {
+        Error("missing submodule metadata record at beginning of block");
+        return true;
+      }
+
+      if (!CurrentModule)
+        break;
+      
+      // FIXME: Be more lazy about this!
+      StringRef FileName(BlobStart, BlobLen);
+      if (const FileEntry *File = PP.getFileManager().getFile(FileName)) {
+        if (std::find(CurrentModule->Headers.begin(), 
+                      CurrentModule->Headers.end(), 
+                      File) == CurrentModule->Headers.end())
+          ModMap.addHeader(CurrentModule, File, true);
+      }
+      break;      
+    }
+
+    case SUBMODULE_TOPHEADER: {
+      if (First) {
+        Error("missing submodule metadata record at beginning of block");
+        return true;
+      }
+
+      if (!CurrentModule)
+        break;
+
+      // FIXME: Be more lazy about this!
+      StringRef FileName(BlobStart, BlobLen);
+      if (const FileEntry *File = PP.getFileManager().getFile(FileName))
+        CurrentModule->TopHeaders.insert(File);
+      break;
+    }
+
+    case SUBMODULE_UMBRELLA_DIR: {
+      if (First) {
+        Error("missing submodule metadata record at beginning of block");
+        return true;
+      }
+      
+      if (!CurrentModule)
+        break;
+      
+      StringRef DirName(BlobStart, BlobLen);
+      if (const DirectoryEntry *Umbrella
+                                  = PP.getFileManager().getDirectory(DirName)) {
+        if (!CurrentModule->getUmbrellaDir())
+          ModMap.setUmbrellaDir(CurrentModule, Umbrella);
+        else if (CurrentModule->getUmbrellaDir() != Umbrella) {
+          Error("mismatched umbrella directories in submodule");
+          return true;
+        }
+      }
+      break;
+    }
+        
+    case SUBMODULE_METADATA: {
+      if (!First) {
+        Error("submodule metadata record not at beginning of block");
+        return true;
+      }
+      First = false;
+      
+      F.BaseSubmoduleID = getTotalNumSubmodules();
+      F.LocalNumSubmodules = Record[0];
+      unsigned LocalBaseSubmoduleID = Record[1];
+      if (F.LocalNumSubmodules > 0) {
+        // Introduce the global -> local mapping for submodules within this 
+        // module.
+        GlobalSubmoduleMap.insert(std::make_pair(getTotalNumSubmodules()+1,&F));
+        
+        // Introduce the local -> global mapping for submodules within this 
+        // module.
+        F.SubmoduleRemap.insertOrReplace(
+          std::make_pair(LocalBaseSubmoduleID,
+                         F.BaseSubmoduleID - LocalBaseSubmoduleID));
+        
+        SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules);
+      }      
+      break;
+    }
+        
+    case SUBMODULE_IMPORTS: {
+      if (First) {
+        Error("missing submodule metadata record at beginning of block");
+        return true;
+      }
+      
+      if (!CurrentModule)
+        break;
+      
+      for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {
+        UnresolvedModuleImportExport Unresolved;
+        Unresolved.File = &F;
+        Unresolved.Mod = CurrentModule;
+        Unresolved.ID = Record[Idx];
+        Unresolved.IsImport = true;
+        Unresolved.IsWildcard = false;
+        UnresolvedModuleImportExports.push_back(Unresolved);
+      }
+      break;
+    }
+
+    case SUBMODULE_EXPORTS: {
+      if (First) {
+        Error("missing submodule metadata record at beginning of block");
+        return true;
+      }
+      
+      if (!CurrentModule)
+        break;
+      
+      for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {
+        UnresolvedModuleImportExport Unresolved;
+        Unresolved.File = &F;
+        Unresolved.Mod = CurrentModule;
+        Unresolved.ID = Record[Idx];
+        Unresolved.IsImport = false;
+        Unresolved.IsWildcard = Record[Idx + 1];
+        UnresolvedModuleImportExports.push_back(Unresolved);
+      }
+      
+      // Once we've loaded the set of exports, there's no reason to keep 
+      // the parsed, unresolved exports around.
+      CurrentModule->UnresolvedExports.clear();
+      break;
+    }
+    case SUBMODULE_REQUIRES: {
+      if (First) {
+        Error("missing submodule metadata record at beginning of block");
+        return true;
+      }
+
+      if (!CurrentModule)
+        break;
+
+      CurrentModule->addRequirement(StringRef(BlobStart, BlobLen), 
+                                    Context.getLangOpts(),
+                                    Context.getTargetInfo());
+      break;
+    }
+    }
+  }
+}
+
+/// \brief Parse the record that corresponds to a LangOptions data
+/// structure.
+///
+/// This routine parses the language options from the AST file and then gives
+/// them to the AST listener if one is set.
+///
+/// \returns true if the listener deems the file unacceptable, false otherwise.
+bool ASTReader::ParseLanguageOptions(const RecordData &Record,
+                                     bool Complain,
+                                     ASTReaderListener &Listener) {
+  LangOptions LangOpts;
+  unsigned Idx = 0;
+#define LANGOPT(Name, Bits, Default, Description) \
+  LangOpts.Name = Record[Idx++];
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+  LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++]));
+#include "clang/Basic/LangOptions.def"
+
+  ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++];
+  VersionTuple runtimeVersion = ReadVersionTuple(Record, Idx);
+  LangOpts.ObjCRuntime = ObjCRuntime(runtimeKind, runtimeVersion);
+  
+  unsigned Length = Record[Idx++];
+  LangOpts.CurrentModule.assign(Record.begin() + Idx, 
+                                Record.begin() + Idx + Length);
+  return Listener.ReadLanguageOptions(LangOpts, Complain);
+}
+
+bool ASTReader::ParseTargetOptions(const RecordData &Record,
+                                   bool Complain,
+                                   ASTReaderListener &Listener) {
+  unsigned Idx = 0;
+  TargetOptions TargetOpts;
+  TargetOpts.Triple = ReadString(Record, Idx);
+  TargetOpts.CPU = ReadString(Record, Idx);
+  TargetOpts.ABI = ReadString(Record, Idx);
+  TargetOpts.CXXABI = ReadString(Record, Idx);
+  TargetOpts.LinkerVersion = ReadString(Record, Idx);
+  for (unsigned N = Record[Idx++]; N; --N) {
+    TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx));
+  }
+  for (unsigned N = Record[Idx++]; N; --N) {
+    TargetOpts.Features.push_back(ReadString(Record, Idx));
+  }
+
+  return Listener.ReadTargetOptions(TargetOpts, Complain);
+}
+
+bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain,
+                                       ASTReaderListener &Listener) {
+  DiagnosticOptions DiagOpts;
+  unsigned Idx = 0;
+#define DIAGOPT(Name, Bits, Default) DiagOpts.Name = Record[Idx++];
+#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
+  DiagOpts.set##Name(static_cast<Type>(Record[Idx++]));
+#include "clang/Basic/DiagnosticOptions.def"
+
+  for (unsigned N = Record[Idx++]; N; --N) {
+    DiagOpts.Warnings.push_back(ReadString(Record, Idx));
+  }
+
+  return Listener.ReadDiagnosticOptions(DiagOpts, Complain);
+}
+
+bool ASTReader::ParseFileSystemOptions(const RecordData &Record, bool Complain,
+                                       ASTReaderListener &Listener) {
+  FileSystemOptions FSOpts;
+  unsigned Idx = 0;
+  FSOpts.WorkingDir = ReadString(Record, Idx);
+  return Listener.ReadFileSystemOptions(FSOpts, Complain);
+}
+
+bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
+                                         bool Complain,
+                                         ASTReaderListener &Listener) {
+  HeaderSearchOptions HSOpts;
+  unsigned Idx = 0;
+  HSOpts.Sysroot = ReadString(Record, Idx);
+
+  // Include entries.
+  for (unsigned N = Record[Idx++]; N; --N) {
+    std::string Path = ReadString(Record, Idx);
+    frontend::IncludeDirGroup Group
+      = static_cast<frontend::IncludeDirGroup>(Record[Idx++]);
+    bool IsUserSupplied = Record[Idx++];
+    bool IsFramework = Record[Idx++];
+    bool IgnoreSysRoot = Record[Idx++];
+    bool IsInternal = Record[Idx++];
+    bool ImplicitExternC = Record[Idx++];
+    HSOpts.UserEntries.push_back(
+      HeaderSearchOptions::Entry(Path, Group, IsUserSupplied, IsFramework,
+                                 IgnoreSysRoot, IsInternal, ImplicitExternC));
+  }
+
+  // System header prefixes.
+  for (unsigned N = Record[Idx++]; N; --N) {
+    std::string Prefix = ReadString(Record, Idx);
+    bool IsSystemHeader = Record[Idx++];
+    HSOpts.SystemHeaderPrefixes.push_back(
+      HeaderSearchOptions::SystemHeaderPrefix(Prefix, IsSystemHeader));
+  }
+
+  HSOpts.ResourceDir = ReadString(Record, Idx);
+  HSOpts.ModuleCachePath = ReadString(Record, Idx);
+  HSOpts.DisableModuleHash = Record[Idx++];
+  HSOpts.UseBuiltinIncludes = Record[Idx++];
+  HSOpts.UseStandardSystemIncludes = Record[Idx++];
+  HSOpts.UseStandardCXXIncludes = Record[Idx++];
+  HSOpts.UseLibcxx = Record[Idx++];
+
+  return Listener.ReadHeaderSearchOptions(HSOpts, Complain);
+}
+
+bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
+                                         bool Complain,
+                                         ASTReaderListener &Listener,
+                                         std::string &SuggestedPredefines) {
+  PreprocessorOptions PPOpts;
+  unsigned Idx = 0;
+
+  // Macro definitions/undefs
+  for (unsigned N = Record[Idx++]; N; --N) {
+    std::string Macro = ReadString(Record, Idx);
+    bool IsUndef = Record[Idx++];
+    PPOpts.Macros.push_back(std::make_pair(Macro, IsUndef));
+  }
+
+  // Includes
+  for (unsigned N = Record[Idx++]; N; --N) {
+    PPOpts.Includes.push_back(ReadString(Record, Idx));
+  }
+
+  // Macro Includes
+  for (unsigned N = Record[Idx++]; N; --N) {
+    PPOpts.MacroIncludes.push_back(ReadString(Record, Idx));
+  }
+
+  PPOpts.UsePredefines = Record[Idx++];
+  PPOpts.ImplicitPCHInclude = ReadString(Record, Idx);
+  PPOpts.ImplicitPTHInclude = ReadString(Record, Idx);
+  PPOpts.ObjCXXARCStandardLibrary =
+    static_cast<ObjCXXARCStandardLibraryKind>(Record[Idx++]);
+  SuggestedPredefines.clear();
+  return Listener.ReadPreprocessorOptions(PPOpts, Complain,
+                                          SuggestedPredefines);
+}
+
+std::pair<ModuleFile *, unsigned>
+ASTReader::getModulePreprocessedEntity(unsigned GlobalIndex) {
+  GlobalPreprocessedEntityMapType::iterator
+  I = GlobalPreprocessedEntityMap.find(GlobalIndex);
+  assert(I != GlobalPreprocessedEntityMap.end() && 
+         "Corrupted global preprocessed entity map");
+  ModuleFile *M = I->second;
+  unsigned LocalIndex = GlobalIndex - M->BasePreprocessedEntityID;
+  return std::make_pair(M, LocalIndex);
+}
+
+std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
+ASTReader::getModulePreprocessedEntities(ModuleFile &Mod) const {
+  if (PreprocessingRecord *PPRec = PP.getPreprocessingRecord())
+    return PPRec->getIteratorsForLoadedRange(Mod.BasePreprocessedEntityID,
+                                             Mod.NumPreprocessedEntities);
+
+  return std::make_pair(PreprocessingRecord::iterator(),
+                        PreprocessingRecord::iterator());
+}
+
+std::pair<ASTReader::ModuleDeclIterator, ASTReader::ModuleDeclIterator>
+ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) {
+  return std::make_pair(ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls),
+                        ModuleDeclIterator(this, &Mod,
+                                 Mod.FileSortedDecls + Mod.NumFileSortedDecls));
+}
+
+PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
+  PreprocessedEntityID PPID = Index+1;
+  std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index);
+  ModuleFile &M = *PPInfo.first;
+  unsigned LocalIndex = PPInfo.second;
+  const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex];
+
+  SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor);  
+  M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset);
+
+  unsigned Code = M.PreprocessorDetailCursor.ReadCode();
+  switch (Code) {
+  case llvm::bitc::END_BLOCK:
+    return 0;
+    
+  case llvm::bitc::ENTER_SUBBLOCK:
+    Error("unexpected subblock record in preprocessor detail block");
+    return 0;
+      
+  case llvm::bitc::DEFINE_ABBREV:
+    Error("unexpected abbrevation record in preprocessor detail block");
+    return 0;
+      
+  default:
+    break;
+  }
+
+  if (!PP.getPreprocessingRecord()) {
+    Error("no preprocessing record");
+    return 0;
+  }
+  
+  // Read the record.
+  SourceRange Range(ReadSourceLocation(M, PPOffs.Begin),
+                    ReadSourceLocation(M, PPOffs.End));
+  PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
+  const char *BlobStart = 0;
+  unsigned BlobLen = 0;
+  RecordData Record;
+  PreprocessorDetailRecordTypes RecType =
+    (PreprocessorDetailRecordTypes)M.PreprocessorDetailCursor.ReadRecord(
+                                             Code, Record, BlobStart, BlobLen);
+  switch (RecType) {
+  case PPD_MACRO_EXPANSION: {
+    bool isBuiltin = Record[0];
+    IdentifierInfo *Name = 0;
+    MacroDefinition *Def = 0;
+    if (isBuiltin)
+      Name = getLocalIdentifier(M, Record[1]);
+    else {
+      PreprocessedEntityID
+          GlobalID = getGlobalPreprocessedEntityID(M, Record[1]);
+      Def =cast<MacroDefinition>(PPRec.getLoadedPreprocessedEntity(GlobalID-1));
+    }
+
+    MacroExpansion *ME;
+    if (isBuiltin)
+      ME = new (PPRec) MacroExpansion(Name, Range);
+    else
+      ME = new (PPRec) MacroExpansion(Def, Range);
+
+    return ME;
+  }
+      
+  case PPD_MACRO_DEFINITION: {
+    // Decode the identifier info and then check again; if the macro is
+    // still defined and associated with the identifier,
+    IdentifierInfo *II = getLocalIdentifier(M, Record[0]);
+    MacroDefinition *MD
+      = new (PPRec) MacroDefinition(II, Range);
+
+    if (DeserializationListener)
+      DeserializationListener->MacroDefinitionRead(PPID, MD);
+
+    return MD;
+  }
+      
+  case PPD_INCLUSION_DIRECTIVE: {
+    const char *FullFileNameStart = BlobStart + Record[0];
+    StringRef FullFileName(FullFileNameStart, BlobLen - Record[0]);
+    const FileEntry *File = 0;
+    if (!FullFileName.empty())
+      File = PP.getFileManager().getFile(FullFileName);
+    
+    // FIXME: Stable encoding
+    InclusionDirective::InclusionKind Kind
+      = static_cast<InclusionDirective::InclusionKind>(Record[2]);
+    InclusionDirective *ID
+      = new (PPRec) InclusionDirective(PPRec, Kind,
+                                       StringRef(BlobStart, Record[0]),
+                                       Record[1], Record[3],
+                                       File,
+                                       Range);
+    return ID;
+  }
+  }
+
+  llvm_unreachable("Invalid PreprocessorDetailRecordTypes");
+}
+
+/// \brief \arg SLocMapI points at a chunk of a module that contains no
+/// preprocessed entities or the entities it contains are not the ones we are
+/// looking for. Find the next module that contains entities and return the ID
+/// of the first entry.
+PreprocessedEntityID ASTReader::findNextPreprocessedEntity(
+                       GlobalSLocOffsetMapType::const_iterator SLocMapI) const {
+  ++SLocMapI;
+  for (GlobalSLocOffsetMapType::const_iterator
+         EndI = GlobalSLocOffsetMap.end(); SLocMapI != EndI; ++SLocMapI) {
+    ModuleFile &M = *SLocMapI->second;
+    if (M.NumPreprocessedEntities)
+      return M.BasePreprocessedEntityID;
+  }
+
+  return getTotalNumPreprocessedEntities();
+}
+
+namespace {
+
+template <unsigned PPEntityOffset::*PPLoc>
+struct PPEntityComp {
+  const ASTReader &Reader;
+  ModuleFile &M;
+
+  PPEntityComp(const ASTReader &Reader, ModuleFile &M) : Reader(Reader), M(M) { }
+
+  bool operator()(const PPEntityOffset &L, const PPEntityOffset &R) const {
+    SourceLocation LHS = getLoc(L);
+    SourceLocation RHS = getLoc(R);
+    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+  }
+
+  bool operator()(const PPEntityOffset &L, SourceLocation RHS) const {
+    SourceLocation LHS = getLoc(L);
+    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+  }
+
+  bool operator()(SourceLocation LHS, const PPEntityOffset &R) const {
+    SourceLocation RHS = getLoc(R);
+    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+  }
+
+  SourceLocation getLoc(const PPEntityOffset &PPE) const {
+    return Reader.ReadSourceLocation(M, PPE.*PPLoc);
+  }
+};
+
+}
+
+/// \brief Returns the first preprocessed entity ID that ends after \arg BLoc.
+PreprocessedEntityID
+ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const {
+  if (SourceMgr.isLocalSourceLocation(BLoc))
+    return getTotalNumPreprocessedEntities();
+
+  GlobalSLocOffsetMapType::const_iterator
+    SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -
+                                        BLoc.getOffset());
+  assert(SLocMapI != GlobalSLocOffsetMap.end() &&
+         "Corrupted global sloc offset map");
+
+  if (SLocMapI->second->NumPreprocessedEntities == 0)
+    return findNextPreprocessedEntity(SLocMapI);
+
+  ModuleFile &M = *SLocMapI->second;
+  typedef const PPEntityOffset *pp_iterator;
+  pp_iterator pp_begin = M.PreprocessedEntityOffsets;
+  pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities;
+
+  size_t Count = M.NumPreprocessedEntities;
+  size_t Half;
+  pp_iterator First = pp_begin;
+  pp_iterator PPI;
+
+  // Do a binary search manually instead of using std::lower_bound because
+  // The end locations of entities may be unordered (when a macro expansion
+  // is inside another macro argument), but for this case it is not important
+  // whether we get the first macro expansion or its containing macro.
+  while (Count > 0) {
+    Half = Count/2;
+    PPI = First;
+    std::advance(PPI, Half);
+    if (SourceMgr.isBeforeInTranslationUnit(ReadSourceLocation(M, PPI->End),
+                                            BLoc)){
+      First = PPI;
+      ++First;
+      Count = Count - Half - 1;
+    } else
+      Count = Half;
+  }
+
+  if (PPI == pp_end)
+    return findNextPreprocessedEntity(SLocMapI);
+
+  return M.BasePreprocessedEntityID + (PPI - pp_begin);
+}
+
+/// \brief Returns the first preprocessed entity ID that begins after \arg ELoc.
+PreprocessedEntityID
+ASTReader::findEndPreprocessedEntity(SourceLocation ELoc) const {
+  if (SourceMgr.isLocalSourceLocation(ELoc))
+    return getTotalNumPreprocessedEntities();
+
+  GlobalSLocOffsetMapType::const_iterator
+    SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -
+                                        ELoc.getOffset());
+  assert(SLocMapI != GlobalSLocOffsetMap.end() &&
+         "Corrupted global sloc offset map");
+
+  if (SLocMapI->second->NumPreprocessedEntities == 0)
+    return findNextPreprocessedEntity(SLocMapI);
+
+  ModuleFile &M = *SLocMapI->second;
+  typedef const PPEntityOffset *pp_iterator;
+  pp_iterator pp_begin = M.PreprocessedEntityOffsets;
+  pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities;
+  pp_iterator PPI =
+      std::upper_bound(pp_begin, pp_end, ELoc,
+                       PPEntityComp<&PPEntityOffset::Begin>(*this, M));
+
+  if (PPI == pp_end)
+    return findNextPreprocessedEntity(SLocMapI);
+
+  return M.BasePreprocessedEntityID + (PPI - pp_begin);
+}
+
+/// \brief Returns a pair of [Begin, End) indices of preallocated
+/// preprocessed entities that \arg Range encompasses.
+std::pair<unsigned, unsigned>
+    ASTReader::findPreprocessedEntitiesInRange(SourceRange Range) {
+  if (Range.isInvalid())
+    return std::make_pair(0,0);
+  assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
+
+  PreprocessedEntityID BeginID = findBeginPreprocessedEntity(Range.getBegin());
+  PreprocessedEntityID EndID = findEndPreprocessedEntity(Range.getEnd());
+  return std::make_pair(BeginID, EndID);
+}
+
+/// \brief Optionally returns true or false if the preallocated preprocessed
+/// entity with index \arg Index came from file \arg FID.
+llvm::Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index,
+                                                             FileID FID) {
+  if (FID.isInvalid())
+    return false;
+
+  std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index);
+  ModuleFile &M = *PPInfo.first;
+  unsigned LocalIndex = PPInfo.second;
+  const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex];
+  
+  SourceLocation Loc = ReadSourceLocation(M, PPOffs.Begin);
+  if (Loc.isInvalid())
+    return false;
+  
+  if (SourceMgr.isInFileID(SourceMgr.getFileLoc(Loc), FID))
+    return true;
+  else
+    return false;
+}
+
+namespace {
+  /// \brief Visitor used to search for information about a header file.
+  class HeaderFileInfoVisitor {
+    ASTReader &Reader;
+    const FileEntry *FE;
+    
+    llvm::Optional<HeaderFileInfo> HFI;
+    
+  public:
+    HeaderFileInfoVisitor(ASTReader &Reader, const FileEntry *FE)
+      : Reader(Reader), FE(FE) { }
+    
+    static bool visit(ModuleFile &M, void *UserData) {
+      HeaderFileInfoVisitor *This
+        = static_cast<HeaderFileInfoVisitor *>(UserData);
+      
+      HeaderFileInfoTrait Trait(This->Reader, M, 
+                                &This->Reader.getPreprocessor().getHeaderSearchInfo(),
+                                M.HeaderFileFrameworkStrings,
+                                This->FE->getName());
+      
+      HeaderFileInfoLookupTable *Table
+        = static_cast<HeaderFileInfoLookupTable *>(M.HeaderFileInfoTable);
+      if (!Table)
+        return false;
+
+      // Look in the on-disk hash table for an entry for this file name.
+      HeaderFileInfoLookupTable::iterator Pos = Table->find(This->FE->getName(),
+                                                            &Trait);
+      if (Pos == Table->end())
+        return false;
+
+      This->HFI = *Pos;
+      return true;
+    }
+    
+    llvm::Optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; }
+  };
+}
+
+HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) {
+  HeaderFileInfoVisitor Visitor(*this, FE);
+  ModuleMgr.visit(&HeaderFileInfoVisitor::visit, &Visitor);
+  if (llvm::Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo()) {
+    if (Listener)
+      Listener->ReadHeaderFileInfo(*HFI, FE->getUID());
+    return *HFI;
+  }
+  
+  return HeaderFileInfo();
+}
+
+void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
+  // FIXME: Make it work properly with modules.
+  llvm::SmallVector<DiagnosticsEngine::DiagState *, 32> DiagStates;
+  for (ModuleIterator I = ModuleMgr.begin(), E = ModuleMgr.end(); I != E; ++I) {
+    ModuleFile &F = *(*I);
+    unsigned Idx = 0;
+    DiagStates.clear();
+    assert(!Diag.DiagStates.empty());
+    DiagStates.push_back(&Diag.DiagStates.front()); // the command-line one.
+    while (Idx < F.PragmaDiagMappings.size()) {
+      SourceLocation Loc = ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]);
+      unsigned DiagStateID = F.PragmaDiagMappings[Idx++];
+      if (DiagStateID != 0) {
+        Diag.DiagStatePoints.push_back(
+                    DiagnosticsEngine::DiagStatePoint(DiagStates[DiagStateID-1],
+                    FullSourceLoc(Loc, SourceMgr)));
+        continue;
+      }
+      
+      assert(DiagStateID == 0);
+      // A new DiagState was created here.
+      Diag.DiagStates.push_back(*Diag.GetCurDiagState());
+      DiagnosticsEngine::DiagState *NewState = &Diag.DiagStates.back();
+      DiagStates.push_back(NewState);
+      Diag.DiagStatePoints.push_back(
+          DiagnosticsEngine::DiagStatePoint(NewState,
+                                            FullSourceLoc(Loc, SourceMgr)));
+      while (1) {
+        assert(Idx < F.PragmaDiagMappings.size() &&
+               "Invalid data, didn't find '-1' marking end of diag/map pairs");
+        if (Idx >= F.PragmaDiagMappings.size()) {
+          break; // Something is messed up but at least avoid infinite loop in
+                 // release build.
+        }
+        unsigned DiagID = F.PragmaDiagMappings[Idx++];
+        if (DiagID == (unsigned)-1) {
+          break; // no more diag/map pairs for this location.
+        }
+        diag::Mapping Map = (diag::Mapping)F.PragmaDiagMappings[Idx++];
+        DiagnosticMappingInfo MappingInfo = Diag.makeMappingInfo(Map, Loc);
+        Diag.GetCurDiagState()->setMappingInfo(DiagID, MappingInfo);
+      }
+    }
+  }
+}
+
+/// \brief Get the correct cursor and offset for loading a type.
+ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) {
+  GlobalTypeMapType::iterator I = GlobalTypeMap.find(Index);
+  assert(I != GlobalTypeMap.end() && "Corrupted global type map");
+  ModuleFile *M = I->second;
+  return RecordLocation(M, M->TypeOffsets[Index - M->BaseTypeIndex]);
+}
+
+/// \brief Read and return the type with the given index..
+///
+/// The index is the type ID, shifted and minus the number of predefs. This
+/// routine actually reads the record corresponding to the type at the given
+/// location. It is a helper routine for GetType, which deals with reading type
+/// IDs.
+QualType ASTReader::readTypeRecord(unsigned Index) {
+  RecordLocation Loc = TypeCursorForIndex(Index);
+  llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor;
+
+  // Keep track of where we are in the stream, then jump back there
+  // after reading this type.
+  SavedStreamPosition SavedPosition(DeclsCursor);
+
+  ReadingKindTracker ReadingKind(Read_Type, *this);
+
+  // Note that we are loading a type record.
+  Deserializing AType(this);
+
+  unsigned Idx = 0;
+  DeclsCursor.JumpToBit(Loc.Offset);
+  RecordData Record;
+  unsigned Code = DeclsCursor.ReadCode();
+  switch ((TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
+  case TYPE_EXT_QUAL: {
+    if (Record.size() != 2) {
+      Error("Incorrect encoding of extended qualifier type");
+      return QualType();
+    }
+    QualType Base = readType(*Loc.F, Record, Idx);
+    Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[Idx++]);
+    return Context.getQualifiedType(Base, Quals);
+  }
+
+  case TYPE_COMPLEX: {
+    if (Record.size() != 1) {
+      Error("Incorrect encoding of complex type");
+      return QualType();
+    }
+    QualType ElemType = readType(*Loc.F, Record, Idx);
+    return Context.getComplexType(ElemType);
+  }
+
+  case TYPE_POINTER: {
+    if (Record.size() != 1) {
+      Error("Incorrect encoding of pointer type");
+      return QualType();
+    }
+    QualType PointeeType = readType(*Loc.F, Record, Idx);
+    return Context.getPointerType(PointeeType);
+  }
+
+  case TYPE_BLOCK_POINTER: {
+    if (Record.size() != 1) {
+      Error("Incorrect encoding of block pointer type");
+      return QualType();
+    }
+    QualType PointeeType = readType(*Loc.F, Record, Idx);
+    return Context.getBlockPointerType(PointeeType);
+  }
+
+  case TYPE_LVALUE_REFERENCE: {
+    if (Record.size() != 2) {
+      Error("Incorrect encoding of lvalue reference type");
+      return QualType();
+    }
+    QualType PointeeType = readType(*Loc.F, Record, Idx);
+    return Context.getLValueReferenceType(PointeeType, Record[1]);
+  }
+
+  case TYPE_RVALUE_REFERENCE: {
+    if (Record.size() != 1) {
+      Error("Incorrect encoding of rvalue reference type");
+      return QualType();
+    }
+    QualType PointeeType = readType(*Loc.F, Record, Idx);
+    return Context.getRValueReferenceType(PointeeType);
+  }
+
+  case TYPE_MEMBER_POINTER: {
+    if (Record.size() != 2) {
+      Error("Incorrect encoding of member pointer type");
+      return QualType();
+    }
+    QualType PointeeType = readType(*Loc.F, Record, Idx);
+    QualType ClassType = readType(*Loc.F, Record, Idx);
+    if (PointeeType.isNull() || ClassType.isNull())
+      return QualType();
+    
+    return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
+  }
+
+  case TYPE_CONSTANT_ARRAY: {
+    QualType ElementType = readType(*Loc.F, Record, Idx);
+    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+    unsigned IndexTypeQuals = Record[2];
+    unsigned Idx = 3;
+    llvm::APInt Size = ReadAPInt(Record, Idx);
+    return Context.getConstantArrayType(ElementType, Size,
+                                         ASM, IndexTypeQuals);
+  }
+
+  case TYPE_INCOMPLETE_ARRAY: {
+    QualType ElementType = readType(*Loc.F, Record, Idx);
+    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+    unsigned IndexTypeQuals = Record[2];
+    return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
+  }
+
+  case TYPE_VARIABLE_ARRAY: {
+    QualType ElementType = readType(*Loc.F, Record, Idx);
+    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+    unsigned IndexTypeQuals = Record[2];
+    SourceLocation LBLoc = ReadSourceLocation(*Loc.F, Record[3]);
+    SourceLocation RBLoc = ReadSourceLocation(*Loc.F, Record[4]);
+    return Context.getVariableArrayType(ElementType, ReadExpr(*Loc.F),
+                                         ASM, IndexTypeQuals,
+                                         SourceRange(LBLoc, RBLoc));
+  }
+
+  case TYPE_VECTOR: {
+    if (Record.size() != 3) {
+      Error("incorrect encoding of vector type in AST file");
+      return QualType();
+    }
+
+    QualType ElementType = readType(*Loc.F, Record, Idx);
+    unsigned NumElements = Record[1];
+    unsigned VecKind = Record[2];
+    return Context.getVectorType(ElementType, NumElements,
+                                  (VectorType::VectorKind)VecKind);
+  }
+
+  case TYPE_EXT_VECTOR: {
+    if (Record.size() != 3) {
+      Error("incorrect encoding of extended vector type in AST file");
+      return QualType();
+    }
+
+    QualType ElementType = readType(*Loc.F, Record, Idx);
+    unsigned NumElements = Record[1];
+    return Context.getExtVectorType(ElementType, NumElements);
+  }
+
+  case TYPE_FUNCTION_NO_PROTO: {
+    if (Record.size() != 6) {
+      Error("incorrect encoding of no-proto function type");
+      return QualType();
+    }
+    QualType ResultType = readType(*Loc.F, Record, Idx);
+    FunctionType::ExtInfo Info(Record[1], Record[2], Record[3],
+                               (CallingConv)Record[4], Record[5]);
+    return Context.getFunctionNoProtoType(ResultType, Info);
+  }
+
+  case TYPE_FUNCTION_PROTO: {
+    QualType ResultType = readType(*Loc.F, Record, Idx);
+
+    FunctionProtoType::ExtProtoInfo EPI;
+    EPI.ExtInfo = FunctionType::ExtInfo(/*noreturn*/ Record[1],
+                                        /*hasregparm*/ Record[2],
+                                        /*regparm*/ Record[3],
+                                        static_cast<CallingConv>(Record[4]),
+                                        /*produces*/ Record[5]);
+
+    unsigned Idx = 6;
+    unsigned NumParams = Record[Idx++];
+    SmallVector<QualType, 16> ParamTypes;
+    for (unsigned I = 0; I != NumParams; ++I)
+      ParamTypes.push_back(readType(*Loc.F, Record, Idx));
+
+    EPI.Variadic = Record[Idx++];
+    EPI.HasTrailingReturn = Record[Idx++];
+    EPI.TypeQuals = Record[Idx++];
+    EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]);
+    ExceptionSpecificationType EST =
+        static_cast<ExceptionSpecificationType>(Record[Idx++]);
+    EPI.ExceptionSpecType = EST;
+    SmallVector<QualType, 2> Exceptions;
+    if (EST == EST_Dynamic) {
+      EPI.NumExceptions = Record[Idx++];
+      for (unsigned I = 0; I != EPI.NumExceptions; ++I)
+        Exceptions.push_back(readType(*Loc.F, Record, Idx));
+      EPI.Exceptions = Exceptions.data();
+    } else if (EST == EST_ComputedNoexcept) {
+      EPI.NoexceptExpr = ReadExpr(*Loc.F);
+    } else if (EST == EST_Uninstantiated) {
+      EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
+      EPI.ExceptionSpecTemplate = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
+    } else if (EST == EST_Unevaluated) {
+      EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
+    }
+    return Context.getFunctionType(ResultType, ParamTypes.data(), NumParams,
+                                    EPI);
+  }
+
+  case TYPE_UNRESOLVED_USING: {
+    unsigned Idx = 0;
+    return Context.getTypeDeclType(
+                  ReadDeclAs<UnresolvedUsingTypenameDecl>(*Loc.F, Record, Idx));
+  }
+      
+  case TYPE_TYPEDEF: {
+    if (Record.size() != 2) {
+      Error("incorrect encoding of typedef type");
+      return QualType();
+    }
+    unsigned Idx = 0;
+    TypedefNameDecl *Decl = ReadDeclAs<TypedefNameDecl>(*Loc.F, Record, Idx);
+    QualType Canonical = readType(*Loc.F, Record, Idx);
+    if (!Canonical.isNull())
+      Canonical = Context.getCanonicalType(Canonical);
+    return Context.getTypedefType(Decl, Canonical);
+  }
+
+  case TYPE_TYPEOF_EXPR:
+    return Context.getTypeOfExprType(ReadExpr(*Loc.F));
+
+  case TYPE_TYPEOF: {
+    if (Record.size() != 1) {
+      Error("incorrect encoding of typeof(type) in AST file");
+      return QualType();
+    }
+    QualType UnderlyingType = readType(*Loc.F, Record, Idx);
+    return Context.getTypeOfType(UnderlyingType);
+  }
+
+  case TYPE_DECLTYPE: {
+    QualType UnderlyingType = readType(*Loc.F, Record, Idx);
+    return Context.getDecltypeType(ReadExpr(*Loc.F), UnderlyingType);
+  }
+
+  case TYPE_UNARY_TRANSFORM: {
+    QualType BaseType = readType(*Loc.F, Record, Idx);
+    QualType UnderlyingType = readType(*Loc.F, Record, Idx);
+    UnaryTransformType::UTTKind UKind = (UnaryTransformType::UTTKind)Record[2];
+    return Context.getUnaryTransformType(BaseType, UnderlyingType, UKind);
+  }
+
+  case TYPE_AUTO:
+    return Context.getAutoType(readType(*Loc.F, Record, Idx));
+
+  case TYPE_RECORD: {
+    if (Record.size() != 2) {
+      Error("incorrect encoding of record type");
+      return QualType();
+    }
+    unsigned Idx = 0;
+    bool IsDependent = Record[Idx++];
+    RecordDecl *RD = ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx);
+    RD = cast_or_null<RecordDecl>(RD->getCanonicalDecl());
+    QualType T = Context.getRecordType(RD);
+    const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
+    return T;
+  }
+
+  case TYPE_ENUM: {
+    if (Record.size() != 2) {
+      Error("incorrect encoding of enum type");
+      return QualType();
+    }
+    unsigned Idx = 0;
+    bool IsDependent = Record[Idx++];
+    QualType T
+      = Context.getEnumType(ReadDeclAs<EnumDecl>(*Loc.F, Record, Idx));
+    const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
+    return T;
+  }
+
+  case TYPE_ATTRIBUTED: {
+    if (Record.size() != 3) {
+      Error("incorrect encoding of attributed type");
+      return QualType();
+    }
+    QualType modifiedType = readType(*Loc.F, Record, Idx);
+    QualType equivalentType = readType(*Loc.F, Record, Idx);
+    AttributedType::Kind kind = static_cast<AttributedType::Kind>(Record[2]);
+    return Context.getAttributedType(kind, modifiedType, equivalentType);
+  }
+
+  case TYPE_PAREN: {
+    if (Record.size() != 1) {
+      Error("incorrect encoding of paren type");
+      return QualType();
+    }
+    QualType InnerType = readType(*Loc.F, Record, Idx);
+    return Context.getParenType(InnerType);
+  }
+
+  case TYPE_PACK_EXPANSION: {
+    if (Record.size() != 2) {
+      Error("incorrect encoding of pack expansion type");
+      return QualType();
+    }
+    QualType Pattern = readType(*Loc.F, Record, Idx);
+    if (Pattern.isNull())
+      return QualType();
+    llvm::Optional<unsigned> NumExpansions;
+    if (Record[1])
+      NumExpansions = Record[1] - 1;
+    return Context.getPackExpansionType(Pattern, NumExpansions);
+  }
+
+  case TYPE_ELABORATED: {
+    unsigned Idx = 0;
+    ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
+    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);
+    QualType NamedType = readType(*Loc.F, Record, Idx);
+    return Context.getElaboratedType(Keyword, NNS, NamedType);
+  }
+
+  case TYPE_OBJC_INTERFACE: {
+    unsigned Idx = 0;
+    ObjCInterfaceDecl *ItfD
+      = ReadDeclAs<ObjCInterfaceDecl>(*Loc.F, Record, Idx);
+    return Context.getObjCInterfaceType(ItfD->getCanonicalDecl());
+  }
+
+  case TYPE_OBJC_OBJECT: {
+    unsigned Idx = 0;
+    QualType Base = readType(*Loc.F, Record, Idx);
+    unsigned NumProtos = Record[Idx++];
+    SmallVector<ObjCProtocolDecl*, 4> Protos;
+    for (unsigned I = 0; I != NumProtos; ++I)
+      Protos.push_back(ReadDeclAs<ObjCProtocolDecl>(*Loc.F, Record, Idx));
+    return Context.getObjCObjectType(Base, Protos.data(), NumProtos);
+  }
+
+  case TYPE_OBJC_OBJECT_POINTER: {
+    unsigned Idx = 0;
+    QualType Pointee = readType(*Loc.F, Record, Idx);
+    return Context.getObjCObjectPointerType(Pointee);
+  }
+
+  case TYPE_SUBST_TEMPLATE_TYPE_PARM: {
+    unsigned Idx = 0;
+    QualType Parm = readType(*Loc.F, Record, Idx);
+    QualType Replacement = readType(*Loc.F, Record, Idx);
+    return
+      Context.getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
+                                            Replacement);
+  }
+
+  case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: {
+    unsigned Idx = 0;
+    QualType Parm = readType(*Loc.F, Record, Idx);
+    TemplateArgument ArgPack = ReadTemplateArgument(*Loc.F, Record, Idx);
+    return Context.getSubstTemplateTypeParmPackType(
+                                               cast<TemplateTypeParmType>(Parm),
+                                                     ArgPack);
+  }
+
+  case TYPE_INJECTED_CLASS_NAME: {
+    CXXRecordDecl *D = ReadDeclAs<CXXRecordDecl>(*Loc.F, Record, Idx);
+    QualType TST = readType(*Loc.F, Record, Idx); // probably derivable
+    // FIXME: ASTContext::getInjectedClassNameType is not currently suitable
+    // for AST reading, too much interdependencies.
+    return
+      QualType(new (Context, TypeAlignment) InjectedClassNameType(D, TST), 0);
+  }
+
+  case TYPE_TEMPLATE_TYPE_PARM: {
+    unsigned Idx = 0;
+    unsigned Depth = Record[Idx++];
+    unsigned Index = Record[Idx++];
+    bool Pack = Record[Idx++];
+    TemplateTypeParmDecl *D
+      = ReadDeclAs<TemplateTypeParmDecl>(*Loc.F, Record, Idx);
+    return Context.getTemplateTypeParmType(Depth, Index, Pack, D);
+  }
+
+  case TYPE_DEPENDENT_NAME: {
+    unsigned Idx = 0;
+    ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
+    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);
+    const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx);
+    QualType Canon = readType(*Loc.F, Record, Idx);
+    if (!Canon.isNull())
+      Canon = Context.getCanonicalType(Canon);
+    return Context.getDependentNameType(Keyword, NNS, Name, Canon);
+  }
+
+  case TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: {
+    unsigned Idx = 0;
+    ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
+    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);
+    const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx);
+    unsigned NumArgs = Record[Idx++];
+    SmallVector<TemplateArgument, 8> Args;
+    Args.reserve(NumArgs);
+    while (NumArgs--)
+      Args.push_back(ReadTemplateArgument(*Loc.F, Record, Idx));
+    return Context.getDependentTemplateSpecializationType(Keyword, NNS, Name,
+                                                      Args.size(), Args.data());
+  }
+
+  case TYPE_DEPENDENT_SIZED_ARRAY: {
+    unsigned Idx = 0;
+
+    // ArrayType
+    QualType ElementType = readType(*Loc.F, Record, Idx);
+    ArrayType::ArraySizeModifier ASM
+      = (ArrayType::ArraySizeModifier)Record[Idx++];
+    unsigned IndexTypeQuals = Record[Idx++];
+
+    // DependentSizedArrayType
+    Expr *NumElts = ReadExpr(*Loc.F);
+    SourceRange Brackets = ReadSourceRange(*Loc.F, Record, Idx);
+
+    return Context.getDependentSizedArrayType(ElementType, NumElts, ASM,
+                                               IndexTypeQuals, Brackets);
+  }
+
+  case TYPE_TEMPLATE_SPECIALIZATION: {
+    unsigned Idx = 0;
+    bool IsDependent = Record[Idx++];
+    TemplateName Name = ReadTemplateName(*Loc.F, Record, Idx);
+    SmallVector<TemplateArgument, 8> Args;
+    ReadTemplateArgumentList(Args, *Loc.F, Record, Idx);
+    QualType Underlying = readType(*Loc.F, Record, Idx);
+    QualType T;
+    if (Underlying.isNull())
+      T = Context.getCanonicalTemplateSpecializationType(Name, Args.data(),
+                                                          Args.size());
+    else
+      T = Context.getTemplateSpecializationType(Name, Args.data(),
+                                                 Args.size(), Underlying);
+    const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
+    return T;
+  }
+
+  case TYPE_ATOMIC: {
+    if (Record.size() != 1) {
+      Error("Incorrect encoding of atomic type");
+      return QualType();
+    }
+    QualType ValueType = readType(*Loc.F, Record, Idx);
+    return Context.getAtomicType(ValueType);
+  }
+  }
+  llvm_unreachable("Invalid TypeCode!");
+}
+
+class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> {
+  ASTReader &Reader;
+  ModuleFile &F;
+  const ASTReader::RecordData &Record;
+  unsigned &Idx;
+
+  SourceLocation ReadSourceLocation(const ASTReader::RecordData &R,
+                                    unsigned &I) {
+    return Reader.ReadSourceLocation(F, R, I);
+  }
+
+  template<typename T>
+  T *ReadDeclAs(const ASTReader::RecordData &Record, unsigned &Idx) {
+    return Reader.ReadDeclAs<T>(F, Record, Idx);
+  }
+  
+public:
+  TypeLocReader(ASTReader &Reader, ModuleFile &F,
+                const ASTReader::RecordData &Record, unsigned &Idx)
+    : Reader(Reader), F(F), Record(Record), Idx(Idx)
+  { }
+
+  // We want compile-time assurance that we've enumerated all of
+  // these, so unfortunately we have to declare them first, then
+  // define them out-of-line.
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
+#include "clang/AST/TypeLocNodes.def"
+
+  void VisitFunctionTypeLoc(FunctionTypeLoc);
+  void VisitArrayTypeLoc(ArrayTypeLoc);
+};
+
+void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+  // nothing to do
+}
+void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+  TL.setBuiltinLoc(ReadSourceLocation(Record, Idx));
+  if (TL.needsExtraLocalData()) {
+    TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++]));
+    TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++]));
+    TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++]));
+    TL.setModeAttr(Record[Idx++]);
+  }
+}
+void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
+  TL.setStarLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+  TL.setCaretLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+  TL.setAmpLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+  TL.setAmpAmpLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+  TL.setStarLoc(ReadSourceLocation(Record, Idx));
+  TL.setClassTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
+}
+void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
+  TL.setLBracketLoc(ReadSourceLocation(Record, Idx));
+  TL.setRBracketLoc(ReadSourceLocation(Record, Idx));
+  if (Record[Idx++])
+    TL.setSizeExpr(Reader.ReadExpr(F));
+  else
+    TL.setSizeExpr(0);
+}
+void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
+  VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
+  VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
+  VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitDependentSizedArrayTypeLoc(
+                                            DependentSizedArrayTypeLoc TL) {
+  VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
+                                        DependentSizedExtVectorTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+  TL.setLocalRangeBegin(ReadSourceLocation(Record, Idx));
+  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+  TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx));
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
+    TL.setArg(i, ReadDeclAs<ParmVarDecl>(Record, Idx));
+  }
+}
+void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
+  VisitFunctionTypeLoc(TL);
+}
+void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
+  VisitFunctionTypeLoc(TL);
+}
+void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+  TL.setTypeofLoc(ReadSourceLocation(Record, Idx));
+  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+  TL.setTypeofLoc(ReadSourceLocation(Record, Idx));
+  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+  TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
+}
+void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
+  TL.setKWLoc(ReadSourceLocation(Record, Idx));
+  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+  TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
+}
+void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+  TL.setAttrNameLoc(ReadSourceLocation(Record, Idx));
+  if (TL.hasAttrOperand()) {
+    SourceRange range;
+    range.setBegin(ReadSourceLocation(Record, Idx));
+    range.setEnd(ReadSourceLocation(Record, Idx));
+    TL.setAttrOperandParensRange(range);
+  }
+  if (TL.hasAttrExprOperand()) {
+    if (Record[Idx++])
+      TL.setAttrExprOperand(Reader.ReadExpr(F));
+    else
+      TL.setAttrExprOperand(0);
+  } else if (TL.hasAttrEnumOperand())
+    TL.setAttrEnumOperandLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
+                                            SubstTemplateTypeParmTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc(
+                                          SubstTemplateTypeParmPackTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTemplateSpecializationTypeLoc(
+                                           TemplateSpecializationTypeLoc TL) {
+  TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx));
+  TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx));
+  TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
+  TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+    TL.setArgLocInfo(i,
+        Reader.GetTemplateArgumentLocInfo(F,
+                                          TL.getTypePtr()->getArg(i).getKind(),
+                                          Record, Idx));
+}
+void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) {
+  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+  TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));
+  TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
+}
+void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+  TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));
+  TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc(
+       DependentTemplateSpecializationTypeLoc TL) {
+  TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));
+  TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
+  TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx));
+  TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx));
+  TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
+  TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+  for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
+    TL.setArgLocInfo(I,
+        Reader.GetTemplateArgumentLocInfo(F,
+                                          TL.getTypePtr()->getArg(I).getKind(),
+                                          Record, Idx));
+}
+void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
+  TL.setEllipsisLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
+  TL.setHasBaseTypeAsWritten(Record[Idx++]);
+  TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
+  TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+    TL.setProtocolLoc(i, ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+  TL.setStarLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
+  TL.setKWLoc(ReadSourceLocation(Record, Idx));
+  TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+  TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F,
+                                             const RecordData &Record,
+                                             unsigned &Idx) {
+  QualType InfoTy = readType(F, Record, Idx);
+  if (InfoTy.isNull())
+    return 0;
+
+  TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy);
+  TypeLocReader TLR(*this, F, Record, Idx);
+  for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
+    TLR.Visit(TL);
+  return TInfo;
+}
+
+QualType ASTReader::GetType(TypeID ID) {
+  unsigned FastQuals = ID & Qualifiers::FastMask;
+  unsigned Index = ID >> Qualifiers::FastWidth;
+
+  if (Index < NUM_PREDEF_TYPE_IDS) {
+    QualType T;
+    switch ((PredefinedTypeIDs)Index) {
+    case PREDEF_TYPE_NULL_ID: return QualType();
+    case PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;
+    case PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;
+
+    case PREDEF_TYPE_CHAR_U_ID:
+    case PREDEF_TYPE_CHAR_S_ID:
+      // FIXME: Check that the signedness of CharTy is correct!
+      T = Context.CharTy;
+      break;
+
+    case PREDEF_TYPE_UCHAR_ID:      T = Context.UnsignedCharTy;     break;
+    case PREDEF_TYPE_USHORT_ID:     T = Context.UnsignedShortTy;    break;
+    case PREDEF_TYPE_UINT_ID:       T = Context.UnsignedIntTy;      break;
+    case PREDEF_TYPE_ULONG_ID:      T = Context.UnsignedLongTy;     break;
+    case PREDEF_TYPE_ULONGLONG_ID:  T = Context.UnsignedLongLongTy; break;
+    case PREDEF_TYPE_UINT128_ID:    T = Context.UnsignedInt128Ty;   break;
+    case PREDEF_TYPE_SCHAR_ID:      T = Context.SignedCharTy;       break;
+    case PREDEF_TYPE_WCHAR_ID:      T = Context.WCharTy;            break;
+    case PREDEF_TYPE_SHORT_ID:      T = Context.ShortTy;            break;
+    case PREDEF_TYPE_INT_ID:        T = Context.IntTy;              break;
+    case PREDEF_TYPE_LONG_ID:       T = Context.LongTy;             break;
+    case PREDEF_TYPE_LONGLONG_ID:   T = Context.LongLongTy;         break;
+    case PREDEF_TYPE_INT128_ID:     T = Context.Int128Ty;           break;
+    case PREDEF_TYPE_HALF_ID:       T = Context.HalfTy;             break;
+    case PREDEF_TYPE_FLOAT_ID:      T = Context.FloatTy;            break;
+    case PREDEF_TYPE_DOUBLE_ID:     T = Context.DoubleTy;           break;
+    case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy;       break;
+    case PREDEF_TYPE_OVERLOAD_ID:   T = Context.OverloadTy;         break;
+    case PREDEF_TYPE_BOUND_MEMBER:  T = Context.BoundMemberTy;      break;
+    case PREDEF_TYPE_PSEUDO_OBJECT: T = Context.PseudoObjectTy;     break;
+    case PREDEF_TYPE_DEPENDENT_ID:  T = Context.DependentTy;        break;
+    case PREDEF_TYPE_UNKNOWN_ANY:   T = Context.UnknownAnyTy;       break;
+    case PREDEF_TYPE_NULLPTR_ID:    T = Context.NullPtrTy;          break;
+    case PREDEF_TYPE_CHAR16_ID:     T = Context.Char16Ty;           break;
+    case PREDEF_TYPE_CHAR32_ID:     T = Context.Char32Ty;           break;
+    case PREDEF_TYPE_OBJC_ID:       T = Context.ObjCBuiltinIdTy;    break;
+    case PREDEF_TYPE_OBJC_CLASS:    T = Context.ObjCBuiltinClassTy; break;
+    case PREDEF_TYPE_OBJC_SEL:      T = Context.ObjCBuiltinSelTy;   break;
+    case PREDEF_TYPE_IMAGE1D_ID:    T = Context.OCLImage1dTy;       break;
+    case PREDEF_TYPE_IMAGE1D_ARR_ID: T = Context.OCLImage1dArrayTy; break;
+    case PREDEF_TYPE_IMAGE1D_BUFF_ID: T = Context.OCLImage1dBufferTy; break;
+    case PREDEF_TYPE_IMAGE2D_ID:    T = Context.OCLImage2dTy;       break;
+    case PREDEF_TYPE_IMAGE2D_ARR_ID: T = Context.OCLImage2dArrayTy; break;
+    case PREDEF_TYPE_IMAGE3D_ID:    T = Context.OCLImage3dTy;       break;
+    case PREDEF_TYPE_AUTO_DEDUCT:   T = Context.getAutoDeductType(); break;
+        
+    case PREDEF_TYPE_AUTO_RREF_DEDUCT: 
+      T = Context.getAutoRRefDeductType(); 
+      break;
+
+    case PREDEF_TYPE_ARC_UNBRIDGED_CAST:
+      T = Context.ARCUnbridgedCastTy;
+      break;
+
+    case PREDEF_TYPE_VA_LIST_TAG:
+      T = Context.getVaListTagType();
+      break;
+
+    case PREDEF_TYPE_BUILTIN_FN:
+      T = Context.BuiltinFnTy;
+      break;
+    }
+
+    assert(!T.isNull() && "Unknown predefined type");
+    return T.withFastQualifiers(FastQuals);
+  }
+
+  Index -= NUM_PREDEF_TYPE_IDS;
+  assert(Index < TypesLoaded.size() && "Type index out-of-range");
+  if (TypesLoaded[Index].isNull()) {
+    TypesLoaded[Index] = readTypeRecord(Index);
+    if (TypesLoaded[Index].isNull())
+      return QualType();
+
+    TypesLoaded[Index]->setFromAST();
+    if (DeserializationListener)
+      DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID),
+                                        TypesLoaded[Index]);
+  }
+
+  return TypesLoaded[Index].withFastQualifiers(FastQuals);
+}
+
+QualType ASTReader::getLocalType(ModuleFile &F, unsigned LocalID) {
+  return GetType(getGlobalTypeID(F, LocalID));
+}
+
+serialization::TypeID 
+ASTReader::getGlobalTypeID(ModuleFile &F, unsigned LocalID) const {
+  unsigned FastQuals = LocalID & Qualifiers::FastMask;
+  unsigned LocalIndex = LocalID >> Qualifiers::FastWidth;
+  
+  if (LocalIndex < NUM_PREDEF_TYPE_IDS)
+    return LocalID;
+
+  ContinuousRangeMap<uint32_t, int, 2>::iterator I
+    = F.TypeRemap.find(LocalIndex - NUM_PREDEF_TYPE_IDS);
+  assert(I != F.TypeRemap.end() && "Invalid index into type index remap");
+  
+  unsigned GlobalIndex = LocalIndex + I->second;
+  return (GlobalIndex << Qualifiers::FastWidth) | FastQuals;
+}
+
+TemplateArgumentLocInfo
+ASTReader::GetTemplateArgumentLocInfo(ModuleFile &F,
+                                      TemplateArgument::ArgKind Kind,
+                                      const RecordData &Record,
+                                      unsigned &Index) {
+  switch (Kind) {
+  case TemplateArgument::Expression:
+    return ReadExpr(F);
+  case TemplateArgument::Type:
+    return GetTypeSourceInfo(F, Record, Index);
+  case TemplateArgument::Template: {
+    NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, 
+                                                                     Index);
+    SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
+    return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc,
+                                   SourceLocation());
+  }
+  case TemplateArgument::TemplateExpansion: {
+    NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, 
+                                                                     Index);
+    SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
+    SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index);
+    return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc, 
+                                   EllipsisLoc);
+  }
+  case TemplateArgument::Null:
+  case TemplateArgument::Integral:
+  case TemplateArgument::Declaration:
+  case TemplateArgument::NullPtr:
+  case TemplateArgument::Pack:
+    // FIXME: Is this right?
+    return TemplateArgumentLocInfo();
+  }
+  llvm_unreachable("unexpected template argument loc");
+}
+
+TemplateArgumentLoc
+ASTReader::ReadTemplateArgumentLoc(ModuleFile &F,
+                                   const RecordData &Record, unsigned &Index) {
+  TemplateArgument Arg = ReadTemplateArgument(F, Record, Index);
+
+  if (Arg.getKind() == TemplateArgument::Expression) {
+    if (Record[Index++]) // bool InfoHasSameExpr.
+      return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr()));
+  }
+  return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(F, Arg.getKind(),
+                                                             Record, Index));
+}
+
+Decl *ASTReader::GetExternalDecl(uint32_t ID) {
+  return GetDecl(ID);
+}
+
+uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record, 
+                                          unsigned &Idx){
+  if (Idx >= Record.size())
+    return 0;
+  
+  unsigned LocalID = Record[Idx++];
+  return getGlobalBitOffset(M, M.CXXBaseSpecifiersOffsets[LocalID - 1]);
+}
+
+CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
+  RecordLocation Loc = getLocalBitOffset(Offset);
+  llvm::BitstreamCursor &Cursor = Loc.F->DeclsCursor;
+  SavedStreamPosition SavedPosition(Cursor);
+  Cursor.JumpToBit(Loc.Offset);
+  ReadingKindTracker ReadingKind(Read_Decl, *this);
+  RecordData Record;
+  unsigned Code = Cursor.ReadCode();
+  unsigned RecCode = Cursor.ReadRecord(Code, Record);
+  if (RecCode != DECL_CXX_BASE_SPECIFIERS) {
+    Error("Malformed AST file: missing C++ base specifiers");
+    return 0;
+  }
+
+  unsigned Idx = 0;
+  unsigned NumBases = Record[Idx++];
+  void *Mem = Context.Allocate(sizeof(CXXBaseSpecifier) * NumBases);
+  CXXBaseSpecifier *Bases = new (Mem) CXXBaseSpecifier [NumBases];
+  for (unsigned I = 0; I != NumBases; ++I)
+    Bases[I] = ReadCXXBaseSpecifier(*Loc.F, Record, Idx);
+  return Bases;
+}
+
+serialization::DeclID 
+ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const {
+  if (LocalID < NUM_PREDEF_DECL_IDS)
+    return LocalID;
+
+  ContinuousRangeMap<uint32_t, int, 2>::iterator I
+    = F.DeclRemap.find(LocalID - NUM_PREDEF_DECL_IDS);
+  assert(I != F.DeclRemap.end() && "Invalid index into decl index remap");
+  
+  return LocalID + I->second;
+}
+
+bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID,
+                                   ModuleFile &M) const {
+  GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(ID);
+  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
+  return &M == I->second;
+}
+
+ModuleFile *ASTReader::getOwningModuleFile(Decl *D) {
+  if (!D->isFromASTFile())
+    return 0;
+  GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID());
+  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
+  return I->second;
+}
+
+SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) {
+  if (ID < NUM_PREDEF_DECL_IDS)
+    return SourceLocation();
+  
+  unsigned Index = ID - NUM_PREDEF_DECL_IDS;
+
+  if (Index > DeclsLoaded.size()) {
+    Error("declaration ID out-of-range for AST file");
+    return SourceLocation();
+  }
+  
+  if (Decl *D = DeclsLoaded[Index])
+    return D->getLocation();
+
+  unsigned RawLocation = 0;
+  RecordLocation Rec = DeclCursorForID(ID, RawLocation);
+  return ReadSourceLocation(*Rec.F, RawLocation);
+}
+
+Decl *ASTReader::GetDecl(DeclID ID) {
+  if (ID < NUM_PREDEF_DECL_IDS) {    
+    switch ((PredefinedDeclIDs)ID) {
+    case PREDEF_DECL_NULL_ID:
+      return 0;
+        
+    case PREDEF_DECL_TRANSLATION_UNIT_ID:
+      return Context.getTranslationUnitDecl();
+        
+    case PREDEF_DECL_OBJC_ID_ID:
+      return Context.getObjCIdDecl();
+
+    case PREDEF_DECL_OBJC_SEL_ID:
+      return Context.getObjCSelDecl();
+
+    case PREDEF_DECL_OBJC_CLASS_ID:
+      return Context.getObjCClassDecl();
+        
+    case PREDEF_DECL_OBJC_PROTOCOL_ID:
+      return Context.getObjCProtocolDecl();
+        
+    case PREDEF_DECL_INT_128_ID:
+      return Context.getInt128Decl();
+
+    case PREDEF_DECL_UNSIGNED_INT_128_ID:
+      return Context.getUInt128Decl();
+        
+    case PREDEF_DECL_OBJC_INSTANCETYPE_ID:
+      return Context.getObjCInstanceTypeDecl();
+
+    case PREDEF_DECL_BUILTIN_VA_LIST_ID:
+      return Context.getBuiltinVaListDecl();
+    }
+  }
+  
+  unsigned Index = ID - NUM_PREDEF_DECL_IDS;
+
+  if (Index >= DeclsLoaded.size()) {
+    assert(0 && "declaration ID out-of-range for AST file");
+    Error("declaration ID out-of-range for AST file");
+    return 0;
+  }
+  
+  if (!DeclsLoaded[Index]) {
+    ReadDeclRecord(ID);
+    if (DeserializationListener)
+      DeserializationListener->DeclRead(ID, DeclsLoaded[Index]);
+  }
+
+  return DeclsLoaded[Index];
+}
+
+DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M, 
+                                                  DeclID GlobalID) {
+  if (GlobalID < NUM_PREDEF_DECL_IDS)
+    return GlobalID;
+  
+  GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID);
+  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
+  ModuleFile *Owner = I->second;
+
+  llvm::DenseMap<ModuleFile *, serialization::DeclID>::iterator Pos
+    = M.GlobalToLocalDeclIDs.find(Owner);
+  if (Pos == M.GlobalToLocalDeclIDs.end())
+    return 0;
+      
+  return GlobalID - Owner->BaseDeclID + Pos->second;
+}
+
+serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F, 
+                                            const RecordData &Record,
+                                            unsigned &Idx) {
+  if (Idx >= Record.size()) {
+    Error("Corrupted AST file");
+    return 0;
+  }
+  
+  return getGlobalDeclID(F, Record[Idx++]);
+}
+
+/// \brief Resolve the offset of a statement into a statement.
+///
+/// This operation will read a new statement from the external
+/// source each time it is called, and is meant to be used via a
+/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
+Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) {
+  // Switch case IDs are per Decl.
+  ClearSwitchCaseIDs();
+
+  // Offset here is a global offset across the entire chain.
+  RecordLocation Loc = getLocalBitOffset(Offset);
+  Loc.F->DeclsCursor.JumpToBit(Loc.Offset);
+  return ReadStmtFromStream(*Loc.F);
+}
+
+namespace {
+  class FindExternalLexicalDeclsVisitor {
+    ASTReader &Reader;
+    const DeclContext *DC;
+    bool (*isKindWeWant)(Decl::Kind);
+    
+    SmallVectorImpl<Decl*> &Decls;
+    bool PredefsVisited[NUM_PREDEF_DECL_IDS];
+
+  public:
+    FindExternalLexicalDeclsVisitor(ASTReader &Reader, const DeclContext *DC,
+                                    bool (*isKindWeWant)(Decl::Kind),
+                                    SmallVectorImpl<Decl*> &Decls)
+      : Reader(Reader), DC(DC), isKindWeWant(isKindWeWant), Decls(Decls) 
+    {
+      for (unsigned I = 0; I != NUM_PREDEF_DECL_IDS; ++I)
+        PredefsVisited[I] = false;
+    }
+
+    static bool visit(ModuleFile &M, bool Preorder, void *UserData) {
+      if (Preorder)
+        return false;
+
+      FindExternalLexicalDeclsVisitor *This
+        = static_cast<FindExternalLexicalDeclsVisitor *>(UserData);
+
+      ModuleFile::DeclContextInfosMap::iterator Info
+        = M.DeclContextInfos.find(This->DC);
+      if (Info == M.DeclContextInfos.end() || !Info->second.LexicalDecls)
+        return false;
+
+      // Load all of the declaration IDs
+      for (const KindDeclIDPair *ID = Info->second.LexicalDecls,
+                               *IDE = ID + Info->second.NumLexicalDecls; 
+           ID != IDE; ++ID) {
+        if (This->isKindWeWant && !This->isKindWeWant((Decl::Kind)ID->first))
+          continue;
+
+        // Don't add predefined declarations to the lexical context more
+        // than once.
+        if (ID->second < NUM_PREDEF_DECL_IDS) {
+          if (This->PredefsVisited[ID->second])
+            continue;
+
+          This->PredefsVisited[ID->second] = true;
+        }
+
+        if (Decl *D = This->Reader.GetLocalDecl(M, ID->second)) {
+          if (!This->DC->isDeclInLexicalTraversal(D))
+            This->Decls.push_back(D);
+        }
+      }
+
+      return false;
+    }
+  };
+}
+
+ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC,
+                                         bool (*isKindWeWant)(Decl::Kind),
+                                         SmallVectorImpl<Decl*> &Decls) {
+  // There might be lexical decls in multiple modules, for the TU at
+  // least. Walk all of the modules in the order they were loaded.
+  FindExternalLexicalDeclsVisitor Visitor(*this, DC, isKindWeWant, Decls);
+  ModuleMgr.visitDepthFirst(&FindExternalLexicalDeclsVisitor::visit, &Visitor);
+  ++NumLexicalDeclContextsRead;
+  return ELR_Success;
+}
+
+namespace {
+
+class DeclIDComp {
+  ASTReader &Reader;
+  ModuleFile &Mod;
+
+public:
+  DeclIDComp(ASTReader &Reader, ModuleFile &M) : Reader(Reader), Mod(M) {}
+
+  bool operator()(LocalDeclID L, LocalDeclID R) const {
+    SourceLocation LHS = getLocation(L);
+    SourceLocation RHS = getLocation(R);
+    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+  }
+
+  bool operator()(SourceLocation LHS, LocalDeclID R) const {
+    SourceLocation RHS = getLocation(R);
+    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+  }
+
+  bool operator()(LocalDeclID L, SourceLocation RHS) const {
+    SourceLocation LHS = getLocation(L);
+    return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+  }
+
+  SourceLocation getLocation(LocalDeclID ID) const {
+    return Reader.getSourceManager().getFileLoc(
+            Reader.getSourceLocationForDeclID(Reader.getGlobalDeclID(Mod, ID)));
+  }
+};
+
+}
+
+void ASTReader::FindFileRegionDecls(FileID File,
+                                    unsigned Offset, unsigned Length,
+                                    SmallVectorImpl<Decl *> &Decls) {
+  SourceManager &SM = getSourceManager();
+
+  llvm::DenseMap<FileID, FileDeclsInfo>::iterator I = FileDeclIDs.find(File);
+  if (I == FileDeclIDs.end())
+    return;
+
+  FileDeclsInfo &DInfo = I->second;
+  if (DInfo.Decls.empty())
+    return;
+
+  SourceLocation
+    BeginLoc = SM.getLocForStartOfFile(File).getLocWithOffset(Offset);
+  SourceLocation EndLoc = BeginLoc.getLocWithOffset(Length);
+
+  DeclIDComp DIDComp(*this, *DInfo.Mod);
+  ArrayRef<serialization::LocalDeclID>::iterator
+    BeginIt = std::lower_bound(DInfo.Decls.begin(), DInfo.Decls.end(),
+                               BeginLoc, DIDComp);
+  if (BeginIt != DInfo.Decls.begin())
+    --BeginIt;
+
+  // If we are pointing at a top-level decl inside an objc container, we need
+  // to backtrack until we find it otherwise we will fail to report that the
+  // region overlaps with an objc container.
+  while (BeginIt != DInfo.Decls.begin() &&
+         GetDecl(getGlobalDeclID(*DInfo.Mod, *BeginIt))
+             ->isTopLevelDeclInObjCContainer())
+    --BeginIt;
+
+  ArrayRef<serialization::LocalDeclID>::iterator
+    EndIt = std::upper_bound(DInfo.Decls.begin(), DInfo.Decls.end(),
+                             EndLoc, DIDComp);
+  if (EndIt != DInfo.Decls.end())
+    ++EndIt;
+  
+  for (ArrayRef<serialization::LocalDeclID>::iterator
+         DIt = BeginIt; DIt != EndIt; ++DIt)
+    Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt)));
+}
+
+namespace {
+  /// \brief ModuleFile visitor used to perform name lookup into a
+  /// declaration context.
+  class DeclContextNameLookupVisitor {
+    ASTReader &Reader;
+    llvm::SmallVectorImpl<const DeclContext *> &Contexts;
+    DeclarationName Name;
+    SmallVectorImpl<NamedDecl *> &Decls;
+
+  public:
+    DeclContextNameLookupVisitor(ASTReader &Reader, 
+                                 SmallVectorImpl<const DeclContext *> &Contexts, 
+                                 DeclarationName Name,
+                                 SmallVectorImpl<NamedDecl *> &Decls)
+      : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { }
+
+    static bool visit(ModuleFile &M, void *UserData) {
+      DeclContextNameLookupVisitor *This
+        = static_cast<DeclContextNameLookupVisitor *>(UserData);
+
+      // Check whether we have any visible declaration information for
+      // this context in this module.
+      ModuleFile::DeclContextInfosMap::iterator Info;
+      bool FoundInfo = false;
+      for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {
+        Info = M.DeclContextInfos.find(This->Contexts[I]);
+        if (Info != M.DeclContextInfos.end() && 
+            Info->second.NameLookupTableData) {
+          FoundInfo = true;
+          break;
+        }
+      }
+
+      if (!FoundInfo)
+        return false;
+      
+      // Look for this name within this module.
+      ASTDeclContextNameLookupTable *LookupTable =
+        Info->second.NameLookupTableData;
+      ASTDeclContextNameLookupTable::iterator Pos
+        = LookupTable->find(This->Name);
+      if (Pos == LookupTable->end())
+        return false;
+
+      bool FoundAnything = false;
+      ASTDeclContextNameLookupTrait::data_type Data = *Pos;
+      for (; Data.first != Data.second; ++Data.first) {
+        NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M, *Data.first);
+        if (!ND)
+          continue;
+
+        if (ND->getDeclName() != This->Name) {
+          // A name might be null because the decl's redeclarable part is
+          // currently read before reading its name. The lookup is triggered by
+          // building that decl (likely indirectly), and so it is later in the
+          // sense of "already existing" and can be ignored here.
+          continue;
+        }
+      
+        // Record this declaration.
+        FoundAnything = true;
+        This->Decls.push_back(ND);
+      }
+
+      return FoundAnything;
+    }
+  };
+}
+
+DeclContext::lookup_result
+ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
+                                          DeclarationName Name) {
+  assert(DC->hasExternalVisibleStorage() &&
+         "DeclContext has no visible decls in storage");
+  if (!Name)
+    return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
+                                      DeclContext::lookup_iterator(0));
+
+  SmallVector<NamedDecl *, 64> Decls;
+  
+  // Compute the declaration contexts we need to look into. Multiple such
+  // declaration contexts occur when two declaration contexts from disjoint
+  // modules get merged, e.g., when two namespaces with the same name are 
+  // independently defined in separate modules.
+  SmallVector<const DeclContext *, 2> Contexts;
+  Contexts.push_back(DC);
+  
+  if (DC->isNamespace()) {
+    MergedDeclsMap::iterator Merged
+      = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+    if (Merged != MergedDecls.end()) {
+      for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
+        Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
+    }
+  }
+  
+  DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
+  ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);
+  ++NumVisibleDeclContextsRead;
+  SetExternalVisibleDeclsForName(DC, Name, Decls);
+  return const_cast<DeclContext*>(DC)->lookup(Name);
+}
+
+namespace {
+  /// \brief ModuleFile visitor used to retrieve all visible names in a
+  /// declaration context.
+  class DeclContextAllNamesVisitor {
+    ASTReader &Reader;
+    llvm::SmallVectorImpl<const DeclContext *> &Contexts;
+    llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> > &Decls;
+
+  public:
+    DeclContextAllNamesVisitor(ASTReader &Reader,
+                               SmallVectorImpl<const DeclContext *> &Contexts,
+                               llvm::DenseMap<DeclarationName,
+                                           SmallVector<NamedDecl *, 8> > &Decls)
+      : Reader(Reader), Contexts(Contexts), Decls(Decls) { }
+
+    static bool visit(ModuleFile &M, void *UserData) {
+      DeclContextAllNamesVisitor *This
+        = static_cast<DeclContextAllNamesVisitor *>(UserData);
+
+      // Check whether we have any visible declaration information for
+      // this context in this module.
+      ModuleFile::DeclContextInfosMap::iterator Info;
+      bool FoundInfo = false;
+      for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {
+        Info = M.DeclContextInfos.find(This->Contexts[I]);
+        if (Info != M.DeclContextInfos.end() &&
+            Info->second.NameLookupTableData) {
+          FoundInfo = true;
+          break;
+        }
+      }
+
+      if (!FoundInfo)
+        return false;
+
+      ASTDeclContextNameLookupTable *LookupTable =
+        Info->second.NameLookupTableData;
+      bool FoundAnything = false;
+      for (ASTDeclContextNameLookupTable::data_iterator
+	     I = LookupTable->data_begin(), E = LookupTable->data_end();
+	   I != E; ++I) {
+        ASTDeclContextNameLookupTrait::data_type Data = *I;
+        for (; Data.first != Data.second; ++Data.first) {
+          NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M,
+                                                                 *Data.first);
+          if (!ND)
+            continue;
+
+          // Record this declaration.
+          FoundAnything = true;
+          This->Decls[ND->getDeclName()].push_back(ND);
+        }
+      }
+
+      return FoundAnything;
+    }
+  };
+}
+
+void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {
+  if (!DC->hasExternalVisibleStorage())
+    return;
+  llvm::DenseMap<DeclarationName, llvm::SmallVector<NamedDecl*, 8> > Decls;
+
+  // Compute the declaration contexts we need to look into. Multiple such
+  // declaration contexts occur when two declaration contexts from disjoint
+  // modules get merged, e.g., when two namespaces with the same name are
+  // independently defined in separate modules.
+  SmallVector<const DeclContext *, 2> Contexts;
+  Contexts.push_back(DC);
+
+  if (DC->isNamespace()) {
+    MergedDeclsMap::iterator Merged
+      = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+    if (Merged != MergedDecls.end()) {
+      for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
+        Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
+    }
+  }
+
+  DeclContextAllNamesVisitor Visitor(*this, Contexts, Decls);
+  ModuleMgr.visit(&DeclContextAllNamesVisitor::visit, &Visitor);
+  ++NumVisibleDeclContextsRead;
+
+  for (llvm::DenseMap<DeclarationName,
+                      llvm::SmallVector<NamedDecl*, 8> >::iterator
+         I = Decls.begin(), E = Decls.end(); I != E; ++I) {
+    SetExternalVisibleDeclsForName(DC, I->first, I->second);
+  }
+  const_cast<DeclContext *>(DC)->setHasExternalVisibleStorage(false);
+}
+
+/// \brief Under non-PCH compilation the consumer receives the objc methods
+/// before receiving the implementation, and codegen depends on this.
+/// We simulate this by deserializing and passing to consumer the methods of the
+/// implementation before passing the deserialized implementation decl.
+static void PassObjCImplDeclToConsumer(ObjCImplDecl *ImplD,
+                                       ASTConsumer *Consumer) {
+  assert(ImplD && Consumer);
+
+  for (ObjCImplDecl::method_iterator
+         I = ImplD->meth_begin(), E = ImplD->meth_end(); I != E; ++I)
+    Consumer->HandleInterestingDecl(DeclGroupRef(*I));
+
+  Consumer->HandleInterestingDecl(DeclGroupRef(ImplD));
+}
+
+void ASTReader::PassInterestingDeclsToConsumer() {
+  assert(Consumer);
+  while (!InterestingDecls.empty()) {
+    Decl *D = InterestingDecls.front();
+    InterestingDecls.pop_front();
+
+    PassInterestingDeclToConsumer(D);
+  }
+}
+
+void ASTReader::PassInterestingDeclToConsumer(Decl *D) {
+  if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D))
+    PassObjCImplDeclToConsumer(ImplD, Consumer);
+  else
+    Consumer->HandleInterestingDecl(DeclGroupRef(D));
+}
+
+void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
+  this->Consumer = Consumer;
+
+  if (!Consumer)
+    return;
+
+  for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
+    // Force deserialization of this decl, which will cause it to be queued for
+    // passing to the consumer.
+    GetDecl(ExternalDefinitions[I]);
+  }
+  ExternalDefinitions.clear();
+
+  PassInterestingDeclsToConsumer();
+}
+
+void ASTReader::PrintStats() {
+  std::fprintf(stderr, "*** AST File Statistics:\n");
+
+  unsigned NumTypesLoaded
+    = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
+                                      QualType());
+  unsigned NumDeclsLoaded
+    = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
+                                      (Decl *)0);
+  unsigned NumIdentifiersLoaded
+    = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
+                                            IdentifiersLoaded.end(),
+                                            (IdentifierInfo *)0);
+  unsigned NumMacrosLoaded
+    = MacrosLoaded.size() - std::count(MacrosLoaded.begin(),
+                                       MacrosLoaded.end(),
+                                       (MacroInfo *)0);
+  unsigned NumSelectorsLoaded
+    = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
+                                          SelectorsLoaded.end(),
+                                          Selector());
+
+  if (unsigned TotalNumSLocEntries = getTotalNumSLocs())
+    std::fprintf(stderr, "  %u/%u source location entries read (%f%%)\n",
+                 NumSLocEntriesRead, TotalNumSLocEntries,
+                 ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
+  if (!TypesLoaded.empty())
+    std::fprintf(stderr, "  %u/%u types read (%f%%)\n",
+                 NumTypesLoaded, (unsigned)TypesLoaded.size(),
+                 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
+  if (!DeclsLoaded.empty())
+    std::fprintf(stderr, "  %u/%u declarations read (%f%%)\n",
+                 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
+                 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
+  if (!IdentifiersLoaded.empty())
+    std::fprintf(stderr, "  %u/%u identifiers read (%f%%)\n",
+                 NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
+                 ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
+  if (!MacrosLoaded.empty())
+    std::fprintf(stderr, "  %u/%u macros read (%f%%)\n",
+                 NumMacrosLoaded, (unsigned)MacrosLoaded.size(),
+                 ((float)NumMacrosLoaded/MacrosLoaded.size() * 100));
+  if (!SelectorsLoaded.empty())
+    std::fprintf(stderr, "  %u/%u selectors read (%f%%)\n",
+                 NumSelectorsLoaded, (unsigned)SelectorsLoaded.size(),
+                 ((float)NumSelectorsLoaded/SelectorsLoaded.size() * 100));
+  if (TotalNumStatements)
+    std::fprintf(stderr, "  %u/%u statements read (%f%%)\n",
+                 NumStatementsRead, TotalNumStatements,
+                 ((float)NumStatementsRead/TotalNumStatements * 100));
+  if (TotalNumMacros)
+    std::fprintf(stderr, "  %u/%u macros read (%f%%)\n",
+                 NumMacrosRead, TotalNumMacros,
+                 ((float)NumMacrosRead/TotalNumMacros * 100));
+  if (TotalLexicalDeclContexts)
+    std::fprintf(stderr, "  %u/%u lexical declcontexts read (%f%%)\n",
+                 NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
+                 ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
+                  * 100));
+  if (TotalVisibleDeclContexts)
+    std::fprintf(stderr, "  %u/%u visible declcontexts read (%f%%)\n",
+                 NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
+                 ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
+                  * 100));
+  if (TotalNumMethodPoolEntries) {
+    std::fprintf(stderr, "  %u/%u method pool entries read (%f%%)\n",
+                 NumMethodPoolEntriesRead, TotalNumMethodPoolEntries,
+                 ((float)NumMethodPoolEntriesRead/TotalNumMethodPoolEntries
+                  * 100));
+    std::fprintf(stderr, "  %u method pool misses\n", NumMethodPoolMisses);
+  }
+  std::fprintf(stderr, "\n");
+  dump();
+  std::fprintf(stderr, "\n");
+}
+
+template<typename Key, typename ModuleFile, unsigned InitialCapacity>
+static void 
+dumpModuleIDMap(StringRef Name,
+                const ContinuousRangeMap<Key, ModuleFile *, 
+                                         InitialCapacity> &Map) {
+  if (Map.begin() == Map.end())
+    return;
+  
+  typedef ContinuousRangeMap<Key, ModuleFile *, InitialCapacity> MapType;
+  llvm::errs() << Name << ":\n";
+  for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end(); 
+       I != IEnd; ++I) {
+    llvm::errs() << "  " << I->first << " -> " << I->second->FileName
+      << "\n";
+  }
+}
+
+void ASTReader::dump() {
+  llvm::errs() << "*** PCH/ModuleFile Remappings:\n";
+  dumpModuleIDMap("Global bit offset map", GlobalBitOffsetsMap);
+  dumpModuleIDMap("Global source location entry map", GlobalSLocEntryMap);
+  dumpModuleIDMap("Global type map", GlobalTypeMap);
+  dumpModuleIDMap("Global declaration map", GlobalDeclMap);
+  dumpModuleIDMap("Global identifier map", GlobalIdentifierMap);
+  dumpModuleIDMap("Global macro map", GlobalMacroMap);
+  dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap);
+  dumpModuleIDMap("Global selector map", GlobalSelectorMap);
+  dumpModuleIDMap("Global preprocessed entity map", 
+                  GlobalPreprocessedEntityMap);
+  
+  llvm::errs() << "\n*** PCH/Modules Loaded:";
+  for (ModuleManager::ModuleConstIterator M = ModuleMgr.begin(), 
+                                       MEnd = ModuleMgr.end();
+       M != MEnd; ++M)
+    (*M)->dump();
+}
+
+/// Return the amount of memory used by memory buffers, breaking down
+/// by heap-backed versus mmap'ed memory.
+void ASTReader::getMemoryBufferSizes(MemoryBufferSizes &sizes) const {
+  for (ModuleConstIterator I = ModuleMgr.begin(),
+      E = ModuleMgr.end(); I != E; ++I) {
+    if (llvm::MemoryBuffer *buf = (*I)->Buffer.get()) {
+      size_t bytes = buf->getBufferSize();
+      switch (buf->getBufferKind()) {
+        case llvm::MemoryBuffer::MemoryBuffer_Malloc:
+          sizes.malloc_bytes += bytes;
+          break;
+        case llvm::MemoryBuffer::MemoryBuffer_MMap:
+          sizes.mmap_bytes += bytes;
+          break;
+      }
+    }
+  }
+}
+
+void ASTReader::InitializeSema(Sema &S) {
+  SemaObj = &S;
+  S.addExternalSource(this);
+
+  // Makes sure any declarations that were deserialized "too early"
+  // still get added to the identifier's declaration chains.
+  for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
+    SemaObj->pushExternalDeclIntoScope(PreloadedDecls[I], 
+                                       PreloadedDecls[I]->getDeclName());
+  }
+  PreloadedDecls.clear();
+
+  // Load the offsets of the declarations that Sema references.
+  // They will be lazily deserialized when needed.
+  if (!SemaDeclRefs.empty()) {
+    assert(SemaDeclRefs.size() == 2 && "More decl refs than expected!");
+    if (!SemaObj->StdNamespace)
+      SemaObj->StdNamespace = SemaDeclRefs[0];
+    if (!SemaObj->StdBadAlloc)
+      SemaObj->StdBadAlloc = SemaDeclRefs[1];
+  }
+
+  if (!FPPragmaOptions.empty()) {
+    assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS");
+    SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0];
+  }
+
+  if (!OpenCLExtensions.empty()) {
+    unsigned I = 0;
+#define OPENCLEXT(nm)  SemaObj->OpenCLFeatures.nm = OpenCLExtensions[I++];
+#include "clang/Basic/OpenCLExtensions.def"
+
+    assert(OpenCLExtensions.size() == I && "Wrong number of OPENCL_EXTENSIONS");
+  }
+}
+
+IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
+  // Note that we are loading an identifier.
+  Deserializing AnIdentifier(this);
+  
+  IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart),
+                                  /*PriorGeneration=*/0);
+  ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
+  IdentifierInfo *II = Visitor.getIdentifierInfo();
+  markIdentifierUpToDate(II);
+  return II;
+}
+
+namespace clang {
+  /// \brief An identifier-lookup iterator that enumerates all of the
+  /// identifiers stored within a set of AST files.
+  class ASTIdentifierIterator : public IdentifierIterator {
+    /// \brief The AST reader whose identifiers are being enumerated.
+    const ASTReader &Reader;
+
+    /// \brief The current index into the chain of AST files stored in
+    /// the AST reader.
+    unsigned Index;
+
+    /// \brief The current position within the identifier lookup table
+    /// of the current AST file.
+    ASTIdentifierLookupTable::key_iterator Current;
+
+    /// \brief The end position within the identifier lookup table of
+    /// the current AST file.
+    ASTIdentifierLookupTable::key_iterator End;
+
+  public:
+    explicit ASTIdentifierIterator(const ASTReader &Reader);
+
+    virtual StringRef Next();
+  };
+}
+
+ASTIdentifierIterator::ASTIdentifierIterator(const ASTReader &Reader)
+  : Reader(Reader), Index(Reader.ModuleMgr.size() - 1) {
+  ASTIdentifierLookupTable *IdTable
+    = (ASTIdentifierLookupTable *)Reader.ModuleMgr[Index].IdentifierLookupTable;
+  Current = IdTable->key_begin();
+  End = IdTable->key_end();
+}
+
+StringRef ASTIdentifierIterator::Next() {
+  while (Current == End) {
+    // If we have exhausted all of our AST files, we're done.
+    if (Index == 0)
+      return StringRef();
+
+    --Index;
+    ASTIdentifierLookupTable *IdTable
+      = (ASTIdentifierLookupTable *)Reader.ModuleMgr[Index].
+        IdentifierLookupTable;
+    Current = IdTable->key_begin();
+    End = IdTable->key_end();
+  }
+
+  // We have any identifiers remaining in the current AST file; return
+  // the next one.
+  std::pair<const char*, unsigned> Key = *Current;
+  ++Current;
+  return StringRef(Key.first, Key.second);
+}
+
+IdentifierIterator *ASTReader::getIdentifiers() const {
+  return new ASTIdentifierIterator(*this);
+}
+
+namespace clang { namespace serialization {
+  class ReadMethodPoolVisitor {
+    ASTReader &Reader;
+    Selector Sel;
+    unsigned PriorGeneration;
+    llvm::SmallVector<ObjCMethodDecl *, 4> InstanceMethods;
+    llvm::SmallVector<ObjCMethodDecl *, 4> FactoryMethods;
+
+  public:
+    ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel, 
+                          unsigned PriorGeneration)
+      : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration) { }
+    
+    static bool visit(ModuleFile &M, void *UserData) {
+      ReadMethodPoolVisitor *This
+        = static_cast<ReadMethodPoolVisitor *>(UserData);
+      
+      if (!M.SelectorLookupTable)
+        return false;
+      
+      // If we've already searched this module file, skip it now.
+      if (M.Generation <= This->PriorGeneration)
+        return true;
+
+      ASTSelectorLookupTable *PoolTable
+        = (ASTSelectorLookupTable*)M.SelectorLookupTable;
+      ASTSelectorLookupTable::iterator Pos = PoolTable->find(This->Sel);
+      if (Pos == PoolTable->end())
+        return false;
+      
+      ++This->Reader.NumSelectorsRead;
+      // FIXME: Not quite happy with the statistics here. We probably should
+      // disable this tracking when called via LoadSelector.
+      // Also, should entries without methods count as misses?
+      ++This->Reader.NumMethodPoolEntriesRead;
+      ASTSelectorLookupTrait::data_type Data = *Pos;
+      if (This->Reader.DeserializationListener)
+        This->Reader.DeserializationListener->SelectorRead(Data.ID, 
+                                                           This->Sel);
+      
+      This->InstanceMethods.append(Data.Instance.begin(), Data.Instance.end());
+      This->FactoryMethods.append(Data.Factory.begin(), Data.Factory.end());
+      return true;
+    }
+    
+    /// \brief Retrieve the instance methods found by this visitor.
+    ArrayRef<ObjCMethodDecl *> getInstanceMethods() const { 
+      return InstanceMethods; 
+    }
+
+    /// \brief Retrieve the instance methods found by this visitor.
+    ArrayRef<ObjCMethodDecl *> getFactoryMethods() const { 
+      return FactoryMethods;
+    }
+  };
+} } // end namespace clang::serialization
+
+/// \brief Add the given set of methods to the method list.
+static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods,
+                             ObjCMethodList &List) {
+  for (unsigned I = 0, N = Methods.size(); I != N; ++I) {
+    S.addMethodToGlobalList(&List, Methods[I]);
+  }
+}
+                             
+void ASTReader::ReadMethodPool(Selector Sel) {
+  // Get the selector generation and update it to the current generation.
+  unsigned &Generation = SelectorGeneration[Sel];
+  unsigned PriorGeneration = Generation;
+  Generation = CurrentGeneration;
+  
+  // Search for methods defined with this selector.
+  ReadMethodPoolVisitor Visitor(*this, Sel, PriorGeneration);
+  ModuleMgr.visit(&ReadMethodPoolVisitor::visit, &Visitor);
+  
+  if (Visitor.getInstanceMethods().empty() &&
+      Visitor.getFactoryMethods().empty()) {
+    ++NumMethodPoolMisses;
+    return;
+  }
+  
+  if (!getSema())
+    return;
+  
+  Sema &S = *getSema();
+  Sema::GlobalMethodPool::iterator Pos
+    = S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethods())).first;
+  
+  addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first);
+  addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second);
+}
+
+void ASTReader::ReadKnownNamespaces(
+                          SmallVectorImpl<NamespaceDecl *> &Namespaces) {
+  Namespaces.clear();
+  
+  for (unsigned I = 0, N = KnownNamespaces.size(); I != N; ++I) {
+    if (NamespaceDecl *Namespace 
+                = dyn_cast_or_null<NamespaceDecl>(GetDecl(KnownNamespaces[I])))
+      Namespaces.push_back(Namespace);
+  }
+}
+
+void ASTReader::ReadTentativeDefinitions(
+                  SmallVectorImpl<VarDecl *> &TentativeDefs) {
+  for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
+    VarDecl *Var = dyn_cast_or_null<VarDecl>(GetDecl(TentativeDefinitions[I]));
+    if (Var)
+      TentativeDefs.push_back(Var);
+  }
+  TentativeDefinitions.clear();
+}
+
+void ASTReader::ReadUnusedFileScopedDecls(
+                               SmallVectorImpl<const DeclaratorDecl *> &Decls) {
+  for (unsigned I = 0, N = UnusedFileScopedDecls.size(); I != N; ++I) {
+    DeclaratorDecl *D
+      = dyn_cast_or_null<DeclaratorDecl>(GetDecl(UnusedFileScopedDecls[I]));
+    if (D)
+      Decls.push_back(D);
+  }
+  UnusedFileScopedDecls.clear();
+}
+
+void ASTReader::ReadDelegatingConstructors(
+                                 SmallVectorImpl<CXXConstructorDecl *> &Decls) {
+  for (unsigned I = 0, N = DelegatingCtorDecls.size(); I != N; ++I) {
+    CXXConstructorDecl *D
+      = dyn_cast_or_null<CXXConstructorDecl>(GetDecl(DelegatingCtorDecls[I]));
+    if (D)
+      Decls.push_back(D);
+  }
+  DelegatingCtorDecls.clear();
+}
+
+void ASTReader::ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {
+  for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) {
+    TypedefNameDecl *D
+      = dyn_cast_or_null<TypedefNameDecl>(GetDecl(ExtVectorDecls[I]));
+    if (D)
+      Decls.push_back(D);
+  }
+  ExtVectorDecls.clear();
+}
+
+void ASTReader::ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) {
+  for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) {
+    CXXRecordDecl *D
+      = dyn_cast_or_null<CXXRecordDecl>(GetDecl(DynamicClasses[I]));
+    if (D)
+      Decls.push_back(D);
+  }
+  DynamicClasses.clear();
+}
+
+void 
+ASTReader::ReadLocallyScopedExternalDecls(SmallVectorImpl<NamedDecl *> &Decls) {
+  for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
+    NamedDecl *D 
+      = dyn_cast_or_null<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
+    if (D)
+      Decls.push_back(D);
+  }
+  LocallyScopedExternalDecls.clear();
+}
+
+void ASTReader::ReadReferencedSelectors(
+       SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {
+  if (ReferencedSelectorsData.empty())
+    return;
+  
+  // If there are @selector references added them to its pool. This is for
+  // implementation of -Wselector.
+  unsigned int DataSize = ReferencedSelectorsData.size()-1;
+  unsigned I = 0;
+  while (I < DataSize) {
+    Selector Sel = DecodeSelector(ReferencedSelectorsData[I++]);
+    SourceLocation SelLoc
+      = SourceLocation::getFromRawEncoding(ReferencedSelectorsData[I++]);
+    Sels.push_back(std::make_pair(Sel, SelLoc));
+  }
+  ReferencedSelectorsData.clear();
+}
+
+void ASTReader::ReadWeakUndeclaredIdentifiers(
+       SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WeakIDs) {
+  if (WeakUndeclaredIdentifiers.empty())
+    return;
+
+  for (unsigned I = 0, N = WeakUndeclaredIdentifiers.size(); I < N; /*none*/) {
+    IdentifierInfo *WeakId 
+      = DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]);
+    IdentifierInfo *AliasId 
+      = DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]);
+    SourceLocation Loc
+      = SourceLocation::getFromRawEncoding(WeakUndeclaredIdentifiers[I++]);
+    bool Used = WeakUndeclaredIdentifiers[I++];
+    WeakInfo WI(AliasId, Loc);
+    WI.setUsed(Used);
+    WeakIDs.push_back(std::make_pair(WeakId, WI));
+  }
+  WeakUndeclaredIdentifiers.clear();
+}
+
+void ASTReader::ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {
+  for (unsigned Idx = 0, N = VTableUses.size(); Idx < N; /* In loop */) {
+    ExternalVTableUse VT;
+    VT.Record = dyn_cast_or_null<CXXRecordDecl>(GetDecl(VTableUses[Idx++]));
+    VT.Location = SourceLocation::getFromRawEncoding(VTableUses[Idx++]);
+    VT.DefinitionRequired = VTableUses[Idx++];
+    VTables.push_back(VT);
+  }
+  
+  VTableUses.clear();
+}
+
+void ASTReader::ReadPendingInstantiations(
+       SmallVectorImpl<std::pair<ValueDecl *, SourceLocation> > &Pending) {
+  for (unsigned Idx = 0, N = PendingInstantiations.size(); Idx < N;) {
+    ValueDecl *D = cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++]));
+    SourceLocation Loc
+      = SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]);
+
+    Pending.push_back(std::make_pair(D, Loc));
+  }  
+  PendingInstantiations.clear();
+}
+
+void ASTReader::LoadSelector(Selector Sel) {
+  // It would be complicated to avoid reading the methods anyway. So don't.
+  ReadMethodPool(Sel);
+}
+
+void ASTReader::SetIdentifierInfo(IdentifierID ID, IdentifierInfo *II) {
+  assert(ID && "Non-zero identifier ID required");
+  assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
+  IdentifiersLoaded[ID - 1] = II;
+  if (DeserializationListener)
+    DeserializationListener->IdentifierRead(ID, II);
+}
+
+/// \brief Set the globally-visible declarations associated with the given
+/// identifier.
+///
+/// If the AST reader is currently in a state where the given declaration IDs
+/// cannot safely be resolved, they are queued until it is safe to resolve
+/// them.
+///
+/// \param II an IdentifierInfo that refers to one or more globally-visible
+/// declarations.
+///
+/// \param DeclIDs the set of declaration IDs with the name @p II that are
+/// visible at global scope.
+///
+/// \param Nonrecursive should be true to indicate that the caller knows that
+/// this call is non-recursive, and therefore the globally-visible declarations
+/// will not be placed onto the pending queue.
+void
+ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II,
+                              const SmallVectorImpl<uint32_t> &DeclIDs,
+                                   bool Nonrecursive) {
+  if (NumCurrentElementsDeserializing && !Nonrecursive) {
+    PendingIdentifierInfos.push_back(PendingIdentifierInfo());
+    PendingIdentifierInfo &PII = PendingIdentifierInfos.back();
+    PII.II = II;
+    PII.DeclIDs.append(DeclIDs.begin(), DeclIDs.end());
+    return;
+  }
+
+  for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
+    NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
+    if (SemaObj) {
+      // Introduce this declaration into the translation-unit scope
+      // and add it to the declaration chain for this identifier, so
+      // that (unqualified) name lookup will find it.
+      SemaObj->pushExternalDeclIntoScope(D, II);
+    } else {
+      // Queue this declaration so that it will be added to the
+      // translation unit scope and identifier's declaration chain
+      // once a Sema object is known.
+      PreloadedDecls.push_back(D);
+    }
+  }
+}
+
+IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) {
+  if (ID == 0)
+    return 0;
+
+  if (IdentifiersLoaded.empty()) {
+    Error("no identifier table in AST file");
+    return 0;
+  }
+
+  ID -= 1;
+  if (!IdentifiersLoaded[ID]) {
+    GlobalIdentifierMapType::iterator I = GlobalIdentifierMap.find(ID + 1);
+    assert(I != GlobalIdentifierMap.end() && "Corrupted global identifier map");
+    ModuleFile *M = I->second;
+    unsigned Index = ID - M->BaseIdentifierID;
+    const char *Str = M->IdentifierTableData + M->IdentifierOffsets[Index];
+
+    // All of the strings in the AST file are preceded by a 16-bit length.
+    // Extract that 16-bit length to avoid having to execute strlen().
+    // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
+    //  unsigned integers.  This is important to avoid integer overflow when
+    //  we cast them to 'unsigned'.
+    const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
+    unsigned StrLen = (((unsigned) StrLenPtr[0])
+                       | (((unsigned) StrLenPtr[1]) << 8)) - 1;
+    IdentifiersLoaded[ID]
+      = &PP.getIdentifierTable().get(StringRef(Str, StrLen));
+    if (DeserializationListener)
+      DeserializationListener->IdentifierRead(ID + 1, IdentifiersLoaded[ID]);
+  }
+
+  return IdentifiersLoaded[ID];
+}
+
+IdentifierInfo *ASTReader::getLocalIdentifier(ModuleFile &M, unsigned LocalID) {
+  return DecodeIdentifierInfo(getGlobalIdentifierID(M, LocalID));
+}
+
+IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) {
+  if (LocalID < NUM_PREDEF_IDENT_IDS)
+    return LocalID;
+  
+  ContinuousRangeMap<uint32_t, int, 2>::iterator I
+    = M.IdentifierRemap.find(LocalID - NUM_PREDEF_IDENT_IDS);
+  assert(I != M.IdentifierRemap.end() 
+         && "Invalid index into identifier index remap");
+  
+  return LocalID + I->second;
+}
+
+MacroInfo *ASTReader::getMacro(MacroID ID, MacroInfo *Hint) {
+  if (ID == 0)
+    return 0;
+
+  if (MacrosLoaded.empty()) {
+    Error("no macro table in AST file");
+    return 0;
+  }
+
+  ID -= NUM_PREDEF_MACRO_IDS;
+  if (!MacrosLoaded[ID]) {
+    GlobalMacroMapType::iterator I
+      = GlobalMacroMap.find(ID + NUM_PREDEF_MACRO_IDS);
+    assert(I != GlobalMacroMap.end() && "Corrupted global macro map");
+    ModuleFile *M = I->second;
+    unsigned Index = ID - M->BaseMacroID;
+    ReadMacroRecord(*M, M->MacroOffsets[Index], Hint);
+  }
+
+  return MacrosLoaded[ID];
+}
+
+MacroID ASTReader::getGlobalMacroID(ModuleFile &M, unsigned LocalID) {
+  if (LocalID < NUM_PREDEF_MACRO_IDS)
+    return LocalID;
+
+  ContinuousRangeMap<uint32_t, int, 2>::iterator I
+    = M.MacroRemap.find(LocalID - NUM_PREDEF_MACRO_IDS);
+  assert(I != M.MacroRemap.end() && "Invalid index into macro index remap");
+
+  return LocalID + I->second;
+}
+
+serialization::SubmoduleID
+ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) {
+  if (LocalID < NUM_PREDEF_SUBMODULE_IDS)
+    return LocalID;
+  
+  ContinuousRangeMap<uint32_t, int, 2>::iterator I
+    = M.SubmoduleRemap.find(LocalID - NUM_PREDEF_SUBMODULE_IDS);
+  assert(I != M.SubmoduleRemap.end() 
+         && "Invalid index into submodule index remap");
+  
+  return LocalID + I->second;
+}
+
+Module *ASTReader::getSubmodule(SubmoduleID GlobalID) {
+  if (GlobalID < NUM_PREDEF_SUBMODULE_IDS) {
+    assert(GlobalID == 0 && "Unhandled global submodule ID");
+    return 0;
+  }
+  
+  if (GlobalID > SubmodulesLoaded.size()) {
+    Error("submodule ID out of range in AST file");
+    return 0;
+  }
+  
+  return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS];
+}
+                               
+Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) {
+  return DecodeSelector(getGlobalSelectorID(M, LocalID));
+}
+
+Selector ASTReader::DecodeSelector(serialization::SelectorID ID) {
+  if (ID == 0)
+    return Selector();
+
+  if (ID > SelectorsLoaded.size()) {
+    Error("selector ID out of range in AST file");
+    return Selector();
+  }
+
+  if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) {
+    // Load this selector from the selector table.
+    GlobalSelectorMapType::iterator I = GlobalSelectorMap.find(ID);
+    assert(I != GlobalSelectorMap.end() && "Corrupted global selector map");
+    ModuleFile &M = *I->second;
+    ASTSelectorLookupTrait Trait(*this, M);
+    unsigned Idx = ID - M.BaseSelectorID - NUM_PREDEF_SELECTOR_IDS;
+    SelectorsLoaded[ID - 1] =
+      Trait.ReadKey(M.SelectorLookupTableData + M.SelectorOffsets[Idx], 0);
+    if (DeserializationListener)
+      DeserializationListener->SelectorRead(ID, SelectorsLoaded[ID - 1]);
+  }
+
+  return SelectorsLoaded[ID - 1];
+}
+
+Selector ASTReader::GetExternalSelector(serialization::SelectorID ID) {
+  return DecodeSelector(ID);
+}
+
+uint32_t ASTReader::GetNumExternalSelectors() {
+  // ID 0 (the null selector) is considered an external selector.
+  return getTotalNumSelectors() + 1;
+}
+
+serialization::SelectorID
+ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const {
+  if (LocalID < NUM_PREDEF_SELECTOR_IDS)
+    return LocalID;
+  
+  ContinuousRangeMap<uint32_t, int, 2>::iterator I
+    = M.SelectorRemap.find(LocalID - NUM_PREDEF_SELECTOR_IDS);
+  assert(I != M.SelectorRemap.end() 
+         && "Invalid index into selector index remap");
+  
+  return LocalID + I->second;
+}
+
+DeclarationName
+ASTReader::ReadDeclarationName(ModuleFile &F, 
+                               const RecordData &Record, unsigned &Idx) {
+  DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
+  switch (Kind) {
+  case DeclarationName::Identifier:
+    return DeclarationName(GetIdentifierInfo(F, Record, Idx));
+
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    return DeclarationName(ReadSelector(F, Record, Idx));
+
+  case DeclarationName::CXXConstructorName:
+    return Context.DeclarationNames.getCXXConstructorName(
+                          Context.getCanonicalType(readType(F, Record, Idx)));
+
+  case DeclarationName::CXXDestructorName:
+    return Context.DeclarationNames.getCXXDestructorName(
+                          Context.getCanonicalType(readType(F, Record, Idx)));
+
+  case DeclarationName::CXXConversionFunctionName:
+    return Context.DeclarationNames.getCXXConversionFunctionName(
+                          Context.getCanonicalType(readType(F, Record, Idx)));
+
+  case DeclarationName::CXXOperatorName:
+    return Context.DeclarationNames.getCXXOperatorName(
+                                       (OverloadedOperatorKind)Record[Idx++]);
+
+  case DeclarationName::CXXLiteralOperatorName:
+    return Context.DeclarationNames.getCXXLiteralOperatorName(
+                                       GetIdentifierInfo(F, Record, Idx));
+
+  case DeclarationName::CXXUsingDirective:
+    return DeclarationName::getUsingDirectiveName();
+  }
+
+  llvm_unreachable("Invalid NameKind!");
+}
+
+void ASTReader::ReadDeclarationNameLoc(ModuleFile &F,
+                                       DeclarationNameLoc &DNLoc,
+                                       DeclarationName Name,
+                                      const RecordData &Record, unsigned &Idx) {
+  switch (Name.getNameKind()) {
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName:
+    DNLoc.NamedType.TInfo = GetTypeSourceInfo(F, Record, Idx);
+    break;
+
+  case DeclarationName::CXXOperatorName:
+    DNLoc.CXXOperatorName.BeginOpNameLoc
+        = ReadSourceLocation(F, Record, Idx).getRawEncoding();
+    DNLoc.CXXOperatorName.EndOpNameLoc
+        = ReadSourceLocation(F, Record, Idx).getRawEncoding();
+    break;
+
+  case DeclarationName::CXXLiteralOperatorName:
+    DNLoc.CXXLiteralOperatorName.OpNameLoc
+        = ReadSourceLocation(F, Record, Idx).getRawEncoding();
+    break;
+
+  case DeclarationName::Identifier:
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+  case DeclarationName::CXXUsingDirective:
+    break;
+  }
+}
+
+void ASTReader::ReadDeclarationNameInfo(ModuleFile &F,
+                                        DeclarationNameInfo &NameInfo,
+                                      const RecordData &Record, unsigned &Idx) {
+  NameInfo.setName(ReadDeclarationName(F, Record, Idx));
+  NameInfo.setLoc(ReadSourceLocation(F, Record, Idx));
+  DeclarationNameLoc DNLoc;
+  ReadDeclarationNameLoc(F, DNLoc, NameInfo.getName(), Record, Idx);
+  NameInfo.setInfo(DNLoc);
+}
+
+void ASTReader::ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info,
+                                  const RecordData &Record, unsigned &Idx) {
+  Info.QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx);
+  unsigned NumTPLists = Record[Idx++];
+  Info.NumTemplParamLists = NumTPLists;
+  if (NumTPLists) {
+    Info.TemplParamLists = new (Context) TemplateParameterList*[NumTPLists];
+    for (unsigned i=0; i != NumTPLists; ++i)
+      Info.TemplParamLists[i] = ReadTemplateParameterList(F, Record, Idx);
+  }
+}
+
+TemplateName
+ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record, 
+                            unsigned &Idx) {
+  TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++];
+  switch (Kind) {
+  case TemplateName::Template:
+      return TemplateName(ReadDeclAs<TemplateDecl>(F, Record, Idx));
+
+  case TemplateName::OverloadedTemplate: {
+    unsigned size = Record[Idx++];
+    UnresolvedSet<8> Decls;
+    while (size--)
+      Decls.addDecl(ReadDeclAs<NamedDecl>(F, Record, Idx));
+
+    return Context.getOverloadedTemplateName(Decls.begin(), Decls.end());
+  }
+
+  case TemplateName::QualifiedTemplate: {
+    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx);
+    bool hasTemplKeyword = Record[Idx++];
+    TemplateDecl *Template = ReadDeclAs<TemplateDecl>(F, Record, Idx);
+    return Context.getQualifiedTemplateName(NNS, hasTemplKeyword, Template);
+  }
+
+  case TemplateName::DependentTemplate: {
+    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx);
+    if (Record[Idx++])  // isIdentifier
+      return Context.getDependentTemplateName(NNS,
+                                               GetIdentifierInfo(F, Record, 
+                                                                 Idx));
+    return Context.getDependentTemplateName(NNS,
+                                         (OverloadedOperatorKind)Record[Idx++]);
+  }
+
+  case TemplateName::SubstTemplateTemplateParm: {
+    TemplateTemplateParmDecl *param
+      = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx);
+    if (!param) return TemplateName();
+    TemplateName replacement = ReadTemplateName(F, Record, Idx);
+    return Context.getSubstTemplateTemplateParm(param, replacement);
+  }
+      
+  case TemplateName::SubstTemplateTemplateParmPack: {
+    TemplateTemplateParmDecl *Param 
+      = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx);
+    if (!Param)
+      return TemplateName();
+    
+    TemplateArgument ArgPack = ReadTemplateArgument(F, Record, Idx);
+    if (ArgPack.getKind() != TemplateArgument::Pack)
+      return TemplateName();
+    
+    return Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
+  }
+  }
+
+  llvm_unreachable("Unhandled template name kind!");
+}
+
+TemplateArgument
+ASTReader::ReadTemplateArgument(ModuleFile &F,
+                                const RecordData &Record, unsigned &Idx) {
+  TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];
+  switch (Kind) {
+  case TemplateArgument::Null:
+    return TemplateArgument();
+  case TemplateArgument::Type:
+    return TemplateArgument(readType(F, Record, Idx));
+  case TemplateArgument::Declaration: {
+    ValueDecl *D = ReadDeclAs<ValueDecl>(F, Record, Idx);
+    bool ForReferenceParam = Record[Idx++];
+    return TemplateArgument(D, ForReferenceParam);
+  }
+  case TemplateArgument::NullPtr:
+    return TemplateArgument(readType(F, Record, Idx), /*isNullPtr*/true);
+  case TemplateArgument::Integral: {
+    llvm::APSInt Value = ReadAPSInt(Record, Idx);
+    QualType T = readType(F, Record, Idx);
+    return TemplateArgument(Context, Value, T);
+  }
+  case TemplateArgument::Template: 
+    return TemplateArgument(ReadTemplateName(F, Record, Idx));
+  case TemplateArgument::TemplateExpansion: {
+    TemplateName Name = ReadTemplateName(F, Record, Idx);
+    llvm::Optional<unsigned> NumTemplateExpansions;
+    if (unsigned NumExpansions = Record[Idx++])
+      NumTemplateExpansions = NumExpansions - 1;
+    return TemplateArgument(Name, NumTemplateExpansions);
+  }
+  case TemplateArgument::Expression:
+    return TemplateArgument(ReadExpr(F));
+  case TemplateArgument::Pack: {
+    unsigned NumArgs = Record[Idx++];
+    TemplateArgument *Args = new (Context) TemplateArgument[NumArgs];
+    for (unsigned I = 0; I != NumArgs; ++I)
+      Args[I] = ReadTemplateArgument(F, Record, Idx);
+    return TemplateArgument(Args, NumArgs);
+  }
+  }
+
+  llvm_unreachable("Unhandled template argument kind!");
+}
+
+TemplateParameterList *
+ASTReader::ReadTemplateParameterList(ModuleFile &F,
+                                     const RecordData &Record, unsigned &Idx) {
+  SourceLocation TemplateLoc = ReadSourceLocation(F, Record, Idx);
+  SourceLocation LAngleLoc = ReadSourceLocation(F, Record, Idx);
+  SourceLocation RAngleLoc = ReadSourceLocation(F, Record, Idx);
+
+  unsigned NumParams = Record[Idx++];
+  SmallVector<NamedDecl *, 16> Params;
+  Params.reserve(NumParams);
+  while (NumParams--)
+    Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx));
+
+  TemplateParameterList* TemplateParams =
+    TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,
+                                  Params.data(), Params.size(), RAngleLoc);
+  return TemplateParams;
+}
+
+void
+ASTReader::
+ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs,
+                         ModuleFile &F, const RecordData &Record,
+                         unsigned &Idx) {
+  unsigned NumTemplateArgs = Record[Idx++];
+  TemplArgs.reserve(NumTemplateArgs);
+  while (NumTemplateArgs--)
+    TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx));
+}
+
+/// \brief Read a UnresolvedSet structure.
+void ASTReader::ReadUnresolvedSet(ModuleFile &F, ASTUnresolvedSet &Set,
+                                  const RecordData &Record, unsigned &Idx) {
+  unsigned NumDecls = Record[Idx++];
+  Set.reserve(Context, NumDecls);
+  while (NumDecls--) {
+    NamedDecl *D = ReadDeclAs<NamedDecl>(F, Record, Idx);
+    AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
+    Set.addDecl(Context, D, AS);
+  }
+}
+
+CXXBaseSpecifier
+ASTReader::ReadCXXBaseSpecifier(ModuleFile &F,
+                                const RecordData &Record, unsigned &Idx) {
+  bool isVirtual = static_cast<bool>(Record[Idx++]);
+  bool isBaseOfClass = static_cast<bool>(Record[Idx++]);
+  AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]);
+  bool inheritConstructors = static_cast<bool>(Record[Idx++]);
+  TypeSourceInfo *TInfo = GetTypeSourceInfo(F, Record, Idx);
+  SourceRange Range = ReadSourceRange(F, Record, Idx);
+  SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Idx);
+  CXXBaseSpecifier Result(Range, isVirtual, isBaseOfClass, AS, TInfo, 
+                          EllipsisLoc);
+  Result.setInheritConstructors(inheritConstructors);
+  return Result;
+}
+
+std::pair<CXXCtorInitializer **, unsigned>
+ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
+                                   unsigned &Idx) {
+  CXXCtorInitializer **CtorInitializers = 0;
+  unsigned NumInitializers = Record[Idx++];
+  if (NumInitializers) {
+    CtorInitializers
+        = new (Context) CXXCtorInitializer*[NumInitializers];
+    for (unsigned i=0; i != NumInitializers; ++i) {
+      TypeSourceInfo *TInfo = 0;
+      bool IsBaseVirtual = false;
+      FieldDecl *Member = 0;
+      IndirectFieldDecl *IndirectMember = 0;
+
+      CtorInitializerType Type = (CtorInitializerType)Record[Idx++];
+      switch (Type) {
+      case CTOR_INITIALIZER_BASE:
+        TInfo = GetTypeSourceInfo(F, Record, Idx);
+        IsBaseVirtual = Record[Idx++];
+        break;
+          
+      case CTOR_INITIALIZER_DELEGATING:
+        TInfo = GetTypeSourceInfo(F, Record, Idx);
+        break;
+
+       case CTOR_INITIALIZER_MEMBER:
+        Member = ReadDeclAs<FieldDecl>(F, Record, Idx);
+        break;
+
+       case CTOR_INITIALIZER_INDIRECT_MEMBER:
+        IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx);
+        break;
+      }
+
+      SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx);
+      Expr *Init = ReadExpr(F);
+      SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);
+      SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);
+      bool IsWritten = Record[Idx++];
+      unsigned SourceOrderOrNumArrayIndices;
+      SmallVector<VarDecl *, 8> Indices;
+      if (IsWritten) {
+        SourceOrderOrNumArrayIndices = Record[Idx++];
+      } else {
+        SourceOrderOrNumArrayIndices = Record[Idx++];
+        Indices.reserve(SourceOrderOrNumArrayIndices);
+        for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
+          Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx));
+      }
+
+      CXXCtorInitializer *BOMInit;
+      if (Type == CTOR_INITIALIZER_BASE) {
+        BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual,
+                                             LParenLoc, Init, RParenLoc,
+                                             MemberOrEllipsisLoc);
+      } else if (Type == CTOR_INITIALIZER_DELEGATING) {
+        BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc,
+                                                   Init, RParenLoc);
+      } else if (IsWritten) {
+        if (Member)
+          BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc,
+                                               LParenLoc, Init, RParenLoc);
+        else 
+          BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember,
+                                               MemberOrEllipsisLoc, LParenLoc,
+                                               Init, RParenLoc);
+      } else {
+        BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc,
+                                             LParenLoc, Init, RParenLoc,
+                                             Indices.data(), Indices.size());
+      }
+
+      if (IsWritten)
+        BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);
+      CtorInitializers[i] = BOMInit;
+    }
+  }
+
+  return std::make_pair(CtorInitializers, NumInitializers);
+}
+
+NestedNameSpecifier *
+ASTReader::ReadNestedNameSpecifier(ModuleFile &F,
+                                   const RecordData &Record, unsigned &Idx) {
+  unsigned N = Record[Idx++];
+  NestedNameSpecifier *NNS = 0, *Prev = 0;
+  for (unsigned I = 0; I != N; ++I) {
+    NestedNameSpecifier::SpecifierKind Kind
+      = (NestedNameSpecifier::SpecifierKind)Record[Idx++];
+    switch (Kind) {
+    case NestedNameSpecifier::Identifier: {
+      IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx);
+      NNS = NestedNameSpecifier::Create(Context, Prev, II);
+      break;
+    }
+
+    case NestedNameSpecifier::Namespace: {
+      NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx);
+      NNS = NestedNameSpecifier::Create(Context, Prev, NS);
+      break;
+    }
+
+    case NestedNameSpecifier::NamespaceAlias: {
+      NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx);
+      NNS = NestedNameSpecifier::Create(Context, Prev, Alias);
+      break;
+    }
+
+    case NestedNameSpecifier::TypeSpec:
+    case NestedNameSpecifier::TypeSpecWithTemplate: {
+      const Type *T = readType(F, Record, Idx).getTypePtrOrNull();
+      if (!T)
+        return 0;
+      
+      bool Template = Record[Idx++];
+      NNS = NestedNameSpecifier::Create(Context, Prev, Template, T);
+      break;
+    }
+
+    case NestedNameSpecifier::Global: {
+      NNS = NestedNameSpecifier::GlobalSpecifier(Context);
+      // No associated value, and there can't be a prefix.
+      break;
+    }
+    }
+    Prev = NNS;
+  }
+  return NNS;
+}
+
+NestedNameSpecifierLoc
+ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record, 
+                                      unsigned &Idx) {
+  unsigned N = Record[Idx++];
+  NestedNameSpecifierLocBuilder Builder;
+  for (unsigned I = 0; I != N; ++I) {
+    NestedNameSpecifier::SpecifierKind Kind
+      = (NestedNameSpecifier::SpecifierKind)Record[Idx++];
+    switch (Kind) {
+    case NestedNameSpecifier::Identifier: {
+      IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx);      
+      SourceRange Range = ReadSourceRange(F, Record, Idx);
+      Builder.Extend(Context, II, Range.getBegin(), Range.getEnd());
+      break;
+    }
+
+    case NestedNameSpecifier::Namespace: {
+      NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx);
+      SourceRange Range = ReadSourceRange(F, Record, Idx);
+      Builder.Extend(Context, NS, Range.getBegin(), Range.getEnd());
+      break;
+    }
+
+    case NestedNameSpecifier::NamespaceAlias: {
+      NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx);
+      SourceRange Range = ReadSourceRange(F, Record, Idx);
+      Builder.Extend(Context, Alias, Range.getBegin(), Range.getEnd());
+      break;
+    }
+
+    case NestedNameSpecifier::TypeSpec:
+    case NestedNameSpecifier::TypeSpecWithTemplate: {
+      bool Template = Record[Idx++];
+      TypeSourceInfo *T = GetTypeSourceInfo(F, Record, Idx);
+      if (!T)
+        return NestedNameSpecifierLoc();
+      SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
+
+      // FIXME: 'template' keyword location not saved anywhere, so we fake it.
+      Builder.Extend(Context, 
+                     Template? T->getTypeLoc().getBeginLoc() : SourceLocation(),
+                     T->getTypeLoc(), ColonColonLoc);
+      break;
+    }
+
+    case NestedNameSpecifier::Global: {
+      SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
+      Builder.MakeGlobal(Context, ColonColonLoc);
+      break;
+    }
+    }
+  }
+  
+  return Builder.getWithLocInContext(Context);
+}
+
+SourceRange
+ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record,
+                           unsigned &Idx) {
+  SourceLocation beg = ReadSourceLocation(F, Record, Idx);
+  SourceLocation end = ReadSourceLocation(F, Record, Idx);
+  return SourceRange(beg, end);
+}
+
+/// \brief Read an integral value
+llvm::APInt ASTReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
+  unsigned BitWidth = Record[Idx++];
+  unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
+  llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
+  Idx += NumWords;
+  return Result;
+}
+
+/// \brief Read a signed integral value
+llvm::APSInt ASTReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
+  bool isUnsigned = Record[Idx++];
+  return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
+}
+
+/// \brief Read a floating-point value
+llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
+  return llvm::APFloat(ReadAPInt(Record, Idx));
+}
+
+// \brief Read a string
+std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) {
+  unsigned Len = Record[Idx++];
+  std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
+  Idx += Len;
+  return Result;
+}
+
+VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record, 
+                                         unsigned &Idx) {
+  unsigned Major = Record[Idx++];
+  unsigned Minor = Record[Idx++];
+  unsigned Subminor = Record[Idx++];
+  if (Minor == 0)
+    return VersionTuple(Major);
+  if (Subminor == 0)
+    return VersionTuple(Major, Minor - 1);
+  return VersionTuple(Major, Minor - 1, Subminor - 1);
+}
+
+CXXTemporary *ASTReader::ReadCXXTemporary(ModuleFile &F, 
+                                          const RecordData &Record,
+                                          unsigned &Idx) {
+  CXXDestructorDecl *Decl = ReadDeclAs<CXXDestructorDecl>(F, Record, Idx);
+  return CXXTemporary::Create(Context, Decl);
+}
+
+DiagnosticBuilder ASTReader::Diag(unsigned DiagID) {
+  return Diag(SourceLocation(), DiagID);
+}
+
+DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) {
+  return Diags.Report(Loc, DiagID);
+}
+
+/// \brief Retrieve the identifier table associated with the
+/// preprocessor.
+IdentifierTable &ASTReader::getIdentifierTable() {
+  return PP.getIdentifierTable();
+}
+
+/// \brief Record that the given ID maps to the given switch-case
+/// statement.
+void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
+  assert((*CurrSwitchCaseStmts)[ID] == 0 &&
+         "Already have a SwitchCase with this ID");
+  (*CurrSwitchCaseStmts)[ID] = SC;
+}
+
+/// \brief Retrieve the switch-case statement with the given ID.
+SwitchCase *ASTReader::getSwitchCaseWithID(unsigned ID) {
+  assert((*CurrSwitchCaseStmts)[ID] != 0 && "No SwitchCase with this ID");
+  return (*CurrSwitchCaseStmts)[ID];
+}
+
+void ASTReader::ClearSwitchCaseIDs() {
+  CurrSwitchCaseStmts->clear();
+}
+
+void ASTReader::ReadComments() {
+  std::vector<RawComment *> Comments;
+  for (SmallVectorImpl<std::pair<llvm::BitstreamCursor,
+                                 serialization::ModuleFile *> >::iterator
+       I = CommentsCursors.begin(),
+       E = CommentsCursors.end();
+       I != E; ++I) {
+    llvm::BitstreamCursor &Cursor = I->first;
+    serialization::ModuleFile &F = *I->second;
+    SavedStreamPosition SavedPosition(Cursor);
+
+    RecordData Record;
+    while (true) {
+      unsigned Code = Cursor.ReadCode();
+      if (Code == llvm::bitc::END_BLOCK)
+        break;
+
+      if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+        // No known subblocks, always skip them.
+        Cursor.ReadSubBlockID();
+        if (Cursor.SkipBlock()) {
+          Error("malformed block record in AST file");
+          return;
+        }
+        continue;
+      }
+
+      if (Code == llvm::bitc::DEFINE_ABBREV) {
+        Cursor.ReadAbbrevRecord();
+        continue;
+      }
+
+      // Read a record.
+      Record.clear();
+      switch ((CommentRecordTypes) Cursor.ReadRecord(Code, Record)) {
+      case COMMENTS_RAW_COMMENT: {
+        unsigned Idx = 0;
+        SourceRange SR = ReadSourceRange(F, Record, Idx);
+        RawComment::CommentKind Kind =
+            (RawComment::CommentKind) Record[Idx++];
+        bool IsTrailingComment = Record[Idx++];
+        bool IsAlmostTrailingComment = Record[Idx++];
+        Comments.push_back(new (Context) RawComment(SR, Kind,
+                                                    IsTrailingComment,
+                                                    IsAlmostTrailingComment));
+        break;
+      }
+      }
+    }
+  }
+  Context.Comments.addCommentsToFront(Comments);
+}
+
+void ASTReader::finishPendingActions() {
+  while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() ||
+         !PendingMacroIDs.empty()) {
+    // If any identifiers with corresponding top-level declarations have
+    // been loaded, load those declarations now.
+    while (!PendingIdentifierInfos.empty()) {
+      SetGloballyVisibleDecls(PendingIdentifierInfos.front().II,
+                              PendingIdentifierInfos.front().DeclIDs, true);
+      PendingIdentifierInfos.pop_front();
+    }
+  
+    // Load pending declaration chains.
+    for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
+      loadPendingDeclChain(PendingDeclChains[I]);
+      PendingDeclChainsKnown.erase(PendingDeclChains[I]);
+    }
+    PendingDeclChains.clear();
+
+    // Load any pending macro definitions.
+    for (unsigned I = 0; I != PendingMacroIDs.size(); ++I) {
+      // FIXME: std::move here
+      SmallVector<MacroID, 2> GlobalIDs = PendingMacroIDs.begin()[I].second;
+      MacroInfo *Hint = 0;
+      for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx !=  NumIDs;
+           ++IDIdx) {
+        Hint = getMacro(GlobalIDs[IDIdx], Hint);
+      }
+    }
+    PendingMacroIDs.clear();
+  }
+  
+  // If we deserialized any C++ or Objective-C class definitions, any
+  // Objective-C protocol definitions, or any redeclarable templates, make sure
+  // that all redeclarations point to the definitions. Note that this can only 
+  // happen now, after the redeclaration chains have been fully wired.
+  for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
+                                           DEnd = PendingDefinitions.end();
+       D != DEnd; ++D) {
+    if (TagDecl *TD = dyn_cast<TagDecl>(*D)) {
+      if (const TagType *TagT = dyn_cast<TagType>(TD->TypeForDecl)) {
+        // Make sure that the TagType points at the definition.
+        const_cast<TagType*>(TagT)->decl = TD;
+      }
+      
+      if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) {
+        for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(),
+                                         REnd = RD->redecls_end();
+             R != REnd; ++R)
+          cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData;
+        
+      }
+
+      continue;
+    }
+    
+    if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) {
+      // Make sure that the ObjCInterfaceType points at the definition.
+      const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl))
+        ->Decl = ID;
+      
+      for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(),
+                                           REnd = ID->redecls_end();
+           R != REnd; ++R)
+        R->Data = ID->Data;
+      
+      continue;
+    }
+    
+    if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) {
+      for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(),
+                                          REnd = PD->redecls_end();
+           R != REnd; ++R)
+        R->Data = PD->Data;
+      
+      continue;
+    }
+    
+    RedeclarableTemplateDecl *RTD
+      = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl();
+    for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(),
+                                                REnd = RTD->redecls_end();
+         R != REnd; ++R)
+      R->Common = RTD->Common;
+  }
+  PendingDefinitions.clear();
+
+  // Load the bodies of any functions or methods we've encountered. We do
+  // this now (delayed) so that we can be sure that the declaration chains
+  // have been fully wired up.
+  for (PendingBodiesMap::iterator PB = PendingBodies.begin(),
+                               PBEnd = PendingBodies.end();
+       PB != PBEnd; ++PB) {
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PB->first)) {
+      // FIXME: Check for =delete/=default?
+      // FIXME: Complain about ODR violations here?
+      if (!getContext().getLangOpts().Modules || !FD->hasBody())
+        FD->setLazyBody(PB->second);
+      continue;
+    }
+
+    ObjCMethodDecl *MD = cast<ObjCMethodDecl>(PB->first);
+    if (!getContext().getLangOpts().Modules || !MD->hasBody())
+      MD->setLazyBody(PB->second);
+  }
+  PendingBodies.clear();
+}
+
+void ASTReader::FinishedDeserializing() {
+  assert(NumCurrentElementsDeserializing &&
+         "FinishedDeserializing not paired with StartedDeserializing");
+  if (NumCurrentElementsDeserializing == 1) {
+    // We decrease NumCurrentElementsDeserializing only after pending actions
+    // are finished, to avoid recursively re-calling finishPendingActions().
+    finishPendingActions();
+  }
+  --NumCurrentElementsDeserializing;
+
+  if (NumCurrentElementsDeserializing == 0 &&
+      Consumer && !PassingDeclsToConsumer) {
+    // Guard variable to avoid recursively redoing the process of passing
+    // decls to consumer.
+    SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer,
+                                                     true);
+
+    while (!InterestingDecls.empty()) {
+      // We are not in recursive loading, so it's safe to pass the "interesting"
+      // decls to the consumer.
+      Decl *D = InterestingDecls.front();
+      InterestingDecls.pop_front();
+      PassInterestingDeclToConsumer(D);
+    }
+  }
+}
+
+ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
+                     StringRef isysroot, bool DisableValidation,
+                     bool AllowASTWithCompilerErrors)
+  : Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
+    SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
+    Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context),
+    Consumer(0), ModuleMgr(PP.getFileManager()),
+    isysroot(isysroot), DisableValidation(DisableValidation),
+    AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), 
+    CurrentGeneration(0), CurrSwitchCaseStmts(&SwitchCaseStmts),
+    NumSLocEntriesRead(0), TotalNumSLocEntries(0), 
+    NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), 
+    TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), 
+    NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0), 
+    NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), 
+    NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
+    TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0),
+    PassingDeclsToConsumer(false),
+    NumCXXBaseSpecifiersLoaded(0)
+{
+  SourceMgr.setExternalSLocEntrySource(this);
+}
+
+ASTReader::~ASTReader() {
+  for (DeclContextVisibleUpdatesPending::iterator
+           I = PendingVisibleUpdates.begin(),
+           E = PendingVisibleUpdates.end();
+       I != E; ++I) {
+    for (DeclContextVisibleUpdates::iterator J = I->second.begin(),
+                                             F = I->second.end();
+         J != F; ++J)
+      delete J->first;
+  }
+}

Added: cfe/trunk/test/CodeGenOpenCL/opencl_types.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/opencl_types.cl?rev=170428&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenOpenCL/opencl_types.cl (added)
+++ cfe/trunk/test/CodeGenOpenCL/opencl_types.cl Tue Dec 18 06:30:03 2012
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -O0 | FileCheck %s
+
+void fnc1(image1d_t img) {}
+// CHECK: @fnc1(%opencl.image1d_t*
+
+void fnc1arr(image1d_array_t img) {}
+// CHECK: @fnc1arr(%opencl.image1d_array_t*
+
+void fnc1buff(image1d_buffer_t img) {}
+// CHECK: @fnc1buff(%opencl.image1d_buffer_t*
+
+void fnc2(image2d_t img) {}
+// CHECK: @fnc2(%opencl.image2d_t*
+
+void fnc2arr(image2d_array_t img) {}
+// CHECK: @fnc2arr(%opencl.image2d_array_t*
+
+void fnc3(image3d_t img) {}
+// CHECK: @fnc3(%opencl.image3d_t*
+
+kernel void foo(image1d_t img) {
+}

Added: cfe/trunk/test/PCH/ocl_types.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/ocl_types.cl?rev=170428&view=auto
==============================================================================
--- cfe/trunk/test/PCH/ocl_types.cl (added)
+++ cfe/trunk/test/PCH/ocl_types.cl Tue Dec 18 06:30:03 2012
@@ -0,0 +1,18 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/ocl_types.h -fsyntax-only %s
+
+// Test with pch.
+// RUN: %clang_cc1 -x cl -emit-pch -o %t %S/ocl_types.h
+// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -ast-print
+
+void foo1(img1d_t img);
+
+void foo2(img1darr_t img);
+
+void foo3(img1dbuff_t img);
+
+void foo4(img2d_t img);
+
+void foo5(img2darr_t img);
+
+void foo6(img3d_t img);

Added: cfe/trunk/test/PCH/ocl_types.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/ocl_types.h?rev=170428&view=auto
==============================================================================
--- cfe/trunk/test/PCH/ocl_types.h (added)
+++ cfe/trunk/test/PCH/ocl_types.h Tue Dec 18 06:30:03 2012
@@ -0,0 +1,19 @@
+/* Used with the ocl_types.cl test */
+
+// image1d_t
+typedef image1d_t img1d_t;
+
+// image1d_array_t
+typedef image1d_array_t img1darr_t;
+
+// image1d_buffer_t
+typedef image1d_buffer_t img1dbuff_t;
+
+// image2d_t
+typedef image2d_t img2d_t;
+
+// image2d_array_t
+typedef image2d_array_t img2darr_t;
+
+// image3d_t
+typedef image3d_t img3d_t;

Modified: cfe/trunk/test/Parser/opencl-image-access.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/opencl-image-access.cl?rev=170428&r1=170427&r2=170428&view=diff
==============================================================================
--- cfe/trunk/test/Parser/opencl-image-access.cl (original)
+++ cfe/trunk/test/Parser/opencl-image-access.cl Tue Dec 18 06:30:03 2012
@@ -1,16 +1,14 @@
-// RUN: %clang_cc1 %s -fsyntax-only
-
-typedef void* image2d_t;
-
-__kernel void f__ro(__read_only image2d_t a) { }
-
-__kernel void f__wo(__write_only image2d_t a) { }
-
-__kernel void f__rw(__read_write image2d_t a) { }
-
-
-__kernel void fro(read_only image2d_t a) { }
-
-__kernel void fwo(write_only image2d_t a) { }
-
-__kernel void frw(read_write image2d_t a) { }
+// RUN: %clang_cc1 %s -fsyntax-only
+
+__kernel void f__ro(__read_only image2d_t a) { }
+
+__kernel void f__wo(__write_only image2d_t a) { }
+
+__kernel void f__rw(__read_write image2d_t a) { }
+
+
+__kernel void fro(read_only image2d_t a) { }
+
+__kernel void fwo(write_only image2d_t a) { }
+
+__kernel void frw(read_write image2d_t a) { }





More information about the cfe-commits mailing list