[llvm-branch-commits] [cfe-branch] r148545 [2/3] - in /cfe/branches/tooling: ./ bindings/python/clang/ docs/ examples/PrintFunctionNames/ examples/clang-interpreter/ include/clang-c/ include/clang/AST/ include/clang/Analysis/ include/clang/Analysis/Analyses/ include/clang/Analysis/Visitors/ include/clang/Basic/ include/clang/CodeGen/ include/clang/Driver/ include/clang/Frontend/ include/clang/Lex/ include/clang/Parse/ include/clang/Sema/ include/clang/Serialization/ include/clang/StaticAnalyzer/Core/ include/clang/StaticAnaly...

Manuel Klimek klimek at google.com
Fri Jan 20 08:14:26 PST 2012


Modified: cfe/branches/tooling/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Driver/Tools.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Driver/Tools.cpp (original)
+++ cfe/branches/tooling/lib/Driver/Tools.cpp Fri Jan 20 10:14:22 2012
@@ -395,8 +395,6 @@
     CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache));
   }
   
-  Args.AddAllArgs(CmdArgs, options::OPT_fauto_module_import);
-
   // Parse additional include paths from environment variables.
   // FIXME: We should probably sink the logic for handling these from the
   // frontend into the driver. It will allow deleting 4 otherwise unused flags.
@@ -519,6 +517,7 @@
   } else {
     // Select the default based on the platform.
     switch(Triple.getEnvironment()) {
+    case llvm::Triple::ANDROIDEABI:
     case llvm::Triple::GNUEABI:
       ABIName = "aapcs-linux";
       break;
@@ -591,6 +590,15 @@
         // EABI is always AAPCS, and if it was not marked 'hard', it's softfp
         FloatABI = "softfp";
         break;
+      case llvm::Triple::ANDROIDEABI: {
+        StringRef ArchName =
+          getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
+        if (ArchName.startswith("v7"))
+          FloatABI = "softfp";
+        else
+          FloatABI = "soft";
+        break;
+      }
       default:
         // Assume "soft", but warn the user we are guessing.
         FloatABI = "soft";
@@ -652,12 +660,23 @@
       CmdArgs.push_back("-vfp3");
       CmdArgs.push_back("-target-feature");
       CmdArgs.push_back("-neon");
+    } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") {
+      CmdArgs.push_back("-target-feature");
+      CmdArgs.push_back("+vfp3");
+      CmdArgs.push_back("-target-feature");
+      CmdArgs.push_back("+d16");
+      CmdArgs.push_back("-target-feature");
+      CmdArgs.push_back("-neon");
     } else if (FPU == "vfp") {
       CmdArgs.push_back("-target-feature");
       CmdArgs.push_back("+vfp2");
-    } else if (FPU == "vfp3") {
+      CmdArgs.push_back("-target-feature");
+      CmdArgs.push_back("-neon");
+    } else if (FPU == "vfp3" || FPU == "vfpv3") {
       CmdArgs.push_back("-target-feature");
       CmdArgs.push_back("+vfp3");
+      CmdArgs.push_back("-target-feature");
+      CmdArgs.push_back("-neon");
     } else if (FPU == "neon") {
       CmdArgs.push_back("-target-feature");
       CmdArgs.push_back("+neon");
@@ -800,9 +819,8 @@
   const Driver &D = getToolChain().getDriver();
 
   if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
-    StringRef MArch = A->getValue(Args);
     CmdArgs.push_back("-target-cpu");
-    CmdArgs.push_back(MArch.str().c_str());
+    CmdArgs.push_back(A->getValue(Args));
   }
 
   // Select the float ABI as determined by -msoft-float, -mhard-float, and
@@ -948,49 +966,39 @@
 {
   Arg * A = NULL;
 
-  for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) {
-    if ((*it)->getOption().matches(options::OPT_mv2) ||
-        (*it)->getOption().matches(options::OPT_mv3) ||
-        (*it)->getOption().matches(options::OPT_mv4) ||
-        (*it)->getOption().matches(options::OPT_march_EQ) ||
+  for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
+       it != ie; ++it) {
+    if ((*it)->getOption().matches(options::OPT_march_EQ) ||
         (*it)->getOption().matches(options::OPT_mcpu_EQ)) {
       A = *it;
       A->claim();
     }
+    else if ((*it)->getOption().matches(options::OPT_m_Joined)){
+      StringRef Value = (*it)->getValue(Args,0);
+      if (Value.startswith("v")) {
+        A = *it;
+        A->claim();
+      }
+    }
   }
   return A;
 }
 
-static const char *getHexagonTargetCPU(const ArgList &Args)
+static StringRef getHexagonTargetCPU(const ArgList &Args)
 {
   Arg *A;
   llvm::StringRef WhichHexagon;
 
+  // Select the default CPU (v4) if none was given or detection failed.
   if ((A = getLastHexagonArchArg (Args))) {
-    if ((A->getOption().matches(options::OPT_march_EQ)) ||
-        (A->getOption().matches(options::OPT_mcpu_EQ))) {
-      WhichHexagon = A->getValue(Args);
-      if (WhichHexagon == "v2")
-        return "hexagonv2";
-      else if (WhichHexagon == "v3")
-        return "hexagonv3";
-      else if (WhichHexagon == "v4")
-        return "hexagonv4";
-      else
-        assert (0 && "Unknown -march or -mcpu value");
-    }
-    else {
-      if (A->getOption().matches(options::OPT_mv2))
-        return "hexagonv2";
-      else if (A->getOption().matches(options::OPT_mv3))
-        return "hexagonv3";
-      else if (A->getOption().matches(options::OPT_mv4))
-        return "hexagonv4";
-      else
-        assert(0 && "Unknown -m argument.");
-    }
+    WhichHexagon = A->getValue(Args);
+    if (WhichHexagon == "")
+      return "v4";
+    else
+      return WhichHexagon;
   }
-  return "hexagonv2";
+  else
+    return "v4";
 }
 
 void Clang::AddHexagonTargetArgs(const ArgList &Args,
@@ -998,7 +1006,7 @@
   llvm::Triple Triple = getToolChain().getTriple();
 
   CmdArgs.push_back("-target-cpu");
-  CmdArgs.push_back(getHexagonTargetCPU(Args));
+  CmdArgs.push_back(Args.MakeArgString("hexagon" + getHexagonTargetCPU(Args)));
   CmdArgs.push_back("-fno-signed-char");
   CmdArgs.push_back("-nobuiltininc");
 
@@ -1342,14 +1350,14 @@
     // Add default argument set.
     if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
       CmdArgs.push_back("-analyzer-checker=core");
-      CmdArgs.push_back("-analyzer-checker=deadcode");
-      CmdArgs.push_back("-analyzer-checker=security");
 
       if (getToolChain().getTriple().getOS() != llvm::Triple::Win32)
         CmdArgs.push_back("-analyzer-checker=unix");
 
       if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple)
         CmdArgs.push_back("-analyzer-checker=osx");
+      
+      CmdArgs.push_back("-analyzer-checker=deadcode");
     }
 
     // Set the output format. The default is plist, for (lame) historical
@@ -1425,7 +1433,6 @@
   if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false))
     CmdArgs.push_back("-mrtd");
 
-  // FIXME: Set --enable-unsafe-fp-math.
   if (shouldUseFramePointer(Args, getToolChain().getTriple()))
     CmdArgs.push_back("-mdisable-fp-elim");
   if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
@@ -1436,18 +1443,90 @@
                     getToolChain().IsStrictAliasingDefault()))
     CmdArgs.push_back("-relaxed-aliasing");
 
-  // Handle -f{no-}honor-infinities, -f{no-}honor-nans, and -ffinite-math-only.
-  bool HonorInfinities = Args.hasFlag(options::OPT_fhonor_infinities,
-                                      options::OPT_fno_honor_infinities);
-  bool HonorNaNs = Args.hasFlag(options::OPT_fhonor_nans,
-                                options::OPT_fno_honor_nans);
-  if (Args.hasArg(options::OPT_ffinite_math_only))
-    HonorInfinities = HonorNaNs = false;
-  if (!HonorInfinities)
-    CmdArgs.push_back("-menable-no-infs");
-  if (!HonorNaNs)
-    CmdArgs.push_back("-menable-no-nans");
-    
+  // Handle various floating point optimization flags, mapping them to the
+  // appropriate LLVM code generation flags. The pattern for all of these is to
+  // default off the codegen optimizations, and if any flag enables them and no
+  // flag disables them after the flag enabling them, enable the codegen
+  // optimization. This is complicated by several "umbrella" flags.
+  if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+                               options::OPT_ffinite_math_only,
+                               options::OPT_fno_finite_math_only,
+                               options::OPT_fhonor_infinities,
+                               options::OPT_fno_honor_infinities))
+    if (A->getOption().getID() != options::OPT_fno_finite_math_only &&
+        A->getOption().getID() != options::OPT_fhonor_infinities)
+      CmdArgs.push_back("-menable-no-infs");
+  if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+                               options::OPT_ffinite_math_only,
+                               options::OPT_fno_finite_math_only,
+                               options::OPT_fhonor_nans,
+                               options::OPT_fno_honor_nans))
+    if (A->getOption().getID() != options::OPT_fno_finite_math_only &&
+        A->getOption().getID() != options::OPT_fhonor_nans)
+      CmdArgs.push_back("-menable-no-nans");
+
+  // -fno-math-errno is default.
+  bool MathErrno = false;
+  if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+                               options::OPT_fmath_errno,
+                               options::OPT_fno_math_errno)) {
+    if (A->getOption().getID() == options::OPT_fmath_errno) {
+      CmdArgs.push_back("-fmath-errno");
+      MathErrno = true;
+    }
+  }
+
+  // There are several flags which require disabling very specific
+  // optimizations. Any of these being disabled forces us to turn off the
+  // entire set of LLVM optimizations, so collect them through all the flag
+  // madness.
+  bool AssociativeMath = false;
+  if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+                               options::OPT_funsafe_math_optimizations,
+                               options::OPT_fno_unsafe_math_optimizations,
+                               options::OPT_fassociative_math,
+                               options::OPT_fno_associative_math))
+    if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+        A->getOption().getID() != options::OPT_fno_associative_math)
+      AssociativeMath = true;
+  bool ReciprocalMath = false;
+  if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+                               options::OPT_funsafe_math_optimizations,
+                               options::OPT_fno_unsafe_math_optimizations,
+                               options::OPT_freciprocal_math,
+                               options::OPT_fno_reciprocal_math))
+    if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+        A->getOption().getID() != options::OPT_fno_reciprocal_math)
+      ReciprocalMath = true;
+  bool SignedZeros = true;
+  if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+                               options::OPT_funsafe_math_optimizations,
+                               options::OPT_fno_unsafe_math_optimizations,
+                               options::OPT_fsigned_zeros,
+                               options::OPT_fno_signed_zeros))
+    if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+        A->getOption().getID() != options::OPT_fsigned_zeros)
+      SignedZeros = false;
+  bool TrappingMath = true;
+  if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+                               options::OPT_funsafe_math_optimizations,
+                               options::OPT_fno_unsafe_math_optimizations,
+                               options::OPT_ftrapping_math,
+                               options::OPT_fno_trapping_math))
+    if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+        A->getOption().getID() != options::OPT_ftrapping_math)
+      TrappingMath = false;
+  if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
+      !TrappingMath)
+    CmdArgs.push_back("-menable-unsafe-fp-math");
+
+  // We separately look for the '-ffast-math' flag, and if we find it, tell the
+  // frontend to provide the appropriate preprocessor macros. This is distinct
+  // from enabling any optimizations as it induces a language change which must
+  // survive serialization and deserialization, etc.
+  if (Args.hasArg(options::OPT_ffast_math))
+    CmdArgs.push_back("-ffast-math");
+
   // Decide whether to use verbose asm. Verbose assembly is the default on
   // toolchains which have the integrated assembler on by default.
   bool IsVerboseAsmDefault = getToolChain().IsIntegratedAssemblerDefault();
@@ -1549,12 +1628,6 @@
                    !getToolChain().getTriple().isOSDarwin()))
     CmdArgs.push_back("-momit-leaf-frame-pointer");
 
-  // -fno-math-errno is default.
-  if (Args.hasFlag(options::OPT_fmath_errno,
-                   options::OPT_fno_math_errno,
-                   false))
-    CmdArgs.push_back("-fmath-errno");
-
   // Explicitly error on some things we know we don't support and can't just
   // ignore.
   types::ID InputType = Inputs[0].getType();
@@ -1844,6 +1917,7 @@
   Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info);
   Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info);
   Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
+  Args.AddLastArg(CmdArgs, options::OPT_faltivec);
   if (getToolChain().SupportsProfiling())
     Args.AddLastArg(CmdArgs, options::OPT_pg);
 
@@ -1957,6 +2031,17 @@
       CmdArgs.push_back("-fblocks-runtime-optional");
   }
 
+  // -fmodules enables modules (off by default). However, for C++/Objective-C++,
+  // users must also pass -fcxx-modules. The latter flag will disappear once the
+  // modules implementation is solid for C++/Objective-C++ programs as well.
+  if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
+    bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules, 
+                                     options::OPT_fno_cxx_modules, 
+                                     false);
+    if (AllowedInCXX || !types::isCXX(InputType))
+      CmdArgs.push_back("-fmodules");
+  }
+
   // -faccess-control is default.
   if (Args.hasFlag(options::OPT_fno_access_control,
                    options::OPT_faccess_control,
@@ -2501,7 +2586,40 @@
   // Ignore explicit -force_cpusubtype_ALL option.
   (void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
 
-  // FIXME: Add -g support, once we have it.
+  // Determine the original source input.
+  const Action *SourceAction = &JA;
+  while (SourceAction->getKind() != Action::InputClass) {
+    assert(!SourceAction->getInputs().empty() && "unexpected root action!");
+    SourceAction = SourceAction->getInputs()[0];
+  }
+
+  // Forward -g, assuming we are dealing with an actual assembly file.
+  if (SourceAction->getType() == types::TY_Asm ||
+      SourceAction->getType() == types::TY_PP_Asm) {
+    Args.ClaimAllArgs(options::OPT_g_Group);
+    if (Arg *A = Args.getLastArg(options::OPT_g_Group))
+      if (!A->getOption().matches(options::OPT_g0))
+        CmdArgs.push_back("-g");
+  }
+
+  // Optionally embed the -cc1as level arguments into the debug info, for build
+  // analysis.
+  if (getToolChain().UseDwarfDebugFlags()) {
+    ArgStringList OriginalArgs;
+    for (ArgList::const_iterator it = Args.begin(),
+           ie = Args.end(); it != ie; ++it)
+      (*it)->render(Args, OriginalArgs);
+
+    llvm::SmallString<256> Flags;
+    const char *Exec = getToolChain().getDriver().getClangProgramPath();
+    Flags += Exec;
+    for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
+      Flags += " ";
+      Flags += OriginalArgs[i];
+    }
+    CmdArgs.push_back("-dwarf-debug-flags");
+    CmdArgs.push_back(Args.MakeArgString(Flags.str()));
+  }
 
   // FIXME: Add -static support, once we have it.
 
@@ -2780,29 +2898,16 @@
 
   // Add Arch Information
   Arg *A;
-  if ((A = getLastHexagonArchArg (Args))) {
-    if ((A->getOption().matches(options::OPT_march_EQ)) ||
-        (A->getOption().matches(options::OPT_mcpu_EQ))) {
-    llvm::StringRef WhichHexagon = A->getValue(Args);
-    if (WhichHexagon == "v2")
-      CmdArgs.push_back("-mv2");
-    else if (WhichHexagon == "v3")
-      CmdArgs.push_back ("-mv3");
-    else if (WhichHexagon == "v4")
-      CmdArgs.push_back ("-mv4");
+  if ((A = getLastHexagonArchArg(Args))) {
+    if (A->getOption().matches(options::OPT_m_Joined))
+      A->render(Args, CmdArgs);
     else
-      assert (0 && "Unknown -march or -mcpu value");
-    }
-    else {
-      if (A->getOption().matches(options::OPT_mv2) ||
-          A->getOption().matches(options::OPT_mv3) ||
-          A->getOption().matches(options::OPT_mv4))
-        A->render(Args, CmdArgs);
-      else
-        assert(0 && "Unknown -m argument.");
-    }
-
+      CmdArgs.push_back (Args.MakeArgString("-m" + getHexagonTargetCPU(Args)));
+  }
+  else {
+    CmdArgs.push_back (Args.MakeArgString("-m" + getHexagonTargetCPU(Args)));
   }
+
   CmdArgs.push_back("-mqdsp6-compat");
 
   const char *GCCName;
@@ -2865,6 +2970,8 @@
   }
 }
 
+void darwin::CC1::anchor() {}
+
 const char *darwin::CC1::getBaseInputName(const ArgList &Args,
                                           const InputInfoList &Inputs) {
   return Args.MakeArgString(
@@ -3509,6 +3616,8 @@
   C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
+void darwin::DarwinTool::anchor() {}
+
 void darwin::DarwinTool::AddDarwinArch(const ArgList &Args,
                                        ArgStringList &CmdArgs) const {
   StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args);
@@ -3540,13 +3649,7 @@
 
   // Newer linkers support -demangle, pass it if supported and not disabled by
   // the user.
-  //
-  // FIXME: We temporarily avoid passing -demangle to any iOS linker, because
-  // unfortunately we can't be guaranteed that the linker version used there
-  // will match the linker version detected at configure time. We need the
-  // universal driver.
-  if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle) &&
-      !DarwinTC.isTargetIPhoneOS()) {
+  if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) {
     // Don't pass -demangle to ld_classic.
     //
     // FIXME: This is a temporary workaround, ld should be handling this.
@@ -4213,11 +4316,12 @@
 
     if (Args.hasArg(options::OPT_pthread))
       CmdArgs.push_back("-lpthread");
-    if (!Args.hasArg(options::OPT_shared))
+    if (!Args.hasArg(options::OPT_shared)) {
       if (Args.hasArg(options::OPT_pg)) 
          CmdArgs.push_back("-lc_p");
       else
          CmdArgs.push_back("-lc");
+    }
     CmdArgs.push_back("-lgcc");
   }
 

Modified: cfe/branches/tooling/lib/Driver/Tools.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Driver/Tools.h?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Driver/Tools.h (original)
+++ cfe/branches/tooling/lib/Driver/Tools.h Fri Jan 20 10:14:22 2012
@@ -192,6 +192,7 @@
 
 namespace darwin {
   class LLVM_LIBRARY_VISIBILITY DarwinTool : public Tool {
+    virtual void anchor();
   protected:
     void AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const;
 
@@ -205,6 +206,7 @@
   };
 
   class LLVM_LIBRARY_VISIBILITY CC1 : public DarwinTool  {
+    virtual void anchor();
   public:
     static const char *getBaseInputName(const ArgList &Args,
                                  const InputInfoList &Input);

Modified: cfe/branches/tooling/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/ASTUnit.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/ASTUnit.cpp Fri Jan 20 10:14:22 2012
@@ -262,6 +262,8 @@
   }    
 }
 
+void ASTUnit::setPreprocessor(Preprocessor *pp) { PP = pp; }
+
 /// \brief Determine the set of code-completion contexts in which this 
 /// declaration should be shown.
 static unsigned getDeclShowContexts(NamedDecl *ND,
@@ -667,7 +669,8 @@
   AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
                                      AST->getFileManager());
   AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager(),
-                                         AST->getDiagnostics()));
+                                         AST->getDiagnostics(),
+                                         AST->ASTFileLangOpts));
   
   for (unsigned I = 0; I != NumRemappedFiles; ++I) {
     FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
@@ -826,22 +829,7 @@
       Hash = llvm::HashString(NameStr, Hash);
     }
     return;
-  }
-  
-  if (ObjCForwardProtocolDecl *Forward 
-      = dyn_cast<ObjCForwardProtocolDecl>(D)) {
-    for (ObjCForwardProtocolDecl::protocol_iterator 
-         P = Forward->protocol_begin(),
-         PEnd = Forward->protocol_end();
-         P != PEnd; ++P)
-      AddTopLevelDeclarationToHash(*P, Hash);
-    return;
-  }
-  
-  if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(D)) {
-    AddTopLevelDeclarationToHash(Class->getForwardInterfaceDecl(), Hash);
-    return;
-  }
+  }  
 }
 
 class TopLevelDeclTrackerConsumer : public ASTConsumer {
@@ -2406,7 +2394,7 @@
   if (Out.has_error())
     return CXSaveError_Unknown;
 
-  if (llvm::error_code ec = llvm::sys::fs::rename(TempPath.str(), File)) {
+  if (llvm::sys::fs::rename(TempPath.str(), File)) {
     bool exists;
     llvm::sys::fs::remove(TempPath.str(), exists);
     return CXSaveError_Unknown;

Modified: cfe/branches/tooling/lib/Frontend/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/CMakeLists.txt?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/CMakeLists.txt (original)
+++ cfe/branches/tooling/lib/Frontend/CMakeLists.txt Fri Jan 20 10:14:22 2012
@@ -13,6 +13,7 @@
   ASTMerge.cpp
   ASTUnit.cpp
   CacheTokens.cpp
+  ChainedDiagnosticConsumer.cpp
   ChainedIncludesSource.cpp
   CompilerInstance.cpp
   CompilerInvocation.cpp

Modified: cfe/branches/tooling/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/CompilerInstance.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/CompilerInstance.cpp Fri Jan 20 10:14:22 2012
@@ -252,7 +252,8 @@
 
   // Create the Preprocessor.
   HeaderSearch *HeaderInfo = new HeaderSearch(getFileManager(), 
-                                              getDiagnostics());
+                                              getDiagnostics(),
+                                              getLangOpts());
   PP = new Preprocessor(getDiagnostics(), getLangOpts(), &getTarget(),
                         getSourceManager(), *HeaderInfo, *this, PTHMgr,
                         /*OwnsHeaderSearch=*/true);
@@ -1221,25 +1222,26 @@
   if (Path.size() > 1) {
     for (unsigned I = 1, N = Path.size(); I != N; ++I) {
       StringRef Name = Path[I].first->getName();
-      llvm::StringMap<clang::Module *>::iterator Pos
-        = Module->SubModules.find(Name);
+      clang::Module *Sub = Module->findSubmodule(Name);
       
-      if (Pos == Module->SubModules.end()) {
+      if (!Sub) {
         // Attempt to perform typo correction to find a module name that works.
         llvm::SmallVector<StringRef, 2> Best;
         unsigned BestEditDistance = (std::numeric_limits<unsigned>::max)();
         
-        for (llvm::StringMap<clang::Module *>::iterator
-                  J = Module->SubModules.begin(), 
-               JEnd = Module->SubModules.end();
+        for (clang::Module::submodule_iterator J = Module->submodule_begin(), 
+                                            JEnd = Module->submodule_end();
              J != JEnd; ++J) {
-          unsigned ED = Name.edit_distance(J->getValue()->Name,
+          unsigned ED = Name.edit_distance((*J)->Name,
                                            /*AllowReplacements=*/true,
                                            BestEditDistance);
           if (ED <= BestEditDistance) {
-            if (ED < BestEditDistance)
+            if (ED < BestEditDistance) {
               Best.clear();
-            Best.push_back(J->getValue()->Name);
+              BestEditDistance = ED;
+            }
+            
+            Best.push_back((*J)->Name);
           }
         }
         
@@ -1251,11 +1253,12 @@
             << SourceRange(Path[0].second, Path[I-1].second)
             << FixItHint::CreateReplacement(SourceRange(Path[I].second),
                                             Best[0]);
-          Pos = Module->SubModules.find(Best[0]);
+          
+          Sub = Module->findSubmodule(Best[0]);
         }
       }
       
-      if (Pos == Module->SubModules.end()) {
+      if (!Sub) {
         // No submodule by this name. Complain, and don't look for further
         // submodules.
         getDiagnostics().Report(Path[I].second, diag::err_no_submodule)
@@ -1264,15 +1267,42 @@
         break;
       }
       
-      Module = Pos->getValue();
+      Module = Sub;
     }
   }
   
   // Make the named module visible, if it's not already part of the module
   // we are parsing.
-  if (ModuleName != getLangOpts().CurrentModule)
-    ModuleManager->makeModuleVisible(Module, Visibility);
+  if (ModuleName != getLangOpts().CurrentModule) {
+    if (!Module->IsFromModuleFile) {
+      // We have an umbrella header or directory that doesn't actually include
+      // all of the headers within the directory it covers. Complain about
+      // this missing submodule and recover by forgetting that we ever saw
+      // this submodule.
+      // FIXME: Should we detect this at module load time? It seems fairly
+      // expensive (and rare).
+      getDiagnostics().Report(ImportLoc, diag::warn_missing_submodule)
+        << Module->getFullModuleName()
+        << SourceRange(Path.front().second, Path.back().second);
+      
+      return 0;
+    }
+
+    // Check whether this module is available.
+    StringRef Feature;
+    if (!Module->isAvailable(getLangOpts(), Feature)) {
+      getDiagnostics().Report(ImportLoc, diag::err_module_unavailable)
+        << Module->getFullModuleName()
+        << Feature
+        << SourceRange(Path.front().second, Path.back().second);
+      LastModuleImportLoc = ImportLoc;
+      LastModuleImportResult = 0;
+      return 0;
+    }
 
+    ModuleManager->makeModuleVisible(Module, Visibility);
+  }
+  
   // If this module import was due to an inclusion directive, create an 
   // implicit import declaration to capture it in the AST.
   if (IsInclusionDirective && hasASTContext()) {

Modified: cfe/branches/tooling/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/CompilerInvocation.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/CompilerInvocation.cpp Fri Jan 20 10:14:22 2012
@@ -716,6 +716,8 @@
     Res.push_back("-fblocks");
   if (Opts.BlocksRuntimeOptional)
     Res.push_back("-fblocks-runtime-optional");
+  if (Opts.Modules)
+    Res.push_back("-fmodules");
   if (Opts.EmitAllDecls)
     Res.push_back("-femit-all-decls");
   if (Opts.MathErrno)
@@ -735,6 +737,8 @@
     Res.push_back("-fheinous-gnu-extensions");
   // Optimize is implicit.
   // OptimizeSize is implicit.
+  if (Opts.FastMath)
+    Res.push_back("-ffast-math");
   if (Opts.Static)
     Res.push_back("-static-define");
   if (Opts.DumpRecordLayouts)
@@ -944,10 +948,10 @@
     Args.getLastArgIntValue(OPT_O, DefaultOpt, Diags);
 }
 
-static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
+static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
                               DiagnosticsEngine &Diags) {
   using namespace cc1options;
-
+  bool Success = true;
   if (Arg *A = Args.getLastArg(OPT_analyzer_store)) {
     StringRef Name = A->getValue(Args);
     AnalysisStores Value = llvm::StringSwitch<AnalysisStores>(Name)
@@ -955,12 +959,13 @@
       .Case(CMDFLAG, NAME##Model)
 #include "clang/Frontend/Analyses.def"
       .Default(NumStores);
-    // FIXME: Error handling.
-    if (Value == NumStores)
+    if (Value == NumStores) {
       Diags.Report(diag::err_drv_invalid_value)
         << A->getAsString(Args) << Name;
-    else
+      Success = false;
+    } else {
       Opts.AnalysisStoreOpt = Value;
+    }
   }
 
   if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {
@@ -970,12 +975,13 @@
       .Case(CMDFLAG, NAME##Model)
 #include "clang/Frontend/Analyses.def"
       .Default(NumConstraints);
-    // FIXME: Error handling.
-    if (Value == NumConstraints)
+    if (Value == NumConstraints) {
       Diags.Report(diag::err_drv_invalid_value)
         << A->getAsString(Args) << Name;
-    else
+      Success = false;
+    } else {
       Opts.AnalysisConstraintsOpt = Value;
+    }
   }
 
   if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {
@@ -985,12 +991,13 @@
       .Case(CMDFLAG, PD_##NAME)
 #include "clang/Frontend/Analyses.def"
       .Default(NUM_ANALYSIS_DIAG_CLIENTS);
-    // FIXME: Error handling.
-    if (Value == NUM_ANALYSIS_DIAG_CLIENTS)
+    if (Value == NUM_ANALYSIS_DIAG_CLIENTS) {
       Diags.Report(diag::err_drv_invalid_value)
         << A->getAsString(Args) << Name;
-    else
+      Success = false;
+    } else {
       Opts.AnalysisDiagOpt = Value;
+    }
   }
 
   if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) {
@@ -1000,12 +1007,13 @@
       .Case(CMDFLAG, NAME)
 #include "clang/Frontend/Analyses.def"
       .Default(NumPurgeModes);
-    // FIXME: Error handling.
-    if (Value == NumPurgeModes)
+    if (Value == NumPurgeModes) {
       Diags.Report(diag::err_drv_invalid_value)
         << A->getAsString(Args) << Name;
-    else
+      Success = false;
+    } else {
       Opts.AnalysisPurgeOpt = Value;
+    }
   }
 
   Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help);
@@ -1041,17 +1049,21 @@
     for (unsigned i = 0, e = checkers.size(); i != e; ++i)
       Opts.CheckersControlList.push_back(std::make_pair(checkers[i], enable));
   }
+
+  return Success;
 }
 
-static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
+static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
                              DiagnosticsEngine &Diags) {
   using namespace cc1options;
+  bool Success = true;
 
   Opts.OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
   if (Opts.OptimizationLevel > 3) {
     Diags.Report(diag::err_drv_invalid_value)
       << Args.getLastArg(OPT_O)->getAsString(Args) << Opts.OptimizationLevel;
     Opts.OptimizationLevel = 3;
+    Success = false;
   }
 
   // We must always run at least the always inlining pass.
@@ -1109,7 +1121,8 @@
   Opts.NoDwarf2CFIAsm = Args.hasArg(OPT_fno_dwarf2_cfi_asm);
   Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm);
   Opts.SoftFloat = Args.hasArg(OPT_msoft_float);
-  Opts.UnsafeFPMath = Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
+  Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) ||
+                      Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
                       Args.hasArg(OPT_cl_fast_relaxed_math);
   Opts.UnwindTables = Args.hasArg(OPT_munwind_tables);
   Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
@@ -1140,11 +1153,15 @@
       .Case("non-legacy", CodeGenOptions::NonLegacy)
       .Case("mixed", CodeGenOptions::Mixed)
       .Default(~0U);
-    if (Method == ~0U)
+    if (Method == ~0U) {
       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
-    else
+      Success = false;
+    } else {
       Opts.ObjCDispatchMethod = Method;
+    }
   }
+
+  return Success;
 }
 
 static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
@@ -1159,9 +1176,11 @@
   Opts.AddMissingHeaderDeps = Args.hasArg(OPT_MG);
 }
 
-static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
+static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
                                 DiagnosticsEngine &Diags) {
   using namespace cc1options;
+  bool Success = true;
+
   Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file);
   Opts.DiagnosticSerializationFile =
     Args.getLastArgValue(OPT_diagnostic_serialized_file);
@@ -1192,10 +1211,12 @@
     Opts.ShowOverloads = DiagnosticsEngine::Ovl_Best;
   else if (ShowOverloads == "all")
     Opts.ShowOverloads = DiagnosticsEngine::Ovl_All;
-  else
+  else {
     Diags.Report(diag::err_drv_invalid_value)
       << Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args)
       << ShowOverloads;
+    Success = false;
+  }
 
   StringRef ShowCategory =
     Args.getLastArgValue(OPT_fdiagnostics_show_category, "none");
@@ -1205,23 +1226,27 @@
     Opts.ShowCategories = 1;
   else if (ShowCategory == "name")
     Opts.ShowCategories = 2;
-  else
+  else {
     Diags.Report(diag::err_drv_invalid_value)
       << Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args)
       << ShowCategory;
+    Success = false;
+  }
 
   StringRef Format =
     Args.getLastArgValue(OPT_fdiagnostics_format, "clang");
   if (Format == "clang")
     Opts.Format = DiagnosticOptions::Clang;
-  else if (Format == "msvc") 
+  else if (Format == "msvc")
     Opts.Format = DiagnosticOptions::Msvc;
-  else if (Format == "vi") 
+  else if (Format == "vi")
     Opts.Format = DiagnosticOptions::Vi;
-  else 
+  else {
     Diags.Report(diag::err_drv_invalid_value)
       << Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args)
       << Format;
+    Success = false;
+  }
   
   Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
   Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
@@ -1248,6 +1273,8 @@
   Opts.MessageLength = Args.getLastArgIntValue(OPT_fmessage_length, 0, Diags);
   Opts.DumpBuildInformation = Args.getLastArgValue(OPT_dump_build_information);
   Opts.Warnings = Args.getAllArgValues(OPT_W);
+
+  return Success;
 }
 
 static void ParseFileSystemArgs(FileSystemOptions &Opts, ArgList &Args) {
@@ -1593,7 +1620,7 @@
   const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
   Opts.BCPLComment = Std.hasBCPLComments();
   Opts.C99 = Std.isC99();
-  Opts.C1X = Std.isC1X();
+  Opts.C11 = Std.isC11();
   Opts.CPlusPlus = Std.isCPlusPlus();
   Opts.CPlusPlus0x = Std.isCPlusPlus0x();
   Opts.Digraphs = Std.hasDigraphs();
@@ -1789,6 +1816,7 @@
   Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
   Opts.Blocks = Args.hasArg(OPT_fblocks);
   Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
+  Opts.Modules = Args.hasArg(OPT_fmodules);
   Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
   Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
   Opts.ShortEnums = Args.hasArg(OPT_fshort_enums);
@@ -1852,6 +1880,8 @@
   // FIXME: This is affected by other options (-fno-inline).
   Opts.NoInline = !Opt;
 
+  Opts.FastMath = Args.hasArg(OPT_ffast_math);
+
   unsigned SSP = Args.getLastArgIntValue(OPT_stack_protector, 0, Diags);
   switch (SSP) {
   default:
@@ -1876,7 +1906,6 @@
     Opts.TokenCache = Opts.ImplicitPTHInclude;
   Opts.UsePredefines = !Args.hasArg(OPT_undef);
   Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record);
-  Opts.AutoModuleImport = Args.hasArg(OPT_fauto_module_import);
   Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch);
 
   Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls);
@@ -1994,10 +2023,12 @@
 
 //
 
-void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
+bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
                                         const char *const *ArgBegin,
                                         const char *const *ArgEnd,
                                         DiagnosticsEngine &Diags) {
+  bool Success = true;
+
   // Parse the arguments.
   llvm::OwningPtr<OptTable> Opts(createCC1OptTable());
   unsigned MissingArgIndex, MissingArgCount;
@@ -2005,22 +2036,28 @@
     Opts->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));
 
   // Check for missing argument error.
-  if (MissingArgCount)
+  if (MissingArgCount) {
     Diags.Report(diag::err_drv_missing_argument)
       << Args->getArgString(MissingArgIndex) << MissingArgCount;
+    Success = false;
+  }
 
   // Issue errors on unknown arguments.
   for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
-         ie = Args->filtered_end(); it != ie; ++it)
+         ie = Args->filtered_end(); it != ie; ++it) {
     Diags.Report(diag::err_drv_unknown_argument) << (*it)->getAsString(*Args);
+    Success = false;
+  }
 
-  ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags);
+  Success = ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags) && Success;
   ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args);
-  ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags);
+  Success = ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags)
+            && Success;
   ParseFileSystemArgs(Res.getFileSystemOpts(), *Args);
   // FIXME: We shouldn't have to pass the DashX option around here
   InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
-  ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags);
+  Success = ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags)
+            && Success;
   ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
   if (DashX != IK_AST && DashX != IK_LLVM_IR) {
     ParseLangArgs(*Res.getLangOpts(), *Args, DashX, Diags);
@@ -2035,6 +2072,8 @@
   ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, FileMgr, Diags);
   ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args);
   ParseTargetArgs(Res.getTargetOpts(), *Args);
+
+  return Success;
 }
 
 namespace {

Modified: cfe/branches/tooling/lib/Frontend/CreateInvocationFromCommandLine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/CreateInvocationFromCommandLine.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/CreateInvocationFromCommandLine.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/CreateInvocationFromCommandLine.cpp Fri Jan 20 10:14:22 2012
@@ -80,11 +80,12 @@
   }
 
   const driver::ArgStringList &CCArgs = Cmd->getArguments();
-  CompilerInvocation *CI = new CompilerInvocation();
-  CompilerInvocation::CreateFromArgs(*CI,
+  llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation());
+  if (!CompilerInvocation::CreateFromArgs(*CI,
                                      const_cast<const char **>(CCArgs.data()),
                                      const_cast<const char **>(CCArgs.data()) +
                                      CCArgs.size(),
-                                     *Diags);
-  return CI;
+                                     *Diags))
+    return 0;
+  return CI.take();
 }

Modified: cfe/branches/tooling/lib/Frontend/DiagnosticRenderer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/DiagnosticRenderer.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/DiagnosticRenderer.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/DiagnosticRenderer.cpp Fri Jan 20 10:14:22 2012
@@ -69,35 +69,6 @@
   return SM.getImmediateSpellingLoc(Loc);
 }
 
-/// \brief Retrieve the name of the immediate macro expansion.
-///
-/// This routine starts from a source location, and finds the name of the macro
-/// responsible for its immediate expansion. It looks through any intervening
-/// macro argument expansions to compute this. It returns a StringRef which
-/// refers to the SourceManager-owned buffer of the source where that macro
-/// name is spelled. Thus, the result shouldn't out-live that SourceManager.
-///
-static StringRef getImmediateMacroName(SourceLocation Loc,
-                                       const SourceManager &SM,
-                                       const LangOptions &LangOpts) {
-  assert(Loc.isMacroID() && "Only reasonble to call this on macros");
-  // Walk past macro argument expanions.
-  while (SM.isMacroArgExpansion(Loc))
-    Loc = SM.getImmediateExpansionRange(Loc).first;
-  
-  // Find the spelling location of the start of the non-argument expansion
-  // range. This is where the macro name was spelled in order to begin
-  // expanding this macro.
-  Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first);
-  
-  // Dig out the buffer where the macro name was spelled and the extents of the
-  // name so that we can render it into the expansion note.
-  std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc);
-  unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts);
-  StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first);
-  return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
-}
-
 /// Get the presumed location of a diagnostic message. This computes the
 /// presumed location for the top of any macro backtrace when present.
 static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM,
@@ -289,7 +260,7 @@
   llvm::SmallString<100> MessageStorage;
   llvm::raw_svector_ostream Message(MessageStorage);
   Message << "expanded from macro '"
-          << getImmediateMacroName(MacroLoc, SM, LangOpts) << "'";
+          << Lexer::getImmediateMacroName(MacroLoc, SM, LangOpts) << "'";
   emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note,
                  Message.str(),
                  Ranges, ArrayRef<FixItHint>());

Modified: cfe/branches/tooling/lib/Frontend/FrontendAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/FrontendAction.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/FrontendAction.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/FrontendAction.cpp Fri Jan 20 10:14:22 2012
@@ -310,16 +310,7 @@
 
   // Initialize the main file entry. This needs to be delayed until after PCH
   // has loaded.
-  if (isCurrentFileAST()) {
-    // Set the main file ID to an empty file.
-    //
-    // FIXME: We probably shouldn't need this, but for now this is the
-    // simplest way to reuse the logic in ParseAST.
-    const char *EmptyStr = "";
-    llvm::MemoryBuffer *SB =
-      llvm::MemoryBuffer::getMemBuffer(EmptyStr, "<dummy input>");
-    CI.getSourceManager().createMainFileIDForMemBuffer(SB);
-  } else {
+  if (!isCurrentFileAST()) {
     if (!CI.InitializeSourceManager(getCurrentFile()))
       return;
   }
@@ -411,6 +402,8 @@
   ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats);
 }
 
+void PluginASTAction::anchor() { }
+
 ASTConsumer *
 PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
                                               StringRef InFile) {

Modified: cfe/branches/tooling/lib/Frontend/FrontendActions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/FrontendActions.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/FrontendActions.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/FrontendActions.cpp Fri Jan 20 10:14:22 2012
@@ -134,8 +134,14 @@
 /// \param Includes Will be augmented with the set of #includes or #imports
 /// needed to load all of the named headers.
 static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
+                                        FileManager &FileMgr,
+                                        ModuleMap &ModMap,
                                         clang::Module *Module,
                                         llvm::SmallString<256> &Includes) {
+  // Don't collect any headers for unavailable modules.
+  if (!Module->isAvailable())
+    return;
+
   // Add includes for each of these headers.
   for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) {
     if (LangOpts.ObjC1)
@@ -157,7 +163,7 @@
       Includes += "\"\n";
     }
   } else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) {
-    // Add all of the headers we find in this subdirectory (FIXME: recursively!).
+    // Add all of the headers we find in this subdirectory.
     llvm::error_code EC;
     llvm::SmallString<128> DirNative;
     llvm::sys::path::native(UmbrellaDir->getName(), DirNative);
@@ -171,6 +177,12 @@
           .Default(false))
         continue;
       
+      // If this header is marked 'unavailable' in this module, don't include 
+      // it.
+      if (const FileEntry *Header = FileMgr.getFile(Dir->path()))
+        if (ModMap.isHeaderInUnavailableModule(Header))
+          continue;
+      
       // Include this header umbrella header for submodules.
       if (LangOpts.ObjC1)
         Includes += "#import \"";
@@ -182,11 +194,10 @@
   }
   
   // Recurse into submodules.
-  for (llvm::StringMap<clang::Module *>::iterator
-            Sub = Module->SubModules.begin(),
-         SubEnd = Module->SubModules.end();
+  for (clang::Module::submodule_iterator Sub = Module->submodule_begin(),
+                                      SubEnd = Module->submodule_end();
        Sub != SubEnd; ++Sub)
-    collectModuleHeaderIncludes(LangOpts, Sub->getValue(), Includes);
+    collectModuleHeaderIncludes(LangOpts, FileMgr, ModMap, *Sub, Includes);
 }
 
 bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, 
@@ -222,13 +233,25 @@
     
     return false;
   }
-  
+
+  // Check whether we can build this module at all.
+  StringRef Feature;
+  if (!Module->isAvailable(CI.getLangOpts(), Feature)) {
+    CI.getDiagnostics().Report(diag::err_module_unavailable)
+      << Module->getFullModuleName()
+      << Feature;
+
+    return false;
+  }
+
   // Do we have an umbrella header for this module?
   const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader();
   
   // Collect the set of #includes we need to build the module.
   llvm::SmallString<256> HeaderContents;
-  collectModuleHeaderIncludes(CI.getLangOpts(), Module, HeaderContents);
+  collectModuleHeaderIncludes(CI.getLangOpts(), CI.getFileManager(),
+    CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(),
+    Module, HeaderContents);
   if (UmbrellaHeader && HeaderContents.empty()) {
     // Simple case: we have an umbrella header and there are no additional
     // includes, we can just parse the umbrella header directly.

Modified: cfe/branches/tooling/lib/Frontend/InitPreprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/InitPreprocessor.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/InitPreprocessor.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/InitPreprocessor.cpp Fri Jan 20 10:14:22 2012
@@ -267,11 +267,8 @@
     Builder.defineMacro("__STDC_HOSTED__");
 
   if (!LangOpts.CPlusPlus) {
-    // FIXME: C1x doesn't have a defined version number yet, so pick something
-    // that is the minimum possible according to their placeholder scheme
-    // 201ymmL.
-    if (LangOpts.C1X)
-      Builder.defineMacro("__STDC_VERSION__", "201001L");
+    if (LangOpts.C11)
+      Builder.defineMacro("__STDC_VERSION__", "201112L");
     else if (LangOpts.C99)
       Builder.defineMacro("__STDC_VERSION__", "199901L");
     else if (!LangOpts.GNUMode && LangOpts.Digraphs)
@@ -328,6 +325,14 @@
   Builder.defineMacro("__GNUC__", "4");
   Builder.defineMacro("__GXX_ABI_VERSION", "1002");
 
+  // Define macros for the C11 / C++11 memory orderings
+  Builder.defineMacro("__ATOMIC_RELAXED", "0");
+  Builder.defineMacro("__ATOMIC_CONSUME", "1");
+  Builder.defineMacro("__ATOMIC_ACQUIRE", "2");
+  Builder.defineMacro("__ATOMIC_RELEASE", "3");
+  Builder.defineMacro("__ATOMIC_ACQ_REL", "4");
+  Builder.defineMacro("__ATOMIC_SEQ_CST", "5");
+
   // As sad as it is, enough software depends on the __VERSION__ for version
   // checks that it is necessary to report 4.2.1 (the base GCC version we claim
   // compatibility with) first.
@@ -414,6 +419,9 @@
   if (LangOpts.OptimizeSize)
     Builder.defineMacro("__OPTIMIZE_SIZE__");
 
+  if (LangOpts.FastMath)
+    Builder.defineMacro("__FAST_MATH__");
+
   // Initialize target-specific preprocessor defines.
 
   // Define type sizing macros based on the target properties.
@@ -516,7 +524,7 @@
   }
 
   // Macros to control C99 numerics and <float.h>
-  Builder.defineMacro("__FLT_EVAL_METHOD__", "0");
+  Builder.defineMacro("__FLT_EVAL_METHOD__", Twine(TI.getFloatEvalMethod()));
   Builder.defineMacro("__FLT_RADIX__", "2");
   int Dig = PickFP(&TI.getLongDoubleFormat(), -1/*FIXME*/, 17, 21, 33, 36);
   Builder.defineMacro("__DECIMAL_DIG__", Twine(Dig));
@@ -627,10 +635,6 @@
   InitializeFileRemapping(PP.getDiagnostics(), PP.getSourceManager(),
                           PP.getFileManager(), InitOpts);
 
-  // Specify whether the preprocessor should replace #include/#import with
-  // module imports when plausible.
-  PP.setAutoModuleImport(InitOpts.AutoModuleImport);
-
   // Emit line markers for various builtin sections of the file.  We don't do
   // this in asm preprocessor mode, because "# 4" is not a line marker directive
   // in this mode.

Modified: cfe/branches/tooling/lib/Frontend/LangStandards.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/LangStandards.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/LangStandards.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/LangStandards.cpp Fri Jan 20 10:14:22 2012
@@ -19,14 +19,13 @@
 
 const LangStandard &LangStandard::getLangStandardForKind(Kind K) {
   switch (K) {
-  default:
-    llvm_unreachable("Invalid language kind!");
   case lang_unspecified:
     llvm::report_fatal_error("getLangStandardForKind() on unspecified kind");
 #define LANGSTANDARD(id, name, desc, features) \
     case lang_##id: return Lang_##id;
 #include "clang/Frontend/LangStandards.def"
   }
+  llvm_unreachable("Invalid language kind!");
 }
 
 const LangStandard *LangStandard::getLangStandardForName(StringRef Name) {

Modified: cfe/branches/tooling/lib/Frontend/LogDiagnosticPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/LogDiagnosticPrinter.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/LogDiagnosticPrinter.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/LogDiagnosticPrinter.cpp Fri Jan 20 10:14:22 2012
@@ -12,6 +12,7 @@
 #include "clang/Basic/SourceManager.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ErrorHandling.h"
 using namespace clang;
 
 LogDiagnosticPrinter::LogDiagnosticPrinter(raw_ostream &os,
@@ -28,14 +29,13 @@
 
 static StringRef getLevelName(DiagnosticsEngine::Level Level) {
   switch (Level) {
-  default:
-    return "<unknown>";
   case DiagnosticsEngine::Ignored: return "ignored";
   case DiagnosticsEngine::Note:    return "note";
   case DiagnosticsEngine::Warning: return "warning";
   case DiagnosticsEngine::Error:   return "error";
   case DiagnosticsEngine::Fatal:   return "fatal error";
   }
+  llvm_unreachable("Invalid DiagnosticsEngine level!");
 }
 
 // Escape XML characters inside the raw string.

Modified: cfe/branches/tooling/lib/Frontend/PrintPreprocessedOutput.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/PrintPreprocessedOutput.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/PrintPreprocessedOutput.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/PrintPreprocessedOutput.cpp Fri Jan 20 10:14:22 2012
@@ -24,7 +24,6 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/Config/config.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <cstdio>
@@ -390,7 +389,6 @@
   MoveToLine(Loc);
   OS << "#pragma " << Namespace << " diagnostic ";
   switch (Map) {
-  default: llvm_unreachable("unexpected diagnostic kind");
   case diag::MAP_WARNING:
     OS << "warning";
     break;

Modified: cfe/branches/tooling/lib/Frontend/VerifyDiagnosticConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/VerifyDiagnosticConsumer.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/VerifyDiagnosticConsumer.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/VerifyDiagnosticConsumer.cpp Fri Jan 20 10:14:22 2012
@@ -459,10 +459,10 @@
     }
   }
   // Now all that's left in Right are those that were not matched.
-
-  return (PrintProblem(Diags, &SourceMgr, LeftOnly, Label, true) +
-          PrintProblem(Diags, &SourceMgr, Right.begin(), Right.end(),
-                       Label, false));
+  unsigned num = PrintProblem(Diags, &SourceMgr, LeftOnly, Label, true);
+  num += PrintProblem(Diags, &SourceMgr, Right.begin(), Right.end(),
+                      Label, false);
+  return num;
 }
 
 /// CheckResults - This compares the expected results to those that

Modified: cfe/branches/tooling/lib/Frontend/Warnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Frontend/Warnings.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Frontend/Warnings.cpp (original)
+++ cfe/branches/tooling/lib/Frontend/Warnings.cpp Fri Jan 20 10:14:22 2012
@@ -83,6 +83,10 @@
     for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) {
       StringRef Opt = Opts.Warnings[i];
 
+      // Treat -Wformat=0 as an alias for -Wno-format.
+      if (Opt == "format=0")
+        Opt = "no-format";
+
       // Check to see if this warning starts with "no-", if so, this is a
       // negative form of the option.
       bool isPositive = true;

Modified: cfe/branches/tooling/lib/FrontendTool/ExecuteCompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/FrontendTool/ExecuteCompilerInvocation.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/FrontendTool/ExecuteCompilerInvocation.cpp (original)
+++ cfe/branches/tooling/lib/FrontendTool/ExecuteCompilerInvocation.cpp Fri Jan 20 10:14:22 2012
@@ -32,9 +32,6 @@
   using namespace clang::frontend;
 
   switch (CI.getFrontendOpts().ProgramAction) {
-  default:
-    llvm_unreachable("Invalid program action!");
-
   case ASTDump:                return new ASTDumpAction();
   case ASTDumpXML:             return new ASTDumpXMLAction();
   case ASTPrint:               return new ASTPrintAction();
@@ -81,6 +78,7 @@
   case RunAnalysis:            return new ento::AnalysisAction();
   case RunPreprocessorOnly:    return new PreprocessOnlyAction();
   }
+  llvm_unreachable("Invalid program action!");
 }
 
 static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {

Modified: cfe/branches/tooling/lib/Headers/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Headers/CMakeLists.txt?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Headers/CMakeLists.txt (original)
+++ cfe/branches/tooling/lib/Headers/CMakeLists.txt Fri Jan 20 10:14:22 2012
@@ -1,16 +1,22 @@
 set(files
   altivec.h
   avxintrin.h
+  avx2intrin.h
+  bmiintrin.h
+  bmi2intrin.h
   emmintrin.h
   float.h
+  fma4intrin.h
   immintrin.h
   iso646.h
   limits.h
+  lzcntintrin.h
   mm3dnow.h
   mmintrin.h
   mm_malloc.h
   nmmintrin.h
   pmmintrin.h
+  popcntintrin.h
   smmintrin.h
   stdalign.h
   stdarg.h

Modified: cfe/branches/tooling/lib/Headers/avxintrin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Headers/avxintrin.h?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Headers/avxintrin.h (original)
+++ cfe/branches/tooling/lib/Headers/avxintrin.h Fri Jan 20 10:14:22 2012
@@ -147,11 +147,11 @@
 
 #define _mm256_round_pd(V, M) __extension__ ({ \
     __m256d __V = (V); \
-    (__m256d)__builtin_ia32_roundpd256((__v4df)__V, M); })
+    (__m256d)__builtin_ia32_roundpd256((__v4df)__V, (M)); })
 
 #define _mm256_round_ps(V, M) __extension__ ({ \
   __m256 __V = (V); \
-  (__m256)__builtin_ia32_roundps256((__v8sf)__V, M); })
+  (__m256)__builtin_ia32_roundps256((__v8sf)__V, (M)); })
 
 #define _mm256_ceil_pd(V)  _mm256_round_pd((V), _MM_FROUND_CEIL)
 #define _mm256_floor_pd(V) _mm256_round_pd((V), _MM_FROUND_FLOOR)
@@ -260,45 +260,45 @@
 
 #define _mm_permute_pd(A, C) __extension__ ({ \
   __m128d __A = (A); \
-  (__m128d)__builtin_ia32_vpermilpd((__v2df)__A, C); })
+  (__m128d)__builtin_ia32_vpermilpd((__v2df)__A, (C)); })
 
 #define _mm256_permute_pd(A, C) __extension__ ({ \
   __m256d __A = (A); \
-  (__m256d)__builtin_ia32_vpermilpd256((__v4df)__A, C); })
+  (__m256d)__builtin_ia32_vpermilpd256((__v4df)__A, (C)); })
 
 #define _mm_permute_ps(A, C) __extension__ ({ \
   __m128 __A = (A); \
-  (__m128)__builtin_ia32_vpermilps((__v4sf)__A, C); })
+  (__m128)__builtin_ia32_vpermilps((__v4sf)__A, (C)); })
 
 #define _mm256_permute_ps(A, C) __extension__ ({ \
   __m256 __A = (A); \
-  (__m256)__builtin_ia32_vpermilps256((__v8sf)__A, C); })
+  (__m256)__builtin_ia32_vpermilps256((__v8sf)__A, (C)); })
 
 #define _mm256_permute2f128_pd(V1, V2, M) __extension__ ({ \
   __m256d __V1 = (V1); \
   __m256d __V2 = (V2); \
-  (__m256d)__builtin_ia32_vperm2f128_pd256((__v4df)__V1, (__v4df)__V2, M); })
+  (__m256d)__builtin_ia32_vperm2f128_pd256((__v4df)__V1, (__v4df)__V2, (M)); })
 
 #define _mm256_permute2f128_ps(V1, V2, M) __extension__ ({ \
   __m256 __V1 = (V1); \
   __m256 __V2 = (V2); \
-  (__m256)__builtin_ia32_vperm2f128_ps256((__v8sf)__V1, (__v8sf)__V2, M); })
+  (__m256)__builtin_ia32_vperm2f128_ps256((__v8sf)__V1, (__v8sf)__V2, (M)); })
 
 #define _mm256_permute2f128_si256(V1, V2, M) __extension__ ({ \
   __m256i __V1 = (V1); \
   __m256i __V2 = (V2); \
-  (__m256i)__builtin_ia32_vperm2f128_si256((__v8si)__V1, (__v8si)__V2, M); })
+  (__m256i)__builtin_ia32_vperm2f128_si256((__v8si)__V1, (__v8si)__V2, (M)); })
 
 /* Vector Blend */
 #define _mm256_blend_pd(V1, V2, M) __extension__ ({ \
   __m256d __V1 = (V1); \
   __m256d __V2 = (V2); \
-  (__m256d)__builtin_ia32_blendpd256((__v4df)__V1, (__v4df)__V2, M); })
+  (__m256d)__builtin_ia32_blendpd256((__v4df)__V1, (__v4df)__V2, (M)); })
 
 #define _mm256_blend_ps(V1, V2, M) __extension__ ({ \
   __m256 __V1 = (V1); \
   __m256 __V2 = (V2); \
-  (__m256)__builtin_ia32_blendps256((__v8sf)__V1, (__v8sf)__V2, M); })
+  (__m256)__builtin_ia32_blendps256((__v8sf)__V1, (__v8sf)__V2, (M)); })
 
 static __inline __m256d __attribute__((__always_inline__, __nodebug__))
 _mm256_blendv_pd(__m256d a, __m256d b, __m256d c)
@@ -316,7 +316,7 @@
 #define _mm256_dp_ps(V1, V2, M) __extension__ ({ \
   __m256 __V1 = (V1); \
   __m256 __V2 = (V2); \
-  (__m256)__builtin_ia32_dpps256((__v8sf)__V1, (__v8sf)__V2, M); })
+  (__m256)__builtin_ia32_dpps256((__v8sf)__V1, (__v8sf)__V2, (M)); })
 
 /* Vector shuffle */
 #define _mm256_shuffle_ps(a, b, mask) __extension__ ({ \
@@ -404,15 +404,15 @@
 /* Vector extract */
 #define _mm256_extractf128_pd(A, O) __extension__ ({ \
   __m256d __A = (A); \
-  (__m128d)__builtin_ia32_vextractf128_pd256((__v4df)__A, O); })
+  (__m128d)__builtin_ia32_vextractf128_pd256((__v4df)__A, (O)); })
 
 #define _mm256_extractf128_ps(A, O) __extension__ ({ \
   __m256 __A = (A); \
-  (__m128)__builtin_ia32_vextractf128_ps256((__v8sf)__A, O); })
+  (__m128)__builtin_ia32_vextractf128_ps256((__v8sf)__A, (O)); })
 
 #define _mm256_extractf128_si256(A, O) __extension__ ({ \
   __m256i __A = (A); \
-  (__m128i)__builtin_ia32_vextractf128_si256((__v8si)__A, O); })
+  (__m128i)__builtin_ia32_vextractf128_si256((__v8si)__A, (O)); })
 
 static __inline int __attribute__((__always_inline__, __nodebug__))
 _mm256_extract_epi32(__m256i a, int const imm)
@@ -448,17 +448,17 @@
 #define _mm256_insertf128_pd(V1, V2, O) __extension__ ({ \
   __m256d __V1 = (V1); \
   __m128d __V2 = (V2); \
-  (__m256d)__builtin_ia32_vinsertf128_pd256((__v4df)__V1, (__v2df)__V2, O); })
+  (__m256d)__builtin_ia32_vinsertf128_pd256((__v4df)__V1, (__v2df)__V2, (O)); })
 
 #define _mm256_insertf128_ps(V1, V2, O) __extension__ ({ \
   __m256 __V1 = (V1); \
   __m128 __V2 = (V2); \
-  (__m256)__builtin_ia32_vinsertf128_ps256((__v8sf)__V1, (__v4sf)__V2, O); })
+  (__m256)__builtin_ia32_vinsertf128_ps256((__v8sf)__V1, (__v4sf)__V2, (O)); })
 
 #define _mm256_insertf128_si256(V1, V2, O) __extension__ ({ \
   __m256i __V1 = (V1); \
   __m128i __V2 = (V2); \
-  (__m256i)__builtin_ia32_vinsertf128_si256((__v8si)__V1, (__v4si)__V2, O); })
+  (__m256i)__builtin_ia32_vinsertf128_si256((__v8si)__V1, (__v4si)__V2, (O)); })
 
 static __inline __m256i __attribute__((__always_inline__, __nodebug__))
 _mm256_insert_epi32(__m256i a, int b, int const imm)

Modified: cfe/branches/tooling/lib/Headers/immintrin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Headers/immintrin.h?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Headers/immintrin.h (original)
+++ cfe/branches/tooling/lib/Headers/immintrin.h Fri Jan 20 10:14:22 2012
@@ -48,7 +48,7 @@
 #include <smmintrin.h>
 #endif
 
-#if defined (__AES__) || defined (__PCLMUL__)
+#if defined (__AES__)
 #include <wmmintrin.h>
 #endif
 
@@ -56,4 +56,20 @@
 #include <avxintrin.h>
 #endif
 
+#ifdef __AVX2__
+#include <avx2intrin.h>
+#endif
+
+#ifdef __BMI__
+#include <bmiintrin.h>
+#endif
+
+#ifdef __BMI2__
+#include <bmi2intrin.h>
+#endif
+
+#ifdef __LZCNT__
+#include <lzcntintrin.h>
+#endif
+
 #endif /* __IMMINTRIN_H */

Modified: cfe/branches/tooling/lib/Headers/smmintrin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Headers/smmintrin.h?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Headers/smmintrin.h (original)
+++ cfe/branches/tooling/lib/Headers/smmintrin.h Fri Jan 20 10:14:22 2012
@@ -245,7 +245,7 @@
 static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
 _mm_cmpeq_epi64(__m128i __V1, __m128i __V2)
 {
-  return (__m128i) __builtin_ia32_pcmpeqq((__v2di)__V1, (__v2di)__V2);
+  return (__m128i)((__v2di)__V1 == (__v2di)__V2);
 }
 
 /* SSE4 Packed Integer Sign-Extension.  */
@@ -398,7 +398,7 @@
 static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
 _mm_cmpgt_epi64(__m128i __V1, __m128i __V2)
 {
-  return __builtin_ia32_pcmpgtq((__v2di)__V1, (__v2di)__V2);
+  return (__m128i)((__v2di)__V1 > (__v2di)__V2);
 }
 
 /* SSE4.2 Accumulate CRC32.  */
@@ -428,20 +428,9 @@
 }
 #endif /* __x86_64__ */
 
-/* SSE4.2 Population Count.  */
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
-_mm_popcnt_u32(unsigned int __A)
-{
-  return __builtin_popcount(__A);
-}
-
-#ifdef __x86_64__
-static __inline__ long long __attribute__((__always_inline__, __nodebug__))
-_mm_popcnt_u64(unsigned long long __A)
-{
-  return __builtin_popcountll(__A);
-}
-#endif /* __x86_64__ */
+#ifdef __POPCNT__
+#include <popcntintrin.h>
+#endif
 
 #endif /* __SSE4_2__ */
 #endif /* __SSE4_1__ */

Modified: cfe/branches/tooling/lib/Headers/unwind.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Headers/unwind.h?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Headers/unwind.h (original)
+++ cfe/branches/tooling/lib/Headers/unwind.h Fri Jan 20 10:14:22 2012
@@ -23,7 +23,8 @@
 
 /* See "Data Definitions for libgcc_s" in the Linux Standard Base.*/
 
-#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >=  1070
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
+    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >=  1070
 /* Starting in OS X Lion the SDK includes a unwind.h. We should just use it. */
 #include_next <unwind.h>
 #else
@@ -54,7 +55,42 @@
   _URC_CONTINUE_UNWIND = 8
 } _Unwind_Reason_Code;
 
+
+#ifdef __arm__
+
+typedef enum { 
+  _UVRSC_CORE = 0,        /* integer register */ 
+  _UVRSC_VFP = 1,         /* vfp */ 
+  _UVRSC_WMMXD = 3,       /* Intel WMMX data register */ 
+  _UVRSC_WMMXC = 4        /* Intel WMMX control register */ 
+} _Unwind_VRS_RegClass; 
+
+typedef enum { 
+  _UVRSD_UINT32 = 0,  
+  _UVRSD_VFPX = 1,  
+  _UVRSD_UINT64 = 3,  
+  _UVRSD_FLOAT = 4,  
+  _UVRSD_DOUBLE = 5 
+} _Unwind_VRS_DataRepresentation; 
+
+typedef enum { 
+  _UVRSR_OK = 0,  
+  _UVRSR_NOT_IMPLEMENTED = 1,  
+  _UVRSR_FAILED = 2  
+} _Unwind_VRS_Result; 
+
+_Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *context,
+  _Unwind_VRS_RegClass regclass,
+  uint32_t regno,
+  _Unwind_VRS_DataRepresentation representation,
+  void *valuep);
+
+#else
+
 uintptr_t _Unwind_GetIP(struct _Unwind_Context* context);
+
+#endif
+
 typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context*, void*);
 _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void*);
 

Modified: cfe/branches/tooling/lib/Headers/x86intrin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Headers/x86intrin.h?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Headers/x86intrin.h (original)
+++ cfe/branches/tooling/lib/Headers/x86intrin.h Fri Jan 20 10:14:22 2012
@@ -26,6 +26,26 @@
 
 #include <immintrin.h>
 
-// FIXME: SSE4A, 3dNOW, FMA4, XOP, LWP, ABM, POPCNT
+#ifdef __BMI__
+#include <bmiintrin.h>
+#endif
+
+#ifdef __BMI2__
+#include <bmi2intrin.h>
+#endif
+
+#ifdef __LZCNT__
+#include <lzcntintrin.h>
+#endif
+
+#ifdef __POPCNT__
+#include <popcntintrin.h>
+#endif
+
+#ifdef __FMA4__
+#include <fma4intrin.h>
+#endif
+
+// FIXME: SSE4A, 3dNOW, XOP, LWP, ABM
 
 #endif /* __X86INTRIN_H */

Modified: cfe/branches/tooling/lib/Headers/xmmintrin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Headers/xmmintrin.h?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Headers/xmmintrin.h (original)
+++ cfe/branches/tooling/lib/Headers/xmmintrin.h Fri Jan 20 10:14:22 2012
@@ -664,7 +664,7 @@
 /* FIXME: We have to #define this because "sel" must be a constant integer, and
    Sema doesn't do any form of constant propagation yet. */
 
-#define _mm_prefetch(a, sel) (__builtin_prefetch((void *)(a), 0, sel))
+#define _mm_prefetch(a, sel) (__builtin_prefetch((void *)(a), 0, (sel)))
 
 static __inline__ void __attribute__((__always_inline__, __nodebug__))
 _mm_stream_pi(__m64 *p, __m64 a)

Modified: cfe/branches/tooling/lib/Index/ASTLocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Index/ASTLocation.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Index/ASTLocation.cpp (original)
+++ cfe/branches/tooling/lib/Index/ASTLocation.cpp Fri Jan 20 10:14:22 2012
@@ -41,7 +41,6 @@
     return 0;
 
   switch (getKind()) {
-  default: llvm_unreachable("Invalid Kind");
   case N_Type:
     return 0;
   case N_Decl:
@@ -60,7 +59,6 @@
     return SourceRange();
 
   switch (getKind()) {
-  default: llvm_unreachable("Invalid Kind");
   case N_Decl:
     return D->getSourceRange();
   case N_Stmt:

Modified: cfe/branches/tooling/lib/Lex/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/CMakeLists.txt?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/CMakeLists.txt (original)
+++ cfe/branches/tooling/lib/Lex/CMakeLists.txt Fri Jan 20 10:14:22 2012
@@ -13,6 +13,7 @@
   MacroInfo.cpp
   ModuleMap.cpp
   PPCaching.cpp
+  PPCallbacks.cpp
   PPDirectives.cpp
   PPExpressions.cpp
   PPLexerChange.cpp

Modified: cfe/branches/tooling/lib/Lex/HeaderSearch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/HeaderSearch.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/HeaderSearch.cpp (original)
+++ cfe/branches/tooling/lib/Lex/HeaderSearch.cpp Fri Jan 20 10:14:22 2012
@@ -38,9 +38,10 @@
 
 ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {}
 
-HeaderSearch::HeaderSearch(FileManager &FM, DiagnosticsEngine &Diags)
+HeaderSearch::HeaderSearch(FileManager &FM, DiagnosticsEngine &Diags,
+                           const LangOptions &LangOpts)
   : FileMgr(FM), Diags(Diags), FrameworkMap(64), 
-    ModMap(FileMgr, *Diags.getClient()) 
+    ModMap(FileMgr, *Diags.getClient(), LangOpts) 
 {
   AngledDirIdx = 0;
   SystemDirIdx = 0;
@@ -798,13 +799,11 @@
     // having module maps if we eventually do find a module map.
     FixUpDirectories.push_back(Dir);
   } while (true);
-  
-  return false;
 }
 
 Module *HeaderSearch::findModuleForHeader(const FileEntry *File) {
-  if (Module *Module = ModMap.findModuleForHeader(File))
-    return Module;
+  if (Module *Mod = ModMap.findModuleForHeader(File))
+    return Mod;
   
   return 0;
 }
@@ -859,7 +858,7 @@
 }
   
 Module *HeaderSearch::getFrameworkModule(StringRef Name, 
-                                                    const DirectoryEntry *Dir) {
+                                         const DirectoryEntry *Dir) {
   if (Module *Module = ModMap.findModule(Name))
     return Module;
   
@@ -875,9 +874,50 @@
   case LMM_NewlyLoaded:
     return ModMap.findModule(Name);
   }
+
+  // The top-level framework directory, from which we'll infer a framework
+  // module.
+  const DirectoryEntry *TopFrameworkDir = Dir;
+  
+  // The path from the module we're actually looking for back to the top-level
+  // framework name.
+  llvm::SmallVector<StringRef, 2> SubmodulePath;
+  SubmodulePath.push_back(Name);
   
-  // Try to infer a module map.
-  return ModMap.inferFrameworkModule(Name, Dir, /*Parent=*/0);
+  // Walk the directory structure to find any enclosing frameworks.
+  StringRef DirName = Dir->getName();
+  do {
+    // Get the parent directory name.
+    DirName = llvm::sys::path::parent_path(DirName);
+    if (DirName.empty())
+      break;
+    
+    // Determine whether this directory exists.
+    Dir = FileMgr.getDirectory(DirName);
+    if (!Dir)
+      break;
+    
+    // If this is a framework directory, then we're a subframework of this
+    // framework.
+    if (llvm::sys::path::extension(DirName) == ".framework") {
+      SubmodulePath.push_back(llvm::sys::path::stem(DirName));
+      TopFrameworkDir = Dir;
+    }
+  } while (true);
+  
+  // Try to infer a module map from the top-level framework directory.
+  Module *Result = ModMap.inferFrameworkModule(SubmodulePath.back(), 
+                                               TopFrameworkDir, 
+                                               /*Parent=*/0);
+  
+  // Follow the submodule path to find the requested (sub)framework module
+  // within the top-level framework module.
+  SubmodulePath.pop_back();
+  while (!SubmodulePath.empty() && Result) {
+    Result = ModMap.lookupModuleQualified(SubmodulePath.back(), Result);
+    SubmodulePath.pop_back();
+  }
+  return Result;
 }
 
 

Modified: cfe/branches/tooling/lib/Lex/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/Lexer.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/Lexer.cpp (original)
+++ cfe/branches/tooling/lib/Lex/Lexer.cpp Fri Jan 20 10:14:22 2012
@@ -59,6 +59,8 @@
 // Lexer Class Implementation
 //===----------------------------------------------------------------------===//
 
+void Lexer::anchor() { }
+
 void Lexer::InitLexer(const char *BufStart, const char *BufPtr,
                       const char *BufEnd) {
   InitCharacterInfo();
@@ -487,11 +489,11 @@
  SourceLocation FileLoc = SM.getSpellingLoc(Loc);
  SourceLocation BeginFileLoc = getBeginningOfFileToken(FileLoc, SM, LangOpts);
  std::pair<FileID, unsigned> FileLocInfo = SM.getDecomposedLoc(FileLoc);
- std::pair<FileID, unsigned> BeginFileLocInfo= SM.getDecomposedLoc(BeginFileLoc);
+ std::pair<FileID, unsigned> BeginFileLocInfo
+   = SM.getDecomposedLoc(BeginFileLoc);
  assert(FileLocInfo.first == BeginFileLocInfo.first &&
         FileLocInfo.second >= BeginFileLocInfo.second);
- return Loc.getLocWithOffset(SM.getDecomposedLoc(BeginFileLoc).second -
-                                 SM.getDecomposedLoc(FileLoc).second);
+ return Loc.getLocWithOffset(BeginFileLocInfo.second - FileLocInfo.second);
 }
 
 namespace {
@@ -718,11 +720,8 @@
     return SourceLocation();
 
   if (Loc.isMacroID()) {
-    if (Offset > 0 || !isAtEndOfMacroExpansion(Loc, SM, Features))
+    if (Offset > 0 || !isAtEndOfMacroExpansion(Loc, SM, Features, &Loc))
       return SourceLocation(); // Points inside the macro expansion.
-
-    // Continue and find the location just after the macro expansion.
-    Loc = SM.getExpansionRange(Loc).second;
   }
 
   unsigned Len = Lexer::MeasureTokenLength(Loc, SM, Features);
@@ -738,7 +737,8 @@
 /// token of the macro expansion.
 bool Lexer::isAtStartOfMacroExpansion(SourceLocation loc,
                                       const SourceManager &SM,
-                                      const LangOptions &LangOpts) {
+                                      const LangOptions &LangOpts,
+                                      SourceLocation *MacroBegin) {
   assert(loc.isValid() && loc.isMacroID() && "Expected a valid macro loc");
 
   std::pair<FileID, unsigned> infoLoc = SM.getDecomposedLoc(loc);
@@ -749,17 +749,22 @@
 
   SourceLocation expansionLoc =
     SM.getSLocEntry(infoLoc.first).getExpansion().getExpansionLocStart();
-  if (expansionLoc.isFileID())
-    return true; // No other macro expansions, this is the first.
+  if (expansionLoc.isFileID()) {
+    // No other macro expansions, this is the first.
+    if (MacroBegin)
+      *MacroBegin = expansionLoc;
+    return true;
+  }
 
-  return isAtStartOfMacroExpansion(expansionLoc, SM, LangOpts);
+  return isAtStartOfMacroExpansion(expansionLoc, SM, LangOpts, MacroBegin);
 }
 
 /// \brief Returns true if the given MacroID location points at the last
 /// token of the macro expansion.
 bool Lexer::isAtEndOfMacroExpansion(SourceLocation loc,
-                                        const SourceManager &SM,
-                                        const LangOptions &LangOpts) {
+                                    const SourceManager &SM,
+                                    const LangOptions &LangOpts,
+                                    SourceLocation *MacroEnd) {
   assert(loc.isValid() && loc.isMacroID() && "Expected a valid macro loc");
 
   SourceLocation spellLoc = SM.getSpellingLoc(loc);
@@ -777,10 +782,106 @@
 
   SourceLocation expansionLoc =
     SM.getSLocEntry(FID).getExpansion().getExpansionLocEnd();
-  if (expansionLoc.isFileID())
-    return true; // No other macro expansions.
+  if (expansionLoc.isFileID()) {
+    // No other macro expansions.
+    if (MacroEnd)
+      *MacroEnd = expansionLoc;
+    return true;
+  }
 
-  return isAtEndOfMacroExpansion(expansionLoc, SM, LangOpts);
+  return isAtEndOfMacroExpansion(expansionLoc, SM, LangOpts, MacroEnd);
+}
+
+/// \brief Accepts a token source range and returns a character range with
+/// file locations.
+/// Returns a null range if a part of the range resides inside a macro
+/// expansion or the range does not reside on the same FileID.
+CharSourceRange Lexer::makeFileCharRange(SourceRange TokenRange,
+                                         const SourceManager &SM,
+                                         const LangOptions &LangOpts) {
+  SourceLocation Begin = TokenRange.getBegin();
+  if (Begin.isInvalid())
+    return CharSourceRange();
+
+  if (Begin.isMacroID())
+    if (!isAtStartOfMacroExpansion(Begin, SM, LangOpts, &Begin))
+      return CharSourceRange();
+
+  SourceLocation End = getLocForEndOfToken(TokenRange.getEnd(), 0, SM,LangOpts);
+  if (End.isInvalid())
+    return CharSourceRange();
+
+  // Break down the source locations.
+  std::pair<FileID, unsigned> beginInfo = SM.getDecomposedLoc(Begin);
+  if (beginInfo.first.isInvalid())
+    return CharSourceRange();
+
+  unsigned EndOffs;
+  if (!SM.isInFileID(End, beginInfo.first, &EndOffs) ||
+      beginInfo.second > EndOffs)
+    return CharSourceRange();
+
+  return CharSourceRange::getCharRange(Begin, End);
+}
+
+StringRef Lexer::getSourceText(CharSourceRange Range,
+                               const SourceManager &SM,
+                               const LangOptions &LangOpts,
+                               bool *Invalid) {
+  if (Range.isTokenRange())
+    Range = makeFileCharRange(Range.getAsRange(), SM, LangOpts);
+
+  if (Range.isInvalid() ||
+      Range.getBegin().isMacroID() || Range.getEnd().isMacroID()) {
+    if (Invalid) *Invalid = true;
+    return StringRef();
+  }
+
+  // Break down the source location.
+  std::pair<FileID, unsigned> beginInfo = SM.getDecomposedLoc(Range.getBegin());
+  if (beginInfo.first.isInvalid()) {
+    if (Invalid) *Invalid = true;
+    return StringRef();
+  }
+
+  unsigned EndOffs;
+  if (!SM.isInFileID(Range.getEnd(), beginInfo.first, &EndOffs) ||
+      beginInfo.second > EndOffs) {
+    if (Invalid) *Invalid = true;
+    return StringRef();
+  }
+
+  // Try to the load the file buffer.
+  bool invalidTemp = false;
+  StringRef file = SM.getBufferData(beginInfo.first, &invalidTemp);
+  if (invalidTemp) {
+    if (Invalid) *Invalid = true;
+    return StringRef();
+  }
+
+  if (Invalid) *Invalid = false;
+  return file.substr(beginInfo.second, EndOffs - beginInfo.second);
+}
+
+StringRef Lexer::getImmediateMacroName(SourceLocation Loc,
+                                       const SourceManager &SM,
+                                       const LangOptions &LangOpts) {
+  assert(Loc.isMacroID() && "Only reasonble to call this on macros");
+  // Walk past macro argument expanions.
+  while (SM.isMacroArgExpansion(Loc))
+    Loc = SM.getImmediateExpansionRange(Loc).first;
+
+  // Find the spelling location of the start of the non-argument expansion
+  // range. This is where the macro name was spelled in order to begin
+  // expanding this macro.
+  Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first);
+
+  // Dig out the buffer where the macro name was spelled and the extents of the
+  // name so that we can render it into the expansion note.
+  std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc);
+  unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts);
+  StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first);
+  return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
 }
 
 //===----------------------------------------------------------------------===//
@@ -1085,9 +1186,8 @@
                                         const LangOptions &LangOpts,
                                         bool SkipTrailingWhitespaceAndNewLine) {
   if (Loc.isMacroID()) {
-    if (!Lexer::isAtEndOfMacroExpansion(Loc, SM, LangOpts))
+    if (!Lexer::isAtEndOfMacroExpansion(Loc, SM, LangOpts, &Loc))
       return SourceLocation();
-    Loc = SM.getExpansionRange(Loc).second;
   }
   Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts);
 
@@ -1169,6 +1269,13 @@
       // Found backslash<whitespace><newline>.  Parse the char after it.
       Size += EscapedNewLineSize;
       Ptr  += EscapedNewLineSize;
+
+      // If the char that we finally got was a \n, then we must have had
+      // something like \<newline><newline>.  We don't want to consume the
+      // second newline.
+      if (*Ptr == '\n' || *Ptr == '\r' || *Ptr == '\0')
+        return ' ';
+
       // Use slow version to accumulate a correct size field.
       return getCharAndSizeSlow(Ptr, Size, Tok);
     }
@@ -1220,6 +1327,12 @@
       Size += EscapedNewLineSize;
       Ptr  += EscapedNewLineSize;
 
+      // If the char that we finally got was a \n, then we must have had
+      // something like \<newline><newline>.  We don't want to consume the
+      // second newline.
+      if (*Ptr == '\n' || *Ptr == '\r' || *Ptr == '\0')
+        return ' ';
+
       // Use slow version to accumulate a correct size field.
       return getCharAndSizeSlowNoWarn(Ptr, Size, Features);
     }
@@ -1687,14 +1800,6 @@
       break;
     }
 
-    // If the char that we finally got was a \n, then we must have had something
-    // like \<newline><newline>.  We don't want to have consumed the second
-    // newline, we want CurPtr, to end up pointing to it down below.
-    if (C == '\n' || C == '\r') {
-      --CurPtr;
-      C = 'x'; // doesn't matter what this is.
-    }
-
     // If we read multiple characters, and one of those characters was a \r or
     // \n, then we had an escaped newline within the comment.  Emit diagnostic
     // unless the next line is also a // comment.

Modified: cfe/branches/tooling/lib/Lex/LiteralSupport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/LiteralSupport.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/LiteralSupport.cpp (original)
+++ cfe/branches/tooling/lib/Lex/LiteralSupport.cpp Fri Jan 20 10:14:22 2012
@@ -182,7 +182,8 @@
 static bool ProcessUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd,
                              uint32_t &UcnVal, unsigned short &UcnLen,
                              FullSourceLoc Loc, DiagnosticsEngine *Diags, 
-                             const LangOptions &Features) {
+                             const LangOptions &Features,
+                             bool in_char_string_literal = false) {
   if (!Features.CPlusPlus && !Features.C99 && Diags)
     Diags->Report(Loc, diag::warn_ucn_not_valid_in_c89);
 
@@ -216,11 +217,20 @@
     }
     return false;
   }
-  // Check UCN constraints (C99 6.4.3p2).
-  if ((UcnVal < 0xa0 &&
-      (UcnVal != 0x24 && UcnVal != 0x40 && UcnVal != 0x60 )) // $, @, `
-      || (UcnVal >= 0xD800 && UcnVal <= 0xDFFF)
-      || (UcnVal > 0x10FFFF)) /* the maximum legal UTF32 value */ {
+  // Check UCN constraints (C99 6.4.3p2) [C++11 lex.charset p2]
+  bool invalid_ucn = (0xD800<=UcnVal && UcnVal<=0xDFFF) // surrogate codepoints
+                       || 0x10FFFF < UcnVal; // maximum legal UTF32 value
+
+  // C++11 allows UCNs that refer to control characters and basic source
+  // characters inside character and string literals
+  if (!Features.CPlusPlus0x || !in_char_string_literal) {
+    if ((UcnVal < 0xa0 &&
+         (UcnVal != 0x24 && UcnVal != 0x40 && UcnVal != 0x60 ))) {  // $, @, `
+      invalid_ucn = true;
+    }
+  }
+
+  if (invalid_ucn) {
     if (Diags)
       Diags->Report(Loc, diag::err_ucn_escape_invalid);
     return false;
@@ -271,8 +281,6 @@
       ResultBuf += 2;
       return;
     }
-    // FIXME: We shouldn't print a diagnostic for UTF-16 mode.
-    if (Diags) Diags->Report(Loc, diag::warn_ucn_escape_too_large);
 
     // Convert to UTF16.
     UcnVal -= 0x10000;
@@ -747,14 +755,13 @@
 CharLiteralParser::CharLiteralParser(const char *begin, const char *end,
                                      SourceLocation Loc, Preprocessor &PP,
                                      tok::TokenKind kind) {
-  // At this point we know that the character matches the regex "L?'.*'".
+  // At this point we know that the character matches the regex "(L|u|U)?'.*'".
   HadError = false;
 
   Kind = kind;
 
-  // Determine if this is a wide or UTF character.
-  if (Kind == tok::wide_char_constant || Kind == tok::utf16_char_constant ||
-      Kind == tok::utf32_char_constant) {
+  // Skip over wide character determinant.
+  if (Kind != tok::char_constant) {
     ++begin;
   }
 
@@ -762,6 +769,10 @@
   assert(begin[0] == '\'' && "Invalid token lexed");
   ++begin;
 
+  // Trim the ending quote.
+  assert(end[-1] == '\'' && "Invalid token lexed");
+  --end;
+
   // FIXME: The "Value" is an uint64_t so we can handle char literals of
   // up to 64-bits.
   // FIXME: This extensively assumes that 'char' is 8-bits.
@@ -773,76 +784,114 @@
   assert(PP.getTargetInfo().getWCharWidth() <= 64 &&
          "Assumes sizeof(wchar) on target is <= 64");
 
-  // This is what we will use for overflow detection
-  llvm::APInt LitVal(PP.getTargetInfo().getIntWidth(), 0);
-
-  unsigned NumCharsSoFar = 0;
-  bool Warned = false;
-  while (begin[0] != '\'') {
-    uint64_t ResultChar;
-
-      // Is this a Universal Character Name escape?
-    if (begin[0] != '\\')     // If this is a normal character, consume it.
-      ResultChar = (unsigned char)*begin++;
-    else {                    // Otherwise, this is an escape character.
-      unsigned CharWidth = getCharWidth(Kind, PP.getTargetInfo());
-      // Check for UCN.
-      if (begin[1] == 'u' || begin[1] == 'U') {
-        uint32_t utf32 = 0;
-        unsigned short UcnLen = 0;
-        if (!ProcessUCNEscape(begin, end, utf32, UcnLen,
-                              FullSourceLoc(Loc, PP.getSourceManager()),
-                              &PP.getDiagnostics(), PP.getLangOptions())) {
-          HadError = 1;
-        }
-        ResultChar = utf32;
-        if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) {
-          PP.Diag(Loc, diag::warn_ucn_escape_too_large);
-          ResultChar &= ~0U >> (32-CharWidth);
-        }
+  SmallVector<uint32_t,4> codepoint_buffer;
+  codepoint_buffer.resize(end-begin);
+  uint32_t *buffer_begin = &codepoint_buffer.front();
+  uint32_t *buffer_end = buffer_begin + codepoint_buffer.size();
+
+  // Unicode escapes representing characters that cannot be correctly
+  // represented in a single code unit are disallowed in character literals
+  // by this implementation.
+  uint32_t largest_character_for_kind;
+  if (tok::wide_char_constant == Kind) {
+    largest_character_for_kind = 0xFFFFFFFFu >> (32-PP.getTargetInfo().getWCharWidth());
+  } else if (tok::utf16_char_constant == Kind) {
+    largest_character_for_kind = 0xFFFF;
+  } else if (tok::utf32_char_constant == Kind) {
+    largest_character_for_kind = 0x10FFFF;
+  } else {
+    largest_character_for_kind = 0x7Fu;
+  }
+
+  while (begin!=end) {
+    // Is this a span of non-escape characters?
+    if (begin[0] != '\\') {
+      char const *start = begin;
+      do {
+        ++begin;
+      } while (begin != end && *begin != '\\');
+
+      uint32_t *tmp_begin = buffer_begin;
+      ConversionResult res =
+      ConvertUTF8toUTF32(reinterpret_cast<UTF8 const **>(&start),
+                         reinterpret_cast<UTF8 const *>(begin),
+                         &buffer_begin,buffer_end,strictConversion);
+      if (res!=conversionOK) {
+        PP.Diag(Loc, diag::err_bad_character_encoding);
+        HadError = true;
       } else {
-        // Otherwise, this is a non-UCN escape character.  Process it.
-        ResultChar = ProcessCharEscape(begin, end, HadError,
-                                       FullSourceLoc(Loc,PP.getSourceManager()),
-                                       CharWidth, &PP.getDiagnostics());
-      }
-    }
-
-    // If this is a multi-character constant (e.g. 'abc'), handle it.  These are
-    // implementation defined (C99 6.4.4.4p10).
-    if (NumCharsSoFar) {
-      if (!isAscii()) {
-        // Emulate GCC's (unintentional?) behavior: L'ab' -> L'b'.
-        LitVal = 0;
-      } else {
-        // Narrow character literals act as though their value is concatenated
-        // in this implementation, but warn on overflow.
-        if (LitVal.countLeadingZeros() < 8 && !Warned) {
-          PP.Diag(Loc, diag::warn_char_constant_too_large);
-          Warned = true;
+        for (; tmp_begin<buffer_begin; ++tmp_begin) {
+          if (*tmp_begin > largest_character_for_kind) {
+            HadError = true;
+            PP.Diag(Loc, diag::err_character_too_large);
+          }
         }
-        LitVal <<= 8;
       }
+
+      continue;
     }
+    // Is this a Universal Character Name excape?
+    if (begin[1] == 'u' || begin[1] == 'U') {
+      unsigned short UcnLen = 0;
+      if (!ProcessUCNEscape(begin, end, *buffer_begin, UcnLen,
+                            FullSourceLoc(Loc, PP.getSourceManager()),
+                            &PP.getDiagnostics(), PP.getLangOptions(),
+                            true))
+      {
+        HadError = true;
+      } else if (*buffer_begin > largest_character_for_kind) {
+        HadError = true;
+        PP.Diag(Loc,diag::err_character_too_large);
+      }
 
-    LitVal = LitVal + ResultChar;
-    ++NumCharsSoFar;
+      ++buffer_begin;
+      continue;
+    }
+    unsigned CharWidth = getCharWidth(Kind, PP.getTargetInfo());
+    uint64_t result =
+    ProcessCharEscape(begin, end, HadError,
+                      FullSourceLoc(Loc,PP.getSourceManager()),
+                      CharWidth, &PP.getDiagnostics());
+    *buffer_begin++ = result;
   }
 
-  // If this is the second character being processed, do special handling.
+  unsigned NumCharsSoFar = buffer_begin-&codepoint_buffer.front();
+
   if (NumCharsSoFar > 1) {
-    // Warn about discarding the top bits for multi-char wide-character
-    // constants (L'abcd').
-    if (!isAscii())
+    if (isWide())
       PP.Diag(Loc, diag::warn_extraneous_char_constant);
-    else if (NumCharsSoFar != 4)
+    else if (isAscii() && NumCharsSoFar == 4)
+      PP.Diag(Loc, diag::ext_four_char_character_literal);
+    else if (isAscii())
       PP.Diag(Loc, diag::ext_multichar_character_literal);
     else
-      PP.Diag(Loc, diag::ext_four_char_character_literal);
+      PP.Diag(Loc, diag::err_multichar_utf_character_literal);
     IsMultiChar = true;
   } else
     IsMultiChar = false;
 
+  llvm::APInt LitVal(PP.getTargetInfo().getIntWidth(), 0);
+
+  // Narrow character literals act as though their value is concatenated
+  // in this implementation, but warn on overflow.
+  bool multi_char_too_long = false;
+  if (isAscii() && isMultiChar()) {
+    LitVal = 0;
+    for (size_t i=0;i<NumCharsSoFar;++i) {
+      // check for enough leading zeros to shift into
+      multi_char_too_long |= (LitVal.countLeadingZeros() < 8);
+      LitVal <<= 8;
+      LitVal = LitVal + (codepoint_buffer[i] & 0xFF);
+    }
+  } else if (NumCharsSoFar > 0) {
+    // otherwise just take the last character
+    LitVal = buffer_begin[-1];
+  }
+
+  if (!HadError && multi_char_too_long) {
+    PP.Diag(Loc,diag::warn_char_constant_too_large);
+  }
+
   // Transfer the value from APInt to uint64_t
   Value = LitVal.getZExtValue();
 

Modified: cfe/branches/tooling/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/ModuleMap.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/ModuleMap.cpp (original)
+++ cfe/branches/tooling/lib/Lex/ModuleMap.cpp Fri Jan 20 10:14:22 2012
@@ -69,7 +69,10 @@
   return Module::ExportDecl(Context, Unresolved.Wildcard);
 }
 
-ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
+ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC,
+                     const LangOptions &LangOpts)
+  : LangOpts(LangOpts)
+{
   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
   Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
             new DiagnosticsEngine(DiagIDs));
@@ -90,8 +93,14 @@
 Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
     = Headers.find(File);
-  if (Known != Headers.end())
+  if (Known != Headers.end()) {
+    // If a header corresponds to an unavailable module, don't report
+    // that it maps to anything.
+    if (!Known->second->isAvailable())
+      return 0;
+
     return Known->second;
+  }
   
   const DirectoryEntry *Dir = File->getDir();
   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
@@ -110,7 +119,7 @@
       Module *UmbrellaModule = Result;
       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
         UmbrellaModule = UmbrellaModule->Parent;
-      
+
       if (UmbrellaModule->InferSubmodules) {
         // Infer submodules for each of the directories we found between
         // the directory of the umbrella header and the directory where 
@@ -149,6 +158,12 @@
       }
       
       Headers[File] = Result;
+
+      // If a header corresponds to an unavailable module, don't report
+      // that it maps to anything.
+      if (!Result->isAvailable())
+        return 0;
+
       return Result;
     }
     
@@ -166,6 +181,67 @@
   return 0;
 }
 
+bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
+  llvm::DenseMap<const FileEntry *, Module *>::iterator Known
+    = Headers.find(Header);
+  if (Known != Headers.end())
+    return !Known->second->isAvailable();
+  
+  const DirectoryEntry *Dir = Header->getDir();
+  llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
+  StringRef DirName = Dir->getName();
+
+  // Keep walking up the directory hierarchy, looking for a directory with
+  // an umbrella header.
+  do {    
+    llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
+      = UmbrellaDirs.find(Dir);
+    if (KnownDir != UmbrellaDirs.end()) {
+      Module *Found = KnownDir->second;
+      if (!Found->isAvailable())
+        return true;
+
+      // Search up the module stack until we find a module with an umbrella
+      // directory.
+      Module *UmbrellaModule = Found;
+      while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
+        UmbrellaModule = UmbrellaModule->Parent;
+
+      if (UmbrellaModule->InferSubmodules) {
+        for (unsigned I = SkippedDirs.size(); I != 0; --I) {
+          // Find or create the module that corresponds to this directory name.
+          StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
+          Found = lookupModuleQualified(Name, Found);
+          if (!Found)
+            return false;
+          if (!Found->isAvailable())
+            return true;
+        }
+        
+        // Infer a submodule with the same name as this header file.
+        StringRef Name = llvm::sys::path::stem(Header->getName());
+        Found = lookupModuleQualified(Name, Found);
+        if (!Found)
+          return false;
+      }
+
+      return !Found->isAvailable();
+    }
+    
+    SkippedDirs.push_back(Dir);
+    
+    // Retrieve our parent path.
+    DirName = llvm::sys::path::parent_path(DirName);
+    if (DirName.empty())
+      break;
+    
+    // Resolve the parent path to a directory entry.
+    Dir = SourceMgr->getFileManager().getDirectory(DirName);
+  } while (Dir);
+  
+  return false;
+}
+
 Module *ModuleMap::findModule(StringRef Name) {
   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
   if (Known != Modules.end())
@@ -187,26 +263,20 @@
   if (!Context)
     return findModule(Name);
   
-  llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name);
-  if (Sub != Context->SubModules.end())
-    return Sub->getValue();
-
-  return 0;
+  return Context->findSubmodule(Name);
 }
 
 std::pair<Module *, bool> 
 ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
                               bool IsExplicit) {
   // Try to find an existing module with this name.
-  if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name])
-    return std::make_pair(Found, false);
+  if (Module *Sub = lookupModuleQualified(Name, Parent))
+    return std::make_pair(Sub, false);
   
   // Create a new module with this name.
   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 
                               IsExplicit);
-  if (Parent)
-    Parent->SubModules[Name] = Result;
-  else
+  if (!Parent)
     Modules[Name] = Result;
   return std::make_pair(Result, true);
 }
@@ -235,12 +305,9 @@
   
   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
                               /*IsFramework=*/true, /*IsExplicit=*/false);
-  
-  if (Parent)
-    Parent->SubModules[ModuleName] = Result;
-  else
+  if (!Parent)
     Modules[ModuleName] = Result;
-
+  
   // umbrella header "umbrella-header-name"
   Result->Umbrella = UmbrellaHeader;
   Headers[UmbrellaHeader] = Result;
@@ -274,20 +341,7 @@
                            Result);
     }
   }
-  
-  // Look for private headers.
-  llvm::SmallString<128> PrivateHeadersDirName(FrameworkDir->getName());
-  llvm::sys::path::append(PrivateHeadersDirName, "PrivateHeaders");
-  if (const DirectoryEntry *Dir = FileMgr.getDirectory(PrivateHeadersDirName)) {
-    Module *Private = findOrCreateModule("Private", Result, 
-                                         /*IsFramework=*/false, 
-                                         /*IsExplicit=*/true).first;
-    setUmbrellaDir(Private, Dir);
-    Private->InferSubmodules = true;
-    Private->InferExplicitSubmodules = true;
-    Private->InferExportWildcard = true;
-  }
-  
+
   return Result;
 }
 
@@ -359,12 +413,23 @@
   
   const SourceManager &SrcMgr = Loc.getManager();
   FileID ExpansionFileID = ExpansionLoc.getFileID();
-  const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
-  if (!ExpansionFile)
-    return 0;
   
-  // Find the module that owns this header.
-  return findModuleForHeader(ExpansionFile);
+  while (const FileEntry *ExpansionFile
+           = SrcMgr.getFileEntryForID(ExpansionFileID)) {
+    // Find the module that owns this header (if any).
+    if (Module *Mod = findModuleForHeader(ExpansionFile))
+      return Mod;
+    
+    // No module owns this header, so look up the inclusion chain to see if
+    // any included header has an associated module.
+    SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
+    if (IncludeLoc.isInvalid())
+      return 0;
+    
+    ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
+  }
+  
+  return 0;
 }
 
 //----------------------------------------------------------------------------//
@@ -375,6 +440,7 @@
   /// \brief A token in a module map file.
   struct MMToken {
     enum TokenKind {
+      Comma,
       EndOfFile,
       HeaderKeyword,
       Identifier,
@@ -384,6 +450,7 @@
       ModuleKeyword,
       Period,
       UmbrellaKeyword,
+      RequiresKeyword,
       Star,
       StringLiteral,
       LBrace,
@@ -449,6 +516,7 @@
       ModuleId;
     bool parseModuleId(ModuleId &Id);
     void parseModuleDecl();
+    void parseRequiresDecl();
     void parseHeaderDecl(SourceLocation UmbrellaLoc);
     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
     void parseExportDecl();
@@ -494,10 +562,15 @@
                  .Case("export", MMToken::ExportKeyword)
                  .Case("framework", MMToken::FrameworkKeyword)
                  .Case("module", MMToken::ModuleKeyword)
+                 .Case("requires", MMToken::RequiresKeyword)
                  .Case("umbrella", MMToken::UmbrellaKeyword)
                  .Default(MMToken::Identifier);
     break;
-      
+
+  case tok::comma:
+    Tok.Kind = MMToken::Comma;
+    break;
+
   case tok::eof:
     Tok.Kind = MMToken::EndOfFile;
     break;
@@ -614,6 +687,7 @@
 ///     'explicit'[opt] 'framework'[opt] 'module' module-id { module-member* }
 ///
 ///   module-member:
+///     requires-declaration
 ///     header-declaration
 ///     submodule-declaration
 ///     export-declaration
@@ -713,15 +787,23 @@
   SourceLocation LBraceLoc = consumeToken();
   
   // Determine whether this (sub)module has already been defined.
-  llvm::StringMap<Module *> &ModuleSpace
-    = ActiveModule? ActiveModule->SubModules : Map.Modules;
-  llvm::StringMap<Module *>::iterator ExistingModule
-    = ModuleSpace.find(ModuleName);
-  if (ExistingModule != ModuleSpace.end()) {
+  if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
+    if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
+      // Skip the module definition.
+      skipUntil(MMToken::RBrace);
+      if (Tok.is(MMToken::RBrace))
+        consumeToken();
+      else {
+        Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
+        Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
+        HadError = true;        
+      }
+      return;
+    }
+    
     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
       << ModuleName;
-    Diags.Report(ExistingModule->getValue()->DefinitionLoc,
-                 diag::note_mmap_prev_definition);
+    Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
     
     // Skip the module definition.
     skipUntil(MMToken::RBrace);
@@ -733,9 +815,9 @@
   }
 
   // Start defining this module.
-  ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
-                            Explicit);
-  ModuleSpace[ModuleName] = ActiveModule;
+  ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
+                                        Explicit).first;
+  ActiveModule->DefinitionLoc = ModuleNameLoc;
   
   bool Done = false;
   do {
@@ -755,6 +837,10 @@
       parseExportDecl();
       break;
         
+    case MMToken::RequiresKeyword:
+      parseRequiresDecl();
+      break;
+
     case MMToken::UmbrellaKeyword: {
       SourceLocation UmbrellaLoc = consumeToken();
       if (Tok.is(MMToken::HeaderKeyword))
@@ -787,6 +873,43 @@
   ActiveModule = PreviousActiveModule;
 }
 
+/// \brief Parse a requires declaration.
+///
+///   requires-declaration:
+///     'requires' feature-list
+///
+///   feature-list:
+///     identifier ',' feature-list
+///     identifier
+void ModuleMapParser::parseRequiresDecl() {
+  assert(Tok.is(MMToken::RequiresKeyword));
+
+  // Parse 'requires' keyword.
+  consumeToken();
+
+  // Parse the feature-list.
+  do {
+    if (!Tok.is(MMToken::Identifier)) {
+      Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
+      HadError = true;
+      return;
+    }
+
+    // Consume the feature name.
+    std::string Feature = Tok.getString();
+    consumeToken();
+
+    // Add this feature.
+    ActiveModule->addRequirement(Feature, Map.LangOpts);
+
+    if (!Tok.is(MMToken::Comma))
+      break;
+
+    // Consume the comma.
+    consumeToken();
+  } while (true);
+}
+
 /// \brief Append to \p Paths the set of paths needed to get to the 
 /// subframework in which the given module lives.
 void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) {
@@ -1123,12 +1246,14 @@
       parseModuleDecl();
       break;
       
+    case MMToken::Comma:
     case MMToken::ExportKeyword:
     case MMToken::HeaderKeyword:
     case MMToken::Identifier:
     case MMToken::LBrace:
     case MMToken::Period:
     case MMToken::RBrace:
+    case MMToken::RequiresKeyword:
     case MMToken::Star:
     case MMToken::StringLiteral:
     case MMToken::UmbrellaKeyword:
@@ -1138,8 +1263,6 @@
       break;
     }
   } while (true);
-  
-  return HadError;
 }
 
 bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
@@ -1149,8 +1272,8 @@
     return true;
   
   // Parse this module map file.
-  Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
-  Diags->getClient()->BeginSourceFile(LangOpts);
+  Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
+  Diags->getClient()->BeginSourceFile(MMapLangOpts);
   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
   bool Result = Parser.parseModuleMapFile();
   Diags->getClient()->EndSourceFile();

Modified: cfe/branches/tooling/lib/Lex/PPCaching.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/PPCaching.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/PPCaching.cpp (original)
+++ cfe/branches/tooling/lib/Lex/PPCaching.cpp Fri Jan 20 10:14:22 2012
@@ -42,6 +42,7 @@
          && "EnableBacktrackAtThisPos was not called!");
   CachedLexPos = BacktrackPositions.back();
   BacktrackPositions.pop_back();
+  recomputeCurLexerKind();
 }
 
 void Preprocessor::CachingLex(Token &Result) {
@@ -74,8 +75,7 @@
     return;
 
   PushIncludeMacroStack();
-  if (CurLexerKind != CLK_LexAfterModuleImport)
-    CurLexerKind = CLK_CachingLexer;
+  CurLexerKind = CLK_CachingLexer;
 }
 
 

Modified: cfe/branches/tooling/lib/Lex/PPDirectives.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/PPDirectives.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/PPDirectives.cpp (original)
+++ cfe/branches/tooling/lib/Lex/PPDirectives.cpp Fri Jan 20 10:14:22 2012
@@ -682,10 +682,15 @@
       //isExtension = true;  // FIXME: implement #unassert
       break;
         
-    case tok::pp___export_macro__:
-      return HandleMacroExportDirective(Result);
-    case tok::pp___private_macro__:
-      return HandleMacroPrivateDirective(Result);
+    case tok::pp___public_macro:
+      if (getLangOptions().Modules)
+        return HandleMacroPublicDirective(Result);
+      break;
+        
+    case tok::pp___private_macro:
+      if (getLangOptions().Modules)
+        return HandleMacroPrivateDirective(Result);
+      break;
     }
     break;
   }
@@ -1038,8 +1043,8 @@
   }
 }
 
-/// \brief Handle a #__export_macro__ directive.
-void Preprocessor::HandleMacroExportDirective(Token &Tok) {
+/// \brief Handle a #public directive.
+void Preprocessor::HandleMacroPublicDirective(Token &Tok) {
   Token MacroNameTok;
   ReadMacroName(MacroNameTok, 2);
   
@@ -1047,8 +1052,8 @@
   if (MacroNameTok.is(tok::eod))
     return;
 
-  // Check to see if this is the last token on the #__export_macro__ line.
-  CheckEndOfDirective("__export_macro__");
+  // Check to see if this is the last token on the #__public_macro line.
+  CheckEndOfDirective("__public_macro");
 
   // Okay, we finally have a valid identifier to undef.
   MacroInfo *MI = getMacroInfo(MacroNameTok.getIdentifierInfo());
@@ -1069,7 +1074,7 @@
     MI->setChangedAfterLoad();
 }
 
-/// \brief Handle a #__private_macro__ directive.
+/// \brief Handle a #private directive.
 void Preprocessor::HandleMacroPrivateDirective(Token &Tok) {
   Token MacroNameTok;
   ReadMacroName(MacroNameTok, 2);
@@ -1078,8 +1083,8 @@
   if (MacroNameTok.is(tok::eod))
     return;
   
-  // Check to see if this is the last token on the #__private_macro__ line.
-  CheckEndOfDirective("__private_macro__");
+  // Check to see if this is the last token on the #__private_macro line.
+  CheckEndOfDirective("__private_macro");
   
   // Okay, we finally have a valid identifier to undef.
   MacroInfo *MI = getMacroInfo(MacroNameTok.getIdentifierInfo());
@@ -1294,7 +1299,7 @@
   const FileEntry *File = LookupFile(
       Filename, isAngled, LookupFrom, CurDir,
       Callbacks ? &SearchPath : NULL, Callbacks ? &RelativePath : NULL,
-      AutoModuleImport? &SuggestedModule : 0);
+      getLangOptions().Modules? &SuggestedModule : 0);
 
   if (Callbacks) {
     if (!File) {
@@ -1308,7 +1313,7 @@
           
           // Try the lookup again, skipping the cache.
           File = LookupFile(Filename, isAngled, LookupFrom, CurDir, 0, 0,
-                            AutoModuleImport ? &SuggestedModule : 0,
+                            getLangOptions().Modules? &SuggestedModule : 0,
                             /*SkipCache*/true);
         }
       }
@@ -1365,7 +1370,6 @@
         
     default:
       llvm_unreachable("unknown include directive kind");
-      break;
     }
 
     // Determine whether we are actually building the module that this
@@ -1373,26 +1377,28 @@
     bool BuildingImportedModule
       = Path[0].first->getName() == getLangOptions().CurrentModule;
     
-    if (!BuildingImportedModule) {
+    if (!BuildingImportedModule && getLangOptions().ObjC2) {
       // If we're not building the imported module, warn that we're going
       // to automatically turn this inclusion directive into a module import.
+      // We only do this in Objective-C, where we have a module-import syntax.
       CharSourceRange ReplaceRange(SourceRange(HashLoc, CharEnd), 
                                    /*IsTokenRange=*/false);
       Diag(HashLoc, diag::warn_auto_module_import)
         << IncludeKind << PathString 
         << FixItHint::CreateReplacement(ReplaceRange,
-             "__import_module__ " + PathString.str().str() + ";");
+             "@import " + PathString.str().str() + ";");
     }
     
     // Load the module.
     // If this was an #__include_macros directive, only make macros visible.
     Module::NameVisibilityKind Visibility 
       = (IncludeKind == 3)? Module::MacrosVisible : Module::AllVisible;
-    TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility,
-                               /*IsIncludeDirective=*/true);
+    Module *Imported
+      = TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility,
+                                   /*IsIncludeDirective=*/true);
     
     // If this header isn't part of the module we're building, we're done.
-    if (!BuildingImportedModule)
+    if (!BuildingImportedModule && Imported)
       return;
   }
   

Modified: cfe/branches/tooling/lib/Lex/PPExpressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/PPExpressions.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/PPExpressions.cpp (original)
+++ cfe/branches/tooling/lib/Lex/PPExpressions.cpp Fri Jan 20 10:14:22 2012
@@ -703,8 +703,6 @@
     LHS.Val = Res;
     LHS.setEnd(RHS.getRange().getEnd());
   }
-
-  return false;
 }
 
 /// EvaluateDirectiveExpression - Evaluate an integer constant expression that

Modified: cfe/branches/tooling/lib/Lex/PPLexerChange.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/PPLexerChange.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/PPLexerChange.cpp (original)
+++ cfe/branches/tooling/lib/Lex/PPLexerChange.cpp Fri Jan 20 10:14:22 2012
@@ -18,7 +18,10 @@
 #include "clang/Lex/LexDiagnostic.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PathV2.h"
+#include "llvm/ADT/StringSwitch.h"
 using namespace clang;
 
 PPCallbacks::~PPCallbacks() {}
@@ -199,6 +202,31 @@
     CurLexerKind = CLK_TokenLexer;
 }
 
+/// \brief Compute the relative path that names the given file relative to
+/// the given directory.
+static void computeRelativePath(FileManager &FM, const DirectoryEntry *Dir,
+                                const FileEntry *File,
+                                llvm::SmallString<128> &Result) {
+  Result.clear();
+
+  StringRef FilePath = File->getDir()->getName();
+  StringRef Path = FilePath;
+  while (!Path.empty()) {
+    if (const DirectoryEntry *CurDir = FM.getDirectory(Path)) {
+      if (CurDir == Dir) {
+        Result = FilePath.substr(Path.size());
+        llvm::sys::path::append(Result, 
+                                llvm::sys::path::filename(File->getName()));
+        return;
+      }
+    }
+    
+    Path = llvm::sys::path::parent_path(Path);
+  }
+  
+  Result = File->getName();
+}
+
 /// HandleEndOfFile - This callback is invoked when the lexer hits the end of
 /// the current file.  This either returns the EOF token or pops a level off
 /// the include stack and keeps going.
@@ -316,6 +344,48 @@
          I=WarnUnusedMacroLocs.begin(), E=WarnUnusedMacroLocs.end(); I!=E; ++I)
     Diag(*I, diag::pp_macro_not_used);
 
+  // If we are building a module that has an umbrella header, make sure that
+  // each of the headers within the directory covered by the umbrella header
+  // was actually included by the umbrella header.
+  if (Module *Mod = getCurrentModule()) {
+    if (Mod->getUmbrellaHeader()) {
+      SourceLocation StartLoc
+        = SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+
+      if (getDiagnostics().getDiagnosticLevel(
+            diag::warn_uncovered_module_header, 
+            StartLoc) != DiagnosticsEngine::Ignored) {
+        ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap();
+        typedef llvm::sys::fs::recursive_directory_iterator
+          recursive_directory_iterator;
+        const DirectoryEntry *Dir = Mod->getUmbrellaDir();
+        llvm::error_code EC;
+        for (recursive_directory_iterator Entry(Dir->getName(), EC), End;
+             Entry != End && !EC; Entry.increment(EC)) {
+          using llvm::StringSwitch;
+          
+          // Check whether this entry has an extension typically associated with
+          // headers.
+          if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->path()))
+                 .Cases(".h", ".H", ".hh", ".hpp", true)
+                 .Default(false))
+            continue;
+
+          if (const FileEntry *Header = getFileManager().getFile(Entry->path()))
+            if (!getSourceManager().hasFileInfo(Header)) {
+              if (!ModMap.isHeaderInUnavailableModule(Header)) {
+                // Find the relative path that would access this header.
+                llvm::SmallString<128> RelativePath;
+                computeRelativePath(FileMgr, Dir, Header, RelativePath);              
+                Diag(StartLoc, diag::warn_uncovered_module_header)
+                  << RelativePath;
+              }
+            }
+        }
+      }
+    }
+  }
+  
   return true;
 }
 

Modified: cfe/branches/tooling/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/PPMacroExpansion.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/branches/tooling/lib/Lex/PPMacroExpansion.cpp Fri Jan 20 10:14:22 2012
@@ -24,7 +24,7 @@
 #include "clang/Lex/LiteralSupport.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/Config/config.h"
+#include "llvm/Config/llvm-config.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <cstdio>
@@ -305,8 +305,10 @@
     // unexpandable.
     if (IdentifierInfo *NewII = Identifier.getIdentifierInfo()) {
       if (MacroInfo *NewMI = getMacroInfo(NewII))
-        if (!NewMI->isEnabled() || NewMI == MI)
+        if (!NewMI->isEnabled() || NewMI == MI) {
           Identifier.setFlag(Token::DisableExpand);
+          Diag(Identifier, diag::pp_disabled_macro_expansion);
+        }
     }
 
     // Since this is not an identifier token, it can't be macro expanded, so
@@ -615,20 +617,23 @@
                  LangOpts.ObjCRuntimeHasWeak)
            .Case("objc_fixed_enum", LangOpts.ObjC2)
            .Case("objc_instancetype", LangOpts.ObjC2)
+           .Case("objc_modules", LangOpts.ObjC2 && LangOpts.Modules)
            .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI)
            .Case("objc_weak_class", LangOpts.ObjCNonFragileABI)
            .Case("ownership_holds", true)
            .Case("ownership_returns", true)
            .Case("ownership_takes", true)
            .Case("arc_cf_code_audited", true)
-           // C1X features
-           .Case("c_alignas", LangOpts.C1X)
-           .Case("c_generic_selections", LangOpts.C1X)
-           .Case("c_static_assert", LangOpts.C1X)
+           // C11 features
+           .Case("c_alignas", LangOpts.C11)
+           .Case("c_atomic", LangOpts.C11)
+           .Case("c_generic_selections", LangOpts.C11)
+           .Case("c_static_assert", LangOpts.C11)
            // C++0x features
            .Case("cxx_access_control_sfinae", LangOpts.CPlusPlus0x)
            .Case("cxx_alias_templates", LangOpts.CPlusPlus0x)
            .Case("cxx_alignas", LangOpts.CPlusPlus0x)
+           .Case("cxx_atomic", LangOpts.CPlusPlus0x)
            .Case("cxx_attributes", LangOpts.CPlusPlus0x)
            .Case("cxx_auto_type", LangOpts.CPlusPlus0x)
          //.Case("cxx_constexpr", false);
@@ -695,6 +700,7 @@
            .Case("is_trivial", LangOpts.CPlusPlus)
            .Case("is_trivially_copyable", LangOpts.CPlusPlus)
            .Case("is_union", LangOpts.CPlusPlus)
+           .Case("modules", LangOpts.Modules)
            .Case("tls", PP.getTargetInfo().isTLSSupported())
            .Case("underlying_type", LangOpts.CPlusPlus)
            .Default(false);
@@ -718,11 +724,13 @@
   // Because we inherit the feature list from HasFeature, this string switch
   // must be less restrictive than HasFeature's.
   return llvm::StringSwitch<bool>(II->getName())
-           // C1X features supported by other languages as extensions.
+           // C11 features supported by other languages as extensions.
            .Case("c_alignas", true)
+           .Case("c_atomic", true)
            .Case("c_generic_selections", true)
            .Case("c_static_assert", true)
            // C++0x features supported by other languages as extensions.
+           .Case("cxx_atomic", LangOpts.CPlusPlus)
            .Case("cxx_deleted_functions", LangOpts.CPlusPlus)
            .Case("cxx_explicit_conversions", LangOpts.CPlusPlus)
            .Case("cxx_inline_namespaces", LangOpts.CPlusPlus)

Modified: cfe/branches/tooling/lib/Lex/Pragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/Pragma.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/Pragma.cpp (original)
+++ cfe/branches/tooling/lib/Lex/Pragma.cpp Fri Jan 20 10:14:22 2012
@@ -714,8 +714,10 @@
 
   // If this is a non-default namespace and it is now empty, remove
   // it.
-  if (NS != PragmaHandlers && NS->IsEmpty())
+  if (NS != PragmaHandlers && NS->IsEmpty()) {
     PragmaHandlers->RemovePragmaHandler(NS);
+    delete NS;
+  }
 }
 
 bool Preprocessor::LexOnOffSwitch(tok::OnOffSwitch &Result) {

Modified: cfe/branches/tooling/lib/Lex/PreprocessingRecord.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/PreprocessingRecord.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/PreprocessingRecord.cpp (original)
+++ cfe/branches/tooling/lib/Lex/PreprocessingRecord.cpp Fri Jan 20 10:14:22 2012
@@ -390,7 +390,6 @@
     
   default:
     llvm_unreachable("Unknown include directive kind");
-    return;
   }
   
   clang::InclusionDirective *ID

Modified: cfe/branches/tooling/lib/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/Preprocessor.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/Preprocessor.cpp (original)
+++ cfe/branches/tooling/lib/Lex/Preprocessor.cpp Fri Jan 20 10:14:22 2012
@@ -130,7 +130,6 @@
   KeepComments = false;
   KeepMacroComments = false;
   SuppressIncludeNotFoundError = false;
-  AutoModuleImport = false;
   
   // Macro expansion is enabled.
   DisableMacroExpansion = false;
@@ -267,6 +266,17 @@
   return Macros.end();
 }
 
+void Preprocessor::recomputeCurLexerKind() {
+  if (CurLexer)
+    CurLexerKind = CLK_Lexer;
+  else if (CurPTHLexer)
+    CurLexerKind = CLK_PTHLexer;
+  else if (CurTokenLexer)
+    CurLexerKind = CLK_TokenLexer;
+  else 
+    CurLexerKind = CLK_CachingLexer;
+}
+
 bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File,
                                           unsigned CompleteLine,
                                           unsigned CompleteColumn) {
@@ -390,19 +400,23 @@
   assert(NumEnteredSourceFiles == 0 && "Cannot reenter the main file!");
   FileID MainFileID = SourceMgr.getMainFileID();
 
-  // Enter the main file source buffer.
-  EnterSourceFile(MainFileID, 0, SourceLocation());
-
-  // If we've been asked to skip bytes in the main file (e.g., as part of a
-  // precompiled preamble), do so now.
-  if (SkipMainFilePreamble.first > 0)
-    CurLexer->SkipBytes(SkipMainFilePreamble.first, 
-                        SkipMainFilePreamble.second);
-  
-  // Tell the header info that the main file was entered.  If the file is later
-  // #imported, it won't be re-entered.
-  if (const FileEntry *FE = SourceMgr.getFileEntryForID(MainFileID))
-    HeaderInfo.IncrementIncludeCount(FE);
+  // If MainFileID is loaded it means we loaded an AST file, no need to enter
+  // a main file.
+  if (!SourceMgr.isLoadedFileID(MainFileID)) {
+    // Enter the main file source buffer.
+    EnterSourceFile(MainFileID, 0, SourceLocation());
+  
+    // If we've been asked to skip bytes in the main file (e.g., as part of a
+    // precompiled preamble), do so now.
+    if (SkipMainFilePreamble.first > 0)
+      CurLexer->SkipBytes(SkipMainFilePreamble.first, 
+                          SkipMainFilePreamble.second);
+    
+    // Tell the header info that the main file was entered.  If the file is later
+    // #imported, it won't be re-entered.
+    if (const FileEntry *FE = SourceMgr.getFileEntryForID(MainFileID))
+      HeaderInfo.IncrementIncludeCount(FE);
+  }
 
   // Preprocess Predefines to populate the initial preprocessor state.
   llvm::MemoryBuffer *SB =
@@ -509,8 +523,10 @@
 
   // If this is a macro to be expanded, do it.
   if (MacroInfo *MI = getMacroInfo(&II)) {
-    if (!DisableMacroExpansion && !Identifier.isExpandDisabled()) {
-      if (MI->isEnabled()) {
+    if (!DisableMacroExpansion) {
+      if (Identifier.isExpandDisabled()) {
+        Diag(Identifier, diag::pp_disabled_macro_expansion);
+      } else if (MI->isEnabled()) {
         if (!HandleMacroExpandedIdentifier(Identifier, MI))
           return;
       } else {
@@ -518,6 +534,7 @@
         // expanded, even if it's in a context where it could be expanded in the
         // future.
         Identifier.setFlag(Token::DisableExpand);
+        Diag(Identifier, diag::pp_disabled_macro_expansion);
       }
     }
   }
@@ -546,10 +563,14 @@
   if (II.isExtensionToken() && !DisableMacroExpansion)
     Diag(Identifier, diag::ext_token_used);
   
-  // If this is the '__import_module__' keyword, note that the next token
+  // If this is the 'import' contextual keyword, note that the next token 
   // indicates a module name.
-  if (II.getTokenID() == tok::kw___import_module__ &&
-      !InMacroArgs && !DisableMacroExpansion) {
+  //
+  // Note that we do not treat 'import' as a contextual keyword when we're
+  // in a caching lexer, because caching lexers only get used in contexts where
+  // import declarations are disallowed.
+  if (II.isImport() && !InMacroArgs && !DisableMacroExpansion &&
+      getLangOptions().Modules && CurLexerKind != CLK_CachingLexer) {
     ModuleImportLoc = Identifier.getLocation();
     ModuleImportPath.clear();
     ModuleImportExpectsIdentifier = true;
@@ -557,27 +578,21 @@
   }
 }
 
-/// \brief Lex a token following the __import_module__ keyword.
+/// \brief Lex a token following the 'import' contextual keyword.
+///
 void Preprocessor::LexAfterModuleImport(Token &Result) {
   // Figure out what kind of lexer we actually have.
-  if (CurLexer)
-    CurLexerKind = CLK_Lexer;
-  else if (CurPTHLexer)
-    CurLexerKind = CLK_PTHLexer;
-  else if (CurTokenLexer)
-    CurLexerKind = CLK_TokenLexer;
-  else 
-    CurLexerKind = CLK_CachingLexer;
+  recomputeCurLexerKind();
   
   // Lex the next token.
   Lex(Result);
 
   // The token sequence 
   //
-  //   __import_module__ identifier (. identifier)*
+  //   import identifier (. identifier)*
   //
-  // indicates a module import directive. We already saw the __import_module__
-  // keyword, so now we're looking for the identifiers.
+  // indicates a module import directive. We already saw the 'import' 
+  // contextual keyword, so now we're looking for the identifiers.
   if (ModuleImportExpectsIdentifier && Result.getKind() == tok::identifier) {
     // We expected to see an identifier here, and we did; continue handling
     // identifiers.

Modified: cfe/branches/tooling/lib/Lex/PreprocessorLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/PreprocessorLexer.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/PreprocessorLexer.cpp (original)
+++ cfe/branches/tooling/lib/Lex/PreprocessorLexer.cpp Fri Jan 20 10:14:22 2012
@@ -17,6 +17,8 @@
 #include "clang/Basic/SourceManager.h"
 using namespace clang;
 
+void PreprocessorLexer::anchor() { }
+
 PreprocessorLexer::PreprocessorLexer(Preprocessor *pp, FileID fid)
   : PP(pp), FID(fid), InitialNumSLocEntries(0),
     ParsingPreprocessorDirective(false),

Modified: cfe/branches/tooling/lib/Lex/TokenConcatenation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Lex/TokenConcatenation.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Lex/TokenConcatenation.cpp (original)
+++ cfe/branches/tooling/lib/Lex/TokenConcatenation.cpp Fri Jan 20 10:14:22 2012
@@ -179,11 +179,9 @@
   switch (PrevKind) {
   default:
     llvm_unreachable("InitAvoidConcatTokenInfo built wrong");
-    return true;
 
   case tok::raw_identifier:
     llvm_unreachable("tok::raw_identifier in non-raw lexing mode!");
-    return true;
 
   case tok::identifier:   // id+id or id+number or id+L"foo".
     // id+'.'... will not append.

Modified: cfe/branches/tooling/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Parse/ParseCXXInlineMethods.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/branches/tooling/lib/Parse/ParseCXXInlineMethods.cpp Fri Jan 20 10:14:22 2012
@@ -76,7 +76,7 @@
     if (Tok.is(tok::kw_delete)) {
       Diag(Tok, getLang().CPlusPlus0x ?
            diag::warn_cxx98_compat_deleted_function :
-           diag::warn_deleted_function_accepted_as_extension);
+           diag::ext_deleted_function);
 
       KWLoc = ConsumeToken();
       Actions.SetDeclDeleted(FnD, KWLoc);
@@ -84,7 +84,7 @@
     } else if (Tok.is(tok::kw_default)) {
       Diag(Tok, getLang().CPlusPlus0x ?
            diag::warn_cxx98_compat_defaulted_function :
-           diag::warn_defaulted_function_accepted_as_extension);
+           diag::ext_defaulted_function);
 
       KWLoc = ConsumeToken();
       Actions.SetDeclDefaulted(FnD, KWLoc);

Modified: cfe/branches/tooling/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Parse/ParseDecl.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Parse/ParseDecl.cpp (original)
+++ cfe/branches/tooling/lib/Parse/ParseDecl.cpp Fri Jan 20 10:14:22 2012
@@ -883,7 +883,7 @@
 /// [C++]   namespace-definition
 /// [C++]   using-directive
 /// [C++]   using-declaration
-/// [C++0x/C1X] static_assert-declaration
+/// [C++0x/C11] static_assert-declaration
 ///         others... [FIXME]
 ///
 Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts,
@@ -962,10 +962,7 @@
 
   ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
                              getDeclSpecContextFromDeclaratorContext(Context));
-  StmtResult R = Actions.ActOnVlaStmt(DS);
-  if (R.isUsable())
-    Stmts.push_back(R.release());
-  
+
   // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
   // declaration-specifiers init-declarator-list[opt] ';'
   if (Tok.is(tok::semi)) {
@@ -997,9 +994,15 @@
 
   case tok::amp:
   case tok::ampamp:
-  case tok::colon: // Might be a typo for '::'.
     return getLang().CPlusPlus;
 
+  case tok::l_square: // Might be an attribute on an unnamed bit-field.
+    return Context == Declarator::MemberContext && getLang().CPlusPlus0x &&
+           NextToken().is(tok::l_square);
+
+  case tok::colon: // Might be a typo for '::' or an unnamed bit-field.
+    return Context == Declarator::MemberContext || getLang().CPlusPlus;
+
   case tok::identifier:
     switch (NextToken().getKind()) {
     case tok::code_completion:
@@ -1022,8 +1025,13 @@
 
     case tok::colon:
       // At namespace scope, 'identifier:' is probably a typo for 'identifier::'
-      // and in block scope it's probably a label.
-      return getLang().CPlusPlus && Context == Declarator::FileContext;
+      // and in block scope it's probably a label. Inside a class definition,
+      // this is a bit-field.
+      return Context == Declarator::MemberContext ||
+             (getLang().CPlusPlus && Context == Declarator::FileContext);
+
+    case tok::identifier: // Possible virt-specifier.
+      return getLang().CPlusPlus0x && isCXX0XVirtSpecifier(NextToken());
 
     default:
       return false;
@@ -1130,6 +1138,7 @@
 
     // Parse the next declarator.
     D.clear();
+    D.setCommaLoc(CommaLoc);
 
     // Accept attributes in an init-declarator.  In the first declarator in a
     // declaration, these would be part of the declspec.  In subsequent
@@ -1141,11 +1150,12 @@
     MaybeParseGNUAttributes(D);
 
     ParseDeclarator(D);
-
-    Decl *ThisDecl = ParseDeclarationAfterDeclarator(D);
-    D.complete(ThisDecl);
-    if (ThisDecl)
-      DeclsInGroup.push_back(ThisDecl);    
+    if (!D.isInvalidType()) {
+      Decl *ThisDecl = ParseDeclarationAfterDeclarator(D);
+      D.complete(ThisDecl);
+      if (ThisDecl)
+        DeclsInGroup.push_back(ThisDecl);   
+    }
   }
 
   if (DeclEnd)
@@ -1259,8 +1269,8 @@
     D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
 
   // Parse declarator '=' initializer.
-  if (isTokenEqualOrMistypedEqualEqual(
-                               diag::err_invalid_equalequal_after_declarator)) {
+  // If a '==' or '+=' is found, suggest a fixit to '='.
+  if (isTokenEqualOrEqualTypo()) {
     ConsumeToken();
     if (Tok.is(tok::kw_delete)) {
       if (D.isFunctionDeclarator())
@@ -1566,8 +1576,8 @@
 /// FIXME: Simply returns an alignof() expression if the argument is a
 /// type. Ideally, the type should be propagated directly into Sema.
 ///
-/// [C1X]   type-id
-/// [C1X]   constant-expression
+/// [C11]   type-id
+/// [C11]   constant-expression
 /// [C++0x] type-id ...[opt]
 /// [C++0x] assignment-expression ...[opt]
 ExprResult Parser::ParseAlignArgument(SourceLocation Start,
@@ -1592,8 +1602,8 @@
 /// attribute to Attrs.
 ///
 /// alignment-specifier:
-/// [C1X]   '_Alignas' '(' type-id ')'
-/// [C1X]   '_Alignas' '(' constant-expression ')'
+/// [C11]   '_Alignas' '(' type-id ')'
+/// [C11]   '_Alignas' '(' constant-expression ')'
 /// [C++0x] 'alignas' '(' type-id ...[opt] ')'
 /// [C++0x] 'alignas' '(' assignment-expression ...[opt] ')'
 void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
@@ -1636,7 +1646,7 @@
 ///         storage-class-specifier declaration-specifiers[opt]
 ///         type-specifier declaration-specifiers[opt]
 /// [C99]   function-specifier declaration-specifiers[opt]
-/// [C1X]   alignment-specifier declaration-specifiers[opt]
+/// [C11]   alignment-specifier declaration-specifiers[opt]
 /// [GNU]   attributes declaration-specifiers[opt]
 /// [Clang] '__module_private__' declaration-specifiers[opt]
 ///
@@ -2085,8 +2095,8 @@
 
     // alignment-specifier
     case tok::kw__Alignas:
-      if (!getLang().C1X)
-        Diag(Tok, diag::ext_c1x_alignas);
+      if (!getLang().C11)
+        Diag(Tok, diag::ext_c11_alignas);
       ParseAlignmentSpecifier(DS.getAttributes());
       continue;
 
@@ -2657,9 +2667,11 @@
 
   // Read struct-declarators until we find the semicolon.
   bool FirstDeclarator = true;
+  SourceLocation CommaLoc;
   while (1) {
     ParsingDeclRAIIObject PD(*this);
     FieldDeclarator DeclaratorInfo(DS);
+    DeclaratorInfo.D.setCommaLoc(CommaLoc);
 
     // Attributes are only allowed here on successive declarators.
     if (!FirstDeclarator)
@@ -2695,7 +2707,7 @@
       return;
 
     // Consume the comma.
-    ConsumeToken();
+    CommaLoc = ConsumeToken();
 
     FirstDeclarator = false;
   }
@@ -2725,9 +2737,10 @@
 
   // Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in
   // C++.
-  if (Tok.is(tok::r_brace) && !getLang().CPlusPlus)
-    Diag(Tok, diag::ext_empty_struct_union)
-      << (TagType == TST_union);
+  if (Tok.is(tok::r_brace) && !getLang().CPlusPlus) {
+    Diag(Tok, diag::ext_empty_struct_union) << (TagType == TST_union);
+    Diag(Tok, diag::warn_empty_struct_union_compat) << (TagType == TST_union);
+  }
 
   SmallVector<Decl *, 32> FieldDecls;
 
@@ -2856,15 +2869,14 @@
     return cutOffParsing();
   }
 
-  bool IsScopedEnum = false;
+  SourceLocation ScopedEnumKWLoc;
   bool IsScopedUsingClassTag = false;
 
   if (getLang().CPlusPlus0x &&
       (Tok.is(tok::kw_class) || Tok.is(tok::kw_struct))) {
     Diag(Tok, diag::warn_cxx98_compat_scoped_enum);
-    IsScopedEnum = true;
     IsScopedUsingClassTag = Tok.is(tok::kw_class);
-    ConsumeToken();
+    ScopedEnumKWLoc = ConsumeToken();
   }
   
   // If attributes exist after tag, parse them.
@@ -2913,11 +2925,11 @@
     NameLoc = ConsumeToken();
   }
 
-  if (!Name && IsScopedEnum) {
+  if (!Name && ScopedEnumKWLoc.isValid()) {
     // C++0x 7.2p2: The optional identifier shall not be omitted in the
     // declaration of a scoped enumeration.
     Diag(Tok, diag::err_scoped_enum_missing_identifier);
-    IsScopedEnum = false;
+    ScopedEnumKWLoc = SourceLocation();
     IsScopedUsingClassTag = false;
   }
 
@@ -2984,16 +2996,20 @@
     }
   }
 
-  // There are three options here.  If we have 'enum foo;', then this is a
-  // forward declaration.  If we have 'enum foo {...' then this is a
-  // definition. Otherwise we have something like 'enum foo xyz', a reference.
+  // There are four options here.  If we have 'friend enum foo;' then this is a
+  // friend declaration, and cannot have an accompanying definition. If we have
+  // 'enum foo;', then this is a forward declaration.  If we have
+  // 'enum foo {...' then this is a definition. Otherwise we have something
+  // like 'enum foo xyz', a reference.
   //
   // This is needed to handle stuff like this right (C99 6.7.2.3p11):
   // enum foo {..};  void bar() { enum foo; }    <- new foo in bar.
   // enum foo {..};  void bar() { enum foo x; }  <- use of old foo.
   //
   Sema::TagUseKind TUK;
-  if (Tok.is(tok::l_brace))
+  if (DS.isFriendSpecified())
+    TUK = Sema::TUK_Friend;
+  else if (Tok.is(tok::l_brace))
     TUK = Sema::TUK_Definition;
   else if (Tok.is(tok::semi))
     TUK = Sema::TUK_Declaration;
@@ -3027,7 +3043,7 @@
                                    StartLoc, SS, Name, NameLoc, attrs.getList(),
                                    AS, DS.getModulePrivateSpecLoc(),
                                    MultiTemplateParamsArg(Actions),
-                                   Owned, IsDependent, IsScopedEnum,
+                                   Owned, IsDependent, ScopedEnumKWLoc,
                                    IsScopedUsingClassTag, BaseType);
 
   if (IsDependent) {
@@ -3066,9 +3082,13 @@
     DS.SetTypeSpecError();
     return;
   }
-  
-  if (Tok.is(tok::l_brace))
+
+  if (Tok.is(tok::l_brace)) {
+    if (TUK == Sema::TUK_Friend)
+      Diag(Tok, diag::err_friend_decl_defines_type)
+        << SourceRange(DS.getFriendSpecLoc());
     ParseEnumBody(StartLoc, TagDecl);
+  }
 
   if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
                          NameLoc.isValid() ? NameLoc : StartLoc,
@@ -3341,7 +3361,7 @@
   case tok::kw_private:
     return getLang().OpenCL;
 
-  // C1x _Atomic()
+  // C11 _Atomic()
   case tok::kw__Atomic:
     return true;
   }
@@ -3465,7 +3485,7 @@
   case tok::annot_decltype:
     return true;
 
-    // C1x _Atomic()
+    // C11 _Atomic()
   case tok::kw__Atomic:
     return true;
 
@@ -4670,7 +4690,7 @@
     Diag(StartLoc, DiagID) << PrevSpec;
 }
 
-/// [C1X]   atomic-specifier:
+/// [C11]   atomic-specifier:
 ///           _Atomic ( type-name )
 ///
 void Parser::ParseAtomicSpecifier(DeclSpec &DS) {

Modified: cfe/branches/tooling/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Parse/ParseDeclCXX.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/branches/tooling/lib/Parse/ParseDeclCXX.cpp Fri Jan 20 10:14:22 2012
@@ -573,20 +573,20 @@
                                        IsTypeName, TypenameLoc);
 }
 
-/// ParseStaticAssertDeclaration - Parse C++0x or C1X static_assert-declaration.
+/// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration.
 ///
 /// [C++0x] static_assert-declaration:
 ///           static_assert ( constant-expression  ,  string-literal  ) ;
 ///
-/// [C1X]   static_assert-declaration:
+/// [C11]   static_assert-declaration:
 ///           _Static_assert ( constant-expression  ,  string-literal  ) ;
 ///
 Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
   assert((Tok.is(tok::kw_static_assert) || Tok.is(tok::kw__Static_assert)) &&
          "Not a static_assert declaration");
 
-  if (Tok.is(tok::kw__Static_assert) && !getLang().C1X)
-    Diag(Tok, diag::ext_c1x_static_assert);
+  if (Tok.is(tok::kw__Static_assert) && !getLang().C11)
+    Diag(Tok, diag::ext_c11_static_assert);
   if (Tok.is(tok::kw_static_assert))
     Diag(Tok, diag::warn_cxx98_compat_static_assert);
 
@@ -1115,7 +1115,7 @@
     if (DS.isFriendSpecified()) {
       // C++ [class.friend]p2:
       //   A class shall not be defined in a friend declaration.
-      Diag(Tok.getLocation(), diag::err_friend_decl_defines_class)
+      Diag(Tok.getLocation(), diag::err_friend_decl_defines_type)
         << SourceRange(DS.getFriendSpecLoc());
 
       // Skip everything up to the semicolon, so that this looks like a proper
@@ -1277,8 +1277,9 @@
     TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
                                        SS, Name, NameLoc, attrs.getList(), AS,
                                        DS.getModulePrivateSpecLoc(),
-                                       TParams, Owned, IsDependent, false,
-                                       false, clang::TypeResult());
+                                       TParams, Owned, IsDependent,
+                                       SourceLocation(), false,
+                                       clang::TypeResult());
 
     // If ActOnTag said the type was dependent, try again with the
     // less common call.
@@ -1548,13 +1549,13 @@
   }
 }
 
-/// isCXX0XVirtSpecifier - Determine whether the next token is a C++0x
+/// isCXX0XVirtSpecifier - Determine whether the given token is a C++0x
 /// virt-specifier.
 ///
 ///       virt-specifier:
 ///         override
 ///         final
-VirtSpecifiers::Specifier Parser::isCXX0XVirtSpecifier() const {
+VirtSpecifiers::Specifier Parser::isCXX0XVirtSpecifier(const Token &Tok) const {
   if (!getLang().CPlusPlus)
     return VirtSpecifiers::VS_None;
 
@@ -1896,6 +1897,7 @@
 
   SmallVector<Decl *, 8> DeclsInGroup;
   ExprResult BitfieldSize;
+  bool ExpectSemi = true;
 
   while (1) {
     // member-declarator:
@@ -2023,7 +2025,18 @@
       break;
 
     // Consume the comma.
-    ConsumeToken();
+    SourceLocation CommaLoc = ConsumeToken();
+
+    if (Tok.isAtStartOfLine() &&
+        !MightBeDeclarator(Declarator::MemberContext)) {
+      // This comma was followed by a line-break and something which can't be
+      // the start of a declarator. The comma was probably a typo for a
+      // semicolon.
+      Diag(CommaLoc, diag::err_expected_semi_declaration)
+        << FixItHint::CreateReplacement(CommaLoc, ";");
+      ExpectSemi = false;
+      break;
+    }
 
     // Parse the next declarator.
     DeclaratorInfo.clear();
@@ -2031,6 +2044,7 @@
     BitfieldSize = true;
     Init = true;
     HasInitializer = false;
+    DeclaratorInfo.setCommaLoc(CommaLoc);
 
     // Attributes are only allowed on the second declarator.
     MaybeParseGNUAttributes(DeclaratorInfo);
@@ -2039,7 +2053,8 @@
       ParseDeclarator(DeclaratorInfo);
   }
 
-  if (ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) {
+  if (ExpectSemi &&
+      ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) {
     // Skip to end of block or statement.
     SkipUntil(tok::r_brace, true, true);
     // If we stopped at a ';', eat it.

Modified: cfe/branches/tooling/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Parse/ParseExpr.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Parse/ParseExpr.cpp (original)
+++ cfe/branches/tooling/lib/Parse/ParseExpr.cpp Fri Jan 20 10:14:22 2012
@@ -247,11 +247,12 @@
 
 
 ExprResult Parser::ParseConstantExpression() {
-  // C++ [basic.def.odr]p2:
+  // C++03 [basic.def.odr]p2:
   //   An expression is potentially evaluated unless it appears where an
   //   integral constant expression is required (see 5.19) [...].
+  // C++98 and C++11 have no such rule, but this is only a defect in C++98.
   EnterExpressionEvaluationContext Unevaluated(Actions,
-                                               Sema::Unevaluated);
+                                               Sema::ConstantEvaluated);
 
   ExprResult LHS(ParseCastExpression(false));
   return ParseRHSOfBinaryExpression(LHS, prec::Conditional);
@@ -311,8 +312,8 @@
         SourceLocation FILoc = Tok.getLocation();
         const char *FIText = ": ";
         const SourceManager &SM = PP.getSourceManager();
-        if (FILoc.isFileID() || PP.isAtStartOfMacroExpansion(FILoc)) {
-          FILoc = SM.getExpansionLoc(FILoc);
+        if (FILoc.isFileID() || PP.isAtStartOfMacroExpansion(FILoc, &FILoc)) {
+          assert(FILoc.isFileID());
           bool IsInvalid = false;
           const char *SourcePtr =
             SM.getCharacterData(FILoc.getLocWithOffset(-1), &IsInvalid);
@@ -465,7 +466,7 @@
 /// [C++]   boolean-literal  [C++ 2.13.5]
 /// [C++0x] 'nullptr'        [C++0x 2.14.7]
 ///         '(' expression ')'
-/// [C1X]   generic-selection
+/// [C11]   generic-selection
 ///         '__func__'        [C99 6.4.2.2]
 /// [GNU]   '__FUNCTION__'
 /// [GNU]   '__PRETTY_FUNCTION__'
@@ -677,7 +678,8 @@
       if (Next.is(tok::coloncolon) ||
           (!ColonIsSacred && Next.is(tok::colon)) ||
           Next.is(tok::less) ||
-          Next.is(tok::l_paren)) {
+          Next.is(tok::l_paren) ||
+          Next.is(tok::l_brace)) {
         // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
         if (TryAnnotateTypeOrScopeToken())
           return ExprError();
@@ -792,7 +794,7 @@
   case tok::utf32_string_literal:
     Res = ParseStringLiteralExpression();
     break;
-  case tok::kw__Generic:   // primary-expression: generic-selection [C1X 6.5.1]
+  case tok::kw__Generic:   // primary-expression: generic-selection [C11 6.5.1]
     Res = ParseGenericSelectionExpression();
     break;
   case tok::kw___builtin_va_arg:
@@ -1041,7 +1043,7 @@
 
     if (T.expectAndConsume(diag::err_expected_lparen_after, "noexcept"))
       return ExprError();
-    // C++ [expr.unary.noexcept]p1:
+    // C++11 [expr.unary.noexcept]p1:
     //   The noexcept operator determines whether the evaluation of its operand,
     //   which is an unevaluated operand, can throw an exception.
     EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
@@ -1130,8 +1132,13 @@
   case tok::l_square:
     if (getLang().CPlusPlus0x) {
       if (getLang().ObjC1) {
+        // C++11 lambda expressions and Objective-C message sends both start with a
+        // square bracket.  There are three possibilities here:
+        // we have a valid lambda expression, we have an invalid lambda
+        // expression, or we have something that doesn't appear to be a lambda.
+        // If we're in the last case, we fall back to ParseObjCMessageExpression.
         Res = TryParseLambdaExpression();
-        if (Res.isInvalid())
+        if (!Res.isInvalid() && !Res.get())
           Res = ParseObjCMessageExpression();
         break;
       }
@@ -1439,8 +1446,8 @@
     //   [...] The operand is either an expression, which is an unevaluated
     //   operand (Clause 5) [...]
     //
-    // The GNU typeof and alignof extensions also behave as unevaluated
-    // operands.
+    // The GNU typeof and GNU/C++11 alignof extensions also behave as
+    // unevaluated operands.
     EnterExpressionEvaluationContext Unevaluated(Actions,
                                                  Sema::Unevaluated);
     Operand = ParseCastExpression(true/*isUnaryExpression*/);
@@ -1456,8 +1463,8 @@
     //   [...] The operand is either an expression, which is an unevaluated
     //   operand (Clause 5) [...]
     //
-    // The GNU typeof and alignof extensions also behave as unevaluated
-    // operands.
+    // The GNU typeof and GNU/C++11 alignof extensions also behave as
+    // unevaluated operands.
     EnterExpressionEvaluationContext Unevaluated(Actions,
                                                  Sema::Unevaluated);
     Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/, 
@@ -1817,9 +1824,24 @@
     return ExprError();
   }
 
+  // Diagnose use of bridge casts in non-arc mode.
+  bool BridgeCast = (getLang().ObjC2 &&
+                     (Tok.is(tok::kw___bridge) || 
+                      Tok.is(tok::kw___bridge_transfer) ||
+                      Tok.is(tok::kw___bridge_retained) ||
+                      Tok.is(tok::kw___bridge_retain)));
+  if (BridgeCast && !getLang().ObjCAutoRefCount) {
+    StringRef BridgeCastName = Tok.getName();
+    SourceLocation BridgeKeywordLoc = ConsumeToken();
+    if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc))
+      Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_nonarc)
+        << BridgeCastName
+        << FixItHint::CreateReplacement(BridgeKeywordLoc, "");
+    BridgeCast = false;
+  }
+  
   // None of these cases should fall through with an invalid Result
   // unless they've already reported an error.
-  
   if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
     Diag(Tok, diag::ext_gnu_statement_expr);
     ParsedAttributes attrs(AttrFactory);
@@ -1829,11 +1851,7 @@
     // If the substmt parsed correctly, build the AST node.
     if (!Stmt.isInvalid())
       Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.take(), Tok.getLocation());
-  } else if (ExprType >= CompoundLiteral && 
-             (Tok.is(tok::kw___bridge) || 
-              Tok.is(tok::kw___bridge_transfer) ||
-              Tok.is(tok::kw___bridge_retained) ||
-              Tok.is(tok::kw___bridge_retain))) {
+  } else if (ExprType >= CompoundLiteral && BridgeCast) {
     tok::TokenKind tokenKind = Tok.getKind();
     SourceLocation BridgeKeywordLoc = ConsumeToken();
 
@@ -2037,8 +2055,8 @@
   return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size());
 }
 
-/// ParseGenericSelectionExpression - Parse a C1X generic-selection
-/// [C1X 6.5.1.1].
+/// ParseGenericSelectionExpression - Parse a C11 generic-selection
+/// [C11 6.5.1.1].
 ///
 ///    generic-selection:
 ///           _Generic ( assignment-expression , generic-assoc-list )
@@ -2052,8 +2070,8 @@
   assert(Tok.is(tok::kw__Generic) && "_Generic keyword expected");
   SourceLocation KeyLoc = ConsumeToken();
 
-  if (!getLang().C1X)
-    Diag(KeyLoc, diag::ext_c1x_generic_selection);
+  if (!getLang().C11)
+    Diag(KeyLoc, diag::ext_c11_generic_selection);
 
   BalancedDelimiterTracker T(*this, tok::l_paren);
   if (T.expectAndConsume(diag::err_expected_lparen))
@@ -2061,7 +2079,7 @@
 
   ExprResult ControllingExpr;
   {
-    // C1X 6.5.1.1p3 "The controlling expression of a generic selection is
+    // C11 6.5.1.1p3 "The controlling expression of a generic selection is
     // not evaluated."
     EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
     ControllingExpr = ParseAssignmentExpression();
@@ -2082,7 +2100,7 @@
   while (1) {
     ParsedType Ty;
     if (Tok.is(tok::kw_default)) {
-      // C1X 6.5.1.1p2 "A generic selection shall have no more than one default
+      // C11 6.5.1.1p2 "A generic selection shall have no more than one default
       // generic association."
       if (!DefaultLoc.isInvalid()) {
         Diag(Tok, diag::err_duplicate_default_assoc);

Modified: cfe/branches/tooling/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Parse/ParseExprCXX.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/branches/tooling/lib/Parse/ParseExprCXX.cpp Fri Jan 20 10:14:22 2012
@@ -14,6 +14,7 @@
 #include "clang/Parse/ParseDiagnostic.h"
 #include "clang/Parse/Parser.h"
 #include "RAIIObjectsForParser.h"
+#include "clang/Basic/PrettyStackTrace.h"
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/ParsedTemplate.h"
@@ -563,6 +564,9 @@
   if (DiagID) {
     Diag(Tok, DiagID.getValue());
     SkipUntil(tok::r_square);
+    SkipUntil(tok::l_brace);
+    SkipUntil(tok::r_brace);
+    return ExprError();
   }
 
   return ParseLambdaExpressionAfterIntroducer(Intro);
@@ -591,14 +595,21 @@
     return ParseLambdaExpression();
   }
 
-  // If lookahead indicates this is an Objective-C message...
+  // If lookahead indicates an ObjC message send...
+  // [identifier identifier
   if (Next.is(tok::identifier) && After.is(tok::identifier)) {
-    return ExprError();
+    return ExprEmpty();
   }
 
+  // Here, we're stuck: lambda introducers and Objective-C message sends are
+  // unambiguous, but it requires arbitrary lookhead.  [a,b,c,d,e,f,g] is a
+  // lambda, and [a,b,c,d,e,f,g h] is a Objective-C message send.  Instead of
+  // writing two routines to parse a lambda introducer, just try to parse
+  // a lambda introducer first, and fall back if that fails.
+  // (TryParseLambdaIntroducer never produces any diagnostic output.)
   LambdaIntroducer Intro;
   if (TryParseLambdaIntroducer(Intro))
-    return ExprError();
+    return ExprEmpty();
   return ParseLambdaExpressionAfterIntroducer(Intro);
 }
 
@@ -694,11 +705,15 @@
 /// expression.
 ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
                      LambdaIntroducer &Intro) {
-  Diag(Intro.Range.getBegin(), diag::warn_cxx98_compat_lambda);
+  SourceLocation LambdaBeginLoc = Intro.Range.getBegin();
+  Diag(LambdaBeginLoc, diag::warn_cxx98_compat_lambda);
+
+  PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc,
+                                "lambda expression parsing");
 
   // Parse lambda-declarator[opt].
   DeclSpec DS(AttrFactory);
-  Declarator D(DS, Declarator::PrototypeContext);
+  Declarator D(DS, Declarator::LambdaExprContext);
 
   if (Tok.is(tok::l_paren)) {
     ParseScope PrototypeScope(this,
@@ -777,22 +792,30 @@
                   Attr, DeclEndLoc);
   }
 
-  // Parse compound-statement.
-  if (Tok.is(tok::l_brace)) {
-    // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
-    // it.
-    ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope |
-                               Scope::BreakScope | Scope::ContinueScope |
-                               Scope::DeclScope);
+  // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
+  // it.
+  ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope |
+                             Scope::BreakScope | Scope::ContinueScope |
+                             Scope::DeclScope);
 
-    StmtResult Stmt(ParseCompoundStatementBody());
+  Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope());
 
-    BodyScope.Exit();
-  } else {
+  // Parse compound-statement.
+  if (!Tok.is(tok::l_brace)) {
     Diag(Tok, diag::err_expected_lambda_body);
+    Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope());
+    return ExprError();
   }
 
-  return ExprEmpty();
+  StmtResult Stmt(ParseCompoundStatementBody());
+  BodyScope.Exit();
+
+  if (!Stmt.isInvalid())
+    return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.take(),
+                                   getCurScope());
+ 
+  Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope());
+  return ExprError();
 }
 
 /// ParseCXXCasts - This handles the various ways to cast expressions to another
@@ -901,10 +924,10 @@
     //   operand (Clause 5).
     //
     // Note that we can't tell whether the expression is an lvalue of a
-    // polymorphic class type until after we've parsed the expression, so
-    // we the expression is potentially potentially evaluated.
-    EnterExpressionEvaluationContext Unevaluated(Actions,
-                                       Sema::PotentiallyPotentiallyEvaluated);
+    // polymorphic class type until after we've parsed the expression; we
+    // speculatively assume the subexpression is unevaluated, and fix it up
+    // later.
+    EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
     Result = ParseExpression();
 
     // Match the ')'.
@@ -1022,7 +1045,7 @@
 
   if (Tok.is(tok::kw_decltype) && !FirstTypeName.isValid() && SS.isEmpty()) {
     DeclSpec DS(AttrFactory);
-    SourceLocation EndLoc = ParseDecltypeSpecifier(DS);
+    ParseDecltypeSpecifier(DS);
     if (DS.getTypeSpecType() == TST_error)
       return ExprError();
     return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, 
@@ -1236,8 +1259,8 @@
   ExprOut = ExprError();
 
   // '=' assignment-expression
-  if (isTokenEqualOrMistypedEqualEqual(
-                               diag::err_invalid_equalequal_after_declarator)) {
+  // If a '==' or '+=' is found, suggest a fixit to '='.
+  if (isTokenEqualOrEqualTypo()) {
     ConsumeToken();
     ExprResult AssignExpr(ParseAssignmentExpression());
     if (!AssignExpr.isInvalid()) 
@@ -2440,8 +2463,6 @@
     return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), DimExpr.get(),
                                        T.getCloseLocation());
   }
-  default:
-    break;
   }
   return ExprError();
 }

Modified: cfe/branches/tooling/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Parse/ParseObjc.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Parse/ParseObjc.cpp (original)
+++ cfe/branches/tooling/lib/Parse/ParseObjc.cpp Fri Jan 20 10:14:22 2012
@@ -42,7 +42,6 @@
   switch (Tok.getObjCKeywordID()) {
   case tok::objc_class:
     return ParseObjCAtClassDeclaration(AtLoc);
-    break;
   case tok::objc_interface: {
     ParsedAttributes attrs(AttrFactory);
     SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, attrs);
@@ -50,15 +49,13 @@
   }
   case tok::objc_protocol: {
     ParsedAttributes attrs(AttrFactory);
-    SingleDecl = ParseObjCAtProtocolDeclaration(AtLoc, attrs);
-    break;
+    return ParseObjCAtProtocolDeclaration(AtLoc, attrs);
   }
   case tok::objc_implementation:
     SingleDecl = ParseObjCAtImplementationDeclaration(AtLoc);
     break;
   case tok::objc_end:
     return ParseObjCAtEndDeclaration(AtLoc);
-    break;
   case tok::objc_compatibility_alias:
     SingleDecl = ParseObjCAtAliasDeclaration(AtLoc);
     break;
@@ -68,6 +65,12 @@
   case tok::objc_dynamic:
     SingleDecl = ParseObjCPropertyDynamic(AtLoc);
     break;
+  case tok::objc_import:
+    if (getLang().Modules)
+      return ParseModuleImport(AtLoc);
+      
+    // Fall through
+      
   default:
     Diag(AtLoc, diag::err_unexpected_at);
     SkipUntil(tok::semi);
@@ -284,6 +287,9 @@
 /// The Objective-C property callback.  This should be defined where
 /// it's used, but instead it's been lifted to here to support VS2005.
 struct Parser::ObjCPropertyCallback : FieldCallback {
+private:
+  virtual void anchor();
+public:
   Parser &P;
   SmallVectorImpl<Decl *> &Props;
   ObjCDeclSpec &OCDS;
@@ -337,6 +343,9 @@
   }
 };
 
+void Parser::ObjCPropertyCallback::anchor() {
+}
+
 ///   objc-interface-decl-list:
 ///     empty
 ///     objc-interface-decl-list objc-property-decl [OBJC2]
@@ -416,7 +425,6 @@
     if (Tok.is(tok::code_completion)) {
       Actions.CodeCompleteObjCAtDirective(getCurScope());
       return cutOffParsing();
-      break;
     }
 
     tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
@@ -1343,8 +1351,9 @@
 ///   "@protocol identifier ;" should be resolved as "@protocol
 ///   identifier-list ;": objc-interface-decl-list may not start with a
 ///   semicolon in the first alternative if objc-protocol-refs are omitted.
-Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
-                                             ParsedAttributes &attrs) {
+Parser::DeclGroupPtrTy 
+Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
+                                       ParsedAttributes &attrs) {
   assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
          "ParseObjCAtProtocolDeclaration(): Expected @protocol");
   ConsumeToken(); // the "protocol" identifier
@@ -1352,12 +1361,12 @@
   if (Tok.is(tok::code_completion)) {
     Actions.CodeCompleteObjCProtocolDecl(getCurScope());
     cutOffParsing();
-    return 0;
+    return DeclGroupPtrTy();
   }
 
   if (Tok.isNot(tok::identifier)) {
     Diag(Tok, diag::err_expected_ident); // missing protocol name.
-    return 0;
+    return DeclGroupPtrTy();
   }
   // Save the protocol name, then consume it.
   IdentifierInfo *protocolName = Tok.getIdentifierInfo();
@@ -1382,7 +1391,7 @@
       if (Tok.isNot(tok::identifier)) {
         Diag(Tok, diag::err_expected_ident);
         SkipUntil(tok::semi);
-        return 0;
+        return DeclGroupPtrTy();
       }
       ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
                                                Tok.getLocation()));
@@ -1393,7 +1402,7 @@
     }
     // Consume the ';'.
     if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
-      return 0;
+      return DeclGroupPtrTy();
 
     return Actions.ActOnForwardProtocolDeclaration(AtLoc,
                                                    &ProtocolRefs[0],
@@ -1409,7 +1418,7 @@
   if (Tok.is(tok::less) &&
       ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false,
                                   LAngleLoc, EndProtoLoc))
-    return 0;
+    return DeclGroupPtrTy();
 
   Decl *ProtoType =
     Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
@@ -1419,7 +1428,7 @@
                                         EndProtoLoc, attrs.getList());
 
   ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType);
-  return ProtoType;
+  return Actions.ConvertDeclToDeclGroup(ProtoType);
 }
 
 ///   objc-implementation:

Modified: cfe/branches/tooling/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Parse/ParseStmt.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Parse/ParseStmt.cpp (original)
+++ cfe/branches/tooling/lib/Parse/ParseStmt.cpp Fri Jan 20 10:14:22 2012
@@ -76,7 +76,8 @@
 /// [OBC]   '@' 'throw' ';'
 ///
 StmtResult
-Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) {
+Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
+                                    SourceLocation *TrailingElseLoc) {
   const char *SemiError = 0;
   StmtResult Res;
 
@@ -234,18 +235,18 @@
   }
 
   case tok::kw_if:                  // C99 6.8.4.1: if-statement
-    return ParseIfStatement(attrs);
+    return ParseIfStatement(attrs, TrailingElseLoc);
   case tok::kw_switch:              // C99 6.8.4.2: switch-statement
-    return ParseSwitchStatement(attrs);
+    return ParseSwitchStatement(attrs, TrailingElseLoc);
 
   case tok::kw_while:               // C99 6.8.5.1: while-statement
-    return ParseWhileStatement(attrs);
+    return ParseWhileStatement(attrs, TrailingElseLoc);
   case tok::kw_do:                  // C99 6.8.5.2: do-statement
     Res = ParseDoStatement(attrs);
     SemiError = "do/while";
     break;
   case tok::kw_for:                 // C99 6.8.5.3: for-statement
-    return ParseForStatement(attrs);
+    return ParseForStatement(attrs, TrailingElseLoc);
 
   case tok::kw_goto:                // C99 6.8.6.1: goto-statement
     Res = ParseGotoStatement(attrs);
@@ -874,7 +875,8 @@
 /// [C++]   'if' '(' condition ')' statement
 /// [C++]   'if' '(' condition ')' statement 'else' statement
 ///
-StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) {
+StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs,
+                                    SourceLocation *TrailingElseLoc) {
   // FIXME: Use attributes?
 
   assert(Tok.is(tok::kw_if) && "Not an if stmt!");
@@ -933,7 +935,9 @@
 
   // Read the 'then' stmt.
   SourceLocation ThenStmtLoc = Tok.getLocation();
-  StmtResult ThenStmt(ParseStatement());
+
+  SourceLocation InnerStatementTrailingElseLoc;
+  StmtResult ThenStmt(ParseStatement(&InnerStatementTrailingElseLoc));
 
   // Pop the 'if' scope if needed.
   InnerScope.Exit();
@@ -944,6 +948,9 @@
   StmtResult ElseStmt;
 
   if (Tok.is(tok::kw_else)) {
+    if (TrailingElseLoc)
+      *TrailingElseLoc = Tok.getLocation();
+
     ElseLoc = ConsumeToken();
     ElseStmtLoc = Tok.getLocation();
 
@@ -967,6 +974,8 @@
     Actions.CodeCompleteAfterIf(getCurScope());
     cutOffParsing();
     return StmtError();
+  } else if (InnerStatementTrailingElseLoc.isValid()) {
+    Diag(InnerStatementTrailingElseLoc, diag::warn_dangling_else);
   }
 
   IfScope.Exit();
@@ -1000,7 +1009,8 @@
 ///       switch-statement:
 ///         'switch' '(' expression ')' statement
 /// [C++]   'switch' '(' condition ')' statement
-StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) {
+StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs,
+                                        SourceLocation *TrailingElseLoc) {
   // FIXME: Use attributes?
 
   assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
@@ -1068,7 +1078,7 @@
                         C99orCXX && Tok.isNot(tok::l_brace));
 
   // Read the body statement.
-  StmtResult Body(ParseStatement());
+  StmtResult Body(ParseStatement(TrailingElseLoc));
 
   // Pop the scopes.
   InnerScope.Exit();
@@ -1085,7 +1095,8 @@
 ///       while-statement: [C99 6.8.5.1]
 ///         'while' '(' expression ')' statement
 /// [C++]   'while' '(' condition ')' statement
-StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs) {
+StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs,
+                                       SourceLocation *TrailingElseLoc) {
   // FIXME: Use attributes?
 
   assert(Tok.is(tok::kw_while) && "Not a while stmt!");
@@ -1143,7 +1154,7 @@
                         C99orCXX && Tok.isNot(tok::l_brace));
 
   // Read the body statement.
-  StmtResult Body(ParseStatement());
+  StmtResult Body(ParseStatement(TrailingElseLoc));
 
   // Pop the body scope if needed.
   InnerScope.Exit();
@@ -1242,7 +1253,8 @@
 /// [C++0x] for-range-initializer:
 /// [C++0x]   expression
 /// [C++0x]   braced-init-list            [TODO]
-StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) {
+StmtResult Parser::ParseForStatement(ParsedAttributes &attrs,
+                                     SourceLocation *TrailingElseLoc) {
   // FIXME: Use attributes?
 
   assert(Tok.is(tok::kw_for) && "Not a for stmt!");
@@ -1306,7 +1318,7 @@
   if (Tok.is(tok::semi)) {  // for (;
     // no first part, eat the ';'.
     ConsumeToken();
-  } else if (isSimpleDeclaration()) {  // for (int X = 4;
+  } else if (isForInitDeclaration()) {  // for (int X = 4;
     // Parse declaration, which eats the ';'.
     if (!C99orCXXorObjC)   // Use of C99-style for loops in C90 mode?
       Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
@@ -1371,6 +1383,14 @@
         return StmtError();
       }
       Collection = ParseExpression();
+    } else if (getLang().CPlusPlus0x && Tok.is(tok::colon) &&
+               !FirstPart.isInvalid()) {
+      // User tried to write the reasonable, but ill-formed, for-range-statement
+      //   for (expr : expr) { ... }
+      Diag(Tok, diag::err_for_range_expected_decl)
+        << FirstPart.get()->getSourceRange();
+      SkipUntil(tok::r_paren, false, true);
+      SecondPartIsInvalid = true;
     } else {
       if (!Value.isInvalid()) {
         Diag(Tok, diag::err_expected_semi_for);
@@ -1459,7 +1479,7 @@
                         C99orCXXorObjC && Tok.isNot(tok::l_brace));
 
   // Read the body statement.
-  StmtResult Body(ParseStatement());
+  StmtResult Body(ParseStatement(TrailingElseLoc));
 
   // Pop the body scope if needed.
   InnerScope.Exit();
@@ -1914,8 +1934,6 @@
     if (Tok.isNot(tok::comma)) return false;
     ConsumeToken();
   }
-
-  return true;
 }
 
 Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
@@ -2183,7 +2201,6 @@
       
   case IEB_Dependent:
     llvm_unreachable("Dependent case handled above");
-    break;
       
   case IEB_Skip:
     Braces.skipToEnd();

Modified: cfe/branches/tooling/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Parse/ParseTemplate.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/branches/tooling/lib/Parse/ParseTemplate.cpp Fri Jan 20 10:14:22 2012
@@ -31,8 +31,9 @@
   ObjCDeclContextSwitch ObjCDC(*this);
   
   if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) {
-    return ParseExplicitInstantiation(SourceLocation(), ConsumeToken(),
-                                           DeclEnd);
+    return ParseExplicitInstantiation(Context,
+                                      SourceLocation(), ConsumeToken(),
+                                      DeclEnd, AS);
   }
   return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS,
                                                   AccessAttrs);
@@ -1107,17 +1108,19 @@
 ///         'extern' [opt] 'template' declaration
 ///
 /// Note that the 'extern' is a GNU extension and C++0x feature.
-Decl *Parser::ParseExplicitInstantiation(SourceLocation ExternLoc,
+Decl *Parser::ParseExplicitInstantiation(unsigned Context,
+                                         SourceLocation ExternLoc,
                                          SourceLocation TemplateLoc,
-                                         SourceLocation &DeclEnd) {
+                                         SourceLocation &DeclEnd,
+                                         AccessSpecifier AS) {
   // This isn't really required here.
   ParsingDeclRAIIObject ParsingTemplateParams(*this);
 
-  return ParseSingleDeclarationAfterTemplate(Declarator::FileContext,
+  return ParseSingleDeclarationAfterTemplate(Context,
                                              ParsedTemplateInfo(ExternLoc,
                                                                 TemplateLoc),
                                              ParsingTemplateParams,
-                                             DeclEnd, AS_none);
+                                             DeclEnd, AS);
 }
 
 SourceRange Parser::ParsedTemplateInfo::getSourceRange() const {

Modified: cfe/branches/tooling/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Parse/ParseTentative.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Parse/ParseTentative.cpp (original)
+++ cfe/branches/tooling/lib/Parse/ParseTentative.cpp Fri Jan 20 10:14:22 2012
@@ -62,7 +62,7 @@
     return true;
     // simple-declaration
   default:
-    return isCXXSimpleDeclaration();
+    return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);
   }
 }
 
@@ -75,7 +75,11 @@
 /// simple-declaration:
 ///   decl-specifier-seq init-declarator-list[opt] ';'
 ///
-bool Parser::isCXXSimpleDeclaration() {
+/// (if AllowForRangeDecl specified)
+/// for ( for-range-declaration : for-range-initializer ) statement
+/// for-range-declaration: 
+///    attribute-specifier-seqopt type-specifier-seq declarator
+bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
   // C++ 6.8p1:
   // There is an ambiguity in the grammar involving expression-statements and
   // declarations: An expression-statement with a function-style explicit type
@@ -112,7 +116,7 @@
   // We need tentative parsing...
 
   TentativeParsingAction PA(*this);
-  TPR = TryParseSimpleDeclaration();
+  TPR = TryParseSimpleDeclaration(AllowForRangeDecl);
   PA.Revert();
 
   // In case of an error, let the declaration parsing code handle it.
@@ -130,7 +134,12 @@
 /// simple-declaration:
 ///   decl-specifier-seq init-declarator-list[opt] ';'
 ///
-Parser::TPResult Parser::TryParseSimpleDeclaration() {
+/// (if AllowForRangeDecl specified)
+/// for ( for-range-declaration : for-range-initializer ) statement
+/// for-range-declaration: 
+///    attribute-specifier-seqopt type-specifier-seq declarator
+///
+Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
   // We know that we have a simple-type-specifier/typename-specifier followed
   // by a '('.
   assert(isCXXDeclarationSpecifier() == TPResult::Ambiguous());
@@ -150,7 +159,7 @@
   if (TPR != TPResult::Ambiguous())
     return TPR;
 
-  if (Tok.isNot(tok::semi))
+  if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon)))
     return TPResult::False();
 
   return TPResult::Ambiguous();
@@ -1037,7 +1046,7 @@
   case tok::kw___underlying_type:
     return TPResult::True();
 
-  // C1x _Atomic
+  // C11 _Atomic
   case tok::kw__Atomic:
     return TPResult::True();
 

Modified: cfe/branches/tooling/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Parse/Parser.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Parse/Parser.cpp (original)
+++ cfe/branches/tooling/lib/Parse/Parser.cpp Fri Jan 20 10:14:22 2012
@@ -552,7 +552,7 @@
     // TODO: Invoke action for top-level semicolon.
     return DeclGroupPtrTy();
   case tok::r_brace:
-    Diag(Tok, diag::err_expected_external_declaration);
+    Diag(Tok, diag::err_extraneous_closing_brace);
     ConsumeBrace();
     return DeclGroupPtrTy();
   case tok::eof:
@@ -581,7 +581,6 @@
   }
   case tok::at:
     return ParseObjCAtDirectives();
-    break;
   case tok::minus:
   case tok::plus:
     if (!getLang().ObjC1) {
@@ -656,7 +655,8 @@
              diag::ext_extern_template) << SourceRange(ExternLoc, TemplateLoc);
       SourceLocation DeclEnd;
       return Actions.ConvertDeclToDeclGroup(
-                  ParseExplicitInstantiation(ExternLoc, TemplateLoc, DeclEnd));
+                  ParseExplicitInstantiation(Declarator::FileContext,
+                                             ExternLoc, TemplateLoc, DeclEnd));
     }
     // FIXME: Detect C++ linkage specifications here?
     goto dont_know;
@@ -665,9 +665,6 @@
   case tok::kw___if_not_exists:
     ParseMicrosoftIfExistsExternalDeclaration();
     return DeclGroupPtrTy();
-
-  case tok::kw___import_module__:
-    return ParseModuleImport();
       
   default:
   dont_know:
@@ -775,12 +772,11 @@
     if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID))
       Diag(AtLoc, DiagID) << PrevSpec;
 
-    Decl *TheDecl = 0;
     if (Tok.isObjCAtKeyword(tok::objc_protocol))
-      TheDecl = ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes());
-    else
-      TheDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes());
-    return Actions.ConvertDeclToDeclGroup(TheDecl);
+      return ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes());
+
+    return Actions.ConvertDeclToDeclGroup(
+            ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes()));
   }
 
   // If the declspec consisted only of 'extern' and we have a string
@@ -932,7 +928,7 @@
     if (Tok.is(tok::kw_delete)) {
       Diag(Tok, getLang().CPlusPlus0x ?
            diag::warn_cxx98_compat_deleted_function :
-           diag::warn_deleted_function_accepted_as_extension);
+           diag::ext_deleted_function);
 
       KWLoc = ConsumeToken();
       Actions.SetDeclDeleted(Res, KWLoc);
@@ -940,7 +936,7 @@
     } else if (Tok.is(tok::kw_default)) {
       Diag(Tok, getLang().CPlusPlus0x ?
            diag::warn_cxx98_compat_defaulted_function :
-           diag::warn_defaulted_function_accepted_as_extension);
+           diag::ext_defaulted_function);
 
       KWLoc = ConsumeToken();
       Actions.SetDeclDefaulted(Res, KWLoc);
@@ -1070,11 +1066,12 @@
       if (Tok.isNot(tok::comma))
         break;
 
+      ParmDeclarator.clear();
+
       // Consume the comma.
-      ConsumeToken();
+      ParmDeclarator.setCommaLoc(ConsumeToken());
 
       // Parse the next declarator.
-      ParmDeclarator.clear();
       ParseDeclarator(ParmDeclarator);
     }
 
@@ -1404,18 +1401,31 @@
   return false;
 }
 
-bool Parser::isTokenEqualOrMistypedEqualEqual(unsigned DiagID) {
-  if (Tok.is(tok::equalequal)) {
-    // We have '==' in a context that we would expect a '='.
-    // The user probably made a typo, intending to type '='. Emit diagnostic,
-    // fixit hint to turn '==' -> '=' and continue as if the user typed '='.
-    Diag(Tok, DiagID)
-      << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()),
-                                      getTokenSimpleSpelling(tok::equal));
+bool Parser::isTokenEqualOrEqualTypo() {
+  tok::TokenKind Kind = Tok.getKind();
+  switch (Kind) {
+  default:
+    return false;
+  case tok::ampequal:            // &=
+  case tok::starequal:           // *=
+  case tok::plusequal:           // +=
+  case tok::minusequal:          // -=
+  case tok::exclaimequal:        // !=
+  case tok::slashequal:          // /=
+  case tok::percentequal:        // %=
+  case tok::lessequal:           // <=
+  case tok::lesslessequal:       // <<=
+  case tok::greaterequal:        // >=
+  case tok::greatergreaterequal: // >>=
+  case tok::caretequal:          // ^=
+  case tok::pipeequal:           // |=
+  case tok::equalequal:          // ==
+    Diag(Tok, diag::err_invalid_token_after_declarator_suggest_equal)
+      << getTokenSimpleSpelling(Kind)
+      << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "=");
+  case tok::equal:
     return true;
   }
-
-  return Tok.is(tok::equal);
 }
 
 SourceLocation Parser::handleUnexpectedCodeCompletionToken() {
@@ -1569,8 +1579,8 @@
   Braces.consumeClose();
 }
 
-Parser::DeclGroupPtrTy Parser::ParseModuleImport() {
-  assert(Tok.is(tok::kw___import_module__) && 
+Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
+  assert(Tok.isObjCAtKeyword(tok::objc_import) && 
          "Improper start to module import");
   SourceLocation ImportLoc = ConsumeToken();
   
@@ -1596,7 +1606,7 @@
     break;
   } while (true);
   
-  DeclResult Import = Actions.ActOnModuleImport(ImportLoc, Path);
+  DeclResult Import = Actions.ActOnModuleImport(AtLoc, ImportLoc, Path);
   ExpectAndConsumeSemi(diag::err_module_expected_semi);
   if (Import.isInvalid())
     return DeclGroupPtrTy();

Modified: cfe/branches/tooling/lib/Rewrite/HTMLRewrite.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Rewrite/HTMLRewrite.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Rewrite/HTMLRewrite.cpp (original)
+++ cfe/branches/tooling/lib/Rewrite/HTMLRewrite.cpp Fri Jan 20 10:14:22 2012
@@ -381,7 +381,6 @@
     default: break;
     case tok::identifier:
       llvm_unreachable("tok::identifier in raw lexing mode!");
-      break;
     case tok::raw_identifier: {
       // Fill in Result.IdentifierInfo and update the token kind,
       // looking up the identifier in the identifier table.

Modified: cfe/branches/tooling/lib/Rewrite/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Rewrite/RewriteObjC.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Rewrite/RewriteObjC.cpp (original)
+++ cfe/branches/tooling/lib/Rewrite/RewriteObjC.cpp Fri Jan 20 10:14:22 2012
@@ -165,10 +165,20 @@
     // Top Level Driver code.
     virtual bool HandleTopLevelDecl(DeclGroupRef D) {
       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
-        if (isa<ObjCClassDecl>((*I))) {
-          RewriteForwardClassDecl(D);
-          break;
+        if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {
+          if (!Class->isThisDeclarationADefinition()) {
+            RewriteForwardClassDecl(D);
+            break;
+          }
+        }
+
+        if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {
+          if (!Proto->isThisDeclarationADefinition()) {
+            RewriteForwardProtocolDecl(D);
+            break;
+          }
         }
+
         HandleTopLevelSingleDecl(*I);
       }
       return true;
@@ -256,7 +266,7 @@
     void RewriteInclude();
     void RewriteForwardClassDecl(DeclGroupRef D);
     void RewriteForwardClassDecl(const llvm::SmallVector<Decl*, 8> &DG);
-    void RewriteForwardClassEpilogue(ObjCClassDecl *ClassDecl, 
+    void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 
                                      const std::string &typedefString);
     void RewriteImplementations();
     void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
@@ -272,7 +282,8 @@
                             ValueDecl *VD, bool def=false);
     void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
     void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
-    void RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *Dcl);
+    void RewriteForwardProtocolDecl(DeclGroupRef D);
+    void RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG);
     void RewriteMethodDeclaration(ObjCMethodDecl *Method);
     void RewriteProperty(ObjCPropertyDecl *prop);
     void RewriteFunctionDecl(FunctionDecl *FD);
@@ -659,37 +670,51 @@
   } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
     RewriteCategoryDecl(CD);
   } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
-    RewriteProtocolDecl(PD);
-  } else if (ObjCForwardProtocolDecl *FP =
-             dyn_cast<ObjCForwardProtocolDecl>(D)){
-    RewriteForwardProtocolDecl(FP);
+    if (PD->isThisDeclarationADefinition())
+      RewriteProtocolDecl(PD);
   } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
     // Recurse into linkage specifications
     for (DeclContext::decl_iterator DI = LSD->decls_begin(),
                                  DIEnd = LSD->decls_end();
          DI != DIEnd; ) {
-      if (isa<ObjCClassDecl>((*DI))) {
-        SmallVector<Decl *, 8> DG;
-        Decl *D = (*DI);
-        SourceLocation Loc = D->getLocation();
-        while (DI != DIEnd &&
-               isa<ObjCClassDecl>(D) && D->getLocation() == Loc) {
-          ObjCClassDecl *Class = cast<ObjCClassDecl>(D);
-          DG.push_back(D);
-          ++DI;
-          D = (*DI);
-
-          // Following the ObjCClassDecl, we should have the corresponding
-          // ObjCInterfaceDecl. Skip over it.
-          if (DI != DIEnd && isa<ObjCInterfaceDecl>(D) && 
-              Class->getForwardInterfaceDecl() == D) {
+      if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {
+        if (!IFace->isThisDeclarationADefinition()) {
+          SmallVector<Decl *, 8> DG;
+          SourceLocation StartLoc = IFace->getLocStart();
+          do {
+            if (isa<ObjCInterfaceDecl>(*DI) &&
+                !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
+                StartLoc == (*DI)->getLocStart())
+              DG.push_back(*DI);
+            else
+              break;
+            
             ++DI;
-            D = (*DI);
-          }
+          } while (DI != DIEnd);
+          RewriteForwardClassDecl(DG);
+          continue;
+        }
+      }
+
+      if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {
+        if (!Proto->isThisDeclarationADefinition()) {
+          SmallVector<Decl *, 8> DG;
+          SourceLocation StartLoc = Proto->getLocStart();
+          do {
+            if (isa<ObjCProtocolDecl>(*DI) &&
+                !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
+                StartLoc == (*DI)->getLocStart())
+              DG.push_back(*DI);
+            else
+              break;
+            
+            ++DI;
+          } while (DI != DIEnd);
+          RewriteForwardProtocolDecl(DG);
+          continue;
         }
-        RewriteForwardClassDecl(DG);
-        continue;
       }
+      
       HandleTopLevelSingleDecl(*DI);
       ++DI;
     }
@@ -873,9 +898,9 @@
   typedefString += ";\n#endif\n";
 }
 
-void RewriteObjC::RewriteForwardClassEpilogue(ObjCClassDecl *ClassDecl,
+void RewriteObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
                                               const std::string &typedefString) {
-    SourceLocation startLoc = ClassDecl->getLocation();
+    SourceLocation startLoc = ClassDecl->getLocStart();
     const char *startBuf = SM->getCharacterData(startLoc);
     const char *semiPtr = strchr(startBuf, ';'); 
     // Replace the @class with typedefs corresponding to the classes.
@@ -885,8 +910,7 @@
 void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) {
   std::string typedefString;
   for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
-    ObjCClassDecl *ClassDecl = cast<ObjCClassDecl>(*I);
-    ObjCInterfaceDecl *ForwardDecl = ClassDecl->getForwardInterfaceDecl();
+    ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I);
     if (I == D.begin()) {
       // Translate to typedef's that forward reference structs with the same name
       // as the class. As a convenience, we include the original declaration
@@ -898,15 +922,14 @@
     RewriteOneForwardClassDecl(ForwardDecl, typedefString);
   }
   DeclGroupRef::iterator I = D.begin();
-  RewriteForwardClassEpilogue(cast<ObjCClassDecl>(*I), typedefString);
+  RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
 }
 
 void RewriteObjC::RewriteForwardClassDecl(
                                 const llvm::SmallVector<Decl*, 8> &D) {
   std::string typedefString;
   for (unsigned i = 0; i < D.size(); i++) {
-    ObjCClassDecl *ClassDecl = cast<ObjCClassDecl>(D[i]);
-    ObjCInterfaceDecl *ForwardDecl = ClassDecl->getForwardInterfaceDecl();
+    ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);
     if (i == 0) {
       typedefString += "// @class ";
       typedefString += ForwardDecl->getNameAsString();
@@ -914,7 +937,7 @@
     }
     RewriteOneForwardClassDecl(ForwardDecl, typedefString);
   }
-  RewriteForwardClassEpilogue(cast<ObjCClassDecl>(D[0]), typedefString);
+  RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
 }
 
 void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
@@ -967,7 +990,8 @@
 
 void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
   SourceLocation LocStart = PDecl->getLocStart();
-
+  assert(PDecl->isThisDeclarationADefinition());
+  
   // FIXME: handle protocol headers that are declared across multiple lines.
   ReplaceText(LocStart, 0, "// ");
 
@@ -1005,8 +1029,17 @@
   }
 }
 
-void RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) {
-  SourceLocation LocStart = PDecl->getLocation();
+void RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
+  SourceLocation LocStart = (*D.begin())->getLocStart();
+  if (LocStart.isInvalid())
+    llvm_unreachable("Invalid SourceLocation");
+  // FIXME: handle forward protocol that are declared across multiple lines.
+  ReplaceText(LocStart, 0, "// ");
+}
+
+void 
+RewriteObjC::RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG) {
+  SourceLocation LocStart = DG[0]->getLocStart();
   if (LocStart.isInvalid())
     llvm_unreachable("Invalid SourceLocation");
   // FIXME: handle forward protocol that are declared across multiple lines.
@@ -1255,7 +1288,7 @@
   SmallVector<SourceLocation, 1> SelLocs;
   OldMsg->getSelectorLocs(SelLocs);
 
-  ObjCMessageExpr *NewMsg;
+  ObjCMessageExpr *NewMsg = 0;
   switch (OldMsg->getReceiverKind()) {
   case ObjCMessageExpr::Class:
     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
@@ -1266,7 +1299,8 @@
                                      SelLocs,
                                      OldMsg->getMethodDecl(),
                                      RHS,
-                                     OldMsg->getRightLoc());
+                                     OldMsg->getRightLoc(),
+                                     OldMsg->isImplicit());
     break;
 
   case ObjCMessageExpr::Instance:
@@ -1278,7 +1312,8 @@
                                      SelLocs,
                                      OldMsg->getMethodDecl(),
                                      RHS,
-                                     OldMsg->getRightLoc());
+                                     OldMsg->getRightLoc(),
+                                     OldMsg->isImplicit());
     break;
 
   case ObjCMessageExpr::SuperClass:
@@ -1293,7 +1328,8 @@
                                      SelLocs,
                                      OldMsg->getMethodDecl(),
                                      RHS,
-                                     OldMsg->getRightLoc());
+                                     OldMsg->getRightLoc(),
+                                     OldMsg->isImplicit());
     break;
   }
 
@@ -1328,7 +1364,7 @@
   SmallVector<SourceLocation, 1> SelLocs;
   SmallVector<Expr*, 1> Args;
 
-  ObjCMessageExpr *NewMsg;
+  ObjCMessageExpr *NewMsg = 0;
   switch (OldMsg->getReceiverKind()) {
   case ObjCMessageExpr::Class:
     NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
@@ -1339,7 +1375,8 @@
                                      SelLocs,
                                      OldMsg->getMethodDecl(),
                                      Args,
-                                     OldMsg->getRightLoc());
+                                     OldMsg->getRightLoc(),
+                                     OldMsg->isImplicit());
     break;
 
   case ObjCMessageExpr::Instance:
@@ -1351,7 +1388,8 @@
                                      SelLocs,
                                      OldMsg->getMethodDecl(),
                                      Args,
-                                     OldMsg->getRightLoc());
+                                     OldMsg->getRightLoc(),
+                                     OldMsg->isImplicit());
     break;
 
   case ObjCMessageExpr::SuperClass:
@@ -1366,7 +1404,8 @@
                                      SelLocs,
                                      OldMsg->getMethodDecl(),
                                      Args,
-                                     OldMsg->getRightLoc());
+                                     OldMsg->getRightLoc(),
+                                     OldMsg->isImplicit());
     break;
   }
 
@@ -2478,7 +2517,7 @@
                                                    false);
 }
 
-// SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name);
+// SynthGetMetaClassFunctionDecl - id objc_getMetaClass(const char *name);
 void RewriteObjC::SynthGetMetaClassFunctionDecl() {
   IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
   SmallVector<QualType, 16> ArgTys;
@@ -2673,7 +2712,7 @@
     // (Class)objc_getClass("CurrentClass")
     CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
                                              Context->getObjCClassType(),
-                                             CK_CPointerToObjCPointerCast, Cls);
+                                             CK_BitCast, Cls);
     ClsExprs.clear();
     ClsExprs.push_back(ArgExpr);
     Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
@@ -3088,7 +3127,7 @@
                                                 CK_BitCast,
                                                 DerefExpr);
   ReplaceStmt(Exp, castExpr);
-  ProtocolExprDecls.insert(Exp->getProtocol());
+  ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());
   // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
   return castExpr;
 
@@ -4990,10 +5029,6 @@
         RewriteRecordBody(RD);
       break;
     }
-    case Decl::ObjCClass: {
-      llvm_unreachable("RewriteObjC::HandleDeclInMainFile - ObjCClassDecl");
-      break;
-    }
     default:
       break;
   }
@@ -5178,7 +5213,7 @@
   static bool objc_protocol_methods = false;
   
   // Output struct protocol_methods holder of method selector and type.
-  if (!objc_protocol_methods && !PDecl->isForwardDecl()) {
+  if (!objc_protocol_methods && PDecl->hasDefinition()) {
     /* struct protocol_methods {
      SEL _cmd;
      char *method_types;
@@ -5192,9 +5227,12 @@
     objc_protocol_methods = true;
   }
   // Do not synthesize the protocol more than once.
-  if (ObjCSynthesizedProtocols.count(PDecl))
+  if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))
     return;
   
+  if (ObjCProtocolDecl *Def = PDecl->getDefinition())
+    PDecl = Def;
+  
   if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
     unsigned NumMethods = std::distance(PDecl->instmeth_begin(),
                                         PDecl->instmeth_end());
@@ -5314,7 +5352,7 @@
   Result += "};\n";
   
   // Mark this protocol as having been generated.
-  if (!ObjCSynthesizedProtocols.insert(PDecl))
+  if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()))
     llvm_unreachable("protocol already synthesized");
   
 }

Modified: cfe/branches/tooling/lib/Sema/AnalysisBasedWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/AnalysisBasedWarnings.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/AnalysisBasedWarnings.cpp (original)
+++ cfe/branches/tooling/lib/Sema/AnalysisBasedWarnings.cpp Fri Jan 20 10:14:22 2012
@@ -415,42 +415,15 @@
     return false;
 
   // Suggest possible initialization (if any).
-  const char *initialization = 0;
   QualType VariableTy = VD->getType().getCanonicalType();
-
-  if (VariableTy->isObjCObjectPointerType() ||
-      VariableTy->isBlockPointerType()) {
-    // Check if 'nil' is defined.
-    if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil")))
-      initialization = " = nil";
-    else
-      initialization = " = 0";
-  }
-  else if (VariableTy->isRealFloatingType())
-    initialization = " = 0.0";
-  else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus)
-    initialization = " = false";
-  else if (VariableTy->isEnumeralType())
+  const char *Init = S.getFixItZeroInitializerForType(VariableTy);
+  if (!Init)
     return false;
-  else if (VariableTy->isPointerType() || VariableTy->isMemberPointerType()) {
-    if (S.Context.getLangOptions().CPlusPlus0x)
-      initialization = " = nullptr";
-    // Check if 'NULL' is defined.
-    else if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("NULL")))
-      initialization = " = NULL";
-    else
-      initialization = " = 0";
-  }
-  else if (VariableTy->isScalarType())
-    initialization = " = 0";
-
-  if (initialization) {
-    SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd());
-    S.Diag(loc, diag::note_var_fixit_add_initialization) << VD->getDeclName()
-      << FixItHint::CreateInsertion(loc, initialization);
-    return true;
-  }
-  return false;
+
+  SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd());
+  S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName()
+    << FixItHint::CreateInsertion(Loc, Init);
+  return true;
 }
 
 /// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
@@ -634,6 +607,7 @@
   }
 };
 
+namespace {
 class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
   Sema &S;
   DiagList Warnings;
@@ -744,6 +718,7 @@
 };
 }
 }
+}
 
 //===----------------------------------------------------------------------===//
 // AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based

Modified: cfe/branches/tooling/lib/Sema/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/AttributeList.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/AttributeList.cpp (original)
+++ cfe/branches/tooling/lib/Sema/AttributeList.cpp Fri Jan 20 10:14:22 2012
@@ -108,6 +108,7 @@
     .Case("weak", AT_weak)
     .Case("weakref", AT_weakref)
     .Case("objc_arc_weak_reference_unavailable", AT_arc_weakref_unavailable)
+    .Case("objc_requires_property_definitions", AT_objc_requires_property_definitions)
     .Case("pure", AT_pure)
     .Case("mode", AT_mode)
     .Case("used", AT_used)

Modified: cfe/branches/tooling/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/CMakeLists.txt?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/CMakeLists.txt (original)
+++ cfe/branches/tooling/lib/Sema/CMakeLists.txt Fri Jan 20 10:14:22 2012
@@ -17,6 +17,7 @@
   SemaCast.cpp
   SemaChecking.cpp
   SemaCodeComplete.cpp
+  SemaConsumer.cpp
   SemaDecl.cpp
   SemaDeclAttr.cpp
   SemaDeclCXX.cpp

Modified: cfe/branches/tooling/lib/Sema/CodeCompleteConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/CodeCompleteConsumer.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/CodeCompleteConsumer.cpp (original)
+++ cfe/branches/tooling/lib/Sema/CodeCompleteConsumer.cpp Fri Jan 20 10:14:22 2012
@@ -71,8 +71,8 @@
   case CCC_ObjCCategoryName:
     return false;
   }
-  
-  return false;
+
+  llvm_unreachable("Invalid CodeCompletionContext::Kind!");
 }
 
 //===----------------------------------------------------------------------===//
@@ -93,7 +93,6 @@
 
   case CK_Optional:
     llvm_unreachable("Optional strings cannot be created from text");
-    break;
       
   case CK_LeftParen:
     this->Text = "(";
@@ -330,8 +329,8 @@
   case CK_FunctionType:
     return Type;
   }
-  
-  return 0;
+
+  llvm_unreachable("Invalid CandidateKind!");
 }
 
 //===----------------------------------------------------------------------===//
@@ -424,8 +423,17 @@
         Availability = CXAvailability_NotAvailable;
       
     CursorKind = getCursorKindForDecl(Declaration);
-    if (CursorKind == CXCursor_UnexposedDecl)
-      CursorKind = CXCursor_NotImplemented;
+    if (CursorKind == CXCursor_UnexposedDecl) {
+      // FIXME: Forward declarations of Objective-C classes and protocols 
+      // are not directly exposed, but we want code completion to treat them 
+      // like a definition.
+      if (isa<ObjCInterfaceDecl>(Declaration))
+        CursorKind = CXCursor_ObjCInterfaceDecl;
+      else if (isa<ObjCProtocolDecl>(Declaration))
+        CursorKind = CXCursor_ObjCProtocolDecl;
+      else
+        CursorKind = CXCursor_NotImplemented;
+    }
     break;
 
   case RK_Macro:

Modified: cfe/branches/tooling/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/DeclSpec.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/DeclSpec.cpp (original)
+++ cfe/branches/tooling/lib/Sema/DeclSpec.cpp Fri Jan 20 10:14:22 2012
@@ -245,7 +245,6 @@
       return false;
     }
     llvm_unreachable("Invalid type chunk");
-    return false;
   }
   
   switch (DS.getTypeSpecType()) {
@@ -295,8 +294,8 @@
       return QT->isFunctionType();
     }
   }
-  
-  return false;
+
+  llvm_unreachable("Invalid TypeSpecType!");
 }
 
 /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
@@ -867,7 +866,8 @@
       TypeSpecType = TST_double;   // _Complex -> _Complex double.
     } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
       // Note that this intentionally doesn't include _Complex _Bool.
-      Diag(D, TSTLoc, diag::ext_integer_complex);
+      if (!PP.getLangOptions().CPlusPlus)
+        Diag(D, TSTLoc, diag::ext_integer_complex);
     } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
       Diag(D, TSCLoc, diag::err_invalid_complex_spec)
         << getSpecifierName((TST)TypeSpecType);

Modified: cfe/branches/tooling/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/Sema.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/Sema.cpp (original)
+++ cfe/branches/tooling/lib/Sema/Sema.cpp Fri Jan 20 10:14:22 2012
@@ -55,10 +55,12 @@
 }
 
 BlockScopeInfo::~BlockScopeInfo() { }
+LambdaScopeInfo::~LambdaScopeInfo() { }
 
-PrintingPolicy Sema::getPrintingPolicy() const {
+PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
+                                       const Preprocessor &PP) {
   PrintingPolicy Policy = Context.getPrintingPolicy();
-  Policy.Bool = getLangOptions().Bool;
+  Policy.Bool = Context.getLangOptions().Bool;
   if (!Policy.Bool) {
     if (MacroInfo *BoolMacro = PP.getMacroInfo(&Context.Idents.get("bool"))) {
       Policy.Bool = BoolMacro->isObjectLike() && 
@@ -75,19 +77,6 @@
   PushDeclContext(S, Context.getTranslationUnitDecl());
 
   VAListTagName = PP.getIdentifierInfo("__va_list_tag");
-
-  if (PP.getLangOptions().ObjC1) {
-    // Synthesize "@class Protocol;
-    if (Context.getObjCProtoType().isNull()) {
-      ObjCInterfaceDecl *ProtocolDecl =
-        ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
-                                  &Context.Idents.get("Protocol"),
-                                  /*PrevDecl=*/0,
-                                  SourceLocation(), true);
-      Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
-      PushOnScopeChains(ProtocolDecl, TUScope, false);
-    }  
-  }
 }
 
 Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
@@ -100,7 +89,7 @@
     CurContext(0), OriginalLexicalContext(0),
     PackContext(0), MSStructPragmaOn(false), VisContext(0),
     ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0),
-    IdResolver(pp), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
+    IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
     GlobalNewDeleteDeclared(false), 
     ObjCShouldCallSuperDealloc(false),
     ObjCShouldCallSuperFinalize(false),
@@ -172,6 +161,11 @@
     DeclarationName Class = &Context.Idents.get("Class");
     if (IdResolver.begin(Class) == IdResolver.end())
       PushOnScopeChains(Context.getObjCClassDecl(), TUScope);
+
+    // Create the built-in forward declaratino for 'Protocol'.
+    DeclarationName Protocol = &Context.Idents.get("Protocol");
+    if (IdResolver.begin(Protocol) == IdResolver.end())
+      PushOnScopeChains(Context.getObjCProtocolDecl(), TUScope);
   }
 }
 
@@ -320,7 +314,7 @@
 
     // Later redecls may add new information resulting in not having to warn,
     // so check again.
-    DeclToCheck = FD->getMostRecentDeclaration();
+    DeclToCheck = FD->getMostRecentDecl();
     if (DeclToCheck != FD)
       return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
   }
@@ -334,7 +328,7 @@
 
     // Later redecls may add new information resulting in not having to warn,
     // so check again.
-    DeclToCheck = VD->getMostRecentDeclaration();
+    DeclToCheck = VD->getMostRecentDecl();
     if (DeclToCheck != VD)
       return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
   }
@@ -503,10 +497,10 @@
         ModMap.resolveExports(Mod, /*Complain=*/false);
         
         // Queue the submodules, so their exports will also be resolved.
-        for (llvm::StringMap<Module *>::iterator Sub = Mod->SubModules.begin(),
-             SubEnd = Mod->SubModules.end();
+        for (Module::submodule_iterator Sub = Mod->submodule_begin(),
+                                     SubEnd = Mod->submodule_end();
              Sub != SubEnd; ++Sub) {
-          Stack.push_back(Sub->getValue());
+          Stack.push_back(*Sub);
         }
       }
     }
@@ -635,8 +629,15 @@
 DeclContext *Sema::getFunctionLevelDeclContext() {
   DeclContext *DC = CurContext;
 
-  while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC))
-    DC = DC->getParent();
+  while (true) {
+    if (isa<BlockDecl>(DC) || isa<EnumDecl>(DC)) {
+      DC = DC->getParent();
+    } else if (isa<CXXMethodDecl>(DC) &&
+               cast<CXXRecordDecl>(DC->getParent())->isLambda()) {
+      DC = DC->getParent()->getParent();
+    }
+    else break;
+  }
 
   return DC;
 }
@@ -828,8 +829,12 @@
                                               BlockScope, Block));
 }
 
-void Sema::PopFunctionOrBlockScope(const AnalysisBasedWarnings::Policy *WP,
-                                   const Decl *D, const BlockExpr *blkExpr) {
+void Sema::PushLambdaScope(CXXRecordDecl *Lambda) {
+  FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda));
+}
+
+void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
+                                const Decl *D, const BlockExpr *blkExpr) {
   FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();  
   assert(!FunctionScopes.empty() && "mismatched push/pop!");
   
@@ -864,6 +869,13 @@
   return dyn_cast<BlockScopeInfo>(FunctionScopes.back());  
 }
 
+LambdaScopeInfo *Sema::getCurLambda() {
+  if (FunctionScopes.empty())
+    return 0;
+  
+  return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());  
+}
+
 // Pin this vtable to this file.
 ExternalSemaSource::~ExternalSemaSource() {}
 

Modified: cfe/branches/tooling/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaAccess.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaAccess.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaAccess.cpp Fri Jan 20 10:14:22 2012
@@ -797,7 +797,6 @@
 
   // Silence bogus warnings
   llvm_unreachable("impossible friendship kind");
-  return OnFailure;
 }
 
 /// Finds the best path from the naming class to the declaring class,
@@ -1020,15 +1019,15 @@
       while (D->isOutOfLine()) {
         NamedDecl *PrevDecl = 0;
         if (VarDecl *VD = dyn_cast<VarDecl>(D))
-          PrevDecl = VD->getPreviousDeclaration();
+          PrevDecl = VD->getPreviousDecl();
         else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
-          PrevDecl = FD->getPreviousDeclaration();
+          PrevDecl = FD->getPreviousDecl();
         else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D))
-          PrevDecl = TND->getPreviousDeclaration();
+          PrevDecl = TND->getPreviousDecl();
         else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
           if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
             break;
-          PrevDecl = TD->getPreviousDeclaration();
+          PrevDecl = TD->getPreviousDecl();
         }
         if (!PrevDecl) break;
         D = PrevDecl;
@@ -1068,7 +1067,6 @@
 
     case AR_dependent:
       llvm_unreachable("can't diagnose dependent access failures");
-      return;
     }
   }
 
@@ -1166,7 +1164,7 @@
     if (Entity.getTargetDecl()->getAccess() == AS_private && 
         (OrigDecl->getAccess() == AS_public ||
          OrigDecl->getAccess() == AS_protected)) {
-      S.Diag(AccessLoc, diag::war_ms_using_declaration_inaccessible) 
+      S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
         << Shadow->getUsingDecl()->getQualifiedNameAsString()
         << OrigDecl->getQualifiedNameAsString();
       return true;
@@ -1298,7 +1296,6 @@
 
   // silence unnecessary warning
   llvm_unreachable("invalid access result");
-  return AR_accessible;
 }
 
 static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
@@ -1333,7 +1330,6 @@
   case AR_dependent: return Sema::AR_dependent;
   }
   llvm_unreachable("falling off end");
-  return Sema::AR_accessible;
 }
 
 void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) {

Modified: cfe/branches/tooling/lib/Sema/SemaAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaAttr.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaAttr.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaAttr.cpp Fri Jan 20 10:14:22 2012
@@ -263,9 +263,6 @@
         Context->setAlignment(AlignmentVal);
     }
     break;
-
-  default:
-    llvm_unreachable("Invalid #pragma pack kind.");
   }
 }
 

Modified: cfe/branches/tooling/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaCXXScopeSpec.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaCXXScopeSpec.cpp Fri Jan 20 10:14:22 2012
@@ -150,14 +150,13 @@
     const TagType *Tag = NNS->getAsType()->getAs<TagType>();
     assert(Tag && "Non-tag type in nested-name-specifier");
     return Tag->getDecl();
-  } break;
+  }
 
   case NestedNameSpecifier::Global:
     return Context.getTranslationUnitDecl();
   }
 
-  // Required to silence a GCC warning.
-  return 0;
+  llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
 }
 
 bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
@@ -363,6 +362,25 @@
   return false;
 }
 
+namespace {
+
+// Callback to only accept typo corrections that can be a valid C++ member
+// intializer: either a non-static field member or a base class.
+class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  explicit NestedNameSpecifierValidatorCCC(Sema &SRef)
+      : SRef(SRef) {}
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    return SRef.isAcceptableNestedNameSpecifier(candidate.getCorrectionDecl());
+  }
+
+ private:
+  Sema &SRef;
+};
+
+}
+
 /// \brief Build a new nested-name-specifier for "identifier::", as described
 /// by ActOnCXXNestedNameSpecifier.
 ///
@@ -478,12 +496,12 @@
     // We haven't found anything, and we're not recovering from a
     // different kind of error, so look for typos.
     DeclarationName Name = Found.getLookupName();
+    NestedNameSpecifierValidatorCCC Validator(*this);
     TypoCorrection Corrected;
     Found.clear();
     if ((Corrected = CorrectTypo(Found.getLookupNameInfo(),
-                                 Found.getLookupKind(), S, &SS, LookupCtx,
-                                 EnteringContext, CTC_NoKeywords)) &&
-        isAcceptableNestedNameSpecifier(Corrected.getCorrectionDecl())) {
+                                 Found.getLookupKind(), S, &SS, &Validator,
+                                 LookupCtx, EnteringContext))) {
       std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
       std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
       if (LookupCtx)
@@ -880,8 +898,7 @@
     return true;
   }
 
-  // Silence bogus warning.
-  return false;
+  llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
 }
 
 /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global

Modified: cfe/branches/tooling/lib/Sema/SemaCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaCast.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaCast.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaCast.cpp Fri Jan 20 10:14:22 2012
@@ -295,8 +295,6 @@
                                                  OpLoc, Parens.getEnd()));
   }
   }
-
-  return ExprError();
 }
 
 /// Try to diagnose a failed overloaded cast.  Returns true if
@@ -346,7 +344,6 @@
 
   switch (sequence.getFailedOverloadResult()) {
   case OR_Success: llvm_unreachable("successful failed overload");
-    return false;
   case OR_No_Viable_Function:
     if (candidates.empty())
       msg = diag::err_ovl_no_conversion_in_cast;
@@ -529,11 +526,12 @@
 /// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime-
 /// checked downcasts in class hierarchies.
 void CastOperation::CheckDynamicCast() {
-  if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload)) {
+  if (ValueKind == VK_RValue)
     SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
-    if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
-      return;
-  }
+  else if (isPlaceholder())
+    SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take());
+  if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+    return;
 
   QualType OrigSrcType = SrcExpr.get()->getType();
   QualType DestType = Self.Context.getCanonicalType(this->DestType);
@@ -662,11 +660,12 @@
 /// const char *str = "literal";
 /// legacy_function(const_cast\<char*\>(str));
 void CastOperation::CheckConstCast() {
-  if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload)) {
+  if (ValueKind == VK_RValue)
     SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
-    if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
-      return;
-  }
+  else if (isPlaceholder())
+    SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take());
+  if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+    return;
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
   if (TryConstCast(Self, SrcExpr.get(), DestType, /*CStyle*/false, msg) != TC_Success
@@ -681,11 +680,12 @@
 /// like this:
 /// char *bytes = reinterpret_cast\<char*\>(int_ptr);
 void CastOperation::CheckReinterpretCast() {
-  if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload)) {
+  if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload))
     SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
-    if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
-      return;
-  }
+  else
+    checkNonOverloadPlaceholders();
+  if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+    return;
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
   TryCastResult tcr = 
@@ -1894,6 +1894,11 @@
   if (SrcExpr.isInvalid())
     return;
   QualType SrcType = SrcExpr.get()->getType();
+
+  // You can cast an _Atomic(T) to anything you can cast a T to.
+  if (const AtomicType *AtomicSrcType = SrcType->getAs<AtomicType>())
+    SrcType = AtomicSrcType->getValueType();
+
   assert(!SrcType->isPlaceholderType());
 
   if (Self.RequireCompleteType(OpRange.getBegin(), DestType,

Modified: cfe/branches/tooling/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaChecking.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaChecking.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaChecking.cpp Fri Jan 20 10:14:22 2012
@@ -44,23 +44,24 @@
   return SL->getLocationOfByte(ByteNo, PP.getSourceManager(),
                                PP.getLangOptions(), PP.getTargetInfo());
 }
-  
 
-/// CheckablePrintfAttr - does a function call have a "printf" attribute
-/// and arguments that merit checking?
-bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) {
-  if (Format->getType() == "printf") return true;
-  if (Format->getType() == "printf0") {
+bool Sema::CheckablePrintfAttr(const FormatAttr *Format, Expr **Args,
+                               unsigned NumArgs, bool IsCXXMemberCall) {
+  StringRef Type = Format->getType();
+  // FIXME: add support for "CFString" Type. They are not string literal though,
+  // so they need special handling.
+  if (Type == "printf" || Type == "NSString") return true;
+  if (Type == "printf0") {
     // printf0 allows null "format" string; if so don't check format/args
     unsigned format_idx = Format->getFormatIdx() - 1;
     // Does the index refer to the implicit object argument?
-    if (isa<CXXMemberCallExpr>(TheCall)) {
+    if (IsCXXMemberCall) {
       if (format_idx == 0)
         return false;
       --format_idx;
     }
-    if (format_idx < TheCall->getNumArgs()) {
-      Expr *Format = TheCall->getArg(format_idx)->IgnoreParenCasts();
+    if (format_idx < NumArgs) {
+      Expr *Format = Args[format_idx]->IgnoreParenCasts();
       if (!Format->isNullPointerConstant(Context,
                                          Expr::NPC_ValueDependentIsNull))
         return true;
@@ -277,6 +278,8 @@
     return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Load);
   case Builtin::BI__atomic_store:
     return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Store);
+  case Builtin::BI__atomic_init:
+    return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Init);
   case Builtin::BI__atomic_exchange:
     return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Xchg);
   case Builtin::BI__atomic_compare_exchange_strong:
@@ -340,7 +343,7 @@
     assert(!shift && "cannot shift float types!");
     return (2 << IsQuad) - 1;
   }
-  return 0;
+  llvm_unreachable("Invalid NeonTypeFlag!");
 }
 
 /// getNeonEltType - Return the QualType corresponding to the elements of
@@ -365,7 +368,7 @@
   case NeonTypeFlags::Float32:
     return Context.FloatTy;
   }
-  return QualType();
+  llvm_unreachable("Invalid NeonTypeFlag!");
 }
 
 bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
@@ -461,16 +464,7 @@
   for (specific_attr_iterator<FormatAttr>
          i = FDecl->specific_attr_begin<FormatAttr>(),
          e = FDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) {
-
-    const FormatAttr *Format = *i;
-    const bool b = Format->getType() == "scanf";
-    if (b || CheckablePrintfAttr(Format, TheCall)) {
-      bool HasVAListArg = Format->getFirstArg() == 0;
-      CheckPrintfScanfArguments(TheCall, HasVAListArg,
-                                Format->getFormatIdx() - 1,
-                                HasVAListArg ? 0 : Format->getFirstArg() - 1,
-                                !b);
-    }
+    CheckFormatArguments(*i, TheCall);
   }
 
   for (specific_attr_iterator<NonNullAttr>
@@ -480,88 +474,35 @@
                           TheCall->getCallee()->getLocStart());
   }
 
-  // Builtin handling
-  int CMF = -1;
-  switch (FDecl->getBuiltinID()) {
-  case Builtin::BI__builtin_memset:
-  case Builtin::BI__builtin___memset_chk:
-  case Builtin::BImemset:
-    CMF = CMF_Memset;
-    break;
-    
-  case Builtin::BI__builtin_memcpy:
-  case Builtin::BI__builtin___memcpy_chk:
-  case Builtin::BImemcpy:
-    CMF = CMF_Memcpy;
-    break;
-    
-  case Builtin::BI__builtin_memmove:
-  case Builtin::BI__builtin___memmove_chk:
-  case Builtin::BImemmove:
-    CMF = CMF_Memmove;
-    break;
+  unsigned CMId = FDecl->getMemoryFunctionKind();
+  if (CMId == 0)
+    return false;
 
-  case Builtin::BIstrlcpy:
-  case Builtin::BIstrlcat:
+  // Handle memory setting and copying functions.
+  if (CMId == Builtin::BIstrlcpy || CMId == Builtin::BIstrlcat)
     CheckStrlcpycatArguments(TheCall, FnInfo);
-    break;
-    
-  case Builtin::BI__builtin_memcmp:
-    CMF = CMF_Memcmp;
-    break;
-    
-  case Builtin::BI__builtin_strncpy:
-  case Builtin::BI__builtin___strncpy_chk:
-  case Builtin::BIstrncpy:
-    CMF = CMF_Strncpy;
-    break;
-
-  case Builtin::BI__builtin_strncmp:
-    CMF = CMF_Strncmp;
-    break;
+  else
+    CheckMemaccessArguments(TheCall, CMId, FnInfo);
 
-  case Builtin::BI__builtin_strncasecmp:
-    CMF = CMF_Strncasecmp;
-    break;
+  return false;
+}
 
-  case Builtin::BI__builtin_strncat:
-  case Builtin::BIstrncat:
-    CMF = CMF_Strncat;
-    break;
+bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, 
+                               Expr **Args, unsigned NumArgs) {
+  for (specific_attr_iterator<FormatAttr>
+       i = Method->specific_attr_begin<FormatAttr>(),
+       e = Method->specific_attr_end<FormatAttr>(); i != e ; ++i) {
 
-  case Builtin::BI__builtin_strndup:
-  case Builtin::BIstrndup:
-    CMF = CMF_Strndup;
-    break;
+    CheckFormatArguments(*i, Args, NumArgs, false, lbrac, 
+                         Method->getSourceRange());
+  }
 
-  default:
-    if (FDecl->getLinkage() == ExternalLinkage &&
-        (!getLangOptions().CPlusPlus || FDecl->isExternC())) {
-      if (FnInfo->isStr("memset"))
-        CMF = CMF_Memset;
-      else if (FnInfo->isStr("memcpy"))
-        CMF = CMF_Memcpy;
-      else if (FnInfo->isStr("memmove"))
-        CMF = CMF_Memmove;
-      else if (FnInfo->isStr("memcmp"))
-        CMF = CMF_Memcmp;
-      else if (FnInfo->isStr("strncpy"))
-        CMF = CMF_Strncpy;
-      else if (FnInfo->isStr("strncmp"))
-        CMF = CMF_Strncmp;
-      else if (FnInfo->isStr("strncasecmp"))
-        CMF = CMF_Strncasecmp;
-      else if (FnInfo->isStr("strncat"))
-        CMF = CMF_Strncat;
-      else if (FnInfo->isStr("strndup"))
-        CMF = CMF_Strndup;
-    }
-    break;
+  // diagnose nonnull arguments.
+  for (specific_attr_iterator<NonNullAttr>
+       i = Method->specific_attr_begin<NonNullAttr>(),
+       e = Method->specific_attr_end<NonNullAttr>(); i != e; ++i) {
+    CheckNonNullArguments(*i, Args, lbrac);
   }
-   
-  // Memset/memcpy/memmove handling
-  if (CMF != -1)
-    CheckMemaccessArguments(TheCall, CheckedMemoryFunction(CMF), FnInfo);
 
   return false;
 }
@@ -580,13 +521,7 @@
   if (!Ty->isBlockPointerType())
     return false;
 
-  const bool b = Format->getType() == "scanf";
-  if (!b && !CheckablePrintfAttr(Format, TheCall))
-    return false;
-
-  bool HasVAListArg = Format->getFirstArg() == 0;
-  CheckPrintfScanfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1,
-                            HasVAListArg ? 0 : Format->getFirstArg() - 1, !b);
+  CheckFormatArguments(Format, TheCall);
 
   return false;
 }
@@ -611,6 +546,8 @@
     NumVals = 2;
     NumOrders = 2;
   }
+  if (Op == AtomicExpr::Init)
+    NumOrders = 0;
 
   if (TheCall->getNumArgs() < NumVals+NumOrders+1) {
     Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
@@ -673,7 +610,7 @@
   }
 
   QualType ResultType = ValType;
-  if (Op == AtomicExpr::Store)
+  if (Op == AtomicExpr::Store || Op == AtomicExpr::Init)
     ResultType = Context.VoidTy;
   else if (Op == AtomicExpr::CmpXchgWeak || Op == AtomicExpr::CmpXchgStrong)
     ResultType = Context.BoolTy;
@@ -714,6 +651,8 @@
   SubExprs.push_back(Ptr);
   if (Op == AtomicExpr::Load) {
     SubExprs.push_back(TheCall->getArg(1)); // Order
+  } else if (Op == AtomicExpr::Init) {
+    SubExprs.push_back(TheCall->getArg(1)); // Val1
   } else if (Op != AtomicExpr::CmpXchgWeak && Op != AtomicExpr::CmpXchgStrong) {
     SubExprs.push_back(TheCall->getArg(2)); // Order
     SubExprs.push_back(TheCall->getArg(1)); // Val1
@@ -1435,8 +1374,8 @@
 }
 
 // Handle i > 1 ? "x" : "y", recursively.
-bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
-                                  bool HasVAListArg,
+bool Sema::SemaCheckStringLiteral(const Expr *E, Expr **Args,
+                                  unsigned NumArgs, bool HasVAListArg,
                                   unsigned format_idx, unsigned firstDataArg,
                                   bool isPrintf, bool inFunctionCall) {
  tryAgain:
@@ -1449,10 +1388,10 @@
   case Stmt::BinaryConditionalOperatorClass:
   case Stmt::ConditionalOperatorClass: {
     const AbstractConditionalOperator *C = cast<AbstractConditionalOperator>(E);
-    return SemaCheckStringLiteral(C->getTrueExpr(), TheCall, HasVAListArg,
+    return SemaCheckStringLiteral(C->getTrueExpr(), Args, NumArgs, HasVAListArg,
                                   format_idx, firstDataArg, isPrintf,
                                   inFunctionCall)
-        && SemaCheckStringLiteral(C->getFalseExpr(), TheCall, HasVAListArg,
+        && SemaCheckStringLiteral(C->getFalseExpr(), Args, NumArgs, HasVAListArg,
                                   format_idx, firstDataArg, isPrintf,
                                   inFunctionCall);
   }
@@ -1500,7 +1439,7 @@
 
       if (isConstant) {
         if (const Expr *Init = VD->getAnyInitializer())
-          return SemaCheckStringLiteral(Init, TheCall,
+          return SemaCheckStringLiteral(Init, Args, NumArgs,
                                         HasVAListArg, format_idx, firstDataArg,
                                         isPrintf, /*inFunctionCall*/false);
       }
@@ -1541,7 +1480,7 @@
             unsigned ArgIndex = FA->getFormatIdx();
             const Expr *Arg = CE->getArg(ArgIndex - 1);
 
-            return SemaCheckStringLiteral(Arg, TheCall, HasVAListArg,
+            return SemaCheckStringLiteral(Arg, Args, NumArgs, HasVAListArg,
                                           format_idx, firstDataArg, isPrintf,
                                           inFunctionCall);
           }
@@ -1561,7 +1500,7 @@
       StrE = cast<StringLiteral>(E);
 
     if (StrE) {
-      CheckFormatString(StrE, E, TheCall, HasVAListArg, format_idx,
+      CheckFormatString(StrE, E, Args, NumArgs, HasVAListArg, format_idx,
                         firstDataArg, isPrintf, inFunctionCall);
       return true;
     }
@@ -1590,37 +1529,52 @@
 
 /// CheckPrintfScanfArguments - Check calls to printf and scanf (and similar
 /// functions) for correct use of format strings.
-void
-Sema::CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg,
-                                unsigned format_idx, unsigned firstDataArg,
-                                bool isPrintf) {
-
-  const Expr *Fn = TheCall->getCallee();
-
+void Sema::CheckFormatArguments(const FormatAttr *Format, CallExpr *TheCall) {
+  bool IsCXXMember = false;
   // The way the format attribute works in GCC, the implicit this argument
   // of member functions is counted. However, it doesn't appear in our own
   // lists, so decrement format_idx in that case.
   if (isa<CXXMemberCallExpr>(TheCall)) {
-    const CXXMethodDecl *method_decl =
-      dyn_cast<CXXMethodDecl>(TheCall->getCalleeDecl());
-    if (method_decl && method_decl->isInstance()) {
-      // Catch a format attribute mistakenly referring to the object argument.
+    const CXXMethodDecl *method_decl = 
+    dyn_cast<CXXMethodDecl>(TheCall->getCalleeDecl());
+    IsCXXMember = method_decl && method_decl->isInstance();
+  }
+  CheckFormatArguments(Format, TheCall->getArgs(), TheCall->getNumArgs(),
+                       IsCXXMember, TheCall->getRParenLoc(), 
+                       TheCall->getCallee()->getSourceRange());
+}
+
+void Sema::CheckFormatArguments(const FormatAttr *Format, Expr **Args,
+                                unsigned NumArgs, bool IsCXXMember,
+                                SourceLocation Loc, SourceRange Range) {
+  const bool b = Format->getType() == "scanf";
+  if (b || CheckablePrintfAttr(Format, Args, NumArgs, IsCXXMember)) {
+    bool HasVAListArg = Format->getFirstArg() == 0;
+    unsigned format_idx = Format->getFormatIdx() - 1;
+    unsigned firstDataArg = HasVAListArg ? 0 : Format->getFirstArg() - 1;
+    if (IsCXXMember) {
       if (format_idx == 0)
         return;
       --format_idx;
       if(firstDataArg != 0)
         --firstDataArg;
     }
+    CheckPrintfScanfArguments(Args, NumArgs, HasVAListArg, format_idx, 
+                              firstDataArg, !b, Loc, Range);
   }
+}
 
+void Sema::CheckPrintfScanfArguments(Expr **Args, unsigned NumArgs,
+                                     bool HasVAListArg, unsigned format_idx,
+                                     unsigned firstDataArg, bool isPrintf,
+                                     SourceLocation Loc, SourceRange Range) {
   // CHECK: printf/scanf-like function is called with no format string.
-  if (format_idx >= TheCall->getNumArgs()) {
-    Diag(TheCall->getRParenLoc(), diag::warn_missing_format_string)
-      << Fn->getSourceRange();
+  if (format_idx >= NumArgs) {
+    Diag(Loc, diag::warn_missing_format_string) << Range;
     return;
   }
 
-  const Expr *OrigFormatExpr = TheCall->getArg(format_idx)->IgnoreParenCasts();
+  const Expr *OrigFormatExpr = Args[format_idx]->IgnoreParenCasts();
 
   // CHECK: format string is not a string literal.
   //
@@ -1634,18 +1588,18 @@
   // C string (e.g. "%d")
   // ObjC string uses the same format specifiers as C string, so we can use
   // the same format string checking logic for both ObjC and C strings.
-  if (SemaCheckStringLiteral(OrigFormatExpr, TheCall, HasVAListArg, format_idx,
-                             firstDataArg, isPrintf))
+  if (SemaCheckStringLiteral(OrigFormatExpr, Args, NumArgs, HasVAListArg,
+                             format_idx, firstDataArg, isPrintf))
     return;  // Literal format string found, check done!
 
   // If there are no arguments specified, warn with -Wformat-security, otherwise
   // warn only with -Wformat-nonliteral.
-  if (TheCall->getNumArgs() == format_idx+1)
-    Diag(TheCall->getArg(format_idx)->getLocStart(),
+  if (NumArgs == format_idx+1)
+    Diag(Args[format_idx]->getLocStart(),
          diag::warn_format_nonliteral_noargs)
       << OrigFormatExpr->getSourceRange();
   else
-    Diag(TheCall->getArg(format_idx)->getLocStart(),
+    Diag(Args[format_idx]->getLocStart(),
          diag::warn_format_nonliteral)
            << OrigFormatExpr->getSourceRange();
 }
@@ -1661,7 +1615,8 @@
   const bool IsObjCLiteral;
   const char *Beg; // Start of format string.
   const bool HasVAListArg;
-  const CallExpr *TheCall;
+  const Expr * const *Args;
+  const unsigned NumArgs;
   unsigned FormatIdx;
   llvm::BitVector CoveredArgs;
   bool usesPositionalArgs;
@@ -1672,14 +1627,14 @@
                      const Expr *origFormatExpr, unsigned firstDataArg,
                      unsigned numDataArgs, bool isObjCLiteral,
                      const char *beg, bool hasVAListArg,
-                     const CallExpr *theCall, unsigned formatIdx,
-                     bool inFunctionCall)
+                     Expr **args, unsigned numArgs,
+                     unsigned formatIdx, bool inFunctionCall)
     : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
       FirstDataArg(firstDataArg),
       NumDataArgs(numDataArgs),
       IsObjCLiteral(isObjCLiteral), Beg(beg),
       HasVAListArg(hasVAListArg),
-      TheCall(theCall), FormatIdx(formatIdx),
+      Args(args), NumArgs(numArgs), FormatIdx(formatIdx),
       usesPositionalArgs(false), atFirstArg(true),
       inFunctionCall(inFunctionCall) {
         CoveredArgs.resize(numDataArgs);
@@ -1794,7 +1749,7 @@
 }
 
 const Expr *CheckFormatHandler::getDataArg(unsigned i) const {
-  return TheCall->getArg(FirstDataArg + i);
+  return Args[FirstDataArg + i];
 }
 
 void CheckFormatHandler::DoneProcessing() {
@@ -1878,7 +1833,7 @@
                                               bool IsStringLocation,
                                               Range StringRange,
                                               FixItHint FixIt) {
-  EmitFormatDiagnostic(S, inFunctionCall, TheCall->getArg(FormatIdx), PDiag,
+  EmitFormatDiagnostic(S, inFunctionCall, Args[FormatIdx], PDiag,
                        Loc, IsStringLocation, StringRange, FixIt);
 }
 
@@ -1937,11 +1892,11 @@
                      const Expr *origFormatExpr, unsigned firstDataArg,
                      unsigned numDataArgs, bool isObjCLiteral,
                      const char *beg, bool hasVAListArg,
-                     const CallExpr *theCall, unsigned formatIdx,
-                     bool inFunctionCall)
+                     Expr **Args, unsigned NumArgs,
+                     unsigned formatIdx, bool inFunctionCall)
   : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
                        numDataArgs, isObjCLiteral, beg, hasVAListArg,
-                       theCall, formatIdx, inFunctionCall) {}
+                       Args, NumArgs, formatIdx, inFunctionCall) {}
   
   
   bool HandleInvalidPrintfConversionSpecifier(
@@ -2261,11 +2216,11 @@
                     const Expr *origFormatExpr, unsigned firstDataArg,
                     unsigned numDataArgs, bool isObjCLiteral,
                     const char *beg, bool hasVAListArg,
-                    const CallExpr *theCall, unsigned formatIdx,
-                    bool inFunctionCall)
+                    Expr **Args, unsigned NumArgs,
+                    unsigned formatIdx, bool inFunctionCall)
   : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
                        numDataArgs, isObjCLiteral, beg, hasVAListArg,
-                       theCall, formatIdx, inFunctionCall) {}
+                       Args, NumArgs, formatIdx, inFunctionCall) {}
   
   bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
                             const char *startSpecifier,
@@ -2408,14 +2363,15 @@
 
 void Sema::CheckFormatString(const StringLiteral *FExpr,
                              const Expr *OrigFormatExpr,
-                             const CallExpr *TheCall, bool HasVAListArg,
-                             unsigned format_idx, unsigned firstDataArg,
-                             bool isPrintf, bool inFunctionCall) {
+                             Expr **Args, unsigned NumArgs,
+                             bool HasVAListArg, unsigned format_idx,
+                             unsigned firstDataArg, bool isPrintf,
+                             bool inFunctionCall) {
   
   // CHECK: is the format string a wide literal?
   if (!FExpr->isAscii()) {
     CheckFormatHandler::EmitFormatDiagnostic(
-      *this, inFunctionCall, TheCall->getArg(format_idx),
+      *this, inFunctionCall, Args[format_idx],
       PDiag(diag::warn_format_string_is_wide_literal), FExpr->getLocStart(),
       /*IsStringLocation*/true, OrigFormatExpr->getSourceRange());
     return;
@@ -2425,12 +2381,12 @@
   StringRef StrRef = FExpr->getString();
   const char *Str = StrRef.data();
   unsigned StrLen = StrRef.size();
-  const unsigned numDataArgs = TheCall->getNumArgs() - firstDataArg;
+  const unsigned numDataArgs = NumArgs - firstDataArg;
   
   // CHECK: empty format string?
   if (StrLen == 0 && numDataArgs > 0) {
     CheckFormatHandler::EmitFormatDiagnostic(
-      *this, inFunctionCall, TheCall->getArg(format_idx),
+      *this, inFunctionCall, Args[format_idx],
       PDiag(diag::warn_empty_format_string), FExpr->getLocStart(),
       /*IsStringLocation*/true, OrigFormatExpr->getSourceRange());
     return;
@@ -2439,7 +2395,7 @@
   if (isPrintf) {
     CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
                          numDataArgs, isa<ObjCStringLiteral>(OrigFormatExpr),
-                         Str, HasVAListArg, TheCall, format_idx,
+                         Str, HasVAListArg, Args, NumArgs, format_idx,
                          inFunctionCall);
   
     if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen,
@@ -2449,7 +2405,7 @@
   else {
     CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
                         numDataArgs, isa<ObjCStringLiteral>(OrigFormatExpr),
-                        Str, HasVAListArg, TheCall, format_idx,
+                        Str, HasVAListArg, Args, NumArgs, format_idx,
                         inFunctionCall);
     
     if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen,
@@ -2500,16 +2456,19 @@
 ///
 /// \param Call The call expression to diagnose.
 void Sema::CheckMemaccessArguments(const CallExpr *Call,
-                                   CheckedMemoryFunction CMF,
+                                   unsigned BId,
                                    IdentifierInfo *FnName) {
+  assert(BId != 0);
+
   // It is possible to have a non-standard definition of memset.  Validate
   // we have enough arguments, and if not, abort further checking.
-  unsigned ExpectedNumArgs = (CMF == CMF_Strndup ? 2 : 3);
+  unsigned ExpectedNumArgs = (BId == Builtin::BIstrndup ? 2 : 3);
   if (Call->getNumArgs() < ExpectedNumArgs)
     return;
 
-  unsigned LastArg = (CMF == CMF_Memset || CMF == CMF_Strndup ? 1 : 2);
-  unsigned LenArg = (CMF == CMF_Strndup ? 1 : 2);
+  unsigned LastArg = (BId == Builtin::BImemset ||
+                      BId == Builtin::BIstrndup ? 1 : 2);
+  unsigned LenArg = (BId == Builtin::BIstrndup ? 1 : 2);
   const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts();
 
   // We have special checking when the length is a sizeof expression.
@@ -2553,7 +2512,8 @@
           if (Context.getTypeSize(PointeeTy) == Context.getCharWidth())
             ActionIdx = 2; // If the pointee's size is sizeof(char),
                            // suggest an explicit length.
-          unsigned DestSrcSelect = (CMF == CMF_Strndup ? 1 : ArgIdx);
+          unsigned DestSrcSelect =
+            (BId == Builtin::BIstrndup ? 1 : ArgIdx);
           DiagRuntimeBehavior(SizeOfArg->getExprLoc(), Dest,
                               PDiag(diag::warn_sizeof_pointer_expr_memaccess)
                                 << FnName << DestSrcSelect << ActionIdx
@@ -2579,16 +2539,29 @@
       }
 
       // Always complain about dynamic classes.
-      if (isDynamicClassType(PointeeTy))
+      if (isDynamicClassType(PointeeTy)) {
+
+        unsigned OperationType = 0;
+        // "overwritten" if we're warning about the destination for any call
+        // but memcmp; otherwise a verb appropriate to the call.
+        if (ArgIdx != 0 || BId == Builtin::BImemcmp) {
+          if (BId == Builtin::BImemcpy)
+            OperationType = 1;
+          else if(BId == Builtin::BImemmove)
+            OperationType = 2;
+          else if (BId == Builtin::BImemcmp)
+            OperationType = 3;
+        }
+          
         DiagRuntimeBehavior(
           Dest->getExprLoc(), Dest,
           PDiag(diag::warn_dyn_class_memaccess)
-            << (CMF == CMF_Memcmp ? ArgIdx + 2 : ArgIdx) << FnName << PointeeTy
-            // "overwritten" if we're warning about the destination for any call
-            // but memcmp; otherwise a verb appropriate to the call.
-            << (ArgIdx == 0 && CMF != CMF_Memcmp ? 0 : (unsigned)CMF)
+            << (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx)
+            << FnName << PointeeTy
+            << OperationType
             << Call->getCallee()->getSourceRange());
-      else if (PointeeTy.hasNonTrivialObjCLifetime() && CMF != CMF_Memset)
+      } else if (PointeeTy.hasNonTrivialObjCLifetime() &&
+               BId != Builtin::BImemset)
         DiagRuntimeBehavior(
           Dest->getExprLoc(), Dest,
           PDiag(diag::warn_arc_object_memaccess)
@@ -3239,7 +3212,7 @@
   // FIXME: The only reason we need to pass the type in here is to get
   // the sign right on this one case.  It would be nice if APValue
   // preserved this.
-  assert(result.isLValue());
+  assert(result.isLValue() || result.isAddrLabelDiff());
   return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType());
 }
 
@@ -3662,12 +3635,10 @@
 
   Expr *OriginalInit = Init->IgnoreParenImpCasts();
 
-  Expr::EvalResult InitValue;
-  if (!OriginalInit->EvaluateAsRValue(InitValue, S.Context) ||
-      !InitValue.Val.isInt())
+  llvm::APSInt Value;
+  if (!OriginalInit->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects))
     return false;
 
-  const llvm::APSInt &Value = InitValue.Val.getInt();
   unsigned OriginalWidth = Value.getBitWidth();
   unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context);
 
@@ -3757,11 +3728,6 @@
   return ValueInRange.toString(10);
 }
 
-static bool isFromSystemMacro(Sema &S, SourceLocation loc) {
-  SourceManager &smgr = S.Context.getSourceManager();
-  return loc.isMacroID() && smgr.isInSystemHeader(smgr.getSpellingLoc(loc));
-}
-
 void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
                              SourceLocation CC, bool *ICContext = 0) {
   if (E->isTypeDependent() || E->isValueDependent()) return;
@@ -3823,7 +3789,7 @@
   // Strip vector types.
   if (isa<VectorType>(Source)) {
     if (!isa<VectorType>(Target)) {
-      if (isFromSystemMacro(S, CC))
+      if (S.SourceMgr.isInSystemMacro(CC))
         return;
       return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar);
     }
@@ -3840,7 +3806,7 @@
   // Strip complex types.
   if (isa<ComplexType>(Source)) {
     if (!isa<ComplexType>(Target)) {
-      if (isFromSystemMacro(S, CC))
+      if (S.SourceMgr.isInSystemMacro(CC))
         return;
 
       return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar);
@@ -3872,7 +3838,7 @@
             return;
         }
 
-        if (isFromSystemMacro(S, CC))
+        if (S.SourceMgr.isInSystemMacro(CC))
           return;
 
         DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision);
@@ -3882,7 +3848,7 @@
 
     // If the target is integral, always warn.    
     if ((TargetBT && TargetBT->isInteger())) {
-      if (isFromSystemMacro(S, CC))
+      if (S.SourceMgr.isInSystemMacro(CC))
         return;
       
       Expr *InnerE = E->IgnoreParenImpCasts();
@@ -3919,7 +3885,7 @@
     // TODO: this should happen for bitfield stores, too.
     llvm::APSInt Value(32);
     if (E->isIntegerConstantExpr(Value, S.Context)) {
-      if (isFromSystemMacro(S, CC))
+      if (S.SourceMgr.isInSystemMacro(CC))
         return;
 
       std::string PrettySourceValue = Value.toString(10);
@@ -3934,7 +3900,7 @@
     }
 
     // People want to build with -Wshorten-64-to-32 and not -Wconversion.
-    if (isFromSystemMacro(S, CC))
+    if (S.SourceMgr.isInSystemMacro(CC))
       return;
     
     if (SourceRange.Width == 64 && TargetRange.Width == 32)
@@ -3946,7 +3912,7 @@
       (!TargetRange.NonNegative && SourceRange.NonNegative &&
        SourceRange.Width == TargetRange.Width)) {
         
-    if (isFromSystemMacro(S, CC))
+    if (S.SourceMgr.isInSystemMacro(CC))
       return;
 
     unsigned DiagID = diag::warn_impcast_integer_sign;
@@ -3984,7 +3950,7 @@
           (TargetEnum->getDecl()->getIdentifier() ||
            TargetEnum->getDecl()->getTypedefNameForAnonDecl()) &&
           SourceEnum != TargetEnum) {
-        if (isFromSystemMacro(S, CC))
+        if (S.SourceMgr.isInSystemMacro(CC))
           return;
 
         return DiagnoseImpCast(S, E, SourceType, T, CC, 
@@ -4465,7 +4431,7 @@
   return true;
 }
 
-static bool findRetainCycleOwner(Expr *e, RetainCycleOwner &owner) {
+static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) {
   while (true) {
     e = e->IgnoreParens();
     if (CastExpr *cast = dyn_cast<CastExpr>(e)) {
@@ -4488,7 +4454,7 @@
         return false;
 
       // Try to find a retain cycle in the base.
-      if (!findRetainCycleOwner(ref->getBase(), owner))
+      if (!findRetainCycleOwner(S, ref->getBase(), owner))
         return false;
 
       if (ref->isFreeIvar()) owner.setLocsFrom(ref);
@@ -4531,6 +4497,14 @@
           return false;
 
       owner.Indirect = true;
+      if (pre->isSuperReceiver()) {
+        owner.Variable = S.getCurMethodDecl()->getSelfDecl();
+        if (!owner.Variable)
+          return false;
+        owner.Loc = pre->getLocation();
+        owner.Range = pre->getSourceRange();
+        return true;
+      }
       e = const_cast<Expr*>(cast<OpaqueValueExpr>(pre->getBase())
                               ->getSourceExpr());
       continue;
@@ -4633,7 +4607,7 @@
   // Try to find a variable that the receiver is strongly owned by.
   RetainCycleOwner owner;
   if (msg->getReceiverKind() == ObjCMessageExpr::Instance) {
-    if (!findRetainCycleOwner(msg->getInstanceReceiver(), owner))
+    if (!findRetainCycleOwner(*this, msg->getInstanceReceiver(), owner))
       return;
   } else {
     assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance);
@@ -4651,7 +4625,7 @@
 /// Check a property assign to see if it's likely to cause a retain cycle.
 void Sema::checkRetainCycles(Expr *receiver, Expr *argument) {
   RetainCycleOwner owner;
-  if (!findRetainCycleOwner(receiver, owner))
+  if (!findRetainCycleOwner(*this, receiver, owner))
     return;
 
   if (Expr *capturer = findCapturingExpr(*this, argument, owner))
@@ -4678,7 +4652,19 @@
 
 void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
                               Expr *LHS, Expr *RHS) {
-  QualType LHSType = LHS->getType();
+  QualType LHSType;
+  // PropertyRef on LHS type need be directly obtained from
+  // its declaration as it has a PsuedoType.
+  ObjCPropertyRefExpr *PRE
+    = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens());
+  if (PRE && !PRE->isImplicitProperty()) {
+    const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
+    if (PD)
+      LHSType = PD->getType();
+  }
+  
+  if (LHSType.isNull())
+    LHSType = LHS->getType();
   if (checkUnsafeAssigns(Loc, LHSType, RHS))
     return;
   Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime();
@@ -4686,8 +4672,7 @@
   if (LT != Qualifiers::OCL_None)
     return;
   
-  if (ObjCPropertyRefExpr *PRE
-        = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens())) {
+  if (PRE) {
     if (PRE->isImplicitProperty())
       return;
     const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
@@ -4695,7 +4680,15 @@
       return;
     
     unsigned Attributes = PD->getPropertyAttributes();
-    if (Attributes & ObjCPropertyDecl::OBJC_PR_assign)
+    if (Attributes & ObjCPropertyDecl::OBJC_PR_assign) {
+      // when 'assign' attribute was not explicitly specified
+      // by user, ignore it and rely on property type itself
+      // for lifetime info.
+      unsigned AsWrittenAttr = PD->getPropertyAttributesAsWritten();
+      if (!(AsWrittenAttr & ObjCPropertyDecl::OBJC_PR_assign) &&
+          LHSType->isObjCRetainableType())
+        return;
+        
       while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
         if (cast->getCastKind() == CK_ARCConsumeObject) {
           Diag(Loc, diag::warn_arc_retained_property_assign)
@@ -4704,5 +4697,6 @@
         }
         RHS = cast->getSubExpr();
       }
+    }
   }
 }

Modified: cfe/branches/tooling/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaCodeComplete.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaCodeComplete.cpp Fri Jan 20 10:14:22 2012
@@ -596,8 +596,7 @@
       default:
         return STC_Arithmetic;
     }
-    return STC_Other;
-    
+
   case Type::Complex:
     return STC_Arithmetic;
     
@@ -1370,19 +1369,24 @@
   case Sema::PCC_ForInit:
     return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
   }
-  
-  return false;
+
+  llvm_unreachable("Invalid ParserCompletionContext!");
 }
 
-/// \brief Retrieve a printing policy suitable for code completion.
-static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
-  PrintingPolicy Policy = S.getPrintingPolicy();
+static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
+                                                  const Preprocessor &PP) {
+  PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
   Policy.AnonymousTagLocations = false;
   Policy.SuppressStrongLifetime = true;
   Policy.SuppressUnwrittenScope = true;
   return Policy;
 }
 
+/// \brief Retrieve a printing policy suitable for code completion.
+static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
+  return getCompletionPrintingPolicy(S.Context, S.PP);
+}
+
 /// \brief Retrieve the string representation of the given type as a string
 /// that has the appropriate lifetime for code completion.
 ///
@@ -1751,7 +1755,7 @@
   case Sema::PCC_Expression: {
     if (SemaRef.getLangOptions().CPlusPlus) {
       // 'this', if we're in a non-static member function.
-      QualType ThisTy = SemaRef.getCurrentThisType(false);
+      QualType ThisTy = SemaRef.getCurrentThisType();
       if (!ThisTy.isNull()) {
         Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy, 
                                                            SemaRef.Context, 
@@ -2409,6 +2413,11 @@
   }
 }
 
+CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
+                                         CodeCompletionAllocator &Allocator) {
+  return CreateCodeCompletionString(S.Context, S.PP, Allocator);
+}
+
 /// \brief If possible, create a new code completion string for the given
 /// result.
 ///
@@ -2416,12 +2425,13 @@
 /// how to use this result, or NULL to indicate that the string or name of the
 /// result is all that is needed.
 CodeCompletionString *
-CodeCompletionResult::CreateCodeCompletionString(Sema &S,
+CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
+                                                 Preprocessor &PP,
                                            CodeCompletionAllocator &Allocator) {
   typedef CodeCompletionString::Chunk Chunk;
   CodeCompletionBuilder Result(Allocator, Priority, Availability);
   
-  PrintingPolicy Policy = getCompletionPrintingPolicy(S);
+  PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
   if (Kind == RK_Pattern) {
     Pattern->Priority = Priority;
     Pattern->Availability = Availability;
@@ -2434,7 +2444,7 @@
   }
   
   if (Kind == RK_Macro) {
-    MacroInfo *MI = S.PP.getMacroInfo(Macro);
+    MacroInfo *MI = PP.getMacroInfo(Macro);
     assert(MI && "Not a macro?");
 
     Result.AddTypedTextChunk(
@@ -2505,14 +2515,14 @@
     }
   }
   
-  AddResultTypeChunk(S.Context, Policy, ND, Result);
+  AddResultTypeChunk(Ctx, Policy, ND, Result);
   
   if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
     AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
-                                   S.Context, Policy);
-    AddTypedNameChunk(S.Context, Policy, ND, Result);
+                                   Ctx, Policy);
+    AddTypedNameChunk(Ctx, Policy, ND, Result);
     Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
-    AddFunctionParameterChunks(S.Context, Policy, Function, Result);
+    AddFunctionParameterChunks(Ctx, Policy, Function, Result);
     Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
     AddFunctionTypeQualsToCompletionString(Result, Function);
     return Result.TakeString();
@@ -2520,14 +2530,14 @@
   
   if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
     AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
-                                   S.Context, Policy);
+                                   Ctx, Policy);
     FunctionDecl *Function = FunTmpl->getTemplatedDecl();
-    AddTypedNameChunk(S.Context, Policy, Function, Result);
+    AddTypedNameChunk(Ctx, Policy, Function, Result);
 
     // Figure out which template parameters are deduced (or have default
     // arguments).
     SmallVector<bool, 16> Deduced;
-    S.MarkDeducedTemplateParameters(FunTmpl, Deduced);
+    Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
     unsigned LastDeducibleArgument;
     for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
          --LastDeducibleArgument) {
@@ -2559,14 +2569,14 @@
       // function call, so we introduce an explicit template argument list
       // containing all of the arguments up to the first deducible argument.
       Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
-      AddTemplateParameterChunks(S.Context, Policy, FunTmpl, Result, 
+      AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result, 
                                  LastDeducibleArgument);
       Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
     }
     
     // Add the function parameters
     Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
-    AddFunctionParameterChunks(S.Context, Policy, Function, Result);
+    AddFunctionParameterChunks(Ctx, Policy, Function, Result);
     Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
     AddFunctionTypeQualsToCompletionString(Result, Function);
     return Result.TakeString();
@@ -2574,11 +2584,11 @@
   
   if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
     AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
-                                   S.Context, Policy);
+                                   Ctx, Policy);
     Result.AddTypedTextChunk(
                 Result.getAllocator().CopyString(Template->getNameAsString()));
     Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
-    AddTemplateParameterChunks(S.Context, Policy, Template, Result);
+    AddTemplateParameterChunks(Ctx, Policy, Template, Result);
     Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
     return Result.TakeString();
   }
@@ -2627,7 +2637,7 @@
       std::string Arg;
       
       if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
-        Arg = FormatFunctionParameter(S.Context, Policy, *P, true);
+        Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
       else {
         (*P)->getType().getAsStringInternal(Arg, Policy);
         Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier()) 
@@ -2658,7 +2668,7 @@
           Result.AddPlaceholderChunk(", ...");
       }
       
-      MaybeAddSentinel(S.Context, Method, Result);
+      MaybeAddSentinel(Ctx, Method, Result);
     }
     
     return Result.TakeString();
@@ -2666,7 +2676,7 @@
 
   if (Qualifier)
     AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
-                                   S.Context, Policy);
+                                   Ctx, Policy);
 
   Result.AddTypedTextChunk(
                        Result.getAllocator().CopyString(ND->getNameAsString()));
@@ -2781,14 +2791,15 @@
       return CXCursor_FunctionDecl;
     case Decl::ObjCCategory:       return CXCursor_ObjCCategoryDecl;
     case Decl::ObjCCategoryImpl:   return CXCursor_ObjCCategoryImplDecl;
-    case Decl::ObjCClass:
-      // FIXME
-      return CXCursor_UnexposedDecl;
-    case Decl::ObjCForwardProtocol:
-      // FIXME
-      return CXCursor_UnexposedDecl;      
     case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
-    case Decl::ObjCInterface:      return CXCursor_ObjCInterfaceDecl;
+
+    case Decl::ObjCInterface:
+      if (cast<ObjCInterfaceDecl>(D)->isThisDeclarationADefinition())
+        return CXCursor_ObjCInterfaceDecl;
+      
+      // Forward declarations are not directly exposed.
+      return CXCursor_UnexposedDecl;
+
     case Decl::ObjCIvar:           return CXCursor_ObjCIvarDecl; 
     case Decl::ObjCMethod:
       return cast<ObjCMethodDecl>(D)->isInstanceMethod()
@@ -2798,7 +2809,12 @@
     case Decl::CXXDestructor:      return CXCursor_Destructor;
     case Decl::CXXConversion:      return CXCursor_ConversionFunction;
     case Decl::ObjCProperty:       return CXCursor_ObjCPropertyDecl;
-    case Decl::ObjCProtocol:       return CXCursor_ObjCProtocolDecl;
+    case Decl::ObjCProtocol:       
+      if (cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition())
+        return CXCursor_ObjCProtocolDecl;
+      
+      return CXCursor_UnexposedDecl;
+      
     case Decl::ParmVar:            return CXCursor_ParmDecl;
     case Decl::Typedef:            return CXCursor_TypedefDecl;
     case Decl::TypeAlias:          return CXCursor_TypeAliasDecl;
@@ -2828,7 +2844,6 @@
       case ObjCPropertyImplDecl::Synthesize:
         return CXCursor_ObjCSynthesizeDecl;
       }
-      break;
       
     default:
       if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
@@ -2907,10 +2922,9 @@
   case Sema::PCC_MemberTemplate:
     if (S.CurContext->isFileContext())
       return CodeCompletionContext::CCC_TopLevel;
-    else if (S.CurContext->isRecord())
+    if (S.CurContext->isRecord())
       return CodeCompletionContext::CCC_ClassStructUnion;
-    else 
-      return CodeCompletionContext::CCC_Other;
+    return CodeCompletionContext::CCC_Other;
       
   case Sema::PCC_RecoveryInFunction:
     return CodeCompletionContext::CCC_Recovery;
@@ -2938,8 +2952,8 @@
   case Sema::PCC_LocalDeclarationSpecifiers:
     return CodeCompletionContext::CCC_Type;
   }
-  
-  return CodeCompletionContext::CCC_Other;
+
+  llvm_unreachable("Invalid ParserCompletionContext!");
 }
 
 /// \brief If we're in a C++ virtual member function, add completion results
@@ -4548,13 +4562,16 @@
   
   // Visit the protocols of protocols.
   if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
-    const ObjCList<ObjCProtocolDecl> &Protocols
-      = Protocol->getReferencedProtocols();
-    for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
-                                              E = Protocols.end(); 
-         I != E; ++I)
-      AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, 
-                     CurContext, Selectors, AllowSameLength, Results, false);    
+    if (Protocol->hasDefinition()) {
+      const ObjCList<ObjCProtocolDecl> &Protocols
+        = Protocol->getReferencedProtocols();
+      for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+                                                E = Protocols.end(); 
+           I != E; ++I)
+        AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, 
+                       NumSelIdents, CurContext, Selectors, AllowSameLength, 
+                       Results, false);
+    }
   }
   
   ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
@@ -5411,19 +5428,8 @@
        D != DEnd; ++D) {
     // Record any protocols we find.
     if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
-      if (!OnlyForwardDeclarations || Proto->isForwardDecl())
+      if (!OnlyForwardDeclarations || !Proto->hasDefinition())
         Results.AddResult(Result(Proto, 0), CurContext, 0, false);
-
-    // Record any forward-declared protocols we find.
-    if (ObjCForwardProtocolDecl *Forward
-          = dyn_cast<ObjCForwardProtocolDecl>(*D)) {
-      for (ObjCForwardProtocolDecl::protocol_iterator 
-             P = Forward->protocol_begin(),
-             PEnd = Forward->protocol_end();
-           P != PEnd; ++P)
-        if (!OnlyForwardDeclarations || (*P)->isForwardDecl())
-          Results.AddResult(Result(*P, 0), CurContext, 0, false);
-    }
   }
 }
 
@@ -5490,15 +5496,6 @@
       if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
           (!OnlyUnimplemented || !Class->getImplementation()))
         Results.AddResult(Result(Class, 0), CurContext, 0, false);
-
-    // Record any forward-declared interfaces we find.
-    if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
-      ObjCInterfaceDecl *IDecl = Forward->getForwardInterfaceDecl();
-      if ((!OnlyForwardDeclarations || !IDecl->hasDefinition()) &&
-          (!OnlyUnimplemented || !IDecl->getImplementation()))
-        Results.AddResult(Result(IDecl, 0), CurContext,
-                          0, false);
-    }
   }
 }
 
@@ -5826,14 +5823,16 @@
   }
 
   if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
-    // Recurse into protocols.
-    const ObjCList<ObjCProtocolDecl> &Protocols
-      = Protocol->getReferencedProtocols();
-    for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
-           E = Protocols.end(); 
-         I != E; ++I)
-      FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
-                               KnownMethods, false);
+    if (Protocol->hasDefinition()) {
+      // Recurse into protocols.
+      const ObjCList<ObjCProtocolDecl> &Protocols
+        = Protocol->getReferencedProtocols();
+      for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+             E = Protocols.end(); 
+           I != E; ++I)
+        FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
+                                 KnownMethods, false);
+    }
   }
 
   // Add methods in this container. This operation occurs last because

Modified: cfe/branches/tooling/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaDecl.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaDecl.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaDecl.cpp Fri Jan 20 10:14:22 2012
@@ -55,6 +55,30 @@
   return DeclGroupPtrTy::make(DeclGroupRef(Ptr));
 }
 
+namespace {
+
+class TypeNameValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  TypeNameValidatorCCC(bool AllowInvalid) : AllowInvalidDecl(AllowInvalid) {
+    WantExpressionKeywords = false;
+    WantCXXNamedCasts = false;
+    WantRemainingKeywords = false;
+  }
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    if (NamedDecl *ND = candidate.getCorrectionDecl())
+      return (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
+          (AllowInvalidDecl || !ND->isInvalidDecl());
+    else
+      return candidate.isKeyword();
+  }
+
+ private:
+  bool AllowInvalidDecl;
+};
+
+}
+
 /// \brief If the identifier refers to a type name within this scope,
 /// return the declaration of that type.
 ///
@@ -147,9 +171,9 @@
   case LookupResult::NotFound:
   case LookupResult::NotFoundInCurrentInstantiation:
     if (CorrectedII) {
+      TypeNameValidatorCCC Validator(true);
       TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(),
-                                              Kind, S, SS, 0, false,
-                                              Sema::CTC_Type);
+                                              Kind, S, SS, &Validator);
       IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
       TemplateTy Template;
       bool MemberOfUnknownSpecialization;
@@ -291,7 +315,6 @@
   if (R.getResultKind() == LookupResult::Found)
     if (const TagDecl *TD = R.getAsSingle<TagDecl>()) {
       switch (TD->getTagKind()) {
-      default:         return DeclSpec::TST_unspecified;
       case TTK_Struct: return DeclSpec::TST_struct;
       case TTK_Union:  return DeclSpec::TST_union;
       case TTK_Class:  return DeclSpec::TST_class;
@@ -340,9 +363,10 @@
   
   // There may have been a typo in the name of the type. Look up typo
   // results, in case we have something that we can suggest.
+  TypeNameValidatorCCC Validator(false);
   if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(&II, IILoc),
-                                             LookupOrdinaryName, S, SS, NULL,
-                                             false, CTC_Type)) {
+                                             LookupOrdinaryName, S, SS,
+                                             &Validator)) {
     std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
     std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
 
@@ -351,32 +375,28 @@
       // FIXME: Actually recover with the keyword we suggest, and emit a fix-it.
       Diag(IILoc, diag::err_unknown_typename_suggest)
         << &II << CorrectedQuotedStr;
-      return true;      
     } else {
       NamedDecl *Result = Corrected.getCorrectionDecl();
-      if ((isa<TypeDecl>(Result) || isa<ObjCInterfaceDecl>(Result)) &&
-          !Result->isInvalidDecl()) {
-        // We found a similarly-named type or interface; suggest that.
-        if (!SS || !SS->isSet())
-          Diag(IILoc, diag::err_unknown_typename_suggest)
-            << &II << CorrectedQuotedStr
-            << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
-        else if (DeclContext *DC = computeDeclContext(*SS, false))
-          Diag(IILoc, diag::err_unknown_nested_typename_suggest) 
-            << &II << DC << CorrectedQuotedStr << SS->getRange()
-            << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
-        else
-          llvm_unreachable("could not have corrected a typo here");
+      // We found a similarly-named type or interface; suggest that.
+      if (!SS || !SS->isSet())
+        Diag(IILoc, diag::err_unknown_typename_suggest)
+          << &II << CorrectedQuotedStr
+          << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
+      else if (DeclContext *DC = computeDeclContext(*SS, false))
+        Diag(IILoc, diag::err_unknown_nested_typename_suggest)
+          << &II << DC << CorrectedQuotedStr << SS->getRange()
+          << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
+      else
+        llvm_unreachable("could not have corrected a typo here");
 
-        Diag(Result->getLocation(), diag::note_previous_decl)
-          << CorrectedQuotedStr;
-        
-        SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS,
-                                    false, false, ParsedType(),
-                                    /*NonTrivialTypeSourceInfo=*/true);
-        return true;
-      }
+      Diag(Result->getLocation(), diag::note_previous_decl)
+        << CorrectedQuotedStr;
+
+      SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS,
+                                  false, false, ParsedType(),
+                                  /*NonTrivialTypeSourceInfo=*/true);
     }
+    return true;
   }
 
   if (getLangOptions().CPlusPlus) {
@@ -547,9 +567,10 @@
     // close to this name.
     if (!SecondTry) {
       SecondTry = true;
+      CorrectionCandidateCallback DefaultValidator;
       if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
                                                  Result.getLookupKind(), S, 
-                                                 &SS)) {
+                                                 &SS, &DefaultValidator)) {
         unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
         unsigned QualifiedDiag = diag::err_no_member_suggest;
         std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
@@ -1095,7 +1116,7 @@
   if (D->isInvalidDecl())
     return false;
 
-  if (D->isUsed() || D->hasAttr<UnusedAttr>())
+  if (D->isReferenced() || D->isUsed() || D->hasAttr<UnusedAttr>())
     return false;
 
   if (isa<LabelDecl>(D))
@@ -1107,7 +1128,7 @@
     return false;
 
   // Types of valid local variables should be complete, so this should succeed.
-  if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
 
     // White-list anything with an __attribute__((unused)) type.
     QualType Ty = VD->getType();
@@ -1129,11 +1150,18 @@
         return false;
 
       if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) {
-        // FIXME: Checking for the presence of a user-declared constructor
-        // isn't completely accurate; we'd prefer to check that the initializer
-        // has no side effects.
-        if (RD->hasUserDeclaredConstructor() || !RD->hasTrivialDestructor())
+        if (!RD->hasTrivialDestructor())
           return false;
+
+        if (const Expr *Init = VD->getInit()) {
+          const CXXConstructExpr *Construct =
+            dyn_cast<CXXConstructExpr>(Init);
+          if (Construct && !Construct->isElidable()) {
+            CXXConstructorDecl *CD = Construct->getConstructor();
+            if (!CD->isTrivial())
+              return false;
+          }
+        }
       }
     }
 
@@ -1235,10 +1263,11 @@
   if (!IDecl && DoTypoCorrection) {
     // Perform typo correction at the given location, but only if we
     // find an Objective-C class name.
-    TypoCorrection C;
-    if ((C = CorrectTypo(DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName,
-                         TUScope, NULL, NULL, false, CTC_NoKeywords)) &&
-        (IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>())) {
+    DeclFilterCCC<ObjCInterfaceDecl> Validator;
+    if (TypoCorrection C = CorrectTypo(DeclarationNameInfo(Id, IdLoc),
+                                       LookupOrdinaryName, TUScope, NULL,
+                                       &Validator)) {
+      IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();
       Diag(IdLoc, diag::err_undef_interface_suggest)
         << Id << IDecl->getDeclName() 
         << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString());
@@ -1248,8 +1277,11 @@
       Id = IDecl->getIdentifier();
     }
   }
-
-  return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
+  ObjCInterfaceDecl *Def = dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
+  // This routine must always return a class definition, if any.
+  if (Def && Def->getDefinition())
+      Def = Def->getDefinition();
+  return Def;
 }
 
 /// getNonFieldDeclScope - Retrieves the innermost scope, starting
@@ -1368,6 +1400,40 @@
   return New;
 }
 
+bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
+  QualType OldType;
+  if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
+    OldType = OldTypedef->getUnderlyingType();
+  else
+    OldType = Context.getTypeDeclType(Old);
+  QualType NewType = New->getUnderlyingType();
+
+  if (NewType->isVariablyModifiedType()) {
+    // Must not redefine a typedef with a variably-modified type.
+    int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0;
+    Diag(New->getLocation(), diag::err_redefinition_variably_modified_typedef)
+      << Kind << NewType;
+    if (Old->getLocation().isValid())
+      Diag(Old->getLocation(), diag::note_previous_definition);
+    New->setInvalidDecl();
+    return true;    
+  }
+  
+  if (OldType != NewType &&
+      !OldType->isDependentType() &&
+      !NewType->isDependentType() &&
+      !Context.hasSameType(OldType, NewType)) { 
+    int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0;
+    Diag(New->getLocation(), diag::err_redefinition_different_typedef)
+      << Kind << NewType << OldType;
+    if (Old->getLocation().isValid())
+      Diag(Old->getLocation(), diag::note_previous_definition);
+    New->setInvalidDecl();
+    return true;
+  }
+  return false;
+}
+
 /// MergeTypedefNameDecl - 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
@@ -1426,42 +1492,16 @@
   if (Old->isInvalidDecl())
     return New->setInvalidDecl();
 
-  // Determine the "old" type we'll use for checking and diagnostics.
-  QualType OldType;
-  if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
-    OldType = OldTypedef->getUnderlyingType();
-  else
-    OldType = Context.getTypeDeclType(Old);
-
   // If the typedef types are not identical, reject them in all languages and
   // with any extensions enabled.
-
-  if (OldType != New->getUnderlyingType() &&
-      Context.getCanonicalType(OldType) !=
-      Context.getCanonicalType(New->getUnderlyingType())) {
-    int Kind = 0;
-    if (isa<TypeAliasDecl>(Old))
-      Kind = 1;
-    Diag(New->getLocation(), diag::err_redefinition_different_typedef)
-      << Kind << New->getUnderlyingType() << OldType;
-    if (Old->getLocation().isValid())
-      Diag(Old->getLocation(), diag::note_previous_definition);
-    return New->setInvalidDecl();
-  }
+  if (isIncompatibleTypedef(Old, New))
+    return;
 
   // The types match.  Link up the redeclaration chain if the old
   // declaration was a typedef.
-  // FIXME: this is a potential source of weirdness if the type
-  // spellings don't match exactly.
   if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old))
     New->setPreviousDeclaration(Typedef);
 
-  // __module_private__ is propagated to later declarations.
-  if (Old->isModulePrivate())
-    New->setModulePrivate();
-  else if (New->isModulePrivate())
-    diagnoseModulePrivateRedeclaration(New, Old);
-           
   if (getLangOptions().MicrosoftExt)
     return;
 
@@ -1503,6 +1543,10 @@
     return New->setInvalidDecl();
   }
 
+  // Modules always permit redefinition of typedefs, as does C11.
+  if (getLangOptions().Modules || getLangOptions().C11)
+    return;
+  
   // If we have a redefinition of a typedef in C, emit a warning.  This warning
   // is normally mapped to an error, but can be controlled with
   // -Wtypedef-redefinition.  If either the original or the redefinition is
@@ -1541,36 +1585,37 @@
 }
 
 /// mergeDeclAttributes - Copy attributes from the Old decl to the New one.
-static void mergeDeclAttributes(Decl *newDecl, const Decl *oldDecl,
-                                ASTContext &C, bool mergeDeprecation = true) {
-  if (!oldDecl->hasAttrs())
+void Sema::mergeDeclAttributes(Decl *New, Decl *Old,
+                               bool MergeDeprecation) {
+  if (!Old->hasAttrs())
     return;
 
-  bool foundAny = newDecl->hasAttrs();
+  bool foundAny = New->hasAttrs();
 
   // Ensure that any moving of objects within the allocated map is done before
   // we process them.
-  if (!foundAny) newDecl->setAttrs(AttrVec());
+  if (!foundAny) New->setAttrs(AttrVec());
 
   for (specific_attr_iterator<InheritableAttr>
-       i = oldDecl->specific_attr_begin<InheritableAttr>(),
-       e = oldDecl->specific_attr_end<InheritableAttr>(); i != e; ++i) {
+         i = Old->specific_attr_begin<InheritableAttr>(),
+         e = Old->specific_attr_end<InheritableAttr>(); 
+       i != e; ++i) {
     // Ignore deprecated/unavailable/availability attributes if requested.
-    if (!mergeDeprecation &&
+    if (!MergeDeprecation &&
         (isa<DeprecatedAttr>(*i) || 
          isa<UnavailableAttr>(*i) ||
          isa<AvailabilityAttr>(*i)))
       continue;
 
-    if (!DeclHasAttr(newDecl, *i)) {
-      InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(C));
+    if (!DeclHasAttr(New, *i)) {
+      InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(Context));
       newAttr->setInherited(true);
-      newDecl->addAttr(newAttr);
+      New->addAttr(newAttr);
       foundAny = true;
     }
   }
 
-  if (!foundAny) newDecl->dropAttrs();
+  if (!foundAny) New->dropAttrs();
 }
 
 /// mergeParamDeclAttributes - Copy attributes from the old parameter
@@ -2036,7 +2081,7 @@
 /// \returns false
 bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
   // Merge the attributes
-  mergeDeclAttributes(New, Old, Context);
+  mergeDeclAttributes(New, Old);
 
   // Merge the storage class.
   if (Old->getStorageClass() != SC_Extern &&
@@ -2047,12 +2092,6 @@
   if (Old->isPure())
     New->setPure();
 
-  // __module_private__ is propagated to later declarations.
-  if (Old->isModulePrivate())
-    New->setModulePrivate();
-  else if (New->isModulePrivate())
-    diagnoseModulePrivateRedeclaration(New, Old);
-
   // Merge attributes from the parameters.  These can mismatch with K&R
   // declarations.
   if (New->getNumParams() == Old->getNumParams())
@@ -2068,13 +2107,13 @@
 
 
 void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
-                                const ObjCMethodDecl *oldMethod) {
+                                ObjCMethodDecl *oldMethod) {
   // We don't want to merge unavailable and deprecated attributes
   // except from interface to implementation.
   bool mergeDeprecation = isa<ObjCImplDecl>(newMethod->getDeclContext());
 
   // Merge the attributes.
-  mergeDeclAttributes(newMethod, oldMethod, Context, mergeDeprecation);
+  mergeDeclAttributes(newMethod, oldMethod, mergeDeprecation);
 
   // Merge attributes from the parameters.
   ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin();
@@ -2181,7 +2220,7 @@
     New->setInvalidDecl();
   }
   
-  mergeDeclAttributes(New, Old, Context);
+  mergeDeclAttributes(New, Old);
   // Warn if an already-declared variable is made a weak_import in a subsequent 
   // declaration
   if (New->getAttr<WeakImportAttr>() &&
@@ -2237,12 +2276,6 @@
     return New->setInvalidDecl();
   }
 
-  // __module_private__ is propagated to later declarations.
-  if (Old->isModulePrivate())
-    New->setModulePrivate();
-  else if (New->isModulePrivate())
-    diagnoseModulePrivateRedeclaration(New, Old);
-
   // Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
 
   // FIXME: The test for external storage here seems wrong? We still
@@ -2486,25 +2519,6 @@
   return TagD;
 }
 
-/// ActOnVlaStmt - This rouine if finds a vla expression in a decl spec.
-/// builds a statement for it and returns it so it is evaluated.
-StmtResult Sema::ActOnVlaStmt(const DeclSpec &DS) {
-  StmtResult R;
-  if (DS.getTypeSpecType() == DeclSpec::TST_typeofExpr) {
-    Expr *Exp = DS.getRepAsExpr();
-    QualType Ty = Exp->getType();
-    if (Ty->isPointerType()) {
-      do
-        Ty = Ty->getAs<PointerType>()->getPointeeType();
-      while (Ty->isPointerType());
-    }
-    if (Ty->isVariableArrayType()) {
-      R = ActOnExprStmt(MakeFullExpr(Exp));
-    }
-  }
-  return R;
-}
-
 /// We are trying to inject an anonymous member into the given scope;
 /// check if there's an existing declaration that can't be overloaded.
 ///
@@ -3966,38 +3980,8 @@
                                            TemplateParamLists.release());
     }
 
-    if (D.getDeclSpec().isConstexprSpecified()) {
-      // FIXME: once we know whether there's an initializer, apply this to
-      // static data members too.
-      if (!NewVD->isStaticDataMember() &&
-          !NewVD->isThisDeclarationADefinition()) {
-        // 'constexpr' is redundant and ill-formed on a non-defining declaration
-        // of a variable. Suggest replacing it with 'const' if appropriate.
-        SourceLocation ConstexprLoc = D.getDeclSpec().getConstexprSpecLoc();
-        SourceRange ConstexprRange(ConstexprLoc, ConstexprLoc);
-        // If the declarator is complex, we need to move the keyword to the
-        // innermost chunk as we switch it from 'constexpr' to 'const'.
-        int Kind = DeclaratorChunk::Paren;
-        for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
-          Kind = D.getTypeObject(I).Kind;
-          if (Kind != DeclaratorChunk::Paren)
-            break;
-        }
-        if ((D.getDeclSpec().getTypeQualifiers() & DeclSpec::TQ_const) ||
-            Kind == DeclaratorChunk::Reference)
-          Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl)
-            << FixItHint::CreateRemoval(ConstexprRange);
-        else if (Kind == DeclaratorChunk::Paren)
-          Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl)
-            << FixItHint::CreateReplacement(ConstexprRange, "const");
-        else
-          Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl)
-            << FixItHint::CreateRemoval(ConstexprRange)
-            << FixItHint::CreateInsertion(D.getIdentifierLoc(), "const ");
-      } else {
-        NewVD->setConstexpr(true);
-      }
-    }
+    if (D.getDeclSpec().isConstexprSpecified())
+      NewVD->setConstexpr(true);
   }
 
   // Set the lexical context. If the declarator has a C++ scope specifier, the
@@ -4448,6 +4432,18 @@
   };
 }
 
+namespace {
+
+// Callback to only accept typo corrections that have a non-zero edit distance.
+class DifferentNameValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    return candidate.getEditDistance() > 0;
+  }
+};
+
+}
+
 /// \brief Generate diagnostics for an invalid function redeclaration.
 ///
 /// This routine handles generating the diagnostic messages for an invalid
@@ -4477,6 +4473,7 @@
   SemaRef.LookupQualifiedName(Prev, NewDC);
   assert(!Prev.isAmbiguous() &&
          "Cannot have an ambiguity in previous-declaration lookup");
+  DifferentNameValidatorCCC Validator;
   if (!Prev.empty()) {
     for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
          Func != FuncEnd; ++Func) {
@@ -4492,8 +4489,8 @@
     }
   // If the qualified name lookup yielded nothing, try typo correction
   } else if ((Correction = SemaRef.CorrectTypo(Prev.getLookupNameInfo(),
-                                         Prev.getLookupKind(), 0, 0, NewDC)) &&
-             Correction.getCorrection() != Name) {
+                                         Prev.getLookupKind(), 0, 0,
+                                         &Validator, NewDC))) {
     // Trap errors.
     Sema::SFINAETrap Trap(SemaRef);
 
@@ -4946,6 +4943,56 @@
         FunctionTemplate->setInvalidDecl();
     }
 
+    // If we see "T var();" at block scope, where T is a class type, it is
+    // probably an attempt to initialize a variable, not a function declaration.
+    // We don't catch this case earlier, since there is no ambiguity here.
+    if (!FunctionTemplate && D.getFunctionDefinitionKind() == FDK_Declaration &&
+        CurContext->isFunctionOrMethod() &&
+        D.getNumTypeObjects() == 1 && D.isFunctionDeclarator() &&
+        D.getDeclSpec().getStorageClassSpecAsWritten()
+          == DeclSpec::SCS_unspecified) {
+      QualType T = R->getAs<FunctionType>()->getResultType();
+      DeclaratorChunk &C = D.getTypeObject(0);
+      if (!T->isVoidType() && C.Fun.NumArgs == 0 && !C.Fun.isVariadic &&
+          !C.Fun.TrailingReturnType &&
+          C.Fun.getExceptionSpecType() == EST_None) {
+        SourceRange ParenRange(C.Loc, C.EndLoc);
+        Diag(C.Loc, diag::warn_empty_parens_are_function_decl) << ParenRange;
+
+        // If the declaration looks like:
+        //   T var1,
+        //   f();
+        // and name lookup finds a function named 'f', then the ',' was
+        // probably intended to be a ';'.
+        if (!D.isFirstDeclarator() && D.getIdentifier()) {
+          FullSourceLoc Comma(D.getCommaLoc(), SourceMgr);
+          FullSourceLoc Name(D.getIdentifierLoc(), SourceMgr);
+          if (Comma.getFileID() != Name.getFileID() ||
+              Comma.getSpellingLineNumber() != Name.getSpellingLineNumber()) {
+            LookupResult Result(*this, D.getIdentifier(), SourceLocation(),
+                                LookupOrdinaryName);
+            if (LookupName(Result, S))
+              Diag(D.getCommaLoc(), diag::note_empty_parens_function_call)
+                << FixItHint::CreateReplacement(D.getCommaLoc(), ";") << NewFD;
+          }
+        }
+        const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+        // Empty parens mean value-initialization, and no parens mean default
+        // initialization. These are equivalent if the default constructor is
+        // user-provided, or if zero-initialization is a no-op.
+        if (RD && RD->hasDefinition() &&
+            (RD->isEmpty() || RD->hasUserProvidedDefaultConstructor()))
+          Diag(C.Loc, diag::note_empty_parens_default_ctor)
+            << FixItHint::CreateRemoval(ParenRange);
+        else if (const char *Init = getFixItZeroInitializerForType(T))
+          Diag(C.Loc, diag::note_empty_parens_zero_initialize)
+            << FixItHint::CreateReplacement(ParenRange, Init);
+        else if (LangOpts.CPlusPlus0x)
+          Diag(C.Loc, diag::note_empty_parens_zero_initialize)
+            << FixItHint::CreateReplacement(ParenRange, "{}");
+      }
+    }
+
     // C++ [dcl.fct.spec]p5:
     //   The virtual specifier shall only be used in declarations of
     //   nonstatic class member functions that appear within a
@@ -5318,7 +5365,7 @@
     if (isFriend && D.isRedeclaration()) {
       AccessSpecifier Access = AS_public;
       if (!NewFD->isInvalidDecl())
-        Access = NewFD->getPreviousDeclaration()->getAccess();
+        Access = NewFD->getPreviousDecl()->getAccess();
 
       NewFD->setAccess(Access);
       if (FunctionTemplate) FunctionTemplate->setAccess(Access);
@@ -5334,7 +5381,7 @@
     // list. This will check and merge default template arguments.
     if (FunctionTemplate) {
       FunctionTemplateDecl *PrevTemplate = 
-                                     FunctionTemplate->getPreviousDeclaration();
+                                     FunctionTemplate->getPreviousDecl();
       CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(),
                        PrevTemplate ? PrevTemplate->getTemplateParameters() : 0,
                             D.getDeclSpec().isFriendSpecified()
@@ -5627,9 +5674,6 @@
           assert(OldTemplateDecl->isMemberSpecialization());
         }
         
-        if (OldTemplateDecl->isModulePrivate())
-          NewTemplateDecl->setModulePrivate();
-        
       } else {
         if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
           NewFD->setAccess(OldDecl->getAccess());
@@ -5968,9 +6012,7 @@
   if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
     TypeSourceInfo *DeducedType = 0;
     if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType))
-      Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
-        << VDecl->getDeclName() << VDecl->getType() << Init->getType()
-        << Init->getSourceRange();
+      DiagnoseAutoDeductionFailure(VDecl, Init);
     if (!DeducedType) {
       RealDecl->setInvalidDecl();
       return;
@@ -5984,7 +6026,7 @@
 
     // If this is a redeclaration, check that the type we just deduced matches
     // the previously declared type.
-    if (VarDecl *Old = VDecl->getPreviousDeclaration())
+    if (VarDecl *Old = VDecl->getPreviousDecl())
       MergeVarDeclTypes(VDecl, Old);
   }
 
@@ -6090,7 +6132,7 @@
   // 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.
+  // "ary" transitions from an IncompleteArrayType to a ConstantArrayType.
   if (!VDecl->isInvalidDecl() && (DclT != SavT)) {
     VDecl->setType(DclT);
     Init->setType(DclT.getNonReferenceType());
@@ -6265,7 +6307,7 @@
   if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
     QualType Type = Var->getType();
 
-    // C++0x [dcl.spec.auto]p3
+    // C++11 [dcl.spec.auto]p3
     if (TypeMayContainAuto && Type->getContainedAutoType()) {
       Diag(Var->getLocation(), diag::err_auto_var_requires_init)
         << Var->getDeclName() << Type;
@@ -6273,13 +6315,19 @@
       return;
     }
 
-    // C++0x [class.static.data]p3: A static data member can be declared with
+    // C++11 [class.static.data]p3: A static data member can be declared with
     // the constexpr specifier; if so, its declaration shall specify
     // a brace-or-equal-initializer.
-    if (Var->isConstexpr() && Var->isStaticDataMember() &&
-        !Var->isThisDeclarationADefinition()) {
-      Diag(Var->getLocation(), diag::err_constexpr_static_mem_var_requires_init)
-        << Var->getDeclName();
+    // C++11 [dcl.constexpr]p1: The constexpr specifier shall be applied only to
+    // the definition of a variable [...] or the declaration of a static data
+    // member.
+    if (Var->isConstexpr() && !Var->isThisDeclarationADefinition()) {
+      if (Var->isStaticDataMember())
+        Diag(Var->getLocation(),
+             diag::err_constexpr_static_mem_var_requires_init)
+          << Var->getDeclName();
+      else
+        Diag(Var->getLocation(), diag::err_invalid_constexpr_var_decl);
       Var->setInvalidDecl();
       return;
     }
@@ -6338,7 +6386,7 @@
           // is accepted by gcc. Hence here we issue a warning instead of
           // an error and we do not invalidate the static declaration.
           // NOTE: to avoid multiple warnings, only check the first declaration.
-          if (Var->getPreviousDeclaration() == 0)
+          if (Var->getPreviousDecl() == 0)
             RequireCompleteType(Var->getLocation(), Type,
                                 diag::ext_typecheck_decl_incomplete_type);
         }
@@ -6539,17 +6587,37 @@
   Expr *Init = var->getInit();
   bool IsGlobal = var->hasGlobalStorage() && !var->isStaticLocal();
 
-  if (!var->getDeclContext()->isDependentContext() &&
-      (var->isConstexpr() || IsGlobal) && Init &&
-      !Init->isConstantInitializer(Context, baseType->isReferenceType())) {
-    // FIXME: Improve this diagnostic to explain why the initializer is not
-    // a constant expression.
-    if (var->isConstexpr())
-      Diag(var->getLocation(), diag::err_constexpr_var_requires_const_init)
-        << var << Init->getSourceRange();
-    if (IsGlobal)
+  if (!var->getDeclContext()->isDependentContext() && Init) {
+    if (IsGlobal && !var->isConstexpr() &&
+        getDiagnostics().getDiagnosticLevel(diag::warn_global_constructor,
+                                            var->getLocation())
+          != DiagnosticsEngine::Ignored &&
+        !Init->isConstantInitializer(Context, baseType->isReferenceType()))
       Diag(var->getLocation(), diag::warn_global_constructor)
         << Init->getSourceRange();
+
+    if (var->isConstexpr()) {
+      llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+      if (!var->evaluateValue(Notes) || !var->isInitICE()) {
+        SourceLocation DiagLoc = var->getLocation();
+        // If the note doesn't add any useful information other than a source
+        // location, fold it into the primary diagnostic.
+        if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
+              diag::note_invalid_subexpr_in_const_expr) {
+          DiagLoc = Notes[0].first;
+          Notes.clear();
+        }
+        Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
+          << var << Init->getSourceRange();
+        for (unsigned I = 0, N = Notes.size(); I != N; ++I)
+          Diag(Notes[I].first, Notes[I].second);
+      }
+    } else if (var->isUsableInConstantExpressions()) {
+      // Check whether the initializer of a const variable of integral or
+      // enumeration type is an ICE now, since we can't tell whether it was
+      // initialized by a constant expression if we check later.
+      var->checkInitIsICE();
+    }
   }
 
   // Require the destructor.
@@ -6769,7 +6837,7 @@
     return;
 
   for (; Param != ParamEnd; ++Param) {
-    if (!(*Param)->isUsed() && (*Param)->getDeclName() &&
+    if (!(*Param)->isReferenced() && (*Param)->getDeclName() &&
         !(*Param)->hasAttr<UnusedAttr>()) {
       Diag((*Param)->getLocation(), diag::warn_unused_parameter)
         << (*Param)->getDeclName();
@@ -6786,7 +6854,7 @@
 
   // Warn if the return value is pass-by-value and larger than the specified
   // threshold.
-  if (ReturnTy.isPODType(Context)) {
+  if (!ReturnTy->isDependentType() && ReturnTy.isPODType(Context)) {
     unsigned Size = Context.getTypeSizeInChars(ReturnTy).getQuantity();
     if (Size > LangOpts.NumLargeByValueCopy)
       Diag(D->getLocation(), diag::warn_return_value_size)
@@ -6797,7 +6865,7 @@
   // threshold.
   for (; Param != ParamEnd; ++Param) {
     QualType T = (*Param)->getType();
-    if (!T.isPODType(Context))
+    if (T->isDependentType() || !T.isPODType(Context))
       continue;
     unsigned Size = Context.getTypeSizeInChars(T).getQuantity();
     if (Size > LangOpts.NumLargeByValueCopy)
@@ -6946,8 +7014,8 @@
     return false;
 
   bool MissingPrototype = true;
-  for (const FunctionDecl *Prev = FD->getPreviousDeclaration();
-       Prev; Prev = Prev->getPreviousDeclaration()) {
+  for (const FunctionDecl *Prev = FD->getPreviousDecl();
+       Prev; Prev = Prev->getPreviousDecl()) {
     // Ignore any declarations that occur in function or method
     // scope, because they aren't visible from the header.
     if (Prev->getDeclContext()->isFunctionOrMethod())
@@ -7226,7 +7294,7 @@
   if (!IsInstantiation)
     PopDeclContext();
 
-  PopFunctionOrBlockScope(ActivePolicy, dcl);
+  PopFunctionScopeInfo(ActivePolicy, dcl);
   
   // If any errors have occurred, clear out any temporaries that may have
   // been leftover. This ensures that these temporaries won't be picked up for
@@ -7266,7 +7334,7 @@
   // Extension in C99.  Legal in C90, but warn about it.
   unsigned diag_id;
   if (II.getName().startswith("__builtin_"))
-    diag_id = diag::err_builtin_unknown;
+    diag_id = diag::warn_builtin_unknown;
   else if (getLangOptions().C99)
     diag_id = diag::ext_implicit_function_decl;
   else
@@ -7277,21 +7345,20 @@
   // function declaration is going to be treated as an error.
   if (Diags.getDiagnosticLevel(diag_id, Loc) >= DiagnosticsEngine::Error) {
     TypoCorrection Corrected;
+    DeclFilterCCC<FunctionDecl> Validator;
     if (S && (Corrected = CorrectTypo(DeclarationNameInfo(&II, Loc),
-                                      LookupOrdinaryName, S, 0))) {
-      NamedDecl *Decl = Corrected.getCorrectionDecl();
-      if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Decl)) {
-        std::string CorrectedStr = Corrected.getAsString(getLangOptions());
-        std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOptions());
-
-        Diag(Loc, diag::note_function_suggestion) << CorrectedQuotedStr
-            << FixItHint::CreateReplacement(Loc, CorrectedStr);
-
-        if (Func->getLocation().isValid()
-            && !II.getName().startswith("__builtin_"))
-          Diag(Func->getLocation(), diag::note_previous_decl)
-              << CorrectedQuotedStr;
-      }
+                                      LookupOrdinaryName, S, 0, &Validator))) {
+      std::string CorrectedStr = Corrected.getAsString(getLangOptions());
+      std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOptions());
+      FunctionDecl *Func = Corrected.getCorrectionDeclAs<FunctionDecl>();
+
+      Diag(Loc, diag::note_function_suggestion) << CorrectedQuotedStr
+          << FixItHint::CreateReplacement(Loc, CorrectedStr);
+
+      if (Func->getLocation().isValid()
+          && !II.getName().startswith("__builtin_"))
+        Diag(Func->getLocation(), diag::note_previous_decl)
+            << CorrectedQuotedStr;
     }
   }
 
@@ -7589,7 +7656,8 @@
                      SourceLocation ModulePrivateLoc,
                      MultiTemplateParamsArg TemplateParameterLists,
                      bool &OwnedDecl, bool &IsDependent,
-                     bool ScopedEnum, bool ScopedEnumUsesClassTag,
+                     SourceLocation ScopedEnumKWLoc,
+                     bool ScopedEnumUsesClassTag,
                      TypeResult UnderlyingType) {
   // If this is not a definition, it must have a name.
   assert((Name != 0 || TUK == TUK_Definition) &&
@@ -7598,6 +7666,7 @@
 
   OwnedDecl = false;
   TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+  bool ScopedEnum = ScopedEnumKWLoc.isValid();
 
   // FIXME: Check explicit specializations more carefully.
   bool isExplicitSpecialization = false;
@@ -7836,7 +7905,8 @@
       // Find the context where we'll be declaring the tag.
       // FIXME: We would like to maintain the current DeclContext as the
       // lexical context,
-      while (SearchDC->isRecord() || SearchDC->isTransparentContext())
+      while (SearchDC->isRecord() || SearchDC->isTransparentContext() ||
+             SearchDC->isObjCContainer())
         SearchDC = SearchDC->getParent();
 
       // Find the scope where we'll be declaring the tag.
@@ -7928,6 +7998,16 @@
         if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) {
           const EnumDecl *PrevEnum = cast<EnumDecl>(PrevTagDecl);
 
+          // If this is an elaborated-type-specifier for a scoped enumeration,
+          // the 'class' keyword is not necessary and not permitted.
+          if (TUK == TUK_Reference || TUK == TUK_Friend) {
+            if (ScopedEnum)
+              Diag(ScopedEnumKWLoc, diag::err_enum_class_reference)
+                << PrevEnum->isScoped()
+                << FixItHint::CreateRemoval(ScopedEnumKWLoc);
+            return PrevTagDecl;
+          }
+
           // All conflicts with previous declarations are recovered by
           // returning the previous declaration.
           if (ScopedEnum != PrevEnum->isScoped()) {
@@ -8029,8 +8109,6 @@
     // lookup.  This is only actually possible in C++, where a few
     // things like templates still live in the tag namespace.
     } else {
-      assert(getLangOptions().CPlusPlus);
-
       // Use a better diagnostic if an elaborated-type-specifier
       // found the wrong kind of type on the first
       // (non-redeclaration) lookup.
@@ -8190,19 +8268,14 @@
     AddMsStructLayoutForRecord(RD);
   }
 
-  if (PrevDecl && PrevDecl->isModulePrivate())
-    New->setModulePrivate();
-  else if (ModulePrivateLoc.isValid()) {
+  if (ModulePrivateLoc.isValid()) {
     if (isExplicitSpecialization)
       Diag(New->getLocation(), diag::err_module_private_specialization)
         << 2
         << FixItHint::CreateRemoval(ModulePrivateLoc);
-    else if (PrevDecl && !PrevDecl->isModulePrivate())
-      diagnoseModulePrivateRedeclaration(New, PrevDecl, ModulePrivateLoc);
     // __module_private__ does not apply to local classes. However, we only
     // diagnose this as an error when the declaration specifiers are
     // freestanding. Here, we just ignore the __module_private__.
-    // foobar
     else if (!SearchDC->isFunctionOrMethod())
       New->setModulePrivate();
   }
@@ -9482,18 +9555,30 @@
     if (Enum->isDependentType() || Val->isTypeDependent())
       EltTy = Context.DependentTy;
     else {
-      // C99 6.7.2.2p2: Make sure we have an integer constant expression.
       SourceLocation ExpLoc;
-      if (!Val->isValueDependent() &&
-          VerifyIntegerConstantExpression(Val, &EnumVal)) {
+      if (getLangOptions().CPlusPlus0x && Enum->isFixed()) {
+        // C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the
+        // constant-expression in the enumerator-definition shall be a converted
+        // constant expression of the underlying type.
+        EltTy = Enum->getIntegerType();
+        ExprResult Converted =
+          CheckConvertedConstantExpression(Val, EltTy, EnumVal,
+                                           CCEK_Enumerator);
+        if (Converted.isInvalid())
+          Val = 0;
+        else
+          Val = Converted.take();
+      } else if (!Val->isValueDependent() &&
+                 VerifyIntegerConstantExpression(Val, &EnumVal)) {
+        // C99 6.7.2.2p2: Make sure we have an integer constant expression.
         Val = 0;
-      } else {        
+      } else {
         if (!getLangOptions().CPlusPlus) {
           // C99 6.7.2.2p2:
           //   The expression that defines the value of an enumeration constant
-          //   shall be an integer constant expression that has a value 
+          //   shall be an integer constant expression that has a value
           //   representable as an int.
-          
+
           // Complain if the value is not representable in an int.
           if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy))
             Diag(IdLoc, diag::ext_enum_value_not_int)
@@ -9504,25 +9589,24 @@
             Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take();
           }
         }
-        
+
         if (Enum->isFixed()) {
           EltTy = Enum->getIntegerType();
 
-          // C++0x [dcl.enum]p5:
-          //   ... if the initializing value of an enumerator cannot be
-          //   represented by the underlying type, the program is ill-formed.
+          // In Obj-C and Microsoft mode, require the enumeration value to be
+          // representable in the underlying type of the enumeration. In C++11,
+          // we perform a non-narrowing conversion as part of converted constant
+          // expression checking.
           if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
             if (getLangOptions().MicrosoftExt) {
               Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy;
               Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
-            } else 
-              Diag(IdLoc, diag::err_enumerator_too_large)
-                << EltTy;
+            } else
+              Diag(IdLoc, diag::err_enumerator_too_large) << EltTy;
           } else
             Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
-        }
-        else {
-          // C++0x [dcl.enum]p5:
+        } else {
+          // C++11 [dcl.enum]p5:
           //   If the underlying type is not fixed, the type of each enumerator
           //   is the type of its initializing value:
           //     - If an initializer is specified for an enumerator, the 
@@ -9627,11 +9711,10 @@
 Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
                               SourceLocation IdLoc, IdentifierInfo *Id,
                               AttributeList *Attr,
-                              SourceLocation EqualLoc, Expr *val) {
+                              SourceLocation EqualLoc, Expr *Val) {
   EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl);
   EnumConstantDecl *LastEnumConst =
     cast_or_null<EnumConstantDecl>(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.
@@ -9920,7 +10003,9 @@
   return New;
 }
 
-DeclResult Sema::ActOnModuleImport(SourceLocation ImportLoc, ModuleIdPath Path) {
+DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, 
+                                   SourceLocation ImportLoc, 
+                                   ModuleIdPath Path) {
   Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path, 
                                                 Module::AllVisible,
                                                 /*IsIncludeDirective=*/false);
@@ -9941,26 +10026,12 @@
 
   ImportDecl *Import = ImportDecl::Create(Context, 
                                           Context.getTranslationUnitDecl(),
-                                          ImportLoc, Mod,
-                                          IdentifierLocs);
+                                          AtLoc.isValid()? AtLoc : ImportLoc, 
+                                          Mod, IdentifierLocs);
   Context.getTranslationUnitDecl()->addDecl(Import);
   return Import;
 }
 
-void 
-Sema::diagnoseModulePrivateRedeclaration(NamedDecl *New, NamedDecl *Old,
-                                         SourceLocation ModulePrivateKeyword) {
-  assert(!Old->isModulePrivate() && "Old is module-private!");
-  
-  Diag(New->getLocation(), diag::err_module_private_follows_public)
-    << New->getDeclName() << SourceRange(ModulePrivateKeyword);
-  Diag(Old->getLocation(), diag::note_previous_declaration)
-    << Old->getDeclName();
-  
-  // Drop the __module_private__ from the new declaration, since it's invalid.
-  New->setModulePrivate(false);
-}
-
 void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
                              SourceLocation PragmaLoc,
                              SourceLocation NameLoc) {

Modified: cfe/branches/tooling/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaDeclAttr.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaDeclAttr.cpp Fri Jan 20 10:14:22 2012
@@ -1055,8 +1055,6 @@
       }
       break;
     }
-    default:
-      llvm_unreachable("Unknown ownership attribute");
     } // switch
 
     // Check we don't have a conflict with another ownership attribute.
@@ -1107,7 +1105,6 @@
     return false;
   }
   llvm_unreachable("unknown linkage kind!");
-  return false;
 }
 
 static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1579,6 +1576,23 @@
                                           Attr.getRange(), S.Context));
 }
 
+static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, 
+                                            const AttributeList &Attr) {
+  if (!isa<ObjCInterfaceDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::err_suppress_autosynthesis);
+    return;
+  }
+  
+  unsigned NumArgs = Attr.getNumArgs();
+  if (NumArgs > 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0;
+    return;
+  }
+  
+  D->addAttr(::new (S.Context) ObjCRequiresPropertyDefsAttr(
+                                 Attr.getRange(), S.Context));
+}
+
 static void handleAvailabilityAttr(Sema &S, Decl *D,
                                    const AttributeList &Attr) {
   IdentifierInfo *Platform = Attr.getParameterName();
@@ -1861,10 +1875,11 @@
       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
       return;
     }
-  } else if (isa<BlockDecl>(D)) {
-    // Note! BlockDecl is typeless. Variadic diagnostics will be issued by the
-    // caller.
-    ;
+  } else if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+    if (!BD->isVariadic()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1;
+      return;
+    }
   } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
     QualType Ty = V->getType();
     if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
@@ -2991,7 +3006,6 @@
   }
   default:
     llvm_unreachable("unexpected attribute kind");
-    return;
   }
 }
 
@@ -3040,7 +3054,7 @@
     }
     // FALLS THROUGH
   }
-  default: llvm_unreachable("unexpected attribute kind"); return true;
+  default: llvm_unreachable("unexpected attribute kind");
   }
 
   return false;
@@ -3226,7 +3240,7 @@
   bool typeOK;
   bool cf;
   switch (Attr.getKind()) {
-  default: llvm_unreachable("invalid ownership attribute"); return;
+  default: llvm_unreachable("invalid ownership attribute");
   case AttributeList::AT_ns_returns_autoreleased:
   case AttributeList::AT_ns_returns_retained:
   case AttributeList::AT_ns_returns_not_retained:
@@ -3603,6 +3617,9 @@
   case AttributeList::AT_arc_weakref_unavailable: 
     handleArcWeakrefUnavailableAttr (S, D, Attr); 
     break;
+  case AttributeList::AT_objc_requires_property_definitions: 
+    handleObjCRequiresPropertyDefsAttr (S, D, Attr); 
+    break;
   case AttributeList::AT_unused:      handleUnusedAttr      (S, D, Attr); break;
   case AttributeList::AT_returns_twice:
     handleReturnsTwiceAttr(S, D, Attr);

Modified: cfe/branches/tooling/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaDeclCXX.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaDeclCXX.cpp Fri Jan 20 10:14:22 2012
@@ -420,8 +420,8 @@
       
       // Look for the function declaration where the default argument was
       // actually written, which may be a declaration prior to Old.
-      for (FunctionDecl *Older = Old->getPreviousDeclaration();
-           Older; Older = Older->getPreviousDeclaration()) {
+      for (FunctionDecl *Older = Old->getPreviousDecl();
+           Older; Older = Older->getPreviousDecl()) {
         if (!Older->getParamDecl(p)->hasDefaultArg())
           break;
         
@@ -648,7 +648,7 @@
 // the requirements of a constexpr function declaration or a constexpr
 // constructor declaration. Return true if it does, false if not.
 //
-// This implements C++0x [dcl.constexpr]p3,4, as amended by N3308.
+// This implements C++11 [dcl.constexpr]p3,4, as amended by N3308.
 //
 // \param CCK Specifies whether to produce diagnostics if the function does not
 // satisfy the requirements.
@@ -659,17 +659,16 @@
            NewFD->getTemplateInstantiationPattern()->isConstexpr())) &&
          "only constexpr templates can be instantiated non-constexpr");
 
-  if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(NewFD)) {
-    // C++0x [dcl.constexpr]p4:
-    //  In the definition of a constexpr constructor, each of the parameter
-    //  types shall be a literal type.
-    if (!CheckConstexprParameterTypes(*this, NewFD, CCK))
-      return false;
-
+  const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
+  if (MD && MD->isInstance()) {
+    // C++11 [dcl.constexpr]p4: In the definition of a constexpr constructor...
     //  In addition, either its function-body shall be = delete or = default or
     //  it shall satisfy the following constraints:
     //  - the class shall not have any virtual base classes;
-    const CXXRecordDecl *RD = CD->getParent();
+    //
+    // We apply this to constexpr member functions too: the class cannot be a
+    // literal type, so the members are not permitted to be constexpr.
+    const CXXRecordDecl *RD = MD->getParent();
     if (RD->getNumVBases()) {
       // Note, this is still illegal if the body is = default, since the
       // implicit body does not satisfy the requirements of a constexpr
@@ -679,7 +678,8 @@
         Diag(NewFD->getLocation(),
              CCK == CCK_Declaration ? diag::err_constexpr_virtual_base
                                     : diag::note_constexpr_tmpl_virtual_base)
-          << RD->isStruct() << RD->getNumVBases();
+          << isa<CXXConstructorDecl>(NewFD) << RD->isStruct()
+          << RD->getNumVBases();
         for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
                E = RD->vbases_end(); I != E; ++I)
           Diag(I->getSourceRange().getBegin(),
@@ -687,8 +687,10 @@
       }
       return false;
     }
-  } else {
-    // C++0x [dcl.constexpr]p3:
+  }
+
+  if (!isa<CXXConstructorDecl>(NewFD)) {
+    // C++11 [dcl.constexpr]p3:
     //  The definition of a constexpr function shall satisfy the following
     //  constraints:
     // - it shall not be virtual;
@@ -705,7 +707,7 @@
         while (!WrittenVirtual->isVirtualAsWritten())
           WrittenVirtual = *WrittenVirtual->begin_overridden_methods();
         if (WrittenVirtual != Method)
-          Diag(WrittenVirtual->getLocation(), 
+          Diag(WrittenVirtual->getLocation(),
                diag::note_overridden_virtual_function);
       }
       return false;
@@ -723,12 +725,12 @@
              diag::note_constexpr_tmpl_non_literal_return) << RT;
       return false;
     }
-
-    // - each of its parameter types shall be a literal type;
-    if (!CheckConstexprParameterTypes(*this, NewFD, CCK))
-      return false;
   }
 
+  // - each of its parameter types shall be a literal type;
+  if (!CheckConstexprParameterTypes(*this, NewFD, CCK))
+    return false;
+
   return true;
 }
 
@@ -1745,6 +1747,31 @@
                              EllipsisLoc);
 }
 
+namespace {
+
+// Callback to only accept typo corrections that can be a valid C++ member
+// intializer: either a non-static field member or a base class.
+class MemInitializerValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl)
+      : ClassDecl(ClassDecl) {}
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    if (NamedDecl *ND = candidate.getCorrectionDecl()) {
+      if (FieldDecl *Member = dyn_cast<FieldDecl>(ND))
+        return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl);
+      else
+        return isa<TypeDecl>(ND);
+    }
+    return false;
+  }
+
+ private:
+  CXXRecordDecl *ClassDecl;
+};
+
+}
+
 /// \brief Handle a C++ member initializer.
 MemInitResult
 Sema::BuildMemInitializer(Decl *ConstructorD,
@@ -1837,24 +1864,23 @@
 
       // If no results were found, try to correct typos.
       TypoCorrection Corr;
+      MemInitializerValidatorCCC Validator(ClassDecl);
       if (R.empty() && BaseType.isNull() &&
           (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
-                              ClassDecl, false, CTC_NoKeywords))) {
+                              &Validator, ClassDecl))) {
         std::string CorrectedStr(Corr.getAsString(getLangOptions()));
         std::string CorrectedQuotedStr(Corr.getQuoted(getLangOptions()));
         if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
-          if (Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl)) {
-            // We have found a non-static data member with a similar
-            // name to what was typed; complain and initialize that
-            // member.
-            Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
-              << MemberOrBase << true << CorrectedQuotedStr
-              << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
-            Diag(Member->getLocation(), diag::note_previous_decl)
-              << CorrectedQuotedStr;
+          // We have found a non-static data member with a similar
+          // name to what was typed; complain and initialize that
+          // member.
+          Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
+            << MemberOrBase << true << CorrectedQuotedStr
+            << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
+          Diag(Member->getLocation(), diag::note_previous_decl)
+            << CorrectedQuotedStr;
 
-            return BuildMemberInitializer(Member, Args, IdLoc);
-          }
+          return BuildMemberInitializer(Member, Args, IdLoc);
         } else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {
           const CXXBaseSpecifier *DirectBaseSpec;
           const CXXBaseSpecifier *VirtualBaseSpec;
@@ -2340,7 +2366,9 @@
     bool Moving = ImplicitInitKind == IIK_Move;
     ParmVarDecl *Param = Constructor->getParamDecl(0);
     QualType ParamType = Param->getType().getNonReferenceType();
-    
+
+    SemaRef.MarkDeclarationReferenced(Constructor->getLocation(), Param);
+
     Expr *CopyCtorArg = 
       DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, 
                           Constructor->getLocation(), ParamType,
@@ -2410,6 +2438,8 @@
     ParmVarDecl *Param = Constructor->getParamDecl(0);
     QualType ParamType = Param->getType().getNonReferenceType();
 
+    SemaRef.MarkDeclarationReferenced(Constructor->getLocation(), Param);
+
     // Suppress copying zero-width bitfields.
     if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0)
       return false;
@@ -3651,7 +3681,7 @@
     for (CXXRecordDecl::method_iterator M = Record->method_begin(),
                                      MEnd = Record->method_end();
          M != MEnd; ++M) {
-      if ((*M)->isConstexpr()) {
+      if (M->isConstexpr() && M->isInstance()) {
         switch (Record->getTemplateSpecializationKind()) {
         case TSK_ImplicitInstantiation:
         case TSK_ExplicitInstantiationDeclaration:
@@ -3756,6 +3786,18 @@
                           *ExceptionType = Context.getFunctionType(
                          Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>();
 
+  // C++11 [dcl.fct.def.default]p2:
+  //   An explicitly-defaulted function may be declared constexpr only if it
+  //   would have been implicitly declared as constexpr,
+  if (CD->isConstexpr()) {
+    if (!CD->getParent()->defaultedDefaultConstructorIsConstexpr()) {
+      Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr)
+        << CXXDefaultConstructor;
+      HadError = true;
+    }
+  }
+  //   and may have an explicit exception-specification only if it is compatible
+  //   with the exception-specification on the implicit declaration.
   if (CtorType->hasExceptionSpec()) {
     if (CheckEquivalentExceptionSpec(
           PDiag(diag::err_incorrect_defaulted_exception_spec)
@@ -3765,11 +3807,20 @@
           CtorType, CD->getLocation())) {
       HadError = true;
     }
-  } else if (First) {
-    // We set the declaration to have the computed exception spec here.
-    // We know there are no parameters.
+  }
+
+  //   If a function is explicitly defaulted on its first declaration,
+  if (First) {
+    //  -- it is implicitly considered to be constexpr if the implicit
+    //     definition would be,
+    CD->setConstexpr(CD->getParent()->defaultedDefaultConstructorIsConstexpr());
+
+    //  -- it is implicitly considered to have the same
+    //     exception-specification as if it had been implicitly declared
+    //
+    // FIXME: a compatible, but different, explicit exception specification
+    // will be silently overridden. We should issue a warning if this happens.
     EPI.ExtInfo = CtorType->getExtInfo();
-    CD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI));
   }
 
   if (HadError) {
@@ -3823,6 +3874,18 @@
     HadError = true;
   }
 
+  // C++11 [dcl.fct.def.default]p2:
+  //   An explicitly-defaulted function may be declared constexpr only if it
+  //   would have been implicitly declared as constexpr,
+  if (CD->isConstexpr()) {
+    if (!CD->getParent()->defaultedCopyConstructorIsConstexpr()) {
+      Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr)
+        << CXXCopyConstructor;
+      HadError = true;
+    }
+  }
+  //   and may have an explicit exception-specification only if it is compatible
+  //   with the exception-specification on the implicit declaration.
   if (CtorType->hasExceptionSpec()) {
     if (CheckEquivalentExceptionSpec(
           PDiag(diag::err_incorrect_defaulted_exception_spec)
@@ -3832,10 +3895,23 @@
           CtorType, CD->getLocation())) {
       HadError = true;
     }
-  } else if (First) {
-    // We set the declaration to have the computed exception spec here.
-    // We duplicate the one parameter type.
+  }
+
+  //   If a function is explicitly defaulted on its first declaration,
+  if (First) {
+    //  -- it is implicitly considered to be constexpr if the implicit
+    //     definition would be,
+    CD->setConstexpr(CD->getParent()->defaultedCopyConstructorIsConstexpr());
+
+    //  -- it is implicitly considered to have the same
+    //     exception-specification as if it had been implicitly declared, and
+    //
+    // FIXME: a compatible, but different, explicit exception specification
+    // will be silently overridden. We should issue a warning if this happens.
     EPI.ExtInfo = CtorType->getExtInfo();
+
+    //  -- [...] it shall have the same parameter type as if it had been
+    //     implicitly declared.
     CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI));
   }
 
@@ -3917,7 +3993,8 @@
           OperType, MD->getLocation())) {
       HadError = true;
     }
-  } else if (First) {
+  }
+  if (First) {
     // We set the declaration to have the computed exception spec here.
     // We duplicate the one parameter type.
     EPI.RefQualifier = OperType->getRefQualifier();
@@ -3974,6 +4051,18 @@
     HadError = true;
   }
 
+  // C++11 [dcl.fct.def.default]p2:
+  //   An explicitly-defaulted function may be declared constexpr only if it
+  //   would have been implicitly declared as constexpr,
+  if (CD->isConstexpr()) {
+    if (!CD->getParent()->defaultedMoveConstructorIsConstexpr()) {
+      Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr)
+        << CXXMoveConstructor;
+      HadError = true;
+    }
+  }
+  //   and may have an explicit exception-specification only if it is compatible
+  //   with the exception-specification on the implicit declaration.
   if (CtorType->hasExceptionSpec()) {
     if (CheckEquivalentExceptionSpec(
           PDiag(diag::err_incorrect_defaulted_exception_spec)
@@ -3983,10 +4072,23 @@
           CtorType, CD->getLocation())) {
       HadError = true;
     }
-  } else if (First) {
-    // We set the declaration to have the computed exception spec here.
-    // We duplicate the one parameter type.
+  }
+
+  //   If a function is explicitly defaulted on its first declaration,
+  if (First) {
+    //  -- it is implicitly considered to be constexpr if the implicit
+    //     definition would be,
+    CD->setConstexpr(CD->getParent()->defaultedMoveConstructorIsConstexpr());
+
+    //  -- it is implicitly considered to have the same
+    //     exception-specification as if it had been implicitly declared, and
+    //
+    // FIXME: a compatible, but different, explicit exception specification
+    // will be silently overridden. We should issue a warning if this happens.
     EPI.ExtInfo = CtorType->getExtInfo();
+
+    //  -- [...] it shall have the same parameter type as if it had been
+    //     implicitly declared.
     CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI));
   }
 
@@ -4066,7 +4168,8 @@
           OperType, MD->getLocation())) {
       HadError = true;
     }
-  } else if (First) {
+  }
+  if (First) {
     // We set the declaration to have the computed exception spec here.
     // We duplicate the one parameter type.
     EPI.RefQualifier = OperType->getRefQualifier();
@@ -4113,7 +4216,8 @@
       DD->setInvalidDecl();
       return;
     }
-  } else if (First) {
+  }
+  if (First) {
     // We set the declaration to have the computed exception spec here.
     // There are no parameters.
     EPI.ExtInfo = DtorType->getExtInfo();
@@ -4907,6 +5011,9 @@
   if (!ClassDecl->hasUserDeclaredCopyConstructor())
     ++ASTContext::NumImplicitCopyConstructors;
 
+  if (getLangOptions().CPlusPlus0x && ClassDecl->needsImplicitMoveConstructor())
+    ++ASTContext::NumImplicitMoveConstructors;
+
   if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
     ++ASTContext::NumImplicitCopyAssignmentOperators;
     
@@ -4918,6 +5025,14 @@
       DeclareImplicitCopyAssignment(ClassDecl);
   }
 
+  if (getLangOptions().CPlusPlus0x && ClassDecl->needsImplicitMoveAssignment()){
+    ++ASTContext::NumImplicitMoveAssignmentOperators;
+
+    // Likewise for the move assignment operator.
+    if (ClassDecl->isDynamicClass())
+      DeclareImplicitMoveAssignment(ClassDecl);
+  }
+
   if (!ClassDecl->hasUserDeclaredDestructor()) {
     ++ASTContext::NumImplicitDestructors;
     
@@ -5446,17 +5561,13 @@
   SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc;
   // For anonymous namespace, take the location of the left brace.
   SourceLocation Loc = II ? IdentLoc : LBrace;
-  NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext,
-                                                 StartLoc, Loc, II);
-  Namespc->setInline(InlineLoc.isValid());
-
+  bool IsInline = InlineLoc.isValid();
+  bool IsInvalid = false;
+  bool IsStd = false;
+  bool AddToKnown = false;
   Scope *DeclRegionScope = NamespcScope->getParent();
 
-  ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
-
-  if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>())
-    PushNamespaceVisibilityAttr(Attr);
-
+  NamespaceDecl *PrevNS = 0;
   if (II) {
     // C++ [namespace.def]p2:
     //   The identifier in an original-namespace-definition shall not
@@ -5470,11 +5581,11 @@
     // look through using directives, just look for any ordinary names.
     
     const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member | 
-      Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | 
-      Decl::IDNS_Namespace;
+    Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | 
+    Decl::IDNS_Namespace;
     NamedDecl *PrevDecl = 0;
     for (DeclContext::lookup_result R 
-            = CurContext->getRedeclContext()->lookup(II);
+         = CurContext->getRedeclContext()->lookup(II);
          R.first != R.second; ++R.first) {
       if ((*R.first)->getIdentifierNamespace() & IDNS) {
         PrevDecl = *R.first;
@@ -5482,100 +5593,91 @@
       }
     }
     
-    if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {
+    PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl);
+    
+    if (PrevNS) {
       // This is an extended namespace definition.
-      if (Namespc->isInline() != OrigNS->isInline()) {
+      if (IsInline != PrevNS->isInline()) {
         // inline-ness must match
-        if (OrigNS->isInline()) {
+        if (PrevNS->isInline()) {
           // The user probably just forgot the 'inline', so suggest that it
           // be added back.
-          Diag(Namespc->getLocation(), 
-               diag::warn_inline_namespace_reopened_noninline)
+          Diag(Loc, diag::warn_inline_namespace_reopened_noninline)
             << FixItHint::CreateInsertion(NamespaceLoc, "inline ");
         } else {
-          Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch)
-            << Namespc->isInline();
+          Diag(Loc, diag::err_inline_namespace_mismatch)
+            << IsInline;
         }
-        Diag(OrigNS->getLocation(), diag::note_previous_definition);
-
-        // Recover by ignoring the new namespace's inline status.
-        Namespc->setInline(OrigNS->isInline());
-      }
-
-      // Attach this namespace decl to the chain of extended namespace
-      // definitions.
-      OrigNS->setNextNamespace(Namespc);
-      Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace());
-
-      // Remove the previous declaration from the scope.
-      if (DeclRegionScope->isDeclScope(OrigNS)) {
-        IdResolver.RemoveDecl(OrigNS);
-        DeclRegionScope->RemoveDecl(OrigNS);
-      }
+        Diag(PrevNS->getLocation(), diag::note_previous_definition);
+        
+        IsInline = PrevNS->isInline();
+      }      
     } else if (PrevDecl) {
       // This is an invalid name redefinition.
-      Diag(Namespc->getLocation(), diag::err_redefinition_different_kind)
-       << Namespc->getDeclName();
+      Diag(Loc, diag::err_redefinition_different_kind)
+        << II;
       Diag(PrevDecl->getLocation(), diag::note_previous_definition);
-      Namespc->setInvalidDecl();
+      IsInvalid = true;
       // Continue on to push Namespc as current DeclContext and return it.
-    } else if (II->isStr("std") && 
+    } else if (II->isStr("std") &&
                CurContext->getRedeclContext()->isTranslationUnit()) {
       // This is the first "real" definition of the namespace "std", so update
       // our cache of the "std" namespace to point at this definition.
-      if (NamespaceDecl *StdNS = getStdNamespace()) {
-        // We had already defined a dummy namespace "std". Link this new 
-        // namespace definition to the dummy namespace "std".
-        StdNS->setNextNamespace(Namespc);
-        StdNS->setLocation(IdentLoc);
-        Namespc->setOriginalNamespace(StdNS->getOriginalNamespace());
-      }
-      
-      // Make our StdNamespace cache point at the first real definition of the
-      // "std" namespace.
-      StdNamespace = Namespc;
-
-      // Add this instance of "std" to the set of known namespaces
-      KnownNamespaces[Namespc] = false;
-    } else if (!Namespc->isInline()) {
-      // Since this is an "original" namespace, add it to the known set of
-      // namespaces if it is not an inline namespace.
-      KnownNamespaces[Namespc] = false;
+      PrevNS = getStdNamespace();
+      IsStd = true;
+      AddToKnown = !IsInline;
+    } else {
+      // We've seen this namespace for the first time.
+      AddToKnown = !IsInline;
     }
-
-    PushOnScopeChains(Namespc, DeclRegionScope);
   } else {
     // Anonymous namespaces.
-    assert(Namespc->isAnonymousNamespace());
-
-    // Link the anonymous namespace into its parent.
-    NamespaceDecl *PrevDecl;
+    
+    // Determine whether the parent already has an anonymous namespace.
     DeclContext *Parent = CurContext->getRedeclContext();
     if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
-      PrevDecl = TU->getAnonymousNamespace();
-      TU->setAnonymousNamespace(Namespc);
+      PrevNS = TU->getAnonymousNamespace();
     } else {
       NamespaceDecl *ND = cast<NamespaceDecl>(Parent);
-      PrevDecl = ND->getAnonymousNamespace();
-      ND->setAnonymousNamespace(Namespc);
+      PrevNS = ND->getAnonymousNamespace();
+    }
+
+    if (PrevNS && IsInline != PrevNS->isInline()) {
+      // inline-ness must match
+      Diag(Loc, diag::err_inline_namespace_mismatch)
+        << IsInline;
+      Diag(PrevNS->getLocation(), diag::note_previous_definition);
+      
+      // Recover by ignoring the new namespace's inline status.
+      IsInline = PrevNS->isInline();
     }
+  }
+  
+  NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline,
+                                                 StartLoc, Loc, II, PrevNS);
+  if (IsInvalid)
+    Namespc->setInvalidDecl();
+  
+  ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
 
-    // Link the anonymous namespace with its previous declaration.
-    if (PrevDecl) {
-      assert(PrevDecl->isAnonymousNamespace());
-      assert(!PrevDecl->getNextNamespace());
-      Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace());
-      PrevDecl->setNextNamespace(Namespc);
+  // FIXME: Should we be merging attributes?
+  if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>())
+    PushNamespaceVisibilityAttr(Attr);
 
-      if (Namespc->isInline() != PrevDecl->isInline()) {
-        // inline-ness must match
-        Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch)
-          << Namespc->isInline();
-        Diag(PrevDecl->getLocation(), diag::note_previous_definition);
-        Namespc->setInvalidDecl();
-        // Recover by ignoring the new namespace's inline status.
-        Namespc->setInline(PrevDecl->isInline());
-      }
+  if (IsStd)
+    StdNamespace = Namespc;
+  if (AddToKnown)
+    KnownNamespaces[Namespc] = false;
+  
+  if (II) {
+    PushOnScopeChains(Namespc, DeclRegionScope);
+  } else {
+    // Link the anonymous namespace into its parent.
+    DeclContext *Parent = CurContext->getRedeclContext();
+    if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
+      TU->setAnonymousNamespace(Namespc);
+    } else {
+      cast<NamespaceDecl>(Parent)->setAnonymousNamespace(Namespc);
     }
 
     CurContext->addDecl(Namespc);
@@ -5596,7 +5698,7 @@
     // declarations semantically contained within an anonymous
     // namespace internal linkage.
 
-    if (!PrevDecl) {
+    if (!PrevNS) {
       UsingDirectiveDecl* UD
         = UsingDirectiveDecl::Create(Context, CurContext,
                                      /* 'using' */ LBrace,
@@ -5655,14 +5757,143 @@
     // The "std" namespace has not yet been defined, so build one implicitly.
     StdNamespace = NamespaceDecl::Create(Context, 
                                          Context.getTranslationUnitDecl(),
+                                         /*Inline=*/false,
                                          SourceLocation(), SourceLocation(),
-                                         &PP.getIdentifierTable().get("std"));
+                                         &PP.getIdentifierTable().get("std"),
+                                         /*PrevDecl=*/0);
     getStdNamespace()->setImplicit(true);
   }
   
   return getStdNamespace();
 }
 
+bool Sema::isStdInitializerList(QualType Ty, QualType *Element) {
+  assert(getLangOptions().CPlusPlus &&
+         "Looking for std::initializer_list outside of C++.");
+
+  // We're looking for implicit instantiations of
+  // template <typename E> class std::initializer_list.
+
+  if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it.
+    return false;
+
+  ClassTemplateDecl *Template = 0;
+  const TemplateArgument *Arguments = 0;
+
+  if (const RecordType *RT = Ty->getAs<RecordType>()) {
+
+    ClassTemplateSpecializationDecl *Specialization =
+        dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+    if (!Specialization)
+      return false;
+
+    if (Specialization->getSpecializationKind() != TSK_ImplicitInstantiation)
+      return false;
+
+    Template = Specialization->getSpecializedTemplate();
+    Arguments = Specialization->getTemplateArgs().data();
+  } else if (const TemplateSpecializationType *TST =
+                 Ty->getAs<TemplateSpecializationType>()) {
+    Template = dyn_cast_or_null<ClassTemplateDecl>(
+        TST->getTemplateName().getAsTemplateDecl());
+    Arguments = TST->getArgs();
+  }
+  if (!Template)
+    return false;
+
+  if (!StdInitializerList) {
+    // Haven't recognized std::initializer_list yet, maybe this is it.
+    CXXRecordDecl *TemplateClass = Template->getTemplatedDecl();
+    if (TemplateClass->getIdentifier() !=
+            &PP.getIdentifierTable().get("initializer_list") ||
+        !TemplateClass->getDeclContext()->Equals(getStdNamespace()))
+      return false;
+    // This is a template called std::initializer_list, but is it the right
+    // template?
+    TemplateParameterList *Params = Template->getTemplateParameters();
+    if (Params->size() != 1)
+      return false;
+    if (!isa<TemplateTypeParmDecl>(Params->getParam(0)))
+      return false;
+
+    // It's the right template.
+    StdInitializerList = Template;
+  }
+
+  if (Template != StdInitializerList)
+    return false;
+
+  // This is an instance of std::initializer_list. Find the argument type.
+  if (Element)
+    *Element = Arguments[0].getAsType();
+  return true;
+}
+
+static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){
+  NamespaceDecl *Std = S.getStdNamespace();
+  if (!Std) {
+    S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
+    return 0;
+  }
+
+  LookupResult Result(S, &S.PP.getIdentifierTable().get("initializer_list"),
+                      Loc, Sema::LookupOrdinaryName);
+  if (!S.LookupQualifiedName(Result, Std)) {
+    S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
+    return 0;
+  }
+  ClassTemplateDecl *Template = Result.getAsSingle<ClassTemplateDecl>();
+  if (!Template) {
+    Result.suppressDiagnostics();
+    // We found something weird. Complain about the first thing we found.
+    NamedDecl *Found = *Result.begin();
+    S.Diag(Found->getLocation(), diag::err_malformed_std_initializer_list);
+    return 0;
+  }
+
+  // We found some template called std::initializer_list. Now verify that it's
+  // correct.
+  TemplateParameterList *Params = Template->getTemplateParameters();
+  if (Params->size() != 1 || !isa<TemplateTypeParmDecl>(Params->getParam(0))) {
+    S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list);
+    return 0;
+  }
+
+  return Template;
+}
+
+QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) {
+  if (!StdInitializerList) {
+    StdInitializerList = LookupStdInitializerList(*this, Loc);
+    if (!StdInitializerList)
+      return QualType();
+  }
+
+  TemplateArgumentListInfo Args(Loc, Loc);
+  Args.addArgument(TemplateArgumentLoc(TemplateArgument(Element),
+                                       Context.getTrivialTypeSourceInfo(Element,
+                                                                        Loc)));
+  return Context.getCanonicalType(
+      CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args));
+}
+
+bool Sema::isInitListConstructor(const CXXConstructorDecl* Ctor) {
+  // C++ [dcl.init.list]p2:
+  //   A constructor is an initializer-list constructor if its first parameter
+  //   is of type std::initializer_list<E> or reference to possibly cv-qualified
+  //   std::initializer_list<E> for some type E, and either there are no other
+  //   parameters or else all other parameters have default arguments.
+  if (Ctor->getNumParams() < 1 ||
+      (Ctor->getNumParams() > 1 && !Ctor->getParamDecl(1)->hasDefaultArg()))
+    return false;
+
+  QualType ArgType = Ctor->getParamDecl(0)->getType();
+  if (const ReferenceType *RT = ArgType->getAs<ReferenceType>())
+    ArgType = RT->getPointeeType().getUnqualifiedType();
+
+  return isStdInitializerList(ArgType, 0);
+}
+
 /// \brief Determine whether a using statement is in a context where it will be
 /// apply in all contexts.
 static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) {
@@ -5676,35 +5907,47 @@
   }
 }
 
+namespace {
+
+// Callback to only accept typo corrections that are namespaces.
+class NamespaceValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    if (NamedDecl *ND = candidate.getCorrectionDecl()) {
+      return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
+    }
+    return false;
+  }
+};
+
+}
+
 static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
                                        CXXScopeSpec &SS,
                                        SourceLocation IdentLoc,
                                        IdentifierInfo *Ident) {
+  NamespaceValidatorCCC Validator;
   R.clear();
   if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(),
-                                               R.getLookupKind(), Sc, &SS, NULL,
-                                               false, S.CTC_NoKeywords, NULL)) {
-    if (Corrected.getCorrectionDeclAs<NamespaceDecl>() ||
-        Corrected.getCorrectionDeclAs<NamespaceAliasDecl>()) {
-      std::string CorrectedStr(Corrected.getAsString(S.getLangOptions()));
-      std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOptions()));
-      if (DeclContext *DC = S.computeDeclContext(SS, false))
-        S.Diag(IdentLoc, diag::err_using_directive_member_suggest)
-          << Ident << DC << CorrectedQuotedStr << SS.getRange()
-          << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
-      else
-        S.Diag(IdentLoc, diag::err_using_directive_suggest)
-          << Ident << CorrectedQuotedStr
-          << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
+                                               R.getLookupKind(), Sc, &SS,
+                                               &Validator)) {
+    std::string CorrectedStr(Corrected.getAsString(S.getLangOptions()));
+    std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOptions()));
+    if (DeclContext *DC = S.computeDeclContext(SS, false))
+      S.Diag(IdentLoc, diag::err_using_directive_member_suggest)
+        << Ident << DC << CorrectedQuotedStr << SS.getRange()
+        << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
+    else
+      S.Diag(IdentLoc, diag::err_using_directive_suggest)
+        << Ident << CorrectedQuotedStr
+        << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
 
-      S.Diag(Corrected.getCorrectionDecl()->getLocation(),
-           diag::note_namespace_defined_here) << CorrectedQuotedStr;
+    S.Diag(Corrected.getCorrectionDecl()->getLocation(),
+         diag::note_namespace_defined_here) << CorrectedQuotedStr;
 
-      Ident = Corrected.getCorrectionAsIdentifierInfo();
-      R.addDecl(Corrected.getCorrectionDecl());
-      return true;
-    }
-    R.setLookupName(Ident);
+    Ident = Corrected.getCorrectionAsIdentifierInfo();
+    R.addDecl(Corrected.getCorrectionDecl());
+    return true;
   }
   return false;
 }
@@ -6699,7 +6942,7 @@
     
     ~ImplicitlyDefinedFunctionScope() {
       S.PopExpressionEvaluationContext();
-      S.PopFunctionOrBlockScope();
+      S.PopFunctionScopeInfo();
     }
   };
 }
@@ -6792,16 +7035,12 @@
   DeclarationName Name
     = Context.DeclarationNames.getCXXConstructorName(ClassType);
   DeclarationNameInfo NameInfo(Name, ClassLoc);
-  CXXConstructorDecl *DefaultCon
-    = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
-                                 Context.getFunctionType(Context.VoidTy,
-                                                         0, 0, EPI),
-                                 /*TInfo=*/0,
-                                 /*isExplicit=*/false,
-                                 /*isInline=*/true,
-                                 /*isImplicitlyDeclared=*/true,
-                                 // FIXME: apply the rules for definitions here
-                                 /*isConstexpr=*/false);
+  CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create(
+      Context, ClassDecl, ClassLoc, NameInfo,
+      Context.getFunctionType(Context.VoidTy, 0, 0, EPI), /*TInfo=*/0,
+      /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
+      /*isConstexpr=*/ClassDecl->defaultedDefaultConstructorIsConstexpr() &&
+        getLangOptions().CPlusPlus0x);
   DefaultCon->setAccess(AS_public);
   DefaultCon->setDefaulted();
   DefaultCon->setImplicit();
@@ -8476,21 +8715,17 @@
   DeclarationNameInfo NameInfo(Name, ClassLoc);
 
   //   An implicitly-declared copy constructor is an inline public
-  //   member of its class. 
-  CXXConstructorDecl *CopyConstructor
-    = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
-                                 Context.getFunctionType(Context.VoidTy,
-                                                         &ArgType, 1, EPI),
-                                 /*TInfo=*/0,
-                                 /*isExplicit=*/false,
-                                 /*isInline=*/true,
-                                 /*isImplicitlyDeclared=*/true,
-                                 // FIXME: apply the rules for definitions here
-                                 /*isConstexpr=*/false);
+  //   member of its class.
+  CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create(
+      Context, ClassDecl, ClassLoc, NameInfo,
+      Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI), /*TInfo=*/0,
+      /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
+      /*isConstexpr=*/ClassDecl->defaultedCopyConstructorIsConstexpr() &&
+        getLangOptions().CPlusPlus0x);
   CopyConstructor->setAccess(AS_public);
   CopyConstructor->setDefaulted();
   CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
-  
+
   // Note that we have declared this constructor.
   ++ASTContext::NumImplicitCopyConstructorsDeclared;
   
@@ -8631,21 +8866,17 @@
 
   // C++0x [class.copy]p11:
   //   An implicitly-declared copy/move constructor is an inline public
-  //   member of its class. 
-  CXXConstructorDecl *MoveConstructor
-    = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
-                                 Context.getFunctionType(Context.VoidTy,
-                                                         &ArgType, 1, EPI),
-                                 /*TInfo=*/0,
-                                 /*isExplicit=*/false,
-                                 /*isInline=*/true,
-                                 /*isImplicitlyDeclared=*/true,
-                                 // FIXME: apply the rules for definitions here
-                                 /*isConstexpr=*/false);
+  //   member of its class.
+  CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create(
+      Context, ClassDecl, ClassLoc, NameInfo,
+      Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI), /*TInfo=*/0,
+      /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
+      /*isConstexpr=*/ClassDecl->defaultedMoveConstructorIsConstexpr() &&
+        getLangOptions().CPlusPlus0x);
   MoveConstructor->setAccess(AS_public);
   MoveConstructor->setDefaulted();
   MoveConstructor->setTrivial(ClassDecl->hasTrivialMoveConstructor());
-  
+
   // Add the parameter to the constructor.
   ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor,
                                                ClassLoc, ClassLoc,
@@ -8825,8 +9056,6 @@
                                          MultiExprArg Exprs,
                                          SourceLocation RParenLoc,
                                          bool TypeMayContainAuto) {
-  assert(Exprs.size() != 0 && Exprs.get() && "missing expressions");
-
   // If there is no declaration, there was an error parsing it.  Just ignore
   // the initializer.
   if (RealDecl == 0)
@@ -8839,9 +9068,18 @@
     return;
   }
 
-  // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
+  // C++0x [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for.
   if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
-    // FIXME: n3225 doesn't actually seem to indicate this is ill-formed
+    if (Exprs.size() == 0) {
+      // It isn't possible to write this directly, but it is possible to
+      // end up in this situation with "auto x(some_pack...);"
+      Diag(LParenLoc, diag::err_auto_var_init_no_expression)
+        << VDecl->getDeclName() << VDecl->getType()
+        << VDecl->getSourceRange();
+      RealDecl->setInvalidDecl();
+      return;
+    }
+
     if (Exprs.size() > 1) {
       Diag(Exprs.get()[1]->getSourceRange().getBegin(),
            diag::err_auto_var_init_multiple_expressions)
@@ -8854,9 +9092,7 @@
     Expr *Init = Exprs.get()[0];
     TypeSourceInfo *DeducedType = 0;
     if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType))
-      Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
-        << VDecl->getDeclName() << VDecl->getType() << Init->getType()
-        << Init->getSourceRange();
+      DiagnoseAutoDeductionFailure(VDecl, Init);
     if (!DeducedType) {
       RealDecl->setInvalidDecl();
       return;
@@ -8870,7 +9106,7 @@
 
     // If this is a redeclaration, check that the type we just deduced matches
     // the previously declared type.
-    if (VarDecl *Old = VDecl->getPreviousDeclaration())
+    if (VarDecl *Old = VDecl->getPreviousDecl())
       MergeVarDeclTypes(VDecl, Old);
   }
 
@@ -9783,7 +10019,7 @@
                       Attr, AS_public, 
                       /*ModulePrivateLoc=*/SourceLocation(),
                       MultiTemplateParamsArg(), Owned, IsDependent, 
-                      /*ScopedEnum=*/false,
+                      /*ScopedEnumKWLoc=*/SourceLocation(),
                       /*ScopedEnumUsesClassTag=*/false,
                       /*UnderlyingType=*/TypeResult());          
     }
@@ -10203,7 +10439,7 @@
     Diag(DelLoc, diag::err_deleted_non_function);
     return;
   }
-  if (const FunctionDecl *Prev = Fn->getPreviousDeclaration()) {
+  if (const FunctionDecl *Prev = Fn->getPreviousDecl()) {
     Diag(DelLoc, diag::err_deleted_decl_not_first);
     Diag(Prev->getLocation(), diag::note_previous_declaration);
     // If the declaration wasn't the first, we delete the function anyway for
@@ -10515,7 +10751,8 @@
   // not have a vtable.
   if (!Class->isDynamicClass() || Class->isDependentContext() ||
       CurContext->isDependentContext() ||
-      ExprEvalContexts.back().Context == Unevaluated)
+      ExprEvalContexts.back().Context == Unevaluated ||
+      ExprEvalContexts.back().Context == ConstantEvaluated)
     return;
 
   // Try to insert this class into the map.

Modified: cfe/branches/tooling/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaDeclObjC.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaDeclObjC.cpp Fri Jan 20 10:14:22 2012
@@ -347,6 +347,28 @@
   }
 }
 
+namespace {
+
+// Callback to only accept typo corrections that are Objective-C classes.
+// If an ObjCInterfaceDecl* is given to the constructor, then the validation
+// function will reject corrections to that class.
+class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  ObjCInterfaceValidatorCCC() : CurrentIDecl(0) {}
+  explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl)
+      : CurrentIDecl(IDecl) {}
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    ObjCInterfaceDecl *ID = candidate.getCorrectionDeclAs<ObjCInterfaceDecl>();
+    return ID && !declaresSameEntity(ID, CurrentIDecl);
+  }
+
+ private:
+  ObjCInterfaceDecl *CurrentIDecl;
+};
+
+}
+
 Decl *Sema::
 ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
                          IdentifierInfo *ClassName, SourceLocation ClassLoc,
@@ -396,20 +418,17 @@
                                 LookupOrdinaryName);
 
     if (!PrevDecl) {
-      // Try to correct for a typo in the superclass name.
-      TypoCorrection Corrected = CorrectTypo(
+      // Try to correct for a typo in the superclass name without correcting
+      // to the class we're defining.
+      ObjCInterfaceValidatorCCC Validator(IDecl);
+      if (TypoCorrection Corrected = CorrectTypo(
           DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope,
-          NULL, NULL, false, CTC_NoKeywords);
-      if ((PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) {
-        if (declaresSameEntity(PrevDecl, IDecl)) {
-          // Don't correct to the class we're defining.
-          PrevDecl = 0;
-        } else {
-          Diag(SuperLoc, diag::err_undef_superclass_suggest)
-            << SuperName << ClassName << PrevDecl->getDeclName();
-          Diag(PrevDecl->getLocation(), diag::note_previous_decl)
-            << PrevDecl->getDeclName();
-        }
+          NULL, &Validator)) {
+        PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
+        Diag(SuperLoc, diag::err_undef_superclass_suggest)
+          << SuperName << ClassName << PrevDecl->getDeclName();
+        Diag(PrevDecl->getLocation(), diag::note_previous_decl)
+          << PrevDecl->getDeclName();
       }
     }
 
@@ -545,6 +564,10 @@
         Diag(PrevLoc, diag::note_previous_definition);
         res = true;
       }
+      
+      if (!PDecl->hasDefinition())
+        continue;
+      
       if (CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc,
             PDecl->getLocation(), PDecl->getReferencedProtocols()))
         res = true;
@@ -565,49 +588,52 @@
   bool err = false;
   // FIXME: Deal with AttrList.
   assert(ProtocolName && "Missing protocol identifier");
-  ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolName, ProtocolLoc);
-  if (PDecl) {
-    // Protocol already seen. Better be a forward protocol declaration
-    if (!PDecl->isForwardDecl()) {
-      Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;
-      Diag(PDecl->getLocation(), diag::note_previous_definition);
-
-      // Create a new one; the other may be in a different DeclContex, (e.g.
-      // this one may be in a LinkageSpecDecl while the other is not) which
-      // will break invariants.
-      // We will not add it to scope chains to ignore it as the warning says.
-      PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
-                                       ProtocolLoc, AtProtoInterfaceLoc,
-                                       /*isForwardDecl=*/false);
-
-    } else {
+  ObjCProtocolDecl *PrevDecl = LookupProtocol(ProtocolName, ProtocolLoc,
+                                              ForRedeclaration);
+  ObjCProtocolDecl *PDecl = 0;
+  if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : 0) {
+    // If we already have a definition, complain.
+    Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;
+    Diag(Def->getLocation(), diag::note_previous_definition);
+
+    // Create a new protocol that is completely distinct from previous
+    // declarations, and do not make this protocol available for name lookup.
+    // That way, we'll end up completely ignoring the duplicate.
+    // FIXME: Can we turn this into an error?
+    PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
+                                     ProtocolLoc, AtProtoInterfaceLoc,
+                                     /*PrevDecl=*/0);
+    PDecl->startDefinition();
+  } else {
+    if (PrevDecl) {
+      // Check for circular dependencies among protocol declarations. This can
+      // only happen if this protocol was forward-declared.
       ObjCList<ObjCProtocolDecl> PList;
       PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);
       err = CheckForwardProtocolDeclarationForCircularDependency(
-              ProtocolName, ProtocolLoc, PDecl->getLocation(), PList);
-  
-      // Make sure the cached decl gets a valid start location.
-      PDecl->setAtStartLoc(AtProtoInterfaceLoc);
-      PDecl->setLocation(ProtocolLoc);
-      // Since this ObjCProtocolDecl was created by a forward declaration,
-      // we now add it to the DeclContext since it wasn't added before
-      PDecl->setLexicalDeclContext(CurContext);
-      CurContext->addDecl(PDecl);
-      PDecl->completedForwardDecl();
+              ProtocolName, ProtocolLoc, PrevDecl->getLocation(), PList);
     }
-  } else {
+
+    // Create the new declaration.
     PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
                                      ProtocolLoc, AtProtoInterfaceLoc,
-                                     /*isForwardDecl=*/false);
+                                     /*PrevDecl=*/PrevDecl);
+    
     PushOnScopeChains(PDecl, TUScope);
+    PDecl->startDefinition();
   }
+  
   if (AttrList)
     ProcessDeclAttributeList(TUScope, PDecl, AttrList);
+  
+  // Merge attributes from previous declarations.
+  if (PrevDecl)
+    mergeDeclAttributes(PDecl, PrevDecl);
+
   if (!err && NumProtoRefs ) {
     /// Check then save referenced protocols.
     PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
                            ProtoLocs, Context);
-    PDecl->setLocEnd(EndProtoLoc);
   }
 
   CheckObjCDeclScope(PDecl);
@@ -626,9 +652,10 @@
     ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first,
                                              ProtocolId[i].second);
     if (!PDecl) {
+      DeclFilterCCC<ObjCProtocolDecl> Validator;
       TypoCorrection Corrected = CorrectTypo(
           DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),
-          LookupObjCProtocolName, TUScope, NULL, NULL, false, CTC_NoKeywords);
+          LookupObjCProtocolName, TUScope, NULL, &Validator);
       if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) {
         Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest)
           << ProtocolId[i].first << Corrected.getCorrection();
@@ -647,7 +674,7 @@
 
     // If this is a forward declaration and we are supposed to warn in this
     // case, do it.
-    if (WarnOnDeclarations && PDecl->isForwardDecl())
+    if (WarnOnDeclarations && !PDecl->hasDefinition())
       Diag(ProtocolId[i].second, diag::warn_undef_protocolref)
         << ProtocolId[i].first;
     Protocols.push_back(PDecl);
@@ -684,43 +711,34 @@
 }
 
 /// ActOnForwardProtocolDeclaration - Handle @protocol foo;
-Decl *
+Sema::DeclGroupPtrTy
 Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
                                       const IdentifierLocPair *IdentList,
                                       unsigned NumElts,
                                       AttributeList *attrList) {
-  SmallVector<ObjCProtocolDecl*, 32> Protocols;
-  SmallVector<SourceLocation, 8> ProtoLocs;
-
+  SmallVector<Decl *, 8> DeclsInGroup;
   for (unsigned i = 0; i != NumElts; ++i) {
     IdentifierInfo *Ident = IdentList[i].first;
-    ObjCProtocolDecl *PDecl = LookupProtocol(Ident, IdentList[i].second);
-    bool isNew = false;
-    if (PDecl == 0) { // Not already seen?
-      PDecl = ObjCProtocolDecl::Create(Context, CurContext, Ident,
-                                       IdentList[i].second, AtProtocolLoc,
-                                       /*isForwardDecl=*/true);
-      PushOnScopeChains(PDecl, TUScope, false);
-      isNew = true;
-    }
-    if (attrList) {
+    ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentList[i].second,
+                                                ForRedeclaration);
+    ObjCProtocolDecl *PDecl
+      = ObjCProtocolDecl::Create(Context, CurContext, Ident, 
+                                 IdentList[i].second, AtProtocolLoc,
+                                 PrevDecl);
+        
+    PushOnScopeChains(PDecl, TUScope);
+    CheckObjCDeclScope(PDecl);
+    
+    if (attrList)
       ProcessDeclAttributeList(TUScope, PDecl, attrList);
-      if (!isNew) {
-        if (ASTMutationListener *L = Context.getASTMutationListener())
-          L->UpdatedAttributeList(PDecl);
-      }
-    }
-    Protocols.push_back(PDecl);
-    ProtoLocs.push_back(IdentList[i].second);
+    
+    if (PrevDecl)
+      mergeDeclAttributes(PDecl, PrevDecl);
+
+    DeclsInGroup.push_back(PDecl);
   }
 
-  ObjCForwardProtocolDecl *PDecl =
-    ObjCForwardProtocolDecl::Create(Context, CurContext, AtProtocolLoc,
-                                    Protocols.data(), Protocols.size(),
-                                    ProtoLocs.data());
-  CurContext->addDecl(PDecl);
-  CheckObjCDeclScope(PDecl);
-  return PDecl;
+  return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false);
 }
 
 Decl *Sema::
@@ -872,15 +890,16 @@
   } else {
     // We did not find anything with the name ClassName; try to correct for 
     // typos in the class name.
-    TypoCorrection Corrected = CorrectTypo(
+    ObjCInterfaceValidatorCCC Validator;
+    if (TypoCorrection Corrected = CorrectTypo(
         DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope,
-        NULL, NULL, false, CTC_NoKeywords);
-    if ((IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) {
+        NULL, &Validator)) {
       // Suggest the (potentially) correct interface name. However, put the
       // fix-it hint itself in a separate note, since changing the name in 
       // the warning would make the fix-it change semantics.However, don't
       // provide a code-modification hint or use the typo name for recovery,
       // because this is just a warning. The program may actually be correct.
+      IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
       DeclarationName CorrectedName = Corrected.getCorrection();
       Diag(ClassLoc, diag::warn_undef_interface_suggest)
         << ClassName << CorrectedName;
@@ -1667,9 +1686,10 @@
   // Check and see if properties declared in the interface have either 1)
   // an implementation or 2) there is a @synthesize/@dynamic implementation
   // of the property in the @implementation.
-  if (isa<ObjCInterfaceDecl>(CDecl) &&
-        !(LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2))
-    DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap);
+  if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl))
+    if  (!(LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2) ||
+      IDecl->isObjCRequiresPropertyDefs())
+      DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap);
       
   llvm::DenseSet<Selector> ClsMap;
   for (ObjCImplementationDecl::classmeth_iterator
@@ -1775,21 +1795,12 @@
       = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
     ObjCInterfaceDecl *IDecl
       = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
-                                  IdentList[i], PrevIDecl, IdentLocs[i], true);
+                                  IdentList[i], PrevIDecl, IdentLocs[i]);
     IDecl->setAtEndRange(IdentLocs[i]);
     
-    // Create the forward declaration. Note that we intentionally do this 
-    // before we add the ObjCInterfaceDecl we just created, so that the
-    // rewriter sees the ObjCClassDecl first.
-    // FIXME: ObjCClassDecl should probably just go away.
-    ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc,
-                                                 IDecl, IdentLocs[i]);
-    CurContext->addDecl(CDecl);
-    
     PushOnScopeChains(IDecl, TUScope);
-    
-    CheckObjCDeclScope(CDecl);
-    DeclsInGroup.push_back(CDecl);
+    CheckObjCDeclScope(IDecl);
+    DeclsInGroup.push_back(IDecl);
   }
   
   return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false);
@@ -2506,6 +2517,9 @@
   }
 
   void searchFrom(ObjCProtocolDecl *protocol) {
+    if (!protocol->hasDefinition())
+      return;
+    
     // A method in a protocol declaration overrides declarations from
     // referenced ("parent") protocols.
     search(protocol->getReferencedProtocols());
@@ -2688,6 +2702,10 @@
     // Apply the attributes to the parameter.
     ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs);
 
+    if (Param->hasAttr<BlocksAttr>()) {
+      Diag(Param->getLocation(), diag::err_block_on_nonlocal);
+      Param->setInvalidDecl();
+    }
     S->AddDecl(Param);
     IdResolver.AddDecl(Param);
 
@@ -2737,8 +2755,11 @@
                                 ObjCMethod->isInstanceMethod());
     if (ObjCMethod->hasAttrs() &&
         containsInvalidMethodImplAttribute(IMD, ObjCMethod->getAttrs())) {
-      Diag(EndLoc, diag::warn_attribute_method_def);
-      Diag(IMD->getLocation(), diag::note_method_declared_at);
+      SourceLocation MethodLoc = IMD->getLocation();
+      if (!getSourceManager().isInSystemHeader(MethodLoc)) {
+        Diag(EndLoc, diag::warn_attribute_method_def);
+        Diag(MethodLoc, diag::note_method_declared_at);
+      }
     }
   } else {
     cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);

Modified: cfe/branches/tooling/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaExceptionSpec.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaExceptionSpec.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaExceptionSpec.cpp Fri Jan 20 10:14:22 2012
@@ -611,10 +611,8 @@
       case AR_inaccessible: continue;
       case AR_dependent:
         llvm_unreachable("access check dependent for unprivileged context");
-        break;
       case AR_delayed:
         llvm_unreachable("access check delayed in non-declaration");
-        break;
       }
 
       Contained = true;

Modified: cfe/branches/tooling/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaExpr.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaExpr.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaExpr.cpp Fri Jan 20 10:14:22 2012
@@ -12,8 +12,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/DelayedDiagnostic.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
+#include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/AnalysisBasedWarnings.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTMutationListener.h"
@@ -38,6 +40,7 @@
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/SemaFixItUtils.h"
 #include "clang/Sema/Template.h"
+#include "TreeTransform.h"
 using namespace clang;
 using namespace sema;
 
@@ -1015,7 +1018,7 @@
       if (Types[i]->getType()->isDependentType()) {
         IsResultDependent = true;
       } else {
-        // C1X 6.5.1.1p2 "The type name in a generic association shall specify a
+        // C11 6.5.1.1p2 "The type name in a generic association shall specify a
         // complete object type other than a variably modified type."
         unsigned D = 0;
         if (Types[i]->getType()->isIncompleteType())
@@ -1032,7 +1035,7 @@
           TypeErrorFound = true;
         }
 
-        // C1X 6.5.1.1p2 "No two generic associations in the same generic
+        // C11 6.5.1.1p2 "No two generic associations in the same generic
         // selection shall specify compatible types."
         for (unsigned j = i+1; j < NumAssocs; ++j)
           if (Types[j] && !Types[j]->getType()->isDependentType() &&
@@ -1073,7 +1076,7 @@
       CompatIndices.push_back(i);
   }
 
-  // C1X 6.5.1.1p2 "The controlling expression of a generic selection shall have
+  // C11 6.5.1.1p2 "The controlling expression of a generic selection shall have
   // type compatible with at most one of the types named in its generic
   // association list."
   if (CompatIndices.size() > 1) {
@@ -1093,7 +1096,7 @@
     return ExprError();
   }
 
-  // C1X 6.5.1.1p2 "If a generic selection has no default generic association,
+  // C11 6.5.1.1p2 "If a generic selection has no default generic association,
   // its controlling expression shall have type compatible with exactly one of
   // the types named in its generic association list."
   if (DefaultIndex == -1U && CompatIndices.size() == 0) {
@@ -1105,7 +1108,7 @@
     return ExprError();
   }
 
-  // C1X 6.5.1.1p3 "If a generic selection has a generic association with a
+  // C11 6.5.1.1p3 "If a generic selection has a generic association with a
   // type name that is compatible with the type of the controlling expression,
   // then the result expression of the generic selection is the expression
   // in that generic association. Otherwise, the result expression of the
@@ -1199,16 +1202,13 @@
                                    VarDecl *var, DeclContext *DC) {
   switch (S.ExprEvalContexts.back().Context) {
   case Sema::Unevaluated:
-    // The argument will never be evaluated, so don't complain.
+  case Sema::ConstantEvaluated:
+    // The argument will never be evaluated at runtime, so don't complain.
     return CR_NoCapture;
 
   case Sema::PotentiallyEvaluated:
   case Sema::PotentiallyEvaluatedIfUsed:
     break;
-
-  case Sema::PotentiallyPotentiallyEvaluated:
-    // FIXME: delay these!
-    break;
   }
 
   // Don't diagnose about capture if we're not actually in code right
@@ -1247,20 +1247,16 @@
 /// There is a well-formed capture at a particular scope level;
 /// propagate it through all the nested blocks.
 static CaptureResult propagateCapture(Sema &S, unsigned ValidScopeIndex,
-                                      const BlockDecl::Capture &Capture) {
-  VarDecl *var = Capture.getVariable();
-
+                                      const CapturingScopeInfo::Capture &Cap) {
   // Update all the inner blocks with the capture information.
   for (unsigned i = ValidScopeIndex + 1, e = S.FunctionScopes.size();
          i != e; ++i) {
     BlockScopeInfo *innerBlock = cast<BlockScopeInfo>(S.FunctionScopes[i]);
-    innerBlock->Captures.push_back(
-      BlockDecl::Capture(Capture.getVariable(), Capture.isByRef(),
-                         /*nested*/ true, Capture.getCopyExpr()));
-    innerBlock->CaptureMap[var] = innerBlock->Captures.size(); // +1
+    innerBlock->AddCapture(Cap.getVariable(), Cap.isReferenceCapture(),
+                           /*nested*/ true, Cap.getCopyExpr());
   }
 
-  return Capture.isByRef() ? CR_CaptureByRef : CR_Capture;
+  return Cap.isReferenceCapture() ? CR_CaptureByRef : CR_Capture;
 }
 
 /// shouldCaptureValueReference - Determine if a reference to the
@@ -1371,9 +1367,7 @@
     cast<BlockScopeInfo>(S.FunctionScopes[functionScopesIndex]);
 
   // Build a valid capture in this scope.
-  blockScope->Captures.push_back(
-                 BlockDecl::Capture(var, byRef, /*nested*/ false, copyExpr));
-  blockScope->CaptureMap[var] = blockScope->Captures.size(); // +1
+  blockScope->AddCapture(var, byRef, /*nested*/ false, copyExpr);
 
   // Propagate that to inner captures if necessary.
   return propagateCapture(S, functionScopesIndex,
@@ -1490,7 +1484,7 @@
 ///
 /// \return false if new lookup candidates were found
 bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
-                               CorrectTypoContext CTC,
+                               CorrectionCandidateCallback &CCC,
                                TemplateArgumentListInfo *ExplicitTemplateArgs,
                                Expr **Args, unsigned NumArgs) {
   DeclarationName Name = R.getLookupName();
@@ -1543,6 +1537,7 @@
             Diag(R.getNameLoc(), diagnostic) << Name
               << FixItHint::CreateInsertion(R.getNameLoc(), "this->");
             QualType DepThisType = DepMethod->getThisType(Context);
+            CheckCXXThisCapture(R.getNameLoc());
             CXXThisExpr *DepThis = new (Context) CXXThisExpr(
                                        R.getNameLoc(), DepThisType, false);
             TemplateArgumentListInfo TList;
@@ -1604,7 +1599,7 @@
   // We didn't find anything, so try to correct for a typo.
   TypoCorrection Corrected;
   if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(),
-                                    S, &SS, NULL, false, CTC))) {
+                                    S, &SS, &CCC))) {
     std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
     std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
     R.setLookupName(Corrected.getCorrection());
@@ -1819,7 +1814,8 @@
         return ActOnDependentIdExpression(SS, NameInfo, IsAddressOfOperand,
                                           TemplateArgs);
 
-      if (DiagnoseEmptyLookup(S, SS, R, CTC_Unknown))
+      CorrectionCandidateCallback DefaultValidator;
+      if (DiagnoseEmptyLookup(S, SS, R, DefaultValidator))
         return ExprError();
 
       assert(!R.empty() &&
@@ -2009,6 +2005,12 @@
           Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName();
       }
     }
+  } else if (Lookup.isSingleResult() &&
+             Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) {
+    // If accessing a stand-alone ivar in a class method, this is an error.
+    if (const ObjCIvarDecl *IV = dyn_cast<ObjCIvarDecl>(Lookup.getFoundDecl()))
+      return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
+                       << IV->getDeclName());
   }
 
   if (Lookup.empty() && II && AllowBuiltinCreation) {
@@ -2390,13 +2392,11 @@
     case Decl::type:
 #include "clang/AST/DeclNodes.inc"
       llvm_unreachable("invalid value decl kind");
-      return ExprError();
 
     // These shouldn't make it here.
     case Decl::ObjCAtDefsField:
     case Decl::ObjCIvar:
       llvm_unreachable("forming non-member reference to ivar?");
-      return ExprError();
 
     // Enum constants are always r-values and never references.
     // Unresolved using declarations are dependent.
@@ -2517,7 +2517,6 @@
   }
 
   llvm_unreachable("unknown capture result");
-  return ExprError();
 }
 
 ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
@@ -2567,16 +2566,14 @@
     return ExprError();
 
   QualType Ty;
-  if (!getLangOptions().CPlusPlus)
-    Ty = Context.IntTy;   // 'x' and L'x' -> int in C.
-  else if (Literal.isWide())
-    Ty = Context.WCharTy; // L'x' -> wchar_t in C++.
+  if (Literal.isWide())
+    Ty = Context.WCharTy; // L'x' -> wchar_t in C and C++.
   else if (Literal.isUTF16())
-    Ty = Context.Char16Ty; // u'x' -> char16_t in C++0x.
+    Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11.
   else if (Literal.isUTF32())
-    Ty = Context.Char32Ty; // U'x' -> char32_t in C++0x.
-  else if (Literal.isMultiChar())
-    Ty = Context.IntTy;   // 'wxyz' -> int in C++.
+    Ty = Context.Char32Ty; // U'x' -> char32_t in C11 and C++11.
+  else if (!getLangOptions().CPlusPlus || Literal.isMultiChar())
+    Ty = Context.IntTy;   // 'x' -> int in C, 'wxyz' -> int in C++.
   else
     Ty = Context.CharTy;  // 'x' -> char in C++
 
@@ -4064,6 +4061,11 @@
   // pointers.  Everything else should be possible.
 
   QualType SrcTy = Src.get()->getType();
+  if (const AtomicType *SrcAtomicTy = SrcTy->getAs<AtomicType>())
+    SrcTy = SrcAtomicTy->getValueType();
+  if (const AtomicType *DestAtomicTy = DestTy->getAs<AtomicType>())
+    DestTy = DestAtomicTy->getValueType();
+
   if (Context.hasSameUnqualifiedType(SrcTy, DestTy))
     return CK_NoOp;
 
@@ -4083,12 +4085,10 @@
     case Type::STK_ObjCObjectPointer:
       if (SrcKind == Type::STK_ObjCObjectPointer)
         return CK_BitCast;
-      else if (SrcKind == Type::STK_CPointer)
+      if (SrcKind == Type::STK_CPointer)
         return CK_CPointerToObjCPointerCast;
-      else {
-        maybeExtendBlockObject(*this, Src);
-        return CK_BlockPointerToObjCPointerCast;
-      }
+      maybeExtendBlockObject(*this, Src);
+      return CK_BlockPointerToObjCPointerCast;
     case Type::STK_Bool:
       return CK_PointerToBoolean;
     case Type::STK_Integral:
@@ -4099,7 +4099,7 @@
     case Type::STK_MemberPointer:
       llvm_unreachable("illegal cast from pointer");
     }
-    break;
+    llvm_unreachable("Should have returned before this");
 
   case Type::STK_Bool: // casting from bool is like casting from an integer
   case Type::STK_Integral:
@@ -4130,7 +4130,7 @@
     case Type::STK_MemberPointer:
       llvm_unreachable("member pointer type in C");
     }
-    break;
+    llvm_unreachable("Should have returned before this");
 
   case Type::STK_Floating:
     switch (DestTy->getScalarTypeKind()) {
@@ -4157,7 +4157,7 @@
     case Type::STK_MemberPointer:
       llvm_unreachable("member pointer type in C");
     }
-    break;
+    llvm_unreachable("Should have returned before this");
 
   case Type::STK_FloatingComplex:
     switch (DestTy->getScalarTypeKind()) {
@@ -4186,7 +4186,7 @@
     case Type::STK_MemberPointer:
       llvm_unreachable("member pointer type in C");
     }
-    break;
+    llvm_unreachable("Should have returned before this");
 
   case Type::STK_IntegralComplex:
     switch (DestTy->getScalarTypeKind()) {
@@ -4215,7 +4215,7 @@
     case Type::STK_MemberPointer:
       llvm_unreachable("member pointer type in C");
     }
-    break;
+    llvm_unreachable("Should have returned before this");
   }
 
   llvm_unreachable("Unhandled scalar cast");
@@ -5302,7 +5302,9 @@
   QualType lhptee = LHSType->getAs<ObjCObjectPointerType>()->getPointeeType();
   QualType rhptee = RHSType->getAs<ObjCObjectPointerType>()->getPointeeType();
 
-  if (!lhptee.isAtLeastAsQualifiedAs(rhptee))
+  if (!lhptee.isAtLeastAsQualifiedAs(rhptee) &&
+      // make an exception for id<P>
+      !LHSType->isObjCQualifiedIdType())
     return Sema::CompatiblePointerDiscardsQualifiers;
 
   if (S.Context.typesAreCompatible(LHSType, RHSType))
@@ -5354,9 +5356,6 @@
   LHSType = Context.getCanonicalType(LHSType).getUnqualifiedType();
   RHSType = Context.getCanonicalType(RHSType).getUnqualifiedType();
 
-  // We can't do assignment from/to atomics yet.
-  if (LHSType->isAtomicType())
-    return Incompatible;
 
   // Common case: no conversion required.
   if (LHSType == RHSType) {
@@ -5364,6 +5363,21 @@
     return Compatible;
   }
 
+  if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(LHSType)) {
+    if (AtomicTy->getValueType() == RHSType) {
+      Kind = CK_NonAtomicToAtomic;
+      return Compatible;
+    }
+  }
+
+  if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(RHSType)) {
+    if (AtomicTy->getValueType() == LHSType) {
+      Kind = CK_AtomicToNonAtomic;
+      return Compatible;
+    }
+  }
+
+
   // If the left-hand side is a reference type, then we are in a
   // (rare!) case where we've allowed the use of references in C,
   // e.g., as a parameter type in a built-in function. In this case,
@@ -5902,9 +5916,15 @@
   if (LHS.isInvalid() || RHS.isInvalid())
     return QualType();
 
+
   if (!LHS.get()->getType()->isArithmeticType() ||
-      !RHS.get()->getType()->isArithmeticType())
+      !RHS.get()->getType()->isArithmeticType()) {
+    if (IsCompAssign &&
+        LHS.get()->getType()->isAtomicType() &&
+        RHS.get()->getType()->isArithmeticType())
+      return compType;
     return InvalidOperands(Loc, LHS, RHS);
+  }
 
   // Check for division by zero.
   if (IsDiv &&
@@ -6130,6 +6150,12 @@
     return compType;
   }
 
+  if (LHS.get()->getType()->isAtomicType() &&
+      RHS.get()->getType()->isArithmeticType()) {
+    *CompLHSTy = LHS.get()->getType();
+    return compType;
+  }
+
   // Put any potential pointer into PExp
   Expr* PExp = LHS.get(), *IExp = RHS.get();
   if (IExp->getType()->isAnyPointerType())
@@ -6190,6 +6216,12 @@
     return compType;
   }
 
+  if (LHS.get()->getType()->isAtomicType() &&
+      RHS.get()->getType()->isArithmeticType()) {
+    *CompLHSTy = LHS.get()->getType();
+    return compType;
+  }
+
   // Either ptr - int   or   ptr - ptr.
   if (LHS.get()->getType()->isAnyPointerType()) {
     QualType lpointee = LHS.get()->getType()->getPointeeType();
@@ -6843,6 +6875,26 @@
   return InvalidOperands(Loc, LHS, RHS);
 }
 
+
+// Return a signed type that is of identical size and number of elements.
+// For floating point vectors, return an integer type of identical size 
+// and number of elements.
+QualType Sema::GetSignedVectorType(QualType V) {
+  const VectorType *VTy = V->getAs<VectorType>();
+  unsigned TypeSize = Context.getTypeSize(VTy->getElementType());
+  if (TypeSize == Context.getTypeSize(Context.CharTy))
+    return Context.getExtVectorType(Context.CharTy, VTy->getNumElements());
+  else if (TypeSize == Context.getTypeSize(Context.ShortTy))
+    return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements());
+  else if (TypeSize == Context.getTypeSize(Context.IntTy))
+    return Context.getExtVectorType(Context.IntTy, VTy->getNumElements());
+  else if (TypeSize == Context.getTypeSize(Context.LongTy))
+    return Context.getExtVectorType(Context.LongTy, VTy->getNumElements());
+  assert(TypeSize == Context.getTypeSize(Context.LongLongTy) &&
+         "Unhandled vector element size in vector compare");
+  return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements());
+}
+
 /// CheckVectorCompareOperands - vector comparisons are a clang extension that
 /// operates on extended vector types.  Instead of producing an IntTy result,
 /// like a scalar comparison, a vector comparison produces a vector of integer
@@ -6857,7 +6909,6 @@
     return vType;
 
   QualType LHSType = LHS.get()->getType();
-  QualType RHSType = RHS.get()->getType();
 
   // If AltiVec, the comparison results in a numeric type, i.e.
   // bool for C++, int for C
@@ -6882,26 +6933,23 @@
 
   // Check for comparisons of floating point operands using != and ==.
   if (!IsRelational && LHSType->hasFloatingRepresentation()) {
-    assert (RHSType->hasFloatingRepresentation());
+    assert (RHS.get()->getType()->hasFloatingRepresentation());
     CheckFloatComparison(Loc, LHS.get(), RHS.get());
   }
+  
+  // Return a signed type for the vector.
+  return GetSignedVectorType(LHSType);
+}
 
-  // Return a signed type that is of identical size and number of elements.
-  // For floating point vectors, return an integer type of identical size 
-  // and number of elements.
-  const VectorType *VTy = LHSType->getAs<VectorType>();
-  unsigned TypeSize = Context.getTypeSize(VTy->getElementType());
-  if (TypeSize == Context.getTypeSize(Context.CharTy))
-    return Context.getExtVectorType(Context.CharTy, VTy->getNumElements());
-  else if (TypeSize == Context.getTypeSize(Context.ShortTy))
-    return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements());
-  else if (TypeSize == Context.getTypeSize(Context.IntTy))
-    return Context.getExtVectorType(Context.IntTy, VTy->getNumElements());
-  else if (TypeSize == Context.getTypeSize(Context.LongTy))
-    return Context.getExtVectorType(Context.LongTy, VTy->getNumElements());
-  assert(TypeSize == Context.getTypeSize(Context.LongLongTy) &&
-         "Unhandled vector element size in vector compare");
-  return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements());
+QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
+                                          SourceLocation Loc) {
+  // Ensure that either both operands are of the same vector type, or
+  // one operand is of a vector type and the other is of its element type.
+  QualType vType = CheckVectorOperands(LHS, RHS, Loc, false);
+  if (vType.isNull() || vType->isFloatingType())
+    return InvalidOperands(Loc, LHS, RHS);
+  
+  return GetSignedVectorType(LHS.get()->getType());
 }
 
 inline QualType Sema::CheckBitwiseOperands(
@@ -6934,6 +6982,10 @@
 inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
   ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc) {
   
+  // Check vector operands differently.
+  if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType())
+    return CheckVectorLogicalOperands(LHS, RHS, Loc);
+  
   // Diagnose cases where the user write a logical and/or but probably meant a
   // bitwise one.  We do this when the LHS is a non-bool integer and the RHS
   // is a constant.
@@ -7141,7 +7193,6 @@
   case Expr::MLV_ReadonlyProperty:
   case Expr::MLV_NoSetterProperty:
     llvm_unreachable("readonly properties should be processed differently");
-    break;
   case Expr::MLV_InvalidMessageExpression:
     Diag = diag::error_readonly_message_assignment;
     break;
@@ -7287,6 +7338,12 @@
     return S.Context.DependentTy;
 
   QualType ResType = Op->getType();
+  // Atomic types can be used for increment / decrement where the non-atomic
+  // versions can, so ignore the _Atomic() specifier for the purpose of
+  // checking.
+  if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>())
+    ResType = ResAtomicType->getValueType();
+
   assert(!ResType.isNull() && "no type for increment/decrement expression");
 
   if (S.getLangOptions().CPlusPlus && ResType->isBooleanType()) {
@@ -8099,6 +8156,9 @@
       if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())
         return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
 
+      if (LHSExpr->getType()->isOverloadableType())
+        return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
+
       return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
     }
 
@@ -8217,6 +8277,10 @@
         Input = ImpCastExprToType(Input.take(), Context.BoolTy,
                                   ScalarTypeToBooleanCastKind(resultType));
       }
+    } else if (resultType->isExtVectorType()) {
+      // Vector logical not returns the signed variant of the operand type.
+      resultType = GetSignedVectorType(resultType);
+      break;
     } else {
       return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
         << resultType << Input.get()->getSourceRange());
@@ -8799,12 +8863,6 @@
   // Finally we can process decl attributes.
   ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
 
-  if (!isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) {
-    Diag(ParamInfo.getAttributes()->getLoc(),
-         diag::warn_attribute_sentinel_not_variadic) << 1;
-    // FIXME: remove the attribute.
-  }
-
   // Put the parameter variables in scope.  We can bail out immediately
   // if we don't have any.
   if (Params.empty())
@@ -8832,7 +8890,7 @@
 
   // Pop off CurBlock, handle nested blocks.
   PopDeclContext();
-  PopFunctionOrBlockScope();
+  PopFunctionScopeInfo();
 }
 
 /// ActOnBlockStmtExpr - This is called when the body of a block statement
@@ -8859,8 +8917,18 @@
   QualType BlockTy;
 
   // Set the captured variables on the block.
-  BSI->TheDecl->setCaptures(Context, BSI->Captures.begin(), BSI->Captures.end(),
-                            BSI->CapturesCXXThis);
+  // FIXME: Share capture structure between BlockDecl and CapturingScopeInfo!
+  SmallVector<BlockDecl::Capture, 4> Captures;
+  for (unsigned i = 0, e = BSI->Captures.size(); i != e; i++) {
+    CapturingScopeInfo::Capture &Cap = BSI->Captures[i];
+    if (Cap.isThisCapture())
+      continue;
+    BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isReferenceCapture(),
+                              Cap.isNested(), Cap.getCopyExpr());
+    Captures.push_back(NewCap);
+  }
+  BSI->TheDecl->setCaptures(Context, Captures.begin(), Captures.end(),
+                            BSI->CXXThisCaptureIndex != 0);
 
   // If the user wrote a function type in some form, try to use that.
   if (!BSI->FunctionType.isNull()) {
@@ -8924,7 +8992,7 @@
   
   BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
   const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy();
-  PopFunctionOrBlockScope(&WP, Result->getBlockDecl(), Result);
+  PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result);
 
   // If the block isn't obviously global, i.e. it captures anything at
   // all, mark this full-expression as needing a cleanup.
@@ -9087,7 +9155,6 @@
   bool MayHaveFunctionDiff = false;
 
   switch (ConvTy) {
-  default: llvm_unreachable("Unknown conversion type");
   case Compatible: return false;
   case PointerToInt:
     DiagKind = diag::ext_typecheck_convert_pointer_int;
@@ -9204,9 +9271,8 @@
   // If we can fix the conversion, suggest the FixIts.
   assert(ConvHints.isNull() || Hint.isNull());
   if (!ConvHints.isNull()) {
-    for (llvm::SmallVector<FixItHint, 1>::iterator
-        HI = ConvHints.Hints.begin(), HE = ConvHints.Hints.end();
-        HI != HE; ++HI)
+    for (std::vector<FixItHint>::iterator HI = ConvHints.Hints.begin(),
+         HE = ConvHints.Hints.end(); HI != HE; ++HI)
       FDiag << *HI;
   } else {
     FDiag << Hint;
@@ -9261,8 +9327,11 @@
   }
 
   if (!Folded || !AllowFold) {
-    Diag(E->getSourceRange().getBegin(),
-         DiagID ? DiagID : diag::err_expr_not_ice) << E->getSourceRange();
+    if (DiagID)
+      Diag(E->getSourceRange().getBegin(), DiagID) << E->getSourceRange();
+    else
+      Diag(E->getSourceRange().getBegin(), diag::err_expr_not_ice)
+        << E->getSourceRange() << LangOpts.CPlusPlus;
 
     // We only show the notes if they're not the usual "invalid subexpression"
     // or if they are actually in a subexpression.
@@ -9277,18 +9346,63 @@
   }
 
   Diag(E->getSourceRange().getBegin(), diag::ext_expr_not_ice)
-    << E->getSourceRange();
-
-  if (Diags.getDiagnosticLevel(diag::ext_expr_not_ice, E->getExprLoc())
-          != DiagnosticsEngine::Ignored)
-    for (unsigned I = 0, N = Notes.size(); I != N; ++I)
-      Diag(Notes[I].first, Notes[I].second);
+    << E->getSourceRange() << LangOpts.CPlusPlus;
+  for (unsigned I = 0, N = Notes.size(); I != N; ++I)
+    Diag(Notes[I].first, Notes[I].second);
 
   if (Result)
     *Result = EvalResult.Val.getInt();
   return false;
 }
 
+namespace {
+  // Handle the case where we conclude a expression which we speculatively
+  // considered to be unevaluated is actually evaluated.
+  class TransformToPE : public TreeTransform<TransformToPE> {
+    typedef TreeTransform<TransformToPE> BaseTransform;
+
+  public:
+    TransformToPE(Sema &SemaRef) : BaseTransform(SemaRef) { }
+
+    // Make sure we redo semantic analysis
+    bool AlwaysRebuild() { return true; }
+
+    // We need to special-case DeclRefExprs referring to FieldDecls which
+    // are not part of a member pointer formation; normal TreeTransforming
+    // doesn't catch this case because of the way we represent them in the AST.
+    // FIXME: This is a bit ugly; is it really the best way to handle this
+    // case?
+    //
+    // Error on DeclRefExprs referring to FieldDecls.
+    ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
+      if (isa<FieldDecl>(E->getDecl()) &&
+          SemaRef.ExprEvalContexts.back().Context != Sema::Unevaluated)
+        return SemaRef.Diag(E->getLocation(),
+                            diag::err_invalid_non_static_member_use)
+            << E->getDecl() << E->getSourceRange();
+
+      return BaseTransform::TransformDeclRefExpr(E);
+    }
+
+    // Exception: filter out member pointer formation
+    ExprResult TransformUnaryOperator(UnaryOperator *E) {
+      if (E->getOpcode() == UO_AddrOf && E->getType()->isMemberPointerType())
+        return E;
+
+      return BaseTransform::TransformUnaryOperator(E);
+    }
+
+  };
+}
+
+ExprResult Sema::TranformToPotentiallyEvaluated(Expr *E) {
+  ExprEvalContexts.back().Context =
+      ExprEvalContexts[ExprEvalContexts.size()-2].Context;
+  if (ExprEvalContexts.back().Context == Unevaluated)
+    return E;
+  return TransformToPE(*this).TransformExpr(E);
+}
+
 void
 Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
   ExprEvalContexts.push_back(
@@ -9303,33 +9417,11 @@
   ExpressionEvaluationContextRecord Rec = ExprEvalContexts.back();
   ExprEvalContexts.pop_back();
 
-  if (Rec.Context == PotentiallyPotentiallyEvaluated) {
-    if (Rec.PotentiallyReferenced) {
-      // Mark any remaining declarations in the current position of the stack
-      // as "referenced". If they were not meant to be referenced, semantic
-      // analysis would have eliminated them (e.g., in ActOnCXXTypeId).
-      for (PotentiallyReferencedDecls::iterator
-             I = Rec.PotentiallyReferenced->begin(),
-             IEnd = Rec.PotentiallyReferenced->end();
-           I != IEnd; ++I)
-        MarkDeclarationReferenced(I->first, I->second);
-    }
-
-    if (Rec.PotentiallyDiagnosed) {
-      // Emit any pending diagnostics.
-      for (PotentiallyEmittedDiagnostics::iterator
-                I = Rec.PotentiallyDiagnosed->begin(),
-             IEnd = Rec.PotentiallyDiagnosed->end();
-           I != IEnd; ++I)
-        Diag(I->first, I->second);
-    }
-  }
-
   // When are coming out of an unevaluated context, clear out any
   // temporaries that we may have created as part of the evaluation of
   // the expression in that context: they aren't relevant because they
   // will never be constructed.
-  if (Rec.Context == Unevaluated) {
+  if (Rec.Context == Unevaluated || Rec.Context == ConstantEvaluated) {
     ExprCleanupObjects.erase(ExprCleanupObjects.begin() + Rec.NumCleanupObjects,
                              ExprCleanupObjects.end());
     ExprNeedsCleanups = Rec.ParentNeedsCleanups;
@@ -9338,9 +9430,6 @@
   } else {
     ExprNeedsCleanups |= Rec.ParentNeedsCleanups;
   }
-
-  // Destroy the popped expression evaluation record.
-  Rec.Destroy();
 }
 
 void Sema::DiscardCleanupsInEvaluationContext() {
@@ -9368,16 +9457,6 @@
   if (D->isUsed(false))
     return;
 
-  // Mark a parameter or variable declaration "used", regardless of whether
-  // we're in a template or not. The reason for this is that unevaluated
-  // expressions (e.g. (void)sizeof()) constitute a use for warning purposes
-  // (-Wunused-variables and -Wunused-parameters)
-  if (isa<ParmVarDecl>(D) ||
-      (isa<VarDecl>(D) && D->getDeclContext()->isFunctionOrMethod())) {
-    D->setUsed();
-    return;
-  }
-
   if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D))
     return;
 
@@ -9391,18 +9470,21 @@
       // We are in an expression that is not potentially evaluated; do nothing.
       return;
 
+    case ConstantEvaluated:
+      // We are in an expression that will be evaluated during translation; in
+      // C++11, we need to define any functions which are used in case they're
+      // constexpr, whereas in C++98, we only need to define static data members
+      // of class templates.
+      if (!getLangOptions().CPlusPlus ||
+          (!getLangOptions().CPlusPlus0x && !isa<VarDecl>(D)))
+        return;
+      break;
+
     case PotentiallyEvaluated:
       // We are in a potentially-evaluated expression, so this declaration is
       // "used"; handle this below.
       break;
 
-    case PotentiallyPotentiallyEvaluated:
-      // We are in an expression that may be potentially evaluated; queue this
-      // declaration reference until we know whether the expression is
-      // potentially evaluated.
-      ExprEvalContexts.back().addReferencedDecl(Loc, D);
-      return;
-      
     case PotentiallyEvaluatedIfUsed:
       // Referenced declarations will only be used if the construct in the
       // containing expression is used.
@@ -9473,6 +9555,11 @@
             cast<CXXRecordDecl>(Function->getDeclContext())->isLocalClass())
           PendingLocalImplicitInstantiations.push_back(std::make_pair(Function,
                                                                       Loc));
+        else if (Function->getTemplateInstantiationPattern()->isConstexpr())
+          // Do not defer instantiations of constexpr functions, to avoid the
+          // expression evaluator needing to call back into Sema if it sees a
+          // call to such a function.
+          InstantiateFunctionDefinition(Loc, Function);
         else
           PendingInstantiations.push_back(std::make_pair(Function, Loc));
       }
@@ -9508,7 +9595,12 @@
         // This is a modification of an existing AST node. Notify listeners.
         if (ASTMutationListener *L = getASTMutationListener())
           L->StaticDataMemberInstantiated(Var);
-        PendingInstantiations.push_back(std::make_pair(Var, Loc));
+        if (Var->isUsableInConstantExpressions())
+          // Do not defer instantiations of variables which could be used in a
+          // constant expression.
+          InstantiateStaticDataMemberDefinition(Loc, Var);
+        else
+          PendingInstantiations.push_back(std::make_pair(Var, Loc));
       }
     }
 
@@ -9662,6 +9754,10 @@
     // The argument will never be evaluated, so don't complain.
     break;
 
+  case ConstantEvaluated:
+    // Relevant diagnostics should be produced by constant evaluation.
+    break;
+
   case PotentiallyEvaluated:
   case PotentiallyEvaluatedIfUsed:
     if (Statement && getCurFunctionOrMethodDecl()) {
@@ -9672,10 +9768,6 @@
       Diag(Loc, PD);
       
     return true;
-
-  case PotentiallyPotentiallyEvaluated:
-    ExprEvalContexts.back().addDiagnostic(Loc, PD);
-    break;
   }
 
   return false;
@@ -9836,7 +9928,6 @@
 
     ExprResult VisitStmt(Stmt *S) {
       llvm_unreachable("unexpected statement!");
-      return ExprError();
     }
 
     ExprResult VisitExpr(Expr *E) {
@@ -9929,7 +10020,6 @@
 
     ExprResult VisitStmt(Stmt *S) {
       llvm_unreachable("unexpected statement!");
-      return ExprError();
     }
 
     ExprResult VisitExpr(Expr *E) {

Modified: cfe/branches/tooling/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaExprCXX.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaExprCXX.cpp Fri Jan 20 10:14:22 2012
@@ -310,7 +310,6 @@
                                 SourceLocation TypeidLoc,
                                 Expr *E,
                                 SourceLocation RParenLoc) {
-  bool isUnevaluatedOperand = true;
   if (E && !E->isTypeDependent()) {
     if (E->getType()->isPlaceholderType()) {
       ExprResult result = CheckPlaceholderExpr(E);
@@ -332,7 +331,11 @@
       //   polymorphic class type [...] [the] expression is an unevaluated
       //   operand. [...]
       if (RecordD->isPolymorphic() && E->Classify(Context).isGLValue()) {
-        isUnevaluatedOperand = false;
+        // The subexpression is potentially evaluated; switch the context
+        // and recheck the subexpression.
+        ExprResult Result = TranformToPotentiallyEvaluated(E);
+        if (Result.isInvalid()) return ExprError();
+        E = Result.take();
 
         // We require a vtable to query the type at run time.
         MarkVTableUsed(TypeidLoc, RecordD);
@@ -352,12 +355,6 @@
     }
   }
 
-  // If this is an unevaluated operand, clear out the set of
-  // declaration references we have been computing and eliminate any
-  // temporaries introduced in its computation.
-  if (isUnevaluatedOperand)
-    ExprEvalContexts.back().Context = Unevaluated;
-
   return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(),
                                            E,
                                            SourceRange(TypeidLoc, RParenLoc)));
@@ -653,22 +650,8 @@
   return Owned(E);
 }
 
-QualType Sema::getCurrentThisType(bool Capture) {
-  // Ignore block scopes: we can capture through them.
-  // Ignore nested enum scopes: we'll diagnose non-constant expressions
-  // where they're invalid, and other uses are legitimate.
-  // Don't ignore nested class scopes: you can't use 'this' in a local class.
-  DeclContext *DC = CurContext;
-  unsigned NumBlocks = 0;
-  while (true) {
-    if (isa<BlockDecl>(DC)) {
-      DC = cast<BlockDecl>(DC)->getDeclContext();
-      ++NumBlocks;
-    } else if (isa<EnumDecl>(DC))
-      DC = cast<EnumDecl>(DC)->getDeclContext();
-    else break;
-  }
-
+QualType Sema::getCurrentThisType() {
+  DeclContext *DC = getFunctionLevelDeclContext();
   QualType ThisTy;
   if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) {
     if (method && method->isInstance())
@@ -683,17 +666,49 @@
       ThisTy = Context.getPointerType(Context.getRecordType(RD));
   }
 
-  if (!Capture || ThisTy.isNull())
-    return ThisTy;
-  
-  // Mark that we're closing on 'this' in all the block scopes we ignored.
-  for (unsigned idx = FunctionScopes.size() - 1;
-       NumBlocks; --idx, --NumBlocks)
-    cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true;
-
   return ThisTy;
 }
 
+void Sema::CheckCXXThisCapture(SourceLocation Loc) {
+  // We don't need to capture this in an unevaluated context.
+  if (ExprEvalContexts.back().Context == Unevaluated)
+    return;
+
+  // Otherwise, check that we can capture 'this'.
+  unsigned NumClosures = 0;
+  for (unsigned idx = FunctionScopes.size() - 1; idx != 0; idx--) {
+    if (CapturingScopeInfo *CSI =
+            dyn_cast<CapturingScopeInfo>(FunctionScopes[idx])) {
+      if (CSI->CXXThisCaptureIndex != 0) {
+        // 'this' is already being captured; there isn't anything more to do.
+        break;
+      }
+      if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByref ||
+          CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_Block) {
+        // This closure can implicitly capture 'this'; continue looking upwards.
+        // FIXME: Is this check correct?  The rules in the standard are a bit
+        // unclear.
+        NumClosures++;
+        continue;
+      }
+      // This context can't implicitly capture 'this'; fail out.
+      Diag(Loc, diag::err_implicit_this_capture);
+      return;
+    }
+    break;
+  }
+
+  // Mark that we're implicitly capturing 'this' in all the scopes we skipped.
+  // FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated
+  // contexts.
+  for (unsigned idx = FunctionScopes.size() - 1;
+       NumClosures; --idx, --NumClosures) {
+    CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]);
+    bool isNested = NumClosures > 1;
+    CSI->AddThisCapture(isNested);
+  }
+}
+
 ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
   /// C++ 9.3.2: In the body of a non-static member function, the keyword this
   /// is a non-lvalue expression whose value is the address of the object for
@@ -702,6 +717,7 @@
   QualType ThisTy = getCurrentThisType();
   if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use);
 
+  CheckCXXThisCapture(Loc);
   return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false));
 }
 
@@ -977,10 +993,13 @@
   // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral
   //   or enumeration type with a non-negative value."
   if (ArraySize && !ArraySize->isTypeDependent()) {
+    // Eliminate placeholders.
+    ExprResult ConvertedSize = CheckPlaceholderExpr(ArraySize);
+    if (ConvertedSize.isInvalid())
+      return ExprError();
+    ArraySize = ConvertedSize.take();
 
-    QualType SizeType = ArraySize->getType();
-
-    ExprResult ConvertedSize = ConvertToIntegralOrEnumerationType(
+    ConvertedSize = ConvertToIntegralOrEnumerationType(
       StartLoc, ArraySize,
       PDiag(diag::err_array_size_not_integral),
       PDiag(diag::err_array_size_incomplete_type)
@@ -996,7 +1015,7 @@
       return ExprError();
 
     ArraySize = ConvertedSize.take();
-    SizeType = ArraySize->getType();
+    QualType SizeType = ArraySize->getType();
     if (!SizeType->isIntegralOrUnscopedEnumerationType())
       return ExprError();
 
@@ -2014,6 +2033,9 @@
                                         ConditionVar->getLocation(),
                             ConditionVar->getType().getNonReferenceType(),
                               VK_LValue));
+
+  MarkDeclarationReferenced(ConditionVar->getLocation(), ConditionVar);
+
   if (ConvertToBoolean) {
     Condition = CheckBooleanCondition(Condition.take(), StmtLoc);
     if (Condition.isInvalid())
@@ -4265,21 +4287,26 @@
       }
     }
 
-    if (BaseType->isPointerType())
+    if (BaseType->isPointerType() || BaseType->isObjCObjectPointerType())
       BaseType = BaseType->getPointeeType();
   }
 
-  // We could end up with various non-record types here, such as extended
-  // vector types or Objective-C interfaces. Just return early and let
-  // ActOnMemberReferenceExpr do the work.
-  if (!BaseType->isRecordType()) {
-    // C++ [basic.lookup.classref]p2:
-    //   [...] If the type of the object expression is of pointer to scalar
-    //   type, the unqualified-id is looked up in the context of the complete
-    //   postfix-expression.
-    //
-    // This also indicates that we should be parsing a
-    // pseudo-destructor-name.
+  // Objective-C properties allow "." access on Objective-C pointer types,
+  // so adjust the base type to the object type itself.
+  if (BaseType->isObjCObjectPointerType())
+    BaseType = BaseType->getPointeeType();
+  
+  // C++ [basic.lookup.classref]p2:
+  //   [...] If the type of the object expression is of pointer to scalar
+  //   type, the unqualified-id is looked up in the context of the complete
+  //   postfix-expression.
+  //
+  // This also indicates that we could be parsing a pseudo-destructor-name.
+  // Note that Objective-C class and object types can be pseudo-destructor
+  // expressions or normal member (ivar or property) access expressions.
+  if (BaseType->isObjCObjectOrInterfaceType()) {
+    MayBePseudoDestructor = true;
+  } else if (!BaseType->isRecordType()) {
     ObjectType = ParsedType();
     MayBePseudoDestructor = true;
     return Owned(Base);
@@ -4749,8 +4776,8 @@
   case LookupResult::NotFoundInCurrentInstantiation:
     return IER_Dependent;
   }
-  
-  return IER_DoesNotExist;  
+
+  llvm_unreachable("Invalid LookupResult Kind!");
 }
 
 Sema::IfExistsResult 
@@ -4774,3 +4801,217 @@
   return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo);
 }
 
+//===----------------------------------------------------------------------===//
+// Lambdas.
+//===----------------------------------------------------------------------===//
+
+void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
+                                        Declarator &ParamInfo,
+                                        Scope *CurScope) {
+  DeclContext *DC = CurContext;
+  while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
+    DC = DC->getParent();
+
+  // Start constructing the lambda class.
+  CXXRecordDecl *Class = CXXRecordDecl::Create(Context, TTK_Class, DC,
+                                               Intro.Range.getBegin(),
+                                               /*IdLoc=*/SourceLocation(),
+                                               /*Id=*/0);
+  Class->startDefinition();
+  Class->setLambda(true);
+  CurContext->addDecl(Class);
+
+  QualType ThisCaptureType;
+  llvm::DenseMap<VarDecl*, unsigned> CaptureMap;
+  unsigned CXXThisCaptureIndex = 0;
+  llvm::SmallVector<LambdaScopeInfo::Capture, 4> Captures;
+  for (llvm::SmallVector<LambdaCapture, 4>::const_iterator
+       C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E; ++C) {
+    if (C->Kind == LCK_This) {
+      if (!ThisCaptureType.isNull()) {
+        Diag(C->Loc, diag::err_capture_more_than_once) << "'this'";
+        continue;
+      }
+
+      if (Intro.Default == LCD_ByCopy) {
+        Diag(C->Loc, diag::err_this_capture_with_copy_default);
+        continue;
+      }
+
+      ThisCaptureType = getCurrentThisType();
+      if (ThisCaptureType.isNull()) {
+        Diag(C->Loc, diag::err_invalid_this_use);
+        continue;
+      }
+      CheckCXXThisCapture(C->Loc);
+
+      // FIXME: Need getCurCapture().
+      bool isNested = getCurBlock() || getCurLambda();
+      CapturingScopeInfo::Capture Cap(CapturingScopeInfo::Capture::ThisCapture,
+                                      isNested);
+      Captures.push_back(Cap);
+      CXXThisCaptureIndex = Captures.size();
+      continue;
+    }
+
+    assert(C->Id && "missing identifier for capture");
+
+    if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
+      Diag(C->Loc, diag::err_reference_capture_with_reference_default);
+      continue;
+    } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
+      Diag(C->Loc, diag::err_copy_capture_with_copy_default);
+      continue;
+    }
+
+    DeclarationNameInfo Name(C->Id, C->Loc);
+    LookupResult R(*this, Name, LookupOrdinaryName);
+    CXXScopeSpec ScopeSpec;
+    LookupParsedName(R, CurScope, &ScopeSpec);
+    if (R.isAmbiguous())
+      continue;
+    if (R.empty()) {
+      DeclFilterCCC<VarDecl> Validator;
+      if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator))
+        continue;
+    }
+
+    VarDecl *Var = R.getAsSingle<VarDecl>();
+    if (!Var) {
+      Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
+      continue;
+    }
+
+    if (CaptureMap.count(Var)) {
+      Diag(C->Loc, diag::err_capture_more_than_once) << C->Id;
+      continue;
+    }
+
+    if (!Var->hasLocalStorage()) {
+      Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id;
+      continue;
+    }
+
+    // FIXME: This is completely wrong for nested captures and variables
+    // with a non-trivial constructor.
+    // FIXME: We should refuse to capture __block variables.
+    Captures.push_back(LambdaScopeInfo::Capture(Var, C->Kind == LCK_ByRef,
+                                                /*isNested*/false, 0));
+    CaptureMap[Var] = Captures.size();
+  }
+
+  // Build the call operator; we don't really have all the relevant information
+  // at this point, but we need something to attach child declarations to.
+  QualType MethodTy;
+  TypeSourceInfo *MethodTyInfo;
+  if (ParamInfo.getNumTypeObjects() == 0) {
+    FunctionProtoType::ExtProtoInfo EPI;
+    EPI.TypeQuals |= DeclSpec::TQ_const;
+    MethodTy = Context.getFunctionType(Context.DependentTy,
+                                       /*Args=*/0, /*NumArgs=*/0, EPI);
+    MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
+  } else {
+    assert(ParamInfo.isFunctionDeclarator() &&
+           "lambda-declarator is a function");
+    DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
+    if (!FTI.hasMutableQualifier())
+      FTI.TypeQuals |= DeclSpec::TQ_const;
+    MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
+    // FIXME: Can these asserts actually fail?
+    assert(MethodTyInfo && "no type from lambda-declarator");
+    MethodTy = MethodTyInfo->getType();
+    assert(!MethodTy.isNull() && "no type from lambda declarator");
+  }
+
+  DeclarationName MethodName
+    = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+  CXXMethodDecl *Method
+    = CXXMethodDecl::Create(Context,
+                            Class,
+                            ParamInfo.getSourceRange().getEnd(),
+                            DeclarationNameInfo(MethodName,
+                                                /*NameLoc=*/SourceLocation()),
+                            MethodTy,
+                            MethodTyInfo,
+                            /*isStatic=*/false,
+                            SC_None,
+                            /*isInline=*/true,
+                            /*isConstExpr=*/false,
+                            ParamInfo.getSourceRange().getEnd());
+  Method->setAccess(AS_public);
+  Class->addDecl(Method);
+  Method->setLexicalDeclContext(DC); // FIXME: Is this really correct?
+
+  ProcessDeclAttributes(CurScope, Method, ParamInfo);
+
+  // Enter a new evaluation context to insulate the block from any
+  // cleanups from the enclosing full-expression.
+  PushExpressionEvaluationContext(PotentiallyEvaluated);
+
+  PushDeclContext(CurScope, Method);
+
+  // Set the parameters on the decl, if specified.
+  if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) {
+    FunctionProtoTypeLoc Proto =
+        cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc());
+    Method->setParams(Proto.getParams());
+    CheckParmsForFunctionDef(Method->param_begin(),
+                             Method->param_end(),
+                             /*CheckParameterNames=*/false);
+
+    // Introduce our parameters into the function scope
+    for (unsigned p = 0, NumParams = Method->getNumParams(); p < NumParams; ++p) {
+      ParmVarDecl *Param = Method->getParamDecl(p);
+      Param->setOwningFunction(Method);
+
+      // If this has an identifier, add it to the scope stack.
+      if (Param->getIdentifier()) {
+        CheckShadow(CurScope, Param);
+
+        PushOnScopeChains(Param, CurScope);
+      }
+    }
+  }
+
+  // Introduce the lambda scope.
+  PushLambdaScope(Class);
+
+  LambdaScopeInfo *LSI = getCurLambda();
+  LSI->CXXThisCaptureIndex = CXXThisCaptureIndex;
+  std::swap(LSI->CaptureMap, CaptureMap);
+  std::swap(LSI->Captures, Captures);
+  LSI->NumExplicitCaptures = Captures.size();
+  if (Intro.Default == LCD_ByCopy)
+    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
+  else if (Intro.Default == LCD_ByRef)
+    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
+
+  const FunctionType *Fn = MethodTy->getAs<FunctionType>();
+  QualType RetTy = Fn->getResultType();
+  if (RetTy != Context.DependentTy) {
+    LSI->ReturnType = RetTy;
+  } else {
+    LSI->HasImplicitReturnType = true;
+  }
+
+  // FIXME: Check return type is complete, !isObjCObjectType
+  
+}
+
+void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
+  // Leave the expression-evaluation context.
+  DiscardCleanupsInEvaluationContext();
+  PopExpressionEvaluationContext();
+
+  // Leave the context of the lambda.
+  PopDeclContext();
+  PopFunctionScopeInfo();
+}
+
+ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
+                                 Stmt *Body, Scope *CurScope) {
+  // FIXME: Implement
+  Diag(StartLoc, diag::err_lambda_unsupported);
+  ActOnLambdaError(StartLoc, CurScope);
+  return ExprError();
+}

Modified: cfe/branches/tooling/lib/Sema/SemaExprMember.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaExprMember.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaExprMember.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaExprMember.cpp Fri Jan 20 10:14:22 2012
@@ -56,7 +56,7 @@
   /// The reference may be an implicit instance member access.
   IMA_Mixed,
 
-  /// The reference may be to an instance member, but it is invalid if
+  /// The reference may be to an instance member, but it might be invalid if
   /// so, because the context is not an instance method.
   IMA_Mixed_StaticContext,
 
@@ -74,6 +74,11 @@
   /// context is not an instance method.
   IMA_Unresolved_StaticContext,
 
+  // The reference refers to a field which is not a member of the containing
+  // class, which is allowed because we're in C++11 mode and the context is
+  // unevaluated.
+  IMA_Field_Uneval_Context,
+
   /// All possible referrents are instance members and the current
   /// context is not an instance method.
   IMA_Error_StaticContext,
@@ -86,7 +91,7 @@
 /// The given lookup names class member(s) and is not being used for
 /// an address-of-member expression.  Classify the type of access
 /// according to whether it's possible that this reference names an
-/// instance member.  This is best-effort; it is okay to
+/// instance member.  This is best-effort in dependent contexts; it is okay to
 /// conservatively answer "yes", in which case some errors will simply
 /// not be caught until template-instantiation.
 static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
@@ -112,14 +117,14 @@
 
   // Collect all the declaring classes of instance members we find.
   bool hasNonInstance = false;
-  bool hasField = false;
+  bool isField = false;
   llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes;
   for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
     NamedDecl *D = *I;
 
     if (D->isCXXInstanceMember()) {
       if (dyn_cast<FieldDecl>(D))
-        hasField = true;
+        isField = true;
 
       CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
       Classes.insert(R->getCanonicalDecl());
@@ -139,8 +144,8 @@
     if (hasNonInstance)
         return IMA_Mixed_StaticContext;
         
-    if (SemaRef.getLangOptions().CPlusPlus0x && hasField) {
-      // C++0x [expr.prim.general]p10:
+    if (SemaRef.getLangOptions().CPlusPlus0x && isField) {
+      // C++11 [expr.prim.general]p12:
       //   An id-expression that denotes a non-static data member or non-static
       //   member function of a class can only be used:
       //   (...)
@@ -148,9 +153,8 @@
       //     appears in an unevaluated operand.
       const Sema::ExpressionEvaluationContextRecord& record
         = SemaRef.ExprEvalContexts.back();
-      bool isUnevaluatedExpression = (record.Context == Sema::Unevaluated);
-      if (isUnevaluatedExpression)
-        return IMA_Mixed_StaticContext;
+      if (record.Context == Sema::Unevaluated)
+        return IMA_Field_Uneval_Context;
     }
     
     return IMA_Error_StaticContext;
@@ -196,16 +200,16 @@
       if (MD->isStatic()) {
         // "invalid use of member 'x' in static member function"
         SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
-        << Range << nameInfo.getName();
+            << Range << nameInfo.getName();
         return;
       }
     }
-    
+
     SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
-    << nameInfo.getName() << Range;
+        << nameInfo.getName() << Range;
     return;
   }
-  
+
   SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range;
 }
 
@@ -226,6 +230,7 @@
   case IMA_Static:
   case IMA_Mixed_StaticContext:
   case IMA_Unresolved_StaticContext:
+  case IMA_Field_Uneval_Context:
     if (TemplateArgs)
       return BuildTemplateIdExpr(SS, R, false, *TemplateArgs);
     return BuildDeclarationNameExpr(SS, R, false);
@@ -238,7 +243,6 @@
   }
 
   llvm_unreachable("unexpected instance member access kind");
-  return ExprError();
 }
 
 /// Check an ext-vector component access expression.
@@ -509,6 +513,20 @@
   return true;
 }
 
+namespace {
+
+// Callback to only accept typo corrections that are either a ValueDecl or a
+// FunctionTemplateDecl.
+class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    NamedDecl *ND = candidate.getCorrectionDecl();
+    return ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND));
+  }
+};
+
+}
+
 static bool
 LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
                          SourceRange BaseRange, const RecordType *RTy,
@@ -559,13 +577,12 @@
   // We didn't find anything with the given name, so try to correct
   // for typos.
   DeclarationName Name = R.getLookupName();
+  RecordMemberExprValidatorCCC Validator;
   TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(),
                                                  R.getLookupKind(), NULL,
-                                                 &SS, DC, false,
-                                                 Sema::CTC_MemberLookup);
-  NamedDecl *ND = Corrected.getCorrectionDecl();
+                                                 &SS, &Validator, DC);
   R.clear();
-  if (ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))) {
+  if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
     std::string CorrectedStr(
         Corrected.getAsString(SemaRef.getLangOptions()));
     std::string CorrectedQuotedStr(
@@ -705,6 +722,7 @@
     }
     
     // Our base object expression is "this".
+    CheckCXXThisCapture(loc);
     baseObjectExpr 
       = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true);
     baseObjectIsPointer = true;
@@ -854,6 +872,7 @@
     SourceLocation Loc = R.getNameLoc();
     if (SS.getRange().isValid())
       Loc = SS.getRange().getBegin();
+    CheckCXXThisCapture(Loc);
     BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true);
   }
 
@@ -974,12 +993,10 @@
 /// Perform conversions on the LHS of a member access expression.
 ExprResult
 Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) {
-  ExprResult BaseResult = DefaultFunctionArrayConversion(Base);
+  if (IsArrow && !Base->getType()->isFunctionType())
+    return DefaultFunctionArrayLvalueConversion(Base);
 
-  if (!BaseResult.isInvalid() && IsArrow)
-    BaseResult = DefaultLvalueConversion(BaseResult.take());
-
-  return BaseResult;
+  return CheckPlaceholderExpr(Base);
 }
 
 /// Look up the given member of the given non-type-dependent
@@ -1031,7 +1048,7 @@
         << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
         << FixItHint::CreateReplacement(OpLoc, ".");
       IsArrow = false;
-    } else if (BaseType == Context.BoundMemberTy) {
+    } else if (BaseType->isFunctionType()) {
       goto fail;
     } else {
       Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
@@ -1073,10 +1090,12 @@
         goto fail;
       // There's an implicit 'isa' ivar on all objects.
       // But we only actually find it this way on objects of type 'id',
-      // apparently.
-      if (OTy->isObjCId() && Member->isStr("isa"))
+      // apparently.ghjg
+      if (OTy->isObjCId() && Member->isStr("isa")) {
+        Diag(MemberLoc, diag::warn_objc_isa_use);
         return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc,
                                                Context.getObjCClassType()));
+      }
 
       if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
         return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
@@ -1084,17 +1103,22 @@
       goto fail;
     }
 
+    if (RequireCompleteType(OpLoc, BaseType, 
+                            PDiag(diag::err_typecheck_incomplete_tag)
+                              << BaseExpr.get()->getSourceRange()))
+      return ExprError();
+    
     ObjCInterfaceDecl *ClassDeclared;
     ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
 
     if (!IV) {
       // Attempt to correct for typos in ivar names.
-      LookupResult Res(*this, R.getLookupName(), R.getNameLoc(),
-                       LookupMemberName);
-      TypoCorrection Corrected = CorrectTypo(
-          R.getLookupNameInfo(), LookupMemberName, NULL, NULL, IDecl, false,
-          IsArrow ? CTC_ObjCIvarLookup : CTC_ObjCPropertyLookup);
-      if ((IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>())) {
+      DeclFilterCCC<ObjCIvarDecl> Validator;
+      Validator.IsObjCIvarLookup = IsArrow;
+      if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
+                                                 LookupMemberName, NULL, NULL,
+                                                 &Validator, IDecl)) {
+        IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
         Diag(R.getNameLoc(),
              diag::err_typecheck_member_reference_ivar_suggest)
           << IDecl->getDeclName() << MemberName << IV->getDeclName()
@@ -1110,8 +1134,6 @@
           << FixItHint::CreateReplacement(OpLoc, ".");
           return ExprError();
         }
-        Res.clear();
-        Res.setLookupName(Member);
 
         Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
           << IDecl->getDeclName() << MemberName
@@ -1358,7 +1380,7 @@
   if (tryToRecoverWithCall(BaseExpr,
                            PDiag(diag::err_member_reference_needs_call),
                            /*complain*/ false,
-                           IsArrow ? &isRecordType : &isPointerToRecordType)) {
+                           IsArrow ? &isPointerToRecordType : &isRecordType)) {
     if (BaseExpr.isInvalid())
       return ExprError();
     BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take());
@@ -1551,6 +1573,7 @@
     SourceLocation Loc = R.getNameLoc();
     if (SS.getRange().isValid())
       Loc = SS.getRange().getBegin();
+    CheckCXXThisCapture(Loc);
     baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true);
   }
   

Modified: cfe/branches/tooling/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaExprObjC.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaExprObjC.cpp Fri Jan 20 10:14:22 2012
@@ -265,8 +265,7 @@
     if (captureIndex) break;
 
     bool nested = isa<BlockScopeInfo>(FunctionScopes[idx-1]);
-    blockScope->Captures.push_back(
-              BlockDecl::Capture(self, /*byref*/ false, nested, /*copy*/ 0));
+    blockScope->AddCapture(self, /*byref*/ false, nested, /*copy*/ 0);
     captureIndex = blockScope->Captures.size(); // +1
   }
 
@@ -454,14 +453,12 @@
                        Args[NumArgs-1]->getLocEnd());
     }
   }
-  // diagnose nonnull arguments.
-  for (specific_attr_iterator<NonNullAttr>
-       i = Method->specific_attr_begin<NonNullAttr>(),
-       e = Method->specific_attr_end<NonNullAttr>(); i != e; ++i) {
-    CheckNonNullArguments(*i, Args, lbrac);
-  }
 
   DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs);
+
+  // Do additional checkings on method.
+  IsError |= CheckObjCMethodCall(Method, lbrac, Args, NumArgs);
+
   return IsError;
 }
 
@@ -704,11 +701,12 @@
   }
 
   // Attempt to correct for typos in property names.
-  TypoCorrection Corrected = CorrectTypo(
+  DeclFilterCCC<ObjCPropertyDecl> Validator;
+  if (TypoCorrection Corrected = CorrectTypo(
       DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL,
-      NULL, IFace, false, CTC_NoKeywords, OPT);
-  if (ObjCPropertyDecl *Property =
-      Corrected.getCorrectionDeclAs<ObjCPropertyDecl>()) {
+      NULL, &Validator, IFace, false, OPT)) {
+    ObjCPropertyDecl *Property =
+        Corrected.getCorrectionDeclAs<ObjCPropertyDecl>();
     DeclarationName TypoResult = Corrected.getCorrection();
     Diag(MemberLoc, diag::err_property_not_found_suggest)
       << MemberName << QualType(OPT, 0) << TypoResult
@@ -848,6 +846,24 @@
                      << &propertyName << Context.getObjCInterfaceType(IFace));
 }
 
+namespace {
+
+class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback {
+ public:
+  ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) {
+    // Determine whether "super" is acceptable in the current context.
+    if (Method && Method->getClassInterface())
+      WantObjCSuper = Method->getClassInterface()->getSuperClass();
+  }
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() ||
+        candidate.isKeyword("super");
+  }
+};
+
+}
+
 Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
                                                IdentifierInfo *Name,
                                                SourceLocation NameLoc,
@@ -917,39 +933,32 @@
   }
   }
 
-  // Determine our typo-correction context.
-  CorrectTypoContext CTC = CTC_Expression;
-  if (ObjCMethodDecl *Method = getCurMethodDecl())
-    if (Method->getClassInterface() &&
-        Method->getClassInterface()->getSuperClass())
-      CTC = CTC_ObjCMessageReceiver;
-      
+  ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl());
   if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
                                              Result.getLookupKind(), S, NULL,
-                                             NULL, false, CTC)) {
-    if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
-      // If we found a declaration, correct when it refers to an Objective-C
-      // class.
-      if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) {
-        Diag(NameLoc, diag::err_unknown_receiver_suggest)
-          << Name << Corrected.getCorrection()
-          << FixItHint::CreateReplacement(SourceRange(NameLoc),
-                                          ND->getNameAsString());
-        Diag(ND->getLocation(), diag::note_previous_decl)
-          << Corrected.getCorrection();
-
-        QualType T = Context.getObjCInterfaceType(Class);
-        TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
-        ReceiverType = CreateParsedType(T, TSInfo);
-        return ObjCClassMessage;
-      }
-    } else if (Corrected.isKeyword() &&
-               Corrected.getCorrectionAsIdentifierInfo()->isStr("super")) {
-      // If we've found the keyword "super", this is a send to super.
+                                             &Validator)) {
+    if (Corrected.isKeyword()) {
+      // If we've found the keyword "super" (the only keyword that would be
+      // returned by CorrectTypo), this is a send to super.
       Diag(NameLoc, diag::err_unknown_receiver_suggest)
         << Name << Corrected.getCorrection()
         << FixItHint::CreateReplacement(SourceRange(NameLoc), "super");
       return ObjCSuperMessage;
+    } else if (ObjCInterfaceDecl *Class =
+               Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
+      // If we found a declaration, correct when it refers to an Objective-C
+      // class.
+      Diag(NameLoc, diag::err_unknown_receiver_suggest)
+        << Name << Corrected.getCorrection()
+        << FixItHint::CreateReplacement(SourceRange(NameLoc),
+                                        Class->getNameAsString());
+      Diag(Class->getLocation(), diag::note_previous_decl)
+        << Corrected.getCorrection();
+
+      QualType T = Context.getObjCInterfaceType(Class);
+      TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
+      ReceiverType = CreateParsedType(T, TSInfo);
+      return ObjCClassMessage;
     }
   }
   
@@ -1011,6 +1020,24 @@
                            LBracLoc, SelectorLocs, RBracLoc, move(Args));
 }
 
+
+ExprResult Sema::BuildClassMessageImplicit(QualType ReceiverType,
+                                           bool isSuperReceiver,
+                                           SourceLocation Loc,
+                                           Selector Sel,
+                                           ObjCMethodDecl *Method,
+                                           MultiExprArg Args) {
+  TypeSourceInfo *receiverTypeInfo = 0;
+  if (!ReceiverType.isNull())
+    receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType);
+
+  return BuildClassMessage(receiverTypeInfo, ReceiverType,
+                          /*SuperLoc=*/isSuperReceiver ? Loc : SourceLocation(),
+                           Sel, Method, Loc, Loc, Loc, Args,
+                           /*isImplicit=*/true);
+
+}
+
 /// \brief Build an Objective-C class message expression.
 ///
 /// This routine takes care of both normal class messages and
@@ -1047,7 +1074,8 @@
                                    SourceLocation LBracLoc, 
                                    ArrayRef<SourceLocation> SelectorLocs,
                                    SourceLocation RBracLoc,
-                                   MultiExprArg ArgsIn) {
+                                   MultiExprArg ArgsIn,
+                                   bool isImplicit) {
   SourceLocation Loc = SuperLoc.isValid()? SuperLoc
     : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin();
   if (LBracLoc.isInvalid()) {
@@ -1065,7 +1093,8 @@
     return Owned(ObjCMessageExpr::Create(Context, ReceiverType,
                                          VK_RValue, LBracLoc, ReceiverTypeInfo,
                                          Sel, SelectorLocs, /*Method=*/0,
-                                         makeArrayRef(Args, NumArgs),RBracLoc));
+                                         makeArrayRef(Args, NumArgs),RBracLoc,
+                                         isImplicit));
   }
   
   // Find the class to which we are sending this message.
@@ -1131,12 +1160,12 @@
                                      SuperLoc, /*IsInstanceSuper=*/false, 
                                      ReceiverType, Sel, SelectorLocs,
                                      Method, makeArrayRef(Args, NumArgs),
-                                     RBracLoc);
+                                     RBracLoc, isImplicit);
   else
     Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, 
                                      ReceiverTypeInfo, Sel, SelectorLocs,
                                      Method, makeArrayRef(Args, NumArgs),
-                                     RBracLoc);
+                                     RBracLoc, isImplicit);
   return MaybeBindToTemporary(Result);
 }
 
@@ -1164,6 +1193,18 @@
                            LBracLoc, SelectorLocs, RBracLoc, move(Args));
 }
 
+ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver,
+                                              QualType ReceiverType,
+                                              SourceLocation Loc,
+                                              Selector Sel,
+                                              ObjCMethodDecl *Method,
+                                              MultiExprArg Args) {
+  return BuildInstanceMessage(Receiver, ReceiverType,
+                              /*SuperLoc=*/!Receiver ? Loc : SourceLocation(),
+                              Sel, Method, Loc, Loc, Loc, Args,
+                              /*isImplicit=*/true);
+}
+
 /// \brief Build an Objective-C instance message expression.
 ///
 /// This routine takes care of both normal instance messages and
@@ -1200,7 +1241,8 @@
                                       SourceLocation LBracLoc, 
                                       ArrayRef<SourceLocation> SelectorLocs,
                                       SourceLocation RBracLoc,
-                                      MultiExprArg ArgsIn) {
+                                      MultiExprArg ArgsIn,
+                                      bool isImplicit) {
   // The location of the receiver.
   SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
   
@@ -1233,7 +1275,7 @@
                                            VK_RValue, LBracLoc, Receiver, Sel, 
                                            SelectorLocs, /*Method=*/0,
                                            makeArrayRef(Args, NumArgs),
-                                           RBracLoc));
+                                           RBracLoc, isImplicit));
     }
 
     // If necessary, apply function/array conversion to the receiver.
@@ -1523,11 +1565,13 @@
     Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
                                      SuperLoc,  /*IsInstanceSuper=*/true,
                                      ReceiverType, Sel, SelectorLocs, Method, 
-                                     makeArrayRef(Args, NumArgs), RBracLoc);
+                                     makeArrayRef(Args, NumArgs), RBracLoc,
+                                     isImplicit);
   else
     Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
                                      Receiver, Sel, SelectorLocs, Method,
-                                     makeArrayRef(Args, NumArgs), RBracLoc);
+                                     makeArrayRef(Args, NumArgs), RBracLoc,
+                                     isImplicit);
 
   if (getLangOptions().ObjCAutoRefCount) {
     // In ARC, annotate delegate init calls.

Modified: cfe/branches/tooling/lib/Sema/SemaFixItUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaFixItUtils.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaFixItUtils.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaFixItUtils.cpp Fri Jan 20 10:14:22 2012
@@ -158,3 +158,39 @@
 
   return false;
 }
+
+static bool isMacroDefined(const Sema &S, StringRef Name) {
+  return S.PP.getMacroInfo(&S.getASTContext().Idents.get(Name));
+}
+
+const char *Sema::getFixItZeroInitializerForType(QualType T) const {
+  if (T->isScalarType()) {
+    // Suggest " = 0" for non-enumeration scalar types, unless we can find a
+    // better initializer.
+    if (T->isEnumeralType())
+      return 0;
+    if ((T->isObjCObjectPointerType() || T->isBlockPointerType()) &&
+        isMacroDefined(*this, "nil"))
+      return " = nil";
+    if (T->isRealFloatingType())
+      return " = 0.0";
+    if (T->isBooleanType() && LangOpts.CPlusPlus)
+      return " = false";
+    if (T->isPointerType() || T->isMemberPointerType()) {
+      if (LangOpts.CPlusPlus0x)
+        return " = nullptr";
+      else if (isMacroDefined(*this, "NULL"))
+        return " = NULL";
+    }
+    return " = 0";
+  }
+
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  if (!RD || !RD->hasDefinition())
+    return 0;
+  if (LangOpts.CPlusPlus0x && !RD->hasUserProvidedDefaultConstructor())
+    return "{}";
+  if (RD->isAggregate())
+    return " = {}";
+  return 0;
+}

Modified: cfe/branches/tooling/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaInit.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaInit.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaInit.cpp Fri Jan 20 10:14:22 2012
@@ -21,6 +21,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/TypeLoc.h"
+#include "llvm/ADT/APInt.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 #include <map>
@@ -171,9 +172,6 @@
   bool hadError;
   bool VerifyOnly; // no diagnostics, no structure building
   bool AllowBraceElision;
-  Expr *LastCheckedSubobject;
-  unsigned LastCheckedSubobjectIndex;
-  
   std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
   InitListExpr *FullyStructuredList;
 
@@ -473,8 +471,7 @@
 InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
                                  InitListExpr *IL, QualType &T,
                                  bool VerifyOnly, bool AllowBraceElision)
-  : SemaRef(S), VerifyOnly(VerifyOnly), AllowBraceElision(AllowBraceElision),
-    LastCheckedSubobject(0), LastCheckedSubobjectIndex(0) {
+  : SemaRef(S), VerifyOnly(VerifyOnly), AllowBraceElision(AllowBraceElision) {
   hadError = false;
 
   unsigned newIndex = 0;
@@ -796,40 +793,13 @@
 
     if (Seq) {
       if (!VerifyOnly) {
-        // struct S {
-        //   S(int);
-        // };
-        //
-        // S s[] = { [0 ... 2] = 3 };
-        //
-        // In code like this, we want to perform the initialization and then
-        // update the syntactic list with the result. However, we reach this
-        // point once for each subobject, but the update needs
-        // to be done only once for each syntactic element. For this reason,
-        // the initialization result and its syntactic Index are cached in
-        // LastCheckedSubobject and LastCheckedSubobjectIndex and reused until
-        // we move to the next Index.
-        Expr *ResultExpr = LastCheckedSubobject;
-        
-        if (!ResultExpr || Index != LastCheckedSubobjectIndex) {
-          ExprResult Result = Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
-
-          if (Result.isInvalid()) {
-            hadError = true;
-            ResultExpr = 0;
-          } else {
-            ResultExpr = Result.takeAs<Expr>();
-          }
-          
-          LastCheckedSubobject = ResultExpr;
-          LastCheckedSubobjectIndex = Index;
-        }
-
-        // Update the syntactic list
-        IList->setInit(Index, ResultExpr);
+        ExprResult Result =
+          Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
+        if (Result.isInvalid())
+          hadError = true;
 
         UpdateStructuredListElement(StructuredList, StructuredIndex,
-                                    ResultExpr);
+                                    Result.takeAs<Expr>());
       }
       ++Index;
       return;
@@ -1560,6 +1530,26 @@
                                     DIE->usesGNUSyntax(), DIE->getInit());
 }
 
+namespace {
+
+// Callback to only accept typo corrections that are for field members of
+// the given struct or union.
+class FieldInitializerValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  explicit FieldInitializerValidatorCCC(RecordDecl *RD)
+      : Record(RD) {}
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>();
+    return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record);
+  }
+
+ private:
+  RecordDecl *Record;
+};
+
+}
+
 /// @brief Check the well-formedness of a C99 designated initializer.
 ///
 /// Determines whether the designated initializer @p DIE, which
@@ -1718,19 +1708,17 @@
       if (Lookup.first == Lookup.second) {
         // Name lookup didn't find anything. Determine whether this
         // was a typo for another field name.
-        LookupResult R(SemaRef, FieldName, D->getFieldLoc(),
-                       Sema::LookupMemberName);
+        FieldInitializerValidatorCCC Validator(RT->getDecl());
         TypoCorrection Corrected = SemaRef.CorrectTypo(
             DeclarationNameInfo(FieldName, D->getFieldLoc()),
-            Sema::LookupMemberName, /*Scope=*/NULL, /*SS=*/NULL,
-            RT->getDecl(), false, Sema::CTC_NoKeywords);
-        if ((ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>()) &&
-            ReplacementField->getDeclContext()->getRedeclContext()
-                                                      ->Equals(RT->getDecl())) {
+            Sema::LookupMemberName, /*Scope=*/0, /*SS=*/0, &Validator,
+            RT->getDecl());
+        if (Corrected) {
           std::string CorrectedStr(
               Corrected.getAsString(SemaRef.getLangOptions()));
           std::string CorrectedQuotedStr(
               Corrected.getQuoted(SemaRef.getLangOptions()));
+          ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>();
           SemaRef.Diag(D->getFieldLoc(),
                        diag::err_field_designator_unknown_suggest)
             << FieldName << CurrentObjectType << CorrectedQuotedStr
@@ -2273,10 +2261,7 @@
                                  InitExpressions.data(), InitExpressions.size(),
                                  Loc, GNUSyntax, Init.takeAs<Expr>());
 
-  if (getLangOptions().CPlusPlus)
-    Diag(DIE->getLocStart(), diag::ext_designated_init_cxx)
-      << DIE->getSourceRange();
-  else if (!getLangOptions().C99)
+  if (!getLangOptions().C99)
     Diag(DIE->getLocStart(), diag::ext_designated_init)
       << DIE->getSourceRange();
 
@@ -2343,8 +2328,7 @@
     return DeclarationName();
   }
 
-  // Silence GCC warning
-  return DeclarationName();
+  llvm_unreachable("Invalid EntityKind!");
 }
 
 DeclaratorDecl *InitializedEntity::getDecl() const {
@@ -2369,8 +2353,7 @@
     return 0;
   }
 
-  // Silence GCC warning
-  return 0;
+  llvm_unreachable("Invalid EntityKind!");
 }
 
 bool InitializedEntity::allowsNRVO() const {
@@ -2426,6 +2409,7 @@
   case SK_PassByIndirectCopyRestore:
   case SK_PassByIndirectRestore:
   case SK_ProduceObjCObject:
+  case SK_StdInitializerList:
     break;
 
   case SK_ConversionSequence:
@@ -2461,180 +2445,25 @@
   case FK_ArrayTypeMismatch:
   case FK_NonConstantArrayInit:
   case FK_ListInitializationFailed:
+  case FK_VariableLengthArrayHasInitializer:
   case FK_PlaceholderType:
+  case FK_InitListElementCopyFailure:
     return false;
 
   case FK_ReferenceInitOverloadFailed:
   case FK_UserConversionOverloadFailed:
   case FK_ConstructorOverloadFailed:
+  case FK_ListConstructorOverloadFailed:
     return FailedOverloadResult == OR_Ambiguous;
   }
 
-  return false;
+  llvm_unreachable("Invalid EntityKind!");
 }
 
 bool InitializationSequence::isConstructorInitialization() const {
   return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization;
 }
 
-bool InitializationSequence::endsWithNarrowing(ASTContext &Ctx,
-                                               const Expr *Initializer,
-                                               bool *isInitializerConstant,
-                                               APValue *ConstantValue) const {
-  if (Steps.empty() || Initializer->isValueDependent())
-    return false;
-
-  const Step &LastStep = Steps.back();
-  if (LastStep.Kind != SK_ConversionSequence)
-    return false;
-
-  const ImplicitConversionSequence &ICS = *LastStep.ICS;
-  const StandardConversionSequence *SCS = NULL;
-  switch (ICS.getKind()) {
-  case ImplicitConversionSequence::StandardConversion:
-    SCS = &ICS.Standard;
-    break;
-  case ImplicitConversionSequence::UserDefinedConversion:
-    SCS = &ICS.UserDefined.After;
-    break;
-  case ImplicitConversionSequence::AmbiguousConversion:
-  case ImplicitConversionSequence::EllipsisConversion:
-  case ImplicitConversionSequence::BadConversion:
-    return false;
-  }
-
-  // Check if SCS represents a narrowing conversion, according to C++0x
-  // [dcl.init.list]p7:
-  //
-  // A narrowing conversion is an implicit conversion ...
-  ImplicitConversionKind PossibleNarrowing = SCS->Second;
-  QualType FromType = SCS->getToType(0);
-  QualType ToType = SCS->getToType(1);
-  switch (PossibleNarrowing) {
-  // * from a floating-point type to an integer type, or
-  //
-  // * from an integer type or unscoped enumeration type to a floating-point
-  //   type, except where the source is a constant expression and the actual
-  //   value after conversion will fit into the target type and will produce
-  //   the original value when converted back to the original type, or
-  case ICK_Floating_Integral:
-    if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) {
-      *isInitializerConstant = false;
-      return true;
-    } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) {
-      llvm::APSInt IntConstantValue;
-      if (Initializer &&
-          Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) {
-        // Convert the integer to the floating type.
-        llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType));
-        Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(),
-                                llvm::APFloat::rmNearestTiesToEven);
-        // And back.
-        llvm::APSInt ConvertedValue = IntConstantValue;
-        bool ignored;
-        Result.convertToInteger(ConvertedValue,
-                                llvm::APFloat::rmTowardZero, &ignored);
-        // If the resulting value is different, this was a narrowing conversion.
-        if (IntConstantValue != ConvertedValue) {
-          *isInitializerConstant = true;
-          *ConstantValue = APValue(IntConstantValue);
-          return true;
-        }
-      } else {
-        // Variables are always narrowings.
-        *isInitializerConstant = false;
-        return true;
-      }
-    }
-    return false;
-
-  // * from long double to double or float, or from double to float, except
-  //   where the source is a constant expression and the actual value after
-  //   conversion is within the range of values that can be represented (even
-  //   if it cannot be represented exactly), or
-  case ICK_Floating_Conversion:
-    if (1 == Ctx.getFloatingTypeOrder(FromType, ToType)) {
-      // FromType is larger than ToType.
-      Expr::EvalResult InitializerValue;
-      // FIXME: Check whether Initializer is a constant expression according
-      // to C++0x [expr.const], rather than just whether it can be folded.
-      if (Initializer->EvaluateAsRValue(InitializerValue, Ctx) &&
-          !InitializerValue.HasSideEffects && InitializerValue.Val.isFloat()) {
-        // Constant! (Except for FIXME above.)
-        llvm::APFloat FloatVal = InitializerValue.Val.getFloat();
-        // Convert the source value into the target type.
-        bool ignored;
-        llvm::APFloat::opStatus ConvertStatus = FloatVal.convert(
-          Ctx.getFloatTypeSemantics(ToType),
-          llvm::APFloat::rmNearestTiesToEven, &ignored);
-        // If there was no overflow, the source value is within the range of
-        // values that can be represented.
-        if (ConvertStatus & llvm::APFloat::opOverflow) {
-          *isInitializerConstant = true;
-          *ConstantValue = InitializerValue.Val;
-          return true;
-        }
-      } else {
-        *isInitializerConstant = false;
-        return true;
-      }
-    }
-    return false;
-
-  // * from an integer type or unscoped enumeration type to an integer type
-  //   that cannot represent all the values of the original type, except where
-  //   the source is a constant expression and the actual value after
-  //   conversion will fit into the target type and will produce the original
-  //   value when converted back to the original type.
-  case ICK_Boolean_Conversion:  // Bools are integers too.
-    if (!FromType->isIntegralOrUnscopedEnumerationType()) {
-      // Boolean conversions can be from pointers and pointers to members
-      // [conv.bool], and those aren't considered narrowing conversions.
-      return false;
-    }  // Otherwise, fall through to the integral case.
-  case ICK_Integral_Conversion: {
-    assert(FromType->isIntegralOrUnscopedEnumerationType());
-    assert(ToType->isIntegralOrUnscopedEnumerationType());
-    const bool FromSigned = FromType->isSignedIntegerOrEnumerationType();
-    const unsigned FromWidth = Ctx.getIntWidth(FromType);
-    const bool ToSigned = ToType->isSignedIntegerOrEnumerationType();
-    const unsigned ToWidth = Ctx.getIntWidth(ToType);
-
-    if (FromWidth > ToWidth ||
-        (FromWidth == ToWidth && FromSigned != ToSigned)) {
-      // Not all values of FromType can be represented in ToType.
-      llvm::APSInt InitializerValue;
-      if (Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) {
-        *isInitializerConstant = true;
-        *ConstantValue = APValue(InitializerValue);
-
-        // Add a bit to the InitializerValue so we don't have to worry about
-        // signed vs. unsigned comparisons.
-        InitializerValue = InitializerValue.extend(
-          InitializerValue.getBitWidth() + 1);
-        // Convert the initializer to and from the target width and signed-ness.
-        llvm::APSInt ConvertedValue = InitializerValue;
-        ConvertedValue = ConvertedValue.trunc(ToWidth);
-        ConvertedValue.setIsSigned(ToSigned);
-        ConvertedValue = ConvertedValue.extend(InitializerValue.getBitWidth());
-        ConvertedValue.setIsSigned(InitializerValue.isSigned());
-        // If the result is different, this was a narrowing conversion.
-        return ConvertedValue != InitializerValue;
-      } else {
-        // Variables are always narrowings.
-        *isInitializerConstant = false;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  default:
-    // Other kinds of conversions are not narrowings.
-    return false;
-  }
-}
-
 void
 InitializationSequence
 ::AddAddressOverloadResolutionStep(FunctionDecl *Function,
@@ -2656,7 +2485,6 @@
   case VK_RValue: S.Kind = SK_CastDerivedToBaseRValue; break;
   case VK_XValue: S.Kind = SK_CastDerivedToBaseXValue; break;
   case VK_LValue: S.Kind = SK_CastDerivedToBaseLValue; break;
-  default: llvm_unreachable("No such category");
   }
   S.Type = BaseType;
   Steps.push_back(S);
@@ -2732,9 +2560,10 @@
 ::AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
                                    AccessSpecifier Access,
                                    QualType T,
-                                   bool HadMultipleCandidates) {
+                                   bool HadMultipleCandidates,
+                                   bool FromInitList) {
   Step S;
-  S.Kind = SK_ConstructorInitialization;
+  S.Kind = FromInitList ? SK_ListConstructorCall : SK_ConstructorInitialization;
   S.Type = T;
   S.Function.HadMultipleCandidates = HadMultipleCandidates;
   S.Function.Function = Constructor;
@@ -2793,6 +2622,13 @@
   Steps.push_back(S);
 }
 
+void InitializationSequence::AddStdInitializerListConstructionStep(QualType T) {
+  Step S;
+  S.Kind = SK_StdInitializerList;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
 void InitializationSequence::RewrapReferenceInitList(QualType T,
                                                      InitListExpr *Syntactic) {
   assert(Syntactic->getNumInits() == 1 &&
@@ -2846,6 +2682,200 @@
   }
 }
 
+/// \brief When initializing from init list via constructor, deal with the
+/// empty init list and std::initializer_list special cases.
+///
+/// \return True if this was a special case, false otherwise.
+static bool TryListConstructionSpecialCases(Sema &S,
+                                            Expr **Args, unsigned NumArgs,
+                                            CXXRecordDecl *DestRecordDecl,
+                                            QualType DestType,
+                                            InitializationSequence &Sequence) {
+  // C++11 [dcl.init.list]p3:
+  //   List-initialization of an object of type T is defined as follows:
+  //   - If the initializer list has no elements and T is a class type with
+  //     a default constructor, the object is value-initialized.
+  if (NumArgs == 0) {
+    if (CXXConstructorDecl *DefaultConstructor =
+            S.LookupDefaultConstructor(DestRecordDecl)) {
+      if (DefaultConstructor->isDeleted() ||
+          S.isFunctionConsideredUnavailable(DefaultConstructor)) {
+        // Fake an overload resolution failure.
+        OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+        DeclAccessPair FoundDecl = DeclAccessPair::make(DefaultConstructor,
+                                              DefaultConstructor->getAccess());
+        if (FunctionTemplateDecl *ConstructorTmpl =
+                dyn_cast<FunctionTemplateDecl>(DefaultConstructor))
+          S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+                                         /*ExplicitArgs*/ 0,
+                                         Args, NumArgs, CandidateSet,
+                                         /*SuppressUserConversions*/ false);
+        else
+          S.AddOverloadCandidate(DefaultConstructor, FoundDecl,
+                                 Args, NumArgs, CandidateSet,
+                                 /*SuppressUserConversions*/ false);
+        Sequence.SetOverloadFailure(
+                       InitializationSequence::FK_ListConstructorOverloadFailed,
+                       OR_Deleted);
+      } else
+        Sequence.AddConstructorInitializationStep(DefaultConstructor,
+                                                DefaultConstructor->getAccess(),
+                                                  DestType,
+                                                  /*MultipleCandidates=*/false,
+                                                  /*FromInitList=*/true);
+      return true;
+    }
+  }
+
+  //   - Otherwise, if T is a specialization of std::initializer_list, [...]
+  QualType E;
+  if (S.isStdInitializerList(DestType, &E)) {
+    // Check that each individual element can be copy-constructed. But since we
+    // have no place to store further information, we'll recalculate everything
+    // later.
+    InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
+        S.Context.getConstantArrayType(E,
+            llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),NumArgs),
+            ArrayType::Normal, 0));
+    InitializedEntity Element = InitializedEntity::InitializeElement(S.Context,
+        0, HiddenArray);
+    for (unsigned i = 0; i < NumArgs; ++i) {
+      Element.setElementIndex(i);
+      if (!S.CanPerformCopyInitialization(Element, Args[i])) {
+        Sequence.SetFailed(
+            InitializationSequence::FK_InitListElementCopyFailure);
+        return true;
+      }
+    }
+    Sequence.AddStdInitializerListConstructionStep(DestType);
+    return true;
+  }
+
+  // Not a special case.
+  return false;
+}
+
+/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
+/// enumerates the constructors of the initialized entity and performs overload
+/// resolution to select the best.
+/// If FromInitList is true, this is list-initialization of a non-aggregate
+/// class type.
+static void TryConstructorInitialization(Sema &S,
+                                         const InitializedEntity &Entity,
+                                         const InitializationKind &Kind,
+                                         Expr **Args, unsigned NumArgs,
+                                         QualType DestType,
+                                         InitializationSequence &Sequence,
+                                         bool FromInitList = false) {
+  // Check constructor arguments for self reference.
+  if (DeclaratorDecl *DD = Entity.getDecl())
+    // Parameters arguments are occassionially constructed with itself,
+    // for instance, in recursive functions.  Skip them.
+    if (!isa<ParmVarDecl>(DD))
+      for (unsigned i = 0; i < NumArgs; ++i)
+        S.CheckSelfReference(DD, Args[i]);
+
+  // Build the candidate set directly in the initialization sequence
+  // structure, so that it will persist if we fail.
+  OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+  CandidateSet.clear();
+
+  // Determine whether we are allowed to call explicit constructors or
+  // explicit conversion operators.
+  bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
+                        Kind.getKind() == InitializationKind::IK_Value ||
+                        Kind.getKind() == InitializationKind::IK_Default);
+
+  // The type we're constructing needs to be complete.
+  if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
+    Sequence.SetFailed(InitializationSequence::FK_Incomplete);
+  }
+
+  const RecordType *DestRecordType = DestType->getAs<RecordType>();
+  assert(DestRecordType && "Constructor initialization requires record type");
+  CXXRecordDecl *DestRecordDecl
+    = cast<CXXRecordDecl>(DestRecordType->getDecl());
+
+  if (FromInitList &&
+      TryListConstructionSpecialCases(S, Args, NumArgs, DestRecordDecl,
+                                      DestType, Sequence))
+    return;
+
+  //   - Otherwise, if T is a class type, constructors are considered. The
+  //     applicable constructors are enumerated, and the best one is chosen
+  //     through overload resolution.
+  DeclContext::lookup_iterator Con, ConEnd;
+  for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
+       Con != ConEnd; ++Con) {
+    NamedDecl *D = *Con;
+    DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+    bool SuppressUserConversions = false;
+
+    // Find the constructor (which may be a template).
+    CXXConstructorDecl *Constructor = 0;
+    FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
+    if (ConstructorTmpl)
+      Constructor = cast<CXXConstructorDecl>(
+                                           ConstructorTmpl->getTemplatedDecl());
+    else {
+      Constructor = cast<CXXConstructorDecl>(D);
+
+      // If we're performing copy initialization using a copy constructor, we
+      // suppress user-defined conversions on the arguments.
+      // FIXME: Move constructors?
+      if (Kind.getKind() == InitializationKind::IK_Copy &&
+          Constructor->isCopyConstructor())
+        SuppressUserConversions = true;
+    }
+
+    if (!Constructor->isInvalidDecl() &&
+        (AllowExplicit || !Constructor->isExplicit())) {
+      if (ConstructorTmpl)
+        S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+                                       /*ExplicitArgs*/ 0,
+                                       Args, NumArgs, CandidateSet,
+                                       SuppressUserConversions);
+      else
+        S.AddOverloadCandidate(Constructor, FoundDecl,
+                               Args, NumArgs, CandidateSet,
+                               SuppressUserConversions);
+    }
+  }
+
+  SourceLocation DeclLoc = Kind.getLocation();
+
+  // Perform overload resolution. If it fails, return the failed result.
+  OverloadCandidateSet::iterator Best;
+  if (OverloadingResult Result
+        = CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
+    Sequence.SetOverloadFailure(FromInitList ?
+                      InitializationSequence::FK_ListConstructorOverloadFailed :
+                      InitializationSequence::FK_ConstructorOverloadFailed,
+                                Result);
+    return;
+  }
+
+  // C++0x [dcl.init]p6:
+  //   If a program calls for the default initialization of an object
+  //   of a const-qualified type T, T shall be a class type with a
+  //   user-provided default constructor.
+  if (Kind.getKind() == InitializationKind::IK_Default &&
+      Entity.getType().isConstQualified() &&
+      cast<CXXConstructorDecl>(Best->Function)->isImplicit()) {
+    Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+    return;
+  }
+
+  // Add the constructor initialization step. Any cv-qualification conversion is
+  // subsumed by the initialization.
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+  CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
+  Sequence.AddConstructorInitializationStep(CtorDecl,
+                                            Best->FoundDecl.getAccess(),
+                                            DestType, HadMultipleCandidates,
+                                            FromInitList);
+}
+
 static bool
 ResolveOverloadedFunctionForReferenceBinding(Sema &S,
                                              Expr *Initializer,
@@ -2973,9 +3003,13 @@
     TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence);
     return;
   }
-  // FIXME: C++11 defines behavior for this case.
   if (DestType->isRecordType() && !DestType->isAggregateType()) {
-    Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
+    if (S.getLangOptions().CPlusPlus0x)
+      TryConstructorInitialization(S, Entity, Kind, InitList->getInits(),
+                                   InitList->getNumInits(), DestType, Sequence,
+                                   /*FromInitList=*/true);
+    else
+      Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
     return;
   }
 
@@ -3451,117 +3485,6 @@
   Sequence.AddStringInitStep(Entity.getType());
 }
 
-/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
-/// enumerates the constructors of the initialized entity and performs overload
-/// resolution to select the best.
-static void TryConstructorInitialization(Sema &S,
-                                         const InitializedEntity &Entity,
-                                         const InitializationKind &Kind,
-                                         Expr **Args, unsigned NumArgs,
-                                         QualType DestType,
-                                         InitializationSequence &Sequence) {
-  // Check constructor arguments for self reference.
-  if (DeclaratorDecl *DD = Entity.getDecl())
-    // Parameters arguments are occassionially constructed with itself,
-    // for instance, in recursive functions.  Skip them.
-    if (!isa<ParmVarDecl>(DD))
-      for (unsigned i = 0; i < NumArgs; ++i)
-        S.CheckSelfReference(DD, Args[i]);
-
-  // Build the candidate set directly in the initialization sequence
-  // structure, so that it will persist if we fail.
-  OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
-  CandidateSet.clear();
-
-  // Determine whether we are allowed to call explicit constructors or
-  // explicit conversion operators.
-  bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
-                        Kind.getKind() == InitializationKind::IK_Value ||
-                        Kind.getKind() == InitializationKind::IK_Default);
-
-  // The type we're constructing needs to be complete.
-  if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
-    Sequence.SetFailed(InitializationSequence::FK_Incomplete);
-    return;
-  }
-
-  // The type we're converting to is a class type. Enumerate its constructors
-  // to see if one is suitable.
-  const RecordType *DestRecordType = DestType->getAs<RecordType>();
-  assert(DestRecordType && "Constructor initialization requires record type");
-  CXXRecordDecl *DestRecordDecl
-    = cast<CXXRecordDecl>(DestRecordType->getDecl());
-
-  DeclContext::lookup_iterator Con, ConEnd;
-  for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
-       Con != ConEnd; ++Con) {
-    NamedDecl *D = *Con;
-    DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
-    bool SuppressUserConversions = false;
-
-    // Find the constructor (which may be a template).
-    CXXConstructorDecl *Constructor = 0;
-    FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
-    if (ConstructorTmpl)
-      Constructor = cast<CXXConstructorDecl>(
-                                           ConstructorTmpl->getTemplatedDecl());
-    else {
-      Constructor = cast<CXXConstructorDecl>(D);
-
-      // If we're performing copy initialization using a copy constructor, we
-      // suppress user-defined conversions on the arguments.
-      // FIXME: Move constructors?
-      if (Kind.getKind() == InitializationKind::IK_Copy &&
-          Constructor->isCopyConstructor())
-        SuppressUserConversions = true;
-    }
-
-    if (!Constructor->isInvalidDecl() &&
-        (AllowExplicit || !Constructor->isExplicit())) {
-      if (ConstructorTmpl)
-        S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
-                                       /*ExplicitArgs*/ 0,
-                                       Args, NumArgs, CandidateSet,
-                                       SuppressUserConversions);
-      else
-        S.AddOverloadCandidate(Constructor, FoundDecl,
-                               Args, NumArgs, CandidateSet,
-                               SuppressUserConversions);
-    }
-  }
-
-  SourceLocation DeclLoc = Kind.getLocation();
-
-  // Perform overload resolution. If it fails, return the failed result.
-  OverloadCandidateSet::iterator Best;
-  if (OverloadingResult Result
-        = CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
-    Sequence.SetOverloadFailure(
-                          InitializationSequence::FK_ConstructorOverloadFailed,
-                                Result);
-    return;
-  }
-
-  // C++0x [dcl.init]p6:
-  //   If a program calls for the default initialization of an object
-  //   of a const-qualified type T, T shall be a class type with a
-  //   user-provided default constructor.
-  if (Kind.getKind() == InitializationKind::IK_Default &&
-      Entity.getType().isConstQualified() &&
-      cast<CXXConstructorDecl>(Best->Function)->isImplicit()) {
-    Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
-    return;
-  }
-
-  // Add the constructor initialization step. Any cv-qualification conversion is
-  // subsumed by the initialization.
-  bool HadMultipleCandidates = (CandidateSet.size() > 1);
-  CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
-  Sequence.AddConstructorInitializationStep(CtorDecl,
-                                            Best->FoundDecl.getAccess(),
-                                            DestType, HadMultipleCandidates);
-}
-
 /// \brief Attempt value initialization (C++ [dcl.init]p7).
 static void TryValueInitialization(Sema &S,
                                    const InitializedEntity &Entity,
@@ -4026,6 +3949,11 @@
   //     - Otherwise, if the destination type is an array, the program is
   //       ill-formed.
   if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) {
+    if (Initializer && isa<VariableArrayType>(DestAT)) {
+      SetFailed(FK_VariableLengthArrayHasInitializer);
+      return;
+    }
+
     if (Initializer && IsStringInit(Initializer, DestAT, Context)) {
       TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
       return;
@@ -4206,7 +4134,7 @@
     return Sema::AA_Initializing;
   }
 
-  return Sema::AA_Converting;
+  llvm_unreachable("Invalid EntityKind!");
 }
 
 /// \brief Whether we should binding a created object as a temporary when
@@ -4557,6 +4485,117 @@
          s.Kind == InitializationSequence::SK_BindReferenceToTemporary;
 }
 
+static ExprResult
+PerformConstructorInitialization(Sema &S,
+                                 const InitializedEntity &Entity,
+                                 const InitializationKind &Kind,
+                                 MultiExprArg Args,
+                                 const InitializationSequence::Step& Step,
+                                 bool &ConstructorInitRequiresZeroInit) {
+  unsigned NumArgs = Args.size();
+  CXXConstructorDecl *Constructor
+    = cast<CXXConstructorDecl>(Step.Function.Function);
+  bool HadMultipleCandidates = Step.Function.HadMultipleCandidates;
+
+  // Build a call to the selected constructor.
+  ASTOwningVector<Expr*> ConstructorArgs(S);
+  SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid())
+                         ? Kind.getEqualLoc()
+                         : Kind.getLocation();
+
+  if (Kind.getKind() == InitializationKind::IK_Default) {
+    // Force even a trivial, implicit default constructor to be
+    // semantically checked. We do this explicitly because we don't build
+    // the definition for completely trivial constructors.
+    CXXRecordDecl *ClassDecl = Constructor->getParent();
+    assert(ClassDecl && "No parent class for constructor.");
+    if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() &&
+        ClassDecl->hasTrivialDefaultConstructor() &&
+        !Constructor->isUsed(false))
+      S.DefineImplicitDefaultConstructor(Loc, Constructor);
+  }
+
+  ExprResult CurInit = S.Owned((Expr *)0);
+
+  // Determine the arguments required to actually perform the constructor
+  // call.
+  if (S.CompleteConstructorCall(Constructor, move(Args),
+                                Loc, ConstructorArgs))
+    return ExprError();
+
+
+  if (Entity.getKind() == InitializedEntity::EK_Temporary &&
+      NumArgs != 1 && // FIXME: Hack to work around cast weirdness
+      (Kind.getKind() == InitializationKind::IK_Direct ||
+       Kind.getKind() == InitializationKind::IK_Value)) {
+    // An explicitly-constructed temporary, e.g., X(1, 2).
+    unsigned NumExprs = ConstructorArgs.size();
+    Expr **Exprs = (Expr **)ConstructorArgs.take();
+    S.MarkDeclarationReferenced(Loc, Constructor);
+    S.DiagnoseUseOfDecl(Constructor, Loc);
+
+    TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
+    if (!TSInfo)
+      TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
+
+    CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context,
+                                                             Constructor,
+                                                             TSInfo,
+                                                             Exprs,
+                                                             NumExprs,
+                                                     Kind.getParenRange(),
+                                                     HadMultipleCandidates,
+                                         ConstructorInitRequiresZeroInit));
+  } else {
+    CXXConstructExpr::ConstructionKind ConstructKind =
+      CXXConstructExpr::CK_Complete;
+
+    if (Entity.getKind() == InitializedEntity::EK_Base) {
+      ConstructKind = Entity.getBaseSpecifier()->isVirtual() ?
+        CXXConstructExpr::CK_VirtualBase :
+        CXXConstructExpr::CK_NonVirtualBase;
+    } else if (Entity.getKind() == InitializedEntity::EK_Delegating) {
+      ConstructKind = CXXConstructExpr::CK_Delegating;
+    }
+
+    // Only get the parenthesis range if it is a direct construction.
+    SourceRange parenRange =
+        Kind.getKind() == InitializationKind::IK_Direct ?
+        Kind.getParenRange() : SourceRange();
+
+    // If the entity allows NRVO, mark the construction as elidable
+    // unconditionally.
+    if (Entity.allowsNRVO())
+      CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+                                        Constructor, /*Elidable=*/true,
+                                        move_arg(ConstructorArgs),
+                                        HadMultipleCandidates,
+                                        ConstructorInitRequiresZeroInit,
+                                        ConstructKind,
+                                        parenRange);
+    else
+      CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+                                        Constructor,
+                                        move_arg(ConstructorArgs),
+                                        HadMultipleCandidates,
+                                        ConstructorInitRequiresZeroInit,
+                                        ConstructKind,
+                                        parenRange);
+  }
+  if (CurInit.isInvalid())
+    return ExprError();
+
+  // Only check access if all of that succeeded.
+  S.CheckConstructorAccess(Loc, Constructor, Entity,
+                           Step.Function.FoundDecl.getAccess());
+  S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc);
+
+  if (shouldBindAsTemporary(Entity))
+    CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+
+  return move(CurInit);
+}
+
 ExprResult
 InitializationSequence::Perform(Sema &S,
                                 const InitializedEntity &Entity,
@@ -4653,7 +4692,8 @@
   case SK_ArrayInit:
   case SK_PassByIndirectCopyRestore:
   case SK_PassByIndirectRestore:
-  case SK_ProduceObjCObject: {
+  case SK_ProduceObjCObject:
+  case SK_StdInitializerList: {
     assert(Args.size() == 1);
     CurInit = Args.get()[0];
     if (!CurInit.get()) return ExprError();
@@ -4941,8 +4981,14 @@
       break;
     }
 
-    case SK_ListConstructorCall:
-      assert(false && "List constructor calls not yet supported.");
+    case SK_ListConstructorCall: {
+      InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
+      MultiExprArg Arg(InitList->getInits(), InitList->getNumInits());
+      CurInit = PerformConstructorInitialization(S, Entity, Kind,
+                                                 move(Arg), *Step,
+                                               ConstructorInitRequiresZeroInit);
+      break;
+    }
 
     case SK_UnwrapInitList:
       CurInit = S.Owned(cast<InitListExpr>(CurInit.take())->getInit(0));
@@ -4960,108 +5006,11 @@
       break;
     }
 
-    case SK_ConstructorInitialization: {
-      unsigned NumArgs = Args.size();
-      CXXConstructorDecl *Constructor
-        = cast<CXXConstructorDecl>(Step->Function.Function);
-      bool HadMultipleCandidates = Step->Function.HadMultipleCandidates;
-
-      // Build a call to the selected constructor.
-      ASTOwningVector<Expr*> ConstructorArgs(S);
-      SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid())
-                             ? Kind.getEqualLoc()
-                             : Kind.getLocation();
-
-      if (Kind.getKind() == InitializationKind::IK_Default) {
-        // Force even a trivial, implicit default constructor to be
-        // semantically checked. We do this explicitly because we don't build
-        // the definition for completely trivial constructors.
-        CXXRecordDecl *ClassDecl = Constructor->getParent();
-        assert(ClassDecl && "No parent class for constructor.");
-        if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() &&
-            ClassDecl->hasTrivialDefaultConstructor() &&
-            !Constructor->isUsed(false))
-          S.DefineImplicitDefaultConstructor(Loc, Constructor);
-      }
-
-      // Determine the arguments required to actually perform the constructor
-      // call.
-      if (S.CompleteConstructorCall(Constructor, move(Args),
-                                    Loc, ConstructorArgs))
-        return ExprError();
-
-
-      if (Entity.getKind() == InitializedEntity::EK_Temporary &&
-          NumArgs != 1 && // FIXME: Hack to work around cast weirdness
-          (Kind.getKind() == InitializationKind::IK_Direct ||
-           Kind.getKind() == InitializationKind::IK_Value)) {
-        // An explicitly-constructed temporary, e.g., X(1, 2).
-        unsigned NumExprs = ConstructorArgs.size();
-        Expr **Exprs = (Expr **)ConstructorArgs.take();
-        S.MarkDeclarationReferenced(Loc, Constructor);
-        S.DiagnoseUseOfDecl(Constructor, Loc);
-
-        TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
-        if (!TSInfo)
-          TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
-
-        CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context,
-                                                                 Constructor,
-                                                                 TSInfo,
-                                                                 Exprs,
-                                                                 NumExprs,
-                                                         Kind.getParenRange(),
-                                                         HadMultipleCandidates,
-                                             ConstructorInitRequiresZeroInit));
-      } else {
-        CXXConstructExpr::ConstructionKind ConstructKind =
-          CXXConstructExpr::CK_Complete;
-
-        if (Entity.getKind() == InitializedEntity::EK_Base) {
-          ConstructKind = Entity.getBaseSpecifier()->isVirtual() ?
-            CXXConstructExpr::CK_VirtualBase :
-            CXXConstructExpr::CK_NonVirtualBase;
-        } else if (Entity.getKind() == InitializedEntity::EK_Delegating) {
-          ConstructKind = CXXConstructExpr::CK_Delegating;
-        }
-
-        // Only get the parenthesis range if it is a direct construction.
-        SourceRange parenRange =
-            Kind.getKind() == InitializationKind::IK_Direct ?
-            Kind.getParenRange() : SourceRange();
-
-        // If the entity allows NRVO, mark the construction as elidable
-        // unconditionally.
-        if (Entity.allowsNRVO())
-          CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
-                                            Constructor, /*Elidable=*/true,
-                                            move_arg(ConstructorArgs),
-                                            HadMultipleCandidates,
-                                            ConstructorInitRequiresZeroInit,
-                                            ConstructKind,
-                                            parenRange);
-        else
-          CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
-                                            Constructor,
-                                            move_arg(ConstructorArgs),
-                                            HadMultipleCandidates,
-                                            ConstructorInitRequiresZeroInit,
-                                            ConstructKind,
-                                            parenRange);
-      }
-      if (CurInit.isInvalid())
-        return ExprError();
-
-      // Only check access if all of that succeeded.
-      S.CheckConstructorAccess(Loc, Constructor, Entity,
-                               Step->Function.FoundDecl.getAccess());
-      S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Loc);
-
-      if (shouldBindAsTemporary(Entity))
-        CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
-
+    case SK_ConstructorInitialization:
+      CurInit = PerformConstructorInitialization(S, Entity, Kind, move(Args),
+                                                 *Step,
+                                               ConstructorInitRequiresZeroInit);
       break;
-    }
 
     case SK_ZeroInitialization: {
       step_iterator NextStep = Step;
@@ -5171,6 +5120,40 @@
                                                  CK_ARCProduceObject,
                                                  CurInit.take(), 0, VK_RValue));
       break;
+
+    case SK_StdInitializerList: {
+      QualType Dest = Step->Type;
+      QualType E;
+      bool Success = S.isStdInitializerList(Dest, &E);
+      (void)Success;
+      assert(Success && "Destination type changed?");
+      InitListExpr *ILE = cast<InitListExpr>(CurInit.take());
+      unsigned NumInits = ILE->getNumInits();
+      SmallVector<Expr*, 16> Converted(NumInits);
+      InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
+          S.Context.getConstantArrayType(E,
+              llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
+                          NumInits),
+              ArrayType::Normal, 0));
+      InitializedEntity Element =InitializedEntity::InitializeElement(S.Context,
+          0, HiddenArray);
+      for (unsigned i = 0; i < NumInits; ++i) {
+        Element.setElementIndex(i);
+        ExprResult Init = S.Owned(ILE->getInit(i));
+        ExprResult Res = S.PerformCopyInitialization(Element,
+                                                     Init.get()->getExprLoc(),
+                                                     Init);
+        assert(!Res.isInvalid() && "Result changed since try phase.");
+        Converted[i] = Res.take();
+      }
+      InitListExpr *Semantic = new (S.Context)
+          InitListExpr(S.Context, ILE->getLBraceLoc(),
+                       Converted.data(), NumInits, ILE->getRBraceLoc());
+      Semantic->setSyntacticForm(ILE);
+      Semantic->setType(Dest);
+      CurInit = S.Owned(Semantic);
+      break;
+    }
     }
   }
 
@@ -5223,6 +5206,11 @@
       << Args[0]->getSourceRange();
     break;
 
+  case FK_VariableLengthArrayHasInitializer:
+    S.Diag(Kind.getLocation(), diag::err_variable_object_no_init)
+      << Args[0]->getSourceRange();
+    break;
+
   case FK_AddressOfOverloadFailed: {
     DeclAccessPair Found;
     S.ResolveAddressOfOverloadedFunction(Args[0],
@@ -5274,7 +5262,6 @@
 
     case OR_Success:
       llvm_unreachable("Conversion did not fail!");
-      break;
     }
     break;
 
@@ -5373,12 +5360,20 @@
       << (DestType->isRecordType()) << DestType << Args[0]->getSourceRange();
     break;
 
+  case FK_ListConstructorOverloadFailed:
   case FK_ConstructorOverloadFailed: {
     SourceRange ArgsRange;
     if (NumArgs)
       ArgsRange = SourceRange(Args[0]->getLocStart(),
                               Args[NumArgs - 1]->getLocEnd());
 
+    if (Failure == FK_ListConstructorOverloadFailed) {
+      assert(NumArgs == 1 && "List construction from other than 1 argument.");
+      InitListExpr *InitList = cast<InitListExpr>(Args[0]);
+      Args = InitList->getInits();
+      NumArgs = InitList->getNumInits();
+    }
+
     // FIXME: Using "DestType" for the entity we're printing is probably
     // bad.
     switch (FailedOverloadResult) {
@@ -5451,10 +5446,9 @@
 
       case OR_Success:
         llvm_unreachable("Conversion did not fail!");
-        break;
     }
-    break;
   }
+  break;
 
   case FK_DefaultInitOfConst:
     if (Entity.getKind() == InitializedEntity::EK_Member &&
@@ -5498,6 +5492,37 @@
     // FIXME: Already diagnosed!
     break;
   }
+
+  case FK_InitListElementCopyFailure: {
+    // Try to perform all copies again.
+    InitListExpr* InitList = cast<InitListExpr>(Args[0]);
+    unsigned NumInits = InitList->getNumInits();
+    QualType DestType = Entity.getType();
+    QualType E;
+    bool Success = S.isStdInitializerList(DestType, &E);
+    (void)Success;
+    assert(Success && "Where did the std::initializer_list go?");
+    InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
+        S.Context.getConstantArrayType(E,
+            llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
+                        NumInits),
+            ArrayType::Normal, 0));
+    InitializedEntity Element = InitializedEntity::InitializeElement(S.Context,
+        0, HiddenArray);
+    // Show at most 3 errors. Otherwise, you'd get a lot of errors for errors
+    // where the init list type is wrong, e.g.
+    //   std::initializer_list<void*> list = { 1, 2, 3, 4, 5, 6, 7, 8 };
+    // FIXME: Emit a note if we hit the limit?
+    int ErrorCount = 0;
+    for (unsigned i = 0; i < NumInits && ErrorCount < 3; ++i) {
+      Element.setElementIndex(i);
+      ExprResult Init = S.Owned(InitList->getInit(i));
+      if (S.PerformCopyInitialization(Element, Init.get()->getExprLoc(), Init)
+           .isInvalid())
+        ++ErrorCount;
+    }
+    break;
+  }
   }
 
   PrintInitLocationNote(S, Entity);
@@ -5597,9 +5622,21 @@
       OS << "list initialization checker failure";
       break;
 
+    case FK_VariableLengthArrayHasInitializer:
+      OS << "variable length array has an initializer";
+      break;
+
     case FK_PlaceholderType:
       OS << "initializer expression isn't contextually valid";
       break;
+
+    case FK_ListConstructorOverloadFailed:
+      OS << "list constructor overloading failed";
+      break;
+
+    case FK_InitListElementCopyFailure:
+      OS << "copy construction of initializer list element failed";
+      break;
     }
     OS << '\n';
     return;
@@ -5721,6 +5758,10 @@
     case SK_ProduceObjCObject:
       OS << "Objective-C object retension";
       break;
+
+    case SK_StdInitializerList:
+      OS << "std::initializer_list from initializer list";
+      break;
     }
   }
 }
@@ -5729,25 +5770,83 @@
   dump(llvm::errs());
 }
 
-static void DiagnoseNarrowingInInitList(
-    Sema& S, QualType EntityType, const Expr *InitE,
-    bool Constant, const APValue &ConstantValue) {
-  if (Constant) {
-    S.Diag(InitE->getLocStart(),
+static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq,
+                                        QualType EntityType,
+                                        const Expr *PreInit,
+                                        const Expr *PostInit) {
+  if (Seq.step_begin() == Seq.step_end() || PreInit->isValueDependent())
+    return;
+
+  // A narrowing conversion can only appear as the final implicit conversion in
+  // an initialization sequence.
+  const InitializationSequence::Step &LastStep = Seq.step_end()[-1];
+  if (LastStep.Kind != InitializationSequence::SK_ConversionSequence)
+    return;
+
+  const ImplicitConversionSequence &ICS = *LastStep.ICS;
+  const StandardConversionSequence *SCS = 0;
+  switch (ICS.getKind()) {
+  case ImplicitConversionSequence::StandardConversion:
+    SCS = &ICS.Standard;
+    break;
+  case ImplicitConversionSequence::UserDefinedConversion:
+    SCS = &ICS.UserDefined.After;
+    break;
+  case ImplicitConversionSequence::AmbiguousConversion:
+  case ImplicitConversionSequence::EllipsisConversion:
+  case ImplicitConversionSequence::BadConversion:
+    return;
+  }
+
+  // Determine the type prior to the narrowing conversion. If a conversion
+  // operator was used, this may be different from both the type of the entity
+  // and of the pre-initialization expression.
+  QualType PreNarrowingType = PreInit->getType();
+  if (Seq.step_begin() + 1 != Seq.step_end())
+    PreNarrowingType = Seq.step_end()[-2].Type;
+
+  // C++11 [dcl.init.list]p7: Check whether this is a narrowing conversion.
+  APValue ConstantValue;
+  switch (SCS->getNarrowingKind(S.Context, PostInit, ConstantValue)) {
+  case NK_Not_Narrowing:
+    // No narrowing occurred.
+    return;
+
+  case NK_Type_Narrowing:
+    // This was a floating-to-integer conversion, which is always considered a
+    // narrowing conversion even if the value is a constant and can be
+    // represented exactly as an integer.
+    S.Diag(PostInit->getLocStart(),
+           S.getLangOptions().CPlusPlus0x && !S.getLangOptions().MicrosoftExt
+           ? diag::err_init_list_type_narrowing
+           : diag::warn_init_list_type_narrowing)
+      << PostInit->getSourceRange()
+      << PreNarrowingType.getLocalUnqualifiedType()
+      << EntityType.getLocalUnqualifiedType();
+    break;
+
+  case NK_Constant_Narrowing:
+    // A constant value was narrowed.
+    S.Diag(PostInit->getLocStart(),
            S.getLangOptions().CPlusPlus0x && !S.getLangOptions().MicrosoftExt
            ? diag::err_init_list_constant_narrowing
            : diag::warn_init_list_constant_narrowing)
-      << InitE->getSourceRange()
+      << PostInit->getSourceRange()
       << ConstantValue.getAsString(S.getASTContext(), EntityType)
       << EntityType.getLocalUnqualifiedType();
-  } else
-    S.Diag(InitE->getLocStart(),
+    break;
+
+  case NK_Variable_Narrowing:
+    // A variable's value may have been narrowed.
+    S.Diag(PostInit->getLocStart(),
            S.getLangOptions().CPlusPlus0x && !S.getLangOptions().MicrosoftExt
            ? diag::err_init_list_variable_narrowing
            : diag::warn_init_list_variable_narrowing)
-      << InitE->getSourceRange()
-      << InitE->getType().getLocalUnqualifiedType()
+      << PostInit->getSourceRange()
+      << PreNarrowingType.getLocalUnqualifiedType()
       << EntityType.getLocalUnqualifiedType();
+    break;
+  }
 
   llvm::SmallString<128> StaticCast;
   llvm::raw_svector_ostream OS(StaticCast);
@@ -5767,11 +5866,11 @@
     return;
   }
   OS << ">(";
-  S.Diag(InitE->getLocStart(), diag::note_init_list_narrowing_override)
-    << InitE->getSourceRange()
-    << FixItHint::CreateInsertion(InitE->getLocStart(), OS.str())
+  S.Diag(PostInit->getLocStart(), diag::note_init_list_narrowing_override)
+    << PostInit->getSourceRange()
+    << FixItHint::CreateInsertion(PostInit->getLocStart(), OS.str())
     << FixItHint::CreateInsertion(
-      S.getPreprocessor().getLocForEndOfToken(InitE->getLocEnd()), ")");
+      S.getPreprocessor().getLocForEndOfToken(PostInit->getLocEnd()), ")");
 }
 
 //===----------------------------------------------------------------------===//
@@ -5811,12 +5910,11 @@
   InitializationSequence Seq(*this, Entity, Kind, &InitE, 1);
   Init.release();
 
-  bool Constant = false;
-  APValue Result;
-  if (TopLevelOfInitList &&
-      Seq.endsWithNarrowing(Context, InitE, &Constant, &Result)) {
-    DiagnoseNarrowingInInitList(*this, Entity.getType(), InitE,
-                                Constant, Result);
-  }
-  return Seq.Perform(*this, Entity, Kind, MultiExprArg(&InitE, 1));
+  ExprResult Result = Seq.Perform(*this, Entity, Kind, MultiExprArg(&InitE, 1));
+
+  if (!Result.isInvalid() && TopLevelOfInitList)
+    DiagnoseNarrowingInInitList(*this, Seq, Entity.getType(),
+                                InitE, Result.get());
+
+  return Result;
 }

Modified: cfe/branches/tooling/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaLookup.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaLookup.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaLookup.cpp Fri Jan 20 10:14:22 2012
@@ -1053,22 +1053,6 @@
   return !R.empty();
 }
 
-/// \brief Retrieve the previous declaration of D.
-static NamedDecl *getPreviousDeclaration(NamedDecl *D) {
-  if (TagDecl *TD = dyn_cast<TagDecl>(D))
-    return TD->getPreviousDeclaration();
-  if (VarDecl *VD = dyn_cast<VarDecl>(D))
-    return VD->getPreviousDeclaration();
-  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
-    return FD->getPreviousDeclaration();
-  if (RedeclarableTemplateDecl *RTD = dyn_cast<RedeclarableTemplateDecl>(D))
-    return RTD->getPreviousDeclaration();
-  if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
-    return ID->getPreviousDeclaration();
-  
-  return 0;
-}
-
 /// \brief Retrieve the visible declaration corresponding to D, if any.
 ///
 /// This routine determines whether the declaration D is visible in the current
@@ -1081,9 +1065,12 @@
   if (LookupResult::isVisible(D))
     return D;
   
-  while ((D = getPreviousDeclaration(D))) {
-    if (LookupResult::isVisible(D))
-      return D;
+  for (Decl::redecl_iterator RD = D->redecls_begin(), RDEnd = D->redecls_end();
+       RD != RDEnd; ++RD) {
+    if (NamedDecl *ND = dyn_cast<NamedDecl>(*RD)) {
+      if (LookupResult::isVisible(ND))
+        return ND;
+    }
   }
   
   return 0;
@@ -1167,36 +1154,56 @@
         
         // If this declaration is module-private and it came from an AST
         // file, we can't see it.
-        NamedDecl *D = getVisibleDecl(*I);
+        NamedDecl *D = R.isHiddenDeclarationVisible()? *I : getVisibleDecl(*I);
         if (!D)
           continue;
                 
         R.addDecl(D);
 
-        if ((*I)->getAttr<OverloadableAttr>()) {
-          // If this declaration has the "overloadable" attribute, we
-          // might have a set of overloaded functions.
-
-          // Figure out what scope the identifier is in.
-          while (!(S->getFlags() & Scope::DeclScope) ||
-                 !S->isDeclScope(*I))
+        // Check whether there are any other declarations with the same name
+        // and in the same scope.
+        if (I != IEnd) {
+          // Find the scope in which this declaration was declared (if it
+          // actually exists in a Scope).
+          while (S && !S->isDeclScope(D))
             S = S->getParent();
-
-          // Find the last declaration in this scope (with the same
-          // name, naturally).
+          
+          // If the scope containing the declaration is the translation unit,
+          // then we'll need to perform our checks based on the matching
+          // DeclContexts rather than matching scopes.
+          if (S && isNamespaceOrTranslationUnitScope(S))
+            S = 0;
+
+          // Compute the DeclContext, if we need it.
+          DeclContext *DC = 0;
+          if (!S)
+            DC = (*I)->getDeclContext()->getRedeclContext();
+            
           IdentifierResolver::iterator LastI = I;
           for (++LastI; LastI != IEnd; ++LastI) {
-            if (!S->isDeclScope(*LastI))
-              break;
+            if (S) {
+              // Match based on scope.
+              if (!S->isDeclScope(*LastI))
+                break;
+            } else {
+              // Match based on DeclContext.
+              DeclContext *LastDC 
+                = (*LastI)->getDeclContext()->getRedeclContext();
+              if (!LastDC->Equals(DC))
+                break;
+            }
             
-            D = getVisibleDecl(*LastI);
+            // If the declaration isn't in the right namespace, skip it.
+            if (!(*LastI)->isInIdentifierNamespace(IDNS))
+              continue;
+                        
+            D = R.isHiddenDeclarationVisible()? *LastI : getVisibleDecl(*LastI);
             if (D)
               R.addDecl(D);
           }
-        }
-
-        R.resolveKind();
 
+          R.resolveKind();
+        }
         return true;
       }
   } else {
@@ -2176,9 +2183,10 @@
 
 /// \brief Find the protocol with the given name, if any.
 ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II,
-                                       SourceLocation IdLoc) {
+                                       SourceLocation IdLoc,
+                                       RedeclarationKind Redecl) {
   Decl *D = LookupSingleName(TUScope, II, IdLoc,
-                             LookupObjCProtocolName);
+                             LookupObjCProtocolName, Redecl);
   return cast_or_null<ObjCProtocolDecl>(D);
 }
 
@@ -2534,7 +2542,7 @@
 
   FunctionDecl *Cursor = NewFD;
   while (true) {
-    Cursor = Cursor->getPreviousDeclaration();
+    Cursor = Cursor->getPreviousDecl();
 
     // If we got to the end without finding OldFD, OldFD is the newer
     // declaration;  leave things as they are.
@@ -2752,8 +2760,10 @@
     Result.getSema().ForceDeclarationOfImplicitMembers(Class);
 
   // Enumerate all of the results in this context.
-  for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx;
-       CurCtx = CurCtx->getNextContext()) {
+  llvm::SmallVector<DeclContext *, 2> Contexts;
+  Ctx->collectAllContexts(Contexts);
+  for (unsigned I = 0, N = Contexts.size(); I != N; ++I) {
+    DeclContext *CurCtx = Contexts[I];
     for (DeclContext::decl_iterator D = CurCtx->decls_begin(),
                                  DEnd = CurCtx->decls_end();
          D != DEnd; ++D) {
@@ -2762,24 +2772,6 @@
           Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
           Visited.add(ND);
         }
-      } else if (ObjCForwardProtocolDecl *ForwardProto
-                                      = dyn_cast<ObjCForwardProtocolDecl>(*D)) {
-        for (ObjCForwardProtocolDecl::protocol_iterator
-                  P = ForwardProto->protocol_begin(),
-               PEnd = ForwardProto->protocol_end();
-             P != PEnd;
-             ++P) {
-          if (NamedDecl *ND = Result.getAcceptableDecl(*P)) {
-            Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
-            Visited.add(ND);
-          }
-        }
-      } else if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) {
-          ObjCInterfaceDecl *IFace = Class->getForwardInterfaceDecl();
-          if (NamedDecl *ND = Result.getAcceptableDecl(IFace)) {
-            Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
-            Visited.add(ND);
-          }
       }
       
       // Visit transparent contexts and inline namespaces inside this context.
@@ -3338,13 +3330,13 @@
                                       Scope *S, CXXScopeSpec *SS,
                                       DeclContext *MemberContext,
                                       bool EnteringContext,
-                                      Sema::CorrectTypoContext CTC) {
+                                      bool isObjCIvarLookup) {
   Res.suppressDiagnostics();
   Res.clear();
   Res.setLookupName(Name);
   if (MemberContext) {
     if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(MemberContext)) {
-      if (CTC == Sema::CTC_ObjCIvarLookup) {
+      if (isObjCIvarLookup) {
         if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(Name)) {
           Res.addDecl(Ivar);
           Res.resolveKind();
@@ -3385,61 +3377,11 @@
 /// \brief Add keywords to the consumer as possible typo corrections.
 static void AddKeywordsToConsumer(Sema &SemaRef,
                                   TypoCorrectionConsumer &Consumer,
-                                  Scope *S, Sema::CorrectTypoContext CTC) {
-  // Add context-dependent keywords.
-  bool WantTypeSpecifiers = false;
-  bool WantExpressionKeywords = false;
-  bool WantCXXNamedCasts = false;
-  bool WantRemainingKeywords = false;
-  switch (CTC) {
-    case Sema::CTC_Unknown:
-      WantTypeSpecifiers = true;
-      WantExpressionKeywords = true;
-      WantCXXNamedCasts = true;
-      WantRemainingKeywords = true;
-
-      if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
-        if (Method->getClassInterface() &&
-            Method->getClassInterface()->getSuperClass())
-          Consumer.addKeywordResult("super");
-
-      break;
-
-    case Sema::CTC_NoKeywords:
-      break;
+                                  Scope *S, CorrectionCandidateCallback &CCC) {
+  if (CCC.WantObjCSuper)
+    Consumer.addKeywordResult("super");
 
-    case Sema::CTC_Type:
-      WantTypeSpecifiers = true;
-      break;
-
-    case Sema::CTC_ObjCMessageReceiver:
-      Consumer.addKeywordResult("super");
-      // Fall through to handle message receivers like expressions.
-
-    case Sema::CTC_Expression:
-      if (SemaRef.getLangOptions().CPlusPlus)
-        WantTypeSpecifiers = true;
-      WantExpressionKeywords = true;
-      // Fall through to get C++ named casts.
-
-    case Sema::CTC_CXXCasts:
-      WantCXXNamedCasts = true;
-      break;
-
-    case Sema::CTC_ObjCPropertyLookup:
-      // FIXME: Add "isa"?
-      break;
-
-    case Sema::CTC_MemberLookup:
-      if (SemaRef.getLangOptions().CPlusPlus)
-        Consumer.addKeywordResult("template");
-      break;
-
-    case Sema::CTC_ObjCIvarLookup:
-      break;
-  }
-
-  if (WantTypeSpecifiers) {
+  if (CCC.WantTypeSpecifiers) {
     // Add type-specifier keywords to the set of results.
     const char *CTypeSpecs[] = {
       "char", "const", "double", "enum", "float", "int", "long", "short",
@@ -3478,14 +3420,14 @@
       Consumer.addKeywordResult("typeof");
   }
 
-  if (WantCXXNamedCasts && SemaRef.getLangOptions().CPlusPlus) {
+  if (CCC.WantCXXNamedCasts && SemaRef.getLangOptions().CPlusPlus) {
     Consumer.addKeywordResult("const_cast");
     Consumer.addKeywordResult("dynamic_cast");
     Consumer.addKeywordResult("reinterpret_cast");
     Consumer.addKeywordResult("static_cast");
   }
 
-  if (WantExpressionKeywords) {
+  if (CCC.WantExpressionKeywords) {
     Consumer.addKeywordResult("sizeof");
     if (SemaRef.getLangOptions().Bool || SemaRef.getLangOptions().CPlusPlus) {
       Consumer.addKeywordResult("false");
@@ -3511,7 +3453,7 @@
     }
   }
 
-  if (WantRemainingKeywords) {
+  if (CCC.WantRemainingKeywords) {
     if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) {
       // Statements.
       const char *CStmts[] = {
@@ -3575,15 +3517,16 @@
 /// \param SS the nested-name-specifier that precedes the name we're
 /// looking for, if present.
 ///
+/// \param CCC A CorrectionCandidateCallback object that provides further
+/// validation of typo correction candidates. It also provides flags for
+/// determining the set of keywords permitted.
+///
 /// \param MemberContext if non-NULL, the context in which to look for
 /// a member access expression.
 ///
 /// \param EnteringContext whether we're entering the context described by
 /// the nested-name-specifier SS.
 ///
-/// \param CTC The context in which typo correction occurs, which impacts the
-/// set of keywords permitted.
-///
 /// \param OPT when non-NULL, the search for visible declarations will
 /// also walk the protocols in the qualified interfaces of \p OPT.
 ///
@@ -3594,9 +3537,9 @@
 TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
                                  Sema::LookupNameKind LookupKind,
                                  Scope *S, CXXScopeSpec *SS,
+                                 CorrectionCandidateCallback *CCC,
                                  DeclContext *MemberContext,
                                  bool EnteringContext,
-                                 CorrectTypoContext CTC,
                                  const ObjCObjectPointerType *OPT) {
   if (Diags.hasFatalErrorOccurred() || !getLangOptions().SpellChecking)
     return TypoCorrection();
@@ -3656,7 +3599,8 @@
     IsUnqualifiedLookup = true;
     UnqualifiedTyposCorrectedMap::iterator Cached
       = UnqualifiedTyposCorrected.find(Typo);
-    if (Cached == UnqualifiedTyposCorrected.end()) {
+    if (Cached == UnqualifiedTyposCorrected.end() ||
+        (Cached->second && CCC && !CCC->ValidateCandidate(Cached->second))) {
       // Provide a stop gap for files that are just seriously broken.  Trying
       // to correct all typos can turn into a HUGE performance penalty, causing
       // some files to take minutes to get rejected by the parser.
@@ -3693,7 +3637,8 @@
     }
   }
 
-  AddKeywordsToConsumer(*this, Consumer, S,  CTC);
+  CorrectionCandidateCallback DefaultCCC;
+  AddKeywordsToConsumer(*this, Consumer, S, CCC ? *CCC : DefaultCCC);
 
   // If we haven't found anything, we're done.
   if (Consumer.empty()) {
@@ -3733,7 +3678,8 @@
       Namespaces.AddNamespace(KNI->first);
   }
 
-  // Weed out any names that could not be found by name lookup.
+  // Weed out any names that could not be found by name lookup or, if a
+  // CorrectionCandidateCallback object was provided, failed validation.
   llvm::SmallPtrSet<IdentifierInfo*, 16> QualifiedResults;
   LookupResult TmpRes(*this, TypoName, LookupKind);
   TmpRes.suppressDiagnostics();
@@ -3743,16 +3689,21 @@
     for (TypoCorrectionConsumer::result_iterator I = DI->second->begin(),
                                               IEnd = DI->second->end();
          I != IEnd; /* Increment in loop. */) {
-      // If the item already has been looked up or is a keyword, keep it
+      // If the item already has been looked up or is a keyword, keep it.
+      // If a validator callback object was given, drop the correction
+      // unless it passes validation.
       if (I->second.isResolved()) {
+        TypoCorrectionConsumer::result_iterator Prev = I;
         ++I;
+        if (CCC && !CCC->ValidateCandidate(Prev->second))
+          DI->second->erase(Prev);
         continue;
       }
 
       // Perform name lookup on this name.
       IdentifierInfo *Name = I->second.getCorrectionAsIdentifierInfo();
       LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext,
-                                EnteringContext, CTC);
+                                EnteringContext, CCC && CCC->IsObjCIvarLookup);
 
       switch (TmpRes.getResultKind()) {
       case LookupResult::NotFound:
@@ -3774,20 +3725,28 @@
         return TypoCorrection();
 
       case LookupResult::FoundOverloaded: {
+        TypoCorrectionConsumer::result_iterator Prev = I;
         // Store all of the Decls for overloaded symbols
         for (LookupResult::iterator TRD = TmpRes.begin(),
                                  TRDEnd = TmpRes.end();
              TRD != TRDEnd; ++TRD)
           I->second.addCorrectionDecl(*TRD);
         ++I;
+        if (CCC && !CCC->ValidateCandidate(Prev->second))
+          DI->second->erase(Prev);
         break;
       }
 
-      case LookupResult::Found:
+      case LookupResult::Found: {
+        TypoCorrectionConsumer::result_iterator Prev = I;
         I->second.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
         ++I;
+        if (CCC && !CCC->ValidateCandidate(Prev->second))
+          DI->second->erase(Prev);
         break;
       }
+
+      }
     }
 
     if (DI->second->empty())
@@ -3818,6 +3777,8 @@
           TmpRes.setLookupName(*QRI);
           if (!LookupQualifiedName(TmpRes, Ctx)) continue;
 
+          // Any corrections added below will be validated in subsequent
+          // iterations of the main while() loop over the Consumer's contents.
           switch (TmpRes.getResultKind()) {
           case LookupResult::Found:
             Consumer.addName((*QRI)->getName(), TmpRes.getAsSingle<NamedDecl>(),
@@ -3891,7 +3852,12 @@
 
     return Result;
   }
-  else if (BestResults.size() > 1 && CTC == CTC_ObjCMessageReceiver
+  else if (BestResults.size() > 1
+           // Ugly hack equivalent to CTC == CTC_ObjCMessageReceiver;
+           // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for
+           // some instances of CTC_Unknown, while WantRemainingKeywords is true
+           // for CTC_Unknown but not for CTC_ObjCMessageReceiver.
+           && CCC && CCC->WantObjCSuper && !CCC->WantRemainingKeywords
            && BestResults["super"].isKeyword()) {
     // Prefer 'super' when we're completing in a message-receiver
     // context.

Modified: cfe/branches/tooling/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaObjCProperty.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaObjCProperty.cpp Fri Jan 20 10:14:22 2012
@@ -518,6 +518,33 @@
   S.Diag(property->getLocation(), diag::note_property_declare);
 }
 
+/// setImpliedPropertyAttributeForReadOnlyProperty -
+/// This routine evaludates life-time attributes for a 'readonly'
+/// property with no known lifetime of its own, using backing
+/// 'ivar's attribute, if any. If no backing 'ivar', property's
+/// life-time is assumed 'strong'.
+static void setImpliedPropertyAttributeForReadOnlyProperty(
+              ObjCPropertyDecl *property, ObjCIvarDecl *ivar) {
+  Qualifiers::ObjCLifetime propertyLifetime = 
+    getImpliedARCOwnership(property->getPropertyAttributes(),
+                           property->getType());
+  if (propertyLifetime != Qualifiers::OCL_None)
+    return;
+  
+  if (!ivar) {
+    // if no backing ivar, make property 'strong'.
+    property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
+    return;
+  }
+  // property assumes owenership of backing ivar.
+  QualType ivarType = ivar->getType();
+  Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
+  if (ivarLifetime == Qualifiers::OCL_Strong)
+    property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
+  else if (ivarLifetime == Qualifiers::OCL_Weak)
+    property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak);
+  return;
+}
 
 /// ActOnPropertyImplDecl - This routine performs semantic checks and
 /// builds the AST node for a property implementation declaration; declared
@@ -608,11 +635,21 @@
     // @synthesize
     if (!PropertyIvar)
       PropertyIvar = PropertyId;
-    ObjCPropertyDecl::PropertyAttributeKind kind 
-      = property->getPropertyAttributes();
+    // Check that this is a previously declared 'ivar' in 'IDecl' interface
+    ObjCInterfaceDecl *ClassDeclared;
+    Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
     QualType PropType = property->getType();
-
     QualType PropertyIvarType = PropType.getNonReferenceType();
+    
+    if (getLangOptions().ObjCAutoRefCount &&
+        (property->getPropertyAttributesAsWritten() &
+         ObjCPropertyDecl::OBJC_PR_readonly) &&
+        PropertyIvarType->isObjCRetainableType()) {
+      setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar);    
+    }
+    
+    ObjCPropertyDecl::PropertyAttributeKind kind 
+      = property->getPropertyAttributes();
 
     // Add GC __weak to the ivar type if the property is weak.
     if ((kind & ObjCPropertyDecl::OBJC_PR_weak) && 
@@ -627,9 +664,6 @@
       }
     }
 
-    // Check that this is a previously declared 'ivar' in 'IDecl' interface
-    ObjCInterfaceDecl *ClassDeclared;
-    Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
     if (!Ivar) {
       // In ARC, give the ivar a lifetime qualifier based on the
       // property attributes.
@@ -830,9 +864,13 @@
               dyn_cast_or_null<CXXOperatorCallExpr>(callExpr))
           if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee())
             if (!FuncDecl->isTrivial())
-              Diag(PropertyLoc, 
-                   diag::warn_atomic_property_nontrivial_assign_op) 
+              if (property->getType()->isReferenceType()) {
+                Diag(PropertyLoc, 
+                     diag::err_atomic_property_nontrivial_assign_op)
                     << property->getType();
+                Diag(FuncDecl->getLocStart(), 
+                     diag::note_callee_decl) << FuncDecl;
+              }
       }
       PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>());
     }
@@ -856,7 +894,8 @@
     }
     IC->addPropertyImplementation(PIDecl);
     if (getLangOptions().ObjCDefaultSynthProperties &&
-        getLangOptions().ObjCNonFragileABI2) {
+        getLangOptions().ObjCNonFragileABI2 &&
+        !IDecl->isObjCRequiresPropertyDefs()) {
       // Diagnose if an ivar was lazily synthesdized due to a previous
       // use and if 1) property is @dynamic or 2) property is synthesized
       // but it requires an ivar of different name.
@@ -1355,7 +1394,8 @@
   if (!IC)
     return;
   if (ObjCInterfaceDecl* IDecl = IC->getClassInterface())
-    DefaultSynthesizeProperties(S, IC, IDecl);
+    if (!IDecl->isObjCRequiresPropertyDefs())
+      DefaultSynthesizeProperties(S, IC, IDecl);
 }
 
 void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
@@ -1392,6 +1432,11 @@
       << Prop->getDeclName() << Prop->getGetterName();
       Diag(Prop->getLocation(),
            diag::note_property_declare);
+      if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2)
+        if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
+          if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
+            Diag(RID->getLocation(), diag::note_suppressed_class_declare);
+            
     }
 
     if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
@@ -1402,6 +1447,10 @@
       << Prop->getDeclName() << Prop->getSetterName();
       Diag(Prop->getLocation(),
            diag::note_property_declare);
+      if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2)
+        if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
+          if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
+            Diag(RID->getLocation(), diag::note_suppressed_class_declare);
     }
   }
 }
@@ -1666,6 +1715,21 @@
   ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
   QualType PropertyTy = PropertyDecl->getType(); 
 
+  if (getLangOptions().ObjCAutoRefCount &&
+      (Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+      PropertyTy->isObjCRetainableType()) {
+    // 'readonly' property with no obvious lifetime.
+    // its life time will be determined by its backing ivar.
+    unsigned rel = (ObjCDeclSpec::DQ_PR_unsafe_unretained |
+                    ObjCDeclSpec::DQ_PR_copy |
+                    ObjCDeclSpec::DQ_PR_retain |
+                    ObjCDeclSpec::DQ_PR_strong |
+                    ObjCDeclSpec::DQ_PR_weak |
+                    ObjCDeclSpec::DQ_PR_assign);
+    if ((Attributes & rel) == 0)
+      return;
+  }
+  
   // readonly and readwrite/assign/retain/copy conflict.
   if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
       (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
@@ -1795,6 +1859,14 @@
         // not specified; including when property is 'readonly'.
         PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
       else if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) {
+        bool isAnyClassTy = 
+          (PropertyTy->isObjCClassType() || 
+           PropertyTy->isObjCQualifiedClassType());
+        // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to
+        // issue any warning.
+        if (isAnyClassTy && getLangOptions().getGC() == LangOptions::NonGC)
+          ;
+        else {
           // Skip this warning in gc-only mode.
           if (getLangOptions().getGC() != LangOptions::GCOnly)
             Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
@@ -1802,6 +1874,7 @@
           // If non-gc code warn that this is likely inappropriate.
           if (getLangOptions().getGC() == LangOptions::NonGC)
             Diag(Loc, diag::warn_objc_property_default_assign_on_object);
+        }
       }
 
     // FIXME: Implement warning dependent on NSCopying being

Modified: cfe/branches/tooling/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaOverload.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaOverload.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaOverload.cpp Fri Jan 20 10:14:22 2012
@@ -258,6 +258,164 @@
   return false;
 }
 
+/// Skip any implicit casts which could be either part of a narrowing conversion
+/// or after one in an implicit conversion.
+static const Expr *IgnoreNarrowingConversion(const Expr *Converted) {
+  while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Converted)) {
+    switch (ICE->getCastKind()) {
+    case CK_NoOp:
+    case CK_IntegralCast:
+    case CK_IntegralToBoolean:
+    case CK_IntegralToFloating:
+    case CK_FloatingToIntegral:
+    case CK_FloatingToBoolean:
+    case CK_FloatingCast:
+      Converted = ICE->getSubExpr();
+      continue;
+
+    default:
+      return Converted;
+    }
+  }
+
+  return Converted;
+}
+
+/// Check if this standard conversion sequence represents a narrowing
+/// conversion, according to C++11 [dcl.init.list]p7.
+///
+/// \param Ctx  The AST context.
+/// \param Converted  The result of applying this standard conversion sequence.
+/// \param ConstantValue  If this is an NK_Constant_Narrowing conversion, the
+///        value of the expression prior to the narrowing conversion.
+NarrowingKind
+StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
+                                             const Expr *Converted,
+                                             APValue &ConstantValue) const {
+  assert(Ctx.getLangOptions().CPlusPlus && "narrowing check outside C++");
+
+  // C++11 [dcl.init.list]p7:
+  //   A narrowing conversion is an implicit conversion ...
+  QualType FromType = getToType(0);
+  QualType ToType = getToType(1);
+  switch (Second) {
+  // -- from a floating-point type to an integer type, or
+  //
+  // -- from an integer type or unscoped enumeration type to a floating-point
+  //    type, except where the source is a constant expression and the actual
+  //    value after conversion will fit into the target type and will produce
+  //    the original value when converted back to the original type, or
+  case ICK_Floating_Integral:
+    if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) {
+      return NK_Type_Narrowing;
+    } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) {
+      llvm::APSInt IntConstantValue;
+      const Expr *Initializer = IgnoreNarrowingConversion(Converted);
+      if (Initializer &&
+          Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) {
+        // Convert the integer to the floating type.
+        llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType));
+        Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(),
+                                llvm::APFloat::rmNearestTiesToEven);
+        // And back.
+        llvm::APSInt ConvertedValue = IntConstantValue;
+        bool ignored;
+        Result.convertToInteger(ConvertedValue,
+                                llvm::APFloat::rmTowardZero, &ignored);
+        // If the resulting value is different, this was a narrowing conversion.
+        if (IntConstantValue != ConvertedValue) {
+          ConstantValue = APValue(IntConstantValue);
+          return NK_Constant_Narrowing;
+        }
+      } else {
+        // Variables are always narrowings.
+        return NK_Variable_Narrowing;
+      }
+    }
+    return NK_Not_Narrowing;
+
+  // -- from long double to double or float, or from double to float, except
+  //    where the source is a constant expression and the actual value after
+  //    conversion is within the range of values that can be represented (even
+  //    if it cannot be represented exactly), or
+  case ICK_Floating_Conversion:
+    if (FromType->isRealFloatingType() && ToType->isRealFloatingType() &&
+        Ctx.getFloatingTypeOrder(FromType, ToType) == 1) {
+      // FromType is larger than ToType.
+      const Expr *Initializer = IgnoreNarrowingConversion(Converted);
+      if (Initializer->isCXX11ConstantExpr(Ctx, &ConstantValue)) {
+        // Constant!
+        assert(ConstantValue.isFloat());
+        llvm::APFloat FloatVal = ConstantValue.getFloat();
+        // Convert the source value into the target type.
+        bool ignored;
+        llvm::APFloat::opStatus ConvertStatus = FloatVal.convert(
+          Ctx.getFloatTypeSemantics(ToType),
+          llvm::APFloat::rmNearestTiesToEven, &ignored);
+        // If there was no overflow, the source value is within the range of
+        // values that can be represented.
+        if (ConvertStatus & llvm::APFloat::opOverflow)
+          return NK_Constant_Narrowing;
+      } else {
+        return NK_Variable_Narrowing;
+      }
+    }
+    return NK_Not_Narrowing;
+
+  // -- from an integer type or unscoped enumeration type to an integer type
+  //    that cannot represent all the values of the original type, except where
+  //    the source is a constant expression and the actual value after
+  //    conversion will fit into the target type and will produce the original
+  //    value when converted back to the original type.
+  case ICK_Boolean_Conversion:  // Bools are integers too.
+    if (!FromType->isIntegralOrUnscopedEnumerationType()) {
+      // Boolean conversions can be from pointers and pointers to members
+      // [conv.bool], and those aren't considered narrowing conversions.
+      return NK_Not_Narrowing;
+    }  // Otherwise, fall through to the integral case.
+  case ICK_Integral_Conversion: {
+    assert(FromType->isIntegralOrUnscopedEnumerationType());
+    assert(ToType->isIntegralOrUnscopedEnumerationType());
+    const bool FromSigned = FromType->isSignedIntegerOrEnumerationType();
+    const unsigned FromWidth = Ctx.getIntWidth(FromType);
+    const bool ToSigned = ToType->isSignedIntegerOrEnumerationType();
+    const unsigned ToWidth = Ctx.getIntWidth(ToType);
+
+    if (FromWidth > ToWidth ||
+        (FromWidth == ToWidth && FromSigned != ToSigned)) {
+      // Not all values of FromType can be represented in ToType.
+      llvm::APSInt InitializerValue;
+      const Expr *Initializer = IgnoreNarrowingConversion(Converted);
+      if (Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) {
+        ConstantValue = APValue(InitializerValue);
+
+        // Add a bit to the InitializerValue so we don't have to worry about
+        // signed vs. unsigned comparisons.
+        InitializerValue = InitializerValue.extend(
+          InitializerValue.getBitWidth() + 1);
+        // Convert the initializer to and from the target width and signed-ness.
+        llvm::APSInt ConvertedValue = InitializerValue;
+        ConvertedValue = ConvertedValue.trunc(ToWidth);
+        ConvertedValue.setIsSigned(ToSigned);
+        ConvertedValue = ConvertedValue.extend(InitializerValue.getBitWidth());
+        ConvertedValue.setIsSigned(InitializerValue.isSigned());
+        // If the result is different, this was a narrowing conversion.
+        if (ConvertedValue != InitializerValue)
+          return NK_Constant_Narrowing;
+      } else {
+        // Variables are always narrowings.
+        return NK_Variable_Narrowing;
+      }
+    }
+    return NK_Not_Narrowing;
+  }
+
+  default:
+    // Other kinds of conversions are not narrowings.
+    return NK_Not_Narrowing;
+  }
+}
+
 /// DebugPrint - Print this standard conversion sequence to standard
 /// error. Useful for debugging overloading issues.
 void StandardConversionSequence::DebugPrint() const {
@@ -541,7 +699,11 @@
 }
 
 void OverloadCandidateSet::clear() {
-  inherited::clear();
+  for (iterator i = begin(), e = end(); i != e; ++i)
+    for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii)
+      i->Conversions[ii].~ImplicitConversionSequence();
+  NumInlineSequences = 0;
+  Candidates.clear();
   Functions.clear();
 }
 
@@ -824,6 +986,86 @@
   return FD->isUnavailable() && !cast<Decl>(CurContext)->isUnavailable();
 }
 
+/// \brief Tries a user-defined conversion from From to ToType.
+///
+/// Produces an implicit conversion sequence for when a standard conversion
+/// is not an option. See TryImplicitConversion for more information.
+static ImplicitConversionSequence
+TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
+                         bool SuppressUserConversions,
+                         bool AllowExplicit,
+                         bool InOverloadResolution,
+                         bool CStyle,
+                         bool AllowObjCWritebackConversion) {
+  ImplicitConversionSequence ICS;
+
+  if (SuppressUserConversions) {
+    // We're not in the case above, so there is no conversion that
+    // we can perform.
+    ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
+    return ICS;
+  }
+
+  // Attempt user-defined conversion.
+  OverloadCandidateSet Conversions(From->getExprLoc());
+  OverloadingResult UserDefResult
+    = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions,
+                              AllowExplicit);
+
+  if (UserDefResult == OR_Success) {
+    ICS.setUserDefined();
+    // C++ [over.ics.user]p4:
+    //   A conversion of an expression of class type to the same class
+    //   type is given Exact Match rank, and a conversion of an
+    //   expression of class type to a base class of that type is
+    //   given Conversion rank, in spite of the fact that a copy
+    //   constructor (i.e., a user-defined conversion function) is
+    //   called for those cases.
+    if (CXXConstructorDecl *Constructor
+          = dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) {
+      QualType FromCanon
+        = S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+      QualType ToCanon
+        = S.Context.getCanonicalType(ToType).getUnqualifiedType();
+      if (Constructor->isCopyConstructor() &&
+          (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) {
+        // Turn this into a "standard" conversion sequence, so that it
+        // gets ranked with standard conversion sequences.
+        ICS.setStandard();
+        ICS.Standard.setAsIdentityConversion();
+        ICS.Standard.setFromType(From->getType());
+        ICS.Standard.setAllToTypes(ToType);
+        ICS.Standard.CopyConstructor = Constructor;
+        if (ToCanon != FromCanon)
+          ICS.Standard.Second = ICK_Derived_To_Base;
+      }
+    }
+
+    // C++ [over.best.ics]p4:
+    //   However, when considering the argument of a user-defined
+    //   conversion function that is a candidate by 13.3.1.3 when
+    //   invoked for the copying of the temporary in the second step
+    //   of a class copy-initialization, or by 13.3.1.4, 13.3.1.5, or
+    //   13.3.1.6 in all cases, only standard conversion sequences and
+    //   ellipsis conversion sequences are allowed.
+    if (SuppressUserConversions && ICS.isUserDefined()) {
+      ICS.setBad(BadConversionSequence::suppressed_user, From, ToType);
+    }
+  } else if (UserDefResult == OR_Ambiguous && !SuppressUserConversions) {
+    ICS.setAmbiguous();
+    ICS.Ambiguous.setFromType(From->getType());
+    ICS.Ambiguous.setToType(ToType);
+    for (OverloadCandidateSet::iterator Cand = Conversions.begin();
+         Cand != Conversions.end(); ++Cand)
+      if (Cand->Viable)
+        ICS.Ambiguous.addConversion(Cand->Function);
+  } else {
+    ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
+  }
+
+  return ICS;
+}
+
 /// TryImplicitConversion - Attempt to perform an implicit conversion
 /// from the given expression (Expr) to the given type (ToType). This
 /// function returns an implicit conversion sequence that can be used
@@ -899,71 +1141,9 @@
     return ICS;
   }
 
-  if (SuppressUserConversions) {
-    // We're not in the case above, so there is no conversion that
-    // we can perform.
-    ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
-    return ICS;
-  }
-
-  // Attempt user-defined conversion.
-  OverloadCandidateSet Conversions(From->getExprLoc());
-  OverloadingResult UserDefResult
-    = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions,
-                              AllowExplicit);
-
-  if (UserDefResult == OR_Success) {
-    ICS.setUserDefined();
-    // C++ [over.ics.user]p4:
-    //   A conversion of an expression of class type to the same class
-    //   type is given Exact Match rank, and a conversion of an
-    //   expression of class type to a base class of that type is
-    //   given Conversion rank, in spite of the fact that a copy
-    //   constructor (i.e., a user-defined conversion function) is
-    //   called for those cases.
-    if (CXXConstructorDecl *Constructor
-          = dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) {
-      QualType FromCanon
-        = S.Context.getCanonicalType(From->getType().getUnqualifiedType());
-      QualType ToCanon
-        = S.Context.getCanonicalType(ToType).getUnqualifiedType();
-      if (Constructor->isCopyConstructor() &&
-          (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) {
-        // Turn this into a "standard" conversion sequence, so that it
-        // gets ranked with standard conversion sequences.
-        ICS.setStandard();
-        ICS.Standard.setAsIdentityConversion();
-        ICS.Standard.setFromType(From->getType());
-        ICS.Standard.setAllToTypes(ToType);
-        ICS.Standard.CopyConstructor = Constructor;
-        if (ToCanon != FromCanon)
-          ICS.Standard.Second = ICK_Derived_To_Base;
-      }
-    }
-
-    // C++ [over.best.ics]p4:
-    //   However, when considering the argument of a user-defined
-    //   conversion function that is a candidate by 13.3.1.3 when
-    //   invoked for the copying of the temporary in the second step
-    //   of a class copy-initialization, or by 13.3.1.4, 13.3.1.5, or
-    //   13.3.1.6 in all cases, only standard conversion sequences and
-    //   ellipsis conversion sequences are allowed.
-    if (SuppressUserConversions && ICS.isUserDefined()) {
-      ICS.setBad(BadConversionSequence::suppressed_user, From, ToType);
-    }
-  } else if (UserDefResult == OR_Ambiguous && !SuppressUserConversions) {
-    ICS.setAmbiguous();
-    ICS.Ambiguous.setFromType(From->getType());
-    ICS.Ambiguous.setToType(ToType);
-    for (OverloadCandidateSet::iterator Cand = Conversions.begin();
-         Cand != Conversions.end(); ++Cand)
-      if (Cand->Viable)
-        ICS.Ambiguous.addConversion(Cand->Function);
-  } else {
-    ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
-  }
-
-  return ICS;
+  return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions,
+                                  AllowExplicit, InOverloadResolution, CStyle,
+                                  AllowObjCWritebackConversion);
 }
 
 ImplicitConversionSequence
@@ -2612,6 +2792,18 @@
       // We're not going to find any constructors.
     } else if (CXXRecordDecl *ToRecordDecl
                  = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
+
+      Expr **Args = &From;
+      unsigned NumArgs = 1;
+      bool ListInitializing = false;
+      // If we're list-initializing, we pass the individual elements as
+      // arguments, not the entire list.
+      if (InitListExpr *InitList = dyn_cast<InitListExpr>(From)) {
+        Args = InitList->getInits();
+        NumArgs = InitList->getNumInits();
+        ListInitializing = true;
+      }
+
       DeclContext::lookup_iterator Con, ConEnd;
       for (llvm::tie(Con, ConEnd) = S.LookupConstructors(ToRecordDecl);
            Con != ConEnd; ++Con) {
@@ -2628,28 +2820,33 @@
         else
           Constructor = cast<CXXConstructorDecl>(D);
 
-        if (!Constructor->isInvalidDecl() &&
-            Constructor->isConvertingConstructor(AllowExplicit)) {
+        bool Usable = !Constructor->isInvalidDecl();
+        if (ListInitializing)
+          Usable = Usable && (AllowExplicit || !Constructor->isExplicit());
+        else
+          Usable = Usable &&Constructor->isConvertingConstructor(AllowExplicit);
+        if (Usable) {
           if (ConstructorTmpl)
             S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
                                            /*ExplicitArgs*/ 0,
-                                           &From, 1, CandidateSet,
+                                           Args, NumArgs, CandidateSet,
                                            /*SuppressUserConversions=*/
-                                             !ConstructorsOnly);
+                                           !ConstructorsOnly &&
+                                             !ListInitializing);
           else
             // Allow one user-defined conversion when user specifies a
             // From->ToType conversion via an static cast (c-style, etc).
             S.AddOverloadCandidate(Constructor, FoundDecl,
-                                   &From, 1, CandidateSet,
+                                   Args, NumArgs, CandidateSet,
                                    /*SuppressUserConversions=*/
-                                     !ConstructorsOnly);
+                                   !ConstructorsOnly && !ListInitializing);
         }
       }
     }
   }
 
   // Enumerate conversion functions, if we're allowed to.
-  if (ConstructorsOnly) {
+  if (ConstructorsOnly || isa<InitListExpr>(From)) {
   } else if (S.RequireCompleteType(From->getLocStart(), From->getType(),
                                    S.PDiag(0) << From->getSourceRange())) {
     // No conversion functions from incomplete types.
@@ -2705,11 +2902,16 @@
       //   the argument of the constructor.
       //
       QualType ThisType = Constructor->getThisType(S.Context);
-      if (Best->Conversions[0].isEllipsis())
-        User.EllipsisConversion = true;
-      else {
-        User.Before = Best->Conversions[0].Standard;
-        User.EllipsisConversion = false;
+      if (isa<InitListExpr>(From)) {
+        // Initializer lists don't have conversions as such.
+        User.Before.setAsIdentityConversion();
+      } else {
+        if (Best->Conversions[0].isEllipsis())
+          User.EllipsisConversion = true;
+        else {
+          User.Before = Best->Conversions[0].Standard;
+          User.EllipsisConversion = false;
+        }
       }
       User.HadMultipleCandidates = HadMultipleCandidates;
       User.ConversionFunction = Constructor;
@@ -2718,7 +2920,8 @@
       User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType());
       User.After.setAllToTypes(ToType);
       return OR_Success;
-    } else if (CXXConversionDecl *Conversion
+    }
+    if (CXXConversionDecl *Conversion
                  = dyn_cast<CXXConversionDecl>(Best->Function)) {
       S.MarkDeclarationReferenced(From->getLocStart(), Conversion);
 
@@ -2745,10 +2948,8 @@
       //   13.3.3.1).
       User.After = Best->FinalConversion;
       return OR_Success;
-    } else {
-      llvm_unreachable("Not a constructor or conversion function?");
-      return OR_No_Viable_Function;
     }
+    llvm_unreachable("Not a constructor or conversion function?");
 
   case OR_No_Viable_Function:
     return OR_No_Viable_Function;
@@ -2760,7 +2961,7 @@
     return OR_Ambiguous;
   }
 
-  return OR_No_Viable_Function;
+  llvm_unreachable("Invalid OverloadResult!");
 }
 
 bool
@@ -2808,7 +3009,7 @@
   //   from any other user-defined conversion sequence.
   if (ICS1.getKindRank() < ICS2.getKindRank())
     return ImplicitConversionSequence::Better;
-  else if (ICS2.getKindRank() < ICS1.getKindRank())
+  if (ICS2.getKindRank() < ICS1.getKindRank())
     return ImplicitConversionSequence::Worse;
 
   // The following checks require both conversion sequences to be of
@@ -3620,7 +3821,7 @@
     return false;
   }
 
-  return false;
+  llvm_unreachable("Invalid OverloadResult!");
 }
 
 /// \brief Compute an implicit conversion sequence for reference
@@ -3910,15 +4111,42 @@
   Result.setBad(BadConversionSequence::no_conversion, From, ToType);
   Result.setListInitializationSequence();
 
+  // We need a complete type for what follows. Incomplete types can bever be
+  // initialized from init lists.
+  if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag()))
+    return Result;
+
   // C++11 [over.ics.list]p2:
   //   If the parameter type is std::initializer_list<X> or "array of X" and
   //   all the elements can be implicitly converted to X, the implicit
   //   conversion sequence is the worst conversion necessary to convert an
   //   element of the list to X.
-  // FIXME: Recognize std::initializer_list.
-  // FIXME: Arrays don't make sense until we can deal with references.
+  QualType X;
   if (ToType->isArrayType())
+    X = S.Context.getBaseElementType(ToType);
+  else
+    (void)S.isStdInitializerList(ToType, &X);
+  if (!X.isNull()) {
+    for (unsigned i = 0, e = From->getNumInits(); i < e; ++i) {
+      Expr *Init = From->getInit(i);
+      ImplicitConversionSequence ICS =
+          TryCopyInitialization(S, Init, X, SuppressUserConversions,
+                                InOverloadResolution,
+                                AllowObjCWritebackConversion);
+      // If a single element isn't convertible, fail.
+      if (ICS.isBad()) {
+        Result = ICS;
+        break;
+      }
+      // Otherwise, look for the worst conversion.
+      if (Result.isBad() ||
+          CompareImplicitConversionSequences(S, ICS, Result) ==
+              ImplicitConversionSequence::Worse)
+        Result = ICS;
+    }
+    Result.setListInitializationSequence();
     return Result;
+  }
 
   // C++11 [over.ics.list]p3:
   //   Otherwise, if the parameter is a non-aggregate class X and overload
@@ -3926,9 +4154,15 @@
   //   conversion sequence is a user-defined conversion sequence. If multiple
   //   constructors are viable but none is better than the others, the
   //   implicit conversion sequence is a user-defined conversion sequence.
-  // FIXME: Implement this.
-  if (ToType->isRecordType() && !ToType->isAggregateType())
+  if (ToType->isRecordType() && !ToType->isAggregateType()) {
+    // This function can deal with initializer lists.
+    Result = TryUserDefinedConversion(S, From, ToType, SuppressUserConversions,
+                                      /*AllowExplicit=*/false,
+                                      InOverloadResolution, /*CStyle=*/false,
+                                      AllowObjCWritebackConversion);
+    Result.setListInitializationSequence();
     return Result;
+  }
 
   // C++11 [over.ics.list]p4:
   //   Otherwise, if the parameter has an aggregate type which can be
@@ -4029,7 +4263,6 @@
     //    - if the initializer list has one element, the implicit conversion
     //      sequence is the one required to convert the element to the
     //      parameter type.
-    // FIXME: Catch narrowing here?
     unsigned NumInits = From->getNumInits();
     if (NumInits == 1)
       Result = TryCopyInitialization(S, From->getInit(0), ToType,
@@ -4299,6 +4532,167 @@
   return ExprError();
 }
 
+/// Check that the specified conversion is permitted in a converted constant
+/// expression, according to C++11 [expr.const]p3. Return true if the conversion
+/// is acceptable.
+static bool CheckConvertedConstantConversions(Sema &S,
+                                              StandardConversionSequence &SCS) {
+  // Since we know that the target type is an integral or unscoped enumeration
+  // type, most conversion kinds are impossible. All possible First and Third
+  // conversions are fine.
+  switch (SCS.Second) {
+  case ICK_Identity:
+  case ICK_Integral_Promotion:
+  case ICK_Integral_Conversion:
+    return true;
+
+  case ICK_Boolean_Conversion:
+    // Conversion from an integral or unscoped enumeration type to bool is
+    // classified as ICK_Boolean_Conversion, but it's also an integral
+    // conversion, so it's permitted in a converted constant expression.
+    return SCS.getFromType()->isIntegralOrUnscopedEnumerationType() &&
+           SCS.getToType(2)->isBooleanType();
+
+  case ICK_Floating_Integral:
+  case ICK_Complex_Real:
+    return false;
+
+  case ICK_Lvalue_To_Rvalue:
+  case ICK_Array_To_Pointer:
+  case ICK_Function_To_Pointer:
+  case ICK_NoReturn_Adjustment:
+  case ICK_Qualification:
+  case ICK_Compatible_Conversion:
+  case ICK_Vector_Conversion:
+  case ICK_Vector_Splat:
+  case ICK_Derived_To_Base:
+  case ICK_Pointer_Conversion:
+  case ICK_Pointer_Member:
+  case ICK_Block_Pointer_Conversion:
+  case ICK_Writeback_Conversion:
+  case ICK_Floating_Promotion:
+  case ICK_Complex_Promotion:
+  case ICK_Complex_Conversion:
+  case ICK_Floating_Conversion:
+  case ICK_TransparentUnionConversion:
+    llvm_unreachable("unexpected second conversion kind");
+
+  case ICK_Num_Conversion_Kinds:
+    break;
+  }
+
+  llvm_unreachable("unknown conversion kind");
+}
+
+/// CheckConvertedConstantExpression - Check that the expression From is a
+/// converted constant expression of type T, perform the conversion and produce
+/// the converted expression, per C++11 [expr.const]p3.
+ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
+                                                  llvm::APSInt &Value,
+                                                  CCEKind CCE) {
+  assert(LangOpts.CPlusPlus0x && "converted constant expression outside C++11");
+  assert(T->isIntegralOrEnumerationType() && "unexpected converted const type");
+
+  if (checkPlaceholderForOverload(*this, From))
+    return ExprError();
+
+  // C++11 [expr.const]p3 with proposed wording fixes:
+  //  A converted constant expression of type T is a core constant expression,
+  //  implicitly converted to a prvalue of type T, where the converted
+  //  expression is a literal constant expression and the implicit conversion
+  //  sequence contains only user-defined conversions, lvalue-to-rvalue
+  //  conversions, integral promotions, and integral conversions other than
+  //  narrowing conversions.
+  ImplicitConversionSequence ICS =
+    TryImplicitConversion(From, T,
+                          /*SuppressUserConversions=*/false,
+                          /*AllowExplicit=*/false,
+                          /*InOverloadResolution=*/false,
+                          /*CStyle=*/false,
+                          /*AllowObjcWritebackConversion=*/false);
+  StandardConversionSequence *SCS = 0;
+  switch (ICS.getKind()) {
+  case ImplicitConversionSequence::StandardConversion:
+    if (!CheckConvertedConstantConversions(*this, ICS.Standard))
+      return Diag(From->getSourceRange().getBegin(),
+                  diag::err_typecheck_converted_constant_expression_disallowed)
+               << From->getType() << From->getSourceRange() << T;
+    SCS = &ICS.Standard;
+    break;
+  case ImplicitConversionSequence::UserDefinedConversion:
+    // We are converting from class type to an integral or enumeration type, so
+    // the Before sequence must be trivial.
+    if (!CheckConvertedConstantConversions(*this, ICS.UserDefined.After))
+      return Diag(From->getSourceRange().getBegin(),
+                  diag::err_typecheck_converted_constant_expression_disallowed)
+               << From->getType() << From->getSourceRange() << T;
+    SCS = &ICS.UserDefined.After;
+    break;
+  case ImplicitConversionSequence::AmbiguousConversion:
+  case ImplicitConversionSequence::BadConversion:
+    if (!DiagnoseMultipleUserDefinedConversion(From, T))
+      return Diag(From->getSourceRange().getBegin(),
+                  diag::err_typecheck_converted_constant_expression)
+                    << From->getType() << From->getSourceRange() << T;
+    return ExprError();
+
+  case ImplicitConversionSequence::EllipsisConversion:
+    llvm_unreachable("ellipsis conversion in converted constant expression");
+  }
+
+  ExprResult Result = PerformImplicitConversion(From, T, ICS, AA_Converting);
+  if (Result.isInvalid())
+    return Result;
+
+  // Check for a narrowing implicit conversion.
+  APValue PreNarrowingValue;
+  switch (SCS->getNarrowingKind(Context, Result.get(), PreNarrowingValue)) {
+  case NK_Variable_Narrowing:
+    // Implicit conversion to a narrower type, and the value is not a constant
+    // expression. We'll diagnose this in a moment.
+  case NK_Not_Narrowing:
+    break;
+
+  case NK_Constant_Narrowing:
+    Diag(From->getSourceRange().getBegin(), diag::err_cce_narrowing)
+      << CCE << /*Constant*/1
+      << PreNarrowingValue.getAsString(Context, QualType()) << T;
+    break;
+
+  case NK_Type_Narrowing:
+    Diag(From->getSourceRange().getBegin(), diag::err_cce_narrowing)
+      << CCE << /*Constant*/0 << From->getType() << T;
+    break;
+  }
+
+  // Check the expression is a constant expression.
+  llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+  Expr::EvalResult Eval;
+  Eval.Diag = &Notes;
+
+  if (!Result.get()->EvaluateAsRValue(Eval, Context)) {
+    // The expression can't be folded, so we can't keep it at this position in
+    // the AST.
+    Result = ExprError();
+  } else if (Notes.empty()) {
+    // It's a constant expression.
+    Value = Eval.Val.getInt();
+    return Result;
+  }
+
+  // It's not a constant expression. Produce an appropriate diagnostic.
+  if (Notes.size() == 1 &&
+      Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr)
+    Diag(Notes[0].first, diag::err_expr_not_cce) << CCE;
+  else {
+    Diag(From->getSourceRange().getBegin(), diag::err_expr_not_cce)
+      << CCE << From->getSourceRange();
+    for (unsigned I = 0; I < Notes.size(); ++I)
+      Diag(Notes[I].first, Notes[I].second);
+  }
+  return ExprError();
+}
+
 /// dropPointerConversions - If the given standard conversion sequence
 /// involves any pointer conversions, remove them.  This may change
 /// the result type of the conversion sequence.
@@ -4601,8 +4995,7 @@
   }
 
   // Add this candidate
-  CandidateSet.push_back(OverloadCandidate());
-  OverloadCandidate& Candidate = CandidateSet.back();
+  OverloadCandidate &Candidate = CandidateSet.addCandidate(NumArgs);
   Candidate.FoundDecl = FoundDecl;
   Candidate.Function = Function;
   Candidate.Viable = true;
@@ -4646,7 +5039,6 @@
 
   // Determine the implicit conversion sequences for each of the
   // arguments.
-  Candidate.Conversions.resize(NumArgs);
   for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
     if (ArgIdx < NumArgsInProto) {
       // (C++ 13.3.2p3): for F to be a viable function, there shall
@@ -4769,8 +5161,7 @@
   EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
 
   // Add this candidate
-  CandidateSet.push_back(OverloadCandidate());
-  OverloadCandidate& Candidate = CandidateSet.back();
+  OverloadCandidate &Candidate = CandidateSet.addCandidate(NumArgs + 1);
   Candidate.FoundDecl = FoundDecl;
   Candidate.Function = Method;
   Candidate.IsSurrogate = false;
@@ -4802,7 +5193,6 @@
   }
 
   Candidate.Viable = true;
-  Candidate.Conversions.resize(NumArgs + 1);
 
   if (Method->isStatic() || ObjectType.isNull())
     // The implicit object argument is ignored.
@@ -4879,8 +5269,7 @@
   if (TemplateDeductionResult Result
       = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs,
                                 Args, NumArgs, Specialization, Info)) {
-    CandidateSet.push_back(OverloadCandidate());
-    OverloadCandidate &Candidate = CandidateSet.back();
+    OverloadCandidate &Candidate = CandidateSet.addCandidate();
     Candidate.FoundDecl = FoundDecl;
     Candidate.Function = MethodTmpl->getTemplatedDecl();
     Candidate.Viable = false;
@@ -4930,8 +5319,7 @@
   if (TemplateDeductionResult Result
         = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
                                   Args, NumArgs, Specialization, Info)) {
-    CandidateSet.push_back(OverloadCandidate());
-    OverloadCandidate &Candidate = CandidateSet.back();
+    OverloadCandidate &Candidate = CandidateSet.addCandidate();
     Candidate.FoundDecl = FoundDecl;
     Candidate.Function = FunctionTemplate->getTemplatedDecl();
     Candidate.Viable = false;
@@ -4973,8 +5361,7 @@
   EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
 
   // Add this candidate
-  CandidateSet.push_back(OverloadCandidate());
-  OverloadCandidate& Candidate = CandidateSet.back();
+  OverloadCandidate &Candidate = CandidateSet.addCandidate(1);
   Candidate.FoundDecl = FoundDecl;
   Candidate.Function = Conversion;
   Candidate.IsSurrogate = false;
@@ -4983,7 +5370,6 @@
   Candidate.FinalConversion.setFromType(ConvType);
   Candidate.FinalConversion.setAllToTypes(ToType);
   Candidate.Viable = true;
-  Candidate.Conversions.resize(1);
   Candidate.ExplicitCallArguments = 1;
 
   // C++ [over.match.funcs]p4:
@@ -5117,8 +5503,7 @@
   if (TemplateDeductionResult Result
         = DeduceTemplateArguments(FunctionTemplate, ToType,
                                   Specialization, Info)) {
-    CandidateSet.push_back(OverloadCandidate());
-    OverloadCandidate &Candidate = CandidateSet.back();
+    OverloadCandidate &Candidate = CandidateSet.addCandidate();
     Candidate.FoundDecl = FoundDecl;
     Candidate.Function = FunctionTemplate->getTemplatedDecl();
     Candidate.Viable = false;
@@ -5156,15 +5541,13 @@
   // Overload resolution is always an unevaluated context.
   EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
 
-  CandidateSet.push_back(OverloadCandidate());
-  OverloadCandidate& Candidate = CandidateSet.back();
+  OverloadCandidate &Candidate = CandidateSet.addCandidate(NumArgs + 1);
   Candidate.FoundDecl = FoundDecl;
   Candidate.Function = 0;
   Candidate.Surrogate = Conversion;
   Candidate.Viable = true;
   Candidate.IsSurrogate = true;
   Candidate.IgnoreObjectArgument = false;
-  Candidate.Conversions.resize(NumArgs + 1);
   Candidate.ExplicitCallArguments = NumArgs;
 
   // Determine the implicit conversion sequence for the implicit
@@ -5309,8 +5692,7 @@
   EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
 
   // Add this candidate
-  CandidateSet.push_back(OverloadCandidate());
-  OverloadCandidate& Candidate = CandidateSet.back();
+  OverloadCandidate &Candidate = CandidateSet.addCandidate(NumArgs);
   Candidate.FoundDecl = DeclAccessPair::make(0, AS_none);
   Candidate.Function = 0;
   Candidate.IsSurrogate = false;
@@ -5322,7 +5704,6 @@
   // Determine the implicit conversion sequences for each of the
   // arguments.
   Candidate.Viable = true;
-  Candidate.Conversions.resize(NumArgs);
   Candidate.ExplicitCallArguments = NumArgs;
   for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
     // C++ [over.match.oper]p4:
@@ -6985,8 +7366,8 @@
   //   A viable function F1 is defined to be a better function than another
   //   viable function F2 if for all arguments i, ICSi(F1) is not a worse
   //   conversion sequence than ICSi(F2), and then...
-  unsigned NumArgs = Cand1.Conversions.size();
-  assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch");
+  unsigned NumArgs = Cand1.NumConversions;
+  assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch");
   bool HasBetterConversion = false;
   for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
     switch (CompareImplicitConversionSequences(S,
@@ -7440,9 +7821,8 @@
     << (unsigned) (Cand->Fix.Kind);
 
   // If we can fix the conversion, suggest the FixIts.
-  for (SmallVector<FixItHint, 1>::iterator
-      HI = Cand->Fix.Hints.begin(), HE = Cand->Fix.Hints.end();
-      HI != HE; ++HI)
+  for (std::vector<FixItHint>::iterator HI = Cand->Fix.Hints.begin(),
+       HE = Cand->Fix.Hints.end(); HI != HE; ++HI)
     FDiag << *HI;
   S.Diag(Fn->getLocation(), FDiag);
 
@@ -7685,7 +8065,7 @@
 
   case ovl_fail_bad_conversion: {
     unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0);
-    for (unsigned N = Cand->Conversions.size(); I != N; ++I)
+    for (unsigned N = Cand->NumConversions; I != N; ++I)
       if (Cand->Conversions[I].isBad())
         return DiagnoseBadConversion(S, Cand, I);
 
@@ -7737,12 +8117,12 @@
                                   const char *Opc,
                                   SourceLocation OpLoc,
                                   OverloadCandidate *Cand) {
-  assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary");
+  assert(Cand->NumConversions <= 2 && "builtin operator is not binary");
   std::string TypeStr("operator");
   TypeStr += Opc;
   TypeStr += "(";
   TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
-  if (Cand->Conversions.size() == 1) {
+  if (Cand->NumConversions == 1) {
     TypeStr += ")";
     S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr;
   } else {
@@ -7755,7 +8135,7 @@
 
 void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
                                   OverloadCandidate *Cand) {
-  unsigned NoOperands = Cand->Conversions.size();
+  unsigned NoOperands = Cand->NumConversions;
   for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
     const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
     if (ICS.isBad()) break; // all meaningless after first invalid
@@ -7859,11 +8239,11 @@
 
         // If there's any ordering between the defined conversions...
         // FIXME: this might not be transitive.
-        assert(L->Conversions.size() == R->Conversions.size());
+        assert(L->NumConversions == R->NumConversions);
 
         int leftBetter = 0;
         unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument);
-        for (unsigned E = L->Conversions.size(); I != E; ++I) {
+        for (unsigned E = L->NumConversions; I != E; ++I) {
           switch (CompareImplicitConversionSequences(S,
                                                      L->Conversions[I],
                                                      R->Conversions[I])) {
@@ -7926,7 +8306,7 @@
 
   // Skip forward to the first bad conversion.
   unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0);
-  unsigned ConvCount = Cand->Conversions.size();
+  unsigned ConvCount = Cand->NumConversions;
   while (true) {
     assert(ConvIdx != ConvCount && "no bad conversion in candidate");
     ConvIdx++;
@@ -8812,10 +9192,13 @@
 
   LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
                  Sema::LookupOrdinaryName);
+  CorrectionCandidateCallback Validator;
+  Validator.WantTypeSpecifiers = SemaRef.getLangOptions().CPlusPlus;
+  Validator.WantRemainingKeywords = false;
   if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R,
                               ExplicitTemplateArgs, Args, NumArgs) &&
       (!EmptyLookup ||
-       SemaRef.DiagnoseEmptyLookup(S, SS, R, Sema::CTC_Expression,
+       SemaRef.DiagnoseEmptyLookup(S, SS, R, Validator,
                                    ExplicitTemplateArgs, Args, NumArgs)))
     return ExprError();
 
@@ -8957,7 +9340,6 @@
       return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs,
                                    RParenLoc, ExecConfig);
     }
-    break;
   }
 
   // Overload resolution failed.
@@ -10355,6 +10737,7 @@
         SourceLocation Loc = MemExpr->getMemberLoc();
         if (MemExpr->getQualifier())
           Loc = MemExpr->getQualifierLoc().getBeginLoc();
+        CheckCXXThisCapture(Loc);
         Base = new (Context) CXXThisExpr(Loc,
                                          MemExpr->getBaseType(),
                                          /*isImplicit=*/true);
@@ -10385,7 +10768,6 @@
   }
 
   llvm_unreachable("Invalid reference to overloaded function");
-  return E;
 }
 
 ExprResult Sema::FixOverloadedFunctionReference(ExprResult E,

Modified: cfe/branches/tooling/lib/Sema/SemaPseudoObject.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaPseudoObject.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaPseudoObject.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaPseudoObject.cpp Fri Jan 20 10:14:22 2012
@@ -492,11 +492,9 @@
   assert(Getter);
   
   QualType receiverType;
-  SourceLocation superLoc;
   if (RefExpr->isClassReceiver()) {
     receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
   } else if (RefExpr->isSuperReceiver()) {
-    superLoc = RefExpr->getReceiverLocation();
     receiverType = RefExpr->getSuperReceiverType();
   } else {
     assert(InstanceReceiver);
@@ -507,19 +505,14 @@
   ExprResult msg;
   if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
     assert(InstanceReceiver || RefExpr->isSuperReceiver());
-    msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
-                                 Getter->getSelector(), Getter,
-                                 GenericLoc, GenericLoc, GenericLoc,
-                                 MultiExprArg());
+    msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
+                                         GenericLoc, Getter->getSelector(),
+                                         Getter, MultiExprArg());
   } else {
-    TypeSourceInfo *receiverTypeInfo = 0;
-    if (!RefExpr->isSuperReceiver())
-      receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
-
-    msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
-                              Getter->getSelector(), Getter,
-                              GenericLoc, GenericLoc, GenericLoc,
-                              MultiExprArg());
+    msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
+                                      GenericLoc,
+                                      Getter->getSelector(), Getter,
+                                      MultiExprArg());
   }
   return msg;
 }
@@ -534,11 +527,9 @@
   assert(hasSetter); (void) hasSetter;
 
   QualType receiverType;
-  SourceLocation superLoc;
   if (RefExpr->isClassReceiver()) {
     receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
   } else if (RefExpr->isSuperReceiver()) {
-    superLoc = RefExpr->getReceiverLocation();
     receiverType = RefExpr->getSuperReceiverType();
   } else {
     assert(InstanceReceiver);
@@ -570,19 +561,14 @@
   // Build a message-send.
   ExprResult msg;
   if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
-    msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
-                                 SetterSelector, Setter,
-                                 GenericLoc, GenericLoc, GenericLoc,
-                                 MultiExprArg(args, 1));
+    msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
+                                         GenericLoc, SetterSelector, Setter,
+                                         MultiExprArg(args, 1));
   } else {
-    TypeSourceInfo *receiverTypeInfo = 0;
-    if (!RefExpr->isSuperReceiver())
-      receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
-
-    msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
-                              SetterSelector, Setter,
-                              GenericLoc, GenericLoc, GenericLoc,
-                              MultiExprArg(args, 1));
+    msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
+                                      GenericLoc,
+                                      SetterSelector, Setter,
+                                      MultiExprArg(args, 1));
   }
 
   if (!msg.isInvalid() && captureSetValueAsResult) {

Modified: cfe/branches/tooling/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaStmt.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaStmt.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaStmt.cpp Fri Jan 20 10:14:22 2012
@@ -16,7 +16,6 @@
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
-#include "clang/AST/APValue.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclObjC.h"
@@ -153,7 +152,8 @@
 
   SourceLocation Loc;
   SourceRange R1, R2;
-  if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))
+  if (SourceMgr.isInSystemMacro(E->getExprLoc()) ||
+      !E->isUnusedResultAWarning(Loc, R1, R2, Context))
     return;
 
   // Okay, we have an unused result.  Depending on what the base expression is,
@@ -266,24 +266,26 @@
                     SourceLocation ColonLoc) {
   assert((LHSVal != 0) && "missing expression in case statement");
 
-  // C99 6.8.4.2p3: The expression shall be an integer constant.
-  // However, GCC allows any evaluatable integer expression.
-  if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent() &&
-      VerifyIntegerConstantExpression(LHSVal))
-    return StmtError();
-
-  // GCC extension: The expression shall be an integer constant.
-
-  if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent() &&
-      VerifyIntegerConstantExpression(RHSVal)) {
-    RHSVal = 0;  // Recover by just forgetting about it.
-  }
-
   if (getCurFunction()->SwitchStack.empty()) {
     Diag(CaseLoc, diag::err_case_not_in_switch);
     return StmtError();
   }
 
+  if (!getLangOptions().CPlusPlus0x) {
+    // C99 6.8.4.2p3: The expression shall be an integer constant.
+    // However, GCC allows any evaluatable integer expression.
+    if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent() &&
+        VerifyIntegerConstantExpression(LHSVal))
+      return StmtError();
+
+    // GCC extension: The expression shall be an integer constant.
+
+    if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent() &&
+        VerifyIntegerConstantExpression(RHSVal)) {
+      RHSVal = 0;  // Recover by just forgetting about it.
+    }
+  }
+
   CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc,
                                         ColonLoc);
   getCurFunction()->SwitchStack.back()->addSwitchCase(CS);
@@ -622,8 +624,6 @@
     } else {
       CaseStmt *CS = cast<CaseStmt>(SC);
 
-      // We already verified that the expression has a i-c-e value (C99
-      // 6.8.4.2p3) - get that value now.
       Expr *Lo = CS->getLHS();
 
       if (Lo->isTypeDependent() || Lo->isValueDependent()) {
@@ -631,19 +631,39 @@
         break;
       }
 
-      llvm::APSInt LoVal = Lo->EvaluateKnownConstInt(Context);
+      llvm::APSInt LoVal;
 
-      // Convert the value to the same width/sign as the condition.
+      if (getLangOptions().CPlusPlus0x) {
+        // C++11 [stmt.switch]p2: the constant-expression shall be a converted
+        // constant expression of the promoted type of the switch condition.
+        ExprResult ConvLo =
+          CheckConvertedConstantExpression(Lo, CondType, LoVal, CCEK_CaseValue);
+        if (ConvLo.isInvalid()) {
+          CaseListIsErroneous = true;
+          continue;
+        }
+        Lo = ConvLo.take();
+      } else {
+        // We already verified that the expression has a i-c-e value (C99
+        // 6.8.4.2p3) - get that value now.
+        LoVal = Lo->EvaluateKnownConstInt(Context);
+
+        // If the LHS is not the same type as the condition, insert an implicit
+        // cast.
+        Lo = DefaultLvalueConversion(Lo).take();
+        Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take();
+      }
+
+      // Convert the value to the same width/sign as the condition had prior to
+      // integral promotions.
+      //
+      // FIXME: This causes us to reject valid code:
+      //   switch ((char)c) { case 256: case 0: return 0; }
+      // Here we claim there is a duplicated condition value, but there is not.
       ConvertIntegerToTypeWarnOnOverflow(LoVal, CondWidth, CondIsSigned,
                                          Lo->getLocStart(),
                                          diag::warn_case_value_overflow);
 
-      // If the LHS is not the same type as the condition, insert an implicit
-      // cast.
-      // FIXME: In C++11, the value is a converted constant expression of the
-      // promoted type of the switch condition.
-      Lo = DefaultLvalueConversion(Lo).take();
-      Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take();
       CS->setLHS(Lo);
 
       // If this is a case range, remember it in CaseRanges, otherwise CaseVals.
@@ -664,20 +684,15 @@
     // condition is constant.
     llvm::APSInt ConstantCondValue;
     bool HasConstantCond = false;
-    bool ShouldCheckConstantCond = false;
     if (!HasDependentValue && !TheDefaultStmt) {
-      Expr::EvalResult Result;
       HasConstantCond
-        = CondExprBeforePromotion->EvaluateAsRValue(Result, Context);
-      if (HasConstantCond) {
-        assert(Result.Val.isInt() && "switch condition evaluated to non-int");
-        ConstantCondValue = Result.Val.getInt();
-        ShouldCheckConstantCond = true;
-
-        assert(ConstantCondValue.getBitWidth() == CondWidth &&
-               ConstantCondValue.isSigned() == CondIsSigned);
-      }
+        = CondExprBeforePromotion->EvaluateAsInt(ConstantCondValue, Context,
+                                                 Expr::SE_AllowSideEffects);
+      assert(!HasConstantCond ||
+             (ConstantCondValue.getBitWidth() == CondWidth &&
+              ConstantCondValue.isSigned() == CondIsSigned));
     }
+    bool ShouldCheckConstantCond = HasConstantCond;
 
     // Sort all the scalar case values so we can easily detect duplicates.
     std::stable_sort(CaseVals.begin(), CaseVals.end(), CmpCaseVals);
@@ -714,19 +729,33 @@
         llvm::APSInt &LoVal = CaseRanges[i].first;
         CaseStmt *CR = CaseRanges[i].second;
         Expr *Hi = CR->getRHS();
-        llvm::APSInt HiVal = Hi->EvaluateKnownConstInt(Context);
+        llvm::APSInt HiVal;
+
+        if (getLangOptions().CPlusPlus0x) {
+          // C++11 [stmt.switch]p2: the constant-expression shall be a converted
+          // constant expression of the promoted type of the switch condition.
+          ExprResult ConvHi =
+            CheckConvertedConstantExpression(Hi, CondType, HiVal,
+                                             CCEK_CaseValue);
+          if (ConvHi.isInvalid()) {
+            CaseListIsErroneous = true;
+            continue;
+          }
+          Hi = ConvHi.take();
+        } else {
+          HiVal = Hi->EvaluateKnownConstInt(Context);
+
+          // If the RHS is not the same type as the condition, insert an
+          // implicit cast.
+          Hi = DefaultLvalueConversion(Hi).take();
+          Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).take();
+        }
 
         // Convert the value to the same width/sign as the condition.
         ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned,
                                            Hi->getLocStart(),
                                            diag::warn_case_value_overflow);
 
-        // If the RHS is not the same type as the condition, insert an implicit
-        // cast.
-        // FIXME: In C++11, the value is a converted constant expression of the
-        // promoted type of the switch condition.
-        Hi = DefaultLvalueConversion(Hi).take();
-        Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).take();
         CR->setRHS(Hi);
 
         // If the low value is bigger than the high value, the case is empty.
@@ -1169,7 +1198,7 @@
   // Deduce the type for the iterator variable now rather than leaving it to
   // AddInitializerToDecl, so we can produce a more suitable diagnostic.
   TypeSourceInfo *InitTSI = 0;
-  if (Init->getType()->isVoidType() ||
+  if ((!isa<InitListExpr>(Init) && Init->getType()->isVoidType()) ||
       !SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitTSI))
     SemaRef.Diag(Loc, diag) << Init->getType();
   if (!InitTSI) {
@@ -1797,8 +1826,7 @@
   QualType FnRetType = CurBlock->ReturnType;
 
   if (CurBlock->FunctionType->getAs<FunctionType>()->getNoReturnAttr()) {
-    Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr)
-      << getCurFunctionOrMethodDecl()->getDeclName();
+    Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr);
     return StmtError();
   }
 
@@ -1875,7 +1903,7 @@
     if (FD->hasAttr<NoReturnAttr>() ||
         FD->getType()->getAs<FunctionType>()->getNoReturnAttr())
       Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
-        << getCurFunctionOrMethodDecl()->getDeclName();
+        << FD->getDeclName();
   } else if (ObjCMethodDecl *MD = getCurMethodDecl()) {
     DeclaredRetType = MD->getResultType();
     if (MD->hasRelatedResultType() && MD->getClassInterface()) {

Modified: cfe/branches/tooling/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaTemplate.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaTemplate.cpp Fri Jan 20 10:14:22 2012
@@ -249,6 +249,12 @@
     isDependent = ObjectType->isDependentType();
     assert((isDependent || !ObjectType->isIncompleteType()) &&
            "Caller should have completed object type");
+    
+    // Template names cannot appear inside an Objective-C class or object type.
+    if (ObjectType->isObjCObjectOrInterfaceType()) {
+      Found.clear();
+      return;
+    }
   } else if (SS.isSet()) {
     // This nested-name-specifier occurs after another nested-name-specifier,
     // so long into the context associated with the prior nested-name-specifier.
@@ -295,10 +301,15 @@
     // If we did not find any names, attempt to correct any typos.
     DeclarationName Name = Found.getLookupName();
     Found.clear();
+    // Simple filter callback that, for keywords, only accepts the C++ *_cast
+    CorrectionCandidateCallback FilterCCC;
+    FilterCCC.WantTypeSpecifiers = false;
+    FilterCCC.WantExpressionKeywords = false;
+    FilterCCC.WantRemainingKeywords = false;
+    FilterCCC.WantCXXNamedCasts = true;
     if (TypoCorrection Corrected = CorrectTypo(Found.getLookupNameInfo(),
                                                Found.getLookupKind(), S, &SS,
-                                               LookupCtx, false,
-                                               CTC_CXXCasts)) {
+                                               &FilterCCC, LookupCtx)) {
       Found.setLookupName(Corrected.getCorrection());
       if (Corrected.getCorrectionDecl())
         Found.addDecl(Corrected.getCorrectionDecl());
@@ -491,7 +502,6 @@
   }
 
   llvm_unreachable("Unhandled parsed template argument");
-  return TemplateArgumentLoc();
 }
 
 /// \brief Translates template arguments as provided by the parser
@@ -1013,15 +1023,8 @@
                                 NewClass, PrevClassTemplate);
   NewClass->setDescribedClassTemplate(NewTemplate);
   
-  if (PrevClassTemplate && PrevClassTemplate->isModulePrivate()) {
+  if (ModulePrivateLoc.isValid())
     NewTemplate->setModulePrivate();
-  } else if (ModulePrivateLoc.isValid()) {
-    if (PrevClassTemplate && !PrevClassTemplate->isModulePrivate())
-      diagnoseModulePrivateRedeclaration(NewTemplate, PrevClassTemplate,
-                                         ModulePrivateLoc);
-    else
-      NewTemplate->setModulePrivate();
-  }
   
   // Build the type for the class template declaration now.
   QualType T = NewTemplate->getInjectedClassNameSpecialization();
@@ -1135,7 +1138,7 @@
     // declaration (and it is a definition). Strange!
   }
 
-  return false;
+  llvm_unreachable("Invalid TemplateParamListContext!");
 }
 
 /// \brief Check for unexpanded parameter packs within the template parameters
@@ -2785,7 +2788,6 @@
 
     case TemplateArgument::Pack:
       llvm_unreachable("Caller must expand template argument packs");
-      break;
     }
 
     return false;
@@ -2835,17 +2837,12 @@
     return true;
 
   case TemplateArgument::Declaration:
-    llvm_unreachable(
-                       "Declaration argument with template template parameter");
-    break;
+    llvm_unreachable("Declaration argument with template template parameter");
   case TemplateArgument::Integral:
-    llvm_unreachable(
-                          "Integral argument with template template parameter");
-    break;
+    llvm_unreachable("Integral argument with template template parameter");
 
   case TemplateArgument::Pack:
     llvm_unreachable("Caller must expand template argument packs");
-    break;
   }
 
   return false;
@@ -3302,7 +3299,7 @@
   case NestedNameSpecifier::TypeSpecWithTemplate:
     return Visit(QualType(NNS->getAsType(), 0));
   }
-  return false;
+  llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
 }
 
 
@@ -3740,14 +3737,70 @@
   //   template-argument cannot be converted to the type of the
   //   corresponding template-parameter then the program is
   //   ill-formed.
-  //
-  //     -- for a non-type template-parameter of integral or
-  //        enumeration type, integral promotions (4.5) and integral
-  //        conversions (4.7) are applied.
   QualType ParamType = InstantiatedParamType;
   if (ParamType->isIntegralOrEnumerationType()) {
-    // FIXME: In C++11, the argument is a converted constant expression of the
-    // type of the template parameter.
+    // C++11:
+    //   -- for a non-type template-parameter of integral or
+    //      enumeration type, conversions permitted in a converted
+    //      constant expression are applied.
+    //
+    // C++98:
+    //   -- for a non-type template-parameter of integral or
+    //      enumeration type, integral promotions (4.5) and integral
+    //      conversions (4.7) are applied.
+
+    if (CTAK == CTAK_Deduced &&
+        !Context.hasSameUnqualifiedType(ParamType, Arg->getType())) {
+      // C++ [temp.deduct.type]p17:
+      //   If, in the declaration of a function template with a non-type
+      //   template-parameter, the non-type template-parameter is used
+      //   in an expression in the function parameter-list and, if the
+      //   corresponding template-argument is deduced, the
+      //   template-argument type shall match the type of the
+      //   template-parameter exactly, except that a template-argument
+      //   deduced from an array bound may be of any integral type.
+      Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
+        << Arg->getType().getUnqualifiedType()
+        << ParamType.getUnqualifiedType();
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return ExprError();
+    }
+
+    if (getLangOptions().CPlusPlus0x) {
+      // We can't check arbitrary value-dependent arguments.
+      // FIXME: If there's no viable conversion to the template parameter type,
+      // we should be able to diagnose that prior to instantiation.
+      if (Arg->isValueDependent()) {
+        Converted = TemplateArgument(Arg);
+        return Owned(Arg);
+      }
+
+      // C++ [temp.arg.nontype]p1:
+      //   A template-argument for a non-type, non-template template-parameter
+      //   shall be one of:
+      //
+      //     -- for a non-type template-parameter of integral or enumeration
+      //        type, a converted constant expression of the type of the
+      //        template-parameter; or
+      llvm::APSInt Value;
+      ExprResult ArgResult =
+        CheckConvertedConstantExpression(Arg, ParamType, Value,
+                                         CCEK_TemplateArg);
+      if (ArgResult.isInvalid())
+        return ExprError();
+
+      // Widen the argument value to sizeof(parameter type). This is almost
+      // always a no-op, except when the parameter type is bool. In
+      // that case, this may extend the argument from 1 bit to 8 bits.
+      QualType IntegerType = ParamType;
+      if (const EnumType *Enum = IntegerType->getAs<EnumType>())
+        IntegerType = Enum->getDecl()->getIntegerType();
+      Value = Value.extOrTrunc(Context.getTypeSize(IntegerType));
+
+      Converted = TemplateArgument(Value, Context.getCanonicalType(ParamType));
+      return ArgResult;
+    }
+
     ExprResult ArgResult = DefaultLvalueConversion(Arg);
     if (ArgResult.isInvalid())
       return ExprError();
@@ -3785,19 +3838,6 @@
     // Try to convert the argument to the parameter's type.
     if (Context.hasSameType(ParamType, ArgType)) {
       // Okay: no conversion necessary
-    } else if (CTAK == CTAK_Deduced) {
-      // C++ [temp.deduct.type]p17:
-      //   If, in the declaration of a function template with a non-type
-      //   template-parameter, the non-type template- parameter is used
-      //   in an expression in the function parameter-list and, if the
-      //   corresponding template-argument is deduced, the
-      //   template-argument type shall match the type of the
-      //   template-parameter exactly, except that a template-argument
-      //   deduced from an array bound may be of any integral type.
-      Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
-        << ArgType << ParamType;
-      Diag(Param->getLocation(), diag::note_template_param_here);
-      return ExprError();
     } else if (ParamType->isBooleanType()) {
       // This is an integral-to-boolean conversion.
       Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean).take();
@@ -4485,7 +4525,7 @@
 
 /// \brief Determine what kind of template specialization the given declaration
 /// is.
-static TemplateSpecializationKind getTemplateSpecializationKind(NamedDecl *D) {
+static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D) {
   if (!D)
     return TSK_Undeclared;
 
@@ -4763,23 +4803,6 @@
   return false;
 }
 
-/// \brief Retrieve the previous declaration of the given declaration.
-static NamedDecl *getPreviousDecl(NamedDecl *ND) {
-  if (VarDecl *VD = dyn_cast<VarDecl>(ND))
-    return VD->getPreviousDeclaration();
-  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
-    return FD->getPreviousDeclaration();
-  if (TagDecl *TD = dyn_cast<TagDecl>(ND))
-    return TD->getPreviousDeclaration();
-  if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(ND))
-    return TD->getPreviousDeclaration();
-  if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
-    return FTD->getPreviousDeclaration();
-  if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND))
-    return CTD->getPreviousDeclaration();
-  return 0;
-}
-
 DeclResult
 Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
                                        TagUseKind TUK,
@@ -5110,7 +5133,7 @@
   //   use occurs; no diagnostic is required.
   if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
     bool Okay = false;
-    for (NamedDecl *Prev = PrevDecl; Prev; Prev = getPreviousDecl(Prev)) {
+    for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
       // Is there any previous explicit specialization declaration?
       if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
         Okay = true;
@@ -5241,6 +5264,23 @@
   }
 }
 
+/// \brief Compute the diagnostic location for an explicit instantiation
+//  declaration or definition.
+static SourceLocation DiagLocForExplicitInstantiation(
+    NamedDecl* D, SourceLocation PointOfInstantiation) {
+  // Explicit instantiations following a specialization have no effect and
+  // hence no PointOfInstantiation. In that case, walk decl backwards
+  // until a valid name loc is found.
+  SourceLocation PrevDiagLoc = PointOfInstantiation;
+  for (Decl *Prev = D; Prev && !PrevDiagLoc.isValid();
+       Prev = Prev->getPreviousDecl()) {
+    PrevDiagLoc = Prev->getLocation();
+  }
+  assert(PrevDiagLoc.isValid() &&
+         "Explicit instantiation without point of instantiation?");
+  return PrevDiagLoc;
+}
+
 /// \brief Diagnose cases where we have an explicit template specialization
 /// before/after an explicit template instantiation, producing diagnostics
 /// for those cases where they are required and determining whether the
@@ -5307,7 +5347,7 @@
       //   before the first use of that specialization that would cause an
       //   implicit instantiation to take place, in every translation unit in
       //   which such a use occurs; no diagnostic is required.
-      for (NamedDecl *Prev = PrevDecl; Prev; Prev = getPreviousDecl(Prev)) {
+      for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
         // Is there any previous explicit specialization declaration?
         if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization)
           return false;
@@ -5320,7 +5360,6 @@
 
       return true;
     }
-    break;
 
   case TSK_ExplicitInstantiationDeclaration:
     switch (PrevTSK) {
@@ -5351,14 +5390,15 @@
       //   translation unit, the definition shall follow the declaration.
       Diag(NewLoc,
            diag::err_explicit_instantiation_declaration_after_definition);
-      Diag(PrevPointOfInstantiation,
+
+      // Explicit instantiations following a specialization have no effect and
+      // hence no PrevPointOfInstantiation. In that case, walk decl backwards
+      // until a valid name loc is found.
+      Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
            diag::note_explicit_instantiation_definition_here);
-      assert(PrevPointOfInstantiation.isValid() &&
-             "Explicit instantiation without point of instantiation?");
       HasNoEffect = true;
       return false;
     }
-    break;
 
   case TSK_ExplicitInstantiationDefinition:
     switch (PrevTSK) {
@@ -5390,6 +5430,20 @@
     case TSK_ExplicitInstantiationDeclaration:
       // We're explicity instantiating a definition for something for which we
       // were previously asked to suppress instantiations. That's fine.
+
+      // C++0x [temp.explicit]p4:
+      //   For a given set of template parameters, if an explicit instantiation
+      //   of a template appears after a declaration of an explicit
+      //   specialization for that template, the explicit instantiation has no
+      //   effect.
+      for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
+        // Is there any previous explicit specialization declaration?
+        if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
+          HasNoEffect = true;
+          break;
+        }
+      }
+
       return false;
 
     case TSK_ExplicitInstantiationDefinition:
@@ -5399,12 +5453,11 @@
       //       in a program,
       Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
         << PrevDecl;
-      Diag(PrevPointOfInstantiation,
+      Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
            diag::note_previous_explicit_instantiation);
       HasNoEffect = true;
       return false;
     }
-    break;
   }
 
   llvm_unreachable("Missing specialization/instantiation case?");
@@ -5684,7 +5737,7 @@
 
   // C++ [temp.expl.spec]p6:
   //   If a template, a member template or the member of a class template is
-  //   explicitly specialized then that spe- cialization shall be declared
+  //   explicitly specialized then that specialization shall be declared
   //   before the first use of that specialization that would cause an implicit
   //   instantiation to take place, in every translation unit in which such a
   //   use occurs; no diagnostic is required.
@@ -5973,6 +6026,9 @@
   Specialization->setExternLoc(ExternLoc);
   Specialization->setTemplateKeywordLoc(TemplateLoc);
 
+  if (Attr)
+    ProcessDeclAttributeList(S, Specialization, Attr);
+
   // Add the explicit instantiation into its lexical context. However,
   // since explicit instantiations are never found by name lookup, we
   // just put it into the declaration context directly.
@@ -6041,7 +6097,7 @@
                         KWLoc, SS, Name, NameLoc, Attr, AS_none,
                         /*ModulePrivateLoc=*/SourceLocation(),
                         MultiTemplateParamsArg(*this, 0, 0),
-                        Owned, IsDependent, false, false,
+                        Owned, IsDependent, SourceLocation(), false,
                         TypeResult());
   assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
 
@@ -6094,7 +6150,7 @@
 
   // Verify that it is okay to explicitly instantiate here.
   CXXRecordDecl *PrevDecl
-    = cast_or_null<CXXRecordDecl>(Record->getPreviousDeclaration());
+    = cast_or_null<CXXRecordDecl>(Record->getPreviousDecl());
   if (!PrevDecl && Record->getDefinition())
     PrevDecl = Record;
   if (PrevDecl) {
@@ -6369,7 +6425,7 @@
     return true;
   }
 
-  FunctionDecl *PrevDecl = Specialization->getPreviousDeclaration();
+  FunctionDecl *PrevDecl = Specialization->getPreviousDecl();
   if (!PrevDecl && Specialization->isThisDeclarationADefinition())
     PrevDecl = Specialization;
 
@@ -6389,6 +6445,9 @@
   }
 
   Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+  AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
+  if (Attr)
+    ProcessDeclAttributeList(S, Specialization, Attr);
 
   if (TSK == TSK_ExplicitInstantiationDefinition)
     InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization);

Modified: cfe/branches/tooling/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaTemplateDeduction.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaTemplateDeduction.cpp Fri Jan 20 10:14:22 2012
@@ -112,15 +112,16 @@
 
 
 static Sema::TemplateDeductionResult
-DeduceTemplateArguments(Sema &S,
-                        TemplateParameterList *TemplateParams,
-                        QualType Param,
-                        QualType Arg,
-                        TemplateDeductionInfo &Info,
-                        SmallVectorImpl<DeducedTemplateArgument> &Deduced,
-                        unsigned TDF,
-                        bool PartialOrdering = false,
-                      SmallVectorImpl<RefParamPartialOrderingComparison> *
+DeduceTemplateArgumentsByTypeMatch(Sema &S,
+                                   TemplateParameterList *TemplateParams,
+                                   QualType Param,
+                                   QualType Arg,
+                                   TemplateDeductionInfo &Info,
+                                   SmallVectorImpl<DeducedTemplateArgument> &
+                                                      Deduced,
+                                   unsigned TDF,
+                                   bool PartialOrdering = false,
+                            SmallVectorImpl<RefParamPartialOrderingComparison> *
                                                       RefParamComparisons = 0);
 
 static Sema::TemplateDeductionResult
@@ -705,12 +706,11 @@
       }
 
       if (Sema::TemplateDeductionResult Result
-            = DeduceTemplateArguments(S, TemplateParams,
-                                      Params[ParamIdx],
-                                      Args[ArgIdx],
-                                      Info, Deduced, TDF,
-                                      PartialOrdering,
-                                      RefParamComparisons))
+            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                 Params[ParamIdx], Args[ArgIdx],
+                                                 Info, Deduced, TDF,
+                                                 PartialOrdering,
+                                                 RefParamComparisons))
         return Result;
 
       ++ArgIdx;
@@ -766,9 +766,10 @@
 
       // Deduce template arguments from the pattern.
       if (Sema::TemplateDeductionResult Result
-            = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
-                                      Info, Deduced, TDF, PartialOrdering,
-                                      RefParamComparisons))
+            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern,
+                                                 Args[ArgIdx], Info, Deduced,
+                                                 TDF, PartialOrdering,
+                                                 RefParamComparisons))
         return Result;
 
       // Capture the deduced template arguments for each parameter pack expanded
@@ -858,14 +859,15 @@
 /// "success" result means that template argument deduction has not yet failed,
 /// but it may still fail, later, for other reasons.
 static Sema::TemplateDeductionResult
-DeduceTemplateArguments(Sema &S,
-                        TemplateParameterList *TemplateParams,
-                        QualType ParamIn, QualType ArgIn,
-                        TemplateDeductionInfo &Info,
-                     SmallVectorImpl<DeducedTemplateArgument> &Deduced,
-                        unsigned TDF,
-                        bool PartialOrdering,
-    SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) {
+DeduceTemplateArgumentsByTypeMatch(Sema &S,
+                                   TemplateParameterList *TemplateParams,
+                                   QualType ParamIn, QualType ArgIn,
+                                   TemplateDeductionInfo &Info,
+                            SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                                   unsigned TDF,
+                                   bool PartialOrdering,
+                            SmallVectorImpl<RefParamPartialOrderingComparison> *
+                                                          RefParamComparisons) {
   // We only want to look at the canonical types, since typedefs and
   // sugar are not part of template argument deduction.
   QualType Param = S.Context.getCanonicalType(ParamIn);
@@ -1110,17 +1112,17 @@
     //     _Complex T   [placeholder extension]  
     case Type::Complex:
       if (const ComplexType *ComplexArg = Arg->getAs<ComplexType>())
-        return DeduceTemplateArguments(S, TemplateParams, 
+        return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, 
                                     cast<ComplexType>(Param)->getElementType(), 
-                                       ComplexArg->getElementType(),
-                                       Info, Deduced, TDF);
+                                    ComplexArg->getElementType(),
+                                    Info, Deduced, TDF);
 
       return Sema::TDK_NonDeducedMismatch;
 
     //     _Atomic T   [extension]
     case Type::Atomic:
       if (const AtomicType *AtomicArg = Arg->getAs<AtomicType>())
-        return DeduceTemplateArguments(S, TemplateParams,
+        return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
                                        cast<AtomicType>(Param)->getValueType(),
                                        AtomicArg->getValueType(),
                                        Info, Deduced, TDF);
@@ -1140,8 +1142,8 @@
       }
 
       unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass);
-      return DeduceTemplateArguments(S, TemplateParams,
-                                   cast<PointerType>(Param)->getPointeeType(),
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                     cast<PointerType>(Param)->getPointeeType(),
                                      PointeeType,
                                      Info, Deduced, SubTDF);
     }
@@ -1152,10 +1154,9 @@
       if (!ReferenceArg)
         return Sema::TDK_NonDeducedMismatch;
 
-      return DeduceTemplateArguments(S, TemplateParams,
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
                            cast<LValueReferenceType>(Param)->getPointeeType(),
-                                     ReferenceArg->getPointeeType(),
-                                     Info, Deduced, 0);
+                           ReferenceArg->getPointeeType(), Info, Deduced, 0);
     }
 
     //     T && [C++0x]
@@ -1164,10 +1165,10 @@
       if (!ReferenceArg)
         return Sema::TDK_NonDeducedMismatch;
 
-      return DeduceTemplateArguments(S, TemplateParams,
-                           cast<RValueReferenceType>(Param)->getPointeeType(),
-                                     ReferenceArg->getPointeeType(),
-                                     Info, Deduced, 0);
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                             cast<RValueReferenceType>(Param)->getPointeeType(),
+                             ReferenceArg->getPointeeType(),
+                             Info, Deduced, 0);
     }
 
     //     T [] (implied, but not stated explicitly)
@@ -1178,10 +1179,10 @@
         return Sema::TDK_NonDeducedMismatch;
 
       unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
-      return DeduceTemplateArguments(S, TemplateParams,
-                     S.Context.getAsIncompleteArrayType(Param)->getElementType(),
-                                     IncompleteArrayArg->getElementType(),
-                                     Info, Deduced, SubTDF);
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                    S.Context.getAsIncompleteArrayType(Param)->getElementType(),
+                    IncompleteArrayArg->getElementType(),
+                    Info, Deduced, SubTDF);
     }
 
     //     T [integer-constant]
@@ -1197,10 +1198,10 @@
         return Sema::TDK_NonDeducedMismatch;
 
       unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
-      return DeduceTemplateArguments(S, TemplateParams,
-                                     ConstantArrayParm->getElementType(),
-                                     ConstantArrayArg->getElementType(),
-                                     Info, Deduced, SubTDF);
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                           ConstantArrayParm->getElementType(),
+                                           ConstantArrayArg->getElementType(),
+                                           Info, Deduced, SubTDF);
     }
 
     //     type [i]
@@ -1215,10 +1216,10 @@
       const DependentSizedArrayType *DependentArrayParm
         = S.Context.getAsDependentSizedArrayType(Param);
       if (Sema::TemplateDeductionResult Result
-            = DeduceTemplateArguments(S, TemplateParams,
-                                      DependentArrayParm->getElementType(),
-                                      ArrayArg->getElementType(),
-                                      Info, Deduced, SubTDF))
+            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                          DependentArrayParm->getElementType(),
+                                          ArrayArg->getElementType(),
+                                          Info, Deduced, SubTDF))
         return Result;
 
       // Determine the array bound is something we can deduce.
@@ -1272,10 +1273,10 @@
 
       // Check return types.
       if (Sema::TemplateDeductionResult Result
-            = DeduceTemplateArguments(S, TemplateParams,
-                                      FunctionProtoParam->getResultType(),
-                                      FunctionProtoArg->getResultType(),
-                                      Info, Deduced, 0))
+            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                            FunctionProtoParam->getResultType(),
+                                            FunctionProtoArg->getResultType(),
+                                            Info, Deduced, 0))
         return Result;
 
       return DeduceTemplateArguments(S, TemplateParams,
@@ -1399,17 +1400,17 @@
         return Sema::TDK_NonDeducedMismatch;
 
       if (Sema::TemplateDeductionResult Result
-            = DeduceTemplateArguments(S, TemplateParams,
-                                      MemPtrParam->getPointeeType(),
-                                      MemPtrArg->getPointeeType(),
-                                      Info, Deduced,
-                                      TDF & TDF_IgnoreQualifiers))
+            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                 MemPtrParam->getPointeeType(),
+                                                 MemPtrArg->getPointeeType(),
+                                                 Info, Deduced,
+                                                 TDF & TDF_IgnoreQualifiers))
         return Result;
 
-      return DeduceTemplateArguments(S, TemplateParams,
-                                     QualType(MemPtrParam->getClass(), 0),
-                                     QualType(MemPtrArg->getClass(), 0),
-                                     Info, Deduced, 0);
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                           QualType(MemPtrParam->getClass(), 0),
+                                           QualType(MemPtrArg->getClass(), 0),
+                                           Info, Deduced, 0);
     }
 
     //     (clang extension)
@@ -1424,10 +1425,10 @@
       if (!BlockPtrArg)
         return Sema::TDK_NonDeducedMismatch;
 
-      return DeduceTemplateArguments(S, TemplateParams,
-                                     BlockPtrParam->getPointeeType(),
-                                     BlockPtrArg->getPointeeType(), Info,
-                                     Deduced, 0);
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                BlockPtrParam->getPointeeType(),
+                                                BlockPtrArg->getPointeeType(),
+                                                Info, Deduced, 0);
     }
 
     //     (clang extension)
@@ -1441,11 +1442,10 @@
           return Sema::TDK_NonDeducedMismatch;
         
         // Perform deduction on the element types.
-        return DeduceTemplateArguments(S, TemplateParams,
-                                       VectorParam->getElementType(),
-                                       VectorArg->getElementType(),
-                                       Info, Deduced,
-                                       TDF);
+        return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                  VectorParam->getElementType(),
+                                                  VectorArg->getElementType(),
+                                                  Info, Deduced, TDF);
       }
       
       if (const DependentSizedExtVectorType *VectorArg 
@@ -1455,11 +1455,10 @@
         // ordering.
 
         // Perform deduction on the element types.
-        return DeduceTemplateArguments(S, TemplateParams,
-                                       VectorParam->getElementType(),
-                                       VectorArg->getElementType(),
-                                       Info, Deduced,
-                                       TDF);
+        return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                  VectorParam->getElementType(),
+                                                  VectorArg->getElementType(),
+                                                  Info, Deduced, TDF);
       }
       
       return Sema::TDK_NonDeducedMismatch;
@@ -1475,11 +1474,10 @@
       if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(Arg)) {
         // Perform deduction on the element types.
         if (Sema::TemplateDeductionResult Result
-              = DeduceTemplateArguments(S, TemplateParams,
-                                        VectorParam->getElementType(),
-                                        VectorArg->getElementType(),
-                                        Info, Deduced,
-                                        TDF))
+              = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                  VectorParam->getElementType(),
+                                                   VectorArg->getElementType(),
+                                                   Info, Deduced, TDF))
           return Result;
         
         // Perform deduction on the vector size, if we can.
@@ -1498,11 +1496,10 @@
                                 = dyn_cast<DependentSizedExtVectorType>(Arg)) {
         // Perform deduction on the element types.
         if (Sema::TemplateDeductionResult Result
-            = DeduceTemplateArguments(S, TemplateParams,
-                                      VectorParam->getElementType(),
-                                      VectorArg->getElementType(),
-                                      Info, Deduced,
-                                      TDF))
+            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                 VectorParam->getElementType(),
+                                                 VectorArg->getElementType(),
+                                                 Info, Deduced, TDF))
           return Result;
         
         // Perform deduction on the vector size, if we can.
@@ -1553,8 +1550,10 @@
 
   case TemplateArgument::Type:
     if (Arg.getKind() == TemplateArgument::Type)
-      return DeduceTemplateArguments(S, TemplateParams, Param.getAsType(),
-                                     Arg.getAsType(), Info, Deduced, 0);
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                Param.getAsType(),
+                                                Arg.getAsType(),
+                                                Info, Deduced, 0);
     Info.FirstArg = Param;
     Info.SecondArg = Arg;
     return Sema::TDK_NonDeducedMismatch;
@@ -2737,9 +2736,8 @@
       Deduced(TemplateParams->size());
     TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc());
     Sema::TemplateDeductionResult Result
-      = DeduceTemplateArguments(S, TemplateParams,
-                                ParamType, ArgType,
-                                Info, Deduced, TDF);
+      = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
+                                           ArgType, Info, Deduced, TDF);
     if (Result) continue;
     if (!Match.isNull()) return QualType();
     Match = ArgType;
@@ -2973,15 +2971,37 @@
       if (!hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
         continue;
 
+      // If the argument is an initializer list ...
+      if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
+        // ... then the parameter is an undeduced context, unless the parameter
+        // type is (reference to cv) std::initializer_list<P'>, in which case
+        // deduction is done for each element of the initializer list, and the
+        // result is the deduced type if it's the same for all elements.
+        QualType X;
+        // Removing references was already done.
+        if (!isStdInitializerList(ParamType, &X))
+          continue;
+
+        for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
+          if (TemplateDeductionResult Result =
+                DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, X,
+                                                   ILE->getInit(i)->getType(),
+                                                   Info, Deduced, TDF))
+            return Result;
+        }
+        // Don't track the argument type, since an initializer list has none.
+        continue;
+      }
+
       // Keep track of the argument type and corresponding parameter index,
       // so we can check for compatibility between the deduced A and A.
       OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx-1, 
                                                  ArgType));
 
       if (TemplateDeductionResult Result
-            = ::DeduceTemplateArguments(*this, TemplateParams,
-                                        ParamType, ArgType, Info, Deduced,
-                                        TDF))
+            = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
+                                                 ParamType, ArgType,
+                                                 Info, Deduced, TDF))
         return Result;
 
       continue;
@@ -3044,17 +3064,35 @@
         break;
       }
 
-      // Keep track of the argument type and corresponding argument index,
-      // so we can check for compatibility between the deduced A and A.
-      if (hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
-        OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx, 
-                                                   ArgType));
+      // As above, initializer lists need special handling.
+      if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
+        QualType X;
+        if (!isStdInitializerList(ParamType, &X)) {
+          ++ArgIdx;
+          break;
+        }
 
-      if (TemplateDeductionResult Result
-          = ::DeduceTemplateArguments(*this, TemplateParams,
-                                      ParamType, ArgType, Info, Deduced,
-                                      TDF))
-        return Result;
+        for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
+          if (TemplateDeductionResult Result =
+                DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, X,
+                                                   ILE->getInit(i)->getType(),
+                                                   Info, Deduced, TDF))
+            return Result;
+        }
+      } else {
+
+        // Keep track of the argument type and corresponding argument index,
+        // so we can check for compatibility between the deduced A and A.
+        if (hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
+          OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx, 
+                                                     ArgType));
+
+        if (TemplateDeductionResult Result
+            = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
+                                                 ParamType, ArgType, Info,
+                                                 Deduced, TDF))
+          return Result;
+      }
 
       // Capture the deduced template arguments for each parameter pack expanded
       // by this pack expansion, add them to the list of arguments we've deduced
@@ -3144,7 +3182,7 @@
   if (!ArgFunctionType.isNull()) {
     // Deduce template arguments from the function type.
     if (TemplateDeductionResult Result
-          = ::DeduceTemplateArguments(*this, TemplateParams,
+          = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
                                       FunctionType, ArgFunctionType, Info,
                                       Deduced, TDF_TopLevelParameterTypeList))
       return Result;
@@ -3255,8 +3293,8 @@
       (P->isMemberPointerType() && A->isMemberPointerType()))
     TDF |= TDF_IgnoreQualifiers;
   if (TemplateDeductionResult Result
-        = ::DeduceTemplateArguments(*this, TemplateParams,
-                                    P, A, Info, Deduced, TDF))
+        = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
+                                             P, A, Info, Deduced, TDF))
     return Result;
 
   // Finish template argument deduction.
@@ -3384,20 +3422,36 @@
     return false;
 
   TemplateDeductionInfo Info(Context, Loc);
-  if (::DeduceTemplateArguments(*this, &TemplateParams,
-                                FuncParam, InitType, Info, Deduced,
-                                TDF))
-    return false;
+
+  InitListExpr * InitList = dyn_cast<InitListExpr>(Init);
+  if (InitList) {
+    for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
+      if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
+                                             InitList->getInit(i)->getType(),
+                                             Info, Deduced, TDF))
+        return false;
+    }
+  } else {
+    if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
+                                           InitType, Info, Deduced, TDF))
+      return false;
+  }
 
   QualType DeducedType = Deduced[0].getAsType();
   if (DeducedType.isNull())
     return false;
-  
+
+  if (InitList) {
+    DeducedType = BuildStdInitializerList(DeducedType, Loc);
+    if (DeducedType.isNull())
+      return false;
+  }
+
   Result = SubstituteAutoTransform(*this, DeducedType).TransformType(Type);
-  
+
   // Check that the deduced argument type is compatible with the original
   // argument type per C++ [temp.deduct.call]p4.
-  if (Result &&
+  if (!InitList && Result &&
       CheckOriginalCallArgDeduction(*this, 
                                     Sema::OriginalCallArg(FuncParam,0,InitType),
                                     Result->getType())) {
@@ -3408,8 +3462,19 @@
   return true;
 }
 
+void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
+  if (isa<InitListExpr>(Init))
+    Diag(VDecl->getLocation(),
+         diag::err_auto_var_deduction_failure_from_init_list)
+      << VDecl->getDeclName() << VDecl->getType() << Init->getSourceRange();
+  else
+    Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
+      << VDecl->getDeclName() << VDecl->getType() << Init->getType()
+      << Init->getSourceRange();
+}
+
 static void
-MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
+MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
                            bool OnlyDeduced,
                            unsigned Level,
                            SmallVectorImpl<bool> &Deduced);
@@ -3521,19 +3586,23 @@
   case TPOC_Conversion:
     //   - In the context of a call to a conversion operator, the return types
     //     of the conversion function templates are used.
-    if (DeduceTemplateArguments(S, TemplateParams, Proto2->getResultType(),
-                                Proto1->getResultType(), Info, Deduced,
-                                TDF_None, /*PartialOrdering=*/true,
-                                RefParamComparisons))
+    if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                           Proto2->getResultType(),
+                                           Proto1->getResultType(),
+                                           Info, Deduced, TDF_None,
+                                           /*PartialOrdering=*/true,
+                                           RefParamComparisons))
       return false;
     break;
 
   case TPOC_Other:
     //   - In other contexts (14.6.6.2) the function template's function type
     //     is used.
-    if (DeduceTemplateArguments(S, TemplateParams, FD2->getType(),
-                                FD1->getType(), Info, Deduced, TDF_None,
-                                /*PartialOrdering=*/true, RefParamComparisons))
+    if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                           FD2->getType(), FD1->getType(),
+                                           Info, Deduced, TDF_None,
+                                           /*PartialOrdering=*/true,
+                                           RefParamComparisons))
       return false;
     break;
   }
@@ -3564,23 +3633,24 @@
                                   std::min(Proto1->getNumArgs(),
                                            Proto2->getNumArgs()));
     if (S.getLangOptions().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1)
-      ::MarkUsedTemplateParameters(S, Method2->getThisType(S.Context), false,
+      ::MarkUsedTemplateParameters(S.Context, Method2->getThisType(S.Context),
+                                   false,
                                    TemplateParams->getDepth(), UsedParameters);
     for (unsigned I = Skip2; I < NumParams; ++I)
-      ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false,
+      ::MarkUsedTemplateParameters(S.Context, Proto2->getArgType(I), false,
                                    TemplateParams->getDepth(),
                                    UsedParameters);
     break;
   }
 
   case TPOC_Conversion:
-    ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false,
+    ::MarkUsedTemplateParameters(S.Context, Proto2->getResultType(), false,
                                  TemplateParams->getDepth(),
                                  UsedParameters);
     break;
 
   case TPOC_Other:
-    ::MarkUsedTemplateParameters(S, FD2->getType(), false,
+    ::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
                                  TemplateParams->getDepth(),
                                  UsedParameters);
     break;
@@ -3899,7 +3969,8 @@
 
   // Determine whether PS1 is at least as specialized as PS2
   Deduced.resize(PS2->getTemplateParameters()->size());
-  bool Better1 = !::DeduceTemplateArguments(*this, PS2->getTemplateParameters(),
+  bool Better1 = !DeduceTemplateArgumentsByTypeMatch(*this,
+                                            PS2->getTemplateParameters(),
                                             PT2, PT1, Info, Deduced, TDF_None,
                                             /*PartialOrdering=*/true,
                                             /*RefParamComparisons=*/0);
@@ -3914,7 +3985,8 @@
   // Determine whether PS2 is at least as specialized as PS1
   Deduced.clear();
   Deduced.resize(PS1->getTemplateParameters()->size());
-  bool Better2 = !::DeduceTemplateArguments(*this, PS1->getTemplateParameters(),
+  bool Better2 = !DeduceTemplateArgumentsByTypeMatch(*this,
+                                            PS1->getTemplateParameters(),
                                             PT1, PT2, Info, Deduced, TDF_None,
                                             /*PartialOrdering=*/true,
                                             /*RefParamComparisons=*/0);
@@ -3933,7 +4005,7 @@
 }
 
 static void
-MarkUsedTemplateParameters(Sema &SemaRef,
+MarkUsedTemplateParameters(ASTContext &Ctx,
                            const TemplateArgument &TemplateArg,
                            bool OnlyDeduced,
                            unsigned Depth,
@@ -3942,7 +4014,7 @@
 /// \brief Mark the template parameters that are used by the given
 /// expression.
 static void
-MarkUsedTemplateParameters(Sema &SemaRef,
+MarkUsedTemplateParameters(ASTContext &Ctx,
                            const Expr *E,
                            bool OnlyDeduced,
                            unsigned Depth,
@@ -3973,7 +4045,7 @@
 /// \brief Mark the template parameters that are used by the given
 /// nested name specifier.
 static void
-MarkUsedTemplateParameters(Sema &SemaRef,
+MarkUsedTemplateParameters(ASTContext &Ctx,
                            NestedNameSpecifier *NNS,
                            bool OnlyDeduced,
                            unsigned Depth,
@@ -3981,16 +4053,16 @@
   if (!NNS)
     return;
 
-  MarkUsedTemplateParameters(SemaRef, NNS->getPrefix(), OnlyDeduced, Depth,
+  MarkUsedTemplateParameters(Ctx, NNS->getPrefix(), OnlyDeduced, Depth,
                              Used);
-  MarkUsedTemplateParameters(SemaRef, QualType(NNS->getAsType(), 0),
+  MarkUsedTemplateParameters(Ctx, QualType(NNS->getAsType(), 0),
                              OnlyDeduced, Depth, Used);
 }
 
 /// \brief Mark the template parameters that are used by the given
 /// template name.
 static void
-MarkUsedTemplateParameters(Sema &SemaRef,
+MarkUsedTemplateParameters(ASTContext &Ctx,
                            TemplateName Name,
                            bool OnlyDeduced,
                            unsigned Depth,
@@ -4005,17 +4077,17 @@
   }
 
   if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName())
-    MarkUsedTemplateParameters(SemaRef, QTN->getQualifier(), OnlyDeduced,
+    MarkUsedTemplateParameters(Ctx, QTN->getQualifier(), OnlyDeduced,
                                Depth, Used);
   if (DependentTemplateName *DTN = Name.getAsDependentTemplateName())
-    MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced,
+    MarkUsedTemplateParameters(Ctx, DTN->getQualifier(), OnlyDeduced,
                                Depth, Used);
 }
 
 /// \brief Mark the template parameters that are used by the given
 /// type.
 static void
-MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
+MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
                            bool OnlyDeduced,
                            unsigned Depth,
                            SmallVectorImpl<bool> &Used) {
@@ -4026,10 +4098,10 @@
   if (!T->isDependentType())
     return;
 
-  T = SemaRef.Context.getCanonicalType(T);
+  T = Ctx.getCanonicalType(T);
   switch (T->getTypeClass()) {
   case Type::Pointer:
-    MarkUsedTemplateParameters(SemaRef,
+    MarkUsedTemplateParameters(Ctx,
                                cast<PointerType>(T)->getPointeeType(),
                                OnlyDeduced,
                                Depth,
@@ -4037,7 +4109,7 @@
     break;
 
   case Type::BlockPointer:
-    MarkUsedTemplateParameters(SemaRef,
+    MarkUsedTemplateParameters(Ctx,
                                cast<BlockPointerType>(T)->getPointeeType(),
                                OnlyDeduced,
                                Depth,
@@ -4046,7 +4118,7 @@
 
   case Type::LValueReference:
   case Type::RValueReference:
-    MarkUsedTemplateParameters(SemaRef,
+    MarkUsedTemplateParameters(Ctx,
                                cast<ReferenceType>(T)->getPointeeType(),
                                OnlyDeduced,
                                Depth,
@@ -4055,29 +4127,29 @@
 
   case Type::MemberPointer: {
     const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr());
-    MarkUsedTemplateParameters(SemaRef, MemPtr->getPointeeType(), OnlyDeduced,
+    MarkUsedTemplateParameters(Ctx, MemPtr->getPointeeType(), OnlyDeduced,
                                Depth, Used);
-    MarkUsedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0),
+    MarkUsedTemplateParameters(Ctx, QualType(MemPtr->getClass(), 0),
                                OnlyDeduced, Depth, Used);
     break;
   }
 
   case Type::DependentSizedArray:
-    MarkUsedTemplateParameters(SemaRef,
+    MarkUsedTemplateParameters(Ctx,
                                cast<DependentSizedArrayType>(T)->getSizeExpr(),
                                OnlyDeduced, Depth, Used);
     // Fall through to check the element type
 
   case Type::ConstantArray:
   case Type::IncompleteArray:
-    MarkUsedTemplateParameters(SemaRef,
+    MarkUsedTemplateParameters(Ctx,
                                cast<ArrayType>(T)->getElementType(),
                                OnlyDeduced, Depth, Used);
     break;
 
   case Type::Vector:
   case Type::ExtVector:
-    MarkUsedTemplateParameters(SemaRef,
+    MarkUsedTemplateParameters(Ctx,
                                cast<VectorType>(T)->getElementType(),
                                OnlyDeduced, Depth, Used);
     break;
@@ -4085,19 +4157,19 @@
   case Type::DependentSizedExtVector: {
     const DependentSizedExtVectorType *VecType
       = cast<DependentSizedExtVectorType>(T);
-    MarkUsedTemplateParameters(SemaRef, VecType->getElementType(), OnlyDeduced,
+    MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced,
                                Depth, Used);
-    MarkUsedTemplateParameters(SemaRef, VecType->getSizeExpr(), OnlyDeduced,
+    MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced,
                                Depth, Used);
     break;
   }
 
   case Type::FunctionProto: {
     const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
-    MarkUsedTemplateParameters(SemaRef, Proto->getResultType(), OnlyDeduced,
+    MarkUsedTemplateParameters(Ctx, Proto->getResultType(), OnlyDeduced,
                                Depth, Used);
     for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
-      MarkUsedTemplateParameters(SemaRef, Proto->getArgType(I), OnlyDeduced,
+      MarkUsedTemplateParameters(Ctx, Proto->getArgType(I), OnlyDeduced,
                                  Depth, Used);
     break;
   }
@@ -4112,10 +4184,10 @@
   case Type::SubstTemplateTypeParmPack: {
     const SubstTemplateTypeParmPackType *Subst
       = cast<SubstTemplateTypeParmPackType>(T);
-    MarkUsedTemplateParameters(SemaRef,
+    MarkUsedTemplateParameters(Ctx,
                                QualType(Subst->getReplacedParameter(), 0),
                                OnlyDeduced, Depth, Used);
-    MarkUsedTemplateParameters(SemaRef, Subst->getArgumentPack(),
+    MarkUsedTemplateParameters(Ctx, Subst->getArgumentPack(),
                                OnlyDeduced, Depth, Used);
     break;
   }
@@ -4127,7 +4199,7 @@
   case Type::TemplateSpecialization: {
     const TemplateSpecializationType *Spec
       = cast<TemplateSpecializationType>(T);
-    MarkUsedTemplateParameters(SemaRef, Spec->getTemplateName(), OnlyDeduced,
+    MarkUsedTemplateParameters(Ctx, Spec->getTemplateName(), OnlyDeduced,
                                Depth, Used);
 
     // C++0x [temp.deduct.type]p9:
@@ -4139,28 +4211,28 @@
       break;
 
     for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
-      MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth,
+      MarkUsedTemplateParameters(Ctx, Spec->getArg(I), OnlyDeduced, Depth,
                                  Used);
     break;
   }
 
   case Type::Complex:
     if (!OnlyDeduced)
-      MarkUsedTemplateParameters(SemaRef,
+      MarkUsedTemplateParameters(Ctx,
                                  cast<ComplexType>(T)->getElementType(),
                                  OnlyDeduced, Depth, Used);
     break;
 
   case Type::Atomic:
     if (!OnlyDeduced)
-      MarkUsedTemplateParameters(SemaRef,
+      MarkUsedTemplateParameters(Ctx,
                                  cast<AtomicType>(T)->getValueType(),
                                  OnlyDeduced, Depth, Used);
     break;
 
   case Type::DependentName:
     if (!OnlyDeduced)
-      MarkUsedTemplateParameters(SemaRef,
+      MarkUsedTemplateParameters(Ctx,
                                  cast<DependentNameType>(T)->getQualifier(),
                                  OnlyDeduced, Depth, Used);
     break;
@@ -4169,7 +4241,7 @@
     const DependentTemplateSpecializationType *Spec
       = cast<DependentTemplateSpecializationType>(T);
     if (!OnlyDeduced)
-      MarkUsedTemplateParameters(SemaRef, Spec->getQualifier(),
+      MarkUsedTemplateParameters(Ctx, Spec->getQualifier(),
                                  OnlyDeduced, Depth, Used);
 
     // C++0x [temp.deduct.type]p9:
@@ -4181,47 +4253,47 @@
       break;
 
     for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
-      MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth,
+      MarkUsedTemplateParameters(Ctx, Spec->getArg(I), OnlyDeduced, Depth,
                                  Used);
     break;
   }
 
   case Type::TypeOf:
     if (!OnlyDeduced)
-      MarkUsedTemplateParameters(SemaRef,
+      MarkUsedTemplateParameters(Ctx,
                                  cast<TypeOfType>(T)->getUnderlyingType(),
                                  OnlyDeduced, Depth, Used);
     break;
 
   case Type::TypeOfExpr:
     if (!OnlyDeduced)
-      MarkUsedTemplateParameters(SemaRef,
+      MarkUsedTemplateParameters(Ctx,
                                  cast<TypeOfExprType>(T)->getUnderlyingExpr(),
                                  OnlyDeduced, Depth, Used);
     break;
 
   case Type::Decltype:
     if (!OnlyDeduced)
-      MarkUsedTemplateParameters(SemaRef,
+      MarkUsedTemplateParameters(Ctx,
                                  cast<DecltypeType>(T)->getUnderlyingExpr(),
                                  OnlyDeduced, Depth, Used);
     break;
 
   case Type::UnaryTransform:
     if (!OnlyDeduced)
-      MarkUsedTemplateParameters(SemaRef,
+      MarkUsedTemplateParameters(Ctx,
                                cast<UnaryTransformType>(T)->getUnderlyingType(),
                                  OnlyDeduced, Depth, Used);
     break;
 
   case Type::PackExpansion:
-    MarkUsedTemplateParameters(SemaRef,
+    MarkUsedTemplateParameters(Ctx,
                                cast<PackExpansionType>(T)->getPattern(),
                                OnlyDeduced, Depth, Used);
     break;
 
   case Type::Auto:
-    MarkUsedTemplateParameters(SemaRef,
+    MarkUsedTemplateParameters(Ctx,
                                cast<AutoType>(T)->getDeducedType(),
                                OnlyDeduced, Depth, Used);
 
@@ -4247,7 +4319,7 @@
 /// \brief Mark the template parameters that are used by this
 /// template argument.
 static void
-MarkUsedTemplateParameters(Sema &SemaRef,
+MarkUsedTemplateParameters(ASTContext &Ctx,
                            const TemplateArgument &TemplateArg,
                            bool OnlyDeduced,
                            unsigned Depth,
@@ -4259,19 +4331,19 @@
     break;
 
   case TemplateArgument::Type:
-    MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsType(), OnlyDeduced,
+    MarkUsedTemplateParameters(Ctx, TemplateArg.getAsType(), OnlyDeduced,
                                Depth, Used);
     break;
 
   case TemplateArgument::Template:
   case TemplateArgument::TemplateExpansion:
-    MarkUsedTemplateParameters(SemaRef,
+    MarkUsedTemplateParameters(Ctx,
                                TemplateArg.getAsTemplateOrTemplatePattern(),
                                OnlyDeduced, Depth, Used);
     break;
 
   case TemplateArgument::Expression:
-    MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsExpr(), OnlyDeduced,
+    MarkUsedTemplateParameters(Ctx, TemplateArg.getAsExpr(), OnlyDeduced,
                                Depth, Used);
     break;
 
@@ -4279,7 +4351,7 @@
     for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(),
                                       PEnd = TemplateArg.pack_end();
          P != PEnd; ++P)
-      MarkUsedTemplateParameters(SemaRef, *P, OnlyDeduced, Depth, Used);
+      MarkUsedTemplateParameters(Ctx, *P, OnlyDeduced, Depth, Used);
     break;
   }
 }
@@ -4306,14 +4378,15 @@
     return;
 
   for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
-    ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced,
+    ::MarkUsedTemplateParameters(Context, TemplateArgs[I], OnlyDeduced,
                                  Depth, Used);
 }
 
 /// \brief Marks all of the template parameters that will be deduced by a
 /// call to the given function template.
 void
-Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate,
+Sema::MarkDeducedTemplateParameters(ASTContext &Ctx,
+                                    FunctionTemplateDecl *FunctionTemplate,
                                     SmallVectorImpl<bool> &Deduced) {
   TemplateParameterList *TemplateParams
     = FunctionTemplate->getTemplateParameters();
@@ -4322,7 +4395,7 @@
 
   FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
   for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I)
-    ::MarkUsedTemplateParameters(*this, Function->getParamDecl(I)->getType(),
+    ::MarkUsedTemplateParameters(Ctx, Function->getParamDecl(I)->getType(),
                                  true, TemplateParams->getDepth(), Deduced);
 }
 
@@ -4336,7 +4409,7 @@
     = FunctionTemplate->getTemplateParameters();
   SmallVector<bool, 4> Deduced;
   Deduced.resize(TemplateParams->size());
-  ::MarkUsedTemplateParameters(S, T, true, TemplateParams->getDepth(), 
+  ::MarkUsedTemplateParameters(S.Context, T, true, TemplateParams->getDepth(), 
                                Deduced);
 
   for (unsigned I = 0, N = Deduced.size(); I != N; ++I)

Modified: cfe/branches/tooling/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaTemplateInstantiate.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaTemplateInstantiate.cpp Fri Jan 20 10:14:22 2012
@@ -163,8 +163,8 @@
   case DefaultTemplateArgumentChecking:
     return false;
   }
-  
-  return true;
+
+  llvm_unreachable("Invalid InstantiationKind!");
 }
 
 Sema::InstantiatingTemplate::
@@ -1709,6 +1709,13 @@
         << Context.getTypeDeclType(Instantiation);
       Diag(Pattern->getLocation(), diag::note_template_decl_here);
     }
+
+    // In general, Instantiation isn't marked invalid to get more than one
+    // error for multiple undefined instantiations. But the code that does
+    // explicit declaration -> explicit definition conversion can't handle
+    // invalid declarations, so mark as invalid in that case.
+    if (TSK == TSK_ExplicitInstantiationDeclaration)
+       Instantiation->setInvalidDecl();
     return true;
   }
   Pattern = PatternDef;
@@ -1719,7 +1726,7 @@
     MSInfo->setTemplateSpecializationKind(TSK);
     MSInfo->setPointOfInstantiation(PointOfInstantiation);
   } else if (ClassTemplateSpecializationDecl *Spec 
-               = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
+        = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
     Spec->setTemplateSpecializationKind(TSK);
     Spec->setPointOfInstantiation(PointOfInstantiation);
   }
@@ -1888,7 +1895,8 @@
       
       // If this is an explicit instantiation definition, mark the
       // vtable as used.
-      if (TSK == TSK_ExplicitInstantiationDefinition)
+      if (TSK == TSK_ExplicitInstantiationDefinition &&
+          !ClassTemplateSpec->isInvalidDecl())
         MarkVTableUsed(PointOfInstantiation, ClassTemplateSpec, true);
 
       return false;
@@ -2122,7 +2130,7 @@
       // Always skip the injected-class-name, along with any
       // redeclarations of nested classes, since both would cause us
       // to try to instantiate the members of a class twice.
-      if (Record->isInjectedClassName() || Record->getPreviousDeclaration())
+      if (Record->isInjectedClassName() || Record->getPreviousDecl())
         continue;
       
       MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo();
@@ -2289,7 +2297,7 @@
       // If this is a tag declaration, it's possible that we need to look for
       // a previous declaration.
       if (const TagDecl *Tag = dyn_cast<TagDecl>(CheckD))
-        CheckD = Tag->getPreviousDeclaration();
+        CheckD = Tag->getPreviousDecl();
       else
         CheckD = 0;
     } while (CheckD);

Modified: cfe/branches/tooling/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Jan 20 10:14:22 2012
@@ -66,17 +66,16 @@
     // FIXME: This should be generalized to more than just the AlignedAttr.
     if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
       if (Aligned->isAlignmentDependent()) {
-        // The alignment expression is not potentially evaluated.
-        EnterExpressionEvaluationContext Unevaluated(*this,
-                                                     Sema::Unevaluated);
-
         if (Aligned->isAlignmentExpr()) {
+          // The alignment expression is a constant expression.
+          EnterExpressionEvaluationContext Unevaluated(*this,
+                                                       Sema::ConstantEvaluated);
+
           ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
                                         TemplateArgs);
           if (!Result.isInvalid())
             AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>());
-        }
-        else {
+        } else {
           TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(),
                                              TemplateArgs,
                                              Aligned->getLocation(),
@@ -164,13 +163,18 @@
     }
   }
 
-  if (TypedefNameDecl *Prev = D->getPreviousDeclaration()) {
+  if (TypedefNameDecl *Prev = D->getPreviousDecl()) {
     NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev,
                                                        TemplateArgs);
     if (!InstPrev)
       return 0;
 
-    Typedef->setPreviousDeclaration(cast<TypedefNameDecl>(InstPrev));
+    TypedefNameDecl *InstPrevTypedef = cast<TypedefNameDecl>(InstPrev);
+
+    // If the typedef types are not identical, reject them.
+    SemaRef.isIncompatibleTypedef(InstPrevTypedef, Typedef);
+
+    Typedef->setPreviousDeclaration(InstPrevTypedef);
   }
 
   SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef);
@@ -206,7 +210,7 @@
   TypeAliasDecl *Pattern = D->getTemplatedDecl();
 
   TypeAliasTemplateDecl *PrevAliasTemplate = 0;
-  if (Pattern->getPreviousDeclaration()) {
+  if (Pattern->getPreviousDecl()) {
     DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
     if (Found.first != Found.second) {
       PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(*Found.first);
@@ -326,6 +330,7 @@
   Var->setThreadSpecified(D->isThreadSpecified());
   Var->setCXXDirectInitializer(D->hasCXXDirectInitializer());
   Var->setCXXForRangeDecl(D->isCXXForRangeDecl());
+  Var->setConstexpr(D->isConstexpr());
 
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(D, Var))
@@ -360,8 +365,7 @@
   SemaRef.CheckVariableDeclaration(Var, Previous);
 
   if (D->isOutOfLine()) {
-    if (!D->isStaticDataMember())
-      D->getLexicalDeclContext()->addDecl(Var);
+    D->getLexicalDeclContext()->addDecl(Var);
     Owner->makeDeclVisibleInContext(Var);
   } else {
     Owner->addDecl(Var);
@@ -380,7 +384,7 @@
     // We already have an initializer in the class.
   } else if (D->getInit()) {
     if (Var->isStaticDataMember() && !D->isOutOfLine())
-      SemaRef.PushExpressionEvaluationContext(Sema::Unevaluated);
+      SemaRef.PushExpressionEvaluationContext(Sema::ConstantEvaluated);
     else
       SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
 
@@ -390,16 +394,15 @@
     if (!SemaRef.InstantiateInitializer(D->getInit(), TemplateArgs, LParenLoc,
                                         InitArgs, RParenLoc)) {
       bool TypeMayContainAuto = true;
-      // Attach the initializer to the declaration, if we have one.
-      if (InitArgs.size() == 0)
-        SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto);
-      else if (D->hasCXXDirectInitializer()) {
+      if (D->hasCXXDirectInitializer()) {
         // Add the direct initializer to the declaration.
         SemaRef.AddCXXDirectInitializerToDecl(Var,
                                               LParenLoc,
                                               move_arg(InitArgs),
                                               RParenLoc,
                                               TypeMayContainAuto);
+      } else if (InitArgs.size() == 0) {
+        SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto);
       } else {
         assert(InitArgs.size() == 1);
         Expr *Init = InitArgs.take()[0];
@@ -462,8 +465,9 @@
   if (Invalid)
     BitWidth = 0;
   else if (BitWidth) {
-    // The bit-width expression is not potentially evaluated.
-    EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+    // The bit-width expression is a constant expression.
+    EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                                 Sema::ConstantEvaluated);
 
     ExprResult InstantiatedBitWidth
       = SemaRef.SubstExpr(BitWidth, TemplateArgs);
@@ -591,8 +595,9 @@
 Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
   Expr *AssertExpr = D->getAssertExpr();
 
-  // The expression in a static assertion is not potentially evaluated.
-  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+  // The expression in a static assertion is a constant expression.
+  EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                               Sema::ConstantEvaluated);
 
   ExprResult InstantiatedAssertExpr
     = SemaRef.SubstExpr(AssertExpr, TemplateArgs);
@@ -653,9 +658,9 @@
     // The specified value for the enumerator.
     ExprResult Value = SemaRef.Owned((Expr *)0);
     if (Expr *UninstValue = EC->getInitExpr()) {
-      // The enumerator's value expression is not potentially evaluated.
+      // The enumerator's value expression is a constant expression.
       EnterExpressionEvaluationContext Unevaluated(SemaRef,
-                                                   Sema::Unevaluated);
+                                                   Sema::ConstantEvaluated);
 
       Value = SemaRef.SubstExpr(UninstValue, TemplateArgs);
     }
@@ -735,7 +740,7 @@
   CXXRecordDecl *PrevDecl = 0;
   ClassTemplateDecl *PrevClassTemplate = 0;
 
-  if (!isFriend && Pattern->getPreviousDeclaration()) {
+  if (!isFriend && Pattern->getPreviousDecl()) {
     DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
     if (Found.first != Found.second) {
       PrevClassTemplate = dyn_cast<ClassTemplateDecl>(*Found.first);
@@ -972,9 +977,9 @@
   CXXRecordDecl *PrevDecl = 0;
   if (D->isInjectedClassName())
     PrevDecl = cast<CXXRecordDecl>(Owner);
-  else if (D->getPreviousDeclaration()) {
+  else if (D->getPreviousDecl()) {
     NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(),
-                                                   D->getPreviousDeclaration(),
+                                                   D->getPreviousDecl(),
                                                    TemplateArgs);
     if (!Prev) return 0;
     PrevDecl = cast<CXXRecordDecl>(Prev);
@@ -1234,9 +1239,9 @@
   if (isFriend) {
     NamedDecl *PrevDecl;
     if (TemplateParams)
-      PrevDecl = FunctionTemplate->getPreviousDeclaration();
+      PrevDecl = FunctionTemplate->getPreviousDecl();
     else
-      PrevDecl = Function->getPreviousDeclaration();
+      PrevDecl = Function->getPreviousDecl();
 
     PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0);
     DC->makeDeclVisibleInContext(PrincipalDecl, /*Recoverable=*/ false);
@@ -2321,11 +2326,12 @@
     }
     Expr *NoexceptExpr = 0;
     if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
-      EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+      EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                                   Sema::ConstantEvaluated);
       ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
       if (E.isUsable())
         E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());
-    
+
       if (E.isUsable()) {
         SourceLocation ErrLoc;
         llvm::APSInt NoexceptVal;
@@ -3335,12 +3341,12 @@
 
     // Don't try to instantiate declarations if the most recent redeclaration
     // is invalid.
-    if (Var->getMostRecentDeclaration()->isInvalidDecl())
+    if (Var->getMostRecentDecl()->isInvalidDecl())
       continue;
 
     // Check if the most recent declaration has changed the specialization kind
     // and removed the need for implicit instantiation.
-    switch (Var->getMostRecentDeclaration()->getTemplateSpecializationKind()) {
+    switch (Var->getMostRecentDecl()->getTemplateSpecializationKind()) {
     case TSK_Undeclared:
       llvm_unreachable("Cannot instantitiate an undeclared specialization.");
     case TSK_ExplicitInstantiationDeclaration:
@@ -3349,7 +3355,7 @@
     case TSK_ExplicitInstantiationDefinition:
       // We only need an instantiation if the pending instantiation *is* the
       // explicit instantiation.
-      if (Var != Var->getMostRecentDeclaration()) continue;
+      if (Var != Var->getMostRecentDecl()) continue;
     case TSK_ImplicitInstantiation:
       break;
     }

Modified: cfe/branches/tooling/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaTemplateVariadic.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaTemplateVariadic.cpp Fri Jan 20 10:14:22 2012
@@ -708,6 +708,19 @@
   return false;
 }
 
+namespace {
+
+// Callback to only accept typo corrections that refer to parameter packs.
+class ParameterPackValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    NamedDecl *ND = candidate.getCorrectionDecl();
+    return ND && ND->isParameterPack();
+  }
+};
+
+}
+
 /// \brief Called when an expression computing the size of a parameter pack
 /// is parsed.
 ///
@@ -733,6 +746,7 @@
   LookupName(R, S);
   
   NamedDecl *ParameterPack = 0;
+  ParameterPackValidatorCCC Validator;
   switch (R.getResultKind()) {
   case LookupResult::Found:
     ParameterPack = R.getFoundDecl();
@@ -741,19 +755,16 @@
   case LookupResult::NotFound:
   case LookupResult::NotFoundInCurrentInstantiation:
     if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
-                                               R.getLookupKind(), S, 0, 0,
-                                               false, CTC_NoKeywords)) {
-      if (NamedDecl *CorrectedResult = Corrected.getCorrectionDecl())
-        if (CorrectedResult->isParameterPack()) {
-          std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
-          ParameterPack = CorrectedResult;
-          Diag(NameLoc, diag::err_sizeof_pack_no_pack_name_suggest)
-            << &Name << CorrectedQuotedStr
-            << FixItHint::CreateReplacement(
-                NameLoc, Corrected.getAsString(getLangOptions()));
-          Diag(ParameterPack->getLocation(), diag::note_parameter_pack_here)
-            << CorrectedQuotedStr;
-        }
+                                               R.getLookupKind(), S, 0,
+                                               &Validator)) {
+      std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
+      ParameterPack = Corrected.getCorrectionDecl();
+      Diag(NameLoc, diag::err_sizeof_pack_no_pack_name_suggest)
+        << &Name << CorrectedQuotedStr
+        << FixItHint::CreateReplacement(
+            NameLoc, Corrected.getAsString(getLangOptions()));
+      Diag(ParameterPack->getLocation(), diag::note_parameter_pack_here)
+        << CorrectedQuotedStr;
     }
       
   case LookupResult::FoundOverloaded:

Modified: cfe/branches/tooling/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/SemaType.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/SemaType.cpp (original)
+++ cfe/branches/tooling/lib/Sema/SemaType.cpp Fri Jan 20 10:14:22 2012
@@ -27,6 +27,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Lookup.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/Support/ErrorHandling.h"
 using namespace clang;
@@ -639,7 +640,10 @@
     
     // If this is a missing declspec in a block literal return context, then it
     // is inferred from the return statements inside the block.
-    if (isOmittedBlockReturnType(declarator)) {
+    // The declspec is always missing in a lambda expr context; it is either
+    // specified with a trailing return type or inferred.
+    if (declarator.getContext() == Declarator::LambdaExprContext ||
+        isOmittedBlockReturnType(declarator)) {
       Result = Context.DependentTy;
       break;
     }
@@ -1053,10 +1057,11 @@
   } else if (type->isObjCARCImplicitlyUnretainedType()) {
     implicitLifetime = Qualifiers::OCL_ExplicitNone;
 
-  // If we are in an unevaluated context, like sizeof, assume ExplicitNone and
-  // don't give error.
-  } else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated) {
-    implicitLifetime = Qualifiers::OCL_ExplicitNone;
+  // If we are in an unevaluated context, like sizeof, skip adding a
+  // qualification.
+  } else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated ||
+             S.ExprEvalContexts.back().Context == Sema::ConstantEvaluated) {
+    return type;
 
   // If that failed, give an error and recover using __autoreleasing.
   } else {
@@ -1179,13 +1184,9 @@
     
   // If we're in a GNU mode (like gnu99, but not c99) accept any evaluatable
   // value as an extension.
-  Expr::EvalResult Result;
-  if (S.LangOpts.GNUMode && ArraySize->EvaluateAsRValue(Result, S.Context)) {
-    if (!Result.hasSideEffects() && Result.Val.isInt()) {
-      SizeVal = Result.Val.getInt();
-      S.Diag(ArraySize->getLocStart(), diag::ext_vla_folded_to_constant);
-      return false;
-    }
+  if (S.LangOpts.GNUMode && ArraySize->EvaluateAsInt(SizeVal, S.Context)) {
+    S.Diag(ArraySize->getLocStart(), diag::ext_vla_folded_to_constant);
+    return false;
   }
 
   return true;
@@ -1266,6 +1267,13 @@
     return QualType();
   }
 
+  // Do placeholder conversions on the array size expression.
+  if (ArraySize && ArraySize->hasPlaceholderType()) {
+    ExprResult Result = CheckPlaceholderExpr(ArraySize);
+    if (Result.isInvalid()) return QualType();
+    ArraySize = Result.take();
+  }
+
   // Do lvalue-to-rvalue conversions on the array size expression.
   if (ArraySize && !ArraySize->isRValue()) {
     ExprResult Result = DefaultLvalueConversion(ArraySize);
@@ -1360,9 +1368,9 @@
       else
         Diag(Loc, diag::ext_vla);
     } else if (ASM != ArrayType::Normal || Quals != 0)
-      Diag(Loc, 
+      Diag(Loc,
            getLangOptions().CPlusPlus? diag::err_c99_array_usage_cxx
-                                     : diag::ext_c99_array_usage);
+                                     : diag::ext_c99_array_usage) << ASM;
   }
 
   return T;
@@ -1787,6 +1795,9 @@
     case Declarator::KNRTypeListContext:
       llvm_unreachable("K&R type lists aren't allowed in C++");
       break;
+    case Declarator::LambdaExprContext:
+      llvm_unreachable("Can't specify a type specifier in lambda grammar");
+      break;
     case Declarator::ObjCParameterContext:
     case Declarator::ObjCResultContext:
     case Declarator::PrototypeContext:
@@ -1877,6 +1888,7 @@
     case Declarator::BlockContext:
     case Declarator::ForContext:
     case Declarator::BlockLiteralContext:
+    case Declarator::LambdaExprContext:
       // C++0x [dcl.type]p3:
       //   A type-specifier-seq shall not define a class or enumeration unless
       //   it appears in the type-id of an alias-declaration (7.1.3) that is not
@@ -1960,7 +1972,6 @@
     state.setCurrentChunkIndex(chunkIndex);
     DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
     switch (DeclType.Kind) {
-    default: llvm_unreachable("Unknown decltype!");
     case DeclaratorChunk::Paren:
       T = S.BuildParenType(T);
       break;
@@ -2060,7 +2071,8 @@
                  diag::err_trailing_return_in_parens)
               << T << D.getDeclSpec().getSourceRange();
             D.setInvalidType(true);
-          } else if (T.hasQualifiers() || !isa<AutoType>(T)) {
+          } else if (D.getContext() != Declarator::LambdaExprContext &&
+                     (T.hasQualifiers() || !isa<AutoType>(T))) {
             S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
                  diag::err_trailing_return_without_auto)
               << T << D.getDeclSpec().getSourceRange();
@@ -2372,7 +2384,8 @@
     // top-level template type arguments.
     bool FreeFunction;
     if (!D.getCXXScopeSpec().isSet()) {
-      FreeFunction = (D.getContext() != Declarator::MemberContext ||
+      FreeFunction = ((D.getContext() != Declarator::MemberContext &&
+                       D.getContext() != Declarator::LambdaExprContext) ||
                       D.getDeclSpec().isFriendSpecified());
     } else {
       DeclContext *DC = S.computeDeclContext(D.getCXXScopeSpec());
@@ -2580,6 +2593,7 @@
     case Declarator::CXXCatchContext:
     case Declarator::ObjCCatchContext:
     case Declarator::BlockLiteralContext:
+    case Declarator::LambdaExprContext:
     case Declarator::TemplateTypeArgContext:
       // FIXME: We may want to allow parameter packs in block-literal contexts
       // in the future.
@@ -4062,8 +4076,23 @@
   //         "Can't ask whether a dependent type is complete");
 
   // If we have a complete type, we're done.
-  if (!T->isIncompleteType())
+  NamedDecl *Def = 0;
+  if (!T->isIncompleteType(&Def)) {
+    // If we know about the definition but it is not visible, complain.
+    if (diag != 0 && Def && !LookupResult::isVisible(Def)) {
+      // Suppress this error outside of a SFINAE context if we've already
+      // emitted the error once for this type. There's no usefulness in 
+      // repeating the diagnostic.
+      // FIXME: Add a Fix-It that imports the corresponding module or includes
+      // the header.
+      if (isSFINAEContext() || HiddenDefinitions.insert(Def)) {
+        Diag(Loc, diag::err_module_private_definition) << T;
+        Diag(Def->getLocation(), diag::note_previous_definition);
+      }
+    }
+    
     return false;
+  }
 
   const TagType *Tag = T->getAs<TagType>();
   const ObjCInterfaceType *IFace = 0;

Modified: cfe/branches/tooling/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Sema/TreeTransform.h?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Sema/TreeTransform.h (original)
+++ cfe/branches/tooling/lib/Sema/TreeTransform.h Fri Jan 20 10:14:22 2012
@@ -1890,6 +1890,7 @@
   ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc,
                                 QualType ThisType,
                                 bool isImplicit) {
+    getSema().CheckCXXThisCapture(ThisLoc);
     return getSema().Owned(
                       new (getSema().Context) CXXThisExpr(ThisLoc, ThisType,
                                                           isImplicit));
@@ -2898,7 +2899,7 @@
     Expr *SourceExpr = Input.getSourceDeclExpression();
     if (SourceExpr) {
       EnterExpressionEvaluationContext Unevaluated(getSema(),
-                                                   Sema::Unevaluated);
+                                                   Sema::ConstantEvaluated);
       ExprResult E = getDerived().TransformExpr(SourceExpr);
       SourceExpr = (E.isInvalid() ? 0 : E.take());
     }
@@ -2932,9 +2933,9 @@
     llvm_unreachable("Caller should expand pack expansions");
 
   case TemplateArgument::Expression: {
-    // Template argument expressions are not potentially evaluated.
+    // Template argument expressions are constant expressions.
     EnterExpressionEvaluationContext Unevaluated(getSema(),
-                                                 Sema::Unevaluated);
+                                                 Sema::ConstantEvaluated);
 
     Expr *InputExpr = Input.getSourceExpression();
     if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
@@ -3182,6 +3183,9 @@
 
 template<typename Derived>
 TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI) {
+  // Refine the base location to the type's location.
+  TemporaryBase Rebase(*this, DI->getTypeLoc().getBeginLoc(),
+                       getDerived().getBaseEntity());
   if (getDerived().AlreadyTransformed(DI->getType()))
     return DI;
 
@@ -3595,7 +3599,8 @@
 
   Expr *Size = TL.getSizeExpr();
   if (Size) {
-    EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+    EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                                 Sema::ConstantEvaluated);
     Size = getDerived().TransformExpr(Size).template takeAs<Expr>();
   }
   NewTL.setSizeExpr(Size);
@@ -3640,9 +3645,6 @@
   if (ElementType.isNull())
     return QualType();
 
-  // Array bounds are not potentially evaluated contexts
-  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
-
   ExprResult SizeResult
     = getDerived().TransformExpr(T->getSizeExpr());
   if (SizeResult.isInvalid())
@@ -3680,8 +3682,9 @@
   if (ElementType.isNull())
     return QualType();
 
-  // Array bounds are not potentially evaluated contexts
-  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+  // Array bounds are constant expressions.
+  EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                               Sema::ConstantEvaluated);
 
   // Prefer the expression from the TypeLoc;  the other may have been uniqued.
   Expr *origSize = TL.getSizeExpr();
@@ -3728,8 +3731,9 @@
   if (ElementType.isNull())
     return QualType();
 
-  // Vector sizes are not potentially evaluated contexts
-  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+  // Vector sizes are constant expressions.
+  EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                               Sema::ConstantEvaluated);
 
   ExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
   if (Size.isInvalid())
@@ -4980,8 +4984,8 @@
 TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) {
   ExprResult LHS, RHS;
   {
-    // The case value expressions are not potentially evaluated.
-    EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+    EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                                 Sema::ConstantEvaluated);
 
     // Transform the left-hand case value.
     LHS = getDerived().TransformExpr(S->getLHS());
@@ -6874,11 +6878,11 @@
                                              E->getLocEnd());
   }
 
-  // We don't know whether the expression is potentially evaluated until
-  // after we perform semantic analysis, so the expression is potentially
+  // We don't know whether the subexpression is potentially evaluated until
+  // after we perform semantic analysis.  We speculatively assume it is
+  // unevaluated; it will get fixed later if the subexpression is in fact
   // potentially evaluated.
-  EnterExpressionEvaluationContext Unevaluated(SemaRef,
-                                      Sema::PotentiallyPotentiallyEvaluated);
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
 
   ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
   if (SubExpr.isInvalid())
@@ -6913,9 +6917,6 @@
                                              E->getLocEnd());
   }
 
-  // We don't know whether the expression is potentially evaluated until
-  // after we perform semantic analysis, so the expression is potentially
-  // potentially evaluated.
   EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
 
   ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
@@ -8114,10 +8115,6 @@
   BlockScopeInfo *blockScope = SemaRef.getCurBlock();
 
   blockScope->TheDecl->setIsVariadic(oldBlock->isVariadic());
-  // We built a new blockScopeInfo in call to ActOnBlockStart
-  // in above, CapturesCXXThis need be set here from the block
-  // expression.
-  blockScope->CapturesCXXThis = oldBlock->capturesCXXThis();
   blockScope->TheDecl->setBlockMissingReturnType(
                          oldBlock->blockMissingReturnType());
   

Modified: cfe/branches/tooling/lib/Serialization/ASTCommon.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Serialization/ASTCommon.h?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Serialization/ASTCommon.h (original)
+++ cfe/branches/tooling/lib/Serialization/ASTCommon.h Fri Jan 20 10:14:22 2012
@@ -22,12 +22,10 @@
 namespace serialization {
 
 enum DeclUpdateKind {
-  UPD_CXX_SET_DEFINITIONDATA,
   UPD_CXX_ADDED_IMPLICIT_MEMBER,
   UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
   UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
-  UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
-  UPD_OBJC_SET_CLASS_DEFINITIONDATA
+  UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER
 };
 
 TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT);

Modified: cfe/branches/tooling/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Serialization/ASTReader.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Serialization/ASTReader.cpp (original)
+++ cfe/branches/tooling/lib/Serialization/ASTReader.cpp Fri Jan 20 10:14:22 2012
@@ -514,7 +514,7 @@
       II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
     Reader.SetIdentifierInfo(ID, II);
     II->setIsFromAST();
-    II->setOutOfDate(false);
+    Reader.markIdentifierUpToDate(II);    
     return II;
   }
 
@@ -529,8 +529,8 @@
   Bits >>= 1;
   bool hasMacroDefinition = Bits & 0x01;
   Bits >>= 1;
-  unsigned ObjCOrBuiltinID = Bits & 0x3FF;
-  Bits >>= 10;
+  unsigned ObjCOrBuiltinID = Bits & 0x7FF;
+  Bits >>= 11;
 
   assert(Bits == 0 && "Extra bits in the identifier?");
   DataLen -= 6;
@@ -540,7 +540,7 @@
   IdentifierInfo *II = KnownII;
   if (!II)
     II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
-  II->setOutOfDate(false);
+  Reader.markIdentifierUpToDate(II);
   II->setIsFromAST();
 
   // Set or check the various bits in the IdentifierInfo structure.
@@ -747,7 +747,7 @@
                                       unsigned DataLen) {
   using namespace clang::io;
   unsigned NumDecls = ReadUnalignedLE16(d);
-  DeclID *Start = (DeclID *)d;
+  LE32DeclID *Start = (LE32DeclID *)d;
   return std::make_pair(Start, Start + NumDecls);
 }
 
@@ -1398,10 +1398,8 @@
       Macro->AddTokenToBody(Tok);
       break;
     }
+    }
   }
-  }
-  
-  return;
 }
 
 PreprocessedEntityID 
@@ -1562,14 +1560,20 @@
   /// \brief Visitor class used to look up identifirs in an AST file.
   class IdentifierLookupVisitor {
     StringRef Name;
+    unsigned PriorGeneration;
     IdentifierInfo *Found;
   public:
-    explicit IdentifierLookupVisitor(StringRef Name) : Name(Name), Found() { }
+    IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration) 
+      : Name(Name), PriorGeneration(PriorGeneration), Found() { }
     
     static bool visit(ModuleFile &M, void *UserData) {
       IdentifierLookupVisitor *This
         = static_cast<IdentifierLookupVisitor *>(UserData);
       
+      // If we've already searched this module file, skip it now.
+      if (M.Generation <= This->PriorGeneration)
+        return true;
+      
       ASTIdentifierLookupTable *IdTable
         = (ASTIdentifierLookupTable *)M.IdentifierLookupTable;
       if (!IdTable)
@@ -1595,7 +1599,24 @@
 }
 
 void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {
-  get(II.getName());
+  unsigned PriorGeneration = 0;
+  if (getContext().getLangOptions().Modules)
+    PriorGeneration = IdentifierGeneration[&II];
+  
+  IdentifierLookupVisitor Visitor(II.getName(), PriorGeneration);
+  ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
+  markIdentifierUpToDate(&II);
+}
+
+void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) {
+  if (!II)
+    return;
+  
+  II->setOutOfDate(false);
+
+  // Update the generation for this identifier.
+  if (getContext().getLangOptions().Modules)
+    IdentifierGeneration[II] = CurrentGeneration;
 }
 
 const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) {
@@ -1817,8 +1838,9 @@
         GlobalTypeMap.insert(std::make_pair(getTotalNumTypes(), &F));
         
         // Introduce the local -> global mapping for types within this module.
-        F.TypeRemap.insert(std::make_pair(LocalBaseTypeIndex, 
-                             F.BaseTypeIndex - LocalBaseTypeIndex));
+        F.TypeRemap.insertOrReplace(
+          std::make_pair(LocalBaseTypeIndex, 
+                         F.BaseTypeIndex - LocalBaseTypeIndex));
         
         TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes);
       }
@@ -1843,8 +1865,12 @@
         
         // Introduce the local -> global mapping for declarations within this
         // module.
-        F.DeclRemap.insert(std::make_pair(LocalBaseDeclID, 
-                                          F.BaseDeclID - LocalBaseDeclID));
+        F.DeclRemap.insertOrReplace(
+          std::make_pair(LocalBaseDeclID, F.BaseDeclID - LocalBaseDeclID));
+        
+        // Introduce the global -> local mapping for declarations within this
+        // module.
+        F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID;
         
         DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);
       }
@@ -1877,16 +1903,6 @@
       break;
     }
 
-    case REDECLS_UPDATE_LATEST: {
-      assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs");
-      for (unsigned i = 0, e = Record.size(); i < e; /* in loop */) {
-        DeclID First = ReadDeclID(F, Record, i);
-        DeclID Latest = ReadDeclID(F, Record, i);
-        FirstLatestDeclIDs[First] = Latest;
-      }
-      break;
-    }
-
     case LANGUAGE_OPTIONS:
       if (ParseLanguageOptions(Record) && !DisableValidation)
         return IgnorePCH;
@@ -1923,9 +1939,9 @@
         
         // Introduce the local -> global mapping for identifiers within this
         // module.
-        F.IdentifierRemap.insert(
-                            std::make_pair(LocalBaseIdentifierID,
-                              F.BaseIdentifierID - LocalBaseIdentifierID));
+        F.IdentifierRemap.insertOrReplace(
+          std::make_pair(LocalBaseIdentifierID,
+                         F.BaseIdentifierID - LocalBaseIdentifierID));
         
         IdentifiersLoaded.resize(IdentifiersLoaded.size() 
                                  + F.LocalNumIdentifiers);
@@ -2000,8 +2016,9 @@
         
         // Introduce the local -> global mapping for selectors within this 
         // module.
-        F.SelectorRemap.insert(std::make_pair(LocalBaseSelectorID,
-                                 F.BaseSelectorID - LocalBaseSelectorID));
+        F.SelectorRemap.insertOrReplace(
+          std::make_pair(LocalBaseSelectorID,
+                         F.BaseSelectorID - LocalBaseSelectorID));
 
         SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors);        
       }
@@ -2125,6 +2142,9 @@
         
         TypeRemap.insert(std::make_pair(TypeIndexOffset, 
                                     OM->BaseTypeIndex - TypeIndexOffset));
+
+        // Global -> local mappings.
+        F.GlobalToLocalDeclIDs[OM] = DeclIDOffset;
       }
       break;
     }
@@ -2268,7 +2288,7 @@
        
         // Introduce the local -> global mapping for preprocessed entities in
         // this module.
-        F.PreprocessedEntityRemap.insert(
+        F.PreprocessedEntityRemap.insertOrReplace(
           std::make_pair(LocalBasePreprocessedEntityID,
             F.BasePreprocessedEntityID - LocalBasePreprocessedEntityID));
       }
@@ -2396,7 +2416,32 @@
         }
       }
       break;
+    }
+
+    case LOCAL_REDECLARATIONS: {
+      F.RedeclarationChains.swap(Record);
+      break;
+    }
+        
+    case LOCAL_REDECLARATIONS_MAP: {
+      if (F.LocalNumRedeclarationsInMap != 0) {
+        Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file");
+        return Failure;
+      }
       
+      F.LocalNumRedeclarationsInMap = Record[0];
+      F.RedeclarationsMap = (const LocalRedeclarationsInfo *)BlobStart;
+      break;
+    }
+        
+    case MERGED_DECLARATIONS: {
+      for (unsigned Idx = 0; Idx < Record.size(); /* increment in loop */) {
+        GlobalDeclID CanonID = getGlobalDeclID(F, Record[Idx++]);
+        SmallVectorImpl<GlobalDeclID> &Decls = StoredMergedDecls[CanonID];
+        for (unsigned N = Record[Idx++]; N > 0; --N)
+          Decls.push_back(getGlobalDeclID(F, Record[Idx++]));
+      }
+      break;
     }
     }
   }
@@ -2477,9 +2522,15 @@
 void ASTReader::makeNamesVisible(const HiddenNames &Names) {
   for (unsigned I = 0, N = Names.size(); I != N; ++I) {
     if (Decl *D = Names[I].dyn_cast<Decl *>())
-      D->ModulePrivate = false;
-    else
-      Names[I].get<IdentifierInfo *>()->setHasMacroDefinition(true);
+      D->Hidden = false;
+    else {
+      IdentifierInfo *II = Names[I].get<IdentifierInfo *>();
+      if (!II->hasMacroDefinition()) {
+        II->setHasMacroDefinition(true);
+        if (DeserializationListener)
+          DeserializationListener->MacroVisible(II);
+      }
+    }
   }
 }
 
@@ -2498,6 +2549,11 @@
       continue;
     }
     
+    if (!Mod->isAvailable()) {
+      // Modules that aren't available cannot be made visible.
+      continue;
+    }
+
     // Update the module's name visibility.
     Mod->NameVisibility = NameVisibility;
     
@@ -2511,11 +2567,11 @@
     
     // Push any non-explicit submodules onto the stack to be marked as
     // visible.
-    for (llvm::StringMap<Module *>::iterator Sub = Mod->SubModules.begin(),
-                                          SubEnd = Mod->SubModules.end();
+    for (Module::submodule_iterator Sub = Mod->submodule_begin(),
+                                 SubEnd = Mod->submodule_end();
          Sub != SubEnd; ++Sub) {
-      if (!Sub->getValue()->IsExplicit && Visited.insert(Sub->getValue()))
-        Stack.push_back(Sub->getValue());
+      if (!(*Sub)->IsExplicit && Visited.insert(*Sub))
+        Stack.push_back(*Sub);
     }
     
     // Push any exported modules onto the stack to be marked as visible.
@@ -2579,6 +2635,9 @@
 
 ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
                                             ModuleKind Type) {
+  // Bump the generation number.
+  ++CurrentGeneration;
+  
   switch(ReadASTCore(FileName, Type, /*ImportedBy=*/0)) {
   case Failure: return Failure;
   case IgnorePCH: return IgnorePCH;
@@ -2586,7 +2645,7 @@
   }
 
   // Here comes stuff that we only do once the entire chain is loaded.
-  
+
   // Check the predefines buffers.
   if (!DisableValidation && Type == MK_PCH &&
       // FIXME: CheckPredefinesBuffers also sets the SuggestedPredefines;
@@ -2602,7 +2661,7 @@
                               IdEnd = PP.getIdentifierTable().end();
        Id != IdEnd; ++Id)
     Id->second->setOutOfDate(true);
-
+  
   // Resolve any unresolved module exports.
   for (unsigned I = 0, N = UnresolvedModuleImportExports.size(); I != N; ++I) {
     UnresolvedModuleImportExport &Unresolved = UnresolvedModuleImportExports[I];
@@ -2626,14 +2685,17 @@
   if (DeserializationListener)
     DeserializationListener->ReaderInitialized(this);
 
-  // If this AST file is a precompiled preamble, then set the preamble file ID
-  // of the source manager to the file source file from which the preamble was
-  // built.
-  if (Type == MK_Preamble) {
-    if (!OriginalFileID.isInvalid()) {
-      OriginalFileID = FileID::get(ModuleMgr.getPrimaryModule().SLocEntryBaseID
-                                        + OriginalFileID.getOpaqueValue() - 1);
+  if (!OriginalFileID.isInvalid()) {
+    OriginalFileID = FileID::get(ModuleMgr.getPrimaryModule().SLocEntryBaseID
+                                      + OriginalFileID.getOpaqueValue() - 1);
+
+    // If this AST file is a precompiled preamble, then set the preamble file ID
+    // of the source manager to the file source file from which the preamble was
+    // built.
+    if (Type == MK_Preamble) {
       SourceMgr.setPreambleFileID(OriginalFileID);
+    } else if (Type == MK_MainFile) {
+      SourceMgr.setMainFileID(OriginalFileID);
     }
   }
   
@@ -2647,7 +2709,7 @@
   bool NewModule;
   std::string ErrorStr;
   llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportedBy,
-                                                ErrorStr);
+                                                CurrentGeneration, ErrorStr);
 
   if (!M) {
     // We couldn't load the module.
@@ -2777,17 +2839,12 @@
   // built-in types. Right now, we just ignore the problem.
   
   // Load the special types.
-  if (SpecialTypes.size() > NumSpecialTypeIDs) {
+  if (SpecialTypes.size() >= NumSpecialTypeIDs) {
     if (Context.getBuiltinVaListType().isNull()) {
       Context.setBuiltinVaListType(
         GetType(SpecialTypes[SPECIAL_TYPE_BUILTIN_VA_LIST]));
     }
     
-    if (unsigned Proto = SpecialTypes[SPECIAL_TYPE_OBJC_PROTOCOL]) {
-      if (Context.ObjCProtoType.isNull())
-        Context.ObjCProtoType = GetType(Proto);
-    }
-    
     if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING]) {
       if (!Context.CFConstantStringTypeDecl)
         Context.setCFConstantStringType(GetType(String));
@@ -3077,6 +3134,7 @@
         return Failure;
       }
       
+      CurrentModule->IsFromModuleFile = true;
       CurrentModule->InferSubmodules = InferSubmodules;
       CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
       CurrentModule->InferExportWildcard = InferExportWildcard;
@@ -3167,7 +3225,7 @@
         
         // Introduce the local -> global mapping for submodules within this 
         // module.
-        F.SubmoduleRemap.insert(
+        F.SubmoduleRemap.insertOrReplace(
           std::make_pair(LocalBaseSubmoduleID,
                          F.BaseSubmoduleID - LocalBaseSubmoduleID));
         
@@ -3221,10 +3279,21 @@
       CurrentModule->UnresolvedExports.clear();
       break;
     }
+    case SUBMODULE_REQUIRES: {
+      if (First) {
+        Error("missing submodule metadata record at beginning of block");
+        return Failure;
+      }
+
+      if (!CurrentModule)
+        break;
+
+      CurrentModule->addRequirement(StringRef(BlobStart, BlobLen), 
+                                    Context.getLangOptions());
+      break;
+    }
     }
   }
-
-  return Success;
 }
 
 /// \brief Parse the record that corresponds to a LangOptions data
@@ -3361,9 +3430,8 @@
     return ID;
   }
   }
-  
-  Error("invalid offset in preprocessor detail block");
-  return 0;
+
+  llvm_unreachable("Invalid PreprocessorDetailRecordTypes");
 }
 
 /// \brief \arg SLocMapI points at a chunk of a module that contains no
@@ -3859,8 +3927,9 @@
     }
     unsigned Idx = 0;
     bool IsDependent = Record[Idx++];
-    QualType T
-      = Context.getRecordType(ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx));
+    RecordDecl *RD = ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx);
+    RD = cast_or_null<RecordDecl>(RD->getCanonicalDecl());
+    QualType T = Context.getRecordType(RD);
     const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
     return T;
   }
@@ -3924,7 +3993,7 @@
     unsigned Idx = 0;
     ObjCInterfaceDecl *ItfD
       = ReadDeclAs<ObjCInterfaceDecl>(*Loc.F, Record, Idx);
-    return Context.getObjCInterfaceType(ItfD);
+    return Context.getObjCInterfaceType(ItfD->getCanonicalDecl());
   }
 
   case TYPE_OBJC_OBJECT: {
@@ -4049,8 +4118,7 @@
     return Context.getAtomicType(ValueType);
   }
   }
-  // Suppress a GCC warning
-  return QualType();
+  llvm_unreachable("Invalid TypeCode!");
 }
 
 class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> {
@@ -4431,7 +4499,6 @@
     return TemplateArgumentLocInfo();
   }
   llvm_unreachable("unexpected template argument loc");
-  return TemplateArgumentLocInfo();
 }
 
 TemplateArgumentLoc
@@ -4539,6 +4606,9 @@
     case PREDEF_DECL_OBJC_CLASS_ID:
       return Context.getObjCClassDecl();
         
+    case PREDEF_DECL_OBJC_PROTOCOL_ID:
+      return Context.getObjCProtocolDecl();
+        
     case PREDEF_DECL_INT_128_ID:
       return Context.getInt128Decl();
 
@@ -4548,15 +4618,12 @@
     case PREDEF_DECL_OBJC_INSTANCETYPE_ID:
       return Context.getObjCInstanceTypeDecl();
     }
-    
-    return 0;
   }
   
   unsigned Index = ID - NUM_PREDEF_DECL_IDS;
 
-  if (Index > DeclsLoaded.size()) {
+  if (Index >= DeclsLoaded.size()) {
     Error("declaration ID out-of-range for AST file");
-    return 0;
   }
   
   if (!DeclsLoaded[Index]) {
@@ -4568,6 +4635,23 @@
   return DeclsLoaded[Index];
 }
 
+DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M, 
+                                                  DeclID GlobalID) {
+  if (GlobalID < NUM_PREDEF_DECL_IDS)
+    return GlobalID;
+  
+  GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID);
+  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
+  ModuleFile *Owner = I->second;
+
+  llvm::DenseMap<ModuleFile *, serialization::DeclID>::iterator Pos
+    = M.GlobalToLocalDeclIDs.find(Owner);
+  if (Pos == M.GlobalToLocalDeclIDs.end())
+    return 0;
+      
+  return GlobalID - Owner->BaseDeclID + Pos->second;
+}
+
 serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F, 
                                             const RecordData &Record,
                                             unsigned &Idx) {
@@ -4744,15 +4828,17 @@
   /// declaration context.
   class DeclContextNameLookupVisitor {
     ASTReader &Reader;
+    llvm::SmallVectorImpl<const DeclContext *> &Contexts;
     const DeclContext *DC;
     DeclarationName Name;
     SmallVectorImpl<NamedDecl *> &Decls;
 
   public:
     DeclContextNameLookupVisitor(ASTReader &Reader, 
-                                 const DeclContext *DC, DeclarationName Name,
+                                 SmallVectorImpl<const DeclContext *> &Contexts, 
+                                 DeclarationName Name,
                                  SmallVectorImpl<NamedDecl *> &Decls)
-      : Reader(Reader), DC(DC), Name(Name), Decls(Decls) { }
+      : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { }
 
     static bool visit(ModuleFile &M, void *UserData) {
       DeclContextNameLookupVisitor *This
@@ -4760,11 +4846,20 @@
 
       // Check whether we have any visible declaration information for
       // this context in this module.
-      ModuleFile::DeclContextInfosMap::iterator Info
-        = M.DeclContextInfos.find(This->DC);
-      if (Info == M.DeclContextInfos.end() || !Info->second.NameLookupTableData)
-        return false;
+      ModuleFile::DeclContextInfosMap::iterator Info;
+      bool FoundInfo = false;
+      for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {
+        Info = M.DeclContextInfos.find(This->Contexts[I]);
+        if (Info != M.DeclContextInfos.end() && 
+            Info->second.NameLookupTableData) {
+          FoundInfo = true;
+          break;
+        }
+      }
 
+      if (!FoundInfo)
+        return false;
+      
       // Look for this name within this module.
       ASTDeclContextNameLookupTable *LookupTable =
         (ASTDeclContextNameLookupTable*)Info->second.NameLookupTableData;
@@ -4806,7 +4901,24 @@
                                       DeclContext::lookup_iterator(0));
 
   SmallVector<NamedDecl *, 64> Decls;
-  DeclContextNameLookupVisitor Visitor(*this, DC, Name, Decls);
+  
+  // Compute the declaration contexts we need to look into. Multiple such
+  // declaration contexts occur when two declaration contexts from disjoint
+  // modules get merged, e.g., when two namespaces with the same name are 
+  // independently defined in separate modules.
+  SmallVector<const DeclContext *, 2> Contexts;
+  Contexts.push_back(DC);
+  
+  if (DC->isNamespace()) {
+    MergedDeclsMap::iterator Merged
+      = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+    if (Merged != MergedDecls.end()) {
+      for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
+        Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
+    }
+  }
+  
+  DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
   ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);
   ++NumVisibleDeclContextsRead;
   SetExternalVisibleDeclsForName(DC, Name, Decls);
@@ -5023,11 +5135,11 @@
 }
 
 IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
-  IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart));
+  IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart),
+                                  /*PriorGeneration=*/0);
   ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
   IdentifierInfo *II = Visitor.getIdentifierInfo();
-  if (II)
-    II->setOutOfDate(false);
+  markIdentifierUpToDate(II);
   return II;
 }
 
@@ -5539,8 +5651,7 @@
     return DeclarationName::getUsingDirectiveName();
   }
 
-  // Required to silence GCC warning
-  return DeclarationName();
+  llvm_unreachable("Invalid NameKind!");
 }
 
 void ASTReader::ReadDeclarationNameLoc(ModuleFile &F,
@@ -6024,59 +6135,120 @@
   SwitchCaseStmts.clear();
 }
 
+void ASTReader::finishPendingActions() {
+  while (!PendingIdentifierInfos.empty() ||
+         !PendingDeclChains.empty() ||
+         !PendingChainedObjCCategories.empty()) {
+
+    // If any identifiers with corresponding top-level declarations have
+    // been loaded, load those declarations now.
+    while (!PendingIdentifierInfos.empty()) {
+      SetGloballyVisibleDecls(PendingIdentifierInfos.front().II,
+                              PendingIdentifierInfos.front().DeclIDs, true);
+      PendingIdentifierInfos.pop_front();
+    }
+  
+    // Load pending declaration chains.
+    for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
+      loadPendingDeclChain(PendingDeclChains[I]);
+      PendingDeclChainsKnown.erase(PendingDeclChains[I]);
+    }
+    PendingDeclChains.clear();
+    
+    for (std::vector<std::pair<ObjCInterfaceDecl *,
+                               serialization::DeclID> >::iterator
+           I = PendingChainedObjCCategories.begin(),
+           E = PendingChainedObjCCategories.end(); I != E; ++I) {
+      loadObjCChainedCategories(I->second, I->first);
+    }
+    PendingChainedObjCCategories.clear();
+  }
+  
+  // If we deserialized any C++ or Objective-C class definitions, any
+  // Objective-C protocol definitions, or any redeclarable templates, make sure
+  // that all redeclarations point to the definitions. Note that this can only 
+  // happen now, after the redeclaration chains have been fully wired.
+  for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
+                                           DEnd = PendingDefinitions.end();
+       D != DEnd; ++D) {
+    if (TagDecl *TD = dyn_cast<TagDecl>(*D)) {
+      if (const TagType *TagT = dyn_cast<TagType>(TD->TypeForDecl)) {
+        // Make sure that the TagType points at the definition.
+        const_cast<TagType*>(TagT)->decl = TD;
+      }
+      
+      if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) {
+        for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(),
+                                         REnd = RD->redecls_end();
+             R != REnd; ++R)
+          cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData;
+        
+      }
+
+      continue;
+    }
+    
+    if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) {
+      // Make sure that the ObjCInterfaceType points at the definition.
+      const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl))
+        ->Decl = ID;
+      
+      for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(),
+                                           REnd = ID->redecls_end();
+           R != REnd; ++R)
+        R->Data = ID->Data;
+      
+      continue;
+    }
+    
+    if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) {
+      for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(),
+                                          REnd = PD->redecls_end();
+           R != REnd; ++R)
+        R->Data = PD->Data;
+      
+      continue;
+    }
+    
+    RedeclarableTemplateDecl *RTD
+      = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl();
+    for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(),
+                                                REnd = RTD->redecls_end();
+         R != REnd; ++R)
+      R->Common = RTD->Common;    
+  }
+  PendingDefinitions.clear();
+}
+
 void ASTReader::FinishedDeserializing() {
   assert(NumCurrentElementsDeserializing &&
          "FinishedDeserializing not paired with StartedDeserializing");
   if (NumCurrentElementsDeserializing == 1) {
 
-    // Fully load the interesting decls, including deserializing their bodies,
-    // so that any other declarations that get referenced in the body will be
-    // fully deserialized by the time we pass them to the consumer.
-    for (std::deque<Decl *>::iterator
-           I = InterestingDecls.begin(),
-           E = InterestingDecls.end(); I != E; ++I)
-      (*I)->getBody();
-
-    do {
-      // If any identifiers with corresponding top-level declarations have
-      // been loaded, load those declarations now.
-      while (!PendingIdentifierInfos.empty()) {
-        SetGloballyVisibleDecls(PendingIdentifierInfos.front().II,
-                                PendingIdentifierInfos.front().DeclIDs, true);
-        PendingIdentifierInfos.pop_front();
-      }
-  
-      // Ready to load previous declarations of Decls that were delayed.
-      while (!PendingPreviousDecls.empty()) {
-        loadAndAttachPreviousDecl(PendingPreviousDecls.front().first,
-                                  PendingPreviousDecls.front().second);
-        PendingPreviousDecls.pop_front();
-      }
-  
-      for (std::vector<std::pair<ObjCInterfaceDecl *,
-                                 serialization::DeclID> >::iterator
-             I = PendingChainedObjCCategories.begin(),
-             E = PendingChainedObjCCategories.end(); I != E; ++I) {
-        loadObjCChainedCategories(I->second, I->first);
-      }
-      PendingChainedObjCCategories.clear();
-  
+    while (Consumer && !InterestingDecls.empty()) {
+      finishPendingActions();
+
       // We are not in recursive loading, so it's safe to pass the "interesting"
       // decls to the consumer.
-      if (Consumer && !InterestingDecls.empty()) {
-        Decl *D = InterestingDecls.front();
-        InterestingDecls.pop_front();
+      Decl *D = InterestingDecls.front();
+      InterestingDecls.pop_front();
 
-        PassInterestingDeclToConsumer(D);
+      // Fully load the interesting decls, including deserializing their
+      // bodies, so that any other declarations that get referenced in the
+      // body will be fully deserialized by the time we pass them to the
+      // consumer.
+      if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+        if (FD->doesThisDeclarationHaveABody()) {
+          FD->getBody();
+          finishPendingActions();
+        }
       }
 
-    } while ((Consumer && !InterestingDecls.empty()) ||
-             !PendingIdentifierInfos.empty() ||
-             !PendingPreviousDecls.empty() ||
-             !PendingChainedObjCCategories.empty());
+      PassInterestingDeclToConsumer(D);
+    }
 
-    assert(PendingForwardRefs.size() == 0 &&
-           "Some forward refs did not get linked to the definition!");
+    finishPendingActions();
+    PendingDeclChainsKnown.clear();
   }
   --NumCurrentElementsDeserializing;
 }
@@ -6090,7 +6262,8 @@
     Consumer(0), ModuleMgr(FileMgr.getFileSystemOptions()),
     RelocatablePCH(false), isysroot(isysroot),
     DisableValidation(DisableValidation),
-    DisableStatCache(DisableStatCache), NumStatHits(0), NumStatMisses(0), 
+    DisableStatCache(DisableStatCache), 
+    CurrentGeneration(0), NumStatHits(0), NumStatMisses(0), 
     NumSLocEntriesRead(0), TotalNumSLocEntries(0), 
     NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), 
     TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), 

Modified: cfe/branches/tooling/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Serialization/ASTReaderDecl.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/branches/tooling/lib/Serialization/ASTReaderDecl.cpp Fri Jan 20 10:14:22 2012
@@ -14,6 +14,8 @@
 
 #include "ASTCommon.h"
 #include "clang/Serialization/ASTReader.h"
+#include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/Sema.h"
 #include "clang/Sema/SemaDiagnostic.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
@@ -101,9 +103,93 @@
     void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
                                const RecordData &R, unsigned &I);
 
-    void InitializeCXXDefinitionData(CXXRecordDecl *D,
-                                     CXXRecordDecl *DefinitionDecl,
-                                     const RecordData &Record, unsigned &Idx);
+    /// \brief RAII class used to capture the first ID within a redeclaration
+    /// chain and to introduce it into the list of pending redeclaration chains
+    /// on destruction.
+    ///
+    /// The caller can choose not to introduce this ID into the redeclaration
+    /// chain by calling \c suppress().
+    class RedeclarableResult {
+      ASTReader &Reader;
+      GlobalDeclID FirstID;
+      mutable bool Owning;
+      
+      RedeclarableResult &operator=(RedeclarableResult&); // DO NOT IMPLEMENT
+      
+    public:
+      RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID)
+        : Reader(Reader), FirstID(FirstID), Owning(true) { }
+
+      RedeclarableResult(const RedeclarableResult &Other)
+        : Reader(Other.Reader), FirstID(Other.FirstID), Owning(Other.Owning) 
+      { 
+        Other.Owning = false;
+      }
+
+      ~RedeclarableResult() {
+        // FIXME: We want to suppress this when the declaration is local to
+        // a function, since there's no reason to search other AST files
+        // for redeclarations (they can't exist). However, this is hard to 
+        // do locally because the declaration hasn't necessarily loaded its
+        // declaration context yet. Also, local externs still have the function
+        // as their (semantic) declaration context, which is wrong and would
+        // break this optimize.
+        
+        if (FirstID && Owning && Reader.PendingDeclChainsKnown.insert(FirstID))
+          Reader.PendingDeclChains.push_back(FirstID);
+      }
+      
+      /// \brief Retrieve the first ID.
+      GlobalDeclID getFirstID() const { return FirstID; }
+      
+      /// \brief Do not introduce this declaration ID into the set of pending
+      /// declaration chains.
+      void suppress() {
+        Owning = false;
+      }
+    };
+    
+    /// \brief Class used to capture the result of searching for an existing
+    /// declaration of a specific kind and name, along with the ability
+    /// to update the place where this result was found (the declaration
+    /// chain hanging off an identifier or the DeclContext we searched in)
+    /// if requested.
+    class FindExistingResult {
+      ASTReader &Reader;
+      NamedDecl *New;
+      NamedDecl *Existing;
+      mutable bool AddResult;
+      
+      FindExistingResult &operator=(FindExistingResult&); // DO NOT IMPLEMENT
+      
+    public:
+      FindExistingResult(ASTReader &Reader)
+        : Reader(Reader), New(0), Existing(0), AddResult(false) { }
+      
+      FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing)
+        : Reader(Reader), New(New), Existing(Existing), AddResult(true) { }
+      
+      FindExistingResult(const FindExistingResult &Other)
+        : Reader(Other.Reader), New(Other.New), Existing(Other.Existing), 
+          AddResult(Other.AddResult)
+      {
+        Other.AddResult = false;
+      }
+      
+      ~FindExistingResult();
+      
+      /// \brief Suppress the addition of this result into the known set of
+      /// names.
+      void suppress() { AddResult = false; }
+      
+      operator NamedDecl*() const { return Existing; }
+      
+      template<typename T>
+      operator T*() const { return dyn_cast_or_null<T>(Existing); }
+    };
+    
+    FindExistingResult findExisting(NamedDecl *D);
+    
   public:
     ASTDeclReader(ASTReader &Reader, ModuleFile &F,
                   llvm::BitstreamCursor &Cursor, DeclID thisDeclID,
@@ -114,6 +200,7 @@
         TypeIDForTypeDecl(0) { }
 
     static void attachPreviousDecl(Decl *D, Decl *previous);
+    static void attachLatestDecl(Decl *D, Decl *latest);
 
     void Visit(Decl *D);
 
@@ -133,6 +220,7 @@
     void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
     void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
     void VisitTypeDecl(TypeDecl *TD);
+    void VisitTypedefNameDecl(TypedefNameDecl *TD);
     void VisitTypedefDecl(TypedefDecl *TD);
     void VisitTypeAliasDecl(TypeAliasDecl *TD);
     void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
@@ -163,7 +251,7 @@
     void VisitParmVarDecl(ParmVarDecl *PD);
     void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
     void VisitTemplateDecl(TemplateDecl *D);
-    void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
+    RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
     void VisitClassTemplateDecl(ClassTemplateDecl *D);
     void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
     void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
@@ -180,8 +268,13 @@
     void VisitBlockDecl(BlockDecl *BD);
 
     std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
-    template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
+    
+    template<typename T> 
+    RedeclarableResult VisitRedeclarable(Redeclarable<T> *D);
 
+    template<typename T>
+    void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl);
+    
     // FIXME: Reorder according to DeclNodes.td?
     void VisitObjCMethodDecl(ObjCMethodDecl *D);
     void VisitObjCContainerDecl(ObjCContainerDecl *D);
@@ -189,8 +282,6 @@
     void VisitObjCIvarDecl(ObjCIvarDecl *D);
     void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
     void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
-    void VisitObjCClassDecl(ObjCClassDecl *D);
-    void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
     void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
     void VisitObjCImplDecl(ObjCImplDecl *D);
     void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
@@ -265,21 +356,24 @@
   D->setImplicit(Record[Idx++]);
   D->setUsed(Record[Idx++]);
   D->setReferenced(Record[Idx++]);
-  D->TopLevelDeclInObjCContainer = Record[Idx++];
+  D->setTopLevelDeclInObjCContainer(Record[Idx++]);
   D->setAccess((AccessSpecifier)Record[Idx++]);
   D->FromASTFile = true;
-  D->ModulePrivate = Record[Idx++];
-
+  D->setModulePrivate(Record[Idx++]);
+  D->Hidden = D->isModulePrivate();
+  
   // Determine whether this declaration is part of a (sub)module. If so, it
   // may not yet be visible.
   if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) {
+    // Store the owning submodule ID in the declaration.
+    D->setOwningModuleID(SubmoduleID);
+    
     // Module-private declarations are never visible, so there is no work to do.
-    if (!D->ModulePrivate) {
+    if (!D->isModulePrivate()) {
       if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
         if (Owner->NameVisibility != Module::AllVisible) {
-          // The owning module is not visible. Mark this declaration as
-          // module-private, 
-          D->ModulePrivate = true;
+          // The owning module is not visible. Mark this declaration as hidden.
+          D->Hidden = true;
           
           // Note that this declaration was hidden because its owning module is 
           // not yet visible.
@@ -306,31 +400,41 @@
   TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]);
 }
 
-void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
+void ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) {
+  RedeclarableResult Redecl = VisitRedeclarable(TD);
   VisitTypeDecl(TD);
+  
   TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
+  mergeRedeclarable(TD, Redecl);
+}
+
+void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
+  VisitTypedefNameDecl(TD);
 }
 
 void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) {
-  VisitTypeDecl(TD);
-  TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
+  VisitTypedefNameDecl(TD);
 }
 
 void ASTDeclReader::VisitTagDecl(TagDecl *TD) {
-  VisitRedeclarable(TD);
+  RedeclarableResult Redecl = VisitRedeclarable(TD);
   VisitTypeDecl(TD);
+  
   TD->IdentifierNamespace = Record[Idx++];
   TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
   TD->setCompleteDefinition(Record[Idx++]);
   TD->setEmbeddedInDeclarator(Record[Idx++]);
   TD->setFreeStanding(Record[Idx++]);
   TD->setRBraceLoc(ReadSourceLocation(Record, Idx));
+  
   if (Record[Idx++]) { // hasExtInfo
     TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo();
     ReadQualifierInfo(*Info, Record, Idx);
     TD->TypedefNameDeclOrQualifier = Info;
   } else
     TD->setTypedefNameForAnonDecl(ReadDeclAs<TypedefNameDecl>(Record, Idx));
+
+  mergeRedeclarable(TD, Redecl);  
 }
 
 void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
@@ -379,14 +483,34 @@
 }
 
 void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
-  VisitRedeclarable(FD);
+  RedeclarableResult Redecl = VisitRedeclarable(FD);
   VisitDeclaratorDecl(FD);
 
   ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName(), Record, Idx);
   FD->IdentifierNamespace = Record[Idx++];
+  
+  // FunctionDecl's body is handled last at ASTDeclReader::Visit,
+  // after everything else is read.
+  
+  FD->SClass = (StorageClass)Record[Idx++];
+  FD->SClassAsWritten = (StorageClass)Record[Idx++];
+  FD->IsInline = Record[Idx++];
+  FD->IsInlineSpecified = Record[Idx++];
+  FD->IsVirtualAsWritten = Record[Idx++];
+  FD->IsPure = Record[Idx++];
+  FD->HasInheritedPrototype = Record[Idx++];
+  FD->HasWrittenPrototype = Record[Idx++];
+  FD->IsDeleted = Record[Idx++];
+  FD->IsTrivial = Record[Idx++];
+  FD->IsDefaulted = Record[Idx++];
+  FD->IsExplicitlyDefaulted = Record[Idx++];
+  FD->HasImplicitReturnZero = Record[Idx++];
+  FD->IsConstexpr = Record[Idx++];
+  FD->EndRangeLoc = ReadSourceLocation(Record, Idx);
+
   switch ((FunctionDecl::TemplatedKind)Record[Idx++]) {
-  default: llvm_unreachable("Unhandled TemplatedKind!");
   case FunctionDecl::TK_NonTemplate:
+    mergeRedeclarable(FD, Redecl);      
     break;
   case FunctionDecl::TK_FunctionTemplate:
     FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>(Record, 
@@ -480,25 +604,6 @@
   }
   }
 
-  // FunctionDecl's body is handled last at ASTDeclReader::Visit,
-  // after everything else is read.
-
-  FD->SClass = (StorageClass)Record[Idx++];
-  FD->SClassAsWritten = (StorageClass)Record[Idx++];
-  FD->IsInline = Record[Idx++];
-  FD->IsInlineSpecified = Record[Idx++];
-  FD->IsVirtualAsWritten = Record[Idx++];
-  FD->IsPure = Record[Idx++];
-  FD->HasInheritedPrototype = Record[Idx++];
-  FD->HasWrittenPrototype = Record[Idx++];
-  FD->IsDeleted = Record[Idx++];
-  FD->IsTrivial = Record[Idx++];
-  FD->IsDefaulted = Record[Idx++];
-  FD->IsExplicitlyDefaulted = Record[Idx++];
-  FD->HasImplicitReturnZero = Record[Idx++];
-  FD->IsConstexpr = Record[Idx++];
-  FD->EndRangeLoc = ReadSourceLocation(Record, Idx);
-
   // Read in the parameters.
   unsigned NumParams = Record[Idx++];
   SmallVector<ParmVarDecl *, 16> Params;
@@ -557,15 +662,19 @@
 }
 
 void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
-  VisitRedeclarable(ID);
+  RedeclarableResult Redecl = VisitRedeclarable(ID);
   VisitObjCContainerDecl(ID);
   TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]);
+  mergeRedeclarable(ID, Redecl);
   
-  ObjCInterfaceDecl *Def = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
-  if (ID == Def) {
+  if (Record[Idx++]) {
     // Read the definition.
     ID->allocateDefinitionData();
     
+    // Set the definition data of the canonical declaration, so other
+    // redeclarations will see it.
+    ID->getCanonicalDecl()->Data = ID->Data;
+    
     ObjCInterfaceDecl::DefinitionData &Data = ID->data();
     
     // Read the superclass.
@@ -609,29 +718,10 @@
     // We will rebuild this list lazily.
     ID->setIvarList(0);
     
-    // If there are any pending forward references, make their definition data
-    // pointers point at the newly-allocated data.
-    ASTReader::PendingForwardRefsMap::iterator
-    FindI = Reader.PendingForwardRefs.find(ID);
-    if (FindI != Reader.PendingForwardRefs.end()) {
-      ASTReader::ForwardRefs &Refs = FindI->second;
-      for (ASTReader::ForwardRefs::iterator I = Refs.begin(), 
-                                            E = Refs.end(); 
-           I != E; ++I)
-        cast<ObjCInterfaceDecl>(*I)->Data = ID->Data;
-#ifndef NDEBUG
-      // We later check whether PendingForwardRefs is empty to make sure all
-      // pending references were linked.
-      Reader.PendingForwardRefs.erase(ID);
-#endif
-    }
-  } else if (Def) {
-    if (Def->Data) {
-      ID->Data = Def->Data;
-    } else {
-      // The definition is still initializing.
-      Reader.PendingForwardRefs[Def].push_back(ID);
-    }
+    // Note that we have deserialized a definition.
+    Reader.PendingDefinitions.insert(ID);
+  } else {
+    ID->Data = ID->getCanonicalDecl()->Data;
   }
 }
 
@@ -645,48 +735,41 @@
 }
 
 void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
+  RedeclarableResult Redecl = VisitRedeclarable(PD);
   VisitObjCContainerDecl(PD);
-  PD->InitiallyForwardDecl = Record[Idx++];
-  PD->isForwardProtoDecl = Record[Idx++];
-  PD->setLocEnd(ReadSourceLocation(Record, Idx));
-  unsigned NumProtoRefs = Record[Idx++];
-  SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
-  ProtoRefs.reserve(NumProtoRefs);
-  for (unsigned I = 0; I != NumProtoRefs; ++I)
-    ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
-  SmallVector<SourceLocation, 16> ProtoLocs;
-  ProtoLocs.reserve(NumProtoRefs);
-  for (unsigned I = 0; I != NumProtoRefs; ++I)
-    ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
-  PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
-                      Reader.getContext());
+  mergeRedeclarable(PD, Redecl);
+  
+  if (Record[Idx++]) {
+    // Read the definition.
+    PD->allocateDefinitionData();
+    
+    // Set the definition data of the canonical declaration, so other
+    // redeclarations will see it.
+    PD->getCanonicalDecl()->Data = PD->Data;
+
+    unsigned NumProtoRefs = Record[Idx++];
+    SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
+    ProtoRefs.reserve(NumProtoRefs);
+    for (unsigned I = 0; I != NumProtoRefs; ++I)
+      ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
+    SmallVector<SourceLocation, 16> ProtoLocs;
+    ProtoLocs.reserve(NumProtoRefs);
+    for (unsigned I = 0; I != NumProtoRefs; ++I)
+      ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
+    PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+                        Reader.getContext());
+    
+    // Note that we have deserialized a definition.
+    Reader.PendingDefinitions.insert(PD);
+  } else {
+    PD->Data = PD->getCanonicalDecl()->Data;
+  }
 }
 
 void ASTDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) {
   VisitFieldDecl(FD);
 }
 
-void ASTDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) {
-  VisitDecl(CD);
-  CD->Interface = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
-  CD->InterfaceLoc = ReadSourceLocation(Record, Idx);
-}
-
-void ASTDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
-  VisitDecl(FPD);
-  unsigned NumProtoRefs = Record[Idx++];
-  SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
-  ProtoRefs.reserve(NumProtoRefs);
-  for (unsigned I = 0; I != NumProtoRefs; ++I)
-    ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
-  SmallVector<SourceLocation, 16> ProtoLocs;
-  ProtoLocs.reserve(NumProtoRefs);
-  for (unsigned I = 0; I != NumProtoRefs; ++I)
-    ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
-  FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
-                       Reader.getContext());
-}
-
 void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
   VisitObjCContainerDecl(CD);
   CD->ClassInterface = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
@@ -786,8 +869,9 @@
 }
 
 void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
-  VisitRedeclarable(VD);
+  RedeclarableResult Redecl = VisitRedeclarable(VD);
   VisitDeclaratorDecl(VD);
+  
   VD->VarDeclBits.SClass = (StorageClass)Record[Idx++];
   VD->VarDeclBits.SClassAsWritten = (StorageClass)Record[Idx++];
   VD->VarDeclBits.ThreadSpecified = Record[Idx++];
@@ -796,8 +880,19 @@
   VD->VarDeclBits.NRVOVariable = Record[Idx++];
   VD->VarDeclBits.CXXForRangeDecl = Record[Idx++];
   VD->VarDeclBits.ARCPseudoStrong = Record[Idx++];
-  if (Record[Idx++])
+
+  // Only true variables (not parameters or implicit parameters) can be merged.
+  if (VD->getKind() == Decl::Var)
+    mergeRedeclarable(VD, Redecl);
+  
+  if (uint64_t Val = Record[Idx++]) {
     VD->setInit(Reader.ReadExpr(F));
+    if (Val > 1) {
+      EvaluatedStmt *Eval = VD->ensureEvaluatedStmt();
+      Eval->CheckedICE = true;
+      Eval->IsICE = Val == 3;
+    }
+  }
 
   if (Record[Idx++]) { // HasMemberSpecializationInfo.
     VarDecl *Tmpl = ReadDeclAs<VarDecl>(Record, Idx);
@@ -878,17 +973,25 @@
 
 
 void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
+  RedeclarableResult Redecl = VisitRedeclarable(D);
   VisitNamedDecl(D);
-  D->IsInline = Record[Idx++];
+  D->setInline(Record[Idx++]);
   D->LocStart = ReadSourceLocation(Record, Idx);
   D->RBraceLoc = ReadSourceLocation(Record, Idx);
-  D->NextNamespace = Record[Idx++];
+  mergeRedeclarable(D, Redecl);
 
-  bool IsOriginal = Record[Idx++];
-  // FIXME: Modules will likely have trouble with pointing directly at
-  // the original namespace.
-  D->OrigOrAnonNamespace.setInt(IsOriginal);
-  D->OrigOrAnonNamespace.setPointer(ReadDeclAs<NamespaceDecl>(Record, Idx));
+  if (Redecl.getFirstID() == ThisDeclID) {
+    // Each module has its own anonymous namespace, which is disjoint from
+    // any other module's anonymous namespaces, so don't attach the anonymous
+    // namespace at all.
+    NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>(Record, Idx);
+    if (F.Kind != MK_Module)
+      D->setAnonymousNamespace(Anon);
+  } else {
+    // Link this namespace back to the first declaration, which has already
+    // been deserialized.
+    D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDeclaration());
+  }
 }
 
 void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
@@ -904,7 +1007,7 @@
   D->setUsingLocation(ReadSourceLocation(Record, Idx));
   D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
   ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
-  D->FirstUsingShadow = ReadDeclAs<UsingShadowDecl>(Record, Idx);
+  D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>(Record, Idx));
   D->setTypeName(Record[Idx++]);
   if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>(Record, Idx))
     Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern);
@@ -994,54 +1097,33 @@
   Data.FirstFriend = ReadDeclAs<FriendDecl>(Record, Idx);
 }
 
-void ASTDeclReader::InitializeCXXDefinitionData(CXXRecordDecl *D,
-                                                CXXRecordDecl *DefinitionDecl,
-                                                const RecordData &Record,
-                                                unsigned &Idx) {
-  ASTContext &C = Reader.getContext();
-
-  if (D == DefinitionDecl) {
-    D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D);
-    ReadCXXDefinitionData(*D->DefinitionData, Record, Idx);
-    // We read the definition info. Check if there are pending forward
-    // references that need to point to this DefinitionData pointer.
-    ASTReader::PendingForwardRefsMap::iterator
-        FindI = Reader.PendingForwardRefs.find(D);
-    if (FindI != Reader.PendingForwardRefs.end()) {
-      ASTReader::ForwardRefs &Refs = FindI->second;
-      for (ASTReader::ForwardRefs::iterator
-             I = Refs.begin(), E = Refs.end(); I != E; ++I)
-        cast<CXXRecordDecl>(*I)->DefinitionData = D->DefinitionData;
-#ifndef NDEBUG
-      // We later check whether PendingForwardRefs is empty to make sure all
-      // pending references were linked.
-      Reader.PendingForwardRefs.erase(D);
-#endif
-    }
-  } else if (DefinitionDecl) {
-    if (DefinitionDecl->DefinitionData) {
-      D->DefinitionData = DefinitionDecl->DefinitionData;
-    } else {
-      // The definition is still initializing.
-      Reader.PendingForwardRefs[DefinitionDecl].push_back(D);
-    }
-  }
-}
-
 void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
   VisitRecordDecl(D);
 
-  CXXRecordDecl *DefinitionDecl = ReadDeclAs<CXXRecordDecl>(Record, Idx);
-  InitializeCXXDefinitionData(D, DefinitionDecl, Record, Idx);
-
   ASTContext &C = Reader.getContext();
+  if (Record[Idx++]) {
+    D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D);
+    
+    // Propagate the DefinitionData pointer to the canonical declaration, so
+    // that all other deserialized declarations will see it.
+    // FIXME: Complain if there already is a DefinitionData!
+    D->getCanonicalDecl()->DefinitionData = D->DefinitionData;
+    
+    ReadCXXDefinitionData(*D->DefinitionData, Record, Idx);
+    
+    // Note that we have deserialized a definition. Any declarations 
+    // deserialized before this one will be be given the DefinitionData pointer
+    // at the end.
+    Reader.PendingDefinitions.insert(D);
+  } else {
+    // Propagate DefinitionData pointer from the canonical declaration.
+    D->DefinitionData = D->getCanonicalDecl()->DefinitionData;    
+  }
 
   enum CXXRecKind {
     CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
   };
   switch ((CXXRecKind)Record[Idx++]) {
-  default:
-    llvm_unreachable("Out of sync with ASTDeclWriter::VisitCXXRecordDecl?");
   case CXXRecNotTemplate:
     break;
   case CXXRecTemplate:
@@ -1147,64 +1229,42 @@
   D->init(TemplatedDecl, TemplateParams);
 }
 
-void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
-  // Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr()
-  // can be used while this is still initializing.
-
-  assert(D->CommonOrPrev.isNull() && "getCommonPtr was called earlier on this");
-  DeclID PreviousDeclID = ReadDeclID(Record, Idx);
-  DeclID FirstDeclID =  PreviousDeclID ? ReadDeclID(Record, Idx) : 0;
-  // We delay loading of the redeclaration chain to avoid deeply nested calls.
-  // We temporarily set the first (canonical) declaration as the previous one
-  // which is the one that matters and mark the real previous DeclID to be
-  // loaded & attached later on.
-  RedeclarableTemplateDecl *FirstDecl =
-      cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(FirstDeclID));
-  assert((FirstDecl == 0 || FirstDecl->getKind() == D->getKind()) &&
-         "FirstDecl kind mismatch");
-  if (FirstDecl) {
-    D->CommonOrPrev = FirstDecl;
-    // Mark the real previous DeclID to be loaded & attached later on.
-    if (PreviousDeclID != FirstDeclID)
-      Reader.PendingPreviousDecls.push_back(std::make_pair(D, PreviousDeclID));
-  } else {
-    D->CommonOrPrev = D->newCommon(Reader.getContext());
+ASTDeclReader::RedeclarableResult 
+ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
+  RedeclarableResult Redecl = VisitRedeclarable(D);
+
+  // Make sure we've allocated the Common pointer first. We do this before
+  // VisitTemplateDecl so that getCommonPtr() can be used during initialization.
+  RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl();
+  if (!CanonD->Common) {
+    CanonD->Common = CanonD->newCommon(Reader.getContext());
+    Reader.PendingDefinitions.insert(CanonD);
+  }
+  D->Common = CanonD->Common;
+
+  // If this is the first declaration of the template, fill in the information
+  // for the 'common' pointer.
+  if (ThisDeclID == Redecl.getFirstID()) {
     if (RedeclarableTemplateDecl *RTD
           = ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx)) {
       assert(RTD->getKind() == D->getKind() &&
              "InstantiatedFromMemberTemplate kind mismatch");
-      D->setInstantiatedFromMemberTemplateImpl(RTD);
+      D->setInstantiatedFromMemberTemplate(RTD);
       if (Record[Idx++])
         D->setMemberSpecialization();
     }
-
-    RedeclarableTemplateDecl *LatestDecl
-      = ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx);
-  
-    // This decl is a first one and the latest declaration that it points to is
-    // in the same AST file. However, if this actually needs to point to a
-    // redeclaration in another AST file, we need to update it by checking
-    // the FirstLatestDeclIDs map which tracks this kind of decls.
-    assert(Reader.GetDecl(ThisDeclID) == D && "Invalid ThisDeclID ?");
-    ASTReader::FirstLatestDeclIDMap::iterator I
-        = Reader.FirstLatestDeclIDs.find(ThisDeclID);
-    if (I != Reader.FirstLatestDeclIDs.end()) {
-      if (Decl *NewLatest = Reader.GetDecl(I->second))
-        LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest);
-    }
-
-    assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch");
-    D->getCommonPtr()->Latest = LatestDecl;
   }
-
+     
   VisitTemplateDecl(D);
   D->IdentifierNamespace = Record[Idx++];
+  
+  return Redecl;
 }
 
 void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
-  VisitRedeclarableTemplateDecl(D);
+  RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
 
-  if (D->getPreviousDeclaration() == 0) {
+  if (ThisDeclID == Redecl.getFirstID()) {
     // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
     // the specializations.
     SmallVector<serialization::DeclID, 2> SpecIDs;
@@ -1226,6 +1286,7 @@
       typedef serialization::DeclID DeclID;
       
       ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
+      // FIXME: Append specializations!
       CommonPtr->LazySpecializations
         = new (Reader.getContext()) DeclID [SpecIDs.size()];
       memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), 
@@ -1306,7 +1367,7 @@
   D->SequenceNumber = Record[Idx++];
 
   // These are read/set from/to the first declaration.
-  if (D->getPreviousDeclaration() == 0) {
+  if (D->getPreviousDecl() == 0) {
     D->InstantiatedFromMember.setPointer(
       ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx));
     D->InstantiatedFromMember.setInt(Record[Idx++]);
@@ -1320,9 +1381,9 @@
 }
 
 void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
-  VisitRedeclarableTemplateDecl(D);
+  RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
 
-  if (D->getPreviousDeclaration() == 0) {
+  if (ThisDeclID == Redecl.getFirstID()) {
     // This FunctionTemplateDecl owns a CommonPtr; read it.
 
     // Read the function specialization declarations.
@@ -1397,73 +1458,90 @@
 }
 
 template <typename T>
-void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
-  enum RedeclKind { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
-  RedeclKind Kind = (RedeclKind)Record[Idx++];
-  switch (Kind) {
-  default:
-    llvm_unreachable("Out of sync with ASTDeclWriter::VisitRedeclarable or"
-                     " messed up reading");
-  case NoRedeclaration:
-    break;
-  case PointsToPrevious: {
-    DeclID PreviousDeclID = ReadDeclID(Record, Idx);
-    DeclID FirstDeclID = ReadDeclID(Record, Idx);
+ASTDeclReader::RedeclarableResult 
+ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
+  DeclID FirstDeclID = ReadDeclID(Record, Idx);
+  
+  // 0 indicates that this declaration was the only declaration of its entity,
+  // and is used for space optimization.
+  if (FirstDeclID == 0)
+    FirstDeclID = ThisDeclID;
+  
+  T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
+  if (FirstDecl != D) {
     // We delay loading of the redeclaration chain to avoid deeply nested calls.
     // We temporarily set the first (canonical) declaration as the previous one
     // which is the one that matters and mark the real previous DeclID to be
     // loaded & attached later on.
-    T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
     D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(FirstDecl);
-    if (PreviousDeclID != FirstDeclID)
-      Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D),
-                                                           PreviousDeclID));
-
-    // If the first declaration in the chain is in an inconsistent
-    // state where it thinks that it is the only declaration, fix its
-    // redeclaration link now to point at this declaration, so that we have a 
-    // proper redeclaration chain.
-    if (FirstDecl->RedeclLink.getPointer() == FirstDecl) {
-      FirstDecl->RedeclLink
-        = typename Redeclarable<T>::LatestDeclLink(static_cast<T*>(D));
-    }
-    break;
-  }
-  case PointsToLatest: {
-    T *LatestDecl = ReadDeclAs<T>(Record, Idx);
-    D->RedeclLink = typename Redeclarable<T>::LatestDeclLink(LatestDecl);
-    
-    // If the latest declaration in the chain is in an inconsistent
-    // state where it thinks that it is the only declaration, fix its
-    // redeclaration link now to point at this declaration, so that we have a 
-    // proper redeclaration chain.
-    if (LatestDecl->RedeclLink.getPointer() == LatestDecl) {
-      LatestDecl->RedeclLink
-        = typename Redeclarable<T>::PreviousDeclLink(static_cast<T*>(D));
-    }
-    break;
-  }
-  }
+  }    
+  
+  // Note that this declaration has been deserialized.
+  Reader.RedeclsDeserialized.insert(static_cast<T *>(D));
+                             
+  // The result structure takes care to note that we need to load the 
+  // other declaration chains for this ID.
+  return RedeclarableResult(Reader, FirstDeclID);
+}
 
-  assert(!(Kind == PointsToPrevious &&
-           Reader.FirstLatestDeclIDs.find(ThisDeclID) !=
-               Reader.FirstLatestDeclIDs.end()) &&
-         "This decl is not first, it should not be in the map");
-  if (Kind == PointsToPrevious)
+/// \brief Attempts to merge the given declaration (D) with another declaration
+/// of the same entity.
+template<typename T>
+void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, 
+                                      RedeclarableResult &Redecl) {
+  // If modules are not available, there is no reason to perform this merge.
+  if (!Reader.getContext().getLangOptions().Modules)
     return;
-
-  // This decl is a first one and the latest declaration that it points to is in
-  // the same AST file. However, if this actually needs to point to a
-  // redeclaration in another AST file, we need to update it by checking the
-  // FirstLatestDeclIDs map which tracks this kind of decls.
-  assert(Reader.GetDecl(ThisDeclID) == static_cast<T*>(D) &&
-         "Invalid ThisDeclID ?");
-  ASTReader::FirstLatestDeclIDMap::iterator I
-      = Reader.FirstLatestDeclIDs.find(ThisDeclID);
-  if (I != Reader.FirstLatestDeclIDs.end()) {
-    Decl *NewLatest = Reader.GetDecl(I->second);
-    D->RedeclLink
-        = typename Redeclarable<T>::LatestDeclLink(cast_or_null<T>(NewLatest));
+  
+  if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) {
+    if (T *Existing = ExistingRes) {
+      T *ExistingCanon = Existing->getCanonicalDecl();
+      T *DCanon = static_cast<T*>(D)->getCanonicalDecl();
+      if (ExistingCanon != DCanon) {
+        // Have our redeclaration link point back at the canonical declaration
+        // of the existing declaration, so that this declaration has the 
+        // appropriate canonical declaration.
+        D->RedeclLink 
+          = typename Redeclarable<T>::PreviousDeclLink(ExistingCanon);
+        
+        // When we merge a namespace, update its pointer to the first namespace.
+        if (NamespaceDecl *Namespace
+              = dyn_cast<NamespaceDecl>(static_cast<T*>(D))) {
+          Namespace->AnonOrFirstNamespaceAndInline.setPointer(
+            static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon)));
+        }
+        
+        // Don't introduce DCanon into the set of pending declaration chains.
+        Redecl.suppress();
+        
+        // Introduce ExistingCanon into the set of pending declaration chains,
+        // if in fact it came from a module file.
+        if (ExistingCanon->isFromASTFile()) {
+          GlobalDeclID ExistingCanonID = ExistingCanon->getGlobalID();
+          assert(ExistingCanonID && "Unrecorded canonical declaration ID?");
+          if (Reader.PendingDeclChainsKnown.insert(ExistingCanonID))
+            Reader.PendingDeclChains.push_back(ExistingCanonID);
+        }
+        
+        // If this declaration was the canonical declaration, make a note of 
+        // that. We accept the linear algorithm here because the number of 
+        // unique canonical declarations of an entity should always be tiny.
+        if (DCanon == static_cast<T*>(D)) {
+          SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon];
+          if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
+                == Merged.end())
+            Merged.push_back(Redecl.getFirstID());
+          
+          // If ExistingCanon did not come from a module file, introduce the
+          // first declaration that *does* come from a module file to the 
+          // set of pending declaration chains, so that we merge this 
+          // declaration.
+          if (!ExistingCanon->isFromASTFile() &&
+              Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID()))
+            Reader.PendingDeclChains.push_back(Merged[0]);
+        }
+      }
+    }
   }
 }
 
@@ -1556,6 +1634,113 @@
   return LocalOffset + M.GlobalBitOffset;
 }
 
+/// \brief Determine whether the two declarations refer to the same entity.
+static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
+  assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");
+  
+  if (X == Y)
+    return true;
+  
+  // Must be in the same context.
+  if (!X->getDeclContext()->getRedeclContext()->Equals(
+         Y->getDeclContext()->getRedeclContext()))
+    return false;
+
+  // Two typedefs refer to the same entity if they have the same underlying
+  // type.
+  if (TypedefNameDecl *TypedefX = dyn_cast<TypedefNameDecl>(X))
+    if (TypedefNameDecl *TypedefY = dyn_cast<TypedefNameDecl>(Y))
+      return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(),
+                                            TypedefY->getUnderlyingType());
+  
+  // Must have the same kind.
+  if (X->getKind() != Y->getKind())
+    return false;
+    
+  // Objective-C classes and protocols with the same name always match.
+  if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X))
+    return true;
+  
+  // Compatible tags match.
+  if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {
+    TagDecl *TagY = cast<TagDecl>(Y);
+    return (TagX->getTagKind() == TagY->getTagKind()) ||
+      ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class) &&
+       (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class));
+  }
+  
+  // Functions with the same type and linkage match.
+  // FIXME: This needs to cope with function templates, merging of 
+  //prototyped/non-prototyped functions, etc.
+  if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) {
+    FunctionDecl *FuncY = cast<FunctionDecl>(Y);
+    return (FuncX->getLinkage() == FuncY->getLinkage()) &&
+      FuncX->getASTContext().hasSameType(FuncX->getType(), FuncY->getType());
+  }
+  
+  // Variables with the same type and linkage match.
+  if (VarDecl *VarX = dyn_cast<VarDecl>(X)) {
+    VarDecl *VarY = cast<VarDecl>(Y);
+    return (VarX->getLinkage() == VarY->getLinkage()) &&
+      VarX->getASTContext().hasSameType(VarX->getType(), VarY->getType());
+  }
+  
+  // Namespaces with the same name and inlinedness match.
+  if (NamespaceDecl *NamespaceX = dyn_cast<NamespaceDecl>(X)) {
+    NamespaceDecl *NamespaceY = cast<NamespaceDecl>(Y);
+    return NamespaceX->isInline() == NamespaceY->isInline();
+  }
+      
+  // FIXME: Many other cases to implement.
+  return false;
+}
+
+ASTDeclReader::FindExistingResult::~FindExistingResult() {
+  if (!AddResult || Existing)
+    return;
+  
+  DeclContext *DC = New->getDeclContext()->getRedeclContext();
+  if (DC->isTranslationUnit() && Reader.SemaObj) {
+    Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, New->getDeclName());
+  } else if (DC->isNamespace()) {
+    DC->addDecl(New);
+  }
+}
+
+ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
+  DeclarationName Name = D->getDeclName();
+  if (!Name) {
+    // Don't bother trying to find unnamed declarations.
+    FindExistingResult Result(Reader, D, /*Existing=*/0);
+    Result.suppress();
+    return Result;
+  }
+  
+  DeclContext *DC = D->getDeclContext()->getRedeclContext();
+  if (!DC->isFileContext())
+    return FindExistingResult(Reader);
+  
+  if (DC->isTranslationUnit() && Reader.SemaObj) {
+    IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver;
+    for (IdentifierResolver::iterator I = IdResolver.begin(Name), 
+                                   IEnd = IdResolver.end();
+         I != IEnd; ++I) {
+      if (isSameEntity(*I, D))
+        return FindExistingResult(Reader, D, *I);
+    }
+  }
+
+  if (DC->isNamespace()) {
+    for (DeclContext::lookup_result R = DC->lookup(Name);
+         R.first != R.second; ++R.first) {
+      if (isSameEntity(*R.first, D))
+        return FindExistingResult(Reader, D, *R.first);
+    }
+  }
+  
+  return FindExistingResult(Reader, D, /*Existing=*/0);
+}
+
 void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
   assert(D && previous);
   if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
@@ -1564,14 +1749,78 @@
     FD->RedeclLink.setPointer(cast<FunctionDecl>(previous));
   } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
     VD->RedeclLink.setPointer(cast<VarDecl>(previous));
-  } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(previous)) {
+  } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+    TD->RedeclLink.setPointer(cast<TypedefNameDecl>(previous));
+  } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
     ID->RedeclLink.setPointer(cast<ObjCInterfaceDecl>(previous));
+  } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
+    PD->RedeclLink.setPointer(cast<ObjCProtocolDecl>(previous));
+  } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) {
+    ND->RedeclLink.setPointer(cast<NamespaceDecl>(previous));
   } else {
     RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
-    TD->CommonOrPrev = cast<RedeclarableTemplateDecl>(previous);
+    TD->RedeclLink.setPointer(cast<RedeclarableTemplateDecl>(previous));
   }
 }
 
+void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
+  assert(D && Latest);
+  if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+    TD->RedeclLink
+      = Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest));
+  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    FD->RedeclLink 
+      = Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest));
+  } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    VD->RedeclLink
+      = Redeclarable<VarDecl>::LatestDeclLink(cast<VarDecl>(Latest));
+  } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+    TD->RedeclLink
+      = Redeclarable<TypedefNameDecl>::LatestDeclLink(
+                                                cast<TypedefNameDecl>(Latest));
+  } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
+    ID->RedeclLink
+      = Redeclarable<ObjCInterfaceDecl>::LatestDeclLink(
+                                              cast<ObjCInterfaceDecl>(Latest));
+  } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
+    PD->RedeclLink
+      = Redeclarable<ObjCProtocolDecl>::LatestDeclLink(
+                                                cast<ObjCProtocolDecl>(Latest));
+  } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) {
+    ND->RedeclLink
+      = Redeclarable<NamespaceDecl>::LatestDeclLink(
+                                                   cast<NamespaceDecl>(Latest));
+  } else {
+    RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
+    TD->RedeclLink
+      = Redeclarable<RedeclarableTemplateDecl>::LatestDeclLink(
+                                        cast<RedeclarableTemplateDecl>(Latest));
+  }
+}
+
+ASTReader::MergedDeclsMap::iterator
+ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) {
+  // If we don't have any stored merged declarations, just look in the
+  // merged declarations set.
+  StoredMergedDeclsMap::iterator StoredPos = StoredMergedDecls.find(CanonID);
+  if (StoredPos == StoredMergedDecls.end())
+    return MergedDecls.find(Canon);
+
+  // Append the stored merged declarations to the merged declarations set.
+  MergedDeclsMap::iterator Pos = MergedDecls.find(Canon);
+  if (Pos == MergedDecls.end())
+    Pos = MergedDecls.insert(std::make_pair(Canon, 
+                                            SmallVector<DeclID, 2>())).first;
+  Pos->second.append(StoredPos->second.begin(), StoredPos->second.end());
+  StoredMergedDecls.erase(StoredPos);
+  
+  // Sort and uniquify the set of merged declarations.
+  llvm::array_pod_sort(Pos->second.begin(), Pos->second.end());
+  Pos->second.erase(std::unique(Pos->second.begin(), Pos->second.end()),
+                    Pos->second.end());
+  return Pos;
+}
+
 void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) {
   Decl *previous = GetDecl(ID);
   ASTDeclReader::attachPreviousDecl(D, previous);
@@ -1604,214 +1853,160 @@
   case DECL_CONTEXT_VISIBLE:
     llvm_unreachable("Record cannot be de-serialized with ReadDeclRecord");
   case DECL_TYPEDEF:
-    D = TypedefDecl::Create(Context, 0, SourceLocation(), SourceLocation(),
-                            0, 0);
+    D = TypedefDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_TYPEALIAS:
-    D = TypeAliasDecl::Create(Context, 0, SourceLocation(), SourceLocation(),
-                              0, 0);
+    D = TypeAliasDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_ENUM:
-    D = EnumDecl::Create(Context, Decl::EmptyShell());
+    D = EnumDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_RECORD:
-    D = RecordDecl::Create(Context, Decl::EmptyShell());
+    D = RecordDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_ENUM_CONSTANT:
-    D = EnumConstantDecl::Create(Context, 0, SourceLocation(), 0, QualType(),
-                                 0, llvm::APSInt());
+    D = EnumConstantDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_FUNCTION:
-    D = FunctionDecl::Create(Context, 0, SourceLocation(), SourceLocation(),
-                             DeclarationName(), QualType(), 0);
+    D = FunctionDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_LINKAGE_SPEC:
-    D = LinkageSpecDecl::Create(Context, 0, SourceLocation(), SourceLocation(),
-                                (LinkageSpecDecl::LanguageIDs)0,
-                                SourceLocation());
+    D = LinkageSpecDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_LABEL:
-    D = LabelDecl::Create(Context, 0, SourceLocation(), 0);
+    D = LabelDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_NAMESPACE:
-    D = NamespaceDecl::Create(Context, 0, SourceLocation(),
-                              SourceLocation(), 0);
+    D = NamespaceDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_NAMESPACE_ALIAS:
-    D = NamespaceAliasDecl::Create(Context, 0, SourceLocation(),
-                                   SourceLocation(), 0, 
-                                   NestedNameSpecifierLoc(),
-                                   SourceLocation(), 0);
+    D = NamespaceAliasDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_USING:
-    D = UsingDecl::Create(Context, 0, SourceLocation(),
-                          NestedNameSpecifierLoc(), DeclarationNameInfo(), 
-                          false);
+    D = UsingDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_USING_SHADOW:
-    D = UsingShadowDecl::Create(Context, 0, SourceLocation(), 0, 0);
+    D = UsingShadowDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_USING_DIRECTIVE:
-    D = UsingDirectiveDecl::Create(Context, 0, SourceLocation(),
-                                   SourceLocation(), NestedNameSpecifierLoc(),
-                                   SourceLocation(), 0, 0);
+    D = UsingDirectiveDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_UNRESOLVED_USING_VALUE:
-    D = UnresolvedUsingValueDecl::Create(Context, 0, SourceLocation(),
-                                         NestedNameSpecifierLoc(), 
-                                         DeclarationNameInfo());
+    D = UnresolvedUsingValueDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_UNRESOLVED_USING_TYPENAME:
-    D = UnresolvedUsingTypenameDecl::Create(Context, 0, SourceLocation(),
-                                            SourceLocation(), 
-                                            NestedNameSpecifierLoc(),
-                                            SourceLocation(),
-                                            DeclarationName());
+    D = UnresolvedUsingTypenameDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_CXX_RECORD:
-    D = CXXRecordDecl::Create(Context, Decl::EmptyShell());
+    D = CXXRecordDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_CXX_METHOD:
-    D = CXXMethodDecl::Create(Context, 0, SourceLocation(),
-                              DeclarationNameInfo(), QualType(), 0,
-                              false, SC_None, false, false, SourceLocation());
+    D = CXXMethodDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_CXX_CONSTRUCTOR:
-    D = CXXConstructorDecl::Create(Context, Decl::EmptyShell());
+    D = CXXConstructorDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_CXX_DESTRUCTOR:
-    D = CXXDestructorDecl::Create(Context, Decl::EmptyShell());
+    D = CXXDestructorDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_CXX_CONVERSION:
-    D = CXXConversionDecl::Create(Context, Decl::EmptyShell());
+    D = CXXConversionDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_ACCESS_SPEC:
-    D = AccessSpecDecl::Create(Context, Decl::EmptyShell());
+    D = AccessSpecDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_FRIEND:
-    D = FriendDecl::Create(Context, Decl::EmptyShell());
+    D = FriendDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_FRIEND_TEMPLATE:
-    D = FriendTemplateDecl::Create(Context, Decl::EmptyShell());
+    D = FriendTemplateDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_CLASS_TEMPLATE:
-    D = ClassTemplateDecl::Create(Context, Decl::EmptyShell());
+    D = ClassTemplateDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_CLASS_TEMPLATE_SPECIALIZATION:
-    D = ClassTemplateSpecializationDecl::Create(Context, Decl::EmptyShell());
+    D = ClassTemplateSpecializationDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION:
-    D = ClassTemplatePartialSpecializationDecl::Create(Context,
-                                                       Decl::EmptyShell());
+    D = ClassTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION:
-    D = ClassScopeFunctionSpecializationDecl::Create(Context,
-                                                     Decl::EmptyShell());
+    D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_FUNCTION_TEMPLATE:
-      D = FunctionTemplateDecl::Create(Context, Decl::EmptyShell());
+    D = FunctionTemplateDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_TEMPLATE_TYPE_PARM:
-    D = TemplateTypeParmDecl::Create(Context, Decl::EmptyShell());
+    D = TemplateTypeParmDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_NON_TYPE_TEMPLATE_PARM:
-    D = NonTypeTemplateParmDecl::Create(Context, 0, SourceLocation(),
-                                        SourceLocation(), 0, 0, 0, QualType(),
-                                        false, 0);
+    D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK:
-    D = NonTypeTemplateParmDecl::Create(Context, 0, SourceLocation(),
-                                        SourceLocation(), 0, 0, 0, QualType(),
-                                        0, 0, Record[Idx++], 0);
+    D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID, Record[Idx++]);
     break;
   case DECL_TEMPLATE_TEMPLATE_PARM:
-    D = TemplateTemplateParmDecl::Create(Context, 0, SourceLocation(), 0, 0,
-                                         false, 0, 0);
+    D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_TYPE_ALIAS_TEMPLATE:
-    D = TypeAliasTemplateDecl::Create(Context, Decl::EmptyShell());
+    D = TypeAliasTemplateDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_STATIC_ASSERT:
-    D = StaticAssertDecl::Create(Context, 0, SourceLocation(), 0, 0,
-                                 SourceLocation());
+    D = StaticAssertDecl::CreateDeserialized(Context, ID);
     break;
-
   case DECL_OBJC_METHOD:
-    D = ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(),
-                               Selector(), QualType(), 0, 0);
+    D = ObjCMethodDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_OBJC_INTERFACE:
-    D = ObjCInterfaceDecl::CreateEmpty(Context);
+    D = ObjCInterfaceDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_OBJC_IVAR:
-    D = ObjCIvarDecl::Create(Context, 0, SourceLocation(), SourceLocation(),
-                             0, QualType(), 0, ObjCIvarDecl::None);
+    D = ObjCIvarDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_OBJC_PROTOCOL:
-    D = ObjCProtocolDecl::Create(Context, 0, 0, SourceLocation(),
-                                 SourceLocation(), 0);
+    D = ObjCProtocolDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_OBJC_AT_DEFS_FIELD:
-    D = ObjCAtDefsFieldDecl::Create(Context, 0, SourceLocation(),
-                                    SourceLocation(), 0, QualType(), 0);
-    break;
-  case DECL_OBJC_CLASS:
-    D = ObjCClassDecl::Create(Context, 0, SourceLocation());
-    break;
-  case DECL_OBJC_FORWARD_PROTOCOL:
-    D = ObjCForwardProtocolDecl::Create(Context, 0, SourceLocation());
+    D = ObjCAtDefsFieldDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_OBJC_CATEGORY:
-    D = ObjCCategoryDecl::Create(Context, Decl::EmptyShell());
+    D = ObjCCategoryDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_OBJC_CATEGORY_IMPL:
-    D = ObjCCategoryImplDecl::Create(Context, 0, 0, 0, SourceLocation(),
-                                     SourceLocation(), SourceLocation());
+    D = ObjCCategoryImplDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_OBJC_IMPLEMENTATION:
-    D = ObjCImplementationDecl::Create(Context, 0, 0, 0, SourceLocation(),
-                                       SourceLocation());
+    D = ObjCImplementationDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_OBJC_COMPATIBLE_ALIAS:
-    D = ObjCCompatibleAliasDecl::Create(Context, 0, SourceLocation(), 0, 0);
+    D = ObjCCompatibleAliasDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_OBJC_PROPERTY:
-    D = ObjCPropertyDecl::Create(Context, 0, SourceLocation(), 0, SourceLocation(),
-                                 0);
+    D = ObjCPropertyDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_OBJC_PROPERTY_IMPL:
-    D = ObjCPropertyImplDecl::Create(Context, 0, SourceLocation(),
-                                     SourceLocation(), 0,
-                                     ObjCPropertyImplDecl::Dynamic, 0,
-                                     SourceLocation());
+    D = ObjCPropertyImplDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_FIELD:
-    D = FieldDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0,
-                          QualType(), 0, 0, false, false);
+    D = FieldDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_INDIRECTFIELD:
-    D = IndirectFieldDecl::Create(Context, 0, SourceLocation(), 0, QualType(),
-                                  0, 0);
+    D = IndirectFieldDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_VAR:
-    D = VarDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0,
-                        QualType(), 0, SC_None, SC_None);
+    D = VarDecl::CreateDeserialized(Context, ID);
     break;
-
   case DECL_IMPLICIT_PARAM:
-    D = ImplicitParamDecl::Create(Context, 0, SourceLocation(), 0, QualType());
+    D = ImplicitParamDecl::CreateDeserialized(Context, ID);
     break;
-
   case DECL_PARM_VAR:
-    D = ParmVarDecl::Create(Context, 0, SourceLocation(), SourceLocation(), 0,
-                            QualType(), 0, SC_None, SC_None, 0);
+    D = ParmVarDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_FILE_SCOPE_ASM:
-    D = FileScopeAsmDecl::Create(Context, 0, 0, SourceLocation(),
-                                 SourceLocation());
+    D = FileScopeAsmDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_BLOCK:
-    D = BlockDecl::Create(Context, 0, SourceLocation());
+    D = BlockDecl::CreateDeserialized(Context, ID);
     break;
   case DECL_CXX_BASE_SPECIFIERS:
     Error("attempt to read a C++ base-specifier record as a declaration");
@@ -1819,7 +2014,7 @@
   case DECL_IMPORT:
     // Note: last entry of the ImportDecl record is the number of stored source 
     // locations.
-    D = ImportDecl::CreateEmpty(Context, Record.back());
+    D = ImportDecl::CreateDeserialized(Context, ID, Record.back());
     break;
   }
 
@@ -1904,6 +2099,147 @@
 }
 
 namespace {
+  struct CompareLocalRedeclarationsInfoToID {
+    bool operator()(const LocalRedeclarationsInfo &X, DeclID Y) {
+      return X.FirstID < Y;
+    }
+
+    bool operator()(DeclID X, const LocalRedeclarationsInfo &Y) {
+      return X < Y.FirstID;
+    }
+
+    bool operator()(const LocalRedeclarationsInfo &X, 
+                    const LocalRedeclarationsInfo &Y) {
+      return X.FirstID < Y.FirstID;
+    }
+    bool operator()(DeclID X, DeclID Y) {
+      return X < Y;
+    }
+  };
+  
+  /// \brief Module visitor class that finds all of the redeclarations of a 
+  /// 
+  class RedeclChainVisitor {
+    ASTReader &Reader;
+    SmallVectorImpl<DeclID> &SearchDecls;
+    llvm::SmallPtrSet<Decl *, 16> &Deserialized;
+    GlobalDeclID CanonID;
+    llvm::SmallVector<Decl *, 4> Chain;
+    
+  public:
+    RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID> &SearchDecls,
+                       llvm::SmallPtrSet<Decl *, 16> &Deserialized,
+                       GlobalDeclID CanonID)
+      : Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized),
+        CanonID(CanonID) { 
+      for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
+        addToChain(Reader.GetDecl(SearchDecls[I]));
+    }
+    
+    static bool visit(ModuleFile &M, bool Preorder, void *UserData) {
+      if (Preorder)
+        return false;
+      
+      return static_cast<RedeclChainVisitor *>(UserData)->visit(M);
+    }
+    
+    void addToChain(Decl *D) {
+      if (!D)
+        return;
+      
+      if (Deserialized.count(D)) {
+        Deserialized.erase(D);
+        Chain.push_back(D);
+      }
+    }
+    
+    void searchForID(ModuleFile &M, GlobalDeclID GlobalID) {
+      // Map global ID of the first declaration down to the local ID
+      // used in this module file.
+      DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID);
+      if (!ID)
+        return;
+      
+      // Perform a binary search to find the local redeclarations for this
+      // declaration (if any).
+      const LocalRedeclarationsInfo *Result
+        = std::lower_bound(M.RedeclarationsMap,
+                           M.RedeclarationsMap + M.LocalNumRedeclarationsInMap, 
+                           ID, CompareLocalRedeclarationsInfoToID());
+      if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap ||
+          Result->FirstID != ID) {
+        // If we have a previously-canonical singleton declaration that was 
+        // merged into another redeclaration chain, create a trivial chain
+        // for this single declaration so that it will get wired into the 
+        // complete redeclaration chain.
+        if (GlobalID != CanonID && 
+            GlobalID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID && 
+            GlobalID - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls) {
+          addToChain(Reader.GetDecl(GlobalID));
+        }
+        
+        return;
+      }
+      
+      // Dig out the starting/ending declarations.
+      unsigned Offset = Result->Offset;
+      unsigned N = M.RedeclarationChains[Offset];
+      M.RedeclarationChains[Offset++] = 0; // Don't try to deserialize again
+      for (unsigned I = 0; I != N; ++I)
+        addToChain(Reader.GetLocalDecl(M, M.RedeclarationChains[Offset++]));
+    }
+    
+    bool visit(ModuleFile &M) {
+      // Visit each of the declarations.
+      for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
+        searchForID(M, SearchDecls[I]);
+      return false;
+    }
+    
+    ArrayRef<Decl *> getChain() const {
+      return Chain;
+    }
+  };
+}
+
+void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) {
+  Decl *D = GetDecl(ID);  
+  Decl *CanonDecl = D->getCanonicalDecl();
+  
+  // Determine the set of declaration IDs we'll be searching for.
+  llvm::SmallVector<DeclID, 1> SearchDecls;
+  GlobalDeclID CanonID = 0;
+  if (D == CanonDecl) {
+    SearchDecls.push_back(ID); // Always first.
+    CanonID = ID;
+  }
+  MergedDeclsMap::iterator MergedPos = combineStoredMergedDecls(CanonDecl, ID);
+  if (MergedPos != MergedDecls.end())
+    SearchDecls.append(MergedPos->second.begin(), MergedPos->second.end());  
+  
+  // Build up the list of redeclarations.
+  RedeclChainVisitor Visitor(*this, SearchDecls, RedeclsDeserialized, CanonID);
+  ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visit, &Visitor);
+  
+  // Retrieve the chains.
+  ArrayRef<Decl *> Chain = Visitor.getChain();
+  if (Chain.empty())
+    return;
+    
+  // Hook up the chains.
+  Decl *MostRecent = CanonDecl->getMostRecentDecl();
+  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+    if (Chain[I] == CanonDecl)
+      continue;
+    
+    ASTDeclReader::attachPreviousDecl(Chain[I], MostRecent);
+    MostRecent = Chain[I];
+  }
+  
+  ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent);  
+}
+
+namespace {
   /// \brief Given an ObjC interface, goes through the modules and links to the
   /// interface all the categories for it.
   class ObjCChainedCategoriesVisitor {
@@ -2034,15 +2370,6 @@
   unsigned Idx = 0;
   while (Idx < Record.size()) {
     switch ((DeclUpdateKind)Record[Idx++]) {
-    case UPD_CXX_SET_DEFINITIONDATA: {
-      CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
-      CXXRecordDecl *DefinitionDecl
-        = Reader.ReadDeclAs<CXXRecordDecl>(ModuleFile, Record, Idx);
-      assert(!RD->DefinitionData && "DefinitionData is already set!");
-      InitializeCXXDefinitionData(RD, DefinitionDecl, Record, Idx);
-      break;
-    }
-
     case UPD_CXX_ADDED_IMPLICIT_MEMBER:
       cast<CXXRecordDecl>(D)->addedMember(Reader.ReadDecl(ModuleFile, Record, Idx));
       break;
@@ -2055,14 +2382,15 @@
     case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: {
       NamespaceDecl *Anon
         = Reader.ReadDeclAs<NamespaceDecl>(ModuleFile, Record, Idx);
-      // Guard against these being loaded out of original order. Don't use
-      // getNextNamespace(), since it tries to access the context and can't in
-      // the middle of deserialization.
-      if (!Anon->NextNamespace) {
+      
+      // Each module has its own anonymous namespace, which is disjoint from
+      // any other module's anonymous namespaces, so don't attach the anonymous
+      // namespace at all.
+      if (ModuleFile.Kind != MK_Module) {
         if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(D))
           TU->setAnonymousNamespace(Anon);
         else
-          cast<NamespaceDecl>(D)->OrigOrAnonNamespace.setPointer(Anon);
+          cast<NamespaceDecl>(D)->setAnonymousNamespace(Anon);
       }
       break;
     }
@@ -2071,19 +2399,6 @@
       cast<VarDecl>(D)->getMemberSpecializationInfo()->setPointOfInstantiation(
           Reader.ReadSourceLocation(ModuleFile, Record, Idx));
       break;
-    
-    case UPD_OBJC_SET_CLASS_DEFINITIONDATA: {
-      ObjCInterfaceDecl *ID = cast<ObjCInterfaceDecl>(D);
-      ObjCInterfaceDecl *Def
-        = Reader.ReadDeclAs<ObjCInterfaceDecl>(ModuleFile, Record, Idx);
-      if (Def->Data) {
-        ID->Data = Def->Data;
-      } else {
-        // The definition is still initializing.
-        Reader.PendingForwardRefs[Def].push_back(ID);
-      }
-      break;
-    }
     }
   }
 }

Modified: cfe/branches/tooling/lib/Serialization/ASTReaderInternals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Serialization/ASTReaderInternals.h?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Serialization/ASTReaderInternals.h (original)
+++ cfe/branches/tooling/lib/Serialization/ASTReaderInternals.h Fri Jan 20 10:14:22 2012
@@ -15,6 +15,7 @@
 
 #include "clang/Basic/OnDiskHashTable.h"
 #include "clang/AST/DeclarationName.h"
+#include "llvm/Support/Endian.h"
 #include <utility>
 #include <sys/stat.h>
 
@@ -41,7 +42,8 @@
   ///
   /// Note that these declaration IDs are local to the module that contains this
   /// particular lookup t
-  typedef std::pair<DeclID *, DeclID *> data_type;
+  typedef llvm::support::ulittle32_t LE32DeclID;
+  typedef std::pair<LE32DeclID *, LE32DeclID *> data_type;
 
   /// \brief Special internal key for declaration names.
   /// The hash table creates keys for comparison; we do not create

Modified: cfe/branches/tooling/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Serialization/ASTReaderStmt.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/branches/tooling/lib/Serialization/ASTReaderStmt.cpp Fri Jan 20 10:14:22 2012
@@ -879,6 +879,7 @@
   unsigned NumStoredSelLocs = Record[Idx++];
   E->SelLocsKind = Record[Idx++]; 
   E->setDelegateInitCall(Record[Idx++]);
+  E->IsImplicit = Record[Idx++];
   ObjCMessageExpr::ReceiverKind Kind
     = static_cast<ObjCMessageExpr::ReceiverKind>(Record[Idx++]);
   switch (Kind) {
@@ -1446,7 +1447,6 @@
   }
 
   llvm_unreachable("ReadingKind not set ?");
-  return 0;
 }
 
 Expr *ASTReader::ReadExpr(ModuleFile &F) {
@@ -1811,7 +1811,6 @@
       break;
     case EXPR_OBJC_KVC_REF_EXPR:
       llvm_unreachable("mismatching AST file");
-      break;
     case EXPR_OBJC_MESSAGE_EXPR:
       S = ObjCMessageExpr::CreateEmpty(Context,
                                      Record[ASTStmtReader::NumExprFields],

Modified: cfe/branches/tooling/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Serialization/ASTWriter.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/branches/tooling/lib/Serialization/ASTWriter.cpp Fri Jan 20 10:14:22 2012
@@ -239,7 +239,7 @@
 
 void ASTTypeWriter::VisitTagType(const TagType *T) {
   Record.push_back(T->isDependentType());
-  Writer.AddDeclRef(T->getDecl(), Record);
+  Writer.AddDeclRef(T->getDecl()->getCanonicalDecl(), Record);
   assert(!T->isBeingDefined() &&
          "Cannot serialize in the middle of a type definition");
 }
@@ -369,7 +369,7 @@
 }
 
 void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
-  Writer.AddDeclRef(T->getDecl(), Record);
+  Writer.AddDeclRef(T->getDecl()->getCanonicalDecl(), Record);
   Code = TYPE_OBJC_INTERFACE;
 }
 
@@ -778,7 +778,7 @@
   RECORD(IMPORTS);
   RECORD(REFERENCED_SELECTOR_POOL);
   RECORD(TU_UPDATE_LEXICAL);
-  RECORD(REDECLS_UPDATE_LATEST);
+  RECORD(LOCAL_REDECLARATIONS_MAP);
   RECORD(SEMA_DECL_REFS);
   RECORD(WEAK_UNDECLARED_IDENTIFIERS);
   RECORD(PENDING_IMPLICIT_INSTANTIATIONS);
@@ -798,7 +798,12 @@
   RECORD(KNOWN_NAMESPACES);
   RECORD(MODULE_OFFSET_MAP);
   RECORD(SOURCE_MANAGER_LINE_TABLE);
-  
+  RECORD(OBJC_CHAINED_CATEGORIES);
+  RECORD(FILE_SORTED_DECLS);
+  RECORD(IMPORTED_MODULES);
+  RECORD(MERGED_DECLARATIONS);
+  RECORD(LOCAL_REDECLARATIONS);
+
   // SourceManager Block.
   BLOCK(SOURCE_MANAGER_BLOCK);
   RECORD(SM_SLOC_FILE_ENTRY);
@@ -862,8 +867,6 @@
   RECORD(DECL_OBJC_PROTOCOL);
   RECORD(DECL_OBJC_IVAR);
   RECORD(DECL_OBJC_AT_DEFS_FIELD);
-  RECORD(DECL_OBJC_CLASS);
-  RECORD(DECL_OBJC_FORWARD_PROTOCOL);
   RECORD(DECL_OBJC_CATEGORY);
   RECORD(DECL_OBJC_CATEGORY_IMPL);
   RECORD(DECL_OBJC_IMPLEMENTATION);
@@ -1657,8 +1660,9 @@
   for (Preprocessor::macro_iterator I = PP.macro_begin(Chain == 0), 
                                     E = PP.macro_end(Chain == 0);
        I != E; ++I) {
+    const IdentifierInfo *Name = I->first;
     if (!IsModule || I->second->isPublic()) {
-      MacroDefinitionsSeen.insert(I->first);
+      MacroDefinitionsSeen.insert(Name);
       MacrosToEmit.push_back(std::make_pair(I->first, I->second));
     }
   }
@@ -1857,10 +1861,10 @@
 /// given module).
 static unsigned getNumberOfModules(Module *Mod) {
   unsigned ChildModules = 0;
-  for (llvm::StringMap<Module *>::iterator Sub = Mod->SubModules.begin(),
-                                        SubEnd = Mod->SubModules.end();
+  for (Module::submodule_iterator Sub = Mod->submodule_begin(),
+                               SubEnd = Mod->submodule_end();
        Sub != SubEnd; ++Sub)
-    ChildModules += getNumberOfModules(Sub->getValue());
+    ChildModules += getNumberOfModules(*Sub);
   
   return ChildModules + 1;
 }
@@ -1874,7 +1878,6 @@
   for (ASTContext::import_iterator I = Context->local_import_begin(),
                                 IEnd = Context->local_import_end();
        I != IEnd; ++I) {
-    assert(SubmoduleIDs.find(I->getImportedModule()) != SubmoduleIDs.end());
     if (Module *ImportedFrom
           = ModMap.inferModuleFromLocation(FullSourceLoc(I->getLocation(), 
                                                          SrcMgr))) {
@@ -1914,6 +1917,11 @@
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
   unsigned UmbrellaDirAbbrev = Stream.EmitAbbrev(Abbrev);
 
+  Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_REQUIRES));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature
+  unsigned RequiresAbbrev = Stream.EmitAbbrev(Abbrev);
+
   // Write the submodule metadata block.
   RecordData Record;
   Record.push_back(getNumberOfModules(WritingModule));
@@ -1945,6 +1953,15 @@
     Record.push_back(Mod->InferExportWildcard);
     Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
     
+    // Emit the requirements.
+    for (unsigned I = 0, N = Mod->Requires.size(); I != N; ++I) {
+      Record.clear();
+      Record.push_back(SUBMODULE_REQUIRES);
+      Stream.EmitRecordWithBlob(RequiresAbbrev, Record,
+                                Mod->Requires[I].data(),
+                                Mod->Requires[I].size());
+    }
+
     // Emit the umbrella header, if there is one.
     if (const FileEntry *UmbrellaHeader = Mod->getUmbrellaHeader()) {
       Record.clear();
@@ -1995,19 +2012,10 @@
     }
     
     // Queue up the submodules of this module.
-    llvm::SmallVector<StringRef, 2> SubModules;
-    
-    // Sort the submodules first, so we get a predictable ordering in the AST
-    // file.
-    for (llvm::StringMap<Module *>::iterator 
-              Sub = Mod->SubModules.begin(),
-           SubEnd = Mod->SubModules.end();
+    for (Module::submodule_iterator Sub = Mod->submodule_begin(),
+                                 SubEnd = Mod->submodule_end();
          Sub != SubEnd; ++Sub)
-      SubModules.push_back(Sub->getKey());
-    llvm::array_pod_sort(SubModules.begin(), SubModules.end());
-    
-    for (unsigned I = 0, N = SubModules.size(); I != N; ++I)
-      Q.push(Mod->SubModules[SubModules[I]]);
+      Q.push(*Sub);
   }
   
   Stream.ExitBlock();
@@ -2518,6 +2526,7 @@
     uint32_t Bits = 0;
     bool HasMacroDefinition = hasMacroDefinition(II, Macro);
     Bits = (uint32_t)II->getObjCOrBuiltinID();
+    assert((Bits & 0x7ff) == Bits && "ObjCOrBuiltinID too big for ASTReader.");
     Bits = (Bits << 1) | unsigned(HasMacroDefinition);
     Bits = (Bits << 1) | unsigned(II->isExtensionToken());
     Bits = (Bits << 1) | unsigned(II->isPoisoned());
@@ -2899,6 +2908,92 @@
   Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
 }
 
+void ASTWriter::WriteRedeclarations() {
+  RecordData LocalRedeclChains;
+  SmallVector<serialization::LocalRedeclarationsInfo, 2> LocalRedeclsMap;
+
+  for (unsigned I = 0, N = Redeclarations.size(); I != N; ++I) {
+    Decl *First = Redeclarations[I];
+    assert(First->getPreviousDecl() == 0 && "Not the first declaration?");
+    
+    Decl *MostRecent = First->getMostRecentDecl();
+    
+    // If we only have a single declaration, there is no point in storing
+    // a redeclaration chain.
+    if (First == MostRecent)
+      continue;
+    
+    unsigned Offset = LocalRedeclChains.size();
+    unsigned Size = 0;
+    LocalRedeclChains.push_back(0); // Placeholder for the size.
+    
+    // Collect the set of local redeclarations of this declaration.
+    for (Decl *Prev = MostRecent; Prev != First; 
+         Prev = Prev->getPreviousDecl()) { 
+      if (!Prev->isFromASTFile()) {
+        AddDeclRef(Prev, LocalRedeclChains);
+        ++Size;
+      }
+    }
+    LocalRedeclChains[Offset] = Size;
+    
+    // Reverse the set of local redeclarations, so that we store them in
+    // order (since we found them in reverse order).
+    std::reverse(LocalRedeclChains.end() - Size, LocalRedeclChains.end());
+    
+    // Add the mapping from the first ID to the set of local declarations.
+    LocalRedeclarationsInfo Info = { getDeclID(First), Offset };
+    LocalRedeclsMap.push_back(Info);
+    
+    assert(N == Redeclarations.size() && 
+           "Deserialized a declaration we shouldn't have");
+  }
+  
+  if (LocalRedeclChains.empty())
+    return;
+  
+  // Sort the local redeclarations map by the first declaration ID,
+  // since the reader will be performing binary searches on this information.
+  llvm::array_pod_sort(LocalRedeclsMap.begin(), LocalRedeclsMap.end());
+  
+  // Emit the local redeclarations map.
+  using namespace llvm;
+  llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(LOCAL_REDECLARATIONS_MAP));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+  unsigned AbbrevID = Stream.EmitAbbrev(Abbrev);
+  
+  RecordData Record;
+  Record.push_back(LOCAL_REDECLARATIONS_MAP);
+  Record.push_back(LocalRedeclsMap.size());
+  Stream.EmitRecordWithBlob(AbbrevID, Record, 
+    reinterpret_cast<char*>(LocalRedeclsMap.data()),
+    LocalRedeclsMap.size() * sizeof(LocalRedeclarationsInfo));
+
+  // Emit the redeclaration chains.
+  Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedeclChains);
+}
+
+void ASTWriter::WriteMergedDecls() {
+  if (!Chain || Chain->MergedDecls.empty())
+    return;
+  
+  RecordData Record;
+  for (ASTReader::MergedDeclsMap::iterator I = Chain->MergedDecls.begin(),
+                                        IEnd = Chain->MergedDecls.end();
+       I != IEnd; ++I) {
+    DeclID CanonID = I->first->isFromASTFile()? I->first->getGlobalID()
+                                              : getDeclID(I->first);
+    assert(CanonID && "Merged declaration not known?");
+    
+    Record.push_back(CanonID);
+    Record.push_back(I->second.size());
+    Record.append(I->second.begin(), I->second.end());
+  }
+  Stream.EmitRecord(MERGED_DECLARATIONS, Record);
+}
+
 //===----------------------------------------------------------------------===//
 // General Serialization Routines
 //===----------------------------------------------------------------------===//
@@ -3039,6 +3134,8 @@
     DeclIDs[Context.ObjCSelDecl] = PREDEF_DECL_OBJC_SEL_ID;
   if (Context.ObjCClassDecl)
     DeclIDs[Context.ObjCClassDecl] = PREDEF_DECL_OBJC_CLASS_ID;
+  if (Context.ObjCProtocolClassDecl)
+    DeclIDs[Context.ObjCProtocolClassDecl] = PREDEF_DECL_OBJC_PROTOCOL_ID;
   if (Context.Int128Decl)
     DeclIDs[Context.Int128Decl] = PREDEF_DECL_INT_128_ID;
   if (Context.UInt128Decl)
@@ -3218,7 +3315,6 @@
   // Form the record of special types.
   RecordData SpecialTypes;
   AddTypeRef(Context.getBuiltinVaListType(), SpecialTypes);
-  AddTypeRef(Context.ObjCProtoType, SpecialTypes);
   AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes);
   AddTypeRef(Context.getFILEType(), SpecialTypes);
   AddTypeRef(Context.getjmp_bufType(), SpecialTypes);
@@ -3311,19 +3407,6 @@
 
   Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);
 
-  /// Build a record containing first declarations from a chained PCH and the
-  /// most recent declarations in this AST that they point to.
-  RecordData FirstLatestDeclIDs;
-  for (FirstLatestDeclMap::iterator I = FirstLatestDecls.begin(), 
-                                    E = FirstLatestDecls.end(); 
-       I != E; ++I) {
-    AddDeclRef(I->first, FirstLatestDeclIDs);
-    AddDeclRef(I->second, FirstLatestDeclIDs);
-  }
-  
-  if (!FirstLatestDeclIDs.empty())
-    Stream.EmitRecord(REDECLS_UPDATE_LATEST, FirstLatestDeclIDs);
-
   // Write the record containing external, unnamed definitions.
   if (!ExternalDefinitions.empty())
     Stream.EmitRecord(EXTERNAL_DEFINITIONS, ExternalDefinitions);
@@ -3410,7 +3493,9 @@
   WriteDeclUpdatesBlocks();
   WriteDeclReplacementsBlock();
   WriteChainedObjCCategories();
-
+  WriteMergedDecls();
+  WriteRedeclarations();
+  
   // Some simple statistics
   Record.clear();
   Record.push_back(NumStatements);
@@ -3435,11 +3520,9 @@
     unsigned Idx = 0, N = URec.size();
     while (Idx < N) {
       switch ((DeclUpdateKind)URec[Idx++]) {
-      case UPD_CXX_SET_DEFINITIONDATA:
       case UPD_CXX_ADDED_IMPLICIT_MEMBER:
       case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
       case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE:
-      case UPD_OBJC_SET_CLASS_DEFINITIONDATA:
         URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx]));
         ++Idx;
         break;
@@ -3695,6 +3778,12 @@
   if (D == 0) {
     return 0;
   }
+  
+  // If D comes from an AST file, its declaration ID is already known and
+  // fixed.
+  if (D->isFromASTFile())
+    return D->getGlobalID();
+  
   assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer");
   DeclID &ID = DeclIDs[D];
   if (ID == 0) {
@@ -3711,6 +3800,11 @@
   if (D == 0)
     return 0;
 
+  // If D comes from an AST file, its declaration ID is already known and
+  // fixed.
+  if (D->isFromASTFile())
+    return D->getGlobalID();
+
   assert(DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!");
   return DeclIDs[D];
 }
@@ -4239,10 +4333,6 @@
     StoredIdx = Idx;
 }
 
-void ASTWriter::DeclRead(DeclID ID, const Decl *D) {
-  DeclIDs[D] = ID;
-}
-
 void ASTWriter::SelectorRead(SelectorID ID, Selector S) {
   SelectorIDs[S] = ID;
 }
@@ -4253,6 +4343,10 @@
   MacroDefinitions[MD] = ID;
 }
 
+void ASTWriter::MacroVisible(IdentifierInfo *II) {
+  DeserializedMacroNames.push_back(II);
+}
+
 void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) {
   assert(SubmoduleIDs.find(Mod) == SubmoduleIDs.end());
   SubmoduleIDs[Mod] = ID;
@@ -4269,22 +4363,6 @@
       // have created a new definition decl instead ?
       RewriteDecl(RD);
     }
-
-    for (CXXRecordDecl::redecl_iterator
-           I = RD->redecls_begin(), E = RD->redecls_end(); I != E; ++I) {
-      CXXRecordDecl *Redecl = cast<CXXRecordDecl>(*I);
-      if (Redecl == RD)
-        continue;
-
-      // We are interested when a PCH decl is modified.
-      if (Redecl->isFromASTFile()) {
-        UpdateRecord &Record = DeclUpdates[Redecl];
-        Record.push_back(UPD_CXX_SET_DEFINITIONDATA);
-        assert(Redecl->DefinitionData);
-        assert(Redecl->DefinitionData->Definition == D);
-        Record.push_back(reinterpret_cast<uint64_t>(D)); // the DefinitionDecl
-      }
-    }
   }
 }
 void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
@@ -4378,29 +4456,6 @@
   LocalChainedObjCCategories.push_back(Data);
 }
 
-void ASTWriter::CompletedObjCForwardRef(const ObjCContainerDecl *D) {
-  assert(!WritingAST && "Already writing the AST!");
-  if (D->isFromASTFile())
-    RewriteDecl(D);
-
-  if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
-    for (ObjCInterfaceDecl::redecl_iterator I = ID->redecls_begin(), 
-                                            E = ID->redecls_end(); 
-         I != E; ++I) {
-      if (*I == ID)
-        continue;
-      
-      // We are interested when a PCH decl is modified.
-      if (I->isFromASTFile()) {
-        UpdateRecord &Record = DeclUpdates[*I];
-        Record.push_back(UPD_OBJC_SET_CLASS_DEFINITIONDATA);
-        assert((*I)->hasDefinition());
-        assert((*I)->getDefinition() == D);
-        Record.push_back(reinterpret_cast<uint64_t>(D)); // the DefinitionDecl
-      }
-    }
-  }
-}
 
 void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
                                           const ObjCPropertyDecl *OrigProp,
@@ -4416,10 +4471,3 @@
   RewriteDecl(D);
 }
 
-void ASTWriter::UpdatedAttributeList(const Decl *D) {
-  assert(!WritingAST && "Already writing the AST!");
-  if (!D->isFromASTFile())
-    return; // Declaration not imported from PCH.
-
-  RewriteDecl(D);
-}

Modified: cfe/branches/tooling/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Serialization/ASTWriterDecl.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/branches/tooling/lib/Serialization/ASTWriterDecl.cpp Fri Jan 20 10:14:22 2012
@@ -55,6 +55,7 @@
     void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
     void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
     void VisitTypeDecl(TypeDecl *D);
+    void VisitTypedefNameDecl(TypedefNameDecl *D);
     void VisitTypedefDecl(TypedefDecl *D);
     void VisitTypeAliasDecl(TypeAliasDecl *D);
     void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
@@ -113,8 +114,6 @@
     void VisitObjCIvarDecl(ObjCIvarDecl *D);
     void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
     void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
-    void VisitObjCClassDecl(ObjCClassDecl *D);
-    void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
     void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
     void VisitObjCImplDecl(ObjCImplDecl *D);
     void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
@@ -155,9 +154,9 @@
   Record.push_back(D->isImplicit());
   Record.push_back(D->isUsed(false));
   Record.push_back(D->isReferenced());
-  Record.push_back(D->TopLevelDeclInObjCContainer);
+  Record.push_back(D->isTopLevelDeclInObjCContainer());
   Record.push_back(D->getAccess());
-  Record.push_back(D->ModulePrivate);
+  Record.push_back(D->isModulePrivate());
   Record.push_back(Writer.inferSubmoduleIDFromLocation(D->getLocation()));
 }
 
@@ -176,14 +175,18 @@
   Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
 }
 
-void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
+void ASTDeclWriter::VisitTypedefNameDecl(TypedefNameDecl *D) {
+  VisitRedeclarable(D);
   VisitTypeDecl(D);
-  Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
+  Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);  
+}
 
+void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
+  VisitTypedefNameDecl(D);
   if (!D->hasAttrs() &&
       !D->isImplicit() &&
       !D->isUsed(false) &&
-      D->RedeclLink.getNext() == D &&
+      D->getFirstDeclaration() == D->getMostRecentDecl() &&
       !D->isInvalidDecl() &&
       !D->isReferenced() &&
       !D->isTopLevelDeclInObjCContainer() &&
@@ -196,8 +199,7 @@
 }
 
 void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) {
-  VisitTypeDecl(D);
-  Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
+  VisitTypedefNameDecl(D);
   Code = serialization::DECL_TYPEALIAS;
 }
 
@@ -234,7 +236,7 @@
       !D->isImplicit() &&
       !D->isUsed(false) &&
       !D->hasExtInfo() &&
-      D->RedeclLink.getNext() == D &&
+      D->getFirstDeclaration() == D->getMostRecentDecl() &&
       !D->isInvalidDecl() &&
       !D->isReferenced() &&
       !D->isTopLevelDeclInObjCContainer() &&
@@ -258,7 +260,7 @@
       !D->isImplicit() &&
       !D->isUsed(false) &&
       !D->hasExtInfo() &&
-      D->RedeclLink.getNext() == D &&
+      D->getFirstDeclaration() == D->getMostRecentDecl() &&
       !D->isInvalidDecl() &&
       !D->isReferenced() &&
       !D->isTopLevelDeclInObjCContainer() &&
@@ -300,9 +302,28 @@
 
   Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
   Record.push_back(D->getIdentifierNamespace());
+  
+  // FunctionDecl's body is handled last at ASTWriterDecl::Visit,
+  // after everything else is written.
+  
+  Record.push_back(D->getStorageClass()); // FIXME: stable encoding
+  Record.push_back(D->getStorageClassAsWritten());
+  Record.push_back(D->IsInline);
+  Record.push_back(D->isInlineSpecified());
+  Record.push_back(D->isVirtualAsWritten());
+  Record.push_back(D->isPure());
+  Record.push_back(D->hasInheritedPrototype());
+  Record.push_back(D->hasWrittenPrototype());
+  Record.push_back(D->isDeletedAsWritten());
+  Record.push_back(D->isTrivial());
+  Record.push_back(D->isDefaulted());
+  Record.push_back(D->isExplicitlyDefaulted());
+  Record.push_back(D->hasImplicitReturnZero());
+  Record.push_back(D->isConstexpr());
+  Writer.AddSourceLocation(D->getLocEnd(), Record);
+
   Record.push_back(D->getTemplatedKind());
   switch (D->getTemplatedKind()) {
-  default: llvm_unreachable("Unhandled TemplatedKind!");
   case FunctionDecl::TK_NonTemplate:
     break;
   case FunctionDecl::TK_FunctionTemplate:
@@ -366,25 +387,6 @@
   }
   }
 
-  // FunctionDecl's body is handled last at ASTWriterDecl::Visit,
-  // after everything else is written.
-
-  Record.push_back(D->getStorageClass()); // FIXME: stable encoding
-  Record.push_back(D->getStorageClassAsWritten());
-  Record.push_back(D->IsInline);
-  Record.push_back(D->isInlineSpecified());
-  Record.push_back(D->isVirtualAsWritten());
-  Record.push_back(D->isPure());
-  Record.push_back(D->hasInheritedPrototype());
-  Record.push_back(D->hasWrittenPrototype());
-  Record.push_back(D->isDeletedAsWritten());
-  Record.push_back(D->isTrivial());
-  Record.push_back(D->isDefaulted());
-  Record.push_back(D->isExplicitlyDefaulted());
-  Record.push_back(D->hasImplicitReturnZero());
-  Record.push_back(D->isConstexpr());
-  Writer.AddSourceLocation(D->getLocEnd(), Record);
-
   Record.push_back(D->param_size());
   for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
        P != PEnd; ++P)
@@ -451,10 +453,8 @@
   VisitObjCContainerDecl(D);
   Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
 
-  ObjCInterfaceDecl *Def = D->getDefinition();
-  Writer.AddDeclRef(Def, Record);
-  
-  if (D == Def) {
+  Record.push_back(D->isThisDeclarationADefinition());
+  if (D->isThisDeclarationADefinition()) {
     // Write the DefinitionData
     ObjCInterfaceDecl::DefinitionData &Data = D->data();
     
@@ -514,18 +514,21 @@
 }
 
 void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
+  VisitRedeclarable(D);
   VisitObjCContainerDecl(D);
-  Record.push_back(D->isInitiallyForwardDecl());
-  Record.push_back(D->isForwardDecl());
-  Writer.AddSourceLocation(D->getLocEnd(), Record);
-  Record.push_back(D->protocol_size());
-  for (ObjCProtocolDecl::protocol_iterator
-       I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
-    Writer.AddDeclRef(*I, Record);
-  for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
-         PLEnd = D->protocol_loc_end();
-       PL != PLEnd; ++PL)
-    Writer.AddSourceLocation(*PL, Record);
+  
+  Record.push_back(D->isThisDeclarationADefinition());
+  if (D->isThisDeclarationADefinition()) {
+    Record.push_back(D->protocol_size());
+    for (ObjCProtocolDecl::protocol_iterator
+         I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
+      Writer.AddDeclRef(*I, Record);
+    for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
+           PLEnd = D->protocol_loc_end();
+         PL != PLEnd; ++PL)
+      Writer.AddSourceLocation(*PL, Record);
+  }
+  
   Code = serialization::DECL_OBJC_PROTOCOL;
 }
 
@@ -534,26 +537,6 @@
   Code = serialization::DECL_OBJC_AT_DEFS_FIELD;
 }
 
-void ASTDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
-  VisitDecl(D);
-  Writer.AddDeclRef(D->Interface, Record);
-  Writer.AddSourceLocation(D->InterfaceLoc, Record);
-  Code = serialization::DECL_OBJC_CLASS;
-}
-
-void ASTDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
-  VisitDecl(D);
-  Record.push_back(D->protocol_size());
-  for (ObjCForwardProtocolDecl::protocol_iterator
-       I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
-    Writer.AddDeclRef(*I, Record);
-  for (ObjCForwardProtocolDecl::protocol_loc_iterator 
-         PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
-       PL != PLEnd; ++PL)
-    Writer.AddSourceLocation(*PL, Record);
-  Code = serialization::DECL_OBJC_FORWARD_PROTOCOL;
-}
-
 void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
   VisitObjCContainerDecl(D);
   Writer.AddDeclRef(D->getClassInterface(), Record);
@@ -678,9 +661,12 @@
   Record.push_back(D->isNRVOVariable());
   Record.push_back(D->isCXXForRangeDecl());
   Record.push_back(D->isARCPseudoStrong());
-  Record.push_back(D->getInit() ? 1 : 0);
-  if (D->getInit())
+  if (D->getInit()) {
+    Record.push_back(!D->isInitKnownICE() ? 1 : (D->isInitICE() ? 3 : 2));
     Writer.AddStmt(D->getInit());
+  } else {
+    Record.push_back(0);
+  }
 
   MemberSpecializationInfo *SpecInfo
     = D->isStaticDataMember() ? D->getMemberSpecializationInfo() : 0;
@@ -701,7 +687,7 @@
       !D->isModulePrivate() &&
       D->getDeclName().getNameKind() == DeclarationName::Identifier &&
       !D->hasExtInfo() &&
-      D->RedeclLink.getNext() == D &&
+      D->getFirstDeclaration() == D->getMostRecentDecl() &&
       !D->hasCXXDirectInitializer() &&
       D->getInit() == 0 &&
       !isa<ParmVarDecl>(D) &&
@@ -738,6 +724,7 @@
       !D->hasExtInfo() &&
       !D->isImplicit() &&
       !D->isUsed(false) &&
+      !D->isReferenced() &&
       D->getAccess() == AS_none &&
       !D->isModulePrivate() &&
       D->getStorageClass() == 0 &&
@@ -756,7 +743,7 @@
   assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread");
   assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
   assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var");
-  assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl");
+  assert(D->getPreviousDecl() == 0 && "PARM_VAR_DECL can't be redecl");
   assert(!D->isStaticDataMember() &&
          "PARM_VAR_DECL can't be static data member");
 }
@@ -811,18 +798,14 @@
 
 
 void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
+  VisitRedeclarable(D);
   VisitNamedDecl(D);
   Record.push_back(D->isInline());
   Writer.AddSourceLocation(D->getLocStart(), Record);
   Writer.AddSourceLocation(D->getRBraceLoc(), Record);
-  Writer.AddDeclRef(D->getNextNamespace(), Record);
 
-  // Only write one reference--original or anonymous
-  Record.push_back(D->isOriginalNamespace());
   if (D->isOriginalNamespace())
     Writer.AddDeclRef(D->getAnonymousNamespace(), Record);
-  else
-    Writer.AddDeclRef(D->getOriginalNamespace(), Record);
   Code = serialization::DECL_NAMESPACE;
 
   if (Writer.hasChain() && !D->isOriginalNamespace() &&
@@ -845,7 +828,8 @@
     }
   }
 
-  if (Writer.hasChain() && D->isAnonymousNamespace() && !D->getNextNamespace()){
+  if (Writer.hasChain() && D->isAnonymousNamespace() && 
+      D == D->getMostRecentDecl()) {
     // This is a most recent reopening of the anonymous namespace. If its parent
     // is in a previous PCH (or is the TU), mark that parent for update, because
     // the original namespace always points to the latest re-opening of its
@@ -874,7 +858,7 @@
   Writer.AddSourceLocation(D->getUsingLocation(), Record);
   Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
   Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
-  Writer.AddDeclRef(D->FirstUsingShadow, Record);
+  Writer.AddDeclRef(D->FirstUsingShadow.getPointer(), Record);
   Record.push_back(D->isTypeName());
   Writer.AddDeclRef(Context.getInstantiatedFromUsingDecl(D), Record);
   Code = serialization::DECL_USING;
@@ -916,12 +900,8 @@
 
 void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
   VisitRecordDecl(D);
-
-  CXXRecordDecl *DefinitionDecl = 0;
-  if (D->DefinitionData)
-    DefinitionDecl = D->DefinitionData->Definition;
-  Writer.AddDeclRef(DefinitionDecl, Record);
-  if (D == DefinitionDecl)
+  Record.push_back(D->isThisDeclarationADefinition());
+  if (D->isThisDeclarationADefinition())
     Writer.AddCXXDefinitionData(D, Record);
 
   enum {
@@ -1042,36 +1022,17 @@
 }
 
 void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
+  VisitRedeclarable(D);
+
   // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
   // getCommonPtr() can be used while this is still initializing.
-
-  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
-  if (D->getPreviousDeclaration())
-    Writer.AddDeclRef(D->getFirstDeclaration(), Record);
-
-  if (D->getPreviousDeclaration() == 0) {
-    // This TemplateDecl owns the CommonPtr; write it.
-    assert(D->isCanonicalDecl());
-
+  if (D->isFirstDeclaration()) {
+    // This declaration owns the 'common' pointer, so serialize that data now.
     Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
     if (D->getInstantiatedFromMemberTemplate())
       Record.push_back(D->isMemberSpecialization());
-
-    Writer.AddDeclRef(D->getCommonPtr()->Latest, Record);
-  } else {
-    RedeclarableTemplateDecl *First = D->getFirstDeclaration();
-    assert(First != D);
-    // If this is a most recent redeclaration that is pointed to by a first decl
-    // in a chained PCH, keep track of the association with the map so we can
-    // update the first decl during AST reading.
-    if (First->getMostRecentDeclaration() == D &&
-        First->isFromASTFile() && !D->isFromASTFile()) {
-      assert(Writer.FirstLatestDecls.find(First)==Writer.FirstLatestDecls.end()
-             && "The latest is already set");
-      Writer.FirstLatestDecls[First] = D;
-    }
   }
-
+  
   VisitTemplateDecl(D);
   Record.push_back(D->getIdentifierNamespace());
 }
@@ -1079,7 +1040,7 @@
 void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
   VisitRedeclarableTemplateDecl(D);
 
-  if (D->getPreviousDeclaration() == 0) {
+  if (D->isFirstDeclaration()) {
     typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy;
     CTSDSetTy &CTSDSet = D->getSpecializations();
     Record.push_back(CTSDSet.size());
@@ -1148,7 +1109,7 @@
   Record.push_back(D->getSequenceNumber());
 
   // These are read/set from/to the first declaration.
-  if (D->getPreviousDeclaration() == 0) {
+  if (D->getPreviousDecl() == 0) {
     Writer.AddDeclRef(D->getInstantiatedFromMember(), Record);
     Record.push_back(D->isMemberSpecialization());
   }
@@ -1167,7 +1128,7 @@
 void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
   VisitRedeclarableTemplateDecl(D);
 
-  if (D->getPreviousDeclaration() == 0) {
+  if (D->isFirstDeclaration()) {
     // This FunctionTemplateDecl owns the CommonPtr; write it.
 
     // Write the function specialization declarations.
@@ -1267,31 +1228,23 @@
 
 template <typename T>
 void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
-  enum { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
-  if (D->RedeclLink.getNext() == D) {
-    Record.push_back(NoRedeclaration);
-  } else {
-    if (D->RedeclLink.NextIsPrevious()) {
-      Record.push_back(PointsToPrevious);
-      Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
-      Writer.AddDeclRef(D->getFirstDeclaration(), Record);
-    } else {
-      Record.push_back(PointsToLatest);
-      Writer.AddDeclRef(D->RedeclLink.getPointer(), Record);
-    }
-  }
-
   T *First = D->getFirstDeclaration();
-  T *ThisDecl = static_cast<T*>(D);
-  // If this is a most recent redeclaration that is pointed to by a first decl
-  // in a chained PCH, keep track of the association with the map so we can
-  // update the first decl during AST reading.
-  if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl &&
-      First->isFromASTFile() && !ThisDecl->isFromASTFile()) {
-    assert(Writer.FirstLatestDecls.find(First) == Writer.FirstLatestDecls.end()
-           && "The latest is already set");
-    Writer.FirstLatestDecls[First] = ThisDecl;
+  if (First->getMostRecentDecl() != First) {
+    // There is more than one declaration of this entity, so we will need to 
+    // write a redeclaration chain.
+    Writer.AddDeclRef(First, Record);
+    Writer.Redeclarations.insert(First);
+
+    // Make sure that we serialize both the previous and the most-recent 
+    // declarations, which (transitively) ensures that all declarations in the
+    // chain get serialized.
+    (void)Writer.GetDeclRef(D->getPreviousDecl());
+    (void)Writer.GetDeclRef(First->getMostRecentDecl());
+  } else {
+    // We use the sentinel value 0 to indicate an only declaration.
+    Record.push_back(0);
   }
+  
 }
 
 //===----------------------------------------------------------------------===//
@@ -1374,7 +1327,7 @@
   Abv = new BitCodeAbbrev();
   Abv->Add(BitCodeAbbrevOp(serialization::DECL_ENUM));
   // Redeclarable
-  Abv->Add(BitCodeAbbrevOp(0));                         // No redeclaration
+  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration
   // Decl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1421,7 +1374,7 @@
   Abv = new BitCodeAbbrev();
   Abv->Add(BitCodeAbbrevOp(serialization::DECL_RECORD));
   // Redeclarable
-  Abv->Add(BitCodeAbbrevOp(0));                         // No redeclaration
+  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration
   // Decl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1511,6 +1464,8 @@
   // Abbreviation for DECL_TYPEDEF
   Abv = new BitCodeAbbrev();
   Abv->Add(BitCodeAbbrevOp(serialization::DECL_TYPEDEF));
+  // Redeclarable
+  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration
   // Decl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1688,12 +1643,18 @@
     VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
   }
 
-  // Determine the ID for this declaration
-  serialization::DeclID &IDR = DeclIDs[D];
-  if (IDR == 0)
-    IDR = NextDeclID++;
-  serialization::DeclID ID = IDR;
-
+  // Determine the ID for this declaration.
+  serialization::DeclID ID;
+  if (D->isFromASTFile())
+    ID = getDeclID(D);
+  else {
+    serialization::DeclID &IDR = DeclIDs[D];
+    if (IDR == 0)
+      IDR = NextDeclID++;
+    
+    ID= IDR;
+  }
+  
   if (ID < FirstDeclID) {
     // We're replacing a decl in a previous file.
     ReplacedDecls.push_back(ReplacedDeclInfo(ID, Stream.GetCurrentBitNo(),

Modified: cfe/branches/tooling/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Serialization/ASTWriterStmt.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/branches/tooling/lib/Serialization/ASTWriterStmt.cpp Fri Jan 20 10:14:22 2012
@@ -848,6 +848,7 @@
   Record.push_back(E->getNumStoredSelLocs());
   Record.push_back(E->SelLocsKind);
   Record.push_back(E->isDelegateInitCall());
+  Record.push_back(E->IsImplicit);
   Record.push_back((unsigned)E->getReceiverKind()); // FIXME: stable encoding
   switch (E->getReceiverKind()) {
   case ObjCMessageExpr::Instance:

Modified: cfe/branches/tooling/lib/Serialization/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Serialization/CMakeLists.txt?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Serialization/CMakeLists.txt (original)
+++ cfe/branches/tooling/lib/Serialization/CMakeLists.txt Fri Jan 20 10:14:22 2012
@@ -1,5 +1,4 @@
-# TODO: This must need some dependencies, but it builds fine without them.
-#set(LLVM_USED_LIBS ???)
+set(LLVM_USED_LIBS clangSema)
 
 add_clang_library(clangSerialization
   ASTCommon.h

Modified: cfe/branches/tooling/lib/Serialization/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Serialization/Module.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Serialization/Module.cpp (original)
+++ cfe/branches/tooling/lib/Serialization/Module.cpp Fri Jan 20 10:14:22 2012
@@ -20,8 +20,8 @@
 using namespace serialization;
 using namespace reader;
 
-ModuleFile::ModuleFile(ModuleKind Kind)
-  : Kind(Kind), DirectlyImported(false), SizeInBits(0), 
+ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation)
+  : Kind(Kind), DirectlyImported(false), Generation(Generation), SizeInBits(0), 
     LocalNumSLocEntries(0), SLocEntryBaseID(0),
     SLocEntryBaseOffset(0), SLocEntryOffsets(0),
     SLocFileOffsets(0), LocalNumIdentifiers(0), 
@@ -30,12 +30,12 @@
     PreprocessedEntityOffsets(0), NumPreprocessedEntities(0),
     LocalNumHeaderFileInfos(0), 
     HeaderFileInfoTableData(0), HeaderFileInfoTable(0),
-    HeaderFileFrameworkStrings(0), LocalNumSubmodules(0),
+    HeaderFileFrameworkStrings(0), LocalNumSubmodules(0), BaseSubmoduleID(0),
     LocalNumSelectors(0), SelectorOffsets(0), BaseSelectorID(0),
     SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0),
     DeclOffsets(0), BaseDeclID(0),
     LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0),
-    FileSortedDecls(0),
+    FileSortedDecls(0), RedeclarationsMap(0), LocalNumRedeclarationsInMap(0),
     LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0), StatCache(0)
 {}
 

Modified: cfe/branches/tooling/lib/Serialization/ModuleManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/Serialization/ModuleManager.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/Serialization/ModuleManager.cpp (original)
+++ cfe/branches/tooling/lib/Serialization/ModuleManager.cpp Fri Jan 20 10:14:22 2012
@@ -35,7 +35,8 @@
 
 std::pair<ModuleFile *, bool>
 ModuleManager::addModule(StringRef FileName, ModuleKind Type, 
-                         ModuleFile *ImportedBy, std::string &ErrorStr) {
+                         ModuleFile *ImportedBy, unsigned Generation,
+                         std::string &ErrorStr) {
   const FileEntry *Entry = FileMgr.getFile(FileName);
   if (!Entry && FileName != "-") {
     ErrorStr = "file not found";
@@ -47,7 +48,7 @@
   bool NewModule = false;
   if (!ModuleEntry) {
     // Allocate a new module.
-    ModuleFile *New = new ModuleFile(Type);
+    ModuleFile *New = new ModuleFile(Type, Generation);
     New->FileName = FileName.str();
     Chain.push_back(New);
     NewModule = true;

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp Fri Jan 20 10:14:22 2012
@@ -38,19 +38,20 @@
 
   // Fetch the signature of the called function.
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
 
-  SVal V = state->getSVal(CE);
+  SVal V = state->getSVal(CE, LCtx);
   
   if (V.isUnknown())
     return;
   
   // Casting to void?  Discard the value.
   if (expectedResultTy->isVoidType()) {
-    C.addTransition(state->BindExpr(CE, UnknownVal()));
+    C.addTransition(state->BindExpr(CE, LCtx, UnknownVal()));
     return;
   }                   
 
-  const MemRegion *callee = state->getSVal(CE->getCallee()).getAsRegion();
+  const MemRegion *callee = state->getSVal(CE->getCallee(), LCtx).getAsRegion();
   if (!callee)
     return;
 
@@ -82,7 +83,7 @@
     // the cast avoids some assertion failures elsewhere.
     SValBuilder &svalBuilder = C.getSValBuilder();
     V = svalBuilder.evalCast(V, expectedResultTy, actualResultTy);
-    C.addTransition(state->BindExpr(CE, V));
+    C.addTransition(state->BindExpr(CE, LCtx, V));
   }
 }
 

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp Fri Jan 20 10:14:22 2012
@@ -34,9 +34,10 @@
 void AttrNonNullChecker::checkPreStmt(const CallExpr *CE,
                                       CheckerContext &C) const {
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
 
   // Check if the callee has a 'nonnull' attribute.
-  SVal X = state->getSVal(CE->getCallee());
+  SVal X = state->getSVal(CE->getCallee(), LCtx);
 
   const FunctionDecl *FD = X.getAsFunctionDecl();
   if (!FD)
@@ -55,7 +56,7 @@
     if (!Att->isNonNull(idx))
       continue;
 
-    SVal V = state->getSVal(*I);
+    SVal V = state->getSVal(*I, LCtx);
     DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
 
     // If the value is unknown or undefined, we can't perform this check.

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp Fri Jan 20 10:14:22 2012
@@ -129,7 +129,7 @@
         Name == "compare:options:range:locale:" ||
         Name == "componentsSeparatedByCharactersInSet:" ||
         Name == "initWithFormat:") {
-      if (isNil(msg.getArgSVal(0, C.getState())))
+      if (isNil(msg.getArgSVal(0, C.getLocationContext(), C.getState())))
         WarnNilArg(C, msg, 0);
     }
   }
@@ -262,7 +262,8 @@
     return;
 
   // Get the value of the "theType" argument.
-  SVal TheTypeVal = state->getSVal(CE->getArg(1));
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);
 
   // FIXME: We really should allow ranges of valid theType values, and
   //   bifurcate the state appropriately.
@@ -280,7 +281,7 @@
   // Look at the value of the integer being passed by reference.  Essentially
   // we want to catch cases where the value passed in is not equal to the
   // size of the type being created.
-  SVal TheValueExpr = state->getSVal(CE->getArg(2));
+  SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx);
 
   // FIXME: Eventually we should handle arbitrary locations.  We can do this
   //  by having an enhanced memory model that does low-level typing.
@@ -382,7 +383,7 @@
 
   // Get the argument's value.
   const Expr *Arg = CE->getArg(0);
-  SVal ArgVal = state->getSVal(Arg);
+  SVal ArgVal = state->getSVal(Arg, C.getLocationContext());
   DefinedSVal *DefArgVal = dyn_cast<DefinedSVal>(&ArgVal);
   if (!DefArgVal)
     return;
@@ -593,7 +594,8 @@
       continue;
 
     // Ignore pointer constants.
-    if (isa<loc::ConcreteInt>(msg.getArgSVal(I, state)))
+    if (isa<loc::ConcreteInt>(msg.getArgSVal(I, C.getLocationContext(),
+                                             state)))
       continue;
     
     // Ignore pointer types annotated with 'NSObject' attribute.

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp Fri Jan 20 10:14:22 2012
@@ -33,6 +33,7 @@
                                       CheckerContext &C) const {
   const ProgramState *state = C.getState();
   const FunctionDecl *FD = C.getCalleeDecl(CE);
+  const LocationContext *LCtx = C.getLocationContext();
   if (!FD)
     return false;
 
@@ -45,8 +46,8 @@
   case Builtin::BI__builtin_expect: {
     // For __builtin_expect, just return the value of the subexpression.
     assert (CE->arg_begin() != CE->arg_end());
-    SVal X = state->getSVal(*(CE->arg_begin()));
-    C.addTransition(state->BindExpr(CE, X));
+    SVal X = state->getSVal(*(CE->arg_begin()), LCtx);
+    C.addTransition(state->BindExpr(CE, LCtx, X));
     return true;
   }
 
@@ -60,7 +61,7 @@
     // SVal of the argument directly. If we save the extent in bits, we
     // cannot represent values like symbol*8.
     DefinedOrUnknownSVal Size =
-      cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin())));
+      cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin()), LCtx));
 
     SValBuilder& svalBuilder = C.getSValBuilder();
     DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
@@ -68,7 +69,7 @@
       svalBuilder.evalEQ(state, Extent, Size);
     state = state->assume(extentMatchesSizeArg, true);
 
-    C.addTransition(state->BindExpr(CE, loc::MemRegionVal(R)));
+    C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));
     return true;
   }
   }

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CMakeLists.txt Fri Jan 20 10:14:22 2012
@@ -3,7 +3,7 @@
   SOURCE Checkers.td
   TARGET ClangSACheckers)
 
-set(LLVM_USED_LIBS clangBasic clangAST)
+set(LLVM_USED_LIBS clangBasic clangAST clangStaticAnalyzerCore)
 
 add_clang_library(clangStaticAnalyzerCheckers
   AdjustedReturnValueChecker.cpp
@@ -62,6 +62,7 @@
   UnixAPIChecker.cpp
   UnreachableCodeChecker.cpp
   VLASizeChecker.cpp
+  VirtualCallChecker.cpp
   )
 
 add_dependencies(clangStaticAnalyzerCheckers

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CStringChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CStringChecker.cpp Fri Jan 20 10:14:22 2012
@@ -329,12 +329,13 @@
 
   SValBuilder &svalBuilder = C.getSValBuilder();
   ASTContext &Ctx = svalBuilder.getContext();
+  const LocationContext *LCtx = C.getLocationContext();
 
   QualType sizeTy = Size->getType();
   QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
 
   // Check that the first buffer is non-null.
-  SVal BufVal = state->getSVal(FirstBuf);
+  SVal BufVal = state->getSVal(FirstBuf, LCtx);
   state = checkNonNull(C, state, FirstBuf, BufVal);
   if (!state)
     return NULL;
@@ -342,7 +343,7 @@
   // Get the access length and make sure it is known.
   // FIXME: This assumes the caller has already checked that the access length
   // is positive. And that it's unsigned.
-  SVal LengthVal = state->getSVal(Size);
+  SVal LengthVal = state->getSVal(Size, LCtx);
   NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
   if (!Length)
     return state;
@@ -368,7 +369,7 @@
 
   // If there's a second buffer, check it as well.
   if (SecondBuf) {
-    BufVal = state->getSVal(SecondBuf);
+    BufVal = state->getSVal(SecondBuf, LCtx);
     state = checkNonNull(C, state, SecondBuf, BufVal);
     if (!state)
       return NULL;
@@ -403,8 +404,9 @@
   const ProgramState *stateTrue, *stateFalse;
 
   // Get the buffer values and make sure they're known locations.
-  SVal firstVal = state->getSVal(First);
-  SVal secondVal = state->getSVal(Second);
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal firstVal = state->getSVal(First, LCtx);
+  SVal secondVal = state->getSVal(Second, LCtx);
 
   Loc *firstLoc = dyn_cast<Loc>(&firstVal);
   if (!firstLoc)
@@ -456,7 +458,7 @@
   }
 
   // Get the length, and make sure it too is known.
-  SVal LengthVal = state->getSVal(Size);
+  SVal LengthVal = state->getSVal(Size, LCtx);
   NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
   if (!Length)
     return state;
@@ -846,7 +848,8 @@
   CurrentFunctionDescription = "memory copy function";
 
   // See if the size argument is zero.
-  SVal sizeVal = state->getSVal(Size);
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal sizeVal = state->getSVal(Size, LCtx);
   QualType sizeTy = Size->getType();
 
   const ProgramState *stateZeroSize, *stateNonZeroSize;
@@ -854,12 +857,12 @@
     assumeZero(C, state, sizeVal, sizeTy);
 
   // Get the value of the Dest.
-  SVal destVal = state->getSVal(Dest);
+  SVal destVal = state->getSVal(Dest, LCtx);
 
   // If the size is zero, there won't be any actual memory access, so
   // just bind the return value to the destination buffer and return.
   if (stateZeroSize) {
-    stateZeroSize = stateZeroSize->BindExpr(CE, destVal);
+    stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal);
     C.addTransition(stateZeroSize);
   }
 
@@ -874,7 +877,7 @@
       return;
 
     // Get the value of the Src.
-    SVal srcVal = state->getSVal(Source);
+    SVal srcVal = state->getSVal(Source, LCtx);
     
     // Ensure the source is not null. If it is NULL there will be a
     // NULL pointer dereference.
@@ -910,20 +913,20 @@
                                                           Dest->getType());
       
         // The byte after the last byte copied is the return value.
-        state = state->BindExpr(CE, lastElement);
+        state = state->BindExpr(CE, LCtx, lastElement);
       } else {
         // If we don't know how much we copied, we can at least
         // conjure a return value for later.
         unsigned Count = C.getCurrentBlockCount();
         SVal result =
           C.getSValBuilder().getConjuredSymbolVal(NULL, CE, Count);
-        state = state->BindExpr(CE, result);
+        state = state->BindExpr(CE, LCtx, result);
       }
 
     } else {
       // All other copies return the destination buffer.
       // (Well, bcopy() has a void return type, but this won't hurt.)
-      state = state->BindExpr(CE, destVal);
+      state = state->BindExpr(CE, LCtx, destVal);
     }
 
     // Invalidate the destination.
@@ -931,7 +934,8 @@
     // can use LazyCompoundVals to copy the source values into the destination.
     // This would probably remove any existing bindings past the end of the
     // copied region, but that's still an improvement over blank invalidation.
-    state = InvalidateBuffer(C, state, Dest, state->getSVal(Dest));
+    state = InvalidateBuffer(C, state, Dest,
+                             state->getSVal(Dest, C.getLocationContext()));
     C.addTransition(state);
   }
 }
@@ -982,7 +986,8 @@
   SValBuilder &svalBuilder = C.getSValBuilder();
 
   // See if the size argument is zero.
-  SVal sizeVal = state->getSVal(Size);
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal sizeVal = state->getSVal(Size, LCtx);
   QualType sizeTy = Size->getType();
 
   const ProgramState *stateZeroSize, *stateNonZeroSize;
@@ -993,7 +998,8 @@
   // have to check either of the buffers.
   if (stateZeroSize) {
     state = stateZeroSize;
-    state = state->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType()));
+    state = state->BindExpr(CE, LCtx,
+                            svalBuilder.makeZeroVal(CE->getType()));
     C.addTransition(state);
   }
 
@@ -1003,8 +1009,10 @@
     // If we know the two buffers are the same, we know the result is 0.
     // First, get the two buffers' addresses. Another checker will have already
     // made sure they're not undefined.
-    DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(state->getSVal(Left));
-    DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right));
+    DefinedOrUnknownSVal LV =
+      cast<DefinedOrUnknownSVal>(state->getSVal(Left, LCtx));
+    DefinedOrUnknownSVal RV =
+      cast<DefinedOrUnknownSVal>(state->getSVal(Right, LCtx));
 
     // See if they are the same.
     DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
@@ -1017,7 +1025,8 @@
       state = StSameBuf;
       state = CheckBufferAccess(C, state, Size, Left);
       if (state) {
-        state = StSameBuf->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType()));
+        state = StSameBuf->BindExpr(CE, LCtx,
+                                    svalBuilder.makeZeroVal(CE->getType()));
         C.addTransition(state);
       }
     }
@@ -1031,7 +1040,7 @@
         // The return value is the comparison result, which we don't know.
         unsigned Count = C.getCurrentBlockCount();
         SVal CmpV = svalBuilder.getConjuredSymbolVal(NULL, CE, Count);
-        state = state->BindExpr(CE, CmpV);
+        state = state->BindExpr(CE, LCtx, CmpV);
         C.addTransition(state);
       }
     }
@@ -1054,10 +1063,11 @@
                                          bool IsStrnlen) const {
   CurrentFunctionDescription = "string length function";
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
 
   if (IsStrnlen) {
     const Expr *maxlenExpr = CE->getArg(1);
-    SVal maxlenVal = state->getSVal(maxlenExpr);
+    SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
 
     const ProgramState *stateZeroSize, *stateNonZeroSize;
     llvm::tie(stateZeroSize, stateNonZeroSize) =
@@ -1067,7 +1077,7 @@
     // have to check the string itself.
     if (stateZeroSize) {
       SVal zero = C.getSValBuilder().makeZeroVal(CE->getType());
-      stateZeroSize = stateZeroSize->BindExpr(CE, zero);
+      stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero);
       C.addTransition(stateZeroSize);
     }
 
@@ -1081,7 +1091,7 @@
 
   // Check that the string argument is non-null.
   const Expr *Arg = CE->getArg(0);
-  SVal ArgVal = state->getSVal(Arg);
+  SVal ArgVal = state->getSVal(Arg, LCtx);
 
   state = checkNonNull(C, state, Arg, ArgVal);
 
@@ -1105,7 +1115,7 @@
     // It's a little unfortunate to be getting this again,
     // but it's not that expensive...
     const Expr *maxlenExpr = CE->getArg(1);
-    SVal maxlenVal = state->getSVal(maxlenExpr);
+    SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
 
     NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength);
     NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal);
@@ -1170,7 +1180,7 @@
 
   // Bind the return value.
   assert(!result.isUnknown() && "Should have conjured a value by now");
-  state = state->BindExpr(CE, result);
+  state = state->BindExpr(CE, LCtx, result);
   C.addTransition(state);
 }
 
@@ -1219,10 +1229,11 @@
                                       bool isAppending) const {
   CurrentFunctionDescription = "string copy function";
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
 
   // Check that the destination is non-null.
   const Expr *Dst = CE->getArg(0);
-  SVal DstVal = state->getSVal(Dst);
+  SVal DstVal = state->getSVal(Dst, LCtx);
 
   state = checkNonNull(C, state, Dst, DstVal);
   if (!state)
@@ -1230,7 +1241,7 @@
 
   // Check that the source is non-null.
   const Expr *srcExpr = CE->getArg(1);
-  SVal srcVal = state->getSVal(srcExpr);
+  SVal srcVal = state->getSVal(srcExpr, LCtx);
   state = checkNonNull(C, state, srcExpr, srcVal);
   if (!state)
     return;
@@ -1257,7 +1268,7 @@
   if (isBounded) {
     // Get the max number of characters to copy.
     const Expr *lenExpr = CE->getArg(2);
-    SVal lenVal = state->getSVal(lenExpr);
+    SVal lenVal = state->getSVal(lenExpr, LCtx);
 
     // Protect against misdeclared strncpy().
     lenVal = svalBuilder.evalCast(lenVal, sizeTy, lenExpr->getType());
@@ -1512,7 +1523,7 @@
   }
 
   // Set the return value.
-  state = state->BindExpr(CE, Result);
+  state = state->BindExpr(CE, LCtx, Result);
   C.addTransition(state);
 }
 
@@ -1542,17 +1553,18 @@
                                       bool isBounded, bool ignoreCase) const {
   CurrentFunctionDescription = "string comparison function";
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
 
   // Check that the first string is non-null
   const Expr *s1 = CE->getArg(0);
-  SVal s1Val = state->getSVal(s1);
+  SVal s1Val = state->getSVal(s1, LCtx);
   state = checkNonNull(C, state, s1, s1Val);
   if (!state)
     return;
 
   // Check that the second string is non-null.
   const Expr *s2 = CE->getArg(1);
-  SVal s2Val = state->getSVal(s2);
+  SVal s2Val = state->getSVal(s2, LCtx);
   state = checkNonNull(C, state, s2, s2Val);
   if (!state)
     return;
@@ -1582,7 +1594,8 @@
   // If the two arguments might be the same buffer, we know the result is 0,
   // and we only need to check one size.
   if (StSameBuf) {
-    StSameBuf = StSameBuf->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType()));
+    StSameBuf = StSameBuf->BindExpr(CE, LCtx,
+                                    svalBuilder.makeZeroVal(CE->getType()));
     C.addTransition(StSameBuf);
 
     // If the two arguments are GUARANTEED to be the same, we're done!
@@ -1608,7 +1621,7 @@
     if (isBounded) {
       // Get the max number of characters to compare.
       const Expr *lenExpr = CE->getArg(2);
-      SVal lenVal = state->getSVal(lenExpr);
+      SVal lenVal = state->getSVal(lenExpr, LCtx);
 
       // If the length is known, we can get the right substrings.
       if (const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {
@@ -1645,7 +1658,7 @@
 
       // Build the SVal of the comparison and bind the return value.
       SVal resultVal = svalBuilder.makeIntVal(result, CE->getType());
-      state = state->BindExpr(CE, resultVal);
+      state = state->BindExpr(CE, LCtx, resultVal);
     }
   }
 
@@ -1653,7 +1666,7 @@
     // Conjure a symbolic value. It's the best we can do.
     unsigned Count = C.getCurrentBlockCount();
     SVal resultVal = svalBuilder.getConjuredSymbolVal(NULL, CE, Count);
-    state = state->BindExpr(CE, resultVal);
+    state = state->BindExpr(CE, LCtx, resultVal);
   }
 
   // Record this as a possible path.
@@ -1728,7 +1741,7 @@
     if (!MR)
       continue;
 
-    SVal StrVal = state->getSVal(Init);
+    SVal StrVal = state->getSVal(Init, C.getLocationContext());
     assert(StrVal.isValid() && "Initializer string is unknown or undefined");
     DefinedOrUnknownSVal strLength
       = cast<DefinedOrUnknownSVal>(getCStringLength(C, state, Init, StrVal));

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp Fri Jan 20 10:14:22 2012
@@ -133,7 +133,7 @@
                 return true;
             }
             else {
-              const SVal &V = StoreMgr.Retrieve(store, loc::MemRegionVal(FR));
+              const SVal &V = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
               if (V.isUndef())
                 return true;
             }
@@ -193,7 +193,8 @@
                                          CheckerContext &C) const{
 
   const Expr *Callee = CE->getCallee()->IgnoreParens();
-  SVal L = C.getState()->getSVal(Callee);
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal L = C.getState()->getSVal(Callee, LCtx);
 
   if (L.isUndef()) {
     if (!BT_call_undef)
@@ -210,7 +211,7 @@
     EmitBadCall(BT_call_null.get(), C, CE);
   }
 
-  PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState()),
+  PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState(), LCtx),
                       "Function call argument is an uninitialized value",
                       BT_call_arg);
 }
@@ -219,10 +220,11 @@
                                                 CheckerContext &C) const {
 
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
 
   // FIXME: Handle 'super'?
   if (const Expr *receiver = msg.getInstanceReceiver()) {
-    SVal recVal = state->getSVal(receiver);
+    SVal recVal = state->getSVal(receiver, LCtx);
     if (recVal.isUndef()) {
       if (ExplodedNode *N = C.generateSink()) {
         if (!BT_msg_undef)
@@ -255,7 +257,8 @@
                      "Argument for property setter is an uninitialized value"
                    : "Argument in message expression is an uninitialized value";
   // Check for any arguments that are uninitialized/undefined.
-  PreVisitProcessArgs(C, CallOrObjCMessage(msg, state), bugDesc, BT_msg_arg);
+  PreVisitProcessArgs(C, CallOrObjCMessage(msg, state, LCtx),
+                      bugDesc, BT_msg_arg);
 }
 
 void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
@@ -298,11 +301,12 @@
   // return different values depending on the return type and the architecture.
   QualType RetTy = msg.getType(Ctx);
   CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
+  const LocationContext *LCtx = C.getLocationContext();
 
   if (CanRetTy->isStructureOrClassType()) {
     // Structure returns are safe since the compiler zeroes them out.
     SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx));
-    C.addTransition(state->BindExpr(msg.getOriginExpr(), V));
+    C.addTransition(state->BindExpr(msg.getOriginExpr(), LCtx, V));
     return;
   }
 
@@ -339,7 +343,7 @@
     // of this case unless we have *a lot* more knowledge.
     //
     SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx));
-    C.addTransition(state->BindExpr(msg.getOriginExpr(), V));
+    C.addTransition(state->BindExpr(msg.getOriginExpr(), LCtx, V));
     return;
   }
 

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp Fri Jan 20 10:14:22 2012
@@ -45,7 +45,7 @@
     return;
 
   const ProgramState *state = C.getState();
-  const MemRegion *R = state->getSVal(E).getAsRegion();
+  const MemRegion *R = state->getSVal(E, C.getLocationContext()).getAsRegion();
   if (R == 0)
     return;
 

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp Fri Jan 20 10:14:22 2012
@@ -34,6 +34,25 @@
 }
 
 namespace {
+struct DefaultBool {
+  bool val;
+  DefaultBool() : val(false) {}
+  operator bool() const { return val; }
+  DefaultBool &operator=(bool b) { val = b; return *this; }
+};
+  
+struct ChecksFilter {
+  DefaultBool check_gets;
+  DefaultBool check_getpw;
+  DefaultBool check_mktemp;
+  DefaultBool check_mkstemp;
+  DefaultBool check_strcpy;
+  DefaultBool check_rand;
+  DefaultBool check_vfork;
+  DefaultBool check_FloatLoopCounter;
+  DefaultBool check_UncheckedReturn;
+};
+  
 class WalkAST : public StmtVisitor<WalkAST> {
   BugReporter &BR;
   AnalysisDeclContext* AC;
@@ -41,11 +60,14 @@
   IdentifierInfo *II_setid[num_setids];
 
   const bool CheckRand;
+  const ChecksFilter &filter;
 
 public:
-  WalkAST(BugReporter &br, AnalysisDeclContext* ac)
+  WalkAST(BugReporter &br, AnalysisDeclContext* ac,
+          const ChecksFilter &f)
   : BR(br), AC(ac), II_setid(),
-    CheckRand(isArc4RandomAvailable(BR.getContext())) {}
+    CheckRand(isArc4RandomAvailable(BR.getContext())),
+    filter(f) {}
 
   // Statement visitor methods.
   void VisitCallExpr(CallExpr *CE);
@@ -66,6 +88,7 @@
   void checkCall_gets(const CallExpr *CE, const FunctionDecl *FD);
   void checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD);
   void checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD);
+  void checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD);
   void checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD);
   void checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD);
   void checkCall_rand(const CallExpr *CE, const FunctionDecl *FD);
@@ -105,6 +128,9 @@
     .Case("gets", &WalkAST::checkCall_gets)
     .Case("getpw", &WalkAST::checkCall_getpw)
     .Case("mktemp", &WalkAST::checkCall_mktemp)
+    .Case("mkstemp", &WalkAST::checkCall_mkstemp)
+    .Case("mkdtemp", &WalkAST::checkCall_mkstemp)
+    .Case("mkstemps", &WalkAST::checkCall_mkstemp)
     .Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy)
     .Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat)
     .Case("drand48", &WalkAST::checkCall_rand)
@@ -186,6 +212,9 @@
 ///  CERT: FLP30-C, FLP30-CPP.
 ///
 void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) {
+  if (!filter.check_FloatLoopCounter)
+    return;
+
   // Does the loop have a condition?
   const Expr *condition = FS->getCond();
 
@@ -268,6 +297,9 @@
 //===----------------------------------------------------------------------===//
 
 void WalkAST::checkCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_gets)
+    return;
+  
   const FunctionProtoType *FPT
     = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
   if (!FPT)
@@ -302,6 +334,9 @@
 //===----------------------------------------------------------------------===//
 
 void WalkAST::checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_getpw)
+    return;
+
   const FunctionProtoType *FPT
     = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
   if (!FPT)
@@ -335,11 +370,18 @@
 }
 
 //===----------------------------------------------------------------------===//
-// Check: Any use of 'mktemp' is insecure.It is obsoleted by mkstemp().
+// Check: Any use of 'mktemp' is insecure.  It is obsoleted by mkstemp().
 // CWE-377: Insecure Temporary File
 //===----------------------------------------------------------------------===//
 
 void WalkAST::checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_mktemp) {
+    // Fall back to the security check of looking for enough 'X's in the
+    // format string, since that is a less severe warning.
+    checkCall_mkstemp(CE, FD);
+    return;
+  }
+
   const FunctionProtoType *FPT
     = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
   if(!FPT)
@@ -369,6 +411,88 @@
                      CELoc, &R, 1);
 }
 
+
+//===----------------------------------------------------------------------===//
+// Check: Use of 'mkstemp', 'mktemp', 'mkdtemp' should contain at least 6 X's.
+//===----------------------------------------------------------------------===//
+
+void WalkAST::checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_mkstemp)
+    return;
+
+  StringRef Name = FD->getIdentifier()->getName();
+  std::pair<signed, signed> ArgSuffix =
+    llvm::StringSwitch<std::pair<signed, signed> >(Name)
+      .Case("mktemp", std::make_pair(0,-1))
+      .Case("mkstemp", std::make_pair(0,-1))
+      .Case("mkdtemp", std::make_pair(0,-1))
+      .Case("mkstemps", std::make_pair(0,1))
+      .Default(std::make_pair(-1, -1));
+  
+  assert(ArgSuffix.first >= 0 && "Unsupported function");
+
+  // Check if the number of arguments is consistent with out expectations.
+  unsigned numArgs = CE->getNumArgs();
+  if ((signed) numArgs <= ArgSuffix.first)
+    return;
+  
+  const StringLiteral *strArg =
+    dyn_cast<StringLiteral>(CE->getArg((unsigned)ArgSuffix.first)
+                              ->IgnoreParenImpCasts());
+  
+  // Currently we only handle string literals.  It is possible to do better,
+  // either by looking at references to const variables, or by doing real
+  // flow analysis.
+  if (!strArg || strArg->getCharByteWidth() != 1)
+    return;
+
+  // Count the number of X's, taking into account a possible cutoff suffix.
+  StringRef str = strArg->getString();
+  unsigned numX = 0;
+  unsigned n = str.size();
+
+  // Take into account the suffix.
+  unsigned suffix = 0;
+  if (ArgSuffix.second >= 0) {
+    const Expr *suffixEx = CE->getArg((unsigned)ArgSuffix.second);
+    llvm::APSInt Result;
+    if (!suffixEx->EvaluateAsInt(Result, BR.getContext()))
+      return;
+    // FIXME: Issue a warning.
+    if (Result.isNegative())
+      return;
+    suffix = (unsigned) Result.getZExtValue();
+    n = (n > suffix) ? n - suffix : 0;
+  }
+  
+  for (unsigned i = 0; i < n; ++i)
+    if (str[i] == 'X') ++numX;
+  
+  if (numX >= 6)
+    return;
+  
+  // Issue a warning.
+  SourceRange R = strArg->getSourceRange();
+  PathDiagnosticLocation CELoc =
+    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+  llvm::SmallString<512> buf;
+  llvm::raw_svector_ostream out(buf);
+  out << "Call to '" << Name << "' should have at least 6 'X's in the"
+    " format string to be secure (" << numX << " 'X'";
+  if (numX != 1)
+    out << 's';
+  out << " seen";
+  if (suffix) {
+    out << ", " << suffix << " character";
+    if (suffix > 1)
+      out << 's';
+    out << " used as a suffix";
+  }
+  out << ')';
+  BR.EmitBasicReport("Insecure temporary file creation", "Security",
+                     out.str(), CELoc, &R, 1);
+}
+
 //===----------------------------------------------------------------------===//
 // Check: Any use of 'strcpy' is insecure.
 //
@@ -376,6 +500,9 @@
 // the Bounds of a Memory Buffer 
 //===----------------------------------------------------------------------===//
 void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_strcpy)
+    return;
+  
   if (!checkCall_strCommon(CE, FD))
     return;
 
@@ -400,6 +527,9 @@
 // the Bounds of a Memory Buffer 
 //===----------------------------------------------------------------------===//
 void WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_strcpy)
+    return;
+
   if (!checkCall_strCommon(CE, FD))
     return;
 
@@ -453,7 +583,7 @@
 //===----------------------------------------------------------------------===//
 
 void WalkAST::checkCall_rand(const CallExpr *CE, const FunctionDecl *FD) {
-  if (!CheckRand)
+  if (!filter.check_rand || !CheckRand)
     return;
 
   const FunctionProtoType *FTP
@@ -497,7 +627,7 @@
 //===----------------------------------------------------------------------===//
 
 void WalkAST::checkCall_random(const CallExpr *CE, const FunctionDecl *FD) {
-  if (!CheckRand)
+  if (!CheckRand || !filter.check_rand)
     return;
 
   const FunctionProtoType *FTP
@@ -526,6 +656,9 @@
 //===----------------------------------------------------------------------===//
 
 void WalkAST::checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD) {
+  if (!filter.check_vfork)
+    return;
+
   // All calls to vfork() are insecure, issue a warning.
   SourceRange R = CE->getCallee()->getSourceRange();
   PathDiagnosticLocation CELoc =
@@ -546,6 +679,9 @@
 //===----------------------------------------------------------------------===//
 
 void WalkAST::checkUncheckedReturnValue(CallExpr *CE) {
+  if (!filter.check_UncheckedReturn)
+    return;
+  
   const FunctionDecl *FD = CE->getDirectCallee();
   if (!FD)
     return;
@@ -609,14 +745,29 @@
 namespace {
 class SecuritySyntaxChecker : public Checker<check::ASTCodeBody> {
 public:
+  ChecksFilter filter;
+  
   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
                         BugReporter &BR) const {
-    WalkAST walker(BR, mgr.getAnalysisDeclContext(D));
+    WalkAST walker(BR, mgr.getAnalysisDeclContext(D), filter);
     walker.Visit(D->getBody());
   }
 };
 }
 
-void ento::registerSecuritySyntaxChecker(CheckerManager &mgr) {
-  mgr.registerChecker<SecuritySyntaxChecker>();
+#define REGISTER_CHECKER(name) \
+void ento::register##name(CheckerManager &mgr) {\
+  mgr.registerChecker<SecuritySyntaxChecker>()->filter.check_##name = true;\
 }
+
+REGISTER_CHECKER(gets)
+REGISTER_CHECKER(getpw)
+REGISTER_CHECKER(mkstemp)
+REGISTER_CHECKER(mktemp)
+REGISTER_CHECKER(strcpy)
+REGISTER_CHECKER(rand)
+REGISTER_CHECKER(vfork)
+REGISTER_CHECKER(FloatLoopCounter)
+REGISTER_CHECKER(UncheckedReturn)
+
+

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/Checkers.td
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/Checkers.td?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/Checkers.td Fri Jan 20 10:14:22 2012
@@ -27,6 +27,7 @@
 def DeadCodeExperimental : Package<"deadcode">, InPackage<Experimental>, Hidden;
 
 def Security : Package <"security">;
+def InsecureAPI : Package<"insecureAPI">, InPackage<Security>;
 def SecurityExperimental : Package<"security">, InPackage<Experimental>, Hidden;
 def Taint : Package<"taint">, InPackage<SecurityExperimental>, Hidden;  
 
@@ -164,6 +165,10 @@
   HelpText<"Check improper uses of STL vector iterators">,
   DescFile<"IteratorsChecker.cpp">;
 
+def VirtualCallChecker : Checker<"VirtualCall">,
+  HelpText<"Check virtual function calls during construction or destruction">, 
+  DescFile<"VirtualCallChecker.cpp">;
+
 } // end: "cplusplus.experimental"
 
 //===----------------------------------------------------------------------===//
@@ -175,15 +180,14 @@
 def DeadStoresChecker : Checker<"DeadStores">,
   HelpText<"Check for values stored to variables that are never read afterwards">,
   DescFile<"DeadStoresChecker.cpp">;
+} // end DeadCode
+
+let ParentPackage = DeadCodeExperimental in {
 
 def IdempotentOperationChecker : Checker<"IdempotentOperations">,
   HelpText<"Warn about idempotent operations">,
   DescFile<"IdempotentOperationChecker.cpp">;
 
-} // end DeadCode
-
-let ParentPackage = DeadCodeExperimental in {
-
 def UnreachableCodeChecker : Checker<"UnreachableCode">,
   HelpText<"Check unreachable code">,
   DescFile<"UnreachableCodeChecker.cpp">;
@@ -194,11 +198,39 @@
 // Security checkers.
 //===----------------------------------------------------------------------===//
 
-let ParentPackage = SecurityExperimental in {
+let ParentPackage = InsecureAPI in {
+  def gets : Checker<"gets">,
+    HelpText<"Warn on uses of the 'gets' function">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def getpw : Checker<"getpw">,
+    HelpText<"Warn on uses of the 'getpw' function">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def mktemp : Checker<"mktemp">,
+    HelpText<"Warn on uses of the 'mktemp' function">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def mkstemp : Checker<"mkstemp">,
+    HelpText<"Warn when 'mkstemp' is passed fewer than 6 X's in the format string">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def rand : Checker<"rand">,
+    HelpText<"Warn on uses of the 'rand', 'random', and related functions">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def strcpy : Checker<"strcpy">,
+    HelpText<"Warn on uses of the 'strcpy' and 'strcat' functions">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def vfork : Checker<"vfork">,
+    HelpText<"Warn on uses of the 'vfork' function">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+  def UncheckedReturn : Checker<"UncheckedReturn">,
+    HelpText<"Warn on uses of functions whose return values must be always checked">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+}
+let ParentPackage = Security in {
+  def FloatLoopCounter : Checker<"FloatLoopCounter">,
+    HelpText<"Warn on using a floating point value as a loop counter (CERT: FLP30-C, FLP30-CPP)">,
+    DescFile<"CheckSecuritySyntaxOnly.cpp">;
+}
 
-def SecuritySyntaxChecker : Checker<"SecuritySyntactic">,
-  HelpText<"Perform quick security API checks that require no data flow">,
-  DescFile<"CheckSecuritySyntaxOnly.cpp">;
+let ParentPackage = SecurityExperimental in {
 
 def ArrayBoundChecker : Checker<"ArrayBound">,
   HelpText<"Warn about buffer overflows (older checker)">,

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp Fri Jan 20 10:14:22 2012
@@ -105,7 +105,7 @@
 
   // After chdir("/"), enter the jail, set the enum value JAIL_ENTERED.
   const Expr *ArgExpr = CE->getArg(0);
-  SVal ArgVal = state->getSVal(ArgExpr);
+  SVal ArgVal = state->getSVal(ArgExpr, C.getLocationContext());
   
   if (const MemRegion *R = ArgVal.getAsRegion()) {
     R = R->StripCasts();

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp Fri Jan 20 10:14:22 2012
@@ -109,9 +109,6 @@
     const char *BugType = 0;
 
     switch (dsk) {
-      default:
-        llvm_unreachable("Impossible dead store type.");
-
       case DeadInit:
         BugType = "Dead initialization";
         os << "Value stored to '" << *V

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp Fri Jan 20 10:14:22 2012
@@ -16,6 +16,7 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "clang/Analysis/Analyses/Dominators.h"
+#include "llvm/Support/Process.h"
 
 using namespace clang;
 using namespace ento;
@@ -92,7 +93,8 @@
   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
                         BugReporter &BR) const {
     if (CFG *cfg = mgr.getCFG(D)) {
-      cfg->dump(mgr.getLangOptions());
+      cfg->dump(mgr.getLangOptions(),
+                llvm::sys::Process::StandardErrHasColors());
     }
   }
 };

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp Fri Jan 20 10:14:22 2012
@@ -42,7 +42,7 @@
       !B->getRHS()->getType()->isScalarType())
     return;
 
-  SVal Denom = C.getState()->getSVal(B->getRHS());
+  SVal Denom = C.getState()->getSVal(B->getRHS(), C.getLocationContext());
   const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
 
   // Divide-by-undefined handled in the generic checking for uses of

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp Fri Jan 20 10:14:22 2012
@@ -45,8 +45,7 @@
     return;
 
   const ProgramState *state = C.getState();
-
-  SVal RV = state->getSVal(B->getRHS());
+  SVal RV = state->getSVal(B->getRHS(), C.getLocationContext());
 
   if (!RV.isConstant() || RV.isZeroConstant())
     return;

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp Fri Jan 20 10:14:22 2012
@@ -20,6 +20,8 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/Basic/Builtins.h"
+#include <climits>
 
 using namespace clang;
 using namespace ento;
@@ -28,199 +30,503 @@
 class GenericTaintChecker : public Checker< check::PostStmt<CallExpr>,
                                             check::PreStmt<CallExpr> > {
 public:
-  enum TaintOnPreVisitKind {
-    /// No taint propagates from pre-visit to post-visit.
-    PrevisitNone = 0,
-    /// Based on the pre-visit, the return argument of the call
-    /// should be tainted.
-    PrevisitTaintRet = 1,
-    /// Based on the pre-visit, the call can taint values through it's
-    /// pointer/reference arguments.
-    PrevisitTaintArgs = 2
-  };
+  static void *getTag() { static int Tag; return &Tag; }
+
+  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+  void checkPostStmt(const DeclRefExpr *DRE, CheckerContext &C) const;
+
+  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
 
 private:
+  static const unsigned ReturnValueIndex = UINT_MAX;
+  static const unsigned InvalidArgIndex = UINT_MAX - 1;
+
   mutable llvm::OwningPtr<BugType> BT;
-  void initBugType() const;
+  inline void initBugType() const {
+    if (!BT)
+      BT.reset(new BugType("Taint Analysis", "General"));
+  }
+
+  /// \brief Catch taint related bugs. Check if tainted data is passed to a
+  /// system call etc.
+  bool checkPre(const CallExpr *CE, CheckerContext &C) const;
+
+  /// \brief Add taint sources on a pre-visit.
+  void addSourcesPre(const CallExpr *CE, CheckerContext &C) const;
 
-  /// Given a pointer argument, get the symbol of the value it contains
+  /// \brief Propagate taint generated at pre-visit.
+  bool propagateFromPre(const CallExpr *CE, CheckerContext &C) const;
+
+  /// \brief Add taint sources on a post visit.
+  void addSourcesPost(const CallExpr *CE, CheckerContext &C) const;
+
+  /// \brief Given a pointer argument, get the symbol of the value it contains
   /// (points to).
-  SymbolRef getPointedToSymbol(CheckerContext &C,
-                               const Expr *Arg,
-                               bool IssueWarning = true) const;
+  static SymbolRef getPointedToSymbol(CheckerContext &C, const Expr *Arg);
+
+  static inline bool isTaintedOrPointsToTainted(const Expr *E,
+                                                const ProgramState *State,
+                                                CheckerContext &C) {
+    return (State->isTainted(E, C.getLocationContext()) ||
+            (E->getType().getTypePtr()->isPointerType() &&
+             State->isTainted(getPointedToSymbol(C, E))));
+  }
 
   /// Functions defining the attack surface.
   typedef const ProgramState *(GenericTaintChecker::*FnCheck)(const CallExpr *,
                                                        CheckerContext &C) const;
   const ProgramState *postScanf(const CallExpr *CE, CheckerContext &C) const;
-  const ProgramState *postFscanf(const CallExpr *CE, CheckerContext &C) const;
+  const ProgramState *postSocket(const CallExpr *CE, CheckerContext &C) const;
   const ProgramState *postRetTaint(const CallExpr *CE, CheckerContext &C) const;
-  const ProgramState *postDefault(const CallExpr *CE, CheckerContext &C) const;
 
   /// Taint the scanned input if the file is tainted.
   const ProgramState *preFscanf(const CallExpr *CE, CheckerContext &C) const;
-  /// Taint if any of the arguments are tainted.
-  const ProgramState *preAnyArgs(const CallExpr *CE, CheckerContext &C) const;
 
   /// Check if the region the expression evaluates to is the standard input,
   /// and thus, is tainted.
   bool isStdin(const Expr *E, CheckerContext &C) const;
 
-public:
-  static void *getTag() { static int Tag; return &Tag; }
+  /// Check for CWE-134: Uncontrolled Format String.
+  static const char MsgUncontrolledFormatString[];
+  bool checkUncontrolledFormatString(const CallExpr *CE,
+                                     CheckerContext &C) const;
+
+  /// Check for:
+  /// CERT/STR02-C. "Sanitize data passed to complex subsystems"
+  /// CWE-78, "Failure to Sanitize Data into an OS Command"
+  static const char MsgSanitizeSystemArgs[];
+  bool checkSystemCall(const CallExpr *CE, StringRef Name,
+                       CheckerContext &C) const;
+
+  /// Check if tainted data is used as a buffer size ins strn.. functions,
+  /// and allocators.
+  static const char MsgTaintedBufferSize[];
+  bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl,
+                              CheckerContext &C) const;
+
+  /// Generate a report if the expression is tainted or points to tainted data.
+  bool generateReportIfTainted(const Expr *E, const char Msg[],
+                               CheckerContext &C) const;
+                               
+  
+  typedef llvm::SmallVector<unsigned, 2> ArgVector;
 
-  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
-  void checkPostStmt(const DeclRefExpr *DRE, CheckerContext &C) const;
+  /// \brief A struct used to specify taint propagation rules for a function.
+  ///
+  /// If any of the possible taint source arguments is tainted, all of the
+  /// destination arguments should also be tainted. Use InvalidArgIndex in the
+  /// src list to specify that all of the arguments can introduce taint. Use
+  /// InvalidArgIndex in the dst arguments to signify that all the non-const
+  /// pointer and reference arguments might be tainted on return. If
+  /// ReturnValueIndex is added to the dst list, the return value will be
+  /// tainted.
+  struct TaintPropagationRule {
+    /// List of arguments which can be taint sources and should be checked.
+    ArgVector SrcArgs;
+    /// List of arguments which should be tainted on function return.
+    ArgVector DstArgs;
+    // TODO: Check if using other data structures would be more optimal.
+
+    TaintPropagationRule() {}
+
+    TaintPropagationRule(unsigned SArg,
+                         unsigned DArg, bool TaintRet = false) {
+      SrcArgs.push_back(SArg);
+      DstArgs.push_back(DArg);
+      if (TaintRet)
+        DstArgs.push_back(ReturnValueIndex);
+    }
 
-  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+    TaintPropagationRule(unsigned SArg1, unsigned SArg2,
+                         unsigned DArg, bool TaintRet = false) {
+      SrcArgs.push_back(SArg1);
+      SrcArgs.push_back(SArg2);
+      DstArgs.push_back(DArg);
+      if (TaintRet)
+        DstArgs.push_back(ReturnValueIndex);
+    }
 
-};
-}
+    /// Get the propagation rule for a given function.
+    static TaintPropagationRule
+      getTaintPropagationRule(const FunctionDecl *FDecl,
+                              StringRef Name,
+                              CheckerContext &C);
+
+    inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
+    inline void addDstArg(unsigned A)  { DstArgs.push_back(A); }
+
+    inline bool isNull() const { return SrcArgs.empty(); }
+
+    inline bool isDestinationArgument(unsigned ArgNum) const {
+      return (std::find(DstArgs.begin(),
+                        DstArgs.end(), ArgNum) != DstArgs.end());
+    }
+
+    /// \brief Pre-process a function which propagates taint according to the
+    /// taint rule.
+    const ProgramState *process(const CallExpr *CE, CheckerContext &C) const;
 
-/// Definitions for the checker specific state.
-namespace { struct TaintOnPreVisit {};}
-namespace clang {
-namespace ento {
-  /// A flag which is used to pass information from call pre-visit instruction
-  /// to the call post-visit. The value is an unsigned, which takes on values
-  /// of the TaintOnPreVisitKind enumeration.
-  template<>
-  struct ProgramStateTrait<TaintOnPreVisit> :
-    public ProgramStatePartialTrait<unsigned> {
-    static void *GDMIndex() { return GenericTaintChecker::getTag(); }
   };
-}
-}
+};
+
+const unsigned GenericTaintChecker::ReturnValueIndex;
+const unsigned GenericTaintChecker::InvalidArgIndex;
+
+const char GenericTaintChecker::MsgUncontrolledFormatString[] =
+  "Tainted format string (CWE-134: Uncontrolled Format String)";
 
-inline void GenericTaintChecker::initBugType() const {
-  if (!BT)
-    BT.reset(new BugType("Tainted data checking", "General"));
+const char GenericTaintChecker::MsgSanitizeSystemArgs[] =
+  "Tainted data passed to a system call "
+  "(CERT/STR02-C. Sanitize data passed to complex subsystems)";
+
+const char GenericTaintChecker::MsgTaintedBufferSize[] =
+  "Tainted data is used to specify the buffer size "
+  "(CERT/STR31-C. Guarantee that storage for strings has sufficient space for "
+  "character data and the null terminator)";
+
+} // end of anonymous namespace
+
+/// A set which is used to pass information from call pre-visit instruction
+/// to the call post-visit. The values are unsigned integers, which are either
+/// ReturnValueIndex, or indexes of the pointer/reference argument, which
+/// points to data, which should be tainted on return.
+namespace { struct TaintArgsOnPostVisit{}; }
+namespace clang { namespace ento {
+template<> struct ProgramStateTrait<TaintArgsOnPostVisit>
+    :  public ProgramStatePartialTrait<llvm::ImmutableSet<unsigned> > {
+  static void *GDMIndex() { return GenericTaintChecker::getTag(); }
+};
+}}
+
+GenericTaintChecker::TaintPropagationRule
+GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
+                                                     const FunctionDecl *FDecl,
+                                                     StringRef Name,
+                                                     CheckerContext &C) {
+  // Check for exact name match for functions without builtin substitutes.
+  TaintPropagationRule Rule = llvm::StringSwitch<TaintPropagationRule>(Name)
+    .Case("atoi", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("atol", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("atoll", TaintPropagationRule(0, ReturnValueIndex))
+    .Case("read", TaintPropagationRule(0, 2, 1, true))
+    .Case("pread", TaintPropagationRule(InvalidArgIndex, 1, true))
+    .Default(TaintPropagationRule());
+
+  if (!Rule.isNull())
+    return Rule;
+
+  // Check if it's one of the memory setting/copying functions.
+  // This check is specialized but faster then calling isCLibraryFunction.
+  unsigned BId = 0;
+  if ( (BId = FDecl->getMemoryFunctionKind()) )
+    switch(BId) {
+    case Builtin::BImemcpy:
+    case Builtin::BImemmove:
+    case Builtin::BIstrncpy:
+    case Builtin::BIstrncat:
+      return TaintPropagationRule(1, 2, 0, true);
+      break;
+    case Builtin::BIstrlcpy:
+    case Builtin::BIstrlcat:
+      return TaintPropagationRule(1, 2, 0, false);
+      break;
+    case Builtin::BIstrndup:
+      return TaintPropagationRule(0, 1, ReturnValueIndex);
+      break;
+
+    default:
+      break;
+    };
+
+  // Process all other functions which could be defined as builtins.
+  if (Rule.isNull()) {
+    if (C.isCLibraryFunction(FDecl, "snprintf") ||
+        C.isCLibraryFunction(FDecl, "sprintf"))
+      return TaintPropagationRule(InvalidArgIndex, 0, true);
+    else if (C.isCLibraryFunction(FDecl, "strcpy") ||
+             C.isCLibraryFunction(FDecl, "stpcpy") ||
+             C.isCLibraryFunction(FDecl, "strcat"))
+      return TaintPropagationRule(1, 0, true);
+    else if (C.isCLibraryFunction(FDecl, "bcopy"))
+      return TaintPropagationRule(0, 2, 1, false);
+    else if (C.isCLibraryFunction(FDecl, "strdup") ||
+             C.isCLibraryFunction(FDecl, "strdupa"))
+      return TaintPropagationRule(0, ReturnValueIndex);
+    else if (C.isCLibraryFunction(FDecl, "wcsdup"))
+      return TaintPropagationRule(0, ReturnValueIndex);
+  }
+
+  // Skipping the following functions, since they might be used for cleansing
+  // or smart memory copy:
+  // - memccpy - copying untill hitting a special character.
+
+  return TaintPropagationRule();
 }
 
 void GenericTaintChecker::checkPreStmt(const CallExpr *CE,
                                        CheckerContext &C) const {
-  const ProgramState *State = C.getState();
+  // Check for errors first.
+  if (checkPre(CE, C))
+    return;
 
-  // Set the evaluation function by switching on the callee name.
-  StringRef Name = C.getCalleeName(CE);
+  // Add taint second.
+  addSourcesPre(CE, C);
+}
+
+void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
+                                        CheckerContext &C) const {
+  if (propagateFromPre(CE, C))
+    return;
+  addSourcesPost(CE, C);
+}
+
+void GenericTaintChecker::addSourcesPre(const CallExpr *CE,
+                                        CheckerContext &C) const {
+  const ProgramState *State = 0;
+  const FunctionDecl *FDecl = C.getCalleeDecl(CE);
+  StringRef Name = C.getCalleeName(FDecl);
+  if (Name.empty())
+    return;
+
+  // First, try generating a propagation rule for this function.
+  TaintPropagationRule Rule =
+    TaintPropagationRule::getTaintPropagationRule(FDecl, Name, C);
+  if (!Rule.isNull()) {
+    State = Rule.process(CE, C);
+    if (!State)
+      return;
+    C.addTransition(State);
+    return;
+  }
+
+  // Otherwise, check if we have custom pre-processing implemented.
   FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
     .Case("fscanf", &GenericTaintChecker::preFscanf)
-    .Case("atoi", &GenericTaintChecker::preAnyArgs)
-    .Case("atol", &GenericTaintChecker::preAnyArgs)
-    .Case("atoll", &GenericTaintChecker::preAnyArgs)
     .Default(0);
-
   // Check and evaluate the call.
   if (evalFunction)
     State = (this->*evalFunction)(CE, C);
   if (!State)
     return;
-
   C.addTransition(State);
+
 }
 
-void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
-                                        CheckerContext &C) const {
+bool GenericTaintChecker::propagateFromPre(const CallExpr *CE,
+                                           CheckerContext &C) const {
   const ProgramState *State = C.getState();
-  
+
+  // Depending on what was tainted at pre-visit, we determined a set of
+  // arguments which should be tainted after the function returns. These are
+  // stored in the state as TaintArgsOnPostVisit set.
+  llvm::ImmutableSet<unsigned> TaintArgs = State->get<TaintArgsOnPostVisit>();
+  for (llvm::ImmutableSet<unsigned>::iterator
+         I = TaintArgs.begin(), E = TaintArgs.end(); I != E; ++I) {
+    unsigned ArgNum  = *I;
+
+    // Special handling for the tainted return value.
+    if (ArgNum == ReturnValueIndex) {
+      State = State->addTaint(CE, C.getLocationContext());
+      continue;
+    }
+
+    // The arguments are pointer arguments. The data they are pointing at is
+    // tainted after the call.
+    const Expr* Arg = CE->getArg(ArgNum);
+    SymbolRef Sym = getPointedToSymbol(C, Arg);
+    if (Sym)
+      State = State->addTaint(Sym);
+  }
+
+  // Clear up the taint info from the state.
+  State = State->remove<TaintArgsOnPostVisit>();
+
+  if (State != C.getState()) {
+    C.addTransition(State);
+    return true;
+  }
+  return false;
+}
+
+void GenericTaintChecker::addSourcesPost(const CallExpr *CE,
+                                         CheckerContext &C) const {
   // Define the attack surface.
   // Set the evaluation function by switching on the callee name.
   StringRef Name = C.getCalleeName(CE);
+  if (Name.empty())
+    return;
   FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
     .Case("scanf", &GenericTaintChecker::postScanf)
-    .Case("fscanf", &GenericTaintChecker::postFscanf)
-    .Case("sscanf", &GenericTaintChecker::postFscanf)
     // TODO: Add support for vfscanf & family.
     .Case("getchar", &GenericTaintChecker::postRetTaint)
     .Case("getenv", &GenericTaintChecker::postRetTaint)
     .Case("fopen", &GenericTaintChecker::postRetTaint)
     .Case("fdopen", &GenericTaintChecker::postRetTaint)
     .Case("freopen", &GenericTaintChecker::postRetTaint)
-    .Default(&GenericTaintChecker::postDefault);
+    .Case("socket", &GenericTaintChecker::postSocket)
+    .Default(0);
 
   // If the callee isn't defined, it is not of security concern.
   // Check and evaluate the call.
+  const ProgramState *State = 0;
   if (evalFunction)
     State = (this->*evalFunction)(CE, C);
   if (!State)
     return;
 
-  assert(State->get<TaintOnPreVisit>() == PrevisitNone &&
-         "State has to be cleared.");
   C.addTransition(State);
 }
 
+bool GenericTaintChecker::checkPre(const CallExpr *CE, CheckerContext &C) const{
+
+  if (checkUncontrolledFormatString(CE, C))
+    return true;
+
+  const FunctionDecl *FDecl = C.getCalleeDecl(CE);
+  StringRef Name = C.getCalleeName(FDecl);
+  if (Name.empty())
+    return false;
+
+  if (checkSystemCall(CE, Name, C))
+    return true;
+
+  if (checkTaintedBufferSize(CE, FDecl, C))
+    return true;
+
+  return false;
+}
+
 SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C,
-                                                  const Expr* Arg,
-                                                  bool IssueWarning) const {
+                                                  const Expr* Arg) {
   const ProgramState *State = C.getState();
-  SVal AddrVal = State->getSVal(Arg->IgnoreParens());
+  SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext());
   if (AddrVal.isUnknownOrUndef())
     return 0;
 
   Loc *AddrLoc = dyn_cast<Loc>(&AddrVal);
-
-  if (!AddrLoc && !IssueWarning)
+  if (!AddrLoc)
     return 0;
 
-  // If the Expr is not a location, issue a warning.
-  if (!AddrLoc) {
-    assert(IssueWarning);
-    if (ExplodedNode *N = C.generateSink(State)) {
-      initBugType();
-      BugReport *report = new BugReport(*BT, "Pointer argument is expected.",N);
-      report->addRange(Arg->getSourceRange());
-      C.EmitReport(report);
+  const PointerType *ArgTy =
+    dyn_cast<PointerType>(Arg->getType().getCanonicalType().getTypePtr());
+  assert(ArgTy);
+  SVal Val = State->getSVal(*AddrLoc, ArgTy->getPointeeType());
+  return Val.getAsSymbol();
+}
+
+const ProgramState *
+GenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE,
+                                                   CheckerContext &C) const {
+  const ProgramState *State = C.getState();
+
+  // Check for taint in arguments.
+  bool IsTainted = false;
+  for (ArgVector::const_iterator I = SrcArgs.begin(),
+                                 E = SrcArgs.end(); I != E; ++I) {
+    unsigned ArgNum = *I;
+
+    if (ArgNum == InvalidArgIndex) {
+      // Check if any of the arguments is tainted, but skip the
+      // destination arguments.
+      for (unsigned int i = 0; i < CE->getNumArgs(); ++i) {
+        if (isDestinationArgument(i))
+          continue;
+        if ((IsTainted =
+               GenericTaintChecker::isTaintedOrPointsToTainted(CE->getArg(i),
+                                                               State, C)))
+          break;
+      }
+      break;
     }
-    return 0;
+
+    assert(ArgNum < CE->getNumArgs());
+    if ((IsTainted =
+           GenericTaintChecker::isTaintedOrPointsToTainted(CE->getArg(ArgNum),
+                                                           State, C)))
+      break;
   }
+  if (!IsTainted)
+    return State;
 
-  SVal Val = State->getSVal(*AddrLoc);
-  return Val.getAsSymbol();
+  // Mark the arguments which should be tainted after the function returns.
+  for (ArgVector::const_iterator I = DstArgs.begin(),
+                                 E = DstArgs.end(); I != E; ++I) {
+    unsigned ArgNum = *I;
+
+    // Should we mark all arguments as tainted?
+    if (ArgNum == InvalidArgIndex) {
+      // For all pointer and references that were passed in:
+      //   If they are not pointing to const data, mark data as tainted.
+      //   TODO: So far we are just going one level down; ideally we'd need to
+      //         recurse here.
+      for (unsigned int i = 0; i < CE->getNumArgs(); ++i) {
+        const Expr *Arg = CE->getArg(i);
+        // Process pointer argument.
+        const Type *ArgTy = Arg->getType().getTypePtr();
+        QualType PType = ArgTy->getPointeeType();
+        if ((!PType.isNull() && !PType.isConstQualified())
+            || (ArgTy->isReferenceType() && !Arg->getType().isConstQualified()))
+          State = State->add<TaintArgsOnPostVisit>(i);
+      }
+      continue;
+    }
+
+    // Should mark the return value?
+    if (ArgNum == ReturnValueIndex) {
+      State = State->add<TaintArgsOnPostVisit>(ReturnValueIndex);
+      continue;
+    }
+
+    // Mark the given argument.
+    assert(ArgNum < CE->getNumArgs());
+    State = State->add<TaintArgsOnPostVisit>(ArgNum);
+  }
+
+  return State;
 }
 
+
+// If argument 0 (file descriptor) is tainted, all arguments except for arg 0
+// and arg 1 should get taint.
 const ProgramState *GenericTaintChecker::preFscanf(const CallExpr *CE,
                                                    CheckerContext &C) const {
   assert(CE->getNumArgs() >= 2);
   const ProgramState *State = C.getState();
 
   // Check is the file descriptor is tainted.
-  if (State->isTainted(CE->getArg(0)) || isStdin(CE->getArg(0), C))
-    return State->set<TaintOnPreVisit>(PrevisitTaintArgs);
-  return 0;
-}
-
-// If any other arguments are tainted, mark state as tainted on pre-visit.
-const ProgramState * GenericTaintChecker::preAnyArgs(const CallExpr *CE,
-                                                     CheckerContext &C) const {
-  for (unsigned int i = 0; i < CE->getNumArgs(); ++i) {
-    const ProgramState *State = C.getState();
-    const Expr *Arg = CE->getArg(i);
-    if (State->isTainted(Arg) || State->isTainted(getPointedToSymbol(C, Arg)))
-      return State = State->set<TaintOnPreVisit>(PrevisitTaintRet);
+  if (State->isTainted(CE->getArg(0), C.getLocationContext()) ||
+      isStdin(CE->getArg(0), C)) {
+    // All arguments except for the first two should get taint.
+    for (unsigned int i = 2; i < CE->getNumArgs(); ++i)
+        State = State->add<TaintArgsOnPostVisit>(i);
+    return State;
   }
+
   return 0;
 }
 
-const ProgramState *GenericTaintChecker::postDefault(const CallExpr *CE,
-                                                     CheckerContext &C) const {
-  const ProgramState *State = C.getState();
 
-  // Check if we know that the result needs to be tainted based on the
-  // pre-visit analysis.
-  if (State->get<TaintOnPreVisit>() == PrevisitTaintRet) {
-    State = State->addTaint(CE);
-    return State->set<TaintOnPreVisit>(PrevisitNone);
-  }
+// If argument 0(protocol domain) is network, the return value should get taint.
+const ProgramState *GenericTaintChecker::postSocket(const CallExpr *CE,
+                                                    CheckerContext &C) const {
+  assert(CE->getNumArgs() >= 3);
+  const ProgramState *State = C.getState();
 
-  return 0;
+  SourceLocation DomLoc = CE->getArg(0)->getExprLoc();
+  StringRef DomName = C.getMacroNameOrSpelling(DomLoc);
+  // White list the internal communication protocols.
+  if (DomName.equals("AF_SYSTEM") || DomName.equals("AF_LOCAL") ||
+      DomName.equals("AF_UNIX") || DomName.equals("AF_RESERVED_36"))
+    return State;
+  State = State->addTaint(CE, C.getLocationContext());
+  return State;
 }
 
 const ProgramState *GenericTaintChecker::postScanf(const CallExpr *CE,
                                                    CheckerContext &C) const {
   const ProgramState *State = C.getState();
   assert(CE->getNumArgs() >= 2);
-  SVal x = State->getSVal(CE->getArg(1));
+  SVal x = State->getSVal(CE->getArg(1), C.getLocationContext());
   // All arguments except for the very first one should get taint.
   for (unsigned int i = 1; i < CE->getNumArgs(); ++i) {
     // The arguments are pointer arguments. The data they are pointing at is
@@ -233,42 +539,15 @@
   return State;
 }
 
-/// If argument 0 (file descriptor) is tainted, all arguments except for arg 0
-/// and arg 1 should get taint.
-const ProgramState *GenericTaintChecker::postFscanf(const CallExpr *CE,
-                                                    CheckerContext &C) const {
-  const ProgramState *State = C.getState();
-  assert(CE->getNumArgs() >= 2);
-
-  // Fscanf is only tainted if the input file is tainted at pre visit, so
-  // check for that first.
-  if (State->get<TaintOnPreVisit>() == PrevisitNone)
-    return 0;
-
-  // Reset the taint state.
-  State = State->set<TaintOnPreVisit>(PrevisitNone);
-
-  // All arguments except for the first two should get taint.
-  for (unsigned int i = 2; i < CE->getNumArgs(); ++i) {
-    // The arguments are pointer arguments. The data they are pointing at is
-    // tainted after the call.
-    const Expr* Arg = CE->getArg(i);
-    SymbolRef Sym = getPointedToSymbol(C, Arg);
-    if (Sym)
-      State = State->addTaint(Sym);
-  }
-  return State;
-}
-
 const ProgramState *GenericTaintChecker::postRetTaint(const CallExpr *CE,
                                                       CheckerContext &C) const {
-  return C.getState()->addTaint(CE);
+  return C.getState()->addTaint(CE, C.getLocationContext());
 }
 
 bool GenericTaintChecker::isStdin(const Expr *E,
                                   CheckerContext &C) const {
   const ProgramState *State = C.getState();
-  SVal Val = State->getSVal(E);
+  SVal Val = State->getSVal(E, C.getLocationContext());
 
   // stdin is a pointer, so it would be a region.
   const MemRegion *MemReg = Val.getAsRegion();
@@ -299,6 +578,136 @@
   return false;
 }
 
+static bool getPrintfFormatArgumentNum(const CallExpr *CE,
+                                       const CheckerContext &C,
+                                       unsigned int &ArgNum) {
+  // Find if the function contains a format string argument.
+  // Handles: fprintf, printf, sprintf, snprintf, vfprintf, vprintf, vsprintf,
+  // vsnprintf, syslog, custom annotated functions.
+  const FunctionDecl *FDecl = C.getCalleeDecl(CE);
+  if (!FDecl)
+    return false;
+  for (specific_attr_iterator<FormatAttr>
+         i = FDecl->specific_attr_begin<FormatAttr>(),
+         e = FDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) {
+
+    const FormatAttr *Format = *i;
+    ArgNum = Format->getFormatIdx() - 1;
+    if ((Format->getType() == "printf") && CE->getNumArgs() > ArgNum)
+      return true;
+  }
+
+  // Or if a function is named setproctitle (this is a heuristic).
+  if (C.getCalleeName(CE).find("setproctitle") != StringRef::npos) {
+    ArgNum = 0;
+    return true;
+  }
+
+  return false;
+}
+
+bool GenericTaintChecker::generateReportIfTainted(const Expr *E,
+                                                  const char Msg[],
+                                                  CheckerContext &C) const {
+  assert(E);
+
+  // Check for taint.
+  const ProgramState *State = C.getState();
+  if (!State->isTainted(getPointedToSymbol(C, E)) &&
+      !State->isTainted(E, C.getLocationContext()))
+    return false;
+
+  // Generate diagnostic.
+  if (ExplodedNode *N = C.addTransition()) {
+    initBugType();
+    BugReport *report = new BugReport(*BT, Msg, N);
+    report->addRange(E->getSourceRange());
+    C.EmitReport(report);
+    return true;
+  }
+  return false;
+}
+
+bool GenericTaintChecker::checkUncontrolledFormatString(const CallExpr *CE,
+                                                        CheckerContext &C) const{
+  // Check if the function contains a format string argument.
+  unsigned int ArgNum = 0;
+  if (!getPrintfFormatArgumentNum(CE, C, ArgNum))
+    return false;
+
+  // If either the format string content or the pointer itself are tainted, warn.
+  if (generateReportIfTainted(CE->getArg(ArgNum),
+                              MsgUncontrolledFormatString, C))
+    return true;
+  return false;
+}
+
+bool GenericTaintChecker::checkSystemCall(const CallExpr *CE,
+                                          StringRef Name,
+                                          CheckerContext &C) const {
+  unsigned ArgNum = llvm::StringSwitch<unsigned>(Name)
+    .Case("system", 0)
+    .Case("popen", 0)
+    .Case("execl", 0)
+    .Case("execle", 0)
+    .Case("execlp", 0)
+    .Case("execv", 0)
+    .Case("execvp", 0)
+    .Case("execvP", 0)
+    .Default(UINT_MAX);
+
+  if (ArgNum == UINT_MAX)
+    return false;
+
+  if (generateReportIfTainted(CE->getArg(ArgNum),
+                              MsgSanitizeSystemArgs, C))
+    return true;
+
+  return false;
+}
+
+// TODO: Should this check be a part of the CString checker?
+// If yes, should taint be a global setting?
+bool GenericTaintChecker::checkTaintedBufferSize(const CallExpr *CE,
+                                                 const FunctionDecl *FDecl,
+                                                 CheckerContext &C) const {
+  // If the function has a buffer size argument, set ArgNum.
+  unsigned ArgNum = InvalidArgIndex;
+  unsigned BId = 0;
+  if ( (BId = FDecl->getMemoryFunctionKind()) )
+    switch(BId) {
+    case Builtin::BImemcpy:
+    case Builtin::BImemmove:
+    case Builtin::BIstrncpy:
+      ArgNum = 2;
+      break;
+    case Builtin::BIstrndup:
+      ArgNum = 1;
+      break;
+    default:
+      break;
+    };
+
+  if (ArgNum == InvalidArgIndex) {
+    if (C.isCLibraryFunction(FDecl, "malloc") ||
+        C.isCLibraryFunction(FDecl, "calloc") ||
+        C.isCLibraryFunction(FDecl, "alloca"))
+      ArgNum = 0;
+    else if (C.isCLibraryFunction(FDecl, "memccpy"))
+      ArgNum = 3;
+    else if (C.isCLibraryFunction(FDecl, "realloc"))
+      ArgNum = 1;
+    else if (C.isCLibraryFunction(FDecl, "bcopy"))
+      ArgNum = 2;
+  }
+
+  if (ArgNum != InvalidArgIndex &&
+      generateReportIfTainted(CE->getArg(ArgNum), MsgTaintedBufferSize, C))
+    return true;
+
+  return false;
+}
+
 void ento::registerGenericTaintChecker(CheckerManager &mgr) {
   mgr.registerChecker<GenericTaintChecker>();
 }

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp Fri Jan 20 10:14:22 2012
@@ -142,9 +142,9 @@
   }
 
   const ProgramState *state = C.getState();
-
-  SVal LHSVal = state->getSVal(LHS);
-  SVal RHSVal = state->getSVal(RHS);
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal LHSVal = state->getSVal(LHS, LCtx);
+  SVal RHSVal = state->getSVal(RHS, LCtx);
 
   // If either value is unknown, we can't be 100% sure of all paths.
   if (LHSVal.isUnknownOrUndef() || RHSVal.isUnknownOrUndef()) {

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp Fri Jan 20 10:14:22 2012
@@ -254,7 +254,7 @@
     lexp = M->GetTemporaryExpr();
   if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(lexp))
     lexp = ICE->getSubExpr();
-  SVal sv = state->getSVal(lexp);
+  SVal sv = state->getSVal(lexp, LC);
   const MemRegion *MR = sv.getAsRegion();
   if (!MR)
     return state;
@@ -574,7 +574,7 @@
   const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ME->getBase());
   if (!DRE || getTemplateKind(DRE->getType()) != VectorKind)
     return;
-  SVal tsv = C.getState()->getSVal(DRE);
+  SVal tsv = C.getState()->getSVal(DRE, C.getLocationContext());
   // Get the MemRegion associated with the container instance.
   const MemRegion *MR = tsv.getAsRegion();
   if (!MR)

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp Fri Jan 20 10:14:22 2012
@@ -220,11 +220,11 @@
 static SymbolRef getAsPointeeSymbol(const Expr *Expr,
                                     CheckerContext &C) {
   const ProgramState *State = C.getState();
-  SVal ArgV = State->getSVal(Expr);
+  SVal ArgV = State->getSVal(Expr, C.getLocationContext());
 
   if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&ArgV)) {
     StoreManager& SM = C.getStoreManager();
-    const MemRegion *V = SM.Retrieve(State->getStore(), *X).getAsRegion();
+    const MemRegion *V = SM.getBinding(State->getStore(), *X).getAsRegion();
     if (V)
       return getSymbolForRegion(C, V);
   }
@@ -325,7 +325,7 @@
 
   // Check the argument to the deallocator.
   const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
-  SVal ArgSVal = State->getSVal(ArgExpr);
+  SVal ArgSVal = State->getSVal(ArgExpr, C.getLocationContext());
 
   // Undef is reported by another checker.
   if (ArgSVal.isUndef())
@@ -462,7 +462,8 @@
     // allocated value symbol, since our diagnostics depend on the value
     // returned by the call. Ex: Data should only be freed if noErr was
     // returned during allocation.)
-    SymbolRef RetStatusSymbol = State->getSVal(CE).getAsSymbol();
+    SymbolRef RetStatusSymbol =
+      State->getSVal(CE, C.getLocationContext()).getAsSymbol();
     C.getSymbolManager().addSymbolDependency(V, RetStatusSymbol);
 
     // Track the allocated value in the checker state.
@@ -481,7 +482,8 @@
 
   // Check  if the value is escaping through the return.
   const ProgramState *state = C.getState();
-  const MemRegion *V = state->getSVal(retExpr).getAsRegion();
+  const MemRegion *V =
+    state->getSVal(retExpr, C.getLocationContext()).getAsRegion();
   if (!V)
     return;
   state = state->remove<AllocatedData>(getSymbolForRegion(C, V));

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp Fri Jan 20 10:14:22 2012
@@ -57,7 +57,8 @@
   // Check if the first argument is stack allocated.  If so, issue a warning
   // because that's likely to be bad news.
   const ProgramState *state = C.getState();
-  const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion();
+  const MemRegion *R =
+    state->getSVal(CE->getArg(0), C.getLocationContext()).getAsRegion();
   if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
     return;
 

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Fri Jan 20 10:14:22 2012
@@ -64,8 +64,14 @@
 
 class RegionState {};
 
-class MallocChecker : public Checker<eval::Call, check::DeadSymbols, check::EndPath, check::PreStmt<ReturnStmt>, check::Location,
-                               check::Bind, eval::Assume> {
+class MallocChecker : public Checker<eval::Call,
+                                     check::DeadSymbols,
+                                     check::EndPath,
+                                     check::PreStmt<ReturnStmt>,
+                                     check::Location,
+                                     check::Bind,
+                                     eval::Assume>
+{
   mutable llvm::OwningPtr<BuiltinBug> BT_DoubleFree;
   mutable llvm::OwningPtr<BuiltinBug> BT_Leak;
   mutable llvm::OwningPtr<BuiltinBug> BT_UseFree;
@@ -94,7 +100,9 @@
   static const ProgramState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
                                      const Expr *SizeEx, SVal Init,
                                      const ProgramState *state) {
-    return MallocMemAux(C, CE, state->getSVal(SizeEx), Init, state);
+    return MallocMemAux(C, CE,
+                        state->getSVal(SizeEx, C.getLocationContext()),
+                        Init, state);
   }
   static const ProgramState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
                                      SVal SizeEx, SVal Init,
@@ -104,7 +112,8 @@
   void FreeMemAttr(CheckerContext &C, const CallExpr *CE,
                    const OwnershipAttr* Att) const;
   const ProgramState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
-                           const ProgramState *state, unsigned Num, bool Hold) const;
+                                 const ProgramState *state, unsigned Num,
+                                 bool Hold) const;
 
   void ReallocMem(CheckerContext &C, const CallExpr *CE) const;
   static void CallocMem(CheckerContext &C, const CallExpr *CE);
@@ -182,8 +191,6 @@
         rv = true;
         break;
       }
-      default:
-        break;
       }
     }
   }
@@ -221,8 +228,9 @@
   SValBuilder &svalBuilder = C.getSValBuilder();
 
   // Set the return value.
-  SVal retVal = svalBuilder.getConjuredSymbolVal(NULL, CE, CE->getType(), Count);
-  state = state->BindExpr(CE, retVal);
+  SVal retVal = svalBuilder.getConjuredSymbolVal(NULL, CE,
+                                                 CE->getType(), Count);
+  state = state->BindExpr(CE, C.getLocationContext(), retVal);
 
   // Fill the region with the initialization value.
   state = state->bindDefault(retVal, Init);
@@ -258,18 +266,21 @@
 
   for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
        I != E; ++I) {
-    const ProgramState *state = FreeMemAux(C, CE, C.getState(), *I,
-                                      Att->getOwnKind() == OwnershipAttr::Holds);
+    const ProgramState *state =
+      FreeMemAux(C, CE, C.getState(), *I,
+                 Att->getOwnKind() == OwnershipAttr::Holds);
     if (state)
       C.addTransition(state);
   }
 }
 
-const ProgramState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
-                                         const ProgramState *state, unsigned Num,
-                                         bool Hold) const {
+const ProgramState *MallocChecker::FreeMemAux(CheckerContext &C,
+                                              const CallExpr *CE,
+                                              const ProgramState *state,
+                                              unsigned Num,
+                                              bool Hold) const {
   const Expr *ArgExpr = CE->getArg(Num);
-  SVal ArgVal = state->getSVal(ArgExpr);
+  SVal ArgVal = state->getSVal(ArgExpr, C.getLocationContext());
 
   DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(ArgVal);
 
@@ -396,8 +407,7 @@
   default: {
     const MemSpaceRegion *MS = MR->getMemorySpace();
     
-    switch (MS->getKind()) {
-    case MemRegion::StackLocalsSpaceRegionKind: {
+    if (isa<StackLocalsSpaceRegion>(MS)) {
       const VarRegion *VR = dyn_cast<VarRegion>(MR);
       const VarDecl *VD;
       if (VR)
@@ -411,7 +421,8 @@
         os << "the address of a local stack variable";
       return true;
     }
-    case MemRegion::StackArgumentsSpaceRegionKind: {
+
+    if (isa<StackArgumentsSpaceRegion>(MS)) {
       const VarRegion *VR = dyn_cast<VarRegion>(MR);
       const VarDecl *VD;
       if (VR)
@@ -425,8 +436,8 @@
         os << "the address of a parameter";
       return true;
     }
-    case MemRegion::NonStaticGlobalSpaceRegionKind:
-    case MemRegion::StaticGlobalSpaceRegionKind: {
+
+    if (isa<GlobalsSpaceRegion>(MS)) {
       const VarRegion *VR = dyn_cast<VarRegion>(MR);
       const VarDecl *VD;
       if (VR)
@@ -443,9 +454,8 @@
         os << "the address of a global variable";
       return true;
     }
-    default:
-      return false;
-    }
+
+    return false;
   }
   }
 }
@@ -491,8 +501,9 @@
 void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
   const Expr *arg0Expr = CE->getArg(0);
+  const LocationContext *LCtx = C.getLocationContext();
   DefinedOrUnknownSVal arg0Val 
-    = cast<DefinedOrUnknownSVal>(state->getSVal(arg0Expr));
+    = cast<DefinedOrUnknownSVal>(state->getSVal(arg0Expr, LCtx));
 
   SValBuilder &svalBuilder = C.getSValBuilder();
 
@@ -506,7 +517,7 @@
 
   // Get the value of the size argument.
   DefinedOrUnknownSVal Arg1Val = 
-    cast<DefinedOrUnknownSVal>(state->getSVal(Arg1));
+    cast<DefinedOrUnknownSVal>(state->getSVal(Arg1, LCtx));
 
   // Compare the size argument to 0.
   DefinedOrUnknownSVal SizeZero =
@@ -532,14 +543,17 @@
 
   if (const ProgramState *stateNotEqual = state->assume(PtrEQ, false)) {
     // If the size is 0, free the memory.
-    if (const ProgramState *stateSizeZero = stateNotEqual->assume(SizeZero, true))
+    if (const ProgramState *stateSizeZero =
+          stateNotEqual->assume(SizeZero, true))
       if (const ProgramState *stateFree = 
           FreeMemAux(C, CE, stateSizeZero, 0, false)) {
 
         // Bind the return value to NULL because it is now free.
-        C.addTransition(stateFree->BindExpr(CE, svalBuilder.makeNull(), true));
+        C.addTransition(stateFree->BindExpr(CE, LCtx,
+                                            svalBuilder.makeNull(), true));
       }
-    if (const ProgramState *stateSizeNotZero = stateNotEqual->assume(SizeZero,false))
+    if (const ProgramState *stateSizeNotZero =
+          stateNotEqual->assume(SizeZero,false))
       if (const ProgramState *stateFree = FreeMemAux(C, CE, stateSizeNotZero,
                                                 0, false)) {
         // FIXME: We should copy the content of the original buffer.
@@ -553,9 +567,9 @@
 void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) {
   const ProgramState *state = C.getState();
   SValBuilder &svalBuilder = C.getSValBuilder();
-
-  SVal count = state->getSVal(CE->getArg(0));
-  SVal elementSize = state->getSVal(CE->getArg(1));
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal count = state->getSVal(CE->getArg(0), LCtx);
+  SVal elementSize = state->getSVal(CE->getArg(1), LCtx);
   SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize,
                                         svalBuilder.getContext().getSizeType());  
   SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
@@ -626,7 +640,7 @@
 
   const ProgramState *state = C.getState();
 
-  SymbolRef Sym = state->getSVal(retExpr).getAsSymbol();
+  SymbolRef Sym = state->getSVal(retExpr, C.getLocationContext()).getAsSymbol();
   if (!Sym)
     return;
 
@@ -641,8 +655,9 @@
   C.addTransition(state);
 }
 
-const ProgramState *MallocChecker::evalAssume(const ProgramState *state, SVal Cond, 
-                                         bool Assumption) const {
+const ProgramState *MallocChecker::evalAssume(const ProgramState *state,
+                                              SVal Cond, 
+                                              bool Assumption) const {
   // If a symblic region is assumed to NULL, set its state to AllocateFailed.
   // FIXME: should also check symbols assumed to non-null.
 

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp Fri Jan 20 10:14:22 2012
@@ -42,7 +42,7 @@
   bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();
 
   if (!BuildSinks) {
-    SVal L = state->getSVal(Callee);
+    SVal L = state->getSVal(Callee, C.getLocationContext());
     const FunctionDecl *FD = L.getAsFunctionDecl();
     if (!FD)
       return;

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp Fri Jan 20 10:14:22 2012
@@ -36,9 +36,10 @@
 }
 
 static StringRef getCalleeName(const ProgramState *State,
-                               const CallExpr *CE) {
+                               const CallExpr *CE,
+                               const LocationContext *LCtx) {
   const Expr *Callee = CE->getCallee();
-  SVal L = State->getSVal(Callee);
+  SVal L = State->getSVal(Callee, LCtx);
   const FunctionDecl *funDecl =  L.getAsFunctionDecl();
   if (!funDecl)
     return StringRef();
@@ -52,7 +53,8 @@
                                  ExprEngine &Eng,
                                  ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) const {
-  StringRef FName = getCalleeName(Pred->getState(), CE);
+  StringRef FName = getCalleeName(Pred->getState(),
+                                  CE, Pred->getLocationContext());
   if (FName.empty())
     return false;
 
@@ -103,8 +105,9 @@
   
   // Load 'theValue'.
   const ProgramState *state = Pred->getState();
+  const LocationContext *LCtx = Pred->getLocationContext();
   ExplodedNodeSet Tmp;
-  SVal location = state->getSVal(theValueExpr);
+  SVal location = state->getSVal(theValueExpr, LCtx);
   // Here we should use the value type of the region as the load type, because
   // we are simulating the semantics of the function, not the semantics of 
   // passing argument. So the type of theValue expr is not we are loading.
@@ -135,9 +138,9 @@
     // Use direct bindings from the environment since we are forcing a load
     // from a location that the Environment would typically not be used
     // to bind a value.
-    SVal theValueVal_untested = stateLoad->getSVal(theValueExpr, true);
+    SVal theValueVal_untested = stateLoad->getSVal(theValueExpr, LCtx, true);
 
-    SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr);
+    SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr, LCtx);
 
     // FIXME: Issue an error.
     if (theValueVal_untested.isUndef() || oldValueVal_untested.isUndef()) {
@@ -161,7 +164,7 @@
     if (stateEqual) {
       // Perform the store.
       ExplodedNodeSet TmpStore;
-      SVal val = stateEqual->getSVal(newValueExpr);
+      SVal val = stateEqual->getSVal(newValueExpr, LCtx);
 
       // Handle implicit value casts.
       if (const TypedValueRegion *R =
@@ -189,7 +192,8 @@
         QualType T = CE->getType();
         if (!T->isVoidType())
           Res = Eng.getSValBuilder().makeTruthVal(true, T);
-        B.generateNode(CE, predNew, stateNew->BindExpr(CE, Res), false, this);
+        B.generateNode(CE, predNew, stateNew->BindExpr(CE, LCtx, Res),
+                       false, this);
       }
     }
 
@@ -201,7 +205,8 @@
       if (!T->isVoidType())
         Res = Eng.getSValBuilder().makeTruthVal(false, CE->getType());
       StmtNodeBuilder B(N, Dst, Eng.getBuilderContext());    
-      B.generateNode(CE, N, stateNotEqual->BindExpr(CE, Res), false, this);
+      B.generateNode(CE, N, stateNotEqual->BindExpr(CE, LCtx, Res),
+                     false, this);
     }
   }
 

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp Fri Jan 20 10:14:22 2012
@@ -39,7 +39,7 @@
 
   const Expr *Ex = S->getSynchExpr();
   const ProgramState *state = C.getState();
-  SVal V = state->getSVal(Ex);
+  SVal V = state->getSVal(Ex, C.getLocationContext());
 
   // Uninitialized value used for the mutex?
   if (isa<UndefinedVal>(V)) {

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp Fri Jan 20 10:14:22 2012
@@ -156,7 +156,7 @@
 /// points to and is an object that did not come from the result of calling
 /// an initializer.
 static bool isInvalidSelf(const Expr *E, CheckerContext &C) {
-  SVal exprVal = C.getState()->getSVal(E);
+  SVal exprVal = C.getState()->getSVal(E, C.getLocationContext());
   if (!hasSelfFlag(exprVal, SelfFlag_Self, C))
     return false; // value did not come from 'self'.
   if (hasSelfFlag(exprVal, SelfFlag_InitRes, C))
@@ -206,7 +206,7 @@
     // value out when we return from this method.
     state = state->set<CalledInit>(true);
     
-    SVal V = state->getSVal(msg.getOriginExpr());
+    SVal V = state->getSVal(msg.getOriginExpr(), C.getLocationContext());
     addSelfFlag(state, V, SelfFlag_InitRes, C);
     return;
   }
@@ -262,7 +262,7 @@
   const ProgramState *state = C.getState();
   for (CallExpr::const_arg_iterator
          I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
-    SVal argV = state->getSVal(*I);
+    SVal argV = state->getSVal(*I, C.getLocationContext());
     if (isSelfVar(argV, C)) {
       unsigned selfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C);
       C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
@@ -278,9 +278,10 @@
 void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
                                         CheckerContext &C) const {
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
   for (CallExpr::const_arg_iterator
          I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
-    SVal argV = state->getSVal(*I);
+    SVal argV = state->getSVal(*I, LCtx);
     if (isSelfVar(argV, C)) {
       SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
       state = state->remove<PreCallSelfFlags>();
@@ -289,7 +290,7 @@
     } else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
       SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
       state = state->remove<PreCallSelfFlags>();
-      addSelfFlag(state, state->getSVal(CE), prevFlags, C);
+      addSelfFlag(state, state->getSVal(CE, LCtx), prevFlags, C);
       return;
     }
   }

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp Fri Jan 20 10:14:22 2012
@@ -37,8 +37,9 @@
     return;
 
   const ProgramState *state = C.getState();
-  SVal LV = state->getSVal(B->getLHS());
-  SVal RV = state->getSVal(B->getRHS());
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal LV = state->getSVal(B->getLHS(), LCtx);
+  SVal RV = state->getSVal(B->getRHS(), LCtx);
 
   const MemRegion *LR = LV.getAsRegion();
 

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp Fri Jan 20 10:14:22 2012
@@ -40,8 +40,9 @@
     return;
 
   const ProgramState *state = C.getState();
-  SVal LV = state->getSVal(B->getLHS());
-  SVal RV = state->getSVal(B->getRHS());
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal LV = state->getSVal(B->getLHS(), LCtx);
+  SVal RV = state->getSVal(B->getRHS(), LCtx);
 
   const MemRegion *LR = LV.getAsRegion();
   const MemRegion *RR = RV.getAsRegion();

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp Fri Jan 20 10:14:22 2012
@@ -57,6 +57,7 @@
 void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
                                        CheckerContext &C) const {
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
   StringRef FName = C.getCalleeName(CE);
   if (FName.empty())
     return;
@@ -67,24 +68,28 @@
   if (FName == "pthread_mutex_lock" ||
       FName == "pthread_rwlock_rdlock" ||
       FName == "pthread_rwlock_wrlock")
-    AcquireLock(C, CE, state->getSVal(CE->getArg(0)), false, PthreadSemantics);
+    AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+                false, PthreadSemantics);
   else if (FName == "lck_mtx_lock" ||
            FName == "lck_rw_lock_exclusive" ||
            FName == "lck_rw_lock_shared") 
-    AcquireLock(C, CE, state->getSVal(CE->getArg(0)), false, XNUSemantics);
+    AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+                false, XNUSemantics);
   else if (FName == "pthread_mutex_trylock" ||
            FName == "pthread_rwlock_tryrdlock" ||
            FName == "pthread_rwlock_tryrwlock")
-    AcquireLock(C, CE, state->getSVal(CE->getArg(0)), true, PthreadSemantics);
+    AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+                true, PthreadSemantics);
   else if (FName == "lck_mtx_try_lock" ||
            FName == "lck_rw_try_lock_exclusive" ||
            FName == "lck_rw_try_lock_shared")
-    AcquireLock(C, CE, state->getSVal(CE->getArg(0)), true, XNUSemantics);
+    AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+                true, XNUSemantics);
   else if (FName == "pthread_mutex_unlock" ||
            FName == "pthread_rwlock_unlock" ||
            FName == "lck_mtx_unlock" ||
            FName == "lck_rw_done")
-    ReleaseLock(C, CE, state->getSVal(CE->getArg(0)));
+    ReleaseLock(C, CE, state->getSVal(CE->getArg(0), LCtx));
 }
 
 void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
@@ -97,7 +102,7 @@
   
   const ProgramState *state = C.getState();
   
-  SVal X = state->getSVal(CE);
+  SVal X = state->getSVal(CE, C.getLocationContext());
   if (X.isUnknownOrUndef())
     return;
   

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Fri Jan 20 10:14:22 2012
@@ -358,15 +358,15 @@
 
   /// DefaultArgEffect - The default ArgEffect to apply to arguments that
   ///  do not have an entry in Args.
-  ArgEffect   DefaultArgEffect;
+  ArgEffect DefaultArgEffect;
 
   /// Receiver - If this summary applies to an Objective-C message expression,
   ///  this is the effect applied to the state of the receiver.
-  ArgEffect   Receiver;
+  ArgEffect Receiver;
 
   /// Ret - The effect on the return value.  Used to indicate if the
   ///  function/method call returns a new tracked symbol.
-  RetEffect   Ret;
+  RetEffect Ret;
 
 public:
   RetainSummary(ArgEffects A, RetEffect R, ArgEffect defaultEff,
@@ -436,7 +436,7 @@
   ObjCSummaryKey(Selector s)
     : II(0), S(s) {}
 
-  IdentifierInfo* getIdentifier() const { return II; }
+  IdentifierInfo *getIdentifier() const { return II; }
   Selector getSelector() const { return S; }
 };
 }
@@ -516,7 +516,7 @@
     return Summ;
   }
 
-  const RetainSummary * find(IdentifierInfo* II, Selector S) {
+  const RetainSummary *find(IdentifierInfo* II, Selector S) {
     // FIXME: Class method lookup.  Right now we dont' have a good way
     // of going between IdentifierInfo* and the class hierarchy.
     MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
@@ -584,7 +584,7 @@
   ArgEffects::Factory AF;
 
   /// ScratchArgs - A holding buffer for construct ArgEffects.
-  ArgEffects ScratchArgs;
+  ArgEffects ScratchArgs; 
 
   /// ObjCAllocRetE - Default return effect for methods returning Objective-C
   ///  objects.
@@ -614,18 +614,18 @@
     return &DefaultSummary;
   }
   
-  const RetainSummary * getUnarySummary(const FunctionType* FT,
+  const RetainSummary *getUnarySummary(const FunctionType* FT,
                                        UnaryFuncKind func);
 
-  const RetainSummary * getCFSummaryCreateRule(const FunctionDecl *FD);
-  const RetainSummary * getCFSummaryGetRule(const FunctionDecl *FD);
-  const RetainSummary * getCFCreateGetRuleSummary(const FunctionDecl *FD);
+  const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
+  const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
+  const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
 
-  const RetainSummary * getPersistentSummary(ArgEffects AE, RetEffect RetEff,
+  const RetainSummary *getPersistentSummary(ArgEffects AE, RetEffect RetEff,
                                             ArgEffect ReceiverEff = DoNothing,
                                             ArgEffect DefaultEff = MayEscape);
 
-  const RetainSummary * getPersistentSummary(RetEffect RE,
+  const RetainSummary *getPersistentSummary(RetEffect RE,
                                             ArgEffect ReceiverEff = DoNothing,
                                             ArgEffect DefaultEff = MayEscape) {
     return getPersistentSummary(getArgEffects(), RE, ReceiverEff, DefaultEff);
@@ -729,19 +729,19 @@
     InitializeMethodSummaries();
   }
 
-  const RetainSummary * getSummary(const FunctionDecl *FD);
+  const RetainSummary *getSummary(const FunctionDecl *FD);
 
   const RetainSummary *getInstanceMethodSummary(const ObjCMessage &msg,
                                                 const ProgramState *state,
                                                 const LocationContext *LC);
 
-  const RetainSummary * getInstanceMethodSummary(const ObjCMessage &msg,
+  const RetainSummary *getInstanceMethodSummary(const ObjCMessage &msg,
                                                 const ObjCInterfaceDecl *ID) {
     return getInstanceMethodSummary(msg.getSelector(), 0,
                             ID, msg.getMethodDecl(), msg.getType(Ctx));
   }
 
-  const RetainSummary * getInstanceMethodSummary(Selector S,
+  const RetainSummary *getInstanceMethodSummary(Selector S,
                                                 IdentifierInfo *ClsName,
                                                 const ObjCInterfaceDecl *ID,
                                                 const ObjCMethodDecl *MD,
@@ -779,7 +779,7 @@
       return getClassMethodSummary(S, ClsName, ID, MD, ResultTy);
   }
 
-  const RetainSummary * getCommonMethodSummary(const ObjCMethodDecl *MD,
+  const RetainSummary *getCommonMethodSummary(const ObjCMethodDecl *MD,
                                               Selector S, QualType RetTy);
 
   void updateSummaryFromAnnotations(const RetainSummary *&Summ,
@@ -1099,7 +1099,6 @@
     case cfretain: Effect = IncRef; break;
     case cfrelease: Effect = DecRef; break;
     case cfmakecollectable: Effect = MakeCollectable; break;
-    default: llvm_unreachable("Not a supported unary function.");
   }
 
   ScratchArgs = AF.add(ScratchArgs, 0, Effect);
@@ -1312,7 +1311,7 @@
   SVal receiverV;
 
   if (Receiver) {
-    receiverV = state->getSValAsScalarOrLoc(Receiver);
+    receiverV = state->getSValAsScalarOrLoc(Receiver, LC);
 
     // FIXME: Eventually replace the use of state->get<RefBindings> with
     // a generic API for reasoning about the Objective-C types of symbolic
@@ -1841,6 +1840,7 @@
   // Check if the type state has changed.
   const ProgramState *PrevSt = PrevN->getState();
   const ProgramState *CurrSt = N->getState();
+  const LocationContext *LCtx = N->getLocationContext();
 
   const RefVal* CurrT = CurrSt->get<RefBindings>(Sym);
   if (!CurrT) return NULL;
@@ -1860,7 +1860,7 @@
 
     if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
       // Get the name of the callee (if it is available).
-      SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee());
+      SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
       if (const FunctionDecl *FD = X.getAsFunctionDecl())
         os << "Call to function '" << *FD << '\'';
       else
@@ -1920,7 +1920,7 @@
 
         // Retrieve the value of the argument.  Is it the symbol
         // we are interested in?
-        if (CurrSt->getSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym)
+        if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
           continue;
 
         // We have an argument.  Get the effect!
@@ -1929,7 +1929,8 @@
     }
     else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
       if (const Expr *receiver = ME->getInstanceReceiver())
-        if (CurrSt->getSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) {
+        if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
+              .getAsLocSymbol() == Sym) {
           // The symbol we are tracking is the receiver.
           AEffects.push_back(Summ->getReceiverEffect());
         }
@@ -1957,7 +1958,8 @@
     if (contains(AEffects, MakeCollectable)) {
       // Get the name of the function.
       const Stmt *S = cast<StmtPoint>(N->getLocation()).getStmt();
-      SVal X = CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee());
+      SVal X =
+        CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee(), LCtx);
       const FunctionDecl *FD = X.getAsFunctionDecl();
 
       if (GCEnabled) {
@@ -2069,7 +2071,7 @@
   for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
        I!=E; ++I)
     if (const Expr *Exp = dyn_cast_or_null<Expr>(*I))
-      if (CurrSt->getSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) {
+      if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
         P->addRange(Exp->getSourceRange());
         break;
       }
@@ -2105,7 +2107,7 @@
     }
 
     operator bool() { return First && Binding; }
-    const MemRegion* getRegion() { return Binding; }
+    const MemRegion *getRegion() { return Binding; }
   };
 }
 
@@ -2201,10 +2203,10 @@
     }
     else {
       const FunctionDecl *FD = cast<FunctionDecl>(D);
-      os << " is return from a function whose name ('"
+      os << " is returned from a function whose name ('"
          << FD->getNameAsString()
          << "') does not contain 'Copy' or 'Create'.  This violates the naming"
-            " convention rules given the Memory Management Guide for Core"
+            " convention rules given in the Memory Management Guide for Core"
             " Foundation";
     }    
   }
@@ -2505,7 +2507,8 @@
 
   const ProgramState *state = C.getState();
   const BlockDataRegion *R =
-    cast<BlockDataRegion>(state->getSVal(BE).getAsRegion());
+    cast<BlockDataRegion>(state->getSVal(BE,
+                                         C.getLocationContext()).getAsRegion());
 
   BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
                                             E = R->referenced_vars_end();
@@ -2555,7 +2558,7 @@
   }
   
   const ProgramState *state = C.getState();
-  SymbolRef Sym = state->getSVal(CE).getAsLocSymbol();
+  SymbolRef Sym = state->getSVal(CE, C.getLocationContext()).getAsLocSymbol();
   if (!Sym)
     return;
   const RefVal* T = state->get<RefBindings>(Sym);
@@ -2579,7 +2582,7 @@
   // Get the callee.
   const ProgramState *state = C.getState();
   const Expr *Callee = CE->getCallee();
-  SVal L = state->getSVal(Callee);
+  SVal L = state->getSVal(Callee, C.getLocationContext());
 
   RetainSummaryManager &Summaries = getSummaryManager(C);
   const RetainSummary *Summ = 0;
@@ -2599,7 +2602,7 @@
   if (!Summ)
     Summ = Summaries.getDefaultSummary();
 
-  checkSummary(*Summ, CallOrObjCMessage(CE, state), C);
+  checkSummary(*Summ, CallOrObjCMessage(CE, state, C.getLocationContext()), C);
 }
 
 void RetainCountChecker::checkPostStmt(const CXXConstructExpr *CE,
@@ -2616,7 +2619,7 @@
     return;
 
   const ProgramState *state = C.getState();
-  checkSummary(*Summ, CallOrObjCMessage(CE, state), C);
+  checkSummary(*Summ, CallOrObjCMessage(CE, state, C.getLocationContext()), C);
 }
 
 void RetainCountChecker::checkPostObjCMessage(const ObjCMessage &Msg, 
@@ -2637,7 +2640,7 @@
   if (!Summ)
     return;
 
-  checkSummary(*Summ, CallOrObjCMessage(Msg, state), C);
+  checkSummary(*Summ, CallOrObjCMessage(Msg, state, C.getLocationContext()), C);
 }
 
 /// GetReturnType - Used to get the return type of a message expression or
@@ -2729,7 +2732,7 @@
 
   switch (RE.getKind()) {
     default:
-      llvm_unreachable("Unhandled RetEffect."); break;
+      llvm_unreachable("Unhandled RetEffect.");
 
     case RetEffect::NoRet:
       // No work necessary.
@@ -2737,7 +2740,8 @@
 
     case RetEffect::OwnedAllocatedSymbol:
     case RetEffect::OwnedSymbol: {
-      SymbolRef Sym = state->getSVal(CallOrMsg.getOriginExpr()).getAsSymbol();
+      SymbolRef Sym = state->getSVal(CallOrMsg.getOriginExpr(),
+                                     C.getLocationContext()).getAsSymbol();
       if (!Sym)
         break;
 
@@ -2764,7 +2768,7 @@
     case RetEffect::ARCNotOwnedSymbol:
     case RetEffect::NotOwnedSymbol: {
       const Expr *Ex = CallOrMsg.getOriginExpr();
-      SymbolRef Sym = state->getSVal(Ex).getAsSymbol();
+      SymbolRef Sym = state->getSVal(Ex, C.getLocationContext()).getAsSymbol();
       if (!Sym)
         break;
 
@@ -2829,7 +2833,6 @@
     case IncRefMsg:
     case MakeCollectable:
       llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted");
-      return state;
 
     case Dealloc:
       // Any use of -dealloc in GC is *bad*.
@@ -2842,7 +2845,6 @@
       switch (V.getKind()) {
         default:
           llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
-          break;
         case RefVal::Owned:
           // The object immediately transitions to the released state.
           V = V ^ RefVal::Released;
@@ -2886,7 +2888,6 @@
       switch (V.getKind()) {
         default:
           llvm_unreachable("Invalid RefVal state for a retain.");
-          break;
         case RefVal::Owned:
         case RefVal::NotOwned:
           V = V + 1;
@@ -2908,7 +2909,6 @@
         default:
           // case 'RefVal::Released' handled above.
           llvm_unreachable("Invalid RefVal state for a release.");
-          break;
 
         case RefVal::Owned:
           assert(V.getCount() > 0);
@@ -2952,7 +2952,6 @@
   switch (ErrorKind) {
     default:
       llvm_unreachable("Unhandled error.");
-      return;
     case RefVal::ErrorUseAfterRelease:
       if (!useAfterRelease)
         useAfterRelease.reset(new UseAfterRelease());
@@ -3030,14 +3029,15 @@
     return false;
 
   // Bind the return value.
-  SVal RetVal = state->getSVal(CE->getArg(0));
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
   if (RetVal.isUnknown()) {
     // If the receiver is unknown, conjure a return value.
     SValBuilder &SVB = C.getSValBuilder();
     unsigned Count = C.getCurrentBlockCount();
     SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count);
   }
-  state = state->BindExpr(CE, RetVal, false);
+  state = state->BindExpr(CE, LCtx, RetVal, false);
 
   // FIXME: This should not be necessary, but otherwise the argument seems to be
   // considered alive during the next statement.
@@ -3072,7 +3072,8 @@
     return;
 
   const ProgramState *state = C.getState();
-  SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol();
+  SymbolRef Sym =
+    state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
   if (!Sym)
     return;
 

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp Fri Jan 20 10:14:22 2012
@@ -39,7 +39,7 @@
   if (!RetE)
     return;
  
-  SVal V = state->getSVal(RetE);
+  SVal V = state->getSVal(RetE, C.getLocationContext());
   const MemRegion *R = V.getAsRegion();
 
   const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R);

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp Fri Jan 20 10:14:22 2012
@@ -38,7 +38,7 @@
   if (!RetE)
     return;
   
-  if (!C.getState()->getSVal(RetE).isUndef())
+  if (!C.getState()->getSVal(RetE, C.getLocationContext()).isUndef())
     return;
   
   ExplodedNode *N = C.generateSink();

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp Fri Jan 20 10:14:22 2012
@@ -119,7 +119,7 @@
   if (!RetE)
     return;
  
-  SVal V = C.getState()->getSVal(RetE);
+  SVal V = C.getState()->getSVal(RetE, C.getLocationContext());
   const MemRegion *R = V.getAsRegion();
 
   if (!R || !R->hasStackStorage())

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/StreamChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/StreamChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/StreamChecker.cpp Fri Jan 20 10:14:22 2012
@@ -223,7 +223,7 @@
   SValBuilder &svalBuilder = C.getSValBuilder();
   DefinedSVal RetVal =
     cast<DefinedSVal>(svalBuilder.getConjuredSymbolVal(0, CE, Count));
-  state = state->BindExpr(CE, RetVal);
+  state = state->BindExpr(CE, C.getLocationContext(), RetVal);
   
   ConstraintManager &CM = C.getConstraintManager();
   // Bifurcate the state into two: one with a valid FILE* pointer, the other
@@ -251,22 +251,25 @@
 
 void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!(state = CheckNullStream(state->getSVal(CE->getArg(0)), state, C)))
+  if (!(state = CheckNullStream(state->getSVal(CE->getArg(0),
+                                               C.getLocationContext()), state, C)))
     return;
   // Check the legality of the 'whence' argument of 'fseek'.
-  SVal Whence = state->getSVal(CE->getArg(2));
+  SVal Whence = state->getSVal(CE->getArg(2), C.getLocationContext());
   const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Whence);
 
   if (!CI)
@@ -289,49 +292,57 @@
 
 void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
@@ -361,7 +372,8 @@
 const ProgramState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
                                                const ProgramState *state,
                                                CheckerContext &C) const {
-  SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol();
+  SymbolRef Sym =
+    state->getSVal(CE->getArg(0), C.getLocationContext()).getAsSymbol();
   if (!Sym)
     return state;
   
@@ -442,7 +454,7 @@
     return;
   
   const ProgramState *state = C.getState();
-  SymbolRef Sym = state->getSVal(RetE).getAsSymbol();
+  SymbolRef Sym = state->getSVal(RetE, C.getLocationContext()).getAsSymbol();
   
   if (!Sym)
     return;

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp Fri Jan 20 10:14:22 2012
@@ -47,7 +47,7 @@
   if (!State)
     return;
 
-  if (State->isTainted(E)) {
+  if (State->isTainted(E, C.getLocationContext())) {
     if (ExplodedNode *N = C.addTransition()) {
       initBugType();
       BugReport *report = new BugReport(*BT, "tainted",N);

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp Fri Jan 20 10:14:22 2012
@@ -28,8 +28,10 @@
 
   struct FindUndefExpr {
     const ProgramState *St;
+    const LocationContext *LCtx;
 
-    FindUndefExpr(const ProgramState *S) : St(S) {}
+    FindUndefExpr(const ProgramState *S, const LocationContext *L) 
+      : St(S), LCtx(L) {}
 
     const Expr *FindExpr(const Expr *Ex) {
       if (!MatchesCriteria(Ex))
@@ -45,7 +47,9 @@
       return Ex;
     }
 
-    bool MatchesCriteria(const Expr *Ex) { return St->getSVal(Ex).isUndef(); }
+    bool MatchesCriteria(const Expr *Ex) { 
+      return St->getSVal(Ex, LCtx).isUndef();
+    }
   };
 
 public:
@@ -56,7 +60,7 @@
 
 void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
                                               CheckerContext &Ctx) const {
-  SVal X = Ctx.getState()->getSVal(Condition);
+  SVal X = Ctx.getState()->getSVal(Condition, Ctx.getLocationContext());
   if (X.isUndef()) {
     // Generate a sink node, which implicitly marks both outgoing branches as
     // infeasible.
@@ -90,7 +94,7 @@
         if (PS->getStmt() == Ex)
           St = PrevN->getState();
 
-      FindUndefExpr FindIt(St);
+      FindUndefExpr FindIt(St, Ctx.getLocationContext());
       Ex = FindIt.FindExpr(Ex);
 
       // Emit the bug report.

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp Fri Jan 20 10:14:22 2012
@@ -57,7 +57,8 @@
 
   const ProgramState *state = C.getState();
   const BlockDataRegion *R =
-    cast<BlockDataRegion>(state->getSVal(BE).getAsRegion());
+    cast<BlockDataRegion>(state->getSVal(BE,
+                                         C.getLocationContext()).getAsRegion());
 
   BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
                                             E = R->referenced_vars_end();

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp Fri Jan 20 10:14:22 2012
@@ -36,7 +36,8 @@
 void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
                                        CheckerContext &C) const {
   const ProgramState *state = C.getState();
-  if (state->getSVal(B).isUndef()) {
+  const LocationContext *LCtx = C.getLocationContext();
+  if (state->getSVal(B, LCtx).isUndef()) {
     // Generate an error node.
     ExplodedNode *N = C.generateSink();
     if (!N)
@@ -50,11 +51,11 @@
     const Expr *Ex = NULL;
     bool isLeft = true;
     
-    if (state->getSVal(B->getLHS()).isUndef()) {
+    if (state->getSVal(B->getLHS(), LCtx).isUndef()) {
       Ex = B->getLHS()->IgnoreParenCasts();
       isLeft = true;
     }
-    else if (state->getSVal(B->getRHS()).isUndef()) {
+    else if (state->getSVal(B->getRHS(), LCtx).isUndef()) {
       Ex = B->getRHS()->IgnoreParenCasts();
       isLeft = false;
     }

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp Fri Jan 20 10:14:22 2012
@@ -34,7 +34,7 @@
 void 
 UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
                                              CheckerContext &C) const {
-  if (C.getState()->getSVal(A->getIdx()).isUndef()) {
+  if (C.getState()->getSVal(A->getIdx(), C.getLocationContext()).isUndef()) {
     if (ExplodedNode *N = C.generateSink()) {
       if (!BT)
         BT.reset(new BuiltinBug("Array subscript is undefined"));

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp Fri Jan 20 10:14:22 2012
@@ -55,7 +55,7 @@
     if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
       if (B->isCompoundAssignmentOp()) {
         const ProgramState *state = C.getState();
-        if (state->getSVal(B->getLHS()).isUndef()) {
+        if (state->getSVal(B->getLHS(), C.getLocationContext()).isUndef()) {
           str = "The left expression of the compound assignment is an "
                 "uninitialized value. The computed value will also be garbage";
           ex = B->getLHS();

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp Fri Jan 20 10:14:22 2012
@@ -36,10 +36,24 @@
 
   void CheckOpen(CheckerContext &C, const CallExpr *CE) const;
   void CheckPthreadOnce(CheckerContext &C, const CallExpr *CE) const;
+  void CheckCallocZero(CheckerContext &C, const CallExpr *CE) const;
   void CheckMallocZero(CheckerContext &C, const CallExpr *CE) const;
+  void CheckReallocZero(CheckerContext &C, const CallExpr *CE) const;
+  void CheckAllocaZero(CheckerContext &C, const CallExpr *CE) const;
+  void CheckVallocZero(CheckerContext &C, const CallExpr *CE) const;
 
   typedef void (UnixAPIChecker::*SubChecker)(CheckerContext &,
                                              const CallExpr *) const;
+private:
+  bool ReportZeroByteAllocation(CheckerContext &C,
+                                const ProgramState *falseState,
+                                const Expr *arg,
+                                const char *fn_name) const;
+  void BasicAllocationCheck(CheckerContext &C,
+                            const CallExpr *CE,
+                            const unsigned numArgs,
+                            const unsigned sizeArg,
+                            const char *fn) const;
 };
 } //end anonymous namespace
 
@@ -84,7 +98,7 @@
 
   // Now check if oflags has O_CREAT set.
   const Expr *oflagsEx = CE->getArg(1);
-  const SVal V = state->getSVal(oflagsEx);
+  const SVal V = state->getSVal(oflagsEx, C.getLocationContext());
   if (!isa<NonLoc>(V)) {
     // The case where 'V' can be a location can only be due to a bad header,
     // so in this case bail out.
@@ -142,7 +156,8 @@
   // Check if the first argument is stack allocated.  If so, issue a warning
   // because that's likely to be bad news.
   const ProgramState *state = C.getState();
-  const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion();
+  const MemRegion *R =
+    state->getSVal(CE->getArg(0), C.getLocationContext()).getAsRegion();
   if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
     return;
 
@@ -170,60 +185,143 @@
 }
 
 //===----------------------------------------------------------------------===//
-// "malloc" with allocation size 0
+// "calloc", "malloc", "realloc", "alloca" and "valloc" with allocation size 0
 //===----------------------------------------------------------------------===//
+// FIXME: Eventually these should be rolled into the MallocChecker, but right now
+// they're more basic and valuable for widespread use.
 
-// FIXME: Eventually this should be rolled into the MallocChecker, but this
-// check is more basic and is valuable for widespread use.
-void UnixAPIChecker::CheckMallocZero(CheckerContext &C,
-                                     const CallExpr *CE) const {
+// Returns true if we try to do a zero byte allocation, false otherwise.
+// Fills in trueState and falseState.
+static bool IsZeroByteAllocation(const ProgramState *state,
+                                const SVal argVal,
+                                const ProgramState **trueState,
+                                const ProgramState **falseState) {
+  llvm::tie(*trueState, *falseState) =
+    state->assume(cast<DefinedSVal>(argVal));
+  
+  return (*falseState && !*trueState);
+}
+
+// Generates an error report, indicating that the function whose name is given
+// will perform a zero byte allocation.
+// Returns false if an error occured, true otherwise.
+bool UnixAPIChecker::ReportZeroByteAllocation(CheckerContext &C,
+                                              const ProgramState *falseState,
+                                              const Expr *arg,
+                                              const char *fn_name) const {
+  ExplodedNode *N = C.generateSink(falseState);
+  if (!N)
+    return false;
+
+  LazyInitialize(BT_mallocZero,
+    "Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)");
+
+  llvm::SmallString<256> S;
+  llvm::raw_svector_ostream os(S);    
+  os << "Call to '" << fn_name << "' has an allocation size of 0 bytes";
+  BugReport *report = new BugReport(*BT_mallocZero, os.str(), N);
+
+  report->addRange(arg->getSourceRange());
+  report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, arg));
+  C.EmitReport(report);
+
+  return true;
+}
 
-  // Sanity check that malloc takes one argument.
-  if (CE->getNumArgs() != 1)
+// Does a basic check for 0-sized allocations suitable for most of the below
+// functions (modulo "calloc")
+void UnixAPIChecker::BasicAllocationCheck(CheckerContext &C,
+                                          const CallExpr *CE,
+                                          const unsigned numArgs,
+                                          const unsigned sizeArg,
+                                          const char *fn) const {
+  // Sanity check for the correct number of arguments
+  if (CE->getNumArgs() != numArgs)
     return;
 
   // Check if the allocation size is 0.
   const ProgramState *state = C.getState();
-  SVal argVal = state->getSVal(CE->getArg(0));
+  const ProgramState *trueState = NULL, *falseState = NULL;
+  const Expr *arg = CE->getArg(sizeArg);
+  SVal argVal = state->getSVal(arg, C.getLocationContext());
 
   if (argVal.isUnknownOrUndef())
     return;
-  
-  const ProgramState *trueState, *falseState;
-  llvm::tie(trueState, falseState) = state->assume(cast<DefinedSVal>(argVal));
-  
+
   // Is the value perfectly constrained to zero?
-  if (falseState && !trueState) {
-    ExplodedNode *N = C.generateSink(falseState);
-    if (!N)
-      return;
-    
-    // FIXME: Add reference to CERT advisory, and/or C99 standard in bug
-    // output.
+  if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
+    (void) ReportZeroByteAllocation(C, falseState, arg, fn); 
+    return;
+  }
+  // Assume the the value is non-zero going forward.
+  assert(trueState);
+  if (trueState != state)
+    C.addTransition(trueState);                           
+}
 
-    LazyInitialize(BT_mallocZero, "Undefined allocation of 0 bytes");
-    
-    BugReport *report =
-      new BugReport(*BT_mallocZero, "Call to 'malloc' has an allocation"
-                                            " size of 0 bytes", N);
-    report->addRange(CE->getArg(0)->getSourceRange());
-    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
-                                                                CE->getArg(0)));
-    C.EmitReport(report);
+void UnixAPIChecker::CheckCallocZero(CheckerContext &C,
+                                     const CallExpr *CE) const {
+  unsigned int nArgs = CE->getNumArgs();
+  if (nArgs != 2)
     return;
+
+  const ProgramState *state = C.getState();
+  const ProgramState *trueState = NULL, *falseState = NULL;
+
+  unsigned int i;
+  for (i = 0; i < nArgs; i++) {
+    const Expr *arg = CE->getArg(i);
+    SVal argVal = state->getSVal(arg, C.getLocationContext());
+    if (argVal.isUnknownOrUndef()) {
+      if (i == 0)
+        continue;
+      else
+        return;
+    }
+
+    if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
+      if (ReportZeroByteAllocation(C, falseState, arg, "calloc"))
+        return;
+      else if (i == 0)
+        continue;
+      else
+        return;
+    }
   }
+
   // Assume the the value is non-zero going forward.
   assert(trueState);
-  if (trueState != state) {
+  if (trueState != state)
     C.addTransition(trueState);
-  }
 }
-  
+
+void UnixAPIChecker::CheckMallocZero(CheckerContext &C,
+                                     const CallExpr *CE) const {
+  BasicAllocationCheck(C, CE, 1, 0, "malloc");
+}
+
+void UnixAPIChecker::CheckReallocZero(CheckerContext &C,
+                                      const CallExpr *CE) const {
+  BasicAllocationCheck(C, CE, 2, 1, "realloc");
+}
+
+void UnixAPIChecker::CheckAllocaZero(CheckerContext &C,
+                                     const CallExpr *CE) const {
+  BasicAllocationCheck(C, CE, 1, 0, "alloca");
+}
+
+void UnixAPIChecker::CheckVallocZero(CheckerContext &C,
+                                     const CallExpr *CE) const {
+  BasicAllocationCheck(C, CE, 1, 0, "valloc");
+}
+
+
 //===----------------------------------------------------------------------===//
 // Central dispatch function.
 //===----------------------------------------------------------------------===//
 
-void UnixAPIChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
+void UnixAPIChecker::checkPreStmt(const CallExpr *CE,
+                                  CheckerContext &C) const {
   StringRef FName = C.getCalleeName(CE);
   if (FName.empty())
     return;
@@ -232,7 +330,11 @@
     llvm::StringSwitch<SubChecker>(FName)
       .Case("open", &UnixAPIChecker::CheckOpen)
       .Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
+      .Case("calloc", &UnixAPIChecker::CheckCallocZero)
       .Case("malloc", &UnixAPIChecker::CheckMallocZero)
+      .Case("realloc", &UnixAPIChecker::CheckReallocZero)
+      .Cases("alloca", "__builtin_alloca", &UnixAPIChecker::CheckAllocaZero)
+      .Case("valloc", &UnixAPIChecker::CheckVallocZero)
       .Default(NULL);
 
   if (SC)

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp Fri Jan 20 10:14:22 2012
@@ -50,7 +50,7 @@
   // FIXME: Handle multi-dimensional VLAs.
   const Expr *SE = VLA->getSizeExpr();
   const ProgramState *state = C.getState();
-  SVal sizeV = state->getSVal(SE);
+  SVal sizeV = state->getSVal(SE, C.getLocationContext());
 
   if (sizeV.isUndef()) {
     // Generate an error node.

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/AnalysisManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/AnalysisManager.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/AnalysisManager.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/AnalysisManager.cpp Fri Jan 20 10:14:22 2012
@@ -14,6 +14,8 @@
 using namespace clang;
 using namespace ento;
 
+void AnalysisManager::anchor() { }
+
 AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
                                  const LangOptions &lang,
                                  PathDiagnosticConsumer *pd,

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/BugReporter.cpp Fri Jan 20 10:14:22 2012
@@ -34,6 +34,8 @@
 
 BugReporterVisitor::~BugReporterVisitor() {}
 
+void BugReporterContext::anchor() {}
+
 //===----------------------------------------------------------------------===//
 // Helper routines for walking the ExplodedGraph and fetching statements.
 //===----------------------------------------------------------------------===//
@@ -341,7 +343,7 @@
     if (!DR)
       continue;
 
-    SVal Y = N->getState()->getSVal(DR);
+    SVal Y = N->getState()->getSVal(DR, N->getLocationContext());
 
     if (X != Y)
       continue;
@@ -1204,10 +1206,14 @@
 
 void BugType::FlushReports(BugReporter &BR) {}
 
+void BuiltinBug::anchor() {}
+
 //===----------------------------------------------------------------------===//
 // Methods for BugReport and subclasses.
 //===----------------------------------------------------------------------===//
 
+void BugReport::NodeResolver::anchor() {}
+
 void BugReport::addVisitor(BugReporterVisitor* visitor) {
   if (!visitor)
     return;

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Fri Jan 20 10:14:22 2012
@@ -339,7 +339,7 @@
     }
   }
 
-  SVal V = state->getSValAsScalarOrLoc(S);
+  SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
 
   // Uncomment this to find cases where we aren't properly getting the
   // base value that was dereferenced.
@@ -389,7 +389,7 @@
   if (!Receiver)
     return 0;
   const ProgramState *state = N->getState();
-  const SVal &V = state->getSVal(Receiver);
+  const SVal &V = state->getSVal(Receiver, N->getLocationContext());
   const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
   if (!DV)
     return 0;
@@ -428,7 +428,7 @@
         StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
 
         // What did we load?
-        SVal V = state->getSVal(S);
+        SVal V = state->getSVal(S, N->getLocationContext());
 
         if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
           // Register a new visitor with the BugReport.
@@ -604,18 +604,26 @@
     shouldInvert = !isVarLHS && isVarRHS;    
   }
   
+  BinaryOperator::Opcode Op = BExpr->getOpcode();
+
+  if (BinaryOperator::isAssignmentOp(Op)) {
+    // For assignment operators, all that we care about is that the LHS
+    // evaluates to "true" or "false".
+    return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue,
+                                  BRC, LC);
+  }
+
+  // For non-assignment operations, we require that we can understand
+  // both the LHS and RHS.
   if (LhsString.empty() || RhsString.empty())
     return 0;
-
-  // Should we invert the strings if the LHS is not a variable name?
   
+  // Should we invert the strings if the LHS is not a variable name?
   llvm::SmallString<256> buf;
   llvm::raw_svector_ostream Out(buf);
   Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is ";
 
   // Do we need to invert the opcode?
-  BinaryOperator::Opcode Op = BExpr->getOpcode();
-    
   if (shouldInvert)
     switch (Op) {
       default: break;
@@ -637,7 +645,7 @@
         return 0;
     }
   
-  switch (BExpr->getOpcode()) {
+  switch (Op) {
     case BO_EQ:
       Out << "equal to ";
       break;
@@ -654,6 +662,33 @@
   PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LC);
   return new PathDiagnosticEventPiece(Loc, Out.str());
 }
+
+PathDiagnosticPiece *
+ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
+                                           const Expr *CondVarExpr,
+                                           const bool tookTrue,
+                                           BugReporterContext &BRC,
+                                           const LocationContext *LC) {
+  llvm::SmallString<256> buf;
+  llvm::raw_svector_ostream Out(buf);
+  Out << "Assuming " << LhsString << " is ";
+  
+  QualType Ty = CondVarExpr->getType();
+
+  if (Ty->isPointerType())
+    Out << (tookTrue ? "not null" : "null");
+  else if (Ty->isObjCObjectPointerType())
+    Out << (tookTrue ? "not nil" : "nil");
+  else if (Ty->isBooleanType())
+    Out << (tookTrue ? "true" : "false");
+  else if (Ty->isIntegerType())
+    Out << (tookTrue ? "non-zero" : "zero");
+  else
+    return 0;
+
+  PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LC);
+  return new PathDiagnosticEventPiece(Loc, Out.str());
+}
   
 PathDiagnosticPiece *
 ConditionBRVisitor::VisitTrueTest(const Expr *Cond,

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/CMakeLists.txt?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/CMakeLists.txt (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/CMakeLists.txt Fri Jan 20 10:14:22 2012
@@ -36,6 +36,7 @@
   SimpleConstraintManager.cpp
   SimpleSValBuilder.cpp
   Store.cpp
+  SubEngine.cpp
   SymbolManager.cpp
   TextPathDiagnostics.cpp
   )

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/Checker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/Checker.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/Checker.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/Checker.cpp Fri Jan 20 10:14:22 2012
@@ -20,3 +20,11 @@
   // FIXME: We want to return the package + name of the checker here.
   return "A Checker";  
 }
+
+void Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
+             check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
+             check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
+             check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
+             check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
+             check::_VoidCheck, check::_VoidCheck, check::_VoidCheck
+             >::anchor() { }

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/CheckerContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/CheckerContext.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/CheckerContext.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/CheckerContext.cpp Fri Jan 20 10:14:22 2012
@@ -13,22 +13,56 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Lex/Lexer.h"
+
 using namespace clang;
 using namespace ento;
 
 const FunctionDecl *CheckerContext::getCalleeDecl(const CallExpr *CE) const {
   const ProgramState *State = getState();
   const Expr *Callee = CE->getCallee();
-  SVal L = State->getSVal(Callee);
+  SVal L = State->getSVal(Callee, Pred->getLocationContext());
   return L.getAsFunctionDecl();
 }
 
-StringRef CheckerContext::getCalleeName(const CallExpr *CE) const {
-  const FunctionDecl *funDecl = getCalleeDecl(CE);
-  if (!funDecl)
+StringRef CheckerContext::getCalleeName(const FunctionDecl *FunDecl) const {
+  if (!FunDecl)
     return StringRef();
-  IdentifierInfo *funI = funDecl->getIdentifier();
+  IdentifierInfo *funI = FunDecl->getIdentifier();
   if (!funI)
     return StringRef();
   return funI->getName();
 }
+
+
+bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD,
+                                        StringRef Name){
+  // To avoid false positives (Ex: finding user defined functions with
+  // similar names), only perform fuzzy name matching when it's a builtin.
+  // Using a string compare is slow, we might want to switch on BuiltinID here.
+  unsigned BId = FD->getBuiltinID();
+  if (BId != 0) {
+    ASTContext &Context = getASTContext();
+    StringRef BName = Context.BuiltinInfo.GetName(BId);
+    if (StringRef(BName).find(Name) != StringRef::npos)
+      return true;
+  }
+
+  if (FD->isExternC() && FD->getIdentifier()->getName().equals(Name))
+    return true;
+
+  return false;
+}
+
+StringRef CheckerContext::getMacroNameOrSpelling(SourceLocation &Loc) {
+  if (!Loc.isMacroID()) {
+    SmallVector<char, 16> buf;
+    return Lexer::getSpelling(Loc, buf, getSourceManager(), getLangOptions());
+  } else {
+    return Lexer::getImmediateMacroName(Loc, getSourceManager(),
+                                             getLangOptions());
+  }
+  return StringRef();
+}
+

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/CoreEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/CoreEngine.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/CoreEngine.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/CoreEngine.cpp Fri Jan 20 10:14:22 2012
@@ -215,12 +215,11 @@
         break;
 
       case ProgramPoint::CallEnterKind:
-        HandleCallEnter(cast<CallEnter>(Node->getLocation()), WU.getBlock(), 
-                        WU.getIndex(), Node);
+        SubEng.processCallEnter(cast<CallEnter>(Node->getLocation()), Node);
         break;
 
       case ProgramPoint::CallExitKind:
-        HandleCallExit(cast<CallExit>(Node->getLocation()), Node);
+        SubEng.processCallExit(Node);
         break;
 
       default:
@@ -246,18 +245,6 @@
   }
 }
 
-void CoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
-                                   unsigned Index, ExplodedNode *Pred) {
-  CallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(), 
-                                 L.getCalleeContext(), Block, Index);
-  SubEng.processCallEnter(Builder);
-}
-
-void CoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) {
-  CallExitNodeBuilder Builder(*this, Pred);
-  SubEng.processCallExit(Builder);
-}
-
 void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
 
   const CFGBlock *Blk = L.getDst();
@@ -537,6 +524,8 @@
 }
 
 
+void NodeBuilder::anchor() { }
+
 ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
                                             const ProgramState *State,
                                             ExplodedNode *FromN,
@@ -556,6 +545,8 @@
   return N;
 }
 
+void NodeBuilderWithSinks::anchor() { }
+
 StmtNodeBuilder::~StmtNodeBuilder() {
   if (EnclosingBldr)
     for (ExplodedNodeSet::iterator I = Frontier.begin(),
@@ -563,6 +554,8 @@
       EnclosingBldr->addNodes(*I);
 }
 
+void BranchNodeBuilder::anchor() { }
+
 ExplodedNode *BranchNodeBuilder::generateNode(const ProgramState *State,
                                               bool branch,
                                               ExplodedNode *NodePred) {
@@ -639,80 +632,3 @@
 
   return Succ;
 }
-
-void CallEnterNodeBuilder::generateNode(const ProgramState *state) {
-  // Check if the callee is in the same translation unit.
-  if (CalleeCtx->getTranslationUnit() != 
-      Pred->getLocationContext()->getTranslationUnit()) {
-    // Create a new engine. We must be careful that the new engine should not
-    // reference data structures owned by the old engine.
-
-    AnalysisManager &OldMgr = Eng.SubEng.getAnalysisManager();
-    
-    // Get the callee's translation unit.
-    idx::TranslationUnit *TU = CalleeCtx->getTranslationUnit();
-
-    // Create a new AnalysisManager with components of the callee's
-    // TranslationUnit.
-    // The Diagnostic is  actually shared when we create ASTUnits from AST files.
-    AnalysisManager AMgr(TU->getASTContext(), TU->getDiagnostic(), OldMgr);
-
-    // Create the new engine.
-    // FIXME: This cast isn't really safe.
-    bool GCEnabled = static_cast<ExprEngine&>(Eng.SubEng).isObjCGCEnabled();
-    ExprEngine NewEng(AMgr, GCEnabled);
-
-    // Create the new LocationContext.
-    AnalysisDeclContext *NewAnaCtx =
-      AMgr.getAnalysisDeclContext(CalleeCtx->getDecl(), 
-                              CalleeCtx->getTranslationUnit());
-
-    const StackFrameContext *OldLocCtx = CalleeCtx;
-    const StackFrameContext *NewLocCtx =
-      NewAnaCtx->getStackFrame(OldLocCtx->getParent(),
-                               OldLocCtx->getCallSite(),
-                               OldLocCtx->getCallSiteBlock(), 
-                               OldLocCtx->getIndex());
-
-    // Now create an initial state for the new engine.
-    const ProgramState *NewState =
-      NewEng.getStateManager().MarshalState(state, NewLocCtx);
-    ExplodedNodeSet ReturnNodes;
-    NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(), 
-                                           NewState, ReturnNodes);
-    return;
-  }
-
-  // Get the callee entry block.
-  const CFGBlock *Entry = &(CalleeCtx->getCFG()->getEntry());
-  assert(Entry->empty());
-  assert(Entry->succ_size() == 1);
-
-  // Get the solitary successor.
-  const CFGBlock *SuccB = *(Entry->succ_begin());
-
-  // Construct an edge representing the starting location in the callee.
-  BlockEdge Loc(Entry, SuccB, CalleeCtx);
-
-  bool isNew;
-  ExplodedNode *Node = Eng.G->getNode(Loc, state, false, &isNew);
-  Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
-
-  if (isNew)
-    Eng.WList->enqueue(Node);
-}
-
-void CallExitNodeBuilder::generateNode(const ProgramState *state) {
-  // Get the callee's location context.
-  const StackFrameContext *LocCtx 
-                         = cast<StackFrameContext>(Pred->getLocationContext());
-  // When exiting an implicit automatic obj dtor call, the callsite is the Stmt
-  // that triggers the dtor.
-  PostStmt Loc(LocCtx->getCallSite(), LocCtx->getParent());
-  bool isNew;
-  ExplodedNode *Node = Eng.G->getNode(Loc, state, false, &isNew);
-  Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
-  if (isNew)
-    Eng.WList->enqueue(Node, LocCtx->getCallSiteBlock(),
-                       LocCtx->getIndex() + 1);
-}

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/Environment.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/Environment.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/Environment.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/Environment.cpp Fri Jan 20 10:14:22 2012
@@ -19,7 +19,7 @@
 using namespace clang;
 using namespace ento;
 
-SVal Environment::lookupExpr(const Stmt *E) const {
+SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
   const SVal* X = ExprBindings.lookup(E);
   if (X) {
     SVal V = *X;
@@ -28,17 +28,21 @@
   return UnknownVal();
 }
 
-SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder,
-			  bool useOnlyDirectBindings) const {
+SVal Environment::getSVal(const EnvironmentEntry &Entry,
+                          SValBuilder& svalBuilder,
+                          bool useOnlyDirectBindings) const {
 
   if (useOnlyDirectBindings) {
     // This branch is rarely taken, but can be exercised by
     // checkers that explicitly bind values to arbitrary
     // expressions.  It is crucial that we do not ignore any
     // expression here, and do a direct lookup.
-    return lookupExpr(E);
+    return lookupExpr(Entry);
   }
 
+  const Stmt *E = Entry.getStmt();
+  const LocationContext *LCtx = Entry.getLocationContext();
+  
   for (;;) {
     if (const Expr *Ex = dyn_cast<Expr>(E))
       E = Ex->IgnoreParens();
@@ -61,7 +65,7 @@
         return svalBuilder.makeIntVal(C->getValue(), C->getType());
       }
       case Stmt::CXXBoolLiteralExprClass: {
-        const SVal *X = ExprBindings.lookup(E);
+        const SVal *X = ExprBindings.lookup(EnvironmentEntry(E, LCtx));
         if (X) 
           return *X;
         else 
@@ -69,7 +73,7 @@
       }
       case Stmt::IntegerLiteralClass: {
         // In C++, this expression may have been bound to a temporary object.
-        SVal const *X = ExprBindings.lookup(E);
+        SVal const *X = ExprBindings.lookup(EnvironmentEntry(E, LCtx));
         if (X)
           return *X;
         else
@@ -86,6 +90,14 @@
         continue;
       case Stmt::ObjCPropertyRefExprClass:
         return loc::ObjCPropRef(cast<ObjCPropertyRefExpr>(E));
+      case Stmt::ReturnStmtClass: {
+        const ReturnStmt *RS = cast<ReturnStmt>(E);
+        if (const Expr *RE = RS->getRetValue()) {
+          E = RE;
+          continue;
+        }
+        return UndefinedVal();        
+      }
         
       // Handle all other Stmt* using a lookup.
       default:
@@ -93,32 +105,33 @@
     };
     break;
   }
-  return lookupExpr(E);
+  return lookupExpr(EnvironmentEntry(E, LCtx));
 }
 
-Environment EnvironmentManager::bindExpr(Environment Env, const Stmt *S,
-                                         SVal V, bool Invalidate) {
-  assert(S);
-
+Environment EnvironmentManager::bindExpr(Environment Env,
+                                         const EnvironmentEntry &E,
+                                         SVal V,
+                                         bool Invalidate) {
   if (V.isUnknown()) {
     if (Invalidate)
-      return Environment(F.remove(Env.ExprBindings, S));
+      return Environment(F.remove(Env.ExprBindings, E));
     else
       return Env;
   }
-
-  return Environment(F.add(Env.ExprBindings, S, V));
+  return Environment(F.add(Env.ExprBindings, E, V));
 }
 
-static inline const Stmt *MakeLocation(const Stmt *S) {
-  return (const Stmt*) (((uintptr_t) S) | 0x1);
+static inline EnvironmentEntry MakeLocation(const EnvironmentEntry &E) {
+  const Stmt *S = E.getStmt();
+  S = (const Stmt*) (((uintptr_t) S) | 0x1);
+  return EnvironmentEntry(S, E.getLocationContext());
 }
 
 Environment EnvironmentManager::bindExprAndLocation(Environment Env,
-                                                    const Stmt *S,
+                                                    const EnvironmentEntry &E,
                                                     SVal location, SVal V) {
-  return Environment(F.add(F.add(Env.ExprBindings, MakeLocation(S), location),
-                           S, V));
+  return Environment(F.add(F.add(Env.ExprBindings, MakeLocation(E), location),
+                           E, V));
 }
 
 namespace {
@@ -130,10 +143,11 @@
 };
 } // end anonymous namespace
 
-// In addition to mapping from Stmt * - > SVals in the Environment, we also
-// maintain a mapping from Stmt * -> SVals (locations) that were used during
-// a load and store.
-static inline bool IsLocation(const Stmt *S) {
+// In addition to mapping from EnvironmentEntry - > SVals in the Environment,
+// we also maintain a mapping from EnvironmentEntry -> SVals (locations)
+// that were used during a load and store.
+static inline bool IsLocation(const EnvironmentEntry &E) {
+  const Stmt *S = E.getStmt();
   return (bool) (((uintptr_t) S) & 0x1);
 }
 
@@ -154,12 +168,12 @@
   // outnumber block-level expression bindings).
   Environment NewEnv = getInitialEnvironment();
   
-  SmallVector<std::pair<const Stmt*, SVal>, 10> deferredLocations;
+  SmallVector<std::pair<EnvironmentEntry, SVal>, 10> deferredLocations;
 
   MarkLiveCallback CB(SymReaper);
   ScanReachableSymbols RSScaner(ST, CB);
 
-  llvm::ImmutableMapRef<const Stmt*,SVal>
+  llvm::ImmutableMapRef<EnvironmentEntry,SVal>
     EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(),
              F.getTreeFactory());
 
@@ -167,7 +181,7 @@
   for (Environment::iterator I = Env.begin(), E = Env.end();
        I != E; ++I) {
 
-    const Stmt *BlkExpr = I.getKey();
+    const EnvironmentEntry &BlkExpr = I.getKey();
     // For recorded locations (used when evaluating loads and stores), we
     // consider them live only when their associated normal expression is
     // also live.
@@ -179,7 +193,7 @@
     }
     const SVal &X = I.getData();
 
-    if (SymReaper.isLive(BlkExpr)) {
+    if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) {
       // Copy the binding to the new map.
       EBMapRef = EBMapRef.add(BlkExpr, X);
 
@@ -204,13 +218,58 @@
   
   // Go through he deferred locations and add them to the new environment if
   // the correspond Stmt* is in the map as well.
-  for (SmallVectorImpl<std::pair<const Stmt*, SVal> >::iterator
+  for (SmallVectorImpl<std::pair<EnvironmentEntry, SVal> >::iterator
       I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) {
-    const Stmt *S = (Stmt*) (((uintptr_t) I->first) & (uintptr_t) ~0x1);
-    if (EBMapRef.lookup(S))
-      EBMapRef = EBMapRef.add(I->first, I->second);
+    const EnvironmentEntry &En = I->first;
+    const Stmt *S = (Stmt*) (((uintptr_t) En.getStmt()) & (uintptr_t) ~0x1);
+    if (EBMapRef.lookup(EnvironmentEntry(S, En.getLocationContext())))
+      EBMapRef = EBMapRef.add(En, I->second);
   }
 
   NewEnv.ExprBindings = EBMapRef.asImmutableMap();
   return NewEnv;
 }
+
+void Environment::print(raw_ostream &Out, const char *NL,
+                        const char *Sep) const {
+  printAux(Out, false, NL, Sep);
+  printAux(Out, true, NL, Sep);
+}
+  
+void Environment::printAux(raw_ostream &Out, bool printLocations,
+                           const char *NL,
+                           const char *Sep) const{
+
+  bool isFirst = true;
+
+  for (Environment::iterator I = begin(), E = end(); I != E; ++I) {
+    const EnvironmentEntry &En = I.getKey();
+    if (IsLocation(En)) {
+      if (!printLocations)
+        continue;
+    }
+    else {
+      if (printLocations)
+        continue;
+    }
+    
+    if (isFirst) {
+      Out << NL << NL
+          << (printLocations ? "Load/Store locations:" : "Expressions:")
+          << NL;      
+      isFirst = false;
+    } else {
+      Out << NL;
+    }
+    
+    const Stmt *S = En.getStmt();
+    if (printLocations) {
+      S = (Stmt*) (((uintptr_t) S) & ((uintptr_t) ~0x1));
+    }
+    
+    Out << " (" << (void*) En.getLocationContext() << ',' << (void*) S << ") ";
+    LangOptions LO; // FIXME.
+    S->printPretty(Out, 0, PrintingPolicy(LO));
+    Out << " : " << I.getData();
+  }
+}

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/ExplodedGraph.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/ExplodedGraph.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/ExplodedGraph.cpp Fri Jan 20 10:14:22 2012
@@ -91,7 +91,8 @@
 
     // Condition 3.
     ProgramPoint progPoint = node->getLocation();
-    if (!isa<PostStmt>(progPoint))
+    if (!isa<PostStmt>(progPoint) ||
+        (isa<CallEnter>(progPoint) || isa<CallExit>(progPoint)))
       continue;
     // Condition 4.
     PostStmt ps = cast<PostStmt>(progPoint);
@@ -379,6 +380,8 @@
   return G;
 }
 
+void InterExplodedGraphMap::anchor() { }
+
 ExplodedNode*
 InterExplodedGraphMap::getMappedNode(const ExplodedNode *N) const {
   llvm::DenseMap<const ExplodedNode*, ExplodedNode*>::const_iterator I =

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Jan 20 10:14:22 2012
@@ -24,7 +24,6 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/SourceManager.h"
-#include "clang/Basic/SourceManager.h"
 #include "clang/Basic/PrettyStackTrace.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/ADT/ImmutableList.h"
@@ -158,27 +157,6 @@
   return state;
 }
 
-bool
-ExprEngine::doesInvalidateGlobals(const CallOrObjCMessage &callOrMessage) const
-{
-  if (callOrMessage.isFunctionCall() && !callOrMessage.isCXXCall()) {
-    SVal calleeV = callOrMessage.getFunctionCallee();
-    if (const FunctionTextRegion *codeR =
-          dyn_cast_or_null<FunctionTextRegion>(calleeV.getAsRegion())) {
-      
-      const FunctionDecl *fd = codeR->getDecl();
-      if (const IdentifierInfo *ii = fd->getIdentifier()) {
-        StringRef fname = ii->getName();
-        if (fname == "strlen")
-          return false;
-      }
-    }
-  }
-  
-  // The conservative answer: invalidates globals.
-  return true;
-}
-
 //===----------------------------------------------------------------------===//
 // Top-level transfer function logic (Dispatcher).
 //===----------------------------------------------------------------------===//
@@ -388,7 +366,7 @@
       const FieldDecl *FD = BMI->getAnyMember();
 
       SVal FieldLoc = state->getLValue(FD, thisVal);
-      SVal InitVal = state->getSVal(BMI->getInit());
+      SVal InitVal = state->getSVal(BMI->getInit(), Pred->getLocationContext());
       state = state->bindLoc(FieldLoc, InitVal);
 
       // Use a custom node building process.
@@ -556,7 +534,8 @@
     case Stmt::GNUNullExprClass: {
       // GNU __null is a pointer-width integer, not an actual pointer.
       const ProgramState *state = Pred->getState();
-      state = state->BindExpr(S, svalBuilder.makeIntValWithPtrWidth(0, false));
+      state = state->BindExpr(S, Pred->getLocationContext(),
+                              svalBuilder.makeIntValWithPtrWidth(0, false));
       Bldr.generateNode(S, Pred, state);
       break;
     }
@@ -575,7 +554,8 @@
       const ProgramState *state = Pred->getState();
       QualType ty = cast<ImplicitValueInitExpr>(S)->getType();
       SVal val = svalBuilder.makeZeroVal(ty);
-      Bldr.generateNode(S, Pred, state->BindExpr(S, val));
+      Bldr.generateNode(S, Pred, state->BindExpr(S, Pred->getLocationContext(),
+                                                 val));
       break;
     }
       
@@ -657,7 +637,9 @@
       else if (B->getOpcode() == BO_Comma) {
         const ProgramState *state = Pred->getState();
         Bldr.generateNode(B, Pred,
-                          state->BindExpr(B, state->getSVal(B->getRHS())));
+                          state->BindExpr(B, Pred->getLocationContext(),
+                                          state->getSVal(B->getRHS(),
+                                                  Pred->getLocationContext())));
         break;
       }
 
@@ -872,7 +854,9 @@
       if (Expr *LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
         const ProgramState *state = Pred->getState();
         Bldr.generateNode(SE, Pred,
-                          state->BindExpr(SE, state->getSVal(LastExpr)));
+                          state->BindExpr(SE, Pred->getLocationContext(),
+                                          state->getSVal(LastExpr,
+                                                  Pred->getLocationContext())));
       }
       break;
     }
@@ -880,7 +864,8 @@
     case Stmt::StringLiteralClass: {
       const ProgramState *state = Pred->getState();
       SVal V = state->getLValue(cast<StringLiteral>(S));
-      Bldr.generateNode(S, Pred, state->BindExpr(S, V));
+      Bldr.generateNode(S, Pred, state->BindExpr(S, Pred->getLocationContext(),
+                                                 V));
       return;
     }
 
@@ -903,11 +888,14 @@
       const ProgramState *state = Pred->getState();
       const PseudoObjectExpr *PE = cast<PseudoObjectExpr>(S);
       if (const Expr *Result = PE->getResultExpr()) { 
-        SVal V = state->getSVal(Result);
-        Bldr.generateNode(S, Pred, state->BindExpr(S, V));
+        SVal V = state->getSVal(Result, Pred->getLocationContext());
+        Bldr.generateNode(S, Pred,
+                          state->BindExpr(S, Pred->getLocationContext(), V));
       }
       else
-        Bldr.generateNode(S, Pred, state->BindExpr(S, UnknownVal()));
+        Bldr.generateNode(S, Pred,
+                          state->BindExpr(S, Pred->getLocationContext(),
+                                                   UnknownVal()));
 
       Bldr.addNodes(Dst);
       break;
@@ -932,8 +920,9 @@
 //===----------------------------------------------------------------------===//
 
 const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
-                                        const Stmt *Terminator,
-                                        bool branchTaken) {
+                                           const Stmt *Terminator,
+                                           const LocationContext *LCtx,
+                                           bool branchTaken) {
 
   switch (Terminator->getStmtClass()) {
     default:
@@ -956,7 +945,7 @@
                        (Op == BO_LOr && !branchTaken)
                        ? B->getRHS() : B->getLHS();
 
-      return state->BindExpr(B, UndefinedVal(Ex));
+      return state->BindExpr(B, LCtx, UndefinedVal(Ex));
     }
 
     case Stmt::BinaryConditionalOperatorClass:
@@ -974,7 +963,7 @@
       else
         Ex = C->getFalseExpr();
 
-      return state->BindExpr(C, UndefinedVal(Ex));
+      return state->BindExpr(C, LCtx, UndefinedVal(Ex));
     }
 
     case Stmt::ChooseExprClass: { // ?:
@@ -982,7 +971,7 @@
       const ChooseExpr *C = cast<ChooseExpr>(Terminator);
 
       const Expr *Ex = branchTaken ? C->getLHS() : C->getRHS();
-      return state->BindExpr(C, UndefinedVal(Ex));
+      return state->BindExpr(C, LCtx, UndefinedVal(Ex));
     }
   }
 }
@@ -995,6 +984,7 @@
 static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr,
                                 const ProgramState *state,
                                 const Stmt *Condition,
+                                const LocationContext *LCtx,
                                 ASTContext &Ctx) {
 
   const Expr *Ex = dyn_cast<Expr>(Condition);
@@ -1025,7 +1015,7 @@
   if (!bitsInit || !T->isIntegerType() || Ctx.getTypeSize(T) > bits)
     return UnknownVal();
 
-  return state->getSVal(Ex);
+  return state->getSVal(Ex, LCtx);
 }
 
 void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
@@ -1064,7 +1054,7 @@
       continue;
 
     const ProgramState *PrevState = Pred->getState();
-    SVal X = PrevState->getSVal(Condition);
+    SVal X = PrevState->getSVal(Condition, Pred->getLocationContext());
 
     if (X.isUnknownOrUndef()) {
       // Give it a chance to recover from unknown.
@@ -1076,6 +1066,7 @@
           // underlying value and use that instead.
           SVal recovered = RecoverCastedSymbol(getStateManager(),
                                                PrevState, Condition,
+                                               Pred->getLocationContext(),
                                                getContext());
 
           if (!recovered.isUnknown()) {
@@ -1084,10 +1075,15 @@
         }
       }
     }
+    
+    const LocationContext *LCtx = PredI->getLocationContext();
+
     // If the condition is still unknown, give up.
     if (X.isUnknownOrUndef()) {
-      builder.generateNode(MarkBranch(PrevState, Term, true), true, PredI);
-      builder.generateNode(MarkBranch(PrevState, Term, false), false, PredI);
+      builder.generateNode(MarkBranch(PrevState, Term, LCtx, true),
+                           true, PredI);
+      builder.generateNode(MarkBranch(PrevState, Term, LCtx, false),
+                           false, PredI);
       continue;
     }
 
@@ -1096,7 +1092,8 @@
     // Process the true branch.
     if (builder.isFeasible(true)) {
       if (const ProgramState *state = PrevState->assume(V, true))
-        builder.generateNode(MarkBranch(state, Term, true), true, PredI);
+        builder.generateNode(MarkBranch(state, Term, LCtx, true),
+                             true, PredI);
       else
         builder.markInfeasible(true);
     }
@@ -1104,7 +1101,8 @@
     // Process the false branch.
     if (builder.isFeasible(false)) {
       if (const ProgramState *state = PrevState->assume(V, false))
-        builder.generateNode(MarkBranch(state, Term, false), false, PredI);
+        builder.generateNode(MarkBranch(state, Term, LCtx, false),
+                             false, PredI);
       else
         builder.markInfeasible(false);
     }
@@ -1117,7 +1115,7 @@
 void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
 
   const ProgramState *state = builder.getState();
-  SVal V = state->getSVal(builder.getTarget());
+  SVal V = state->getSVal(builder.getTarget(), builder.getLocationContext());
 
   // Three possibilities:
   //
@@ -1171,7 +1169,7 @@
   typedef SwitchNodeBuilder::iterator iterator;
   const ProgramState *state = builder.getState();
   const Expr *CondE = builder.getCondition();
-  SVal  CondV_untested = state->getSVal(CondE);
+  SVal  CondV_untested = state->getSVal(CondE, builder.getLocationContext());
 
   if (CondV_untested.isUndef()) {
     //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
@@ -1278,6 +1276,7 @@
   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
 
   const ProgramState *state = Pred->getState();
+  const LocationContext *LCtx = Pred->getLocationContext();
 
   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
     assert(Ex->isLValue());
@@ -1292,19 +1291,19 @@
         V = UnknownVal();
     }
 
-    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, V), false, 0,
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), false, 0,
                       ProgramPoint::PostLValueKind);
     return;
   }
   if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) {
     assert(!Ex->isLValue());
     SVal V = svalBuilder.makeIntVal(ED->getInitVal());
-    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, V));
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V));
     return;
   }
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     SVal V = svalBuilder.getFunctionPointer(FD);
-    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, V), false, 0,
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), false, 0,
                       ProgramPoint::PostLValueKind);
     return;
   }
@@ -1328,11 +1327,13 @@
 
   for (ExplodedNodeSet::iterator it = checkerPreStmt.begin(),
                                  ei = checkerPreStmt.end(); it != ei; ++it) {
+    const LocationContext *LCtx = (*it)->getLocationContext();
     const ProgramState *state = (*it)->getState();
-    SVal V = state->getLValue(A->getType(), state->getSVal(Idx),
-                              state->getSVal(Base));
+    SVal V = state->getLValue(A->getType(),
+                              state->getSVal(Idx, LCtx),
+                              state->getSVal(Base, LCtx));
     assert(A->isLValue());
-    Bldr.generateNode(A, *it, state->BindExpr(A, V),
+    Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V),
                       false, 0, ProgramPoint::PostLValueKind);
   }
 }
@@ -1358,14 +1359,15 @@
 
   Expr *baseExpr = M->getBase()->IgnoreParens();
   const ProgramState *state = Pred->getState();
-  SVal baseExprVal = state->getSVal(baseExpr);
+  const LocationContext *LCtx = Pred->getLocationContext();
+  SVal baseExprVal = state->getSVal(baseExpr, Pred->getLocationContext());
   if (isa<nonloc::LazyCompoundVal>(baseExprVal) ||
       isa<nonloc::CompoundVal>(baseExprVal) ||
       // FIXME: This can originate by conjuring a symbol for an unknown
       // temporary struct object, see test/Analysis/fields.c:
       // (p = getit()).x
       isa<nonloc::SymbolVal>(baseExprVal)) {
-    Bldr.generateNode(M, Pred, state->BindExpr(M, UnknownVal()));
+    Bldr.generateNode(M, Pred, state->BindExpr(M, LCtx, UnknownVal()));
     return;
   }
 
@@ -1376,7 +1378,7 @@
   // For all other cases, compute an lvalue.    
   SVal L = state->getLValue(field, baseExprVal);
   if (M->isLValue())
-    Bldr.generateNode(M, Pred, state->BindExpr(M, L), false, 0,
+    Bldr.generateNode(M, Pred, state->BindExpr(M, LCtx, L), false, 0,
                       ProgramPoint::PostLValueKind);
   else {
     Bldr.takeNodes(Pred);
@@ -1487,7 +1489,7 @@
       // Perform the load from the referenced value.
       for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end() ; I!=E; ++I) {
         state = (*I)->getState();
-        location = state->getSVal(Ex);
+        location = state->getSVal(Ex, (*I)->getLocationContext());
         evalLoadCommon(Dst, Ex, *I, state, location, tag, LoadTy);
       }
       return;
@@ -1515,17 +1517,19 @@
   // Proceed with the load.
   for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
     state = (*NI)->getState();
+    const LocationContext *LCtx = (*NI)->getLocationContext();
 
     if (location.isUnknown()) {
       // This is important.  We must nuke the old binding.
-      Bldr.generateNode(Ex, *NI, state->BindExpr(Ex, UnknownVal()),
+      Bldr.generateNode(Ex, *NI, state->BindExpr(Ex, LCtx, UnknownVal()),
                         false, tag, ProgramPoint::PostLoadKind);
     }
     else {
       if (LoadTy.isNull())
         LoadTy = Ex->getType();
       SVal V = state->getSVal(cast<Loc>(location), LoadTy);
-      Bldr.generateNode(Ex, *NI, state->bindExprAndLocation(Ex, location, V),
+      Bldr.generateNode(Ex, *NI, state->bindExprAndLocation(Ex, LCtx,
+                                                            location, V),
                         false, tag, ProgramPoint::PostLoadKind);
     }
   }
@@ -1565,82 +1569,6 @@
   BldrTop.addNodes(Tmp);
 }
 
-bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, 
-                              ExplodedNode *Pred) {
-  return false;
-  
-  // Inlining isn't correct right now because we:
-  // (a) don't generate CallExit nodes.
-  // (b) we need a way to postpone doing post-visits of CallExprs until
-  // the CallExit.  This means we need CallExits for the non-inline
-  // cases as well.
-  
-#if 0
-  const ProgramState *state = Pred->getState();
-  const Expr *Callee = CE->getCallee();
-  SVal L = state->getSVal(Callee);
-  
-  const FunctionDecl *FD = L.getAsFunctionDecl();
-  if (!FD)
-    return false;
-
-  // Specially handle CXXMethods.
-  const CXXMethodDecl *methodDecl = 0;
-  
-  switch (CE->getStmtClass()) {
-    default: break;
-    case Stmt::CXXOperatorCallExprClass: {
-      const CXXOperatorCallExpr *opCall = cast<CXXOperatorCallExpr>(CE);
-      methodDecl = 
-        dyn_cast_or_null<CXXMethodDecl>(opCall->getCalleeDecl());
-      break;
-    }
-    case Stmt::CXXMemberCallExprClass: {
-      const CXXMemberCallExpr *memberCall = cast<CXXMemberCallExpr>(CE);
-      const MemberExpr *memberExpr = 
-        cast<MemberExpr>(memberCall->getCallee()->IgnoreParens());
-      methodDecl = cast<CXXMethodDecl>(memberExpr->getMemberDecl());
-      break;
-    }
-  }
-      
-  
-  
-  
-  // Check if the function definition is in the same translation unit.
-  if (FD->hasBody(FD)) {
-    const StackFrameContext *stackFrame = 
-      AMgr.getStackFrame(AMgr.getAnalysisDeclContext(FD), 
-                         Pred->getLocationContext(),
-                         CE, currentBuilderContext->getBlock(), currentStmtIdx);
-    // Now we have the definition of the callee, create a CallEnter node.
-    CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
-
-    ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
-    Dst.Add(N);
-    return true;
-  }
-
-  // Check if we can find the function definition in other translation units.
-  if (AMgr.hasIndexer()) {
-    AnalysisDeclContext *C = AMgr.getAnalysisDeclContextInAnotherTU(FD);
-    if (C == 0)
-      return false;
-    const StackFrameContext *stackFrame = 
-      AMgr.getStackFrame(C, Pred->getLocationContext(),
-                         CE, currentBuilderContext->getBlock(), currentStmtIdx);
-    CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
-    ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
-    Dst.Add(N);
-    return true;
-  }
-  
-  // Generate the CallExit node.
-
-  return false;
-#endif
-}
-
 std::pair<const ProgramPointTag *, const ProgramPointTag*>
 ExprEngine::getEagerlyAssumeTags() {
   static SimpleProgramPointTag
@@ -1664,7 +1592,7 @@
     }
 
     const ProgramState *state = Pred->getState();
-    SVal V = state->getSVal(Ex);
+    SVal V = state->getSVal(Ex, Pred->getLocationContext());
     nonloc::SymbolVal *SEV = dyn_cast<nonloc::SymbolVal>(&V);
     if (SEV && SEV->isExpression()) {
       const std::pair<const ProgramPointTag *, const ProgramPointTag*> &tags =
@@ -1673,14 +1601,14 @@
       // First assume that the condition is true.
       if (const ProgramState *StateTrue = state->assume(*SEV, true)) {
         SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());        
-        StateTrue = StateTrue->BindExpr(Ex, Val);
+        StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);
         Bldr.generateNode(Ex, Pred, StateTrue, false, tags.first);
       }
 
       // Next, assume that the condition is false.
       if (const ProgramState *StateFalse = state->assume(*SEV, false)) {
         SVal Val = svalBuilder.makeIntVal(0U, Ex->getType());
-        StateFalse = StateFalse->BindExpr(Ex, Val);
+        StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val);
         Bldr.generateNode(Ex, Pred, StateFalse, false, tags.second);
       }
     }
@@ -1728,7 +1656,7 @@
     for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(),
                                    OE = A->end_outputs(); OI != OE; ++OI) {
 
-      SVal X = state->getSVal(*OI);
+      SVal X = state->getSVal(*OI, Pred->getLocationContext());
       assert (!isa<NonLoc>(X));  // Should be an Lval, or unknown, undef.
 
       if (isa<Loc>(X))
@@ -1933,7 +1861,7 @@
     const ProgramState *state = N->getState();
     Out << "\\|StateID: " << (void*) state
         << " NodeID: " << (void*) N << "\\|";
-    state->printDOT(Out, *N->getLocationContext()->getCFG());
+    state->printDOT(Out);
 
     Out << "\\l";    
 

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngineC.cpp Fri Jan 20 10:14:22 2012
@@ -35,8 +35,9 @@
          it != ei; ++it) {
       
     const ProgramState *state = (*it)->getState();
-    SVal LeftV = state->getSVal(LHS);
-    SVal RightV = state->getSVal(RHS);
+    const LocationContext *LCtx = (*it)->getLocationContext();
+    SVal LeftV = state->getSVal(LHS, LCtx);
+    SVal RightV = state->getSVal(RHS, LCtx);
       
     BinaryOperator::Opcode Op = B->getOpcode();
       
@@ -50,7 +51,8 @@
       // Simulate the effects of a "store":  bind the value of the RHS
       // to the L-Value represented by the LHS.
       SVal ExprVal = B->isLValue() ? LeftV : RightV;
-      evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, ExprVal), LeftV, RightV);
+      evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, LCtx, ExprVal),
+                LeftV, RightV);
       continue;
     }
       
@@ -64,7 +66,7 @@
         continue;
       }        
 
-      state = state->BindExpr(B, Result);      
+      state = state->BindExpr(B, LCtx, Result);      
       Bldr.generateNode(B, *it, state);
       continue;
     }
@@ -96,7 +98,8 @@
          ++I) {
 
       state = (*I)->getState();
-      SVal V = state->getSVal(LHS);
+      const LocationContext *LCtx = (*I)->getLocationContext();
+      SVal V = state->getSVal(LHS, LCtx);
       
       // Get the computation type.
       QualType CTy =
@@ -143,9 +146,9 @@
       // In C++, assignment and compound assignment operators return an 
       // lvalue.
       if (B->isLValue())
-        state = state->BindExpr(B, location);
+        state = state->BindExpr(B, LCtx, location);
       else
-        state = state->BindExpr(B, Result);
+        state = state->BindExpr(B, LCtx, Result);
       
       evalStore(Tmp2, B, LHS, *I, state, location, LHSVal);
     }
@@ -164,7 +167,10 @@
   
   ExplodedNodeSet Tmp;
   StmtNodeBuilder Bldr(Pred, Tmp, *currentBuilderContext);
-  Bldr.generateNode(BE, Pred, Pred->getState()->BindExpr(BE, V), false, 0,
+  Bldr.generateNode(BE, Pred,
+                    Pred->getState()->BindExpr(BE, Pred->getLocationContext(),
+                                               V),
+                    false, 0,
                     ProgramPoint::PostLValueKind);
   
   // FIXME: Move all post/pre visits to ::Visit().
@@ -182,7 +188,8 @@
          I!=E; ++I) {
       ExplodedNode *subExprNode = *I;
       const ProgramState *state = subExprNode->getState();
-      evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex));
+      const LocationContext *LCtx = subExprNode->getLocationContext();
+      evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex, LCtx));
     }
     return;
   }
@@ -211,13 +218,19 @@
       case CK_ARCConsumeObject:
       case CK_ARCReclaimReturnedObject:
       case CK_ARCExtendBlockObject: // Fall-through.
+        // The analyser can ignore atomic casts for now, although some future
+        // checkers may want to make certain that you're not modifying the same
+        // value through atomic and nonatomic pointers.
+      case CK_AtomicToNonAtomic:
+      case CK_NonAtomicToAtomic:
         // True no-ops.
       case CK_NoOp:
       case CK_FunctionToPointerDecay: {
         // Copy the SVal of Ex to CastE.
         const ProgramState *state = Pred->getState();
-        SVal V = state->getSVal(Ex);
-        state = state->BindExpr(CastE, V);
+        const LocationContext *LCtx = Pred->getLocationContext();
+        SVal V = state->getSVal(Ex, LCtx);
+        state = state->BindExpr(CastE, LCtx, V);
         Bldr.generateNode(CastE, Pred, state);
         continue;
       }
@@ -251,9 +264,10 @@
       case CK_ObjCObjectLValueCast: {
         // Delegate to SValBuilder to process.
         const ProgramState *state = Pred->getState();
-        SVal V = state->getSVal(Ex);
+        const LocationContext *LCtx = Pred->getLocationContext();
+        SVal V = state->getSVal(Ex, LCtx);
         V = svalBuilder.evalCast(V, T, ExTy);
-        state = state->BindExpr(CastE, V);
+        state = state->BindExpr(CastE, LCtx, V);
         Bldr.generateNode(CastE, Pred, state);
         continue;
       }
@@ -261,9 +275,10 @@
       case CK_UncheckedDerivedToBase: {
         // For DerivedToBase cast, delegate to the store manager.
         const ProgramState *state = Pred->getState();
-        SVal val = state->getSVal(Ex);
+        const LocationContext *LCtx = Pred->getLocationContext();
+        SVal val = state->getSVal(Ex, LCtx);
         val = getStoreManager().evalDerivedToBase(val, T);
-        state = state->BindExpr(CastE, val);
+        state = state->BindExpr(CastE, LCtx, val);
         Bldr.generateNode(CastE, Pred, state);
         continue;
       }
@@ -287,7 +302,9 @@
         svalBuilder.getConjuredSymbolVal(NULL, CastE, resultType,
                                currentBuilderContext->getCurrentBlockCount());
         
-        const ProgramState *state = Pred->getState()->BindExpr(CastE, result);
+        const LocationContext *LCtx = Pred->getLocationContext();
+        const ProgramState *state = Pred->getState()->BindExpr(CastE, LCtx,
+                                                               result);
         Bldr.generateNode(CastE, Pred, state);
         continue;
       }
@@ -304,14 +321,14 @@
     = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
   
   const ProgramState *state = Pred->getState();
-  SVal ILV = state->getSVal(ILE);
+  SVal ILV = state->getSVal(ILE, Pred->getLocationContext());
   const LocationContext *LC = Pred->getLocationContext();
   state = state->bindCompoundLiteral(CL, LC, ILV);
   
   if (CL->isLValue())
-    B.generateNode(CL, Pred, state->BindExpr(CL, state->getLValue(CL, LC)));
+    B.generateNode(CL, Pred, state->BindExpr(CL, LC, state->getLValue(CL, LC)));
   else
-    B.generateNode(CL, Pred, state->BindExpr(CL, ILV));
+    B.generateNode(CL, Pred, state->BindExpr(CL, LC, ILV));
 }
 
 void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
@@ -345,7 +362,7 @@
     const LocationContext *LC = N->getLocationContext();
     
     if (const Expr *InitEx = VD->getInit()) {
-      SVal InitVal = state->getSVal(InitEx);
+      SVal InitVal = state->getSVal(InitEx, Pred->getLocationContext());
       
       // We bound the temp obj region to the CXXConstructExpr. Now recover
       // the lazy compound value when the variable is not a reference.
@@ -379,18 +396,19 @@
 
   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
   const ProgramState *state = Pred->getState();
-  SVal X = state->getSVal(B);
+  const LocationContext *LCtx = Pred->getLocationContext();
+  SVal X = state->getSVal(B, LCtx);
   assert(X.isUndef());
   
   const Expr *Ex = (const Expr*) cast<UndefinedVal>(X).getData();
   assert(Ex);
   
   if (Ex == B->getRHS()) {
-    X = state->getSVal(Ex);
+    X = state->getSVal(Ex, LCtx);
     
     // Handle undefined values.
     if (X.isUndef()) {
-      Bldr.generateNode(B, Pred, state->BindExpr(B, X));
+      Bldr.generateNode(B, Pred, state->BindExpr(B, LCtx, X));
       return;
     }
     
@@ -404,11 +422,13 @@
     // the payoff is not likely to be large.  Instead, we do eager evaluation.
     if (const ProgramState *newState = state->assume(XD, true))
       Bldr.generateNode(B, Pred,
-               newState->BindExpr(B, svalBuilder.makeIntVal(1U, B->getType())));
+               newState->BindExpr(B, LCtx,
+                                  svalBuilder.makeIntVal(1U, B->getType())));
     
     if (const ProgramState *newState = state->assume(XD, false))
       Bldr.generateNode(B, Pred,
-               newState->BindExpr(B, svalBuilder.makeIntVal(0U, B->getType())));
+               newState->BindExpr(B, LCtx,
+                                  svalBuilder.makeIntVal(0U, B->getType())));
   }
   else {
     // We took the LHS expression.  Depending on whether we are '&&' or
@@ -416,7 +436,7 @@
     // the short-circuiting.
     X = svalBuilder.makeIntVal(B->getOpcode() == BO_LAnd ? 0U : 1U,
                                B->getType());
-    Bldr.generateNode(B, Pred, state->BindExpr(B, X));
+    Bldr.generateNode(B, Pred, state->BindExpr(B, LCtx, X));
   }
 }
 
@@ -426,6 +446,7 @@
   StmtNodeBuilder B(Pred, Dst, *currentBuilderContext);
 
   const ProgramState *state = Pred->getState();
+  const LocationContext *LCtx = Pred->getLocationContext();
   QualType T = getContext().getCanonicalType(IE->getType());
   unsigned NumInitElements = IE->getNumInits();
   
@@ -436,24 +457,27 @@
     // e.g: static int* myArray[] = {};
     if (NumInitElements == 0) {
       SVal V = svalBuilder.makeCompoundVal(T, vals);
-      B.generateNode(IE, Pred, state->BindExpr(IE, V));
+      B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V));
       return;
     }
     
     for (InitListExpr::const_reverse_iterator it = IE->rbegin(),
          ei = IE->rend(); it != ei; ++it) {
-      vals = getBasicVals().consVals(state->getSVal(cast<Expr>(*it)), vals);
+      vals = getBasicVals().consVals(state->getSVal(cast<Expr>(*it), LCtx),
+                                     vals);
     }
     
     B.generateNode(IE, Pred,
-                   state->BindExpr(IE, svalBuilder.makeCompoundVal(T, vals)));
+                   state->BindExpr(IE, LCtx,
+                                   svalBuilder.makeCompoundVal(T, vals)));
     return;
   }
   
   if (Loc::isLocType(T) || T->isIntegerType()) {
     assert(IE->getNumInits() == 1);
     const Expr *initEx = IE->getInit(0);
-    B.generateNode(IE, Pred, state->BindExpr(IE, state->getSVal(initEx)));
+    B.generateNode(IE, Pred, state->BindExpr(IE, LCtx,
+                                             state->getSVal(initEx, LCtx)));
     return;
   }
   
@@ -468,28 +492,30 @@
   StmtNodeBuilder B(Pred, Dst, *currentBuilderContext);
   
   const ProgramState *state = Pred->getState();
-  SVal X = state->getSVal(Ex);  
+  const LocationContext *LCtx = Pred->getLocationContext();
+  SVal X = state->getSVal(Ex, LCtx);  
   assert (X.isUndef());  
   const Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
   assert(SE);
-  X = state->getSVal(SE);
+  X = state->getSVal(SE, LCtx);
   
   // Make sure that we invalidate the previous binding.
-  B.generateNode(Ex, Pred, state->BindExpr(Ex, X, true));
+  B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, X, true));
 }
 
 void ExprEngine::
 VisitOffsetOfExpr(const OffsetOfExpr *OOE, 
                   ExplodedNode *Pred, ExplodedNodeSet &Dst) {
   StmtNodeBuilder B(Pred, Dst, *currentBuilderContext);
-  Expr::EvalResult Res;
-  if (OOE->EvaluateAsRValue(Res, getContext()) && Res.Val.isInt()) {
-    const APSInt &IV = Res.Val.getInt();
+  APSInt IV;
+  if (OOE->EvaluateAsInt(IV, getContext())) {
     assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));
     assert(OOE->getType()->isIntegerType());
     assert(IV.isSigned() == OOE->getType()->isSignedIntegerOrEnumerationType());
     SVal X = svalBuilder.makeIntVal(IV);
-    B.generateNode(OOE, Pred, Pred->getState()->BindExpr(OOE, X));
+    B.generateNode(OOE, Pred,
+                   Pred->getState()->BindExpr(OOE, Pred->getLocationContext(),
+                                              X));
   }
   // FIXME: Handle the case where __builtin_offsetof is not a constant.
 }
@@ -519,12 +545,12 @@
     }
   }
   
-  Expr::EvalResult Result;
-  Ex->EvaluateAsRValue(Result, getContext());
-  CharUnits amt = CharUnits::fromQuantity(Result.Val.getInt().getZExtValue());
+  APSInt Value = Ex->EvaluateKnownConstInt(getContext());
+  CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue());
   
   const ProgramState *state = Pred->getState();
-  state = state->BindExpr(Ex, svalBuilder.makeIntVal(amt.getQuantity(),
+  state = state->BindExpr(Ex, Pred->getLocationContext(),
+                          svalBuilder.makeIntVal(amt.getQuantity(),
                                                      Ex->getType()));
   Bldr.generateNode(Ex, Pred, state);
 }
@@ -557,7 +583,9 @@
         // For all other types, UO_Real is an identity operation.
         assert (U->getType() == Ex->getType());
         const ProgramState *state = (*I)->getState();
-        Bldr.generateNode(U, *I, state->BindExpr(U, state->getSVal(Ex)));
+        const LocationContext *LCtx = (*I)->getLocationContext();
+        Bldr.generateNode(U, *I, state->BindExpr(U, LCtx,
+                                                 state->getSVal(Ex, LCtx)));
       }
       
       break;
@@ -578,8 +606,9 @@
         
         // For all other types, UO_Imag returns 0.
         const ProgramState *state = (*I)->getState();
+        const LocationContext *LCtx = (*I)->getLocationContext();
         SVal X = svalBuilder.makeZeroVal(Ex->getType());
-        Bldr.generateNode(U, *I, state->BindExpr(U, X));
+        Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, X));
       }
       
       break;
@@ -603,7 +632,9 @@
       
       for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
         const ProgramState *state = (*I)->getState();
-        Bldr.generateNode(U, *I, state->BindExpr(U, state->getSVal(Ex)));
+        const LocationContext *LCtx = (*I)->getLocationContext();
+        Bldr.generateNode(U, *I, state->BindExpr(U, LCtx,
+                                                 state->getSVal(Ex, LCtx)));
       }
       
       break;
@@ -619,12 +650,13 @@
       
       for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
         const ProgramState *state = (*I)->getState();
+        const LocationContext *LCtx = (*I)->getLocationContext();
         
         // Get the value of the subexpression.
-        SVal V = state->getSVal(Ex);
+        SVal V = state->getSVal(Ex, LCtx);
         
         if (V.isUnknownOrUndef()) {
-          Bldr.generateNode(U, *I, state->BindExpr(U, V));
+          Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V));
           continue;
         }
         
@@ -634,12 +666,12 @@
             
           case UO_Not:
             // FIXME: Do we need to handle promotions?
-            state = state->BindExpr(U, evalComplement(cast<NonLoc>(V)));
+            state = state->BindExpr(U, LCtx, evalComplement(cast<NonLoc>(V)));
             break;
             
           case UO_Minus:
             // FIXME: Do we need to handle promotions?
-            state = state->BindExpr(U, evalMinus(cast<NonLoc>(V)));
+            state = state->BindExpr(U, LCtx, evalMinus(cast<NonLoc>(V)));
             break;
             
           case UO_LNot:
@@ -661,7 +693,7 @@
                                  U->getType());
             }
             
-            state = state->BindExpr(U, Result);
+            state = state->BindExpr(U, LCtx, Result);
             
             break;
         }
@@ -683,9 +715,9 @@
   Visit(Ex, Pred, Tmp);
   
   for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
-    
+    const LocationContext *LCtx = (*I)->getLocationContext();
     const ProgramState *state = (*I)->getState();
-    SVal loc = state->getSVal(Ex);
+    SVal loc = state->getSVal(Ex, LCtx);
     
     // Perform a load.
     ExplodedNodeSet Tmp2;
@@ -696,11 +728,12 @@
     for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end();I2!=E2;++I2) {
       
       state = (*I2)->getState();
-      SVal V2_untested = state->getSVal(Ex);
+      assert(LCtx == (*I2)->getLocationContext());
+      SVal V2_untested = state->getSVal(Ex, LCtx);
       
       // Propagate unknown and undefined values.
       if (V2_untested.isUnknownOrUndef()) {
-        Bldr.generateNode(U, *I2, state->BindExpr(U, V2_untested));
+        Bldr.generateNode(U, *I2, state->BindExpr(U, LCtx, V2_untested));
         continue;
       }
       DefinedSVal V2 = cast<DefinedSVal>(V2_untested);
@@ -751,9 +784,9 @@
       // Since the lvalue-to-rvalue conversion is explicit in the AST,
       // we bind an l-value if the operator is prefix and an lvalue (in C++).
       if (U->isLValue())
-        state = state->BindExpr(U, loc);
+        state = state->BindExpr(U, LCtx, loc);
       else
-        state = state->BindExpr(U, U->isPostfix() ? V2 : Result);
+        state = state->BindExpr(U, LCtx, U->isPostfix() ? V2 : Result);
       
       // Perform the store.
       Bldr.takeNodes(*I2);

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Fri Jan 20 10:14:22 2012
@@ -110,17 +110,17 @@
   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
   const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
   const ProgramState *state = Pred->getState();
+  const LocationContext *LCtx = Pred->getLocationContext();
 
   // Bind the temporary object to the value of the expression. Then bind
   // the expression to the location of the object.
-  SVal V = state->getSVal(tempExpr);
+  SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
 
   const MemRegion *R =
-    svalBuilder.getRegionManager().getCXXTempObjectRegion(ME,
-                                                 Pred->getLocationContext());
+    svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
 
   state = state->bindLoc(loc::MemRegionVal(R), V);
-  Bldr.generateNode(ME, Pred, state->BindExpr(ME, loc::MemRegionVal(R)));
+  Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
 }
 
 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, 
@@ -208,7 +208,7 @@
       const LocationContext *LC = Pred->getLocationContext();
       const ProgramState *state = Pred->getState();
 
-      state = invalidateArguments(state, CallOrObjCMessage(E, state), LC);
+      state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC);
       Bldr.generateNode(E, Pred, state);
     }
   }
@@ -256,7 +256,8 @@
     // FIXME: allocating an array requires simulating the constructors.
     // For now, just return a symbolicated region.
     const ProgramState *state = Pred->getState();
-    state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
+    state = state->BindExpr(CNE, Pred->getLocationContext(),
+                            loc::MemRegionVal(EleReg));
     Bldr.generateNode(CNE, Pred, state);
     return;
   }
@@ -286,7 +287,7 @@
           ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
           ai != ae; ++ai)
     {
-      SVal val = state->getSVal(*ai);
+      SVal val = state->getSVal(*ai, (*I)->getLocationContext());
       if (const MemRegion *region = val.getAsRegion())
         regionsToInvalidate.push_back(region);
     }
@@ -294,18 +295,21 @@
     if (ObjTy->isRecordType()) {
       regionsToInvalidate.push_back(EleReg);
       // Invalidate the regions.
+      // TODO: Pass the call to new information as the last argument, to limit
+      // the globals which will get invalidated.
       state = state->invalidateRegions(regionsToInvalidate,
-                                       CNE, blockCount, 0,
-                                       /* invalidateGlobals = */ true);
+                                       CNE, blockCount, 0, 0);
       
     } else {
       // Invalidate the regions.
+      // TODO: Pass the call to new information as the last argument, to limit
+      // the globals which will get invalidated.
       state = state->invalidateRegions(regionsToInvalidate,
-                                       CNE, blockCount, 0,
-                                       /* invalidateGlobals = */ true);
+                                       CNE, blockCount, 0, 0);
 
       if (CNE->hasInitializer()) {
-        SVal V = state->getSVal(*CNE->constructor_arg_begin());
+        SVal V = state->getSVal(*CNE->constructor_arg_begin(),
+                                (*I)->getLocationContext());
         state = state->bindLoc(loc::MemRegionVal(EleReg), V);
       } else {
         // Explicitly set to undefined, because currently we retrieve symbolic
@@ -313,7 +317,8 @@
         state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
       }
     }
-    state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
+    state = state->BindExpr(CNE, (*I)->getLocationContext(),
+                            loc::MemRegionVal(EleReg));
     Bldr.generateNode(CNE, *I, state);
   }
 }
@@ -336,12 +341,13 @@
   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
 
   // Get the this object region from StoreManager.
+  const LocationContext *LCtx = Pred->getLocationContext();
   const MemRegion *R =
     svalBuilder.getRegionManager().getCXXThisRegion(
                                   getContext().getCanonicalType(TE->getType()),
-                                               Pred->getLocationContext());
+                                                    LCtx);
 
   const ProgramState *state = Pred->getState();
   SVal V = state->getSVal(loc::MemRegionVal(R));
-  Bldr.generateNode(TE, Pred, state->BindExpr(TE, V));
+  Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
 }

Modified: cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=148545&r1=148544&r2=148545&view=diff
==============================================================================
--- cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/branches/tooling/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Fri Jan 20 10:14:22 2012
@@ -14,40 +14,72 @@
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "clang/Analysis/Support/SaveAndRestore.h"
 #include "clang/AST/DeclCXX.h"
 
 using namespace clang;
 using namespace ento;
 
-namespace {
-  // Trait class for recording returned expression in the state.
-  struct ReturnExpr {
-    static int TagInt;
-    typedef const Stmt *data_type;
-  };
-  int ReturnExpr::TagInt; 
+void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
+  // Get the entry block in the CFG of the callee.
+  const StackFrameContext *calleeCtx = CE.getCalleeContext();
+  const CFG *CalleeCFG = calleeCtx->getCFG();
+  const CFGBlock *Entry = &(CalleeCFG->getEntry());
+  
+  // Validate the CFG.
+  assert(Entry->empty());
+  assert(Entry->succ_size() == 1);
+  
+  // Get the solitary sucessor.
+  const CFGBlock *Succ = *(Entry->succ_begin());
+  
+  // Construct an edge representing the starting location in the callee.
+  BlockEdge Loc(Entry, Succ, calleeCtx);
+
+  // Construct a new state which contains the mapping from actual to
+  // formal arguments.
+  const LocationContext *callerCtx = Pred->getLocationContext();
+  const ProgramState *state = Pred->getState()->enterStackFrame(callerCtx,
+                                                                calleeCtx);
+  
+  // Construct a new node and add it to the worklist.
+  bool isNew;
+  ExplodedNode *Node = G.getNode(Loc, state, false, &isNew);
+  Node->addPredecessor(Pred, G);
+  if (isNew)
+    Engine.getWorkList()->enqueue(Node);
 }
 
-void ExprEngine::processCallEnter(CallEnterNodeBuilder &B) {
-  const ProgramState *state =
-    B.getState()->enterStackFrame(B.getCalleeContext());
-  B.generateNode(state);
+static const ReturnStmt *getReturnStmt(const ExplodedNode *Node) {
+  while (Node) {
+    const ProgramPoint &PP = Node->getLocation();
+    // Skip any BlockEdges.
+    if (isa<BlockEdge>(PP) || isa<CallExit>(PP)) {
+      assert(Node->pred_size() == 1);
+      Node = *Node->pred_begin();
+      continue;
+    } 
+    if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP)) {
+      const Stmt *S = SP->getStmt();
+      return dyn_cast<ReturnStmt>(S);
+    }
+    break;
+  }
+  return 0;
 }
 
-void ExprEngine::processCallExit(CallExitNodeBuilder &B) {
-  const ProgramState *state = B.getState();
-  const ExplodedNode *Pred = B.getPredecessor();
+void ExprEngine::processCallExit(ExplodedNode *Pred) {
+  const ProgramState *state = Pred->getState();
   const StackFrameContext *calleeCtx = 
-    cast<StackFrameContext>(Pred->getLocationContext());
+    Pred->getLocationContext()->getCurrentStackFrame();
+  const LocationContext *callerCtx = calleeCtx->getParent();
   const Stmt *CE = calleeCtx->getCallSite();
   
   // If the callee returns an expression, bind its value to CallExpr.
-  const Stmt *ReturnedExpr = state->get<ReturnExpr>();
-  if (ReturnedExpr) {
-    SVal RetVal = state->getSVal(ReturnedExpr);
-    state = state->BindExpr(CE, RetVal);
-    // Clear the return expr GDM.
-    state = state->remove<ReturnExpr>();
+  if (const ReturnStmt *RS = getReturnStmt(Pred)) {
+    const LocationContext *LCtx = Pred->getLocationContext();
+    SVal V = state->getSVal(RS, LCtx);
+    state = state->BindExpr(CE, callerCtx, V);
   }
   
   // Bind the constructed object value to CXXConstructExpr.
@@ -57,10 +89,123 @@
     
     SVal ThisV = state->getSVal(ThisR);
     // Always bind the region to the CXXConstructExpr.
-    state = state->BindExpr(CCE, ThisV);
+    state = state->BindExpr(CCE, Pred->getLocationContext(), ThisV);
+  }
+  
+  static SimpleProgramPointTag returnTag("ExprEngine : Call Return");
+  PostStmt Loc(CE, callerCtx, &returnTag);
+  bool isNew;
+  ExplodedNode *N = G.getNode(Loc, state, false, &isNew);
+  N->addPredecessor(Pred, G);
+  if (!isNew)
+    return;
+  
+  // Perform the post-condition check of the CallExpr.
+  ExplodedNodeSet Dst;
+  NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), N);
+  SaveAndRestore<const NodeBuilderContext*> NBCSave(currentBuilderContext,
+                                                    &Ctx);
+  SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex());
+  
+  getCheckerManager().runCheckersForPostStmt(Dst, N, CE, *this);
+  
+  // Enqueue the next element in the block.
+  for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I) {
+    Engine.getWorkList()->enqueue(*I,
+                                  calleeCtx->getCallSiteBlock(),
+                                  calleeCtx->getIndex()+1);
+  }
+}
+
+static unsigned getNumberStackFrames(const LocationContext *LCtx) {
+  unsigned count = 0;
+  while (LCtx) {
+    if (isa<StackFrameContext>(LCtx))
+      ++count;
+    LCtx = LCtx->getParent();
   }
+  return count;  
+}
+
+bool ExprEngine::InlineCall(ExplodedNodeSet &Dst,
+                            const CallExpr *CE, 
+                            ExplodedNode *Pred) {
+  const ProgramState *state = Pred->getState();
+  const Expr *Callee = CE->getCallee();
+  const FunctionDecl *FD =
+  state->getSVal(Callee, Pred->getLocationContext()).getAsFunctionDecl();
+  if (!FD || !FD->hasBody(FD))
+    return false;
   
-  B.generateNode(state);
+  switch (CE->getStmtClass()) {
+    default:
+      // FIXME: Handle C++.
+      break;
+    case Stmt::CallExprClass: {
+      // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
+      // These heuristics are a WIP.
+      if (getNumberStackFrames(Pred->getLocationContext()) == 5)
+        return false;
+      
+      // Construct a new stack frame for the callee.
+      AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(FD);
+      const StackFrameContext *CallerSFC =
+      Pred->getLocationContext()->getCurrentStackFrame();
+      const StackFrameContext *CalleeSFC =
+      CalleeADC->getStackFrame(CallerSFC, CE,
+                               currentBuilderContext->getBlock(),
+                               currentStmtIdx);
+      
+      CallEnter Loc(CE, CalleeSFC, Pred->getLocationContext());
+      bool isNew;
+      ExplodedNode *N = G.getNode(Loc, state, false, &isNew);
+      N->addPredecessor(Pred, G);
+      if (isNew)
+        Engine.getWorkList()->enqueue(N);
+      return true;
+    }
+  }
+  return false;
+}
+
+static bool isPointerToConst(const ParmVarDecl *ParamDecl) {
+  QualType PointeeTy = ParamDecl->getOriginalType()->getPointeeType();
+  if (PointeeTy != QualType() && PointeeTy.isConstQualified() &&
+      !PointeeTy->isAnyPointerType() && !PointeeTy->isReferenceType()) {
+    return true;
+  }
+  return false;
+}
+
+// Try to retrieve the function declaration and find the function parameter
+// types which are pointers/references to a non-pointer const.
+// We do not invalidate the corresponding argument regions.
+static void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs,
+                       const CallOrObjCMessage &Call) {
+  const Decl *CallDecl = Call.getDecl();
+  if (!CallDecl)
+    return;
+
+  if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(CallDecl)) {
+    for (unsigned Idx = 0, E = Call.getNumArgs(); Idx != E; ++Idx) {
+      if (FDecl && Idx < FDecl->getNumParams()) {
+        if (isPointerToConst(FDecl->getParamDecl(Idx)))
+          PreserveArgs.insert(Idx);
+      }
+    }
+    return;
+  }
+
+  if (const ObjCMethodDecl *MDecl = dyn_cast<ObjCMethodDecl>(CallDecl)) {
+    assert(MDecl->param_size() <= Call.getNumArgs());
+    unsigned Idx = 0;
+    for (clang::ObjCMethodDecl::param_const_iterator
+         I = MDecl->param_begin(), E = MDecl->param_end(); I != E; ++I, ++Idx) {
+      if (isPointerToConst(*I))
+        PreserveArgs.insert(Idx);
+    }
+    return;
+  }
 }
 
 const ProgramState *
@@ -84,13 +229,21 @@
 
   } else if (Call.isFunctionCall()) {
     // Block calls invalidate all captured-by-reference values.
-    if (const MemRegion *Callee = Call.getFunctionCallee().getAsRegion()) {
+    SVal CalleeVal = Call.getFunctionCallee();
+    if (const MemRegion *Callee = CalleeVal.getAsRegion()) {
       if (isa<BlockDataRegion>(Callee))
         RegionsToInvalidate.push_back(Callee);
     }
   }
 
+  // Indexes of arguments whose values will be preserved by the call.
+  llvm::SmallSet<unsigned, 1> PreserveArgs;
+  findPtrToConstParams(PreserveArgs, Call);
+
   for (unsigned idx = 0, e = Call.getNumArgs(); idx != e; ++idx) {
+    if (PreserveArgs.count(idx))
+      continue;
+
     SVal V = Call.getArgSVal(idx);
 
     // If we are passing a location wrapped as an integer, unwrap it and
@@ -104,7 +257,7 @@
       // Invalidate the value of the variable passed by reference.
 
       // Are we dealing with an ElementRegion?  If the element type is
-      // a basic integer type (e.g., char, int) and the underying region
+      // a basic integer type (e.g., char, int) and the underlying region
       // is a variable region then strip off the ElementRegion.
       // FIXME: We really need to think about this for the general case
       //   as sometimes we are reasoning about arrays and other times
@@ -115,7 +268,7 @@
         // we'll leave it in for now until we have a systematic way of
         // handling all of these cases.  Eventually we need to come up
         // with an interface to StoreManager so that this logic can be
-        // approriately delegated to the respective StoreManagers while
+        // appropriately delegated to the respective StoreManagers while
         // still allowing us to do checker-specific logic (e.g.,
         // invalidating reference counts), probably via callbacks.
         if (ER->getElementType()->isIntegralOrEnumerationType()) {
@@ -152,7 +305,7 @@
   //  global variables.
   return State->invalidateRegions(RegionsToInvalidate,
                                   Call.getOriginExpr(), Count,
-                                  &IS, doesInvalidateGlobals(Call));
+                                  &IS, &Call);
 
 }
 
@@ -183,7 +336,7 @@
       // Get the callee.
       const Expr *Callee = CE->getCallee()->IgnoreParens();
       const ProgramState *state = Pred->getState();
-      SVal L = state->getSVal(Callee);
+      SVal L = state->getSVal(Callee, Pred->getLocationContext());
 
       // Figure out the result type. We do this dance to handle references.
       QualType ResultTy;
@@ -201,11 +354,12 @@
       SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count);
 
       // Generate a new state with the return value set.
-      state = state->BindExpr(CE, RetVal);
+      const LocationContext *LCtx = Pred->getLocationContext();
+      state = state->BindExpr(CE, LCtx, RetVal);
 
       // Invalidate the arguments.
-      const LocationContext *LC = Pred->getLocationContext();
-      state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state), LC);
+      state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state, LCtx),
+                                      LCtx);
 
       // And make the result node.
       Bldr.generateNode(CE, Pred, state);
@@ -228,27 +382,19 @@
 
 void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) {
-  ExplodedNodeSet Src;
-  {
-    StmtNodeBuilder Bldr(Pred, Src, *currentBuilderContext);
-    if (const Expr *RetE = RS->getRetValue()) {
-      // Record the returned expression in the state. It will be used in
-      // processCallExit to bind the return value to the call expr.
-      {
-        static SimpleProgramPointTag tag("ExprEngine: ReturnStmt");
-        const ProgramState *state = Pred->getState();
-        state = state->set<ReturnExpr>(RetE);
-        Pred = Bldr.generateNode(RetE, Pred, state, false, &tag);
-      }
-      // We may get a NULL Pred because we generated a cached node.
-      if (Pred) {
-        Bldr.takeNodes(Pred);
-        ExplodedNodeSet Tmp;
-        Visit(RetE, Pred, Tmp);
-        Bldr.addNodes(Tmp);
-      }
+  
+  ExplodedNodeSet dstPreVisit;
+  getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, RS, *this);
+
+  StmtNodeBuilder B(dstPreVisit, Dst, *currentBuilderContext);
+  
+  if (RS->getRetValue()) {
+    for (ExplodedNodeSet::iterator it = dstPreVisit.begin(),
+                                  ei = dstPreVisit.end(); it != ei; ++it) {
+      B.generateNode(RS, *it, (*it)->getState());
     }
   }
-  
-  getCheckerManager().runCheckersForPreStmt(Dst, Src, RS, *this);
+  else {
+    B.takeNodes(dstPreVisit);
+  }
 }





More information about the llvm-branch-commits mailing list