//===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for declarations.
//
//===----------------------------------------------------------------------===//

#include "Sema.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/SourceManager.h"
// FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's)
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h" 
#include "llvm/ADT/SmallSet.h"
using namespace clang;

Sema::TypeTy *Sema::isTypeName(IdentifierInfo &II, Scope *S,
                               const CXXScopeSpec *SS) {
  DeclContext *DC = 0;
  if (SS) {
    if (SS->isInvalid())
      return 0;
    DC = static_cast<DeclContext*>(SS->getScopeRep());
  }
  Decl *IIDecl = LookupDecl(&II, Decl::IDNS_Ordinary, S, DC, false);

  if (IIDecl && (isa<TypedefDecl>(IIDecl) || 
                 isa<ObjCInterfaceDecl>(IIDecl) ||
                 isa<TagDecl>(IIDecl) ||
		 isa<TemplateTypeParmDecl>(IIDecl)))
    return IIDecl;
  return 0;
}

DeclContext *Sema::getContainingDC(DeclContext *DC) {
  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
    // A C++ out-of-line method will return to the file declaration context.
    if (MD->isOutOfLineDefinition())
      return MD->getLexicalDeclContext();

    // A C++ inline method is parsed *after* the topmost class it was declared in
    // is fully parsed (it's "complete").
    // The parsing of a C++ inline method happens at the declaration context of
    // the topmost (non-nested) class it is lexically declared in.
    assert(isa<CXXRecordDecl>(MD->getParent()) && "C++ method not in Record.");
    DC = MD->getParent();
    while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent()))
      DC = RD;

    // Return the declaration context of the topmost class the inline method is
    // declared in.
    return DC;
  }

  if (isa<ObjCMethodDecl>(DC))
    return Context.getTranslationUnitDecl();

  if (ScopedDecl *SD = dyn_cast<ScopedDecl>(DC))
    return SD->getLexicalDeclContext();

  return DC->getLexicalParent();
}

void Sema::PushDeclContext(DeclContext *DC) {
  assert(getContainingDC(DC) == CurContext &&
      "The next DeclContext should be lexically contained in the current one.");
  CurContext = DC;
}

void Sema::PopDeclContext() {
  assert(CurContext && "DeclContext imbalance!");
  CurContext = getContainingDC(CurContext);
}

/// Add this decl to the scope shadowed decl chains.
void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
  S->AddDecl(D);

  // C++ [basic.scope]p4:
  //   -- exactly one declaration shall declare a class name or
  //   enumeration name that is not a typedef name and the other
  //   declarations shall all refer to the same object or
  //   enumerator, or all refer to functions and function templates;
  //   in this case the class name or enumeration name is hidden.
  if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
    // We are pushing the name of a tag (enum or class).
    IdentifierResolver::iterator
        I = IdResolver.begin(TD->getIdentifier(),
                             TD->getDeclContext(), false/*LookInParentCtx*/);
    if (I != IdResolver.end() && isDeclInScope(*I, TD->getDeclContext(), S)) {
      // There is already a declaration with the same name in the same
      // scope. It must be found before we find the new declaration,
      // so swap the order on the shadowed declaration chain.

      IdResolver.AddShadowedDecl(TD, *I);
      return;
    }
  } else if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) {
    FunctionDecl *FD = cast<FunctionDecl>(D);
    // We are pushing the name of a function, which might be an
    // overloaded name.
    IdentifierResolver::iterator
        I = IdResolver.begin(FD->getDeclName(),
                             FD->getDeclContext(), false/*LookInParentCtx*/);
    if (I != IdResolver.end() &&
        IdResolver.isDeclInScope(*I, FD->getDeclContext(), S) &&
        (isa<OverloadedFunctionDecl>(*I) || isa<FunctionDecl>(*I))) {
      // There is already a declaration with the same name in the same
      // scope. It must be a function or an overloaded function.
      OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(*I);
      if (!Ovl) {
        // We haven't yet overloaded this function. Take the existing
        // FunctionDecl and put it into an OverloadedFunctionDecl.
        Ovl = OverloadedFunctionDecl::Create(Context, 
                                             FD->getDeclContext(),
                                             FD->getDeclName());
        Ovl->addOverload(dyn_cast<FunctionDecl>(*I));
        
        // Remove the name binding to the existing FunctionDecl...
        IdResolver.RemoveDecl(*I);

        // ... and put the OverloadedFunctionDecl in its place.
        IdResolver.AddDecl(Ovl);
      }

      // We have an OverloadedFunctionDecl. Add the new FunctionDecl
      // to its list of overloads.
      Ovl->addOverload(FD);

      return;
    }
  }

  IdResolver.AddDecl(D);
}

void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
  if (S->decl_empty()) return;
  assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
	 "Scope shouldn't contain decls!");

  for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
       I != E; ++I) {
    Decl *TmpD = static_cast<Decl*>(*I);
    assert(TmpD && "This decl didn't get pushed??");

    if (isa<CXXFieldDecl>(TmpD)) continue;

    assert(isa<ScopedDecl>(TmpD) && "Decl isn't ScopedDecl?");
    ScopedDecl *D = cast<ScopedDecl>(TmpD);
    
    IdentifierInfo *II = D->getIdentifier();
    if (!II) continue;
    
    // We only want to remove the decls from the identifier decl chains for
    // local scopes, when inside a function/method.
    // However, we *always* remove template parameters, since they are
    // purely lexically scoped (and can never be found by qualified
    // name lookup).
    if (S->getFnParent() != 0 || isa<TemplateTypeParmDecl>(D))
      IdResolver.RemoveDecl(D);

    // Chain this decl to the containing DeclContext.
    D->setNext(CurContext->getDeclChain());
    CurContext->setDeclChain(D);
  }
}

/// getObjCInterfaceDecl - Look up a for a class declaration in the scope.
/// return 0 if one not found.
ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
  // The third "scope" argument is 0 since we aren't enabling lazy built-in
  // creation from this context.
  Decl *IDecl = LookupDecl(Id, Decl::IDNS_Ordinary, 0, false);
  
  return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
}

/// LookupDecl - Look up the inner-most declaration in the specified
/// namespace.
Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
                       const DeclContext *LookupCtx,
                       bool enableLazyBuiltinCreation) {
  if (!Name) return 0;
  unsigned NS = NSI;
  if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
    NS |= Decl::IDNS_Tag;

  IdentifierResolver::iterator 
    I = LookupCtx ? IdResolver.begin(Name, LookupCtx, false/*LookInParentCtx*/)
                  : IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/);
  // Scan up the scope chain looking for a decl that matches this identifier
  // that is in the appropriate namespace.  This search should not take long, as
  // shadowing of names is uncommon, and deep shadowing is extremely uncommon.
  for (; I != IdResolver.end(); ++I)
    if ((*I)->getIdentifierNamespace() & NS)
      return *I;

  // If we didn't find a use of this identifier, and if the identifier
  // corresponds to a compiler builtin, create the decl object for the builtin
  // now, injecting it into translation unit scope, and return it.
  if (NS & Decl::IDNS_Ordinary) {
    IdentifierInfo *II = Name.getAsIdentifierInfo();
    if (enableLazyBuiltinCreation && II &&
        (LookupCtx == 0 || isa<TranslationUnitDecl>(LookupCtx))) {
      // If this is a builtin on this (or all) targets, create the decl.
      if (unsigned BuiltinID = II->getBuiltinID())
        return LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, S);
    }
    if (getLangOptions().ObjC1 && II) {
      // @interface and @compatibility_alias introduce typedef-like names.
      // Unlike typedef's, they can only be introduced at file-scope (and are 
      // therefore not scoped decls). They can, however, be shadowed by
      // other names in IDNS_Ordinary.
      ObjCInterfaceDeclsTy::iterator IDI = ObjCInterfaceDecls.find(II);
      if (IDI != ObjCInterfaceDecls.end())
        return IDI->second;
      ObjCAliasTy::iterator I = ObjCAliasDecls.find(II);
      if (I != ObjCAliasDecls.end())
        return I->second->getClassInterface();
    }
  }
  return 0;
}

void Sema::InitBuiltinVaListType() {
  if (!Context.getBuiltinVaListType().isNull())
    return;
  
  IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list");
  Decl *VaDecl = LookupDecl(VaIdent, Decl::IDNS_Ordinary, TUScope);
  TypedefDecl *VaTypedef = cast<TypedefDecl>(VaDecl);
  Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef));
}

/// LazilyCreateBuiltin - The specified Builtin-ID was first used at file scope.
/// lazily create a decl for it.
ScopedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
                                      Scope *S) {
  Builtin::ID BID = (Builtin::ID)bid;

  if (Context.BuiltinInfo.hasVAListUse(BID))
    InitBuiltinVaListType();
    
  QualType R = Context.BuiltinInfo.GetBuiltinType(BID, Context);  
  FunctionDecl *New = FunctionDecl::Create(Context,
                                           Context.getTranslationUnitDecl(),
                                           SourceLocation(), II, R,
                                           FunctionDecl::Extern, false, 0);
  
  // Create Decl objects for each parameter, adding them to the
  // FunctionDecl.
  if (FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(R)) {
    llvm::SmallVector<ParmVarDecl*, 16> Params;
    for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i)
      Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0,
                                           FT->getArgType(i), VarDecl::None, 0,
                                           0));
    New->setParams(&Params[0], Params.size());
  }
  
  
  
  // TUScope is the translation-unit scope to insert this function into.
  PushOnScopeChains(New, TUScope);
  return New;
}

/// GetStdNamespace - This method gets the C++ "std" namespace. This is where
/// everything from the standard library is defined.
NamespaceDecl *Sema::GetStdNamespace() {
  if (!StdNamespace) {
    IdentifierInfo *StdIdent = &PP.getIdentifierTable().get("std");
    DeclContext *Global = Context.getTranslationUnitDecl();
    Decl *Std = LookupDecl(StdIdent, Decl::IDNS_Tag | Decl::IDNS_Ordinary,
                           0, Global, /*enableLazyBuiltinCreation=*/false);
    StdNamespace = dyn_cast_or_null<NamespaceDecl>(Std);
  }
  return StdNamespace;
}

/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the same name
/// and scope as a previous declaration 'Old'.  Figure out how to resolve this
/// situation, merging decls or emitting diagnostics as appropriate.
///
TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
  // Allow multiple definitions for ObjC built-in typedefs.
  // FIXME: Verify the underlying types are equivalent!
  if (getLangOptions().ObjC1) {
    const IdentifierInfo *TypeID = New->getIdentifier();
    switch (TypeID->getLength()) {
    default: break;
    case 2: 
      if (!TypeID->isStr("id"))
        break;
      Context.setObjCIdType(New);
      return New;
    case 5:
      if (!TypeID->isStr("Class"))
        break;
      Context.setObjCClassType(New);
      return New;
    case 3:
      if (!TypeID->isStr("SEL"))
        break;
      Context.setObjCSelType(New);
      return New;
    case 8:
      if (!TypeID->isStr("Protocol"))
        break;
      Context.setObjCProtoType(New->getUnderlyingType());
      return New;
    }
    // Fall through - the typedef name was not a builtin type.
  }
  // Verify the old decl was also a typedef.
  TypedefDecl *Old = dyn_cast<TypedefDecl>(OldD);
  if (!Old) {
    Diag(New->getLocation(), diag::err_redefinition_different_kind)
      << New->getDeclName();
    Diag(OldD->getLocation(), diag::note_previous_definition);
    return New;
  }
  
  // If the typedef types are not identical, reject them in all languages and
  // with any extensions enabled.
  if (Old->getUnderlyingType() != New->getUnderlyingType() && 
      Context.getCanonicalType(Old->getUnderlyingType()) != 
      Context.getCanonicalType(New->getUnderlyingType())) {
    Diag(New->getLocation(), diag::err_redefinition_different_typedef)
      << New->getUnderlyingType() << Old->getUnderlyingType();
    Diag(Old->getLocation(), diag::note_previous_definition);
    return Old;
  }
  
  if (getLangOptions().Microsoft) return New;

  // C++ [dcl.typedef]p2:
  //   In a given non-class scope, a typedef specifier can be used to
  //   redefine the name of any type declared in that scope to refer
  //   to the type to which it already refers.
  if (getLangOptions().CPlusPlus && !isa<CXXRecordDecl>(CurContext))
    return New;

  // In C, redeclaration of a type is a constraint violation (6.7.2.3p1).
  // Apparently GCC, Intel, and Sun all silently ignore the redeclaration if
  // *either* declaration is in a system header. The code below implements
  // this adhoc compatibility rule. FIXME: The following code will not
  // work properly when compiling ".i" files (containing preprocessed output).
  if (PP.getDiagnostics().getSuppressSystemWarnings()) {
    SourceManager &SrcMgr = Context.getSourceManager();
    if (SrcMgr.isInSystemHeader(Old->getLocation()))
      return New;
    if (SrcMgr.isInSystemHeader(New->getLocation()))
      return New;
  }

  Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
  Diag(Old->getLocation(), diag::note_previous_definition);
  return New;
}

/// DeclhasAttr - returns true if decl Declaration already has the target
/// attribute.
static bool DeclHasAttr(const Decl *decl, const Attr *target) {
  for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext())
    if (attr->getKind() == target->getKind())
      return true;

  return false;
}

/// MergeAttributes - append attributes from the Old decl to the New one.
static void MergeAttributes(Decl *New, Decl *Old) {
  Attr *attr = const_cast<Attr*>(Old->getAttrs()), *tmp;

  while (attr) {
     tmp = attr;
     attr = attr->getNext();

    if (!DeclHasAttr(New, tmp)) {
       New->addAttr(tmp);
    } else {
       tmp->setNext(0);
       delete(tmp);
    }
  }

  Old->invalidateAttrs();
}

/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'.  Figure out how to resolve this situation,
/// merging decls or emitting diagnostics as appropriate.
/// Redeclaration will be set true if this New is a redeclaration OldD.
///
/// In C++, New and Old must be declarations that are not
/// overloaded. Use IsOverload to determine whether New and Old are
/// overloaded, and to select the Old declaration that New should be
/// merged with.
FunctionDecl *
Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) {
  assert(!isa<OverloadedFunctionDecl>(OldD) && 
         "Cannot merge with an overloaded function declaration");

  Redeclaration = false;
  // Verify the old decl was also a function.
  FunctionDecl *Old = dyn_cast<FunctionDecl>(OldD);
  if (!Old) {
    Diag(New->getLocation(), diag::err_redefinition_different_kind)
      << New->getDeclName();
    Diag(OldD->getLocation(), diag::note_previous_definition);
    return New;
  }

  // Determine whether the previous declaration was a definition,
  // implicit declaration, or a declaration.
  diag::kind PrevDiag;
  if (Old->isThisDeclarationADefinition())
    PrevDiag = diag::note_previous_definition;
  else if (Old->isImplicit())
    PrevDiag = diag::note_previous_implicit_declaration;
  else 
    PrevDiag = diag::note_previous_declaration;
  
  QualType OldQType = Context.getCanonicalType(Old->getType());
  QualType NewQType = Context.getCanonicalType(New->getType());
  
  if (getLangOptions().CPlusPlus) {
    // (C++98 13.1p2):
    //   Certain function declarations cannot be overloaded:
    //     -- Function declarations that differ only in the return type 
    //        cannot be overloaded.
    QualType OldReturnType 
      = cast<FunctionType>(OldQType.getTypePtr())->getResultType();
    QualType NewReturnType 
      = cast<FunctionType>(NewQType.getTypePtr())->getResultType();
    if (OldReturnType != NewReturnType) {
      Diag(New->getLocation(), diag::err_ovl_diff_return_type);
      Diag(Old->getLocation(), PrevDiag);
      return New;
    }

    const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
    const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
    if (OldMethod && NewMethod) {
      //    -- Member function declarations with the same name and the 
      //       same parameter types cannot be overloaded if any of them 
      //       is a static member function declaration.
      if (OldMethod->isStatic() || NewMethod->isStatic()) {
        Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
        Diag(Old->getLocation(), PrevDiag);
        return New;
      }
    }

    // (C++98 8.3.5p3):
    //   All declarations for a function shall agree exactly in both the
    //   return type and the parameter-type-list.
    if (OldQType == NewQType) {
      // We have a redeclaration.
      MergeAttributes(New, Old);
      Redeclaration = true;
      return MergeCXXFunctionDecl(New, Old);
    } 

    // Fall through for conflicting redeclarations and redefinitions.
  }

  // C: Function types need to be compatible, not identical. This handles
  // duplicate function decls like "void f(int); void f(enum X);" properly.
  if (!getLangOptions().CPlusPlus &&
      Context.typesAreCompatible(OldQType, NewQType)) {
    MergeAttributes(New, Old);
    Redeclaration = true;
    return New;
  }

  // A function that has already been declared has been redeclared or defined
  // with a different type- show appropriate diagnostic

  // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
  // TODO: This is totally simplistic.  It should handle merging functions
  // together etc, merging extern int X; int X; ...
  Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName();
  Diag(Old->getLocation(), PrevDiag);
  return New;
}

/// Predicate for C "tentative" external object definitions (C99 6.9.2).
static bool isTentativeDefinition(VarDecl *VD) {
  if (VD->isFileVarDecl())
    return (!VD->getInit() &&
            (VD->getStorageClass() == VarDecl::None ||
             VD->getStorageClass() == VarDecl::Static));
  return false;
}

/// CheckForFileScopedRedefinitions - Make sure we forgo redefinition errors
/// when dealing with C "tentative" external object definitions (C99 6.9.2).
void Sema::CheckForFileScopedRedefinitions(Scope *S, VarDecl *VD) {
  bool VDIsTentative = isTentativeDefinition(VD);
  bool VDIsIncompleteArray = VD->getType()->isIncompleteArrayType();
  
  for (IdentifierResolver::iterator
       I = IdResolver.begin(VD->getIdentifier(), 
                            VD->getDeclContext(), false/*LookInParentCtx*/), 
       E = IdResolver.end(); I != E; ++I) {
    if (*I != VD && isDeclInScope(*I, VD->getDeclContext(), S)) {
      VarDecl *OldDecl = dyn_cast<VarDecl>(*I);
      
      // Handle the following case:
      //   int a[10];
      //   int a[];   - the code below makes sure we set the correct type. 
      //   int a[11]; - this is an error, size isn't 10.
      if (OldDecl && VDIsTentative && VDIsIncompleteArray && 
          OldDecl->getType()->isConstantArrayType())
        VD->setType(OldDecl->getType());
      
      // Check for "tentative" definitions. We can't accomplish this in 
      // MergeVarDecl since the initializer hasn't been attached.
      if (!OldDecl || isTentativeDefinition(OldDecl) || VDIsTentative)
        continue;
  
      // Handle __private_extern__ just like extern.
      if (OldDecl->getStorageClass() != VarDecl::Extern &&
          OldDecl->getStorageClass() != VarDecl::PrivateExtern &&
          VD->getStorageClass() != VarDecl::Extern &&
          VD->getStorageClass() != VarDecl::PrivateExtern) {
        Diag(VD->getLocation(), diag::err_redefinition) << VD->getDeclName();
        Diag(OldDecl->getLocation(), diag::note_previous_definition);
      }
    }
  }
}

/// MergeVarDecl - We just parsed a variable 'New' which has the same name
/// and scope as a previous declaration 'Old'.  Figure out how to resolve this
/// situation, merging decls or emitting diagnostics as appropriate.
///
/// Tentative definition rules (C99 6.9.2p2) are checked by 
/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative 
/// definitions here, since the initializer hasn't been attached.
/// 
VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
  // Verify the old decl was also a variable.
  VarDecl *Old = dyn_cast<VarDecl>(OldD);
  if (!Old) {
    Diag(New->getLocation(), diag::err_redefinition_different_kind)
      << New->getDeclName();
    Diag(OldD->getLocation(), diag::note_previous_definition);
    return New;
  }

  MergeAttributes(New, Old);

  // Verify the types match.
  QualType OldCType = Context.getCanonicalType(Old->getType());
  QualType NewCType = Context.getCanonicalType(New->getType());
  if (OldCType != NewCType && !Context.typesAreCompatible(OldCType, NewCType)) {
    Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
    Diag(Old->getLocation(), diag::note_previous_definition);
    return New;
  }
  // C99 6.2.2p4: Check if we have a static decl followed by a non-static.
  if (New->getStorageClass() == VarDecl::Static &&
      (Old->getStorageClass() == VarDecl::None ||
       Old->getStorageClass() == VarDecl::Extern)) {
    Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
    Diag(Old->getLocation(), diag::note_previous_definition);
    return New;
  }
  // C99 6.2.2p4: Check if we have a non-static decl followed by a static.
  if (New->getStorageClass() != VarDecl::Static &&
      Old->getStorageClass() == VarDecl::Static) {
    Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
    Diag(Old->getLocation(), diag::note_previous_definition);
    return New;
  }
  // Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
  if (New->getStorageClass() != VarDecl::Extern && !New->isFileVarDecl()) {
    Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
    Diag(Old->getLocation(), diag::note_previous_definition);
  }
  return New;
}

/// CheckParmsForFunctionDef - Check that the parameters of the given
/// function are appropriate for the definition of a function. This
/// takes care of any checks that cannot be performed on the
/// declaration itself, e.g., that the types of each of the function
/// parameters are complete.
bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
  bool HasInvalidParm = false;
  for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
    ParmVarDecl *Param = FD->getParamDecl(p);

    // C99 6.7.5.3p4: the parameters in a parameter type list in a
    // function declarator that is part of a function definition of
    // that function shall not have incomplete type.
    if (Param->getType()->isIncompleteType() &&
        !Param->isInvalidDecl()) {
      Diag(Param->getLocation(), diag::err_typecheck_decl_incomplete_type)
        << Param->getType();
      Param->setInvalidDecl();
      HasInvalidParm = true;
    }
  }

  return HasInvalidParm;
}

/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed.
Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
  // TODO: emit error on 'int;' or 'const enum foo;'.
  // TODO: emit error on 'typedef int;'
  // if (!DS.isMissingDeclaratorOk()) Diag(...);
  
  return dyn_cast_or_null<TagDecl>(static_cast<Decl *>(DS.getTypeRep()));
}

bool Sema::CheckSingleInitializer(Expr *&Init, QualType DeclType) {  
  // Get the type before calling CheckSingleAssignmentConstraints(), since
  // it can promote the expression.
  QualType InitType = Init->getType(); 
  
  AssignConvertType ConvTy = CheckSingleAssignmentConstraints(DeclType, Init);
  return DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType,
                                  InitType, Init, "initializing");
}

bool Sema::CheckStringLiteralInit(StringLiteral *strLiteral, QualType &DeclT) {
  const ArrayType *AT = Context.getAsArrayType(DeclT);
  
  if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
    // C99 6.7.8p14. We have an array of character type with unknown size 
    // being initialized to a string literal.
    llvm::APSInt ConstVal(32);
    ConstVal = strLiteral->getByteLength() + 1;
    // Return a new array type (C99 6.7.8p22).
    DeclT = Context.getConstantArrayType(IAT->getElementType(), ConstVal, 
                                         ArrayType::Normal, 0);
  } else {
    const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
    // C99 6.7.8p14. We have an array of character type with known size.
    // FIXME: Avoid truncation for 64-bit length strings.
    if (strLiteral->getByteLength() > (unsigned)CAT->getSize().getZExtValue())
      Diag(strLiteral->getSourceRange().getBegin(),
           diag::warn_initializer_string_for_char_array_too_long)
        << strLiteral->getSourceRange();
  }
  // Set type from "char *" to "constant array of char".
  strLiteral->setType(DeclT);
  // For now, we always return false (meaning success).
  return false;
}

StringLiteral *Sema::IsStringLiteralInit(Expr *Init, QualType DeclType) {
  const ArrayType *AT = Context.getAsArrayType(DeclType);
  if (AT && AT->getElementType()->isCharType()) {
    return dyn_cast<StringLiteral>(Init);
  }
  return 0;
}

bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
                                 SourceLocation InitLoc,
                                 DeclarationName InitEntity) {
  // C++ [dcl.init.ref]p1:
  //   A variable declared to be a T&, that is "reference to type T"
  //   (8.3.2), shall be initialized by an object, or function, of
  //   type T or by an object that can be converted into a T.
  if (DeclType->isReferenceType())
    return CheckReferenceInit(Init, DeclType);

  // C99 6.7.8p3: The type of the entity to be initialized shall be an array
  // of unknown size ("[]") or an object type that is not a variable array type.
  if (const VariableArrayType *VAT = Context.getAsVariableArrayType(DeclType))
    return Diag(InitLoc,  diag::err_variable_object_no_init)
      << VAT->getSizeExpr()->getSourceRange();
  
  InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
  if (!InitList) {
    // FIXME: Handle wide strings
    if (StringLiteral *strLiteral = IsStringLiteralInit(Init, DeclType))
      return CheckStringLiteralInit(strLiteral, DeclType);

    // C++ [dcl.init]p14:
    //   -- If the destination type is a (possibly cv-qualified) class
    //      type:
    if (getLangOptions().CPlusPlus && DeclType->isRecordType()) {
      QualType DeclTypeC = Context.getCanonicalType(DeclType);
      QualType InitTypeC = Context.getCanonicalType(Init->getType());

      //   -- If the initialization is direct-initialization, or if it is
      //      copy-initialization where the cv-unqualified version of the
      //      source type is the same class as, or a derived class of, the
      //      class of the destination, constructors are considered.
      if ((DeclTypeC.getUnqualifiedType() == InitTypeC.getUnqualifiedType()) ||
          IsDerivedFrom(InitTypeC, DeclTypeC)) {
        CXXConstructorDecl *Constructor 
          = PerformInitializationByConstructor(DeclType, &Init, 1,
                                               InitLoc, Init->getSourceRange(),
                                               InitEntity, IK_Copy);
        return Constructor == 0;
      }

      //   -- Otherwise (i.e., for the remaining copy-initialization
      //      cases), user-defined conversion sequences that can
      //      convert from the source type to the destination type or
      //      (when a conversion function is used) to a derived class
      //      thereof are enumerated as described in 13.3.1.4, and the
      //      best one is chosen through overload resolution
      //      (13.3). If the conversion cannot be done or is
      //      ambiguous, the initialization is ill-formed. The
      //      function selected is called with the initializer
      //      expression as its argument; if the function is a
      //      constructor, the call initializes a temporary of the
      //      destination type.
      // FIXME: We're pretending to do copy elision here; return to
      // this when we have ASTs for such things.
      if (!PerformImplicitConversion(Init, DeclType))
        return false;
      
      return Diag(InitLoc, diag::err_typecheck_convert_incompatible)
        << DeclType << InitEntity << "initializing"
        << Init->getSourceRange();
    }

    // C99 6.7.8p16.
    if (DeclType->isArrayType())
      return Diag(Init->getLocStart(), diag::err_array_init_list_required)
        << Init->getSourceRange();

    return CheckSingleInitializer(Init, DeclType);
  } else if (getLangOptions().CPlusPlus) {
    // C++ [dcl.init]p14:
    //   [...] If the class is an aggregate (8.5.1), and the initializer
    //   is a brace-enclosed list, see 8.5.1.
    //
    // Note: 8.5.1 is handled below; here, we diagnose the case where
    // we have an initializer list and a destination type that is not
    // an aggregate.
    // FIXME: In C++0x, this is yet another form of initialization.
    if (const RecordType *ClassRec = DeclType->getAsRecordType()) {
      const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl());
      if (!ClassDecl->isAggregate())
        return Diag(InitLoc, diag::err_init_non_aggr_init_list)
           << DeclType << Init->getSourceRange();
    }
  }

  InitListChecker CheckInitList(this, InitList, DeclType);
  return CheckInitList.HadError();
}

/// GetNameForDeclarator - Determine the full declaration name for the
/// given Declarator.
DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
  switch (D.getKind()) {
  case Declarator::DK_Abstract:
    assert(D.getIdentifier() == 0 && "abstract declarators have no name");
    return DeclarationName();

  case Declarator::DK_Normal:
    assert (D.getIdentifier() != 0 && "normal declarators have an identifier");
    return DeclarationName(D.getIdentifier());

  case Declarator::DK_Constructor: {
    QualType Ty = Context.getTypeDeclType((TypeDecl *)D.getDeclaratorIdType());
    Ty = Context.getCanonicalType(Ty);
    return Context.DeclarationNames.getCXXConstructorName(Ty);
  }

  case Declarator::DK_Destructor: {
    QualType Ty = Context.getTypeDeclType((TypeDecl *)D.getDeclaratorIdType());
    Ty = Context.getCanonicalType(Ty);
    return Context.DeclarationNames.getCXXDestructorName(Ty);
  }

  case Declarator::DK_Conversion: {
    QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType());
    Ty = Context.getCanonicalType(Ty);
    return Context.DeclarationNames.getCXXConversionFunctionName(Ty);
  }

  case Declarator::DK_Operator:
    assert(D.getIdentifier() == 0 && "operator names have no identifier");
    return Context.DeclarationNames.getCXXOperatorName(
                                                D.getOverloadedOperator());
  }

  assert(false && "Unknown name kind");
  return DeclarationName();
}

Sema::DeclTy *
Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
  ScopedDecl *LastDeclarator = dyn_cast_or_null<ScopedDecl>((Decl *)lastDecl);
  DeclarationName Name = GetNameForDeclarator(D);

  // All of these full declarators require an identifier.  If it doesn't have
  // one, the ParsedFreeStandingDeclSpec action should be used.
  if (!Name) {
    if (!D.getInvalidType())  // Reject this if we think it is valid.
      Diag(D.getDeclSpec().getSourceRange().getBegin(),
           diag::err_declarator_need_ident)
        << D.getDeclSpec().getSourceRange() << D.getSourceRange();
    return 0;
  }
  
  // The scope passed in may not be a decl scope.  Zip up the scope tree until
  // we find one that is.
  while ((S->getFlags() & Scope::DeclScope) == 0)
    S = S->getParent();
  
  DeclContext *DC;
  Decl *PrevDecl;
  ScopedDecl *New;
  bool InvalidDecl = false;
 
  // See if this is a redefinition of a variable in the same scope.
  if (!D.getCXXScopeSpec().isSet()) {
    DC = CurContext;
    PrevDecl = LookupDecl(Name, Decl::IDNS_Ordinary, S);
  } else { // Something like "int foo::x;"
    DC = static_cast<DeclContext*>(D.getCXXScopeSpec().getScopeRep());
    PrevDecl = LookupDecl(Name, Decl::IDNS_Ordinary, S, DC);

    // C++ 7.3.1.2p2:
    // Members (including explicit specializations of templates) of a named
    // namespace can also be defined outside that namespace by explicit
    // qualification of the name being defined, provided that the entity being
    // defined was already declared in the namespace and the definition appears
    // after the point of declaration in a namespace that encloses the
    // declarations namespace.
    //
    if (PrevDecl == 0) {
      // No previous declaration in the qualifying scope.
      Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
        << Name << D.getCXXScopeSpec().getRange();
    } else if (!CurContext->Encloses(DC)) {
      // The qualifying scope doesn't enclose the original declaration.
      // Emit diagnostic based on current scope.
      SourceLocation L = D.getIdentifierLoc();
      SourceRange R = D.getCXXScopeSpec().getRange();
      if (isa<FunctionDecl>(CurContext)) {
        Diag(L, diag::err_invalid_declarator_in_function) << Name << R;
      } else {
        Diag(L, diag::err_invalid_declarator_scope)
          << Name << cast<NamedDecl>(DC)->getDeclName() << R;
      }
    }
  }

  if (PrevDecl && isTemplateParameterDecl(PrevDecl)) {
    // Maybe we will complain about the shadowed template parameter.
    InvalidDecl = InvalidDecl 
      || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
    // Just pretend that we didn't see the previous declaration.
    PrevDecl = 0;
  }

  // In C++, the previous declaration we find might be a tag type
  // (class or enum). In this case, the new declaration will hide the
  // tag type. 
  if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
    PrevDecl = 0;

  QualType R = GetTypeForDeclarator(D, S);
  assert(!R.isNull() && "GetTypeForDeclarator() returned null type");

  if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
    // Check that there are no default arguments (C++ only).
    if (getLangOptions().CPlusPlus)
      CheckExtraCXXDefaultArguments(D);

    TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, LastDeclarator);
    if (!NewTD) return 0;

    // Handle attributes prior to checking for duplicates in MergeVarDecl
    ProcessDeclAttributes(NewTD, D);
    // Merge the decl with the existing one if appropriate. If the decl is
    // in an outer scope, it isn't the same thing.
    if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
      NewTD = MergeTypeDefDecl(NewTD, PrevDecl);
      if (NewTD == 0) return 0;
    }
    New = NewTD;
    if (S->getFnParent() == 0) {
      // C99 6.7.7p2: If a typedef name specifies a variably modified type
      // then it shall have block scope.
      if (NewTD->getUnderlyingType()->isVariablyModifiedType()) {
        if (NewTD->getUnderlyingType()->isVariableArrayType())
          Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope);
        else
          Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope);

        InvalidDecl = true;
      }
    }
  } else if (R.getTypePtr()->isFunctionType()) {
    FunctionDecl::StorageClass SC = FunctionDecl::None;
    switch (D.getDeclSpec().getStorageClassSpec()) {
      default: assert(0 && "Unknown storage class!");
      case DeclSpec::SCS_auto:        
      case DeclSpec::SCS_register:
      case DeclSpec::SCS_mutable:
        Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_func);
        InvalidDecl = true;
        break;
      case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break;
      case DeclSpec::SCS_extern:      SC = FunctionDecl::Extern; break;
      case DeclSpec::SCS_static:      SC = FunctionDecl::Static; break;
      case DeclSpec::SCS_private_extern: SC = FunctionDecl::PrivateExtern;break;
    }

    bool isInline = D.getDeclSpec().isInlineSpecified();
    // bool isVirtual = D.getDeclSpec().isVirtualSpecified();
    bool isExplicit = D.getDeclSpec().isExplicitSpecified();

    FunctionDecl *NewFD;
    if (D.getKind() == Declarator::DK_Constructor) {
      // This is a C++ constructor declaration.
      assert(DC->isCXXRecord() &&
             "Constructors can only be declared in a member context");

      bool isInvalidDecl = CheckConstructorDeclarator(D, R, SC);

      // Create the new declaration
      NewFD = CXXConstructorDecl::Create(Context, 
                                         cast<CXXRecordDecl>(DC),
                                         D.getIdentifierLoc(), Name, R,
                                         isExplicit, isInline,
                                         /*isImplicitlyDeclared=*/false);

      if (isInvalidDecl)
        NewFD->setInvalidDecl();
    } else if (D.getKind() == Declarator::DK_Destructor) {
      // This is a C++ destructor declaration.
      if (DC->isCXXRecord()) {
        bool isInvalidDecl = CheckDestructorDeclarator(D, R, SC);

        NewFD = CXXDestructorDecl::Create(Context,
                                          cast<CXXRecordDecl>(DC),
                                          D.getIdentifierLoc(), Name, R, 
                                          isInline,
                                          /*isImplicitlyDeclared=*/false);

        if (isInvalidDecl)
          NewFD->setInvalidDecl();
      } else {
        Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
        // Create a FunctionDecl to satisfy the function definition parsing
        // code path.
        NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(),
                                     Name, R, SC, isInline, LastDeclarator,
                                     // FIXME: Move to DeclGroup...
                                   D.getDeclSpec().getSourceRange().getBegin());
        NewFD->setInvalidDecl();
      }
    } else if (D.getKind() == Declarator::DK_Conversion) {
      if (!DC->isCXXRecord()) {
        Diag(D.getIdentifierLoc(),
             diag::err_conv_function_not_member);
        return 0;
      } else {
        bool isInvalidDecl = CheckConversionDeclarator(D, R, SC);

        NewFD = CXXConversionDecl::Create(Context, 
                                          cast<CXXRecordDecl>(DC),
                                          D.getIdentifierLoc(), Name, R,
                                          isInline, isExplicit);
        
        if (isInvalidDecl)
          NewFD->setInvalidDecl();
      }
    } else if (DC->isCXXRecord()) {
      // This is a C++ method declaration.
      NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
                                    D.getIdentifierLoc(), Name, R,
                                    (SC == FunctionDecl::Static), isInline,
                                    LastDeclarator);
    } else {
      NewFD = FunctionDecl::Create(Context, DC,
                                   D.getIdentifierLoc(),
                                   Name, R, SC, isInline, LastDeclarator,
                                   // FIXME: Move to DeclGroup...
                                   D.getDeclSpec().getSourceRange().getBegin());
    }
    // Handle attributes.
    ProcessDeclAttributes(NewFD, D);

    // Handle GNU asm-label extension (encoded as an attribute).
    if (Expr *E = (Expr*) D.getAsmLabel()) {
      // The parser guarantees this is a string.
      StringLiteral *SE = cast<StringLiteral>(E);  
      NewFD->addAttr(new AsmLabelAttr(std::string(SE->getStrData(),
                                                  SE->getByteLength())));
    }

    // Copy the parameter declarations from the declarator D to
    // the function declaration NewFD, if they are available.
    if (D.getNumTypeObjects() > 0) {
      DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;

      // Create Decl objects for each parameter, adding them to the
      // FunctionDecl.
      llvm::SmallVector<ParmVarDecl*, 16> Params;
  
      // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs
      // function that takes no arguments, not a function that takes a
      // single void argument.
      // We let through "const void" here because Sema::GetTypeForDeclarator
      // already checks for that case.
      if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
          FTI.ArgInfo[0].Param &&
          ((ParmVarDecl*)FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
        // empty arg list, don't push any params.
        ParmVarDecl *Param = (ParmVarDecl*)FTI.ArgInfo[0].Param;

        // In C++, the empty parameter-type-list must be spelled "void"; a
        // typedef of void is not permitted.
        if (getLangOptions().CPlusPlus &&
            Param->getType().getUnqualifiedType() != Context.VoidTy) {
          Diag(Param->getLocation(), diag::ext_param_typedef_of_void);
        }
      } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
        for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
          Params.push_back((ParmVarDecl *)FTI.ArgInfo[i].Param);
      }
  
      NewFD->setParams(&Params[0], Params.size());
    } else if (R->getAsTypedefType()) {
      // When we're declaring a function with a typedef, as in the
      // following example, we'll need to synthesize (unnamed)
      // parameters for use in the declaration.
      //
      // @code
      // typedef void fn(int);
      // fn f;
      // @endcode
      const FunctionTypeProto *FT = R->getAsFunctionTypeProto();
      if (!FT) {
        // This is a typedef of a function with no prototype, so we
        // don't need to do anything.
      } else if ((FT->getNumArgs() == 0) ||
          (FT->getNumArgs() == 1 && !FT->isVariadic() &&
           FT->getArgType(0)->isVoidType())) {
        // This is a zero-argument function. We don't need to do anything.
      } else {
        // Synthesize a parameter for each argument type.
        llvm::SmallVector<ParmVarDecl*, 16> Params;
        for (FunctionTypeProto::arg_type_iterator ArgType = FT->arg_type_begin();
             ArgType != FT->arg_type_end(); ++ArgType) {
          Params.push_back(ParmVarDecl::Create(Context, DC,
                                               SourceLocation(), 0,
                                               *ArgType, VarDecl::None,
                                               0, 0));
        }

        NewFD->setParams(&Params[0], Params.size());
      }
    }

    // C++ constructors and destructors are handled by separate
    // routines, since they don't require any declaration merging (C++
    // [class.mfct]p2) and they aren't ever pushed into scope, because
    // they can't be found by name lookup anyway (C++ [class.ctor]p2).
    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD))
      return ActOnConstructorDeclarator(Constructor);
    else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(NewFD))
      return ActOnDestructorDeclarator(Destructor);
    
    // Extra checking for conversion functions, including recording
    // the conversion function in its class.
    if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
      ActOnConversionDeclarator(Conversion);

    // Extra checking for C++ overloaded operators (C++ [over.oper]).
    if (NewFD->isOverloadedOperator() &&
        CheckOverloadedOperatorDeclaration(NewFD))
      NewFD->setInvalidDecl();
    
    // Merge the decl with the existing one if appropriate. Since C functions
    // are in a flat namespace, make sure we consider decls in outer scopes.
    if (PrevDecl &&
        (!getLangOptions().CPlusPlus||isDeclInScope(PrevDecl, DC, S))) {
      bool Redeclaration = false;

      // If C++, determine whether NewFD is an overload of PrevDecl or
      // a declaration that requires merging. If it's an overload,
      // there's no more work to do here; we'll just add the new
      // function to the scope.
      OverloadedFunctionDecl::function_iterator MatchedDecl;
      if (!getLangOptions().CPlusPlus ||
          !IsOverload(NewFD, PrevDecl, MatchedDecl)) {
        Decl *OldDecl = PrevDecl;

        // If PrevDecl was an overloaded function, extract the
        // FunctionDecl that matched.
        if (isa<OverloadedFunctionDecl>(PrevDecl))
          OldDecl = *MatchedDecl;

        // NewFD and PrevDecl represent declarations that need to be
        // merged. 
        NewFD = MergeFunctionDecl(NewFD, OldDecl, Redeclaration);

        if (NewFD == 0) return 0;
        if (Redeclaration) {
          NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));

          if (OldDecl == PrevDecl) {
            // Remove the name binding for the previous
            // declaration. We'll add the binding back later, but then
            // it will refer to the new declaration (which will
            // contain more information).
            IdResolver.RemoveDecl(cast<NamedDecl>(PrevDecl));
          } else {
            // We need to update the OverloadedFunctionDecl with the
            // latest declaration of this function, so that name
            // lookup will always refer to the latest declaration of
            // this function.
            *MatchedDecl = NewFD;
           
            // Add the redeclaration to the current scope, since we'll
            // be skipping PushOnScopeChains.
            S->AddDecl(NewFD);

            return NewFD;
          }
        }
      }
    }
    New = NewFD;

    // In C++, check default arguments now that we have merged decls.
    if (getLangOptions().CPlusPlus)
      CheckCXXDefaultArguments(NewFD);
  } else {
    // Check that there are no default arguments (C++ only).
    if (getLangOptions().CPlusPlus)
      CheckExtraCXXDefaultArguments(D);

    if (R.getTypePtr()->isObjCInterfaceType()) {
      Diag(D.getIdentifierLoc(), diag::err_statically_allocated_object)
        << D.getIdentifier();
      InvalidDecl = true;
    }

    VarDecl *NewVD;
    VarDecl::StorageClass SC;
    switch (D.getDeclSpec().getStorageClassSpec()) {
    default: assert(0 && "Unknown storage class!");
    case DeclSpec::SCS_unspecified:    SC = VarDecl::None; break;
    case DeclSpec::SCS_extern:         SC = VarDecl::Extern; break;
    case DeclSpec::SCS_static:         SC = VarDecl::Static; break;
    case DeclSpec::SCS_auto:           SC = VarDecl::Auto; break;
    case DeclSpec::SCS_register:       SC = VarDecl::Register; break;
    case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
    case DeclSpec::SCS_mutable:
      // mutable can only appear on non-static class members, so it's always
      // an error here
      Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
      InvalidDecl = true;
      SC = VarDecl::None;
      break;
    }

    IdentifierInfo *II = Name.getAsIdentifierInfo();
    if (!II) {
      Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
       << Name.getAsString();
      return 0;
    }

    if (DC->isCXXRecord()) {
      assert(SC == VarDecl::Static && "Invalid storage class for member!");
      // This is a static data member for a C++ class.
      NewVD = CXXClassVarDecl::Create(Context, cast<CXXRecordDecl>(DC),
                                      D.getIdentifierLoc(), II,
                                      R, LastDeclarator);
    } else {
      bool ThreadSpecified = D.getDeclSpec().isThreadSpecified();
      if (S->getFnParent() == 0) {
        // C99 6.9p2: The storage-class specifiers auto and register shall not
        // appear in the declaration specifiers in an external declaration.
        if (SC == VarDecl::Auto || SC == VarDecl::Register) {
          Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
          InvalidDecl = true;
        }
      }
      NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), 
                              II, R, SC, LastDeclarator,
                              // FIXME: Move to DeclGroup...
                              D.getDeclSpec().getSourceRange().getBegin());
      NewVD->setThreadSpecified(ThreadSpecified);
    }
    // Handle attributes prior to checking for duplicates in MergeVarDecl
    ProcessDeclAttributes(NewVD, D);

    // Handle GNU asm-label extension (encoded as an attribute).
    if (Expr *E = (Expr*) D.getAsmLabel()) {
      // The parser guarantees this is a string.
      StringLiteral *SE = cast<StringLiteral>(E);  
      NewVD->addAttr(new AsmLabelAttr(std::string(SE->getStrData(),
                                                  SE->getByteLength())));
    }

    // Emit an error if an address space was applied to decl with local storage.
    // This includes arrays of objects with address space qualifiers, but not
    // automatic variables that point to other address spaces.
    // ISO/IEC TR 18037 S5.1.2
    if (NewVD->hasLocalStorage() && (NewVD->getType().getAddressSpace() != 0)) {
      Diag(D.getIdentifierLoc(), diag::err_as_qualified_auto_decl);
      InvalidDecl = true;
    }
    // Merge the decl with the existing one if appropriate. If the decl is
    // in an outer scope, it isn't the same thing.
    if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
      NewVD = MergeVarDecl(NewVD, PrevDecl);
      if (NewVD == 0) return 0;
    }
    New = NewVD;
  }
  
  // Set the lexical context. If the declarator has a C++ scope specifier, the
  // lexical context will be different from the semantic context.
  New->setLexicalDeclContext(CurContext);

  // If this has an identifier, add it to the scope stack.
  if (Name)
    PushOnScopeChains(New, S);
  // If any semantic error occurred, mark the decl as invalid.
  if (D.getInvalidType() || InvalidDecl)
    New->setInvalidDecl();
  
  return New;
}

void Sema::InitializerElementNotConstant(const Expr *Init) {
  Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
    << Init->getSourceRange();
}

bool Sema::CheckAddressConstantExpressionLValue(const Expr* Init) {
  switch (Init->getStmtClass()) {
  default:
    InitializerElementNotConstant(Init);
    return true;
  case Expr::ParenExprClass: {
    const ParenExpr* PE = cast<ParenExpr>(Init);
    return CheckAddressConstantExpressionLValue(PE->getSubExpr());
  }
  case Expr::CompoundLiteralExprClass:
    return cast<CompoundLiteralExpr>(Init)->isFileScope();
  case Expr::DeclRefExprClass: {
    const Decl *D = cast<DeclRefExpr>(Init)->getDecl();
    if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
      if (VD->hasGlobalStorage())
        return false;
      InitializerElementNotConstant(Init);
      return true;
    }
    if (isa<FunctionDecl>(D))
      return false;
    InitializerElementNotConstant(Init);
    return true;
  }
  case Expr::MemberExprClass: {
    const MemberExpr *M = cast<MemberExpr>(Init);
    if (M->isArrow())
      return CheckAddressConstantExpression(M->getBase());
    return CheckAddressConstantExpressionLValue(M->getBase());
  }
  case Expr::ArraySubscriptExprClass: {
    // FIXME: Should we pedwarn for "x[0+0]" (where x is a pointer)?
    const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(Init);
    return CheckAddressConstantExpression(ASE->getBase()) ||
           CheckArithmeticConstantExpression(ASE->getIdx());
  }
  case Expr::StringLiteralClass:
  case Expr::PredefinedExprClass:
    return false;
  case Expr::UnaryOperatorClass: {
    const UnaryOperator *Exp = cast<UnaryOperator>(Init);

    // C99 6.6p9
    if (Exp->getOpcode() == UnaryOperator::Deref)
      return CheckAddressConstantExpression(Exp->getSubExpr());

    InitializerElementNotConstant(Init);
    return true;
  }
  }
}

bool Sema::CheckAddressConstantExpression(const Expr* Init) {
  switch (Init->getStmtClass()) {
  default:
    InitializerElementNotConstant(Init);
    return true;
  case Expr::ParenExprClass:
    return CheckAddressConstantExpression(cast<ParenExpr>(Init)->getSubExpr());
  case Expr::StringLiteralClass:
  case Expr::ObjCStringLiteralClass:
    return false;
  case Expr::CallExprClass:
  case Expr::CXXOperatorCallExprClass:
    // __builtin___CFStringMakeConstantString is a valid constant l-value.
    if (cast<CallExpr>(Init)->isBuiltinCall() == 
           Builtin::BI__builtin___CFStringMakeConstantString)
      return false;
      
    InitializerElementNotConstant(Init);
    return true;
      
  case Expr::UnaryOperatorClass: {
    const UnaryOperator *Exp = cast<UnaryOperator>(Init);

    // C99 6.6p9
    if (Exp->getOpcode() == UnaryOperator::AddrOf)
      return CheckAddressConstantExpressionLValue(Exp->getSubExpr());

    if (Exp->getOpcode() == UnaryOperator::Extension)
      return CheckAddressConstantExpression(Exp->getSubExpr());
  
    InitializerElementNotConstant(Init);
    return true;
  }
  case Expr::BinaryOperatorClass: {
    // FIXME: Should we pedwarn for expressions like "a + 1 + 2"?
    const BinaryOperator *Exp = cast<BinaryOperator>(Init);

    Expr *PExp = Exp->getLHS();
    Expr *IExp = Exp->getRHS();
    if (IExp->getType()->isPointerType())
      std::swap(PExp, IExp);

    // FIXME: Should we pedwarn if IExp isn't an integer constant expression?
    return CheckAddressConstantExpression(PExp) ||
           CheckArithmeticConstantExpression(IExp);
  }
  case Expr::ImplicitCastExprClass:
  case Expr::CStyleCastExprClass: {
    const Expr* SubExpr = cast<CastExpr>(Init)->getSubExpr();
    if (Init->getStmtClass() == Expr::ImplicitCastExprClass) {
      // Check for implicit promotion
      if (SubExpr->getType()->isFunctionType() ||
          SubExpr->getType()->isArrayType())
        return CheckAddressConstantExpressionLValue(SubExpr);
    }

    // Check for pointer->pointer cast
    if (SubExpr->getType()->isPointerType())
      return CheckAddressConstantExpression(SubExpr);

    if (SubExpr->getType()->isIntegralType()) {
      // Check for the special-case of a pointer->int->pointer cast;
      // this isn't standard, but some code requires it. See
      // PR2720 for an example.
      if (const CastExpr* SubCast = dyn_cast<CastExpr>(SubExpr)) {
        if (SubCast->getSubExpr()->getType()->isPointerType()) {
          unsigned IntWidth = Context.getIntWidth(SubCast->getType());
          unsigned PointerWidth = Context.getTypeSize(Context.VoidPtrTy);
          if (IntWidth >= PointerWidth) {
            return CheckAddressConstantExpression(SubCast->getSubExpr());
          }
        }
      }
    }
    if (SubExpr->getType()->isArithmeticType()) {
      return CheckArithmeticConstantExpression(SubExpr);
    }

    InitializerElementNotConstant(Init);
    return true;
  }
  case Expr::ConditionalOperatorClass: {
    // FIXME: Should we pedwarn here?
    const ConditionalOperator *Exp = cast<ConditionalOperator>(Init);
    if (!Exp->getCond()->getType()->isArithmeticType()) {
      InitializerElementNotConstant(Init);
      return true;
    }
    if (CheckArithmeticConstantExpression(Exp->getCond()))
      return true;
    if (Exp->getLHS() &&
        CheckAddressConstantExpression(Exp->getLHS()))
      return true;
    return CheckAddressConstantExpression(Exp->getRHS());
  }
  case Expr::AddrLabelExprClass:
    return false;
  }
}

static const Expr* FindExpressionBaseAddress(const Expr* E);

static const Expr* FindExpressionBaseAddressLValue(const Expr* E) {
  switch (E->getStmtClass()) {
  default:
    return E;
  case Expr::ParenExprClass: {
    const ParenExpr* PE = cast<ParenExpr>(E);
    return FindExpressionBaseAddressLValue(PE->getSubExpr());
  }
  case Expr::MemberExprClass: {
    const MemberExpr *M = cast<MemberExpr>(E);
    if (M->isArrow())
      return FindExpressionBaseAddress(M->getBase());
    return FindExpressionBaseAddressLValue(M->getBase());
  }
  case Expr::ArraySubscriptExprClass: {
    const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(E);
    return FindExpressionBaseAddress(ASE->getBase());
  }
  case Expr::UnaryOperatorClass: {
    const UnaryOperator *Exp = cast<UnaryOperator>(E);

    if (Exp->getOpcode() == UnaryOperator::Deref)
      return FindExpressionBaseAddress(Exp->getSubExpr());

    return E;
  }
  }
}

static const Expr* FindExpressionBaseAddress(const Expr* E) {
  switch (E->getStmtClass()) {
  default:
    return E;
  case Expr::ParenExprClass: {
    const ParenExpr* PE = cast<ParenExpr>(E);
    return FindExpressionBaseAddress(PE->getSubExpr());
  }
  case Expr::UnaryOperatorClass: {
    const UnaryOperator *Exp = cast<UnaryOperator>(E);

    // C99 6.6p9
    if (Exp->getOpcode() == UnaryOperator::AddrOf)
      return FindExpressionBaseAddressLValue(Exp->getSubExpr());

    if (Exp->getOpcode() == UnaryOperator::Extension)
      return FindExpressionBaseAddress(Exp->getSubExpr());
  
    return E;
  }
  case Expr::BinaryOperatorClass: {
    const BinaryOperator *Exp = cast<BinaryOperator>(E);

    Expr *PExp = Exp->getLHS();
    Expr *IExp = Exp->getRHS();
    if (IExp->getType()->isPointerType())
      std::swap(PExp, IExp);

    return FindExpressionBaseAddress(PExp);
  }
  case Expr::ImplicitCastExprClass: {
    const Expr* SubExpr = cast<ImplicitCastExpr>(E)->getSubExpr();

    // Check for implicit promotion
    if (SubExpr->getType()->isFunctionType() ||
        SubExpr->getType()->isArrayType())
      return FindExpressionBaseAddressLValue(SubExpr);

    // Check for pointer->pointer cast
    if (SubExpr->getType()->isPointerType())
      return FindExpressionBaseAddress(SubExpr);

    // We assume that we have an arithmetic expression here;
    // if we don't, we'll figure it out later
    return 0;
  }
  case Expr::CStyleCastExprClass: {
    const Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();

    // Check for pointer->pointer cast
    if (SubExpr->getType()->isPointerType())
      return FindExpressionBaseAddress(SubExpr);

    // We assume that we have an arithmetic expression here;
    // if we don't, we'll figure it out later
    return 0;
  }
  }
}

bool Sema::CheckArithmeticConstantExpression(const Expr* Init) {  
  switch (Init->getStmtClass()) {
  default:
    InitializerElementNotConstant(Init);
    return true;
  case Expr::ParenExprClass: {
    const ParenExpr* PE = cast<ParenExpr>(Init);
    return CheckArithmeticConstantExpression(PE->getSubExpr());
  }
  case Expr::FloatingLiteralClass:
  case Expr::IntegerLiteralClass:
  case Expr::CharacterLiteralClass:
  case Expr::ImaginaryLiteralClass:
  case Expr::TypesCompatibleExprClass:
  case Expr::CXXBoolLiteralExprClass:
    return false;
  case Expr::CallExprClass: 
  case Expr::CXXOperatorCallExprClass: {
    const CallExpr *CE = cast<CallExpr>(Init);

    // Allow any constant foldable calls to builtins.
    if (CE->isBuiltinCall() && CE->isEvaluatable(Context))
      return false;
    
    InitializerElementNotConstant(Init);
    return true;
  }
  case Expr::DeclRefExprClass: {
    const Decl *D = cast<DeclRefExpr>(Init)->getDecl();
    if (isa<EnumConstantDecl>(D))
      return false;
    InitializerElementNotConstant(Init);
    return true;
  }
  case Expr::CompoundLiteralExprClass:
    // Allow "(vector type){2,4}"; normal C constraints don't allow this,
    // but vectors are allowed to be magic.
    if (Init->getType()->isVectorType())
      return false;
    InitializerElementNotConstant(Init);
    return true;
  case Expr::UnaryOperatorClass: {
    const UnaryOperator *Exp = cast<UnaryOperator>(Init);
  
    switch (Exp->getOpcode()) {
    // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
    // See C99 6.6p3.
    default:
      InitializerElementNotConstant(Init);
      return true;
    case UnaryOperator::OffsetOf:
      if (Exp->getSubExpr()->getType()->isConstantSizeType())
        return false;
      InitializerElementNotConstant(Init);
      return true;
    case UnaryOperator::Extension:
    case UnaryOperator::LNot:
    case UnaryOperator::Plus:
    case UnaryOperator::Minus:
    case UnaryOperator::Not:
      return CheckArithmeticConstantExpression(Exp->getSubExpr());
    }
  }
  case Expr::SizeOfAlignOfExprClass: {
    const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(Init);
    // Special check for void types, which are allowed as an extension
    if (Exp->getTypeOfArgument()->isVoidType())
      return false;
    // alignof always evaluates to a constant.
    // FIXME: is sizeof(int[3.0]) a constant expression?
    if (Exp->isSizeOf() && !Exp->getTypeOfArgument()->isConstantSizeType()) {
      InitializerElementNotConstant(Init);
      return true;
    }
    return false;
  }
  case Expr::BinaryOperatorClass: {
    const BinaryOperator *Exp = cast<BinaryOperator>(Init);

    if (Exp->getLHS()->getType()->isArithmeticType() &&
        Exp->getRHS()->getType()->isArithmeticType()) {
      return CheckArithmeticConstantExpression(Exp->getLHS()) ||
             CheckArithmeticConstantExpression(Exp->getRHS());
    }

    if (Exp->getLHS()->getType()->isPointerType() &&
        Exp->getRHS()->getType()->isPointerType()) {
      const Expr* LHSBase = FindExpressionBaseAddress(Exp->getLHS());
      const Expr* RHSBase = FindExpressionBaseAddress(Exp->getRHS());

      // Only allow a null (constant integer) base; we could
      // allow some additional cases if necessary, but this
      // is sufficient to cover offsetof-like constructs.
      if (!LHSBase && !RHSBase) {
        return CheckAddressConstantExpression(Exp->getLHS()) ||
               CheckAddressConstantExpression(Exp->getRHS());
      }
    }

    InitializerElementNotConstant(Init);
    return true;
  }
  case Expr::ImplicitCastExprClass:
  case Expr::CStyleCastExprClass: {
    const Expr *SubExpr = cast<CastExpr>(Init)->getSubExpr();
    if (SubExpr->getType()->isArithmeticType())
      return CheckArithmeticConstantExpression(SubExpr);

    if (SubExpr->getType()->isPointerType()) {
      const Expr* Base = FindExpressionBaseAddress(SubExpr);
      // If the pointer has a null base, this is an offsetof-like construct
      if (!Base)
        return CheckAddressConstantExpression(SubExpr);
    }

    InitializerElementNotConstant(Init);
    return true;
  }
  case Expr::ConditionalOperatorClass: {
    const ConditionalOperator *Exp = cast<ConditionalOperator>(Init);
    
    // If GNU extensions are disabled, we require all operands to be arithmetic
    // constant expressions.
    if (getLangOptions().NoExtensions) {
      return CheckArithmeticConstantExpression(Exp->getCond()) ||
          (Exp->getLHS() && CheckArithmeticConstantExpression(Exp->getLHS())) ||
             CheckArithmeticConstantExpression(Exp->getRHS());
    }

    // Otherwise, we have to emulate some of the behavior of fold here.
    // Basically GCC treats things like "4 ? 1 : somefunc()" as a constant
    // because it can constant fold things away.  To retain compatibility with
    // GCC code, we see if we can fold the condition to a constant (which we
    // should always be able to do in theory).  If so, we only require the
    // specified arm of the conditional to be a constant.  This is a horrible
    // hack, but is require by real world code that uses __builtin_constant_p.
    APValue Val;
    if (!Exp->getCond()->Evaluate(Val, Context)) {
      // If Evaluate couldn't fold it, CheckArithmeticConstantExpression
      // won't be able to either.  Use it to emit the diagnostic though.
      bool Res = CheckArithmeticConstantExpression(Exp->getCond());
      assert(Res && "Evaluate couldn't evaluate this constant?");
      return Res;
    }
    
    // Verify that the side following the condition is also a constant.
    const Expr *TrueSide = Exp->getLHS(), *FalseSide = Exp->getRHS();
    if (Val.getInt() == 0) 
      std::swap(TrueSide, FalseSide);
    
    if (TrueSide && CheckArithmeticConstantExpression(TrueSide))
      return true;
      
    // Okay, the evaluated side evaluates to a constant, so we accept this.
    // Check to see if the other side is obviously not a constant.  If so, 
    // emit a warning that this is a GNU extension.
    if (FalseSide && !FalseSide->isEvaluatable(Context))
      Diag(Init->getExprLoc(), 
           diag::ext_typecheck_expression_not_constant_but_accepted)
        << FalseSide->getSourceRange();
    return false;
  }
  }
}

bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
  Expr::EvalResult Result;

  Init = Init->IgnoreParens();

  if (Init->Evaluate(Result, Context) && !Result.HasSideEffects)
    return false;

  // Look through CXXDefaultArgExprs; they have no meaning in this context.
  if (CXXDefaultArgExpr* DAE = dyn_cast<CXXDefaultArgExpr>(Init))
    return CheckForConstantInitializer(DAE->getExpr(), DclT);

  if (CompoundLiteralExpr *e = dyn_cast<CompoundLiteralExpr>(Init))
    return CheckForConstantInitializer(e->getInitializer(), DclT);

  if (InitListExpr *Exp = dyn_cast<InitListExpr>(Init)) {
    unsigned numInits = Exp->getNumInits();
    for (unsigned i = 0; i < numInits; i++) {
      // FIXME: Need to get the type of the declaration for C++,
      // because it could be a reference?
      if (CheckForConstantInitializer(Exp->getInit(i),
                                      Exp->getInit(i)->getType()))
        return true;
    }
    return false;
  }

  // FIXME: We can probably remove some of this code below, now that 
  // Expr::Evaluate is doing the heavy lifting for scalars.
  
  if (Init->isNullPointerConstant(Context))
    return false;
  if (Init->getType()->isArithmeticType()) {
    QualType InitTy = Context.getCanonicalType(Init->getType())
                             .getUnqualifiedType();
    if (InitTy == Context.BoolTy) {
      // Special handling for pointers implicitly cast to bool;
      // (e.g. "_Bool rr = &rr;"). This is only legal at the top level.
      if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(Init)) {
        Expr* SubE = ICE->getSubExpr();
        if (SubE->getType()->isPointerType() ||
            SubE->getType()->isArrayType() ||
            SubE->getType()->isFunctionType()) {
          return CheckAddressConstantExpression(Init);
        }
      }
    } else if (InitTy->isIntegralType()) {
      Expr* SubE = 0;
      if (CastExpr* CE = dyn_cast<CastExpr>(Init))
        SubE = CE->getSubExpr();
      // Special check for pointer cast to int; we allow as an extension
      // an address constant cast to an integer if the integer
      // is of an appropriate width (this sort of code is apparently used
      // in some places).
      // FIXME: Add pedwarn?
      // FIXME: Don't allow bitfields here!  Need the FieldDecl for that.
      if (SubE && (SubE->getType()->isPointerType() ||
                   SubE->getType()->isArrayType() ||
                   SubE->getType()->isFunctionType())) {
        unsigned IntWidth = Context.getTypeSize(Init->getType());
        unsigned PointerWidth = Context.getTypeSize(Context.VoidPtrTy);
        if (IntWidth >= PointerWidth)
          return CheckAddressConstantExpression(Init);
      }
    }

    return CheckArithmeticConstantExpression(Init);
  }

  if (Init->getType()->isPointerType())
    return CheckAddressConstantExpression(Init);

  // An array type at the top level that isn't an init-list must
  // be a string literal
  if (Init->getType()->isArrayType())
    return false;

  if (Init->getType()->isFunctionType())
    return false;

  // Allow block exprs at top level.
  if (Init->getType()->isBlockPointerType())
    return false;
    
  InitializerElementNotConstant(Init);
  return true;
}

void Sema::AddInitializerToDecl(DeclTy *dcl, ExprTy *init) {
  Decl *RealDecl = static_cast<Decl *>(dcl);
  Expr *Init = static_cast<Expr *>(init);
  assert(Init && "missing initializer");
  
  // If there is no declaration, there was an error parsing it.  Just ignore
  // the initializer.
  if (RealDecl == 0) {
    delete Init;
    return;
  }
  
  VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl);
  if (!VDecl) {
    Diag(dyn_cast<ScopedDecl>(RealDecl)->getLocation(), 
         diag::err_illegal_initializer);
    RealDecl->setInvalidDecl();
    return;
  }  
  // Get the decls type and save a reference for later, since
  // CheckInitializerTypes may change it.
  QualType DclT = VDecl->getType(), SavT = DclT;
  if (VDecl->isBlockVarDecl()) {
    VarDecl::StorageClass SC = VDecl->getStorageClass();
    if (SC == VarDecl::Extern) { // C99 6.7.8p5
      Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
      VDecl->setInvalidDecl();
    } else if (!VDecl->isInvalidDecl()) {
      if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
                                VDecl->getDeclName()))
        VDecl->setInvalidDecl();
      
      // C++ 3.6.2p2, allow dynamic initialization of static initializers.
      if (!getLangOptions().CPlusPlus) {
        if (SC == VarDecl::Static) // C99 6.7.8p4.
          CheckForConstantInitializer(Init, DclT);
      }
    }
  } else if (VDecl->isFileVarDecl()) {
    if (VDecl->getStorageClass() == VarDecl::Extern)
      Diag(VDecl->getLocation(), diag::warn_extern_init);
    if (!VDecl->isInvalidDecl())
      if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
                                VDecl->getDeclName()))
        VDecl->setInvalidDecl();
    
    // C++ 3.6.2p2, allow dynamic initialization of static initializers.
    if (!getLangOptions().CPlusPlus) {
      // C99 6.7.8p4. All file scoped initializers need to be constant.
      CheckForConstantInitializer(Init, DclT);
    }
  }
  // If the type changed, it means we had an incomplete type that was
  // completed by the initializer. For example: 
  //   int ary[] = { 1, 3, 5 };
  // "ary" transitions from a VariableArrayType to a ConstantArrayType.
  if (!VDecl->isInvalidDecl() && (DclT != SavT)) {
    VDecl->setType(DclT);
    Init->setType(DclT);
  }
    
  // Attach the initializer to the decl.
  VDecl->setInit(Init);
  return;
}

void Sema::ActOnUninitializedDecl(DeclTy *dcl) {
  Decl *RealDecl = static_cast<Decl *>(dcl);

  // If there is no declaration, there was an error parsing it. Just ignore it.
  if (RealDecl == 0)
    return;

  if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
    QualType Type = Var->getType();
    // C++ [dcl.init.ref]p3:
    //   The initializer can be omitted for a reference only in a
    //   parameter declaration (8.3.5), in the declaration of a
    //   function return type, in the declaration of a class member
    //   within its class declaration (9.2), and where the extern
    //   specifier is explicitly used.
    if (Type->isReferenceType() && Var->getStorageClass() != VarDecl::Extern) {
      Diag(Var->getLocation(), diag::err_reference_var_requires_init)
        << Var->getDeclName()
        << SourceRange(Var->getLocation(), Var->getLocation());
      Var->setInvalidDecl();
      return;
    }

    // C++ [dcl.init]p9:
    //
    //   If no initializer is specified for an object, and the object
    //   is of (possibly cv-qualified) non-POD class type (or array
    //   thereof), the object shall be default-initialized; if the
    //   object is of const-qualified type, the underlying class type
    //   shall have a user-declared default constructor.
    if (getLangOptions().CPlusPlus) {
      QualType InitType = Type;
      if (const ArrayType *Array = Context.getAsArrayType(Type))
        InitType = Array->getElementType();
      if (InitType->isRecordType()) {
        const CXXConstructorDecl *Constructor
          = PerformInitializationByConstructor(InitType, 0, 0, 
                                               Var->getLocation(),
                                               SourceRange(Var->getLocation(),
                                                           Var->getLocation()),
                                               Var->getDeclName(),
                                               IK_Default);
        if (!Constructor)
          Var->setInvalidDecl();
      }
    }

#if 0
    // FIXME: Temporarily disabled because we are not properly parsing
    // linkage specifications on declarations, e.g., 
    //
    //   extern "C" const CGPoint CGPointerZero;
    //
    // C++ [dcl.init]p9:
    //
    //     If no initializer is specified for an object, and the
    //     object is of (possibly cv-qualified) non-POD class type (or
    //     array thereof), the object shall be default-initialized; if
    //     the object is of const-qualified type, the underlying class
    //     type shall have a user-declared default
    //     constructor. Otherwise, if no initializer is specified for
    //     an object, the object and its subobjects, if any, have an
    //     indeterminate initial value; if the object or any of its
    //     subobjects are of const-qualified type, the program is
    //     ill-formed.
    //
    // This isn't technically an error in C, so we don't diagnose it.
    //
    // FIXME: Actually perform the POD/user-defined default
    // constructor check.
    if (getLangOptions().CPlusPlus &&
        Context.getCanonicalType(Type).isConstQualified() &&
        Var->getStorageClass() != VarDecl::Extern)
      Diag(Var->getLocation(),  diag::err_const_var_requires_init)
        << Var->getName()
        << SourceRange(Var->getLocation(), Var->getLocation());
#endif
  }
}

/// The declarators are chained together backwards, reverse the list.
Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) {
  // Often we have single declarators, handle them quickly.
  Decl *GroupDecl = static_cast<Decl*>(group);
  if (GroupDecl == 0)
    return 0;
  
  ScopedDecl *Group = dyn_cast<ScopedDecl>(GroupDecl);
  ScopedDecl *NewGroup = 0;
  if (Group->getNextDeclarator() == 0) 
    NewGroup = Group;
  else { // reverse the list.
    while (Group) {
      ScopedDecl *Next = Group->getNextDeclarator();
      Group->setNextDeclarator(NewGroup);
      NewGroup = Group;
      Group = Next;
    }
  }
  // Perform semantic analysis that depends on having fully processed both
  // the declarator and initializer.
  for (ScopedDecl *ID = NewGroup; ID; ID = ID->getNextDeclarator()) {
    VarDecl *IDecl = dyn_cast<VarDecl>(ID);
    if (!IDecl)
      continue;
    QualType T = IDecl->getType();
    
    if (T->isVariableArrayType()) {
      const VariableArrayType *VAT = 
        cast<VariableArrayType>(T.getUnqualifiedType());
      
      // FIXME: This won't give the correct result for 
      // int a[10][n];      
      SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange();
      if (IDecl->isFileVarDecl()) {
        Diag(IDecl->getLocation(), diag::err_vla_decl_in_file_scope) <<
          SizeRange;
          
        IDecl->setInvalidDecl();
      } else {
        // C99 6.7.5.2p2: If an identifier is declared to be an object with 
        // static storage duration, it shall not have a variable length array.
        if (IDecl->getStorageClass() == VarDecl::Static) {
          Diag(IDecl->getLocation(), diag::err_vla_decl_has_static_storage)
            << SizeRange;
          IDecl->setInvalidDecl();
        } else if (IDecl->getStorageClass() == VarDecl::Extern) {
          Diag(IDecl->getLocation(), diag::err_vla_decl_has_extern_linkage)
            << SizeRange;
          IDecl->setInvalidDecl();
        }
      }
    } else if (T->isVariablyModifiedType()) {
      if (IDecl->isFileVarDecl()) {
        Diag(IDecl->getLocation(), diag::err_vm_decl_in_file_scope);
        IDecl->setInvalidDecl();
      } else {
        if (IDecl->getStorageClass() == VarDecl::Extern) {
          Diag(IDecl->getLocation(), diag::err_vm_decl_has_extern_linkage);
          IDecl->setInvalidDecl();
        }
      }
    }
     
    // Block scope. C99 6.7p7: If an identifier for an object is declared with
    // no linkage (C99 6.2.2p6), the type for the object shall be complete...
    if (IDecl->isBlockVarDecl() && 
        IDecl->getStorageClass() != VarDecl::Extern) {
      if (T->isIncompleteType() && !IDecl->isInvalidDecl()) {
        Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type)<<T;
        IDecl->setInvalidDecl();
      }
    }
    // File scope. C99 6.9.2p2: A declaration of an identifier for and 
    // object that has file scope without an initializer, and without a
    // storage-class specifier or with the storage-class specifier "static",
    // constitutes a tentative definition. Note: A tentative definition with
    // external linkage is valid (C99 6.2.2p5).
    if (isTentativeDefinition(IDecl)) {
      if (T->isIncompleteArrayType()) {
        // C99 6.9.2 (p2, p5): Implicit initialization causes an incomplete
        // array to be completed. Don't issue a diagnostic.
      } else if (T->isIncompleteType() && !IDecl->isInvalidDecl()) {
        // C99 6.9.2p3: If the declaration of an identifier for an object is
        // a tentative definition and has internal linkage (C99 6.2.2p3), the  
        // declared type shall not be an incomplete type.
        Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type)<<T;
        IDecl->setInvalidDecl();
      }
    }
    if (IDecl->isFileVarDecl())
      CheckForFileScopedRedefinitions(S, IDecl);
  }
  return NewGroup;
}

/// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator()
/// to introduce parameters into function prototype scope.
Sema::DeclTy *
Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
  // FIXME: disallow CXXScopeSpec for param declarators.
  const DeclSpec &DS = D.getDeclSpec();
  
  // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
  VarDecl::StorageClass StorageClass = VarDecl::None;
  if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
    StorageClass = VarDecl::Register;
  } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
    Diag(DS.getStorageClassSpecLoc(),
         diag::err_invalid_storage_class_in_func_decl);
    D.getMutableDeclSpec().ClearStorageClassSpecs();
  }
  if (DS.isThreadSpecified()) {
    Diag(DS.getThreadSpecLoc(),
         diag::err_invalid_storage_class_in_func_decl);
    D.getMutableDeclSpec().ClearStorageClassSpecs();
  }
  
  // Check that there are no default arguments inside the type of this
  // parameter (C++ only).
  if (getLangOptions().CPlusPlus)
    CheckExtraCXXDefaultArguments(D);
 
  // In this context, we *do not* check D.getInvalidType(). If the declarator
  // type was invalid, GetTypeForDeclarator() still returns a "valid" type,
  // though it will not reflect the user specified type.
  QualType parmDeclType = GetTypeForDeclarator(D, S);
  
  assert(!parmDeclType.isNull() && "GetTypeForDeclarator() returned null type");

  // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
  // Can this happen for params?  We already checked that they don't conflict
  // among each other.  Here they can only shadow globals, which is ok.
  IdentifierInfo *II = D.getIdentifier();
  if (Decl *PrevDecl = LookupDecl(II, Decl::IDNS_Ordinary, S)) {
    if (isTemplateParameterDecl(PrevDecl)) {
      // Maybe we will complain about the shadowed template parameter.
      DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
      // Just pretend that we didn't see the previous declaration.
      PrevDecl = 0;
    } else if (S->isDeclScope(PrevDecl)) {
      Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II;

      // Recover by removing the name
      II = 0;
      D.SetIdentifier(0, D.getIdentifierLoc());
    }
  }

  // Perform the default function/array conversion (C99 6.7.5.3p[7,8]).
  // Doing the promotion here has a win and a loss. The win is the type for
  // both Decl's and DeclRefExpr's will match (a convenient invariant for the
  // code generator). The loss is the orginal type isn't preserved. For example:
  //
  // void func(int parmvardecl[5]) { // convert "int [5]" to "int *"
  //    int blockvardecl[5];
  //    sizeof(parmvardecl);  // size == 4
  //    sizeof(blockvardecl); // size == 20
  // }
  //
  // For expressions, all implicit conversions are captured using the
  // ImplicitCastExpr AST node (we have no such mechanism for Decl's).
  //
  // FIXME: If a source translation tool needs to see the original type, then
  // we need to consider storing both types (in ParmVarDecl)...
  // 
  if (parmDeclType->isArrayType()) {
    // int x[restrict 4] ->  int *restrict
    parmDeclType = Context.getArrayDecayedType(parmDeclType);
  } else if (parmDeclType->isFunctionType())
    parmDeclType = Context.getPointerType(parmDeclType);
  
  ParmVarDecl *New = ParmVarDecl::Create(Context, CurContext, 
                                         D.getIdentifierLoc(), II,
                                         parmDeclType, StorageClass, 
                                         0, 0);
  
  if (D.getInvalidType())
    New->setInvalidDecl();
    
  if (II)
    PushOnScopeChains(New, S);

  ProcessDeclAttributes(New, D);
  return New;

}

Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
  assert(getCurFunctionDecl() == 0 && "Function parsing confused");
  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
         "Not a function declarator!");
  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;

  // Verify 6.9.1p6: 'every identifier in the identifier list shall be declared'
  // for a K&R function.
  if (!FTI.hasPrototype) {
    for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
      if (FTI.ArgInfo[i].Param == 0) {
        Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared)
          << FTI.ArgInfo[i].Ident;
        // Implicitly declare the argument as type 'int' for lack of a better
        // type.
        DeclSpec DS;
        const char* PrevSpec; // unused
        DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc, 
                           PrevSpec);
        Declarator ParamD(DS, Declarator::KNRTypeListContext);
        ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc);
        FTI.ArgInfo[i].Param = ActOnParamDeclarator(FnBodyScope, ParamD);
      }
    }
  } else {
    // FIXME: Diagnose arguments without names in C. 
  }
  
  Scope *GlobalScope = FnBodyScope->getParent();

  return ActOnStartOfFunctionDef(FnBodyScope,
                                 ActOnDeclarator(GlobalScope, D, 0));
}

Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) {
  Decl *decl = static_cast<Decl*>(D);
  FunctionDecl *FD = cast<FunctionDecl>(decl);

  // See if this is a redefinition.
  const FunctionDecl *Definition;
  if (FD->getBody(Definition)) {
    Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
    Diag(Definition->getLocation(), diag::note_previous_definition);
  }

  PushDeclContext(FD);
    
  // Check the validity of our function parameters
  CheckParmsForFunctionDef(FD);

  // Introduce our parameters into the function scope
  for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
    ParmVarDecl *Param = FD->getParamDecl(p);
    // If this has an identifier, add it to the scope stack.
    if (Param->getIdentifier())
      PushOnScopeChains(Param, FnBodyScope);
  }

  return FD;
}

Sema::DeclTy *Sema::ActOnFinishFunctionBody(DeclTy *D, StmtTy *Body) {
  Decl *dcl = static_cast<Decl *>(D);
  if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(dcl)) {
    FD->setBody((Stmt*)Body);
    assert(FD == getCurFunctionDecl() && "Function parsing confused");
  } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
    MD->setBody((Stmt*)Body);
  } else
    return 0;
  PopDeclContext();
  // Verify and clean out per-function state.
  
  // Check goto/label use.
  for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
       I = LabelMap.begin(), E = LabelMap.end(); I != E; ++I) {
    // Verify that we have no forward references left.  If so, there was a goto
    // or address of a label taken, but no definition of it.  Label fwd
    // definitions are indicated with a null substmt.
    if (I->second->getSubStmt() == 0) {
      LabelStmt *L = I->second;
      // Emit error.
      Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName();
      
      // At this point, we have gotos that use the bogus label.  Stitch it into
      // the function body so that they aren't leaked and that the AST is well
      // formed.
      if (Body) {
        L->setSubStmt(new NullStmt(L->getIdentLoc()));
        cast<CompoundStmt>((Stmt*)Body)->push_back(L);
      } else {
        // The whole function wasn't parsed correctly, just delete this.
        delete L;
      }
    }
  }
  LabelMap.clear();
  
  return D;
}

/// ImplicitlyDefineFunction - An undeclared identifier was used in a function
/// call, forming a call to an implicitly defined function (per C99 6.5.1p2).
ScopedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, 
                                           IdentifierInfo &II, Scope *S) {
  // Extension in C99.  Legal in C90, but warn about it.
  if (getLangOptions().C99)
    Diag(Loc, diag::ext_implicit_function_decl) << &II;
  else
    Diag(Loc, diag::warn_implicit_function_decl) << &II;
  
  // FIXME: handle stuff like:
  // void foo() { extern float X(); }
  // void bar() { X(); }  <-- implicit decl for X in another scope.

  // Set a Declarator for the implicit definition: int foo();
  const char *Dummy;
  DeclSpec DS;
  bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy);
  Error = Error; // Silence warning.
  assert(!Error && "Error setting up implicit decl!");
  Declarator D(DS, Declarator::BlockContext);
  D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, 0, Loc));
  D.SetIdentifier(&II, Loc);
  
  // Insert this function into translation-unit scope.

  DeclContext *PrevDC = CurContext;
  CurContext = Context.getTranslationUnitDecl();
 
  FunctionDecl *FD = 
    dyn_cast<FunctionDecl>(static_cast<Decl*>(ActOnDeclarator(TUScope, D, 0)));
  FD->setImplicit();

  CurContext = PrevDC;

  return FD;
}


TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
                                    ScopedDecl *LastDeclarator) {
  assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
  assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
  
  // Scope manipulation handled by caller.
  TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext,
                                           D.getIdentifierLoc(),
                                           D.getIdentifier(), 
                                           T, LastDeclarator);
  if (D.getInvalidType())
    NewTD->setInvalidDecl();
  return NewTD;
}

/// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'.  In the
/// former case, Name will be non-null.  In the later case, Name will be null.
/// TagType indicates what kind of tag this is. TK indicates whether this is a
/// reference/declaration/definition of a tag.
Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
                             SourceLocation KWLoc, const CXXScopeSpec &SS,
                             IdentifierInfo *Name, SourceLocation NameLoc,
                             AttributeList *Attr) {
  // If this is a use of an existing tag, it must have a name.
  assert((Name != 0 || TK == TK_Definition) &&
         "Nameless record must be a definition!");
  
  TagDecl::TagKind Kind;
  switch (TagType) {
  default: assert(0 && "Unknown tag type!");
  case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break;
  case DeclSpec::TST_union:  Kind = TagDecl::TK_union; break;
  case DeclSpec::TST_class:  Kind = TagDecl::TK_class; break;
  case DeclSpec::TST_enum:   Kind = TagDecl::TK_enum; break;
  }
  
  // Two code paths: a new one for structs/unions/classes where we create
  //   separate decls for forward declarations, and an old (eventually to
  //   be removed) code path for enums.
  if (Kind != TagDecl::TK_enum)
    return ActOnTagStruct(S, Kind, TK, KWLoc, SS, Name, NameLoc, Attr);
  
  DeclContext *DC = CurContext;
  ScopedDecl *PrevDecl = 0;

  if (Name && SS.isNotEmpty()) {
    // We have a nested-name tag ('struct foo::bar').

    // Check for invalid 'foo::'.
    if (SS.isInvalid()) {
      Name = 0;
      goto CreateNewDecl;
    }

    DC = static_cast<DeclContext*>(SS.getScopeRep());
    // Look-up name inside 'foo::'.
    PrevDecl = dyn_cast_or_null<TagDecl>(LookupDecl(Name, Decl::IDNS_Tag,S,DC));

    // A tag 'foo::bar' must already exist.
    if (PrevDecl == 0) {
      Diag(NameLoc, diag::err_not_tag_in_scope) << Name << SS.getRange();
      Name = 0;
      goto CreateNewDecl;
    }
  } else {
    // If this is a named struct, check to see if there was a previous forward
    // declaration or definition.
    // Use ScopedDecl instead of TagDecl, because a NamespaceDecl may come up.
    PrevDecl = dyn_cast_or_null<ScopedDecl>(LookupDecl(Name, Decl::IDNS_Tag,S));
  }

  if (PrevDecl && isTemplateParameterDecl(PrevDecl)) {
    // Maybe we will complain about the shadowed template parameter.
    DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
    // Just pretend that we didn't see the previous declaration.
    PrevDecl = 0;
  }

  if (PrevDecl) {    
    assert((isa<TagDecl>(PrevDecl) || isa<NamespaceDecl>(PrevDecl)) &&
            "unexpected Decl type");
    if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
      // If this is a use of a previous tag, or if the tag is already declared
      // in the same scope (so that the definition/declaration completes or
      // rementions the tag), reuse the decl.
      if (TK == TK_Reference || isDeclInScope(PrevDecl, DC, S)) {
        // Make sure that this wasn't declared as an enum and now used as a
        // struct or something similar.
        if (PrevTagDecl->getTagKind() != Kind) {
          Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
          Diag(PrevDecl->getLocation(), diag::note_previous_use);
          // Recover by making this an anonymous redefinition.
          Name = 0;
          PrevDecl = 0;
        } else {
          // If this is a use or a forward declaration, we're good.
          if (TK != TK_Definition)
            return PrevDecl;

          // Diagnose attempts to redefine a tag.
          if (PrevTagDecl->isDefinition()) {
            Diag(NameLoc, diag::err_redefinition) << Name;
            Diag(PrevDecl->getLocation(), diag::note_previous_definition);
            // If this is a redefinition, recover by making this struct be
            // anonymous, which will make any later references get the previous
            // definition.
            Name = 0;
          } else {
            // Okay, this is definition of a previously declared or referenced
            // tag. Move the location of the decl to be the definition site.
            PrevDecl->setLocation(NameLoc);
            return PrevDecl;
          }
        }
      }
      // If we get here, this is a definition of a new struct type in a nested
      // scope, e.g. "struct foo; void bar() { struct foo; }", just create a new
      // type.
    } else {
      // PrevDecl is a namespace.
      if (isDeclInScope(PrevDecl, DC, S)) {
        // The tag name clashes with a namespace name, issue an error and
        // recover by making this tag be anonymous.
        Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
        Diag(PrevDecl->getLocation(), diag::note_previous_definition);
        Name = 0;
      }
    }
  }

  CreateNewDecl:
  
  // If there is an identifier, use the location of the identifier as the
  // location of the decl, otherwise use the location of the struct/union
  // keyword.
  SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc;
  
  // Otherwise, if this is the first time we've seen this tag, create the decl.
  TagDecl *New;
  if (Kind == TagDecl::TK_enum) {
    // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
    // enum X { A, B, C } D;    D should chain to X.
    New = EnumDecl::Create(Context, DC, Loc, Name, 0);
    // If this is an undefined enum, warn.
    if (TK != TK_Definition) Diag(Loc, diag::ext_forward_ref_enum);
  } else {
    // struct/union/class

    // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
    // struct X { int A; } D;    D should chain to X.
    if (getLangOptions().CPlusPlus)
      // FIXME: Look for a way to use RecordDecl for simple structs.
      New = CXXRecordDecl::Create(Context, Kind, DC, Loc, Name);
    else
      New = RecordDecl::Create(Context, Kind, DC, Loc, Name);
  }
  
  // If this has an identifier, add it to the scope stack.
  if (Name) {
    // The scope passed in may not be a decl scope.  Zip up the scope tree until
    // we find one that is.
    while ((S->getFlags() & Scope::DeclScope) == 0)
      S = S->getParent();
    
    // Add it to the decl chain.
    PushOnScopeChains(New, S);
  }
  
  if (Attr)
    ProcessDeclAttributeList(New, Attr);

  // Set the lexical context. If the tag has a C++ scope specifier, the
  // lexical context will be different from the semantic context.
  New->setLexicalDeclContext(CurContext);

  return New;
}

/// ActOnTagStruct - New "ActOnTag" logic for structs/unions/classes.  Unlike
///  the logic for enums, we create separate decls for forward declarations.
///  This is called by ActOnTag, but eventually will replace its logic.
Sema::DeclTy *Sema::ActOnTagStruct(Scope *S, TagDecl::TagKind Kind, TagKind TK,
                             SourceLocation KWLoc, const CXXScopeSpec &SS,
                             IdentifierInfo *Name, SourceLocation NameLoc,
                             AttributeList *Attr) {
  DeclContext *DC = CurContext;
  ScopedDecl *PrevDecl = 0;

  if (Name && SS.isNotEmpty()) {
    // We have a nested-name tag ('struct foo::bar').

    // Check for invalid 'foo::'.
    if (SS.isInvalid()) {
      Name = 0;
      goto CreateNewDecl;
    }

    DC = static_cast<DeclContext*>(SS.getScopeRep());
    // Look-up name inside 'foo::'.
    PrevDecl = dyn_cast_or_null<TagDecl>(LookupDecl(Name, Decl::IDNS_Tag,S,DC));

    // A tag 'foo::bar' must already exist.
    if (PrevDecl == 0) {
      Diag(NameLoc, diag::err_not_tag_in_scope) << Name << SS.getRange();
      Name = 0;
      goto CreateNewDecl;
    }
  } else {
    // If this is a named struct, check to see if there was a previous forward
    // declaration or definition.
    // Use ScopedDecl instead of TagDecl, because a NamespaceDecl may come up.
    PrevDecl = dyn_cast_or_null<ScopedDecl>(LookupDecl(Name, Decl::IDNS_Tag,S));
  }
  
  if (PrevDecl && isTemplateParameterDecl(PrevDecl)) {
    // Maybe we will complain about the shadowed template parameter.
    DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
    // Just pretend that we didn't see the previous declaration.
    PrevDecl = 0;
  }

  if (PrevDecl) {    
    assert((isa<TagDecl>(PrevDecl) || isa<NamespaceDecl>(PrevDecl)) &&
           "unexpected Decl type");
    
    if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
      // If this is a use of a previous tag, or if the tag is already declared
      // in the same scope (so that the definition/declaration completes or
      // rementions the tag), reuse the decl.
      if (TK == TK_Reference || isDeclInScope(PrevDecl, DC, S)) {
        // Make sure that this wasn't declared as an enum and now used as a
        // struct or something similar.
        if (PrevTagDecl->getTagKind() != Kind) {
          Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
          Diag(PrevDecl->getLocation(), diag::note_previous_use);
          // Recover by making this an anonymous redefinition.
          Name = 0;
          PrevDecl = 0;
        } else {
          // If this is a use, return the original decl.
          
          // FIXME: In the future, return a variant or some other clue
          //  for the consumer of this Decl to know it doesn't own it.
          //  For our current ASTs this shouldn't be a problem, but will
          //  need to be changed with DeclGroups.
          if (TK == TK_Reference)
            return PrevDecl;
          
          // The new decl is a definition?
          if (TK == TK_Definition) {
            // Diagnose attempts to redefine a tag.
            if (RecordDecl* DefRecord =
                cast<RecordDecl>(PrevTagDecl)->getDefinition(Context)) {
              Diag(NameLoc, diag::err_redefinition) << Name;
              Diag(DefRecord->getLocation(), diag::note_previous_definition);
              // If this is a redefinition, recover by making this struct be
              // anonymous, which will make any later references get the previous
              // definition.
              Name = 0;
              PrevDecl = 0;
            }
            // Okay, this is definition of a previously declared or referenced
            // tag.  We're going to create a new Decl.
          }
        }
        // If we get here we have (another) forward declaration.  Just create
        // a new decl.        
      }
      else {
        // If we get here, this is a definition of a new struct type in a nested
        // scope, e.g. "struct foo; void bar() { struct foo; }", just create a 
        // new decl/type.  We set PrevDecl to NULL so that the Records
        // have distinct types.
        PrevDecl = 0;
      }
    } else {
      // PrevDecl is a namespace.
      if (isDeclInScope(PrevDecl, DC, S)) {
        // The tag name clashes with a namespace name, issue an error and
        // recover by making this tag be anonymous.
        Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
        Diag(PrevDecl->getLocation(), diag::note_previous_definition);
        Name = 0;
      }
    }
  }

  CreateNewDecl:

  // If there is an identifier, use the location of the identifier as the
  // location of the decl, otherwise use the location of the struct/union
  // keyword.
  SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc;
  
  // Otherwise, if this is the first time we've seen this tag, create the decl.
  TagDecl *New;
    
  // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
  // struct X { int A; } D;    D should chain to X.
  if (getLangOptions().CPlusPlus)
    // FIXME: Look for a way to use RecordDecl for simple structs.
    New = CXXRecordDecl::Create(Context, Kind, DC, Loc, Name,
                                dyn_cast_or_null<CXXRecordDecl>(PrevDecl));
  else
    New = RecordDecl::Create(Context, Kind, DC, Loc, Name,
                             dyn_cast_or_null<RecordDecl>(PrevDecl));
  
  // If this has an identifier, add it to the scope stack.
  if ((TK == TK_Definition || !PrevDecl) && Name) {
    // The scope passed in may not be a decl scope.  Zip up the scope tree until
    // we find one that is.
    while ((S->getFlags() & Scope::DeclScope) == 0)
      S = S->getParent();
    
    // Add it to the decl chain.
    PushOnScopeChains(New, S);
  }

  // Handle #pragma pack: if the #pragma pack stack has non-default
  // alignment, make up a packed attribute for this decl. These
  // attributes are checked when the ASTContext lays out the
  // structure.
  //
  // It is important for implementing the correct semantics that this
  // happen here (in act on tag decl). The #pragma pack stack is
  // maintained as a result of parser callbacks which can occur at
  // many points during the parsing of a struct declaration (because
  // the #pragma tokens are effectively skipped over during the
  // parsing of the struct).
  if (unsigned Alignment = PackContext.getAlignment())
    New->addAttr(new PackedAttr(Alignment * 8));
  
  if (Attr)
    ProcessDeclAttributeList(New, Attr);

  // Set the lexical context. If the tag has a C++ scope specifier, the
  // lexical context will be different from the semantic context.
  New->setLexicalDeclContext(CurContext);

  return New;
}


/// Collect the instance variables declared in an Objective-C object.  Used in
/// the creation of structures from objects using the @defs directive.
static void CollectIvars(ObjCInterfaceDecl *Class, ASTContext& Ctx,
                         llvm::SmallVectorImpl<Sema::DeclTy*> &ivars) {
  if (Class->getSuperClass())
    CollectIvars(Class->getSuperClass(), Ctx, ivars);
  
  // For each ivar, create a fresh ObjCAtDefsFieldDecl.
  for (ObjCInterfaceDecl::ivar_iterator
        I=Class->ivar_begin(), E=Class->ivar_end(); I!=E; ++I) {
    
    ObjCIvarDecl* ID = *I;
    ivars.push_back(ObjCAtDefsFieldDecl::Create(Ctx, ID->getLocation(),
                                                ID->getIdentifier(),
                                                ID->getType(),
                                                ID->getBitWidth()));
  }
}

/// Called whenever @defs(ClassName) is encountered in the source.  Inserts the
/// instance variables of ClassName into Decls.
void Sema::ActOnDefs(Scope *S, SourceLocation DeclStart, 
                     IdentifierInfo *ClassName,
                     llvm::SmallVectorImpl<DeclTy*> &Decls) {
  // Check that ClassName is a valid class
  ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName);
  if (!Class) {
    Diag(DeclStart, diag::err_undef_interface) << ClassName;
    return;
  }
  // Collect the instance variables
  CollectIvars(Class, Context, Decls);
}

/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array
/// types into constant array types in certain situations which would otherwise
/// be errors (for GCC compatibility).
static QualType TryToFixInvalidVariablyModifiedType(QualType T,
                                                    ASTContext &Context) {
  // This method tries to turn a variable array into a constant
  // array even when the size isn't an ICE.  This is necessary
  // for compatibility with code that depends on gcc's buggy
  // constant expression folding, like struct {char x[(int)(char*)2];}
  const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
  if (!VLATy) return QualType();
  
  APValue Result;
  if (!VLATy->getSizeExpr() ||
      !VLATy->getSizeExpr()->Evaluate(Result, Context))
    return QualType();
    
  assert(Result.isInt() && "Size expressions must be integers!");
  llvm::APSInt &Res = Result.getInt();
  if (Res > llvm::APSInt(Res.getBitWidth(), Res.isUnsigned()))
    return Context.getConstantArrayType(VLATy->getElementType(),
                                        Res, ArrayType::Normal, 0);
  return QualType();
}

bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, 
                          QualType FieldTy, const Expr *BitWidth)
{
  // FIXME: 6.7.2.1p4 - verify the field type.
  
  llvm::APSInt Value;
  if (VerifyIntegerConstantExpression(BitWidth, &Value))
    return true;

  if (Value.isNegative()) {
    Diag(FieldLoc, diag::err_bitfield_has_negative_width) << FieldName;
    return true;
  }

  uint64_t TypeSize = Context.getTypeSize(FieldTy);
  // FIXME: We won't need the 0 size once we check that the field type is valid.
  if (TypeSize && Value.getZExtValue() > TypeSize) {
    Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size) << 
         FieldName << (unsigned)TypeSize;
    return true;
  }

  return false;
}

/// ActOnField - Each field of a struct/union/class is passed into this in order
/// to create a FieldDecl object for it.
Sema::DeclTy *Sema::ActOnField(Scope *S,
                               SourceLocation DeclStart, 
                               Declarator &D, ExprTy *BitfieldWidth) {
  IdentifierInfo *II = D.getIdentifier();
  Expr *BitWidth = (Expr*)BitfieldWidth;
  SourceLocation Loc = DeclStart;
  if (II) Loc = D.getIdentifierLoc();
  
  // FIXME: Unnamed fields can be handled in various different ways, for
  // example, unnamed unions inject all members into the struct namespace!

  QualType T = GetTypeForDeclarator(D, S);
  assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
  bool InvalidDecl = false;
  
  // C99 6.7.2.1p8: A member of a structure or union may have any type other
  // than a variably modified type.
  if (T->isVariablyModifiedType()) {
    QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context);
    if (!FixedTy.isNull()) {
      Diag(Loc, diag::warn_illegal_constant_array_size);
      T = FixedTy;
    } else {
      Diag(Loc, diag::err_typecheck_field_variable_size);
      T = Context.IntTy;
      InvalidDecl = true;
    }
  }
  
  if (BitWidth) {
    if (VerifyBitField(Loc, II, T, BitWidth))
      InvalidDecl = true;
  } else {
    // Not a bitfield.

    // validate II.
    
  }
  
  // FIXME: Chain fielddecls together.
  FieldDecl *NewFD;

  if (getLangOptions().CPlusPlus) {
    // FIXME: Replace CXXFieldDecls with FieldDecls for simple structs.
    NewFD = CXXFieldDecl::Create(Context, cast<CXXRecordDecl>(CurContext),
                                 Loc, II, T,
                                 D.getDeclSpec().getStorageClassSpec() ==
                                   DeclSpec::SCS_mutable, BitWidth);
    if (II)
      PushOnScopeChains(NewFD, S);
  }
  else
    NewFD = FieldDecl::Create(Context, Loc, II, T, BitWidth);
  
  ProcessDeclAttributes(NewFD, D);

  if (D.getInvalidType() || InvalidDecl)
    NewFD->setInvalidDecl();
  return NewFD;
}

/// TranslateIvarVisibility - Translate visibility from a token ID to an 
///  AST enum value.
static ObjCIvarDecl::AccessControl
TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {
  switch (ivarVisibility) {
  default: assert(0 && "Unknown visitibility kind");
  case tok::objc_private: return ObjCIvarDecl::Private;
  case tok::objc_public: return ObjCIvarDecl::Public;
  case tok::objc_protected: return ObjCIvarDecl::Protected;
  case tok::objc_package: return ObjCIvarDecl::Package;
  }
}

/// ActOnIvar - Each ivar field of an objective-c class is passed into this 
/// in order to create an IvarDecl object for it.
Sema::DeclTy *Sema::ActOnIvar(Scope *S,
                              SourceLocation DeclStart, 
                              Declarator &D, ExprTy *BitfieldWidth,
                              tok::ObjCKeywordKind Visibility) {
  IdentifierInfo *II = D.getIdentifier();
  Expr *BitWidth = (Expr*)BitfieldWidth;
  SourceLocation Loc = DeclStart;
  if (II) Loc = D.getIdentifierLoc();
  
  // FIXME: Unnamed fields can be handled in various different ways, for
  // example, unnamed unions inject all members into the struct namespace!
  
  QualType T = GetTypeForDeclarator(D, S);
  assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
  bool InvalidDecl = false;
  
  if (BitWidth) {
    // TODO: Validate.
    //printf("WARNING: BITFIELDS IGNORED!\n");
    
    // 6.7.2.1p3
    // 6.7.2.1p4
    
  } else {
    // Not a bitfield.
    
    // validate II.
    
  }
  
  // C99 6.7.2.1p8: A member of a structure or union may have any type other
  // than a variably modified type.
  if (T->isVariablyModifiedType()) {
    Diag(Loc, diag::err_typecheck_ivar_variable_size);
    InvalidDecl = true;
  }
  
  // Get the visibility (access control) for this ivar.
  ObjCIvarDecl::AccessControl ac = 
    Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility)
                                        : ObjCIvarDecl::None;

  // Construct the decl.
  ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, Loc, II, T, ac,                                             
                                             (Expr *)BitfieldWidth);
  
  // Process attributes attached to the ivar.
  ProcessDeclAttributes(NewID, D);
  
  if (D.getInvalidType() || InvalidDecl)
    NewID->setInvalidDecl();

  return NewID;
}

void Sema::ActOnFields(Scope* S,
                       SourceLocation RecLoc, DeclTy *RecDecl,
                       DeclTy **Fields, unsigned NumFields,
                       SourceLocation LBrac, SourceLocation RBrac,
                       AttributeList *Attr) {
  Decl *EnclosingDecl = static_cast<Decl*>(RecDecl);
  assert(EnclosingDecl && "missing record or interface decl");
  RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
  
  if (Record)
    if (RecordDecl* DefRecord = Record->getDefinition(Context)) {
      // Diagnose code like:
      //     struct S { struct S {} X; };
      // We discover this when we complete the outer S.  Reject and ignore the
      // outer S.
      Diag(DefRecord->getLocation(), diag::err_nested_redefinition)
        << DefRecord->getDeclName();
      Diag(RecLoc, diag::note_previous_definition);
      Record->setInvalidDecl();
      return;
    }
  
  // Verify that all the fields are okay.
  unsigned NumNamedMembers = 0;
  llvm::SmallVector<FieldDecl*, 32> RecFields;
  llvm::SmallSet<const IdentifierInfo*, 32> FieldIDs;
  
  for (unsigned i = 0; i != NumFields; ++i) {
    
    FieldDecl *FD = cast_or_null<FieldDecl>(static_cast<Decl*>(Fields[i]));
    assert(FD && "missing field decl");
    
    // Remember all fields.
    RecFields.push_back(FD);
    
    // Get the type for the field.
    Type *FDTy = FD->getType().getTypePtr();
      
    // C99 6.7.2.1p2 - A field may not be a function type.
    if (FDTy->isFunctionType()) {
      Diag(FD->getLocation(), diag::err_field_declared_as_function)
        << FD->getDeclName();
      FD->setInvalidDecl();
      EnclosingDecl->setInvalidDecl();
      continue;
    }
    // C99 6.7.2.1p2 - A field may not be an incomplete type except...
    if (FDTy->isIncompleteType()) {
      if (!Record) {  // Incomplete ivar type is always an error.
        Diag(FD->getLocation(), diag::err_field_incomplete) <<FD->getDeclName();
        FD->setInvalidDecl();
        EnclosingDecl->setInvalidDecl();
        continue;
      }
      if (i != NumFields-1 ||                   // ... that the last member ...
          !Record->isStruct() ||  // ... of a structure ...
          !FDTy->isArrayType()) {         //... may have incomplete array type.
        Diag(FD->getLocation(), diag::err_field_incomplete) <<FD->getDeclName();
        FD->setInvalidDecl();
        EnclosingDecl->setInvalidDecl();
        continue;
      }
      if (NumNamedMembers < 1) {  //... must have more than named member ...
        Diag(FD->getLocation(), diag::err_flexible_array_empty_struct)
          << FD->getDeclName();
        FD->setInvalidDecl();
        EnclosingDecl->setInvalidDecl();
        continue;
      }
      // Okay, we have a legal flexible array member at the end of the struct.
      if (Record)
        Record->setHasFlexibleArrayMember(true);
    }
    /// C99 6.7.2.1p2 - a struct ending in a flexible array member cannot be the
    /// field of another structure or the element of an array.
    if (const RecordType *FDTTy = FDTy->getAsRecordType()) {
      if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
        // If this is a member of a union, then entire union becomes "flexible".
        if (Record && Record->isUnion()) {
          Record->setHasFlexibleArrayMember(true);
        } else {
          // If this is a struct/class and this is not the last element, reject
          // it.  Note that GCC supports variable sized arrays in the middle of
          // structures.
          if (i != NumFields-1) {
            Diag(FD->getLocation(), diag::err_variable_sized_type_in_struct)
              << FD->getDeclName();
            FD->setInvalidDecl();
            EnclosingDecl->setInvalidDecl();
            continue;
          }
          // We support flexible arrays at the end of structs in other structs
          // as an extension.
          Diag(FD->getLocation(), diag::ext_flexible_array_in_struct)
            << FD->getDeclName();
          if (Record)
            Record->setHasFlexibleArrayMember(true);
        }
      }
    }
    /// A field cannot be an Objective-c object
    if (FDTy->isObjCInterfaceType()) {
      Diag(FD->getLocation(), diag::err_statically_allocated_object)
        << FD->getDeclName();
      FD->setInvalidDecl();
      EnclosingDecl->setInvalidDecl();
      continue;
    }
    // Keep track of the number of named members.
    if (IdentifierInfo *II = FD->getIdentifier()) {
      // Detect duplicate member names.
      if (!FieldIDs.insert(II)) {
        Diag(FD->getLocation(), diag::err_duplicate_member) << II;
        // Find the previous decl.
        SourceLocation PrevLoc;
        for (unsigned i = 0; ; ++i) {
          assert(i != RecFields.size() && "Didn't find previous def!");
          if (RecFields[i]->getIdentifier() == II) {
            PrevLoc = RecFields[i]->getLocation();
            break;
          }
        }
        Diag(PrevLoc, diag::note_previous_definition);
        FD->setInvalidDecl();
        EnclosingDecl->setInvalidDecl();
        continue;
      }
      ++NumNamedMembers;
    }
  }
 
  // Okay, we successfully defined 'Record'.
  if (Record) {
    Record->defineBody(Context, &RecFields[0], RecFields.size());
    // If this is a C++ record, HandleTagDeclDefinition will be invoked in
    // Sema::ActOnFinishCXXClassDef.
    if (!isa<CXXRecordDecl>(Record))
      Consumer.HandleTagDeclDefinition(Record);
  } else {
    ObjCIvarDecl **ClsFields = reinterpret_cast<ObjCIvarDecl**>(&RecFields[0]);
    if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl))
      ID->addInstanceVariablesToClass(ClsFields, RecFields.size(), RBrac);
    else if (ObjCImplementationDecl *IMPDecl = 
               dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
      assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl");
      IMPDecl->ObjCAddInstanceVariablesToClassImpl(ClsFields, RecFields.size());
      CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac);
    }
  }

  if (Attr)
    ProcessDeclAttributeList(Record, Attr);
}

Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
                                      DeclTy *lastEnumConst,
                                      SourceLocation IdLoc, IdentifierInfo *Id,
                                      SourceLocation EqualLoc, ExprTy *val) {
  EnumDecl *TheEnumDecl = cast<EnumDecl>(static_cast<Decl*>(theEnumDecl));
  EnumConstantDecl *LastEnumConst =
    cast_or_null<EnumConstantDecl>(static_cast<Decl*>(lastEnumConst));
  Expr *Val = static_cast<Expr*>(val);

  // The scope passed in may not be a decl scope.  Zip up the scope tree until
  // we find one that is.
  while ((S->getFlags() & Scope::DeclScope) == 0)
    S = S->getParent();
  
  // Verify that there isn't already something declared with this name in this
  // scope.
  Decl *PrevDecl = LookupDecl(Id, Decl::IDNS_Ordinary, S);
  if (PrevDecl && isTemplateParameterDecl(PrevDecl)) {
    // Maybe we will complain about the shadowed template parameter.
    DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
    // Just pretend that we didn't see the previous declaration.
    PrevDecl = 0;
  }

  if (PrevDecl) {
    // When in C++, we may get a TagDecl with the same name; in this case the
    // enum constant will 'hide' the tag.
    assert((getLangOptions().CPlusPlus || !isa<TagDecl>(PrevDecl)) &&
           "Received TagDecl when not in C++!");
    if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) {
      if (isa<EnumConstantDecl>(PrevDecl))
        Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id;
      else
        Diag(IdLoc, diag::err_redefinition) << Id;
      Diag(PrevDecl->getLocation(), diag::note_previous_definition);
      delete Val;
      return 0;
    }
  }

  llvm::APSInt EnumVal(32);
  QualType EltTy;
  if (Val) {
    // Make sure to promote the operand type to int.
    UsualUnaryConversions(Val);
    
    // C99 6.7.2.2p2: Make sure we have an integer constant expression.
    SourceLocation ExpLoc;
    if (VerifyIntegerConstantExpression(Val, &EnumVal)) {
      delete Val;
      Val = 0;  // Just forget about it.
    } else {
      EltTy = Val->getType();
    }
  }
  
  if (!Val) {
    if (LastEnumConst) {
      // Assign the last value + 1.
      EnumVal = LastEnumConst->getInitVal();
      ++EnumVal;

      // Check for overflow on increment.
      if (EnumVal < LastEnumConst->getInitVal())
        Diag(IdLoc, diag::warn_enum_value_overflow);
      
      EltTy = LastEnumConst->getType();
    } else {
      // First value, set to zero.
      EltTy = Context.IntTy;
      EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy)));
    }
  }
  
  EnumConstantDecl *New = 
    EnumConstantDecl::Create(Context, TheEnumDecl, IdLoc, Id, EltTy,
                             Val, EnumVal,
                             LastEnumConst);
  
  // Register this decl in the current scope stack.
  PushOnScopeChains(New, S);
  return New;
}

// FIXME: For consistency with ActOnFields(), we should have the parser
// pass in the source location for the left/right braces.
void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
                         DeclTy **Elements, unsigned NumElements) {
  EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX));
  
  if (Enum && Enum->isDefinition()) {
    // Diagnose code like:
    //   enum e0 {
    //     E0 = sizeof(enum e0 { E1 })
    //   };
    Diag(Enum->getLocation(), diag::err_nested_redefinition)
      << Enum->getDeclName();
    Diag(EnumLoc, diag::note_previous_definition);
    Enum->setInvalidDecl();
    return;
  }
  // TODO: If the result value doesn't fit in an int, it must be a long or long
  // long value.  ISO C does not support this, but GCC does as an extension,
  // emit a warning.
  unsigned IntWidth = Context.Target.getIntWidth();
  
  // Verify that all the values are okay, compute the size of the values, and
  // reverse the list.
  unsigned NumNegativeBits = 0;
  unsigned NumPositiveBits = 0;
  
  // Keep track of whether all elements have type int.
  bool AllElementsInt = true;
  
  EnumConstantDecl *EltList = 0;
  for (unsigned i = 0; i != NumElements; ++i) {
    EnumConstantDecl *ECD =
      cast_or_null<EnumConstantDecl>(static_cast<Decl*>(Elements[i]));
    if (!ECD) continue;  // Already issued a diagnostic.
    
    // If the enum value doesn't fit in an int, emit an extension warning.
    const llvm::APSInt &InitVal = ECD->getInitVal();
    assert(InitVal.getBitWidth() >= IntWidth &&
           "Should have promoted value to int");
    if (InitVal.getBitWidth() > IntWidth) {
      llvm::APSInt V(InitVal);
      V.trunc(IntWidth);
      V.extend(InitVal.getBitWidth());
      if (V != InitVal)
        Diag(ECD->getLocation(), diag::ext_enum_value_not_int)
          << InitVal.toString(10);
    }
    
    // Keep track of the size of positive and negative values.
    if (InitVal.isUnsigned() || InitVal.isNonNegative())
      NumPositiveBits = std::max(NumPositiveBits,
                                 (unsigned)InitVal.getActiveBits());
    else
      NumNegativeBits = std::max(NumNegativeBits,
                                 (unsigned)InitVal.getMinSignedBits());

    // Keep track of whether every enum element has type int (very commmon).
    if (AllElementsInt)
      AllElementsInt = ECD->getType() == Context.IntTy; 
    
    ECD->setNextDeclarator(EltList);
    EltList = ECD;
  }
  
  // Figure out the type that should be used for this enum.
  // FIXME: Support attribute(packed) on enums and -fshort-enums.
  QualType BestType;
  unsigned BestWidth;
  
  if (NumNegativeBits) {
    // If there is a negative value, figure out the smallest integer type (of 
    // int/long/longlong) that fits.
    if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
      BestType = Context.IntTy;
      BestWidth = IntWidth;
    } else {
      BestWidth = Context.Target.getLongWidth();
      
      if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth)
        BestType = Context.LongTy;
      else {
        BestWidth = Context.Target.getLongLongWidth();
        
        if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
          Diag(Enum->getLocation(), diag::warn_enum_too_large);
        BestType = Context.LongLongTy;
      }
    }
  } else {
    // If there is no negative value, figure out which of uint, ulong, ulonglong
    // fits.
    if (NumPositiveBits <= IntWidth) {
      BestType = Context.UnsignedIntTy;
      BestWidth = IntWidth;
    } else if (NumPositiveBits <=
               (BestWidth = Context.Target.getLongWidth())) {
      BestType = Context.UnsignedLongTy;
    } else {
      BestWidth = Context.Target.getLongLongWidth();
      assert(NumPositiveBits <= BestWidth &&
             "How could an initializer get larger than ULL?");
      BestType = Context.UnsignedLongLongTy;
    }
  }
  
  // Loop over all of the enumerator constants, changing their types to match
  // the type of the enum if needed.
  for (unsigned i = 0; i != NumElements; ++i) {
    EnumConstantDecl *ECD =
      cast_or_null<EnumConstantDecl>(static_cast<Decl*>(Elements[i]));
    if (!ECD) continue;  // Already issued a diagnostic.

    // Standard C says the enumerators have int type, but we allow, as an
    // extension, the enumerators to be larger than int size.  If each
    // enumerator value fits in an int, type it as an int, otherwise type it the
    // same as the enumerator decl itself.  This means that in "enum { X = 1U }"
    // that X has type 'int', not 'unsigned'.
    if (ECD->getType() == Context.IntTy) {
      // Make sure the init value is signed.
      llvm::APSInt IV = ECD->getInitVal();
      IV.setIsSigned(true);
      ECD->setInitVal(IV);
      continue;  // Already int type.
    }

    // Determine whether the value fits into an int.
    llvm::APSInt InitVal = ECD->getInitVal();
    bool FitsInInt;
    if (InitVal.isUnsigned() || !InitVal.isNegative())
      FitsInInt = InitVal.getActiveBits() < IntWidth;
    else
      FitsInInt = InitVal.getMinSignedBits() <= IntWidth;

    // If it fits into an integer type, force it.  Otherwise force it to match
    // the enum decl type.
    QualType NewTy;
    unsigned NewWidth;
    bool NewSign;
    if (FitsInInt) {
      NewTy = Context.IntTy;
      NewWidth = IntWidth;
      NewSign = true;
    } else if (ECD->getType() == BestType) {
      // Already the right type!
      continue;
    } else {
      NewTy = BestType;
      NewWidth = BestWidth;
      NewSign = BestType->isSignedIntegerType();
    }

    // Adjust the APSInt value.
    InitVal.extOrTrunc(NewWidth);
    InitVal.setIsSigned(NewSign);
    ECD->setInitVal(InitVal);
    
    // Adjust the Expr initializer and type.
    ECD->setInitExpr(new ImplicitCastExpr(NewTy, ECD->getInitExpr(), 
                                          /*isLvalue=*/false));
    ECD->setType(NewTy);
  }
  
  Enum->defineElements(EltList, BestType);
  Consumer.HandleTagDeclDefinition(Enum);
}

Sema::DeclTy *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc,
                                          ExprTy *expr) {
  StringLiteral *AsmString = cast<StringLiteral>((Expr*)expr);
  
  return FileScopeAsmDecl::Create(Context, Loc, AsmString);
}

Sema::DeclTy* Sema::ActOnLinkageSpec(SourceLocation Loc,
                                     SourceLocation LBrace,
                                     SourceLocation RBrace,
                                     const char *Lang,
                                     unsigned StrSize,
                                     DeclTy *D) {
  LinkageSpecDecl::LanguageIDs Language;
  Decl *dcl = static_cast<Decl *>(D);
  if (strncmp(Lang, "\"C\"", StrSize) == 0)
    Language = LinkageSpecDecl::lang_c;
  else if (strncmp(Lang, "\"C++\"", StrSize) == 0)
    Language = LinkageSpecDecl::lang_cxx;
  else {
    Diag(Loc, diag::err_bad_language);
    return 0;
  }

  // FIXME: Add all the various semantics of linkage specifications
  return LinkageSpecDecl::Create(Context, Loc, Language, dcl);
}

void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, 
                           ExprTy *alignment, SourceLocation PragmaLoc, 
                           SourceLocation LParenLoc, SourceLocation RParenLoc) {
  Expr *Alignment = static_cast<Expr *>(alignment);

  // If specified then alignment must be a "small" power of two.
  unsigned AlignmentVal = 0;
  if (Alignment) {
    llvm::APSInt Val;
    if (!Alignment->isIntegerConstantExpr(Val, Context) ||
        !Val.isPowerOf2() ||
        Val.getZExtValue() > 16) {
      Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
      delete Alignment;
      return; // Ignore
    }

    AlignmentVal = (unsigned) Val.getZExtValue();
  }

  switch (Kind) {
  case Action::PPK_Default: // pack([n])
    PackContext.setAlignment(AlignmentVal);
    break;

  case Action::PPK_Show: // pack(show)
    // Show the current alignment, making sure to show the right value
    // for the default.
    AlignmentVal = PackContext.getAlignment();
    // FIXME: This should come from the target.
    if (AlignmentVal == 0)
      AlignmentVal = 8;
    Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
    break;

  case Action::PPK_Push: // pack(push [, id] [, [n])
    PackContext.push(Name);
    // Set the new alignment if specified.
    if (Alignment)
      PackContext.setAlignment(AlignmentVal);    
    break;

  case Action::PPK_Pop: // pack(pop [, id] [,  n])
    // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
    // "#pragma pack(pop, identifier, n) is undefined"
    if (Alignment && Name)
      Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);    
    
    // Do the pop.
    if (!PackContext.pop(Name)) {
      // If a name was specified then failure indicates the name
      // wasn't found. Otherwise failure indicates the stack was
      // empty.
      Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
        << (Name ? "no record matching name" : "stack empty");

      // FIXME: Warn about popping named records as MSVC does.
    } else {
      // Pop succeeded, set the new alignment if specified.
      if (Alignment)
        PackContext.setAlignment(AlignmentVal);
    }
    break;

  default:
    assert(0 && "Invalid #pragma pack kind.");
  }
}

bool PragmaPackStack::pop(IdentifierInfo *Name) {
  if (Stack.empty())
    return false;

  // If name is empty just pop top.
  if (!Name) {
    Alignment = Stack.back().first;
    Stack.pop_back();
    return true;
  } 

  // Otherwise, find the named record.
  for (unsigned i = Stack.size(); i != 0; ) {
    --i;
    if (Stack[i].second == Name) {
      // Found it, pop up to and including this record.
      Alignment = Stack[i].first;
      Stack.erase(Stack.begin() + i, Stack.end());
      return true;
    }
  }

  return false;
}
